123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- discard """
- matrix: "--mm:refc; --mm:arc"
- joinable: false
- targets: "c js cpp"
- """
- import std/os
- from std/sequtils import toSeq
- import stdtest/testutils
- when defined(nimPreviewSlimSystem):
- import std/[assertions]
- # "LATIN CAPITAL LETTER AE" in UTF-8 (0xc386)
- const unicodeUtf8 = "\xc3\x86"
- template main =
- block: # delEnv, existsEnv, getEnv, envPairs
- for val in ["val", "", unicodeUtf8]: # ensures empty val works too
- const key = "NIM_TESTS_TOSENV_KEY"
- doAssert not existsEnv(key)
- putEnv(key, "tempval")
- doAssert existsEnv(key)
- doAssert getEnv(key) == "tempval"
- putEnv(key, val) # change a key that already exists
- doAssert existsEnv(key)
- doAssert getEnv(key) == val
- doAssert (key, val) in toSeq(envPairs())
- delEnv(key)
- doAssert (key, val) notin toSeq(envPairs())
- doAssert not existsEnv(key)
- delEnv(key) # deleting an already deleted env var
- doAssert not existsEnv(key)
- block:
- doAssert getEnv("NIM_TESTS_TOSENV_NONEXISTENT", "") == ""
- doAssert getEnv("NIM_TESTS_TOSENV_NONEXISTENT", " ") == " "
- doAssert getEnv("NIM_TESTS_TOSENV_NONEXISTENT", "defval") == "defval"
- whenVMorJs: discard # xxx improve
- do:
- doAssertRaises(OSError, putEnv("NIM_TESTS_TOSENV_PUT=DUMMY_VALUE", "NEW_DUMMY_VALUE"))
- doAssertRaises(OSError, putEnv("", "NEW_DUMMY_VALUE"))
- doAssert not existsEnv("")
- doAssert not existsEnv("NIM_TESTS_TOSENV_PUT=DUMMY_VALUE")
- doAssert not existsEnv("NIM_TESTS_TOSENV_PUT")
- static: main()
- main()
- when defined(windows):
- import std/widestrs
- proc c_wgetenv(env: WideCString): WideCString {.importc: "_wgetenv", header: "<stdlib.h>".}
- proc c_getenv(env: cstring): cstring {.importc: "getenv", header: "<stdlib.h>".}
- when not defined(js) and not defined(nimscript):
- when defined(nimPreviewSlimSystem):
- import std/typedthreads
- block: # bug #18533
- var thr: Thread[void]
- proc threadFunc {.thread.} = putEnv("foo", "fooVal2")
- putEnv("foo", "fooVal1")
- doAssert getEnv("foo") == "fooVal1"
- createThread(thr, threadFunc)
- joinThreads(thr)
- when defined(windows):
- doAssert getEnv("foo") == $c_wgetenv("foo".newWideCString)
- else:
- doAssert getEnv("foo") == $c_getenv("foo".cstring)
- doAssertRaises(OSError): delEnv("foo=bar")
- when defined(windows) and not defined(nimscript):
- import std/encodings
- proc c_putenv(env: cstring): int32 {.importc: "putenv", header: "<stdlib.h>".}
- proc c_wputenv(env: WideCString): int32 {.importc: "_wputenv", header: "<stdlib.h>".}
- block: # Bug #20083
- # These test that `getEnv`, `putEnv` and `existsEnv` handle Unicode
- # characters correctly. This means that module X in the process calling the
- # CRT environment variable API will get the correct string. Raw CRT API
- # calls below represent module X.
- # Getting an env. var. with unicode characters returns the correct UTF-8
- # encoded string.
- block:
- const envName = "twin_envvars1"
- doAssert c_wputenv(newWideCString(envName & "=" & unicodeUtf8)) == 0
- doAssert existsEnv(envName)
- doAssert getEnv(envName) == unicodeUtf8
- # Putting an env. var. with unicode characters gives the correct UTF-16
- # encoded string from low-level routine.
- block:
- const envName = "twin_envvars2"
- putEnv(envName, unicodeUtf8)
- doAssert $c_wgetenv(envName.newWideCString) == unicodeUtf8
- # Env. name containing Unicode characters is retrieved correctly
- block:
- const envName = unicodeUtf8 & "1"
- doAssert c_wputenv(newWideCString(envName & "=" & unicodeUtf8)) == 0
- doAssert existsEnv(envName)
- doAssert getEnv(envName) == unicodeUtf8
- # Env. name containing Unicode characters is set correctly
- block:
- const envName = unicodeUtf8 & "2"
- putEnv(envName, unicodeUtf8)
- doAssert existsEnv(envName)
- doAssert $c_wgetenv(envName.newWideCString) == unicodeUtf8
- # Env. name containing Unicode characters and empty value is set correctly
- block:
- const envName = unicodeUtf8 & "3"
- putEnv(envName, "")
- doAssert existsEnv(envName)
- doAssert $c_wgetenv(envName.newWideCString) == ""
- # It's hard to test on Windows code pages, because there is no "change
- # a process' locale" API.
- if getCurrentEncoding(true) == "windows-1252":
- const
- unicodeAnsi = "\xc6" # `unicodeUtf8` in `windows-1252` encoding
- # Test that env. var. ANSI API has correct encoding
- block:
- const
- envName = unicodeUtf8 & "4"
- envNameAnsi = unicodeAnsi & "4"
- putEnv(envName, unicodeUtf8)
- doAssert $c_getenv(envNameAnsi.cstring) == unicodeAnsi
- block:
- const
- envName = unicodeUtf8 & "5"
- envNameAnsi = unicodeAnsi & "5"
- doAssert c_putenv((envNameAnsi & "=" & unicodeAnsi).cstring) == 0
- doAssert getEnv(envName) == unicodeUtf8
- # Env. name containing Unicode characters and empty value is set correctly;
- # and, if env. name. characters cannot be represented in codepage, don't
- # raise an error.
- #
- # `win_setenv.nim` converts UTF-16 to ANSI when setting empty env. var. The
- # windows-1250 locale has no representation of `abreveUtf8` below, so the
- # conversion will fail, but this must not be fatal. It is expected that the
- # routine ignores updating MBCS environment (`environ` global) and carries
- # on.
- block:
- const
- # "LATIN SMALL LETTER A WITH BREVE" in UTF-8
- abreveUtf8 = "\xc4\x83"
- envName = abreveUtf8 & "6"
- putEnv(envName, "")
- doAssert existsEnv(envName)
- doAssert $c_wgetenv(envName.newWideCString) == ""
- doAssert getEnv(envName) == ""
|