tosenv.nim 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. discard """
  2. matrix: "--threads"
  3. joinable: false
  4. targets: "c js cpp"
  5. """
  6. import std/os
  7. from std/sequtils import toSeq
  8. import stdtest/testutils
  9. when defined(nimPreviewSlimSystem):
  10. import std/[assertions]
  11. # "LATIN CAPITAL LETTER AE" in UTF-8 (0xc386)
  12. const unicodeUtf8 = "\xc3\x86"
  13. template main =
  14. block: # delEnv, existsEnv, getEnv, envPairs
  15. for val in ["val", "", unicodeUtf8]: # ensures empty val works too
  16. const key = "NIM_TESTS_TOSENV_KEY"
  17. doAssert not existsEnv(key)
  18. putEnv(key, "tempval")
  19. doAssert existsEnv(key)
  20. doAssert getEnv(key) == "tempval"
  21. putEnv(key, val) # change a key that already exists
  22. doAssert existsEnv(key)
  23. doAssert getEnv(key) == val
  24. doAssert (key, val) in toSeq(envPairs())
  25. delEnv(key)
  26. doAssert (key, val) notin toSeq(envPairs())
  27. doAssert not existsEnv(key)
  28. delEnv(key) # deleting an already deleted env var
  29. doAssert not existsEnv(key)
  30. block:
  31. doAssert getEnv("NIM_TESTS_TOSENV_NONEXISTENT", "") == ""
  32. doAssert getEnv("NIM_TESTS_TOSENV_NONEXISTENT", " ") == " "
  33. doAssert getEnv("NIM_TESTS_TOSENV_NONEXISTENT", "defval") == "defval"
  34. whenVMorJs: discard # xxx improve
  35. do:
  36. doAssertRaises(OSError, putEnv("NIM_TESTS_TOSENV_PUT=DUMMY_VALUE", "NEW_DUMMY_VALUE"))
  37. doAssertRaises(OSError, putEnv("", "NEW_DUMMY_VALUE"))
  38. doAssert not existsEnv("")
  39. doAssert not existsEnv("NIM_TESTS_TOSENV_PUT=DUMMY_VALUE")
  40. doAssert not existsEnv("NIM_TESTS_TOSENV_PUT")
  41. static: main()
  42. main()
  43. when defined(windows):
  44. import std/widestrs
  45. proc c_wgetenv(env: WideCString): WideCString {.importc: "_wgetenv", header: "<stdlib.h>".}
  46. proc c_getenv(env: cstring): cstring {.importc: "getenv", header: "<stdlib.h>".}
  47. when not defined(js) and not defined(nimscript):
  48. when defined(nimPreviewSlimSystem):
  49. import std/typedthreads
  50. block: # bug #18533
  51. var thr: Thread[void]
  52. proc threadFunc {.thread.} = putEnv("foo", "fooVal2")
  53. putEnv("foo", "fooVal1")
  54. doAssert getEnv("foo") == "fooVal1"
  55. createThread(thr, threadFunc)
  56. joinThreads(thr)
  57. when defined(windows):
  58. doAssert getEnv("foo") == $c_wgetenv("foo".newWideCString)
  59. else:
  60. doAssert getEnv("foo") == $c_getenv("foo".cstring)
  61. doAssertRaises(OSError): delEnv("foo=bar")
  62. when defined(windows) and not defined(nimscript):
  63. import std/encodings
  64. proc c_putenv(env: cstring): int32 {.importc: "putenv", header: "<stdlib.h>".}
  65. proc c_wputenv(env: WideCString): int32 {.importc: "_wputenv", header: "<stdlib.h>".}
  66. block: # Bug #20083
  67. # These test that `getEnv`, `putEnv` and `existsEnv` handle Unicode
  68. # characters correctly. This means that module X in the process calling the
  69. # CRT environment variable API will get the correct string. Raw CRT API
  70. # calls below represent module X.
  71. # Getting an env. var. with unicode characters returns the correct UTF-8
  72. # encoded string.
  73. block:
  74. const envName = "twin_envvars1"
  75. doAssert c_wputenv(newWideCString(envName & "=" & unicodeUtf8)) == 0
  76. doAssert existsEnv(envName)
  77. doAssert getEnv(envName) == unicodeUtf8
  78. # Putting an env. var. with unicode characters gives the correct UTF-16
  79. # encoded string from low-level routine.
  80. block:
  81. const envName = "twin_envvars2"
  82. putEnv(envName, unicodeUtf8)
  83. doAssert $c_wgetenv(envName.newWideCString) == unicodeUtf8
  84. # Env. name containing Unicode characters is retrieved correctly
  85. block:
  86. const envName = unicodeUtf8 & "1"
  87. doAssert c_wputenv(newWideCString(envName & "=" & unicodeUtf8)) == 0
  88. doAssert existsEnv(envName)
  89. doAssert getEnv(envName) == unicodeUtf8
  90. # Env. name containing Unicode characters is set correctly
  91. block:
  92. const envName = unicodeUtf8 & "2"
  93. putEnv(envName, unicodeUtf8)
  94. doAssert existsEnv(envName)
  95. doAssert $c_wgetenv(envName.newWideCString) == unicodeUtf8
  96. # Env. name containing Unicode characters and empty value is set correctly
  97. block:
  98. const envName = unicodeUtf8 & "3"
  99. putEnv(envName, "")
  100. doAssert existsEnv(envName)
  101. doAssert $c_wgetenv(envName.newWideCString) == ""
  102. # It's hard to test on Windows code pages, because there is no "change
  103. # a process' locale" API.
  104. if getCurrentEncoding(true) == "windows-1252":
  105. const
  106. unicodeAnsi = "\xc6" # `unicodeUtf8` in `windows-1252` encoding
  107. # Test that env. var. ANSI API has correct encoding
  108. block:
  109. const
  110. envName = unicodeUtf8 & "4"
  111. envNameAnsi = unicodeAnsi & "4"
  112. putEnv(envName, unicodeUtf8)
  113. doAssert $c_getenv(envNameAnsi.cstring) == unicodeAnsi
  114. block:
  115. const
  116. envName = unicodeUtf8 & "5"
  117. envNameAnsi = unicodeAnsi & "5"
  118. doAssert c_putenv((envNameAnsi & "=" & unicodeAnsi).cstring) == 0
  119. doAssert getEnv(envName) == unicodeUtf8
  120. # Env. name containing Unicode characters and empty value is set correctly;
  121. # and, if env. name. characters cannot be represented in codepage, don't
  122. # raise an error.
  123. #
  124. # `win_setenv.nim` converts UTF-16 to ANSI when setting empty env. var. The
  125. # windows-1250 locale has no representation of `abreveUtf8` below, so the
  126. # conversion will fail, but this must not be fatal. It is expected that the
  127. # routine ignores updating MBCS environment (`environ` global) and carries
  128. # on.
  129. block:
  130. const
  131. # "LATIN SMALL LETTER A WITH BREVE" in UTF-8
  132. abreveUtf8 = "\xc4\x83"
  133. envName = abreveUtf8 & "6"
  134. putEnv(envName, "")
  135. doAssert existsEnv(envName)
  136. doAssert $c_wgetenv(envName.newWideCString) == ""
  137. doAssert getEnv(envName) == ""