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