mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-12 17:27:50 +08:00
pkg/eval/vals: Add methods to ValueTester; use it to test StructMap.
This commit is contained in:
parent
d19b9c5ab7
commit
2d609bd5b4
|
@ -37,13 +37,6 @@ func TestAssoc(t *testing.T) {
|
|||
Args(MakeMap("k", "v"), "k2", "v2").Rets(
|
||||
Eq(MakeMap("k", "v", "k2", "v2")), nil),
|
||||
|
||||
Args(testStructMap{"foo", 1.0}, "name", "bar").
|
||||
Rets(testStructMap{"bar", 1.0}, nil),
|
||||
Args(testStructMap{"foo", 1.0}, "score-number", "2.0").
|
||||
Rets(testStructMap{"foo", 2.0}, nil),
|
||||
Args(testStructMap{"foo", 1.0}, "score-number", "bad number").
|
||||
Rets(nil, cannotParseAs{"number", `'bad number'`}),
|
||||
|
||||
Args(customAssocer{}, "x", "y").Rets("custom result", errCustomAssoc),
|
||||
|
||||
Args(struct{}{}, "x", "y").Rets(nil, errAssocUnsupported),
|
||||
|
|
|
@ -37,11 +37,6 @@ func TestEqual(t *testing.T) {
|
|||
Args(MakeMap("k", "v"), MakeMap("k2", "v")).Rets(false),
|
||||
Args(MakeMap("k", "v", "k2", "v2"), MakeMap("k", "v")).Rets(false),
|
||||
|
||||
Args(testStructMap{}, testStructMap{}).Rets(true),
|
||||
Args(testStructMap{"a", 1.0}, testStructMap{"a", 1.0}).Rets(true),
|
||||
Args(testStructMap{"a", 1.0}, testStructMap{"a", 2.0}).Rets(false),
|
||||
Args(testStructMap{"a", 1.0}, "a").Rets(false),
|
||||
|
||||
Args(customEqualer{true}, 2).Rets(true),
|
||||
Args(customEqualer{false}, 2).Rets(false),
|
||||
|
||||
|
|
|
@ -15,9 +15,6 @@ func TestHasKey(t *testing.T) {
|
|||
// Map
|
||||
Args(MakeMap("k", "v"), "k").Rets(true),
|
||||
Args(MakeMap("k", "v"), "bad").Rets(false),
|
||||
// StructMap
|
||||
Args(testStructMap{}, "name").Rets(true),
|
||||
Args(testStructMap{}, "bad").Rets(false),
|
||||
// HasKeyer
|
||||
Args(hasKeyer{"valid"}, "valid").Rets(true),
|
||||
Args(hasKeyer{"valid"}, "invalid").Rets(false),
|
||||
|
|
|
@ -25,8 +25,6 @@ func TestHash(t *testing.T) {
|
|||
Args(MakeList("foo", "bar")).Rets(hash.DJB(Hash("foo"), Hash("bar"))),
|
||||
Args(MakeMap("foo", "bar")).
|
||||
Rets(hash.DJB(Hash("foo"), Hash("bar"))),
|
||||
Args(testStructMap{"name", 1.0}).
|
||||
Rets(hash.DJB(Hash("name"), Hash(1.0))),
|
||||
Args(hasher{}).Rets(uint32(42)),
|
||||
Args(nonHasher{}).Rets(uint32(0)),
|
||||
})
|
||||
|
|
|
@ -80,9 +80,5 @@ func TestIndex(t *testing.T) {
|
|||
|
||||
Args(m, "foo").Rets("bar", nil),
|
||||
Args(m, "bad").Rets(Any, NoSuchKey("bad")),
|
||||
|
||||
// StructMap indicies
|
||||
Args(testStructMap{"foo", 1.0}, "name").Rets("foo", nil),
|
||||
Args(testStructMap{"foo", 1.0}, "bad").Rets(nil, NoSuchKey("bad")),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -7,16 +7,6 @@ import (
|
|||
"github.com/elves/elvish/pkg/util"
|
||||
)
|
||||
|
||||
// A variant of IterateKeys that is easier to test.
|
||||
func iterateKeys(v interface{}) ([]interface{}, error) {
|
||||
var keys []interface{}
|
||||
err := IterateKeys(v, func(k interface{}) bool {
|
||||
keys = append(keys, k)
|
||||
return true
|
||||
})
|
||||
return keys, err
|
||||
}
|
||||
|
||||
func vs(xs ...interface{}) []interface{} { return xs }
|
||||
|
||||
type keysIterator struct{ keys []interface{} }
|
||||
|
@ -28,9 +18,8 @@ func (k keysIterator) IterateKeys(f func(interface{}) bool) {
|
|||
type nonKeysIterator struct{}
|
||||
|
||||
func TestIterateKeys(t *testing.T) {
|
||||
Test(t, Fn("iterateKeys", iterateKeys), Table{
|
||||
Test(t, Fn("collectKeys", collectKeys), Table{
|
||||
Args(MakeMap("k1", "v1", "k2", "v2")).Rets(vs("k1", "k2"), nil),
|
||||
Args(testStructMap{}).Rets(vs("name", "score-number")),
|
||||
Args(keysIterator{vs("lorem", "ipsum")}).Rets(vs("lorem", "ipsum")),
|
||||
Args(nonKeysIterator{}).Rets(
|
||||
Any, cannotIterateKeysOf{"!!vals.nonKeysIterator"}),
|
||||
|
|
|
@ -17,7 +17,6 @@ func TestKind(t *testing.T) {
|
|||
Args(os.Stdin).Rets("file"),
|
||||
Args(EmptyList).Rets("list"),
|
||||
Args(EmptyMap).Rets("map"),
|
||||
Args(testStructMap{}).Rets("structmap"),
|
||||
|
||||
Args(xtype(0)).Rets("!!vals.xtype"),
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
func TestLen(t *testing.T) {
|
||||
Test(t, Fn("Len", Len), Table{
|
||||
Args("foobar").Rets(6),
|
||||
Args(testStructMap{}).Rets(2),
|
||||
Args(10).Rets(-1),
|
||||
})
|
||||
}
|
||||
|
|
|
@ -17,9 +17,9 @@ func TestPipe(t *testing.T) {
|
|||
defer w.Close()
|
||||
|
||||
TestValue(t, NewPipe(r, w)).
|
||||
HasKind("pipe").
|
||||
HasHash(hash.DJB(hash.UIntPtr(r.Fd()), hash.UIntPtr(w.Fd()))).
|
||||
HasRepr(fmt.Sprintf("<pipe{%v %v}>", r.Fd(), w.Fd())).
|
||||
IsEqualTo(NewPipe(r, w)).
|
||||
IsNotEqualTo(123, "a string", NewPipe(w, r))
|
||||
Kind("pipe").
|
||||
Hash(hash.DJB(hash.UIntPtr(r.Fd()), hash.UIntPtr(w.Fd()))).
|
||||
Repr(fmt.Sprintf("<pipe{%v %v}>", r.Fd(), w.Fd())).
|
||||
Equal(NewPipe(r, w)).
|
||||
NotEqual(123, "a string", NewPipe(w, r))
|
||||
}
|
||||
|
|
|
@ -29,8 +29,6 @@ func TestRepr(t *testing.T) {
|
|||
Args(MakeList("foo", "bar")).Rets("[foo bar]"),
|
||||
Args(EmptyMap).Rets("[&]"),
|
||||
Args(MakeMap("foo", "bar")).Rets("[&foo=bar]"),
|
||||
Args(testStructMap{"name", 1.0}).Rets(
|
||||
"[&name=name &score-number=(float64 1)]"),
|
||||
Args(reprer{}).Rets("<reprer>"),
|
||||
Args(nonReprer{}).Rets("<unknown {}>"),
|
||||
})
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
package vals
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/xiaq/persistent/hash"
|
||||
)
|
||||
|
||||
// A test structmap type used in other tests.
|
||||
type testStructMap struct {
|
||||
Name string `json:"name"`
|
||||
|
@ -7,3 +13,33 @@ type testStructMap struct {
|
|||
}
|
||||
|
||||
func (testStructMap) IsStructMap(StructMapMarker) {}
|
||||
|
||||
func TestStructMap(t *testing.T) {
|
||||
TestValue(t, testStructMap{}).
|
||||
Kind("structmap").
|
||||
Hash(hash.DJB(Hash(""), Hash(0.0))).
|
||||
Repr(`[&name='' &score-number=(float64 0)]`).
|
||||
Len(2).
|
||||
Equal(testStructMap{}).
|
||||
NotEqual("a", MakeMap(), testStructMap{"a", 1.0}).
|
||||
HasKey("name", "score-number").
|
||||
HasNoKey("bad").
|
||||
AllKeys("name", "score-number").
|
||||
Index("name", "").
|
||||
Index("score-number", 0.0)
|
||||
|
||||
TestValue(t, testStructMap{"a", 1.0}).
|
||||
Kind("structmap").
|
||||
Hash(hash.DJB(Hash("a"), Hash(1.0))).
|
||||
Repr(`[&name=a &score-number=(float64 1)]`).
|
||||
Len(2).
|
||||
Equal(testStructMap{"a", 1.0}).
|
||||
NotEqual(
|
||||
"a", MakeMap("name", "", "score-number", 1.0),
|
||||
testStructMap{}, testStructMap{"a", 2.0}, testStructMap{"b", 1.0}).
|
||||
Index("name", "a").
|
||||
Index("score-number", 1.0).
|
||||
Assoc("name", "b", testStructMap{"b", 1.0}).
|
||||
Assoc("score-number", 2.0, testStructMap{"a", 2.0}).
|
||||
AssocError("score-number", "not-num", cannotParseAs{"number", "not-num"})
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package vals
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/elves/elvish/pkg/tt"
|
||||
|
@ -17,8 +18,8 @@ func TestValue(t *testing.T, v interface{}) ValueTester {
|
|||
return ValueTester{t, v}
|
||||
}
|
||||
|
||||
// HasKind tests the Kind of the value.
|
||||
func (vt ValueTester) HasKind(wantKind string) ValueTester {
|
||||
// Kind tests the Kind of the value.
|
||||
func (vt ValueTester) Kind(wantKind string) ValueTester {
|
||||
vt.t.Helper()
|
||||
kind := Kind(vt.v)
|
||||
if kind != wantKind {
|
||||
|
@ -27,8 +28,8 @@ func (vt ValueTester) HasKind(wantKind string) ValueTester {
|
|||
return vt
|
||||
}
|
||||
|
||||
// HasHash tests the Hash of the value.
|
||||
func (vt ValueTester) HasHash(wantHash uint32) ValueTester {
|
||||
// Hash tests the Hash of the value.
|
||||
func (vt ValueTester) Hash(wantHash uint32) ValueTester {
|
||||
vt.t.Helper()
|
||||
kind := Hash(vt.v)
|
||||
if kind != wantHash {
|
||||
|
@ -37,18 +38,28 @@ func (vt ValueTester) HasHash(wantHash uint32) ValueTester {
|
|||
return vt
|
||||
}
|
||||
|
||||
// HasRepr tests the Repr of the value.
|
||||
func (vt ValueTester) HasRepr(wantRepr string) ValueTester {
|
||||
// Len tests the Len of the value.
|
||||
func (vt ValueTester) Len(wantLen int) ValueTester {
|
||||
vt.t.Helper()
|
||||
kind := Repr(vt.v, -1)
|
||||
kind := Len(vt.v)
|
||||
if kind != wantLen {
|
||||
vt.t.Errorf("Len(v) = %v, want %v", kind, wantLen)
|
||||
}
|
||||
return vt
|
||||
}
|
||||
|
||||
// Repr tests the Repr of the value.
|
||||
func (vt ValueTester) Repr(wantRepr string) ValueTester {
|
||||
vt.t.Helper()
|
||||
kind := Repr(vt.v, NoPretty)
|
||||
if kind != wantRepr {
|
||||
vt.t.Errorf("Repr(v) = %s, want %s", kind, wantRepr)
|
||||
}
|
||||
return vt
|
||||
}
|
||||
|
||||
// IsEqualTo tests that the value is Equal to another.
|
||||
func (vt ValueTester) IsEqualTo(others ...interface{}) ValueTester {
|
||||
// Equal tests that the value is Equal to every of the given values.
|
||||
func (vt ValueTester) Equal(others ...interface{}) ValueTester {
|
||||
vt.t.Helper()
|
||||
for _, other := range others {
|
||||
eq := Equal(vt.v, other)
|
||||
|
@ -59,8 +70,8 @@ func (vt ValueTester) IsEqualTo(others ...interface{}) ValueTester {
|
|||
return vt
|
||||
}
|
||||
|
||||
// IsNotEqualTo tests that the value is not Equal to another.
|
||||
func (vt ValueTester) IsNotEqualTo(others ...interface{}) ValueTester {
|
||||
// NotEqual tests that the value is not Equal to any of the given values.
|
||||
func (vt ValueTester) NotEqual(others ...interface{}) ValueTester {
|
||||
vt.t.Helper()
|
||||
for _, other := range others {
|
||||
eq := Equal(vt.v, other)
|
||||
|
@ -71,6 +82,107 @@ func (vt ValueTester) IsNotEqualTo(others ...interface{}) ValueTester {
|
|||
return vt
|
||||
}
|
||||
|
||||
// HasKey tests that the value has each of the given keys.
|
||||
func (vt ValueTester) HasKey(keys ...interface{}) ValueTester {
|
||||
vt.t.Helper()
|
||||
for _, key := range keys {
|
||||
has := HasKey(vt.v, key)
|
||||
if !has {
|
||||
vt.t.Errorf("HasKey(v, %v) = false, want true", key)
|
||||
}
|
||||
}
|
||||
return vt
|
||||
}
|
||||
|
||||
// HasNoKey tests that the value does not have any of the given keys.
|
||||
func (vt ValueTester) HasNoKey(keys ...interface{}) ValueTester {
|
||||
vt.t.Helper()
|
||||
for _, key := range keys {
|
||||
has := HasKey(vt.v, key)
|
||||
if has {
|
||||
vt.t.Errorf("HasKey(v, %v) = true, want false", key)
|
||||
}
|
||||
}
|
||||
return vt
|
||||
}
|
||||
|
||||
// AllKeys tests that the given keys match what the result of IterateKeys on the
|
||||
// value.
|
||||
//
|
||||
// NOTE: This now checks equality using reflect.DeepEqual, since all the builtin
|
||||
// types have string keys. This can be changed in future to use Equal is the
|
||||
// need arises.
|
||||
func (vt ValueTester) AllKeys(wantKeys ...interface{}) ValueTester {
|
||||
vt.t.Helper()
|
||||
keys, err := collectKeys(vt.v)
|
||||
if err != nil {
|
||||
vt.t.Errorf("IterateKeys(v, f) -> err %v, want nil", err)
|
||||
}
|
||||
if !reflect.DeepEqual(keys, wantKeys) {
|
||||
vt.t.Errorf("IterateKeys(v, f) calls f with %v, want %v", keys, wantKeys)
|
||||
}
|
||||
return vt
|
||||
}
|
||||
|
||||
func collectKeys(v interface{}) ([]interface{}, error) {
|
||||
var keys []interface{}
|
||||
err := IterateKeys(v, func(k interface{}) bool {
|
||||
keys = append(keys, k)
|
||||
return true
|
||||
})
|
||||
return keys, err
|
||||
}
|
||||
|
||||
// Index tests that Index'ing the value with the given key returns the wanted value
|
||||
// and no error.
|
||||
func (vt ValueTester) Index(key, wantVal interface{}) ValueTester {
|
||||
vt.t.Helper()
|
||||
got, err := Index(vt.v, key)
|
||||
if err != nil {
|
||||
vt.t.Errorf("Index(v, %v) -> err %v, want nil", key, err)
|
||||
}
|
||||
if !Equal(got, wantVal) {
|
||||
vt.t.Errorf("Index(v, %v) -> %v, want %v", key, got, wantVal)
|
||||
}
|
||||
return vt
|
||||
}
|
||||
|
||||
// IndexError tests that Index'ing the value with the given key returns the given
|
||||
// error.
|
||||
func (vt ValueTester) IndexError(key interface{}, wantErr error) ValueTester {
|
||||
vt.t.Helper()
|
||||
_, err := Index(vt.v, key)
|
||||
if !reflect.DeepEqual(err, wantErr) {
|
||||
vt.t.Errorf("Index(v, %v) -> err %v, want %v", key, err, wantErr)
|
||||
}
|
||||
return vt
|
||||
}
|
||||
|
||||
// Assoc tests that Assoc'ing the value with the given key-value pair returns
|
||||
// the wanted new value and no error.
|
||||
func (vt ValueTester) Assoc(key, val, wantNew interface{}) ValueTester {
|
||||
vt.t.Helper()
|
||||
got, err := Assoc(vt.v, key, val)
|
||||
if err != nil {
|
||||
vt.t.Errorf("Assoc(v, %v) -> err %v, want nil", key, err)
|
||||
}
|
||||
if !Equal(got, wantNew) {
|
||||
vt.t.Errorf("Assoc(v, %v) -> %v, want %v", key, got, wantNew)
|
||||
}
|
||||
return vt
|
||||
}
|
||||
|
||||
// AssocError tests that Assoc'ing the value with the given key-value pair
|
||||
// returns the given error.
|
||||
func (vt ValueTester) AssocError(key, val interface{}, wantErr error) ValueTester {
|
||||
vt.t.Helper()
|
||||
_, err := Assoc(vt.v, key, val)
|
||||
if !reflect.DeepEqual(err, wantErr) {
|
||||
vt.t.Errorf("Assoc(v, %v) -> err %v, want %v", key, err, wantErr)
|
||||
}
|
||||
return vt
|
||||
}
|
||||
|
||||
// Eq returns a tt.Matcher that matches using the Equal function.
|
||||
func Eq(r interface{}) tt.Matcher { return equalMatcher{r} }
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user