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 }