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  }