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