github.com/elves/elvish@v0.15.0/pkg/eval/vals/testutils.go (about) 1 package vals 2 3 import ( 4 "reflect" 5 "testing" 6 7 "github.com/elves/elvish/pkg/tt" 8 ) 9 10 // ValueTester is a helper for testing properties of a value. 11 type ValueTester struct { 12 t *testing.T 13 v interface{} 14 } 15 16 // TestValue returns a ValueTester. 17 func TestValue(t *testing.T, v interface{}) ValueTester { 18 return ValueTester{t, v} 19 } 20 21 // Kind tests the Kind of the value. 22 func (vt ValueTester) Kind(wantKind string) ValueTester { 23 vt.t.Helper() 24 kind := Kind(vt.v) 25 if kind != wantKind { 26 vt.t.Errorf("Kind(v) = %s, want %s", kind, wantKind) 27 } 28 return vt 29 } 30 31 // Bool tests the Boool of the value. 32 func (vt ValueTester) Bool(wantBool bool) ValueTester { 33 vt.t.Helper() 34 b := Bool(vt.v) 35 if b != wantBool { 36 vt.t.Errorf("Bool(v) = %v, want %v", b, wantBool) 37 } 38 return vt 39 } 40 41 // Hash tests the Hash of the value. 42 func (vt ValueTester) Hash(wantHash uint32) ValueTester { 43 vt.t.Helper() 44 hash := Hash(vt.v) 45 if hash != wantHash { 46 vt.t.Errorf("Hash(v) = %v, want %v", hash, wantHash) 47 } 48 return vt 49 } 50 51 // Len tests the Len of the value. 52 func (vt ValueTester) Len(wantLen int) ValueTester { 53 vt.t.Helper() 54 kind := Len(vt.v) 55 if kind != wantLen { 56 vt.t.Errorf("Len(v) = %v, want %v", kind, wantLen) 57 } 58 return vt 59 } 60 61 // Repr tests the Repr of the value. 62 func (vt ValueTester) Repr(wantRepr string) ValueTester { 63 vt.t.Helper() 64 kind := Repr(vt.v, NoPretty) 65 if kind != wantRepr { 66 vt.t.Errorf("Repr(v) = %s, want %s", kind, wantRepr) 67 } 68 return vt 69 } 70 71 // Equal tests that the value is Equal to every of the given values. 72 func (vt ValueTester) Equal(others ...interface{}) ValueTester { 73 vt.t.Helper() 74 for _, other := range others { 75 eq := Equal(vt.v, other) 76 if !eq { 77 vt.t.Errorf("Equal(v, %v) = false, want true", other) 78 } 79 } 80 return vt 81 } 82 83 // NotEqual tests that the value is not Equal to any of the given values. 84 func (vt ValueTester) NotEqual(others ...interface{}) ValueTester { 85 vt.t.Helper() 86 for _, other := range others { 87 eq := Equal(vt.v, other) 88 if eq { 89 vt.t.Errorf("Equal(v, %v) = true, want false", other) 90 } 91 } 92 return vt 93 } 94 95 // HasKey tests that the value has each of the given keys. 96 func (vt ValueTester) HasKey(keys ...interface{}) ValueTester { 97 vt.t.Helper() 98 for _, key := range keys { 99 has := HasKey(vt.v, key) 100 if !has { 101 vt.t.Errorf("HasKey(v, %v) = false, want true", key) 102 } 103 } 104 return vt 105 } 106 107 // HasNoKey tests that the value does not have any of the given keys. 108 func (vt ValueTester) HasNoKey(keys ...interface{}) ValueTester { 109 vt.t.Helper() 110 for _, key := range keys { 111 has := HasKey(vt.v, key) 112 if has { 113 vt.t.Errorf("HasKey(v, %v) = true, want false", key) 114 } 115 } 116 return vt 117 } 118 119 // AllKeys tests that the given keys match what the result of IterateKeys on the 120 // value. 121 // 122 // NOTE: This now checks equality using reflect.DeepEqual, since all the builtin 123 // types have string keys. This can be changed in future to use Equal is the 124 // need arises. 125 func (vt ValueTester) AllKeys(wantKeys ...interface{}) ValueTester { 126 vt.t.Helper() 127 keys, err := collectKeys(vt.v) 128 if err != nil { 129 vt.t.Errorf("IterateKeys(v, f) -> err %v, want nil", err) 130 } 131 if !reflect.DeepEqual(keys, wantKeys) { 132 vt.t.Errorf("IterateKeys(v, f) calls f with %v, want %v", keys, wantKeys) 133 } 134 return vt 135 } 136 137 func collectKeys(v interface{}) ([]interface{}, error) { 138 var keys []interface{} 139 err := IterateKeys(v, func(k interface{}) bool { 140 keys = append(keys, k) 141 return true 142 }) 143 return keys, err 144 } 145 146 // Index tests that Index'ing the value with the given key returns the wanted value 147 // and no error. 148 func (vt ValueTester) Index(key, wantVal interface{}) ValueTester { 149 vt.t.Helper() 150 got, err := Index(vt.v, key) 151 if err != nil { 152 vt.t.Errorf("Index(v, %v) -> err %v, want nil", key, err) 153 } 154 if !Equal(got, wantVal) { 155 vt.t.Errorf("Index(v, %v) -> %v, want %v", key, got, wantVal) 156 } 157 return vt 158 } 159 160 // IndexError tests that Index'ing the value with the given key returns the given 161 // error. 162 func (vt ValueTester) IndexError(key interface{}, wantErr error) ValueTester { 163 vt.t.Helper() 164 _, err := Index(vt.v, key) 165 if !reflect.DeepEqual(err, wantErr) { 166 vt.t.Errorf("Index(v, %v) -> err %v, want %v", key, err, wantErr) 167 } 168 return vt 169 } 170 171 // Assoc tests that Assoc'ing the value with the given key-value pair returns 172 // the wanted new value and no error. 173 func (vt ValueTester) Assoc(key, val, wantNew interface{}) ValueTester { 174 vt.t.Helper() 175 got, err := Assoc(vt.v, key, val) 176 if err != nil { 177 vt.t.Errorf("Assoc(v, %v) -> err %v, want nil", key, err) 178 } 179 if !Equal(got, wantNew) { 180 vt.t.Errorf("Assoc(v, %v) -> %v, want %v", key, got, wantNew) 181 } 182 return vt 183 } 184 185 // AssocError tests that Assoc'ing the value with the given key-value pair 186 // returns the given error. 187 func (vt ValueTester) AssocError(key, val interface{}, wantErr error) ValueTester { 188 vt.t.Helper() 189 _, err := Assoc(vt.v, key, val) 190 if !reflect.DeepEqual(err, wantErr) { 191 vt.t.Errorf("Assoc(v, %v) -> err %v, want %v", key, err, wantErr) 192 } 193 return vt 194 } 195 196 // Eq returns a tt.Matcher that matches using the Equal function. 197 func Eq(r interface{}) tt.Matcher { return equalMatcher{r} } 198 199 type equalMatcher struct{ want interface{} } 200 201 func (em equalMatcher) Match(got tt.RetValue) bool { return Equal(got, em.want) }