Files
Nim/tests/destructor/tnewruntime_misc.nim
havardjohn f4bbf3bf0b Add use of Windows Wide CRT API for env. vars (#20084)
* Add use of Windows Wide CRT API for env. vars

Replaces use of CRT API `getenv` and `putenv` with respectively
`_wgetenv` and `_wputenv`. Motivation is to reliably convert environment
variables to UTF-8, and the wide API is best there, because it's
reliably UTF-16.

Changed the hack in `lib/std/private/win_setenv.nim` by switching the
order of the Unicode and MBCS environment update; Unicode first, MBCS
second. Because `_wgetenv`/`_wputenv` is now used, the Unicode
environment will be initialized, so it should always be updated.

Stop updating MBCS environment with the name of `getEnv`. It's not
necessarily true that MBCS encoding and the `string` encoding is the
same. Instead convert UTF-16 to current Windows code page with
`wcstombs`, and use that string to update MBCS.

Fixes regression in `6b3c77e` that caused `std/envvars.getEnv` or
`std/os.getEnv` on Windows to return non-UTF-8 encoded strings.

Add tests that test environment variables with Unicode characters in
their name or value.

* Fix test issues

Fixes

* `nim cpp` didn't compile the tests
* Nimscript import of `tosenv.nim` from `test_nimscript.nims` failed
  with "cannot importc"

* Fix missing error check on `wcstombs`

* Fix ANSI testing errors

* Separate ANSI-related testing to their own tests, and only executing
  them if running process has a specific code page
  * Setting locale with `setlocale` was not reliable and didn't work on
    certain machines
* Add handling of a "no character representation" error in second
  `wcstombs` call

* tests/newruntime_misc: Increment allocCount

Increments overall allocations in `tnewruntime_misc` test. This is
because `getEnv` now does an additional allocation: allocation of the
UTF-16 string used as parameter to `c_wgetenv`.

* Revert "tests/newruntime_misc: Increment allocCount"

This reverts commit 4d4fe8bd3e.

* tests/newruntime_misc: Increment allocCount on Windows

Increments overall allocations in `tnewruntime_misc` test for Windows.
This is because `getEnv` on Windows now does an additional allocation:
allocation of the UTF-16 string used as parameter to `c_wgetenv`.

* Refactor, adding suggestions from code review

Co-authored-by: Clay Sweetser <Varriount@users.noreply.github.com>

* Document, adding suggestions

Co-authored-by: Clay Sweetser <Varriount@users.noreply.github.com>

Co-authored-by: ringabout <43030857+ringabout@users.noreply.github.com>
Co-authored-by: Clay Sweetser <Varriount@users.noreply.github.com>
2022-08-20 04:30:11 -04:00

156 lines
2.5 KiB
Nim

discard """
cmd: '''nim cpp -d:nimAllocStats --newruntime --threads:on $file'''
output: '''(field: "value")
Indeed
axc
(v: 10)
...
destroying GenericObj[T] GenericObj[system.int]
test
(allocCount: 12, deallocCount: 10)
3'''
"""
import system / ansi_c
import tables
type
Node = ref object
field: string
# bug #11807
import os
putEnv("HEAPTRASHING", "Indeed")
let s1 = getAllocStats()
proc newTableOwned[A, B](initialSize = defaultInitialSize): owned(TableRef[A, B]) =
new(result)
result[] = initTable[A, B](initialSize)
proc main =
var w = newTableOwned[string, owned Node]()
w["key"] = Node(field: "value")
echo w["key"][]
echo getEnv("HEAPTRASHING")
# bug #11891
var x = "abc"
x[1] = 'x'
echo x
main()
# bug #11745
type
Foo = object
bar: seq[int]
var x = [Foo()]
# bug #11563
type
MyTypeType = enum
Zero, One
MyType = object
case kind: MyTypeType
of Zero:
s*: seq[MyType]
of One:
x*: int
var t: MyType
# bug #11254
proc test(p: owned proc()) =
let x = (proc())p
test(proc() = discard)
# bug #10689
type
O = object
v: int
proc `=sink`(d: var O, s: O) =
d.v = s.v
proc selfAssign =
var o = O(v: 10)
o = o
echo o
selfAssign()
# bug #11833
type FooAt = object
proc testWrongAt() =
var x = @[@[FooAt()]]
testWrongAt()
#-------------------------------------------------
type
Table[A, B] = object
x: seq[(A, B)]
proc toTable[A,B](p: sink openArray[(A, B)]): Table[A, B] =
for zz in mitems(p):
result.x.add move(zz)
let table = {"a": new(int)}.toTable()
# bug # #12051
type
GenericObj[T] = object
val: T
Generic[T] = owned ref GenericObj[T]
proc `=destroy`[T](x: var GenericObj[T]) =
echo "destroying GenericObj[T] ", x.typeof # to know when its being destroyed
proc main12() =
let gnrc = Generic[int](val: 42)
echo "..."
main12()
#####################################################################
## bug #12827
type
MyObject = object
x: string
y: seq[string]
needs_ref: ref int
proc xx(xml: string): MyObject =
let stream = xml
result.x = xml
defer: echo stream
discard xx("test")
# Windows has 1 extra allocation in `getEnv` - there it allocates parameter to
# `_wgetenv` (WideCString). Therefore subtract by 1 to match other OSes'
# allocation.
when defined(windows):
import std/importutils
privateAccess(AllocStats)
echo getAllocStats() - s1 - AllocStats(allocCount: 1, deallocCount: 1)
else:
echo getAllocStats() - s1
# bug #13457
var s = "abcde"
s.setLen(3)
echo s.cstring.len