Source file
test/fixedbugs/issue81266.go
1
2
3
4
5
6
7
8
9
10 package main
11
12 import (
13 "fmt"
14 "unsafe"
15 )
16
17 func check(name string, got, want bool) {
18 if got != want {
19 panic(fmt.Sprintf("%s: got %v want %v", name, got, want))
20 }
21 }
22
23
24 type Big struct {
25 Filler [2000]byte
26 S string
27 B byte
28 }
29
30
31
32 type Outer struct {
33 Big Big
34 X byte
35 }
36
37
38
39
40 func fill(p unsafe.Pointer, size uintptr, b byte) {
41 buf := unsafe.Slice((*byte)(p), size)
42 for i := range buf {
43 buf[i] = b
44 }
45 }
46
47 var filler [2000]byte
48
49 func init() {
50 for i := range filler {
51 filler[i] = byte(i)
52 }
53 }
54
55 func mkBig(s string, b byte, pad byte) Big {
56 var x Big
57 fill(unsafe.Pointer(&x), unsafe.Sizeof(x), pad)
58 x.Filler = filler
59 x.S = s
60 x.B = b
61 return x
62 }
63
64 func testBasic() {
65 a := Outer{Big: mkBig("foo", 7, 0xAA), X: 1}
66 c := Outer{Big: mkBig("foo", 7, 0x55), X: 1}
67 check("equal despite differing padding inside Big", a == c, true)
68
69 d := Outer{Big: mkBig("foo", 7, 0xAA), X: 2}
70 check("differ in trailing field X", a == d, false)
71
72 e := Outer{Big: mkBig("bar", 7, 0xAA), X: 1}
73 check("differ in Big.S", a == e, false)
74
75 g := Outer{Big: mkBig("foo", 9, 0xAA), X: 1}
76 check("differ in Big.B", a == g, false)
77
78 h := a
79 h.Big.Filler[1000] ^= 0xFF
80 check("differ in Big.Filler", a == h, false)
81 }
82
83
84 func testPadding() {
85 var a, c Outer
86 fill(unsafe.Pointer(&a), unsafe.Sizeof(a), 0x11)
87 fill(unsafe.Pointer(&c), unsafe.Sizeof(c), 0x99)
88 a.Big.Filler = filler
89 c.Big.Filler = filler
90 a.Big.S = "padding-check"
91 c.Big.S = "padding-check"
92 a.Big.B = 42
93 c.Big.B = 42
94 a.X = 5
95 c.X = 5
96 check("equal with garbage-filled padding", a == c, true)
97 }
98
99
100 func testHash() {
101 m := make(map[Outer]int)
102 k1 := Outer{Big: mkBig("k1", 1, 0), X: 1}
103 k2 := Outer{Big: mkBig("k2", 2, 0), X: 2}
104 m[k1] = 100
105 m[k2] = 200
106
107 look1 := Outer{Big: mkBig("k1", 1, 0xFF), X: 1}
108 look2 := Outer{Big: mkBig("k2", 2, 0xFF), X: 2}
109 v1, ok1 := m[look1]
110 v2, ok2 := m[look2]
111 check("map lookup k1 found", ok1, true)
112 check("map lookup k2 found", ok2, true)
113 if v1 != 100 {
114 panic(fmt.Sprintf("map k1 value: got %v want 100", v1))
115 }
116 if v2 != 200 {
117 panic(fmt.Sprintf("map k2 value: got %v want 200", v2))
118 }
119
120 notFound := Outer{Big: mkBig("k1", 1, 0), X: 99}
121 _, ok3 := m[notFound]
122 check("map lookup miss", ok3, false)
123 }
124
125
126
127 func testNested() {
128
129
130 type Level1 struct {
131 B Big
132 F2 [2000]byte
133 T string
134 C byte
135 }
136
137 type Outer2 struct {
138 L1 Level1
139 Y byte
140 }
141
142 mkLevel1 := func(s1, s2 string, b1, b2 byte) Level1 {
143 var l Level1
144 l.B = mkBig(s1, b1, 0)
145 l.F2 = filler
146 l.T = s2
147 l.C = b2
148 return l
149 }
150
151 a := Outer2{L1: mkLevel1("inner1", "outer1", 1, 2), Y: 9}
152 c := Outer2{L1: mkLevel1("inner1", "outer1", 1, 2), Y: 9}
153 check("nested equal", a == c, true)
154
155 d := a
156 d.L1.B.S = "changed"
157 check("nested differ in deepest field", a == d, false)
158
159 e := a
160 e.L1.T = "changed"
161 check("nested differ in Level1 field", a == e, false)
162
163 g := a
164 g.Y = 10
165 check("nested differ in outer field", a == g, false)
166
167 mm := make(map[Outer2]string)
168 mm[a] = "a-value"
169 if got := mm[c]; got != "a-value" {
170 panic(fmt.Sprintf("nested map lookup: got %q want %q", got, "a-value"))
171 }
172 }
173
174
175
176 func testArray() {
177 type BigArr struct {
178 A [3]Big
179 }
180 var a, c BigArr
181 for i := range a.A {
182 a.A[i] = mkBig(fmt.Sprintf("elem%d", i), byte(i), byte(i))
183 c.A[i] = mkBig(fmt.Sprintf("elem%d", i), byte(i), byte(i+100))
184 }
185 check("array equal despite differing padding", a == c, true)
186
187 d := a
188 d.A[2].S = "different"
189 check("array differ in one element", a == d, false)
190 }
191
192
193
194 func testBoundary() {
195 type Exactly1024 struct {
196 F [1024 - 16]byte
197 S string
198 }
199 type Container1024 struct {
200 V Exactly1024
201 X byte
202 }
203 var a, c Container1024
204 a.V.S = "same"
205 c.V.S = "same"
206 a.X = 1
207 c.X = 1
208 check("boundary <=1024 equal", a == c, true)
209 d := a
210 d.V.S = "diff"
211 check("boundary <=1024 differ", a == d, false)
212
213 type Exactly1025 struct {
214 F [1025 - 16]byte
215 S string
216 }
217 type Container1025 struct {
218 V Exactly1025
219 X byte
220 }
221 var e, g Container1025
222 e.V.S = "same"
223 g.V.S = "same"
224 e.X = 1
225 g.X = 1
226 check("boundary >1024 equal", e == g, true)
227 h := e
228 h.V.S = "diff"
229 check("boundary >1024 differ", e == h, false)
230 }
231
232 func main() {
233 testBasic()
234 testPadding()
235 testHash()
236 testNested()
237 testArray()
238 testBoundary()
239 }
240
View as plain text