Import upstream version 1.0.2
Debian Janitor
2 years ago
66 | 66 |
type PointerWalker interface {
|
67 | 67 |
PointerEnter(bool) error
|
68 | 68 |
PointerExit(bool) error
|
|
69 |
}
|
|
70 |
|
|
71 |
// PointerValueWalker implementations are notified with the value of
|
|
72 |
// a particular pointer when a pointer is walked. Pointer is called
|
|
73 |
// right before PointerEnter.
|
|
74 |
type PointerValueWalker interface {
|
|
75 |
Pointer(reflect.Value) error
|
69 | 76 |
}
|
70 | 77 |
|
71 | 78 |
// SkipEntry can be returned from walk functions to skip walking
|
|
129 | 136 |
}
|
130 | 137 |
|
131 | 138 |
if pointerV.Kind() == reflect.Ptr {
|
|
139 |
if pw, ok := w.(PointerValueWalker); ok {
|
|
140 |
if err = pw.Pointer(pointerV); err != nil {
|
|
141 |
if err == SkipEntry {
|
|
142 |
// Skip the rest of this entry but clear the error
|
|
143 |
return nil
|
|
144 |
}
|
|
145 |
|
|
146 |
return
|
|
147 |
}
|
|
148 |
}
|
|
149 |
|
132 | 150 |
pointer = true
|
133 | 151 |
v = reflect.Indirect(pointerV)
|
134 | 152 |
}
|
45 | 45 |
return fmt.Errorf("bad pointer exit '%t' at exit %d", v, t.exits)
|
46 | 46 |
}
|
47 | 47 |
t.pointers = t.pointers[:len(t.pointers)-1]
|
|
48 |
return nil
|
|
49 |
}
|
|
50 |
|
|
51 |
type TestPointerValueWalker struct {
|
|
52 |
skip bool
|
|
53 |
pointers []reflect.Type
|
|
54 |
}
|
|
55 |
|
|
56 |
func (t *TestPointerValueWalker) Pointer(v reflect.Value) error {
|
|
57 |
t.pointers = append(t.pointers, v.Type())
|
|
58 |
if t.skip {
|
|
59 |
return SkipEntry
|
|
60 |
}
|
|
61 |
|
48 | 62 |
return nil
|
49 | 63 |
}
|
50 | 64 |
|
|
481 | 495 |
}
|
482 | 496 |
}
|
483 | 497 |
|
|
498 |
func TestWalk_PointerValue(t *testing.T) {
|
|
499 |
type X struct{}
|
|
500 |
type T struct {
|
|
501 |
x *X
|
|
502 |
}
|
|
503 |
|
|
504 |
v := &T{x: &X{}}
|
|
505 |
|
|
506 |
expected := []reflect.Type{
|
|
507 |
reflect.TypeOf(v),
|
|
508 |
reflect.TypeOf(v.x),
|
|
509 |
}
|
|
510 |
|
|
511 |
w := new(TestPointerValueWalker)
|
|
512 |
err := Walk(v, w)
|
|
513 |
if err != nil {
|
|
514 |
t.Fatal(err)
|
|
515 |
}
|
|
516 |
|
|
517 |
if !reflect.DeepEqual(expected, w.pointers) {
|
|
518 |
t.Fatalf("unexpected pointer order or length (expected len=%d, actual len=%d)", len(expected), len(w.pointers))
|
|
519 |
}
|
|
520 |
}
|
|
521 |
|
|
522 |
func TestWalk_PointerValueSkip(t *testing.T) {
|
|
523 |
type T struct{}
|
|
524 |
type W struct {
|
|
525 |
TestPointerValueWalker
|
|
526 |
TestPointerWalker
|
|
527 |
}
|
|
528 |
|
|
529 |
v := &T{}
|
|
530 |
w := &W{
|
|
531 |
TestPointerValueWalker: TestPointerValueWalker{
|
|
532 |
skip: true,
|
|
533 |
},
|
|
534 |
}
|
|
535 |
err := Walk(v, w)
|
|
536 |
if err != nil {
|
|
537 |
t.Fatal(err)
|
|
538 |
}
|
|
539 |
|
|
540 |
if len(w.TestPointerValueWalker.pointers) != 1 {
|
|
541 |
t.Errorf("expected len=1, got len=%d", len(w.TestPointerValueWalker.pointers))
|
|
542 |
}
|
|
543 |
|
|
544 |
if w.TestPointerValueWalker.pointers[0] != reflect.TypeOf(v) {
|
|
545 |
t.Error("pointer value type mismatch")
|
|
546 |
}
|
|
547 |
|
|
548 |
if w.enters != 0 || w.exits != 0 {
|
|
549 |
t.Error("should have been skipped and have zero enters or exits")
|
|
550 |
}
|
|
551 |
}
|
|
552 |
|
484 | 553 |
func TestWalk_Slice(t *testing.T) {
|
485 | 554 |
w := new(TestSliceWalker)
|
486 | 555 |
|