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) }