github.com/safing/portbase@v0.19.5/database/accessor/accessor_test.go (about)

     1  //nolint:maligned,unparam
     2  package accessor
     3  
     4  import (
     5  	"encoding/json"
     6  	"testing"
     7  
     8  	"github.com/safing/portbase/utils"
     9  )
    10  
    11  type TestStruct struct {
    12  	S    string
    13  	A    []string
    14  	I    int
    15  	I8   int8
    16  	I16  int16
    17  	I32  int32
    18  	I64  int64
    19  	UI   uint
    20  	UI8  uint8
    21  	UI16 uint16
    22  	UI32 uint32
    23  	UI64 uint64
    24  	F32  float32
    25  	F64  float64
    26  	B    bool
    27  }
    28  
    29  var (
    30  	testStruct = &TestStruct{
    31  		S:    "banana",
    32  		A:    []string{"black", "white"},
    33  		I:    42,
    34  		I8:   42,
    35  		I16:  42,
    36  		I32:  42,
    37  		I64:  42,
    38  		UI:   42,
    39  		UI8:  42,
    40  		UI16: 42,
    41  		UI32: 42,
    42  		UI64: 42,
    43  		F32:  42.42,
    44  		F64:  42.42,
    45  		B:    true,
    46  	}
    47  	testJSONBytes, _ = json.Marshal(testStruct) //nolint:errchkjson
    48  	testJSON         = string(testJSONBytes)
    49  )
    50  
    51  func testGetString(t *testing.T, acc Accessor, key string, shouldSucceed bool, expectedValue string) {
    52  	t.Helper()
    53  
    54  	v, ok := acc.GetString(key)
    55  	switch {
    56  	case !ok && shouldSucceed:
    57  		t.Errorf("%s failed to get string with key %s", acc.Type(), key)
    58  	case ok && !shouldSucceed:
    59  		t.Errorf("%s should have failed to get string with key %s, it returned %v", acc.Type(), key, v)
    60  	}
    61  	if v != expectedValue {
    62  		t.Errorf("%s returned an unexpected value: wanted %v, got %v", acc.Type(), expectedValue, v)
    63  	}
    64  }
    65  
    66  func testGetStringArray(t *testing.T, acc Accessor, key string, shouldSucceed bool, expectedValue []string) {
    67  	t.Helper()
    68  
    69  	v, ok := acc.GetStringArray(key)
    70  	switch {
    71  	case !ok && shouldSucceed:
    72  		t.Errorf("%s failed to get []string with key %s", acc.Type(), key)
    73  	case ok && !shouldSucceed:
    74  		t.Errorf("%s should have failed to get []string with key %s, it returned %v", acc.Type(), key, v)
    75  	}
    76  	if !utils.StringSliceEqual(v, expectedValue) {
    77  		t.Errorf("%s returned an unexpected value: wanted %v, got %v", acc.Type(), expectedValue, v)
    78  	}
    79  }
    80  
    81  func testGetInt(t *testing.T, acc Accessor, key string, shouldSucceed bool, expectedValue int64) {
    82  	t.Helper()
    83  
    84  	v, ok := acc.GetInt(key)
    85  	switch {
    86  	case !ok && shouldSucceed:
    87  		t.Errorf("%s failed to get int with key %s", acc.Type(), key)
    88  	case ok && !shouldSucceed:
    89  		t.Errorf("%s should have failed to get int with key %s, it returned %v", acc.Type(), key, v)
    90  	}
    91  	if v != expectedValue {
    92  		t.Errorf("%s returned an unexpected value: wanted %v, got %v", acc.Type(), expectedValue, v)
    93  	}
    94  }
    95  
    96  func testGetFloat(t *testing.T, acc Accessor, key string, shouldSucceed bool, expectedValue float64) {
    97  	t.Helper()
    98  
    99  	v, ok := acc.GetFloat(key)
   100  	switch {
   101  	case !ok && shouldSucceed:
   102  		t.Errorf("%s failed to get float with key %s", acc.Type(), key)
   103  	case ok && !shouldSucceed:
   104  		t.Errorf("%s should have failed to get float with key %s, it returned %v", acc.Type(), key, v)
   105  	}
   106  	if int64(v) != int64(expectedValue) {
   107  		t.Errorf("%s returned an unexpected value: wanted %v, got %v", acc.Type(), expectedValue, v)
   108  	}
   109  }
   110  
   111  func testGetBool(t *testing.T, acc Accessor, key string, shouldSucceed bool, expectedValue bool) {
   112  	t.Helper()
   113  
   114  	v, ok := acc.GetBool(key)
   115  	switch {
   116  	case !ok && shouldSucceed:
   117  		t.Errorf("%s failed to get bool with key %s", acc.Type(), key)
   118  	case ok && !shouldSucceed:
   119  		t.Errorf("%s should have failed to get bool with key %s, it returned %v", acc.Type(), key, v)
   120  	}
   121  	if v != expectedValue {
   122  		t.Errorf("%s returned an unexpected value: wanted %v, got %v", acc.Type(), expectedValue, v)
   123  	}
   124  }
   125  
   126  func testExists(t *testing.T, acc Accessor, key string, shouldSucceed bool) {
   127  	t.Helper()
   128  
   129  	ok := acc.Exists(key)
   130  	switch {
   131  	case !ok && shouldSucceed:
   132  		t.Errorf("%s should report key %s as existing", acc.Type(), key)
   133  	case ok && !shouldSucceed:
   134  		t.Errorf("%s should report key %s as non-existing", acc.Type(), key)
   135  	}
   136  }
   137  
   138  func testSet(t *testing.T, acc Accessor, key string, shouldSucceed bool, valueToSet interface{}) {
   139  	t.Helper()
   140  
   141  	err := acc.Set(key, valueToSet)
   142  	switch {
   143  	case err != nil && shouldSucceed:
   144  		t.Errorf("%s failed to set %s to %+v: %s", acc.Type(), key, valueToSet, err)
   145  	case err == nil && !shouldSucceed:
   146  		t.Errorf("%s should have failed to set %s to %+v", acc.Type(), key, valueToSet)
   147  	}
   148  }
   149  
   150  func TestAccessor(t *testing.T) {
   151  	t.Parallel()
   152  
   153  	// Test interface compliance.
   154  	accs := []Accessor{
   155  		NewJSONAccessor(&testJSON),
   156  		NewJSONBytesAccessor(&testJSONBytes),
   157  		NewStructAccessor(testStruct),
   158  	}
   159  
   160  	// get
   161  	for _, acc := range accs {
   162  		testGetString(t, acc, "S", true, "banana")
   163  		testGetStringArray(t, acc, "A", true, []string{"black", "white"})
   164  		testGetInt(t, acc, "I", true, 42)
   165  		testGetInt(t, acc, "I8", true, 42)
   166  		testGetInt(t, acc, "I16", true, 42)
   167  		testGetInt(t, acc, "I32", true, 42)
   168  		testGetInt(t, acc, "I64", true, 42)
   169  		testGetInt(t, acc, "UI", true, 42)
   170  		testGetInt(t, acc, "UI8", true, 42)
   171  		testGetInt(t, acc, "UI16", true, 42)
   172  		testGetInt(t, acc, "UI32", true, 42)
   173  		testGetInt(t, acc, "UI64", true, 42)
   174  		testGetFloat(t, acc, "F32", true, 42.42)
   175  		testGetFloat(t, acc, "F64", true, 42.42)
   176  		testGetBool(t, acc, "B", true, true)
   177  	}
   178  
   179  	// set
   180  	for _, acc := range accs {
   181  		testSet(t, acc, "S", true, "coconut")
   182  		testSet(t, acc, "A", true, []string{"green", "blue"})
   183  		testSet(t, acc, "I", true, uint32(44))
   184  		testSet(t, acc, "I8", true, uint64(44))
   185  		testSet(t, acc, "I16", true, uint8(44))
   186  		testSet(t, acc, "I32", true, uint16(44))
   187  		testSet(t, acc, "I64", true, 44)
   188  		testSet(t, acc, "UI", true, 44)
   189  		testSet(t, acc, "UI8", true, int64(44))
   190  		testSet(t, acc, "UI16", true, int32(44))
   191  		testSet(t, acc, "UI32", true, int8(44))
   192  		testSet(t, acc, "UI64", true, int16(44))
   193  		testSet(t, acc, "F32", true, 44.44)
   194  		testSet(t, acc, "F64", true, 44.44)
   195  		testSet(t, acc, "B", true, false)
   196  	}
   197  
   198  	// get again to check if new values were set
   199  	for _, acc := range accs {
   200  		testGetString(t, acc, "S", true, "coconut")
   201  		testGetStringArray(t, acc, "A", true, []string{"green", "blue"})
   202  		testGetInt(t, acc, "I", true, 44)
   203  		testGetInt(t, acc, "I8", true, 44)
   204  		testGetInt(t, acc, "I16", true, 44)
   205  		testGetInt(t, acc, "I32", true, 44)
   206  		testGetInt(t, acc, "I64", true, 44)
   207  		testGetInt(t, acc, "UI", true, 44)
   208  		testGetInt(t, acc, "UI8", true, 44)
   209  		testGetInt(t, acc, "UI16", true, 44)
   210  		testGetInt(t, acc, "UI32", true, 44)
   211  		testGetInt(t, acc, "UI64", true, 44)
   212  		testGetFloat(t, acc, "F32", true, 44.44)
   213  		testGetFloat(t, acc, "F64", true, 44.44)
   214  		testGetBool(t, acc, "B", true, false)
   215  	}
   216  
   217  	// failures
   218  	for _, acc := range accs {
   219  		testSet(t, acc, "S", false, true)
   220  		testSet(t, acc, "S", false, false)
   221  		testSet(t, acc, "S", false, 1)
   222  		testSet(t, acc, "S", false, 1.1)
   223  
   224  		testSet(t, acc, "A", false, "1")
   225  		testSet(t, acc, "A", false, true)
   226  		testSet(t, acc, "A", false, false)
   227  		testSet(t, acc, "A", false, 1)
   228  		testSet(t, acc, "A", false, 1.1)
   229  
   230  		testSet(t, acc, "I", false, "1")
   231  		testSet(t, acc, "I8", false, "1")
   232  		testSet(t, acc, "I16", false, "1")
   233  		testSet(t, acc, "I32", false, "1")
   234  		testSet(t, acc, "I64", false, "1")
   235  		testSet(t, acc, "UI", false, "1")
   236  		testSet(t, acc, "UI8", false, "1")
   237  		testSet(t, acc, "UI16", false, "1")
   238  		testSet(t, acc, "UI32", false, "1")
   239  		testSet(t, acc, "UI64", false, "1")
   240  
   241  		testSet(t, acc, "F32", false, "1.1")
   242  		testSet(t, acc, "F64", false, "1.1")
   243  
   244  		testSet(t, acc, "B", false, "false")
   245  		testSet(t, acc, "B", false, 1)
   246  		testSet(t, acc, "B", false, 1.1)
   247  	}
   248  
   249  	// get again to check if values werent changed when an error occurred
   250  	for _, acc := range accs {
   251  		testGetString(t, acc, "S", true, "coconut")
   252  		testGetStringArray(t, acc, "A", true, []string{"green", "blue"})
   253  		testGetInt(t, acc, "I", true, 44)
   254  		testGetInt(t, acc, "I8", true, 44)
   255  		testGetInt(t, acc, "I16", true, 44)
   256  		testGetInt(t, acc, "I32", true, 44)
   257  		testGetInt(t, acc, "I64", true, 44)
   258  		testGetInt(t, acc, "UI", true, 44)
   259  		testGetInt(t, acc, "UI8", true, 44)
   260  		testGetInt(t, acc, "UI16", true, 44)
   261  		testGetInt(t, acc, "UI32", true, 44)
   262  		testGetInt(t, acc, "UI64", true, 44)
   263  		testGetFloat(t, acc, "F32", true, 44.44)
   264  		testGetFloat(t, acc, "F64", true, 44.44)
   265  		testGetBool(t, acc, "B", true, false)
   266  	}
   267  
   268  	// test existence
   269  	for _, acc := range accs {
   270  		testExists(t, acc, "S", true)
   271  		testExists(t, acc, "A", true)
   272  		testExists(t, acc, "I", true)
   273  		testExists(t, acc, "I8", true)
   274  		testExists(t, acc, "I16", true)
   275  		testExists(t, acc, "I32", true)
   276  		testExists(t, acc, "I64", true)
   277  		testExists(t, acc, "UI", true)
   278  		testExists(t, acc, "UI8", true)
   279  		testExists(t, acc, "UI16", true)
   280  		testExists(t, acc, "UI32", true)
   281  		testExists(t, acc, "UI64", true)
   282  		testExists(t, acc, "F32", true)
   283  		testExists(t, acc, "F64", true)
   284  		testExists(t, acc, "B", true)
   285  	}
   286  
   287  	// test non-existence
   288  	for _, acc := range accs {
   289  		testExists(t, acc, "X", false)
   290  	}
   291  }