winutil_windows_test.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. package winutil
  4. import (
  5. "reflect"
  6. "testing"
  7. "unsafe"
  8. )
  9. //lint:file-ignore U1000 Fields are unused but necessary for tests.
  10. const (
  11. localSystemSID = "S-1-5-18"
  12. networkSID = "S-1-5-2"
  13. )
  14. func TestLookupPseudoUser(t *testing.T) {
  15. localSystem, err := LookupPseudoUser(localSystemSID)
  16. if err != nil {
  17. t.Errorf("LookupPseudoUser(%q) error: %v", localSystemSID, err)
  18. }
  19. if localSystem.Gid != localSystemSID {
  20. t.Errorf("incorrect Gid, got %q, want %q", localSystem.Gid, localSystemSID)
  21. }
  22. t.Logf("localSystem: %v", localSystem)
  23. // networkSID is a built-in known group but not a pseudo-user.
  24. _, err = LookupPseudoUser(networkSID)
  25. if err == nil {
  26. t.Errorf("LookupPseudoUser(%q) unexpectedly succeeded", networkSID)
  27. }
  28. }
  29. type testType interface {
  30. byte | uint16 | uint32 | uint64
  31. }
  32. type noPointers[T testType] struct {
  33. foo byte
  34. bar T
  35. baz bool
  36. }
  37. type hasPointer struct {
  38. foo byte
  39. bar uint32
  40. s1 *struct{}
  41. baz byte
  42. }
  43. func checkContiguousBuffer[T any, BU BufUnit](t *testing.T, extra []BU, pt *T, ptLen uint32, slcs [][]BU) {
  44. szBU := int(unsafe.Sizeof(BU(0)))
  45. expectedAlign := max(reflect.TypeFor[T]().Align(), szBU)
  46. // Check that pointer is aligned
  47. if rem := uintptr(unsafe.Pointer(pt)) % uintptr(expectedAlign); rem != 0 {
  48. t.Errorf("pointer alignment got %d, want 0", rem)
  49. }
  50. // Check that alloc length is aligned
  51. if rem := int(ptLen) % expectedAlign; rem != 0 {
  52. t.Errorf("allocation length alignment got %d, want 0", rem)
  53. }
  54. expectedLen := int(unsafe.Sizeof(*pt))
  55. expectedLen = alignUp(expectedLen, szBU)
  56. expectedLen += len(extra) * szBU
  57. expectedLen = alignUp(expectedLen, expectedAlign)
  58. if gotLen := int(ptLen); gotLen != expectedLen {
  59. t.Errorf("allocation length got %d, want %d", gotLen, expectedLen)
  60. }
  61. if ln := len(slcs); ln != 1 {
  62. t.Errorf("len(slcs) got %d, want 1", ln)
  63. }
  64. if len(extra) == 0 && slcs[0] != nil {
  65. t.Error("slcs[0] got non-nil, want nil")
  66. }
  67. if len(extra) != len(slcs[0]) {
  68. t.Errorf("len(slcs[0]) got %d, want %d", len(slcs[0]), len(extra))
  69. } else if rem := uintptr(unsafe.Pointer(unsafe.SliceData(slcs[0]))) % uintptr(szBU); rem != 0 {
  70. t.Errorf("additional data alignment got %d, want 0", rem)
  71. }
  72. }
  73. func TestAllocateContiguousBuffer(t *testing.T) {
  74. t.Run("NoValues", testNoValues)
  75. t.Run("NoPointers", testNoPointers)
  76. t.Run("HasPointer", testHasPointer)
  77. }
  78. func testNoValues(t *testing.T) {
  79. defer func() {
  80. if r := recover(); r == nil {
  81. t.Error("expected panic but didn't get one")
  82. }
  83. }()
  84. AllocateContiguousBuffer[hasPointer, byte]()
  85. }
  86. const maxTestBufLen = 8
  87. func testNoPointers(t *testing.T) {
  88. buf8 := make([]byte, maxTestBufLen)
  89. buf16 := make([]uint16, maxTestBufLen)
  90. for i := range maxTestBufLen {
  91. s8, sl, slcs8 := AllocateContiguousBuffer[noPointers[byte]](buf8[:i])
  92. checkContiguousBuffer(t, buf8[:i], s8, sl, slcs8)
  93. s16, sl, slcs8 := AllocateContiguousBuffer[noPointers[uint16]](buf8[:i])
  94. checkContiguousBuffer(t, buf8[:i], s16, sl, slcs8)
  95. s32, sl, slcs8 := AllocateContiguousBuffer[noPointers[uint32]](buf8[:i])
  96. checkContiguousBuffer(t, buf8[:i], s32, sl, slcs8)
  97. s64, sl, slcs8 := AllocateContiguousBuffer[noPointers[uint64]](buf8[:i])
  98. checkContiguousBuffer(t, buf8[:i], s64, sl, slcs8)
  99. s8, sl, slcs16 := AllocateContiguousBuffer[noPointers[byte]](buf16[:i])
  100. checkContiguousBuffer(t, buf16[:i], s8, sl, slcs16)
  101. s16, sl, slcs16 = AllocateContiguousBuffer[noPointers[uint16]](buf16[:i])
  102. checkContiguousBuffer(t, buf16[:i], s16, sl, slcs16)
  103. s32, sl, slcs16 = AllocateContiguousBuffer[noPointers[uint32]](buf16[:i])
  104. checkContiguousBuffer(t, buf16[:i], s32, sl, slcs16)
  105. s64, sl, slcs16 = AllocateContiguousBuffer[noPointers[uint64]](buf16[:i])
  106. checkContiguousBuffer(t, buf16[:i], s64, sl, slcs16)
  107. }
  108. }
  109. func testHasPointer(t *testing.T) {
  110. buf8 := make([]byte, maxTestBufLen)
  111. buf16 := make([]uint16, maxTestBufLen)
  112. for i := range maxTestBufLen {
  113. s, sl, slcs8 := AllocateContiguousBuffer[hasPointer](buf8[:i])
  114. checkContiguousBuffer(t, buf8[:i], s, sl, slcs8)
  115. s, sl, slcs16 := AllocateContiguousBuffer[hasPointer](buf16[:i])
  116. checkContiguousBuffer(t, buf16[:i], s, sl, slcs16)
  117. }
  118. }