GoPLS Viewer

Home|gopls/go/callgraph/vta/internal/trie/trie_test.go
1// Copyright 2021 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5//go:build go1.13
6// +build go1.13
7
8package trie
9
10import (
11    "reflect"
12    "strconv"
13    "testing"
14)
15
16func TestScope(t *testing.T) {
17    def := Scope{}
18    s0s1 := newScope(), newScope()
19    if s0 == def || s1 == def {
20        t.Error("newScope() should never be == to the default scope")
21    }
22    if s0 == s1 {
23        t.Errorf("newScope() %q and %q should not be =="s0s1)
24    }
25    if s0.id == 0 {
26        t.Error("s0.id is 0")
27    }
28    if s1.id == 0 {
29        t.Error("s1.id is 0")
30    }
31    got := s0.String()
32    if _err := strconv.Atoi(got); err != nil {
33        t.Errorf("scope{%s}.String() is not an int: got %s with error %s"s0goterr)
34    }
35}
36
37func TestCollision(t *testing.T) {
38    var x interface{} = 1
39    var y interface{} = 2
40
41    if v := TakeLhs(xy); v != x {
42        t.Errorf("TakeLhs(%s, %s) got %s. want %s"xyvx)
43    }
44    if v := TakeRhs(xy); v != y {
45        t.Errorf("TakeRhs(%s, %s) got %s. want %s"xyvy)
46    }
47}
48
49func TestDefault(t *testing.T) {
50    def := Map{}
51
52    if def.Size() != 0 {
53        t.Errorf("default node has non-0 size %d"def.Size())
54    }
55    if wantgot := (Scope{}), def.Scope(); got != want {
56        t.Errorf("default is in a non default scope (%s) from b (%s)"gotwant)
57    }
58    if vok := def.Lookup(123); !(v == nil && !ok) {
59        t.Errorf("Scope{}.Lookup() = (%s, %v) not (nil, false)"vok)
60    }
61    if !def.Range(func(k uint64v interface{}) bool {
62        t.Errorf("Scope{}.Range() called it callback on %d:%s"kv)
63        return true
64    }) {
65        t.Error("Scope{}.Range() always iterates through all elements")
66    }
67
68    if gotwant := def.String(), "{}"got != want {
69        t.Errorf("Scope{}.String() got %s. want %s"gotwant)
70    }
71
72    b := NewBuilder()
73    if def == b.Empty() {
74        t.Error("Scope{} == to an empty node from a builder")
75    }
76    if b.Clone(def) != b.Empty() {
77        t.Error("b.Clone(Scope{}) should equal b.Empty()")
78    }
79    if !def.DeepEqual(b.Empty()) {
80        t.Error("Scope{}.DeepEqual(b.Empty()) should hold")
81    }
82}
83
84func TestBuilders(t *testing.T) {
85    b0b1 := NewBuilder(), NewBuilder()
86    if b0.Scope() == b1.Scope() {
87        t.Errorf("builders have the same scope %s"b0.Scope())
88    }
89
90    if b0.Empty() == b1.Empty() {
91        t.Errorf("empty nodes from different scopes are disequal")
92    }
93    if !b0.Empty().DeepEqual(b1.Empty()) {
94        t.Errorf("empty nodes from different scopes are not DeepEqual")
95    }
96
97    clone := b1.Clone(b0.Empty())
98    if clone != b1.Empty() {
99        t.Errorf("Clone() empty nodes %v != %v"cloneb1.Empty())
100    }
101}
102
103func TestEmpty(t *testing.T) {
104    b := NewBuilder()
105    e := b.Empty()
106    if e.Size() != 0 {
107        t.Errorf("empty nodes has non-0 size %d"e.Size())
108    }
109    if e.Scope() != b.Scope() {
110        t.Errorf("b.Empty() is in a different scope (%s) from b (%s)"e.Scope(), b.Scope())
111    }
112    if vok := e.Lookup(123); !(v == nil && !ok) {
113        t.Errorf("empty.Lookup() = (%s, %v) not (nil, false)"vok)
114    }
115    if l := e.n.find(123); l != nil {
116        t.Errorf("empty.find(123) got %v. want nil"l)
117    }
118    e.Range(func(k uint64v interface{}) bool {
119        t.Errorf("empty.Range() called it callback on %d:%s"kv)
120        return true
121    })
122
123    want := "{}"
124    if got := e.String(); got != want {
125        t.Errorf("empty.String(123) got %s. want %s"gotwant)
126    }
127}
128
129func TestCreate(t *testing.T) {
130    // The node orders are printed in lexicographic little-endian.
131    b := NewBuilder()
132    for _c := range []struct {
133        m    map[uint64]interface{}
134        want string
135    }{
136        {
137            map[uint64]interface{}{},
138            "{}",
139        },
140        {
141            map[uint64]interface{}{1"a"},
142            "{1: a}",
143        },
144        {
145            map[uint64]interface{}{2"b"1"a"},
146            "{1: a, 2: b}",
147        },
148        {
149            map[uint64]interface{}{1"x"4"y"5"z"},
150            "{1: x, 4: y, 5: z}",
151        },
152    } {
153        m := b.Create(c.m)
154        if got := m.String(); got != c.want {
155            t.Errorf("Create(%v) got %q. want %q "c.mgotc.want)
156        }
157    }
158}
159
160func TestElems(t *testing.T) {
161    b := NewBuilder()
162    for _orig := range []map[uint64]interface{}{
163        {},
164        {1"a"},
165        {1"a"2"b"},
166        {1"x"4"y"5"z"},
167        {1"x"4"y"5"z"123"abc"},
168    } {
169        m := b.Create(orig)
170        if elems := Elems(m); !reflect.DeepEqual(origelems) {
171            t.Errorf("Elems(%v) got %q. want %q "melemsorig)
172        }
173    }
174}
175
176func TestRange(t *testing.T) {
177    b := NewBuilder()
178    m := b.Create(map[uint64]interface{}{1"x"3"y"5"z"6"stop"8"a"})
179
180    calls := 0
181    cb := func(k uint64v interface{}) bool {
182        t.Logf("visiting (%d, %v)"kv)
183        calls++
184        return k%2 != 0 // stop after the first even number.
185    }
186    // The nodes are visited in increasing order.
187    all := m.Range(cb)
188    if all {
189        t.Error("expected to stop early")
190    }
191    want := 4
192    if calls != want {
193        t.Errorf("# of callbacks (%d) was expected to equal %d (1 + # of evens)",
194            callswant)
195    }
196}
197
198func TestDeepEqual(t *testing.T) {
199    for _m := range []map[uint64]interface{}{
200        {},
201        {1"x"},
202        {1"x"2"y"},
203    } {
204        l := NewBuilder().Create(m)
205        r := NewBuilder().Create(m)
206        if !l.DeepEqual(r) {
207            t.Errorf("Expect %v to be DeepEqual() to %v"lr)
208        }
209    }
210}
211
212func TestNotDeepEqual(t *testing.T) {
213    for _c := range []struct {
214        left  map[uint64]interface{}
215        right map[uint64]interface{}
216    }{
217        {
218            map[uint64]interface{}{1"x"},
219            map[uint64]interface{}{},
220        },
221        {
222            map[uint64]interface{}{},
223            map[uint64]interface{}{1"y"},
224        },
225        {
226            map[uint64]interface{}{1"x"},
227            map[uint64]interface{}{1"y"},
228        },
229        {
230            map[uint64]interface{}{1"x"},
231            map[uint64]interface{}{1"x"2"Y"},
232        },
233        {
234            map[uint64]interface{}{1"x"2"Y"},
235            map[uint64]interface{}{1"x"},
236        },
237        {
238            map[uint64]interface{}{1"x"2"y"},
239            map[uint64]interface{}{1"x"2"Y"},
240        },
241    } {
242        l := NewBuilder().Create(c.left)
243        r := NewBuilder().Create(c.right)
244        if l.DeepEqual(r) {
245            t.Errorf("Expect %v to be !DeepEqual() to %v"lr)
246        }
247    }
248}
249
250func TestMerge(t *testing.T) {
251    b := NewBuilder()
252    for _c := range []struct {
253        left  map[uint64]interface{}
254        right map[uint64]interface{}
255        want  string
256    }{
257        {
258            map[uint64]interface{}{},
259            map[uint64]interface{}{},
260            "{}",
261        },
262        {
263            map[uint64]interface{}{},
264            map[uint64]interface{}{1"a"},
265            "{1: a}",
266        },
267        {
268            map[uint64]interface{}{1"a"},
269            map[uint64]interface{}{},
270            "{1: a}",
271        },
272        {
273            map[uint64]interface{}{1"a"2"b"},
274            map[uint64]interface{}{},
275            "{1: a, 2: b}",
276        },
277        {
278            map[uint64]interface{}{1"x"},
279            map[uint64]interface{}{1"y"},
280            "{1: x}"// default collision is left
281        },
282        {
283            map[uint64]interface{}{1"x"},
284            map[uint64]interface{}{2"y"},
285            "{1: x, 2: y}",
286        },
287        {
288            map[uint64]interface{}{4"y"5"z"},
289            map[uint64]interface{}{1"x"},
290            "{1: x, 4: y, 5: z}",
291        },
292        {
293            map[uint64]interface{}{1"x"5"z"},
294            map[uint64]interface{}{4"y"},
295            "{1: x, 4: y, 5: z}",
296        },
297        {
298            map[uint64]interface{}{1"x"4"y"},
299            map[uint64]interface{}{5"z"},
300            "{1: x, 4: y, 5: z}",
301        },
302        {
303            map[uint64]interface{}{1"a"4"c"},
304            map[uint64]interface{}{2"b"5"d"},
305            "{1: a, 2: b, 4: c, 5: d}",
306        },
307        {
308            map[uint64]interface{}{1"a"4"c"},
309            map[uint64]interface{}{2"b"5 + 8"d"},
310            "{1: a, 2: b, 4: c, 13: d}",
311        },
312        {
313            map[uint64]interface{}{2"b"5 + 8"d"},
314            map[uint64]interface{}{1"a"4"c"},
315            "{1: a, 2: b, 4: c, 13: d}",
316        },
317        {
318            map[uint64]interface{}{1"a"4"c"},
319            map[uint64]interface{}{2"b"5 + 8"d"},
320            "{1: a, 2: b, 4: c, 13: d}",
321        },
322        {
323            map[uint64]interface{}{2"b"5 + 8"d"},
324            map[uint64]interface{}{1"a"4"c"},
325            "{1: a, 2: b, 4: c, 13: d}",
326        },
327        {
328            map[uint64]interface{}{2"b"5 + 8"d"},
329            map[uint64]interface{}{2""3"a"},
330            "{2: b, 3: a, 13: d}",
331        },
332
333        {
334            // crafted for `!prefixesOverlap(p, m, q, n)`
335            left:  map[uint64]interface{}{1"a"2 + 1"b"},
336            right: map[uint64]interface{}{4 + 1"c"4 + 2"d"},
337            // p: 5, m: 2 q: 1, n: 2
338            want"{1: a, 3: b, 5: c, 6: d}",
339        },
340        {
341            // crafted for `ord(m, n) && !zeroBit(q, m)`
342            left:  map[uint64]interface{}{8 + 2 + 1"a"16 + 4"b"},
343            right: map[uint64]interface{}{16 + 8 + 2 + 1"c"16 + 8 + 4 + 2 + 1"d"},
344            // left: p: 15, m: 16
345            // right: q: 27, n: 4
346            want"{11: a, 20: b, 27: c, 31: d}",
347        },
348        {
349            // crafted for `ord(n, m) && !zeroBit(p, n)`
350            // p: 6, m: 1 q: 5, n: 2
351            left:  map[uint64]interface{}{4 + 2"b"4 + 2 + 1"c"},
352            right: map[uint64]interface{}{4"a"4 + 2 + 1"dropped"},
353            want:  "{4: a, 6: b, 7: c}",
354        },
355    } {
356        lr := b.Create(c.left), b.Create(c.right)
357        m := b.Merge(lr)
358        if got := m.String(); got != c.want {
359            t.Errorf("Merge(%s, %s) got %q. want %q "lrgotc.want)
360        }
361    }
362}
363
364func TestIntersect(t *testing.T) {
365    // Most of the test cases go after specific branches of intersect.
366    b := NewBuilder()
367    for _c := range []struct {
368        left  map[uint64]interface{}
369        right map[uint64]interface{}
370        want  string
371    }{
372        {
373            left:  map[uint64]interface{}{10"a"39"b"},
374            right: map[uint64]interface{}{10"A"39"B"75"C"},
375            want:  "{10: a, 39: b}",
376        },
377        {
378            left:  map[uint64]interface{}{10"a"39"b"},
379            right: map[uint64]interface{}{},
380            want:  "{}",
381        },
382        {
383            left:  map[uint64]interface{}{},
384            right: map[uint64]interface{}{10"A"39"B"75"C"},
385            want:  "{}",
386        },
387        { // m == n && p == q  && left.(*empty) case
388            left:  map[uint64]interface{}{416310815"on left"},
389            right: map[uint64]interface{}{087611015"on right"},
390            want:  "{15: on left}",
391        },
392        { // m == n && p == q  && right.(*empty) case
393            left:  map[uint64]interface{}{0"on left"12233173},
394            right: map[uint64]interface{}{0"on right"5168},
395            want:  "{0: on left}",
396        },
397        { // m == n && p == q  &&  both left and right are not empty
398            left:  map[uint64]interface{}{1"a"2"b"3"c"},
399            right: map[uint64]interface{}{0"A"1"B"2"C"},
400            want:  "{1: a, 2: b}",
401        },
402        { // m == n && p == q  &&  both left and right are not empty
403            left:  map[uint64]interface{}{1"a"2"b"3"c"},
404            right: map[uint64]interface{}{0"A"1"B"2"C"},
405            want:  "{1: a, 2: b}",
406        },
407        { // !prefixesOverlap(p, m, q, n)
408            // p = 1, m = 2, q = 5, n = 2
409            left:  map[uint64]interface{}{0b00110b0113},
410            right: map[uint64]interface{}{0b10040b1117},
411            want:  "{}",
412        },
413        { // ord(m, n) && zeroBit(q, m)
414            // p = 3, m = 4, q = 0, n = 1
415            left:  map[uint64]interface{}{0b01020b1015},
416            right: map[uint64]interface{}{0b00000b0011},
417            want:  "{}",
418        },
419
420        { // ord(m, n) && !zeroBit(q, m)
421            // p = 29, m = 2, q = 30, n = 1
422            left: map[uint64]interface{}{
423                0b11101"29",
424                0b11110"30",
425            },
426            right: map[uint64]interface{}{
427                0b11110"30 on right",
428                0b11111"31",
429            },
430            want"{30: 30}",
431        },
432        { // ord(n, m) && zeroBit(p, n)
433            // p = 5, m = 2, q = 3, n = 4
434            left:  map[uint64]interface{}{0b00000b0011},
435            right: map[uint64]interface{}{0b01020b1015},
436            want:  "{}",
437        },
438        { // default case
439            // p = 5, m = 2, q = 3, n = 4
440            left:  map[uint64]interface{}{0b10010b1103},
441            right: map[uint64]interface{}{0b00080b1116},
442            want:  "{}",
443        },
444    } {
445        lr := b.Create(c.left), b.Create(c.right)
446        m := b.Intersect(lr)
447        if got := m.String(); got != c.want {
448            t.Errorf("Intersect(%s, %s) got %q. want %q "lrgotc.want)
449        }
450    }
451}
452
453func TestIntersectWith(t *testing.T) {
454    b := NewBuilder()
455    l := b.Create(map[uint64]interface{}{102.03932.0})
456    r := b.Create(map[uint64]interface{}{106.03910.0751.0})
457
458    prodIfDifferent := func(x interface{}, y interface{}) interface{} {
459        if xok := x.(float64); ok {
460            if yok := y.(float64); ok {
461                if x == y {
462                    return x
463                }
464                return x * y
465            }
466        }
467        return x
468    }
469
470    m := b.IntersectWith(prodIfDifferentlr)
471
472    want := "{10: %!s(float64=12), 39: %!s(float64=320)}"
473    if got := m.String(); got != want {
474        t.Errorf("IntersectWith(min, %s, %s) got %q. want %q "lrgotwant)
475    }
476}
477
478func TestRemove(t *testing.T) {
479    // Most of the test cases go after specific branches of intersect.
480    b := NewBuilder()
481    for _c := range []struct {
482        m    map[uint64]interface{}
483        key  uint64
484        want string
485    }{
486        {map[uint64]interface{}{}, 10"{}"},
487        {map[uint64]interface{}{10"a"}, 10"{}"},
488        {map[uint64]interface{}{39"b"}, 10"{39: b}"},
489        // Branch cases:
490        // !matchPrefix(kp, br.prefix, br.branching)
491        {map[uint64]interface{}{10"a"39"b"}, 128"{10: a, 39: b}"},
492        // case: left == br.left && right == br.right
493        {map[uint64]interface{}{10"a"39"b"}, 16"{10: a, 39: b}"},
494        // left updated and is empty.
495        {map[uint64]interface{}{10"a"39"b"}, 10"{39: b}"},
496        // right updated and is empty.
497        {map[uint64]interface{}{10"a"39"b"}, 39"{10: a}"},
498        // final b.mkBranch(...) case.
499        {map[uint64]interface{}{10"a"39"b"128"c"}, 39"{10: a, 128: c}"},
500    } {
501        pre := b.Create(c.m)
502        post := b.Remove(prec.key)
503        if got := post.String(); got != c.want {
504            t.Errorf("Remove(%s, %d) got %q. want %q "prec.keygotc.want)
505        }
506    }
507}
508
509func TestRescope(t *testing.T) {
510    b := NewBuilder()
511    l := b.Create(map[uint64]interface{}{10"a"39"b"})
512    r := b.Create(map[uint64]interface{}{10"A"39"B"75"C"})
513
514    b.Rescope()
515
516    m := b.Intersect(lr)
517    if gotwant := m.String(), "{10: a, 39: b}"got != want {
518        t.Errorf("Intersect(%s, %s) got %q. want %q"lrgotwant)
519    }
520    if m.Scope() == l.Scope() {
521        t.Errorf("m.Scope() = %v should not equal l.Scope() = %v"m.Scope(), l.Scope())
522    }
523    if m.Scope() == r.Scope() {
524        t.Errorf("m.Scope() = %v should not equal r.Scope() = %v"m.Scope(), r.Scope())
525    }
526}
527
528func TestSharing(t *testing.T) {
529    b := NewBuilder()
530    l := b.Create(map[uint64]interface{}{0"a"1"b"})
531    r := b.Create(map[uint64]interface{}{1"B"2"C"})
532
533    rleftold := r.n.(*branch).left
534
535    m := b.Merge(lr)
536    if mleft := m.n.(*branch).leftmleft != l.n {
537        t.Errorf("unexpected value for left branch of %v. want %v got %v"mlmleft)
538    }
539
540    if rleftnow := r.n.(*branch).leftrleftnow != rleftold {
541        t.Errorf("r.n.(*branch).left was modified by the Merge operation. was %v now %v"rleftoldrleftnow)
542    }
543}
544
MembersX
TestElems
TestDeepEqual.t
TestEmpty.ok
TestMerge.b
TestRemove.RangeStmt_11986.c
TestRescope.t
TestIntersectWith
TestIntersectWith.b
TestRescope.m
TestRescope.got
TestEmpty
TestElems.RangeStmt_3856.BlockStmt.m
TestRescope.l
TestRemove
TestBuilders.b1
TestNotDeepEqual.RangeStmt_5010.c
TestCollision.t
TestRange.want
TestIntersect.RangeStmt_8681.BlockStmt.got
TestIntersectWith.r
TestRemove.t
TestRescope.r
TestBuilders
TestBuilders.clone
TestRange.all
TestDeepEqual.RangeStmt_4736.BlockStmt.r
TestNotDeepEqual.RangeStmt_5010.BlockStmt.l
TestRescope
TestEmpty.l
TestEmpty.got
TestMerge.RangeStmt_5814.BlockStmt.got
TestIntersect.b
TestDeepEqual.RangeStmt_4736.BlockStmt.l
TestRemove.RangeStmt_11986.BlockStmt.pre
TestNotDeepEqual
TestMerge
TestElems.RangeStmt_3856.BlockStmt.elems
TestRange.m
TestNotDeepEqual.RangeStmt_5010.BlockStmt.r
TestIntersectWith.want
TestCollision.v
TestElems.b
TestIntersect.RangeStmt_8681.c
TestSharing.rleftnow
TestDefault
TestRange.t
TestDeepEqual.RangeStmt_4736.m
TestRemove.b
TestScope
TestScope.s1
TestSharing.b
TestSharing.t
TestDefault.b
TestEmpty.b
TestIntersect.RangeStmt_8681.BlockStmt.l
TestRescope.b
TestCreate.b
TestSharing.l
TestSharing.rleftold
TestScope.err
TestDefault.v
TestBuilders.b0
TestMerge.RangeStmt_5814.BlockStmt.l
TestIntersectWith.m
TestSharing.m
TestScope.s0
TestDeepEqual
TestScope.def
TestMerge.t
TestIntersect.RangeStmt_8681.BlockStmt.m
TestIntersectWith.l
TestSharing.r
TestEmpty.t
TestEmpty.want
TestIntersect.t
TestDefault.def
TestRange.b
TestMerge.RangeStmt_5814.c
TestRemove.RangeStmt_11986.BlockStmt.got
TestScope.t
TestScope._
TestCollision
TestDefault.want
TestBuilders.t
TestEmpty.e
TestCreate.RangeStmt_3331.BlockStmt.m
TestMerge.RangeStmt_5814.BlockStmt.m
TestIntersectWith.t
TestCreate.RangeStmt_3331.c
TestIntersect
TestRescope.want
TestSharing.mleft
TestScope.got
TestDefault.ok
TestCreate
TestCreate.t
TestRange.calls
TestIntersect.RangeStmt_8681.BlockStmt.r
TestDefault.t
TestDefault.got
TestCreate.RangeStmt_3331.BlockStmt.got
TestMerge.RangeStmt_5814.BlockStmt.r
TestIntersectWith.got
TestEmpty.v
TestElems.t
TestElems.RangeStmt_3856.orig
TestNotDeepEqual.t
TestRange
TestRemove.RangeStmt_11986.BlockStmt.post
TestSharing
Members
X