github.com/weaviate/weaviate@v1.24.6/test/acceptance/graphql_resolvers/aggregate_response_assert.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package test 13 14 import ( 15 "encoding/json" 16 "fmt" 17 "testing" 18 19 "github.com/stretchr/testify/assert" 20 "github.com/weaviate/weaviate/entities/schema" 21 ) 22 23 const delta = 0.00001 24 25 type assertFunc func(response map[string]interface{}) bool 26 27 type aggregateResponseAssert struct { 28 t *testing.T 29 assert *assert.Assertions 30 } 31 32 func newAggregateResponseAssert(t *testing.T) *aggregateResponseAssert { 33 return &aggregateResponseAssert{t, assert.New(t)} 34 } 35 36 func (a *aggregateResponseAssert) meta(count int64) assertFunc { 37 return func(response map[string]interface{}) bool { 38 metaKey := "meta" 39 if !a.assert.Contains(response, metaKey) { 40 return false 41 } 42 return a.hasInt(response[metaKey].(map[string]interface{}), metaKey, "count", count) 43 } 44 } 45 46 func (a *aggregateResponseAssert) groupedBy(value string, path ...interface{}) assertFunc { 47 return func(response map[string]interface{}) bool { 48 groupedByKey := "groupedBy" 49 if !a.assert.Contains(response, groupedByKey) { 50 return false 51 } 52 aggMap := response[groupedByKey].(map[string]interface{}) 53 return combinedAssert( 54 a.hasString(aggMap, groupedByKey, "value", value), 55 a.hasArray(aggMap, groupedByKey, "path", path), 56 ) 57 } 58 } 59 60 func (a *aggregateResponseAssert) pointingTo(propName string, path ...interface{}) assertFunc { 61 return func(response map[string]interface{}) bool { 62 if !a.assert.Contains(response, propName) { 63 return false 64 } 65 aggMap := response[propName].(map[string]interface{}) 66 return a.hasArray(aggMap, propName, "pointingTo", path) 67 } 68 } 69 70 func (a *aggregateResponseAssert) typedBoolean(dataType schema.DataType, propName string, 71 count, totalFalse, totalTrue int64, 72 percentageFalse, percentageTrue float64, 73 ) assertFunc { 74 return func(response map[string]interface{}) bool { 75 if !a.assert.Contains(response, propName) { 76 return false 77 } 78 aggMap := response[propName].(map[string]interface{}) 79 return combinedAssert( 80 a.hasInt(aggMap, propName, "count", count), 81 a.hasInt(aggMap, propName, "totalFalse", totalFalse), 82 a.hasInt(aggMap, propName, "totalTrue", totalTrue), 83 a.hasNumber(aggMap, propName, "percentageFalse", percentageFalse), 84 a.hasNumber(aggMap, propName, "percentageTrue", percentageTrue), 85 a.hasString(aggMap, propName, "type", string(dataType)), 86 ) 87 } 88 } 89 90 func (a *aggregateResponseAssert) booleanArray(propName string, 91 count, totalFalse, totalTrue int64, 92 percentageFalse, percentageTrue float64, 93 ) assertFunc { 94 return a.typedBoolean(schema.DataTypeBooleanArray, propName, count, totalFalse, totalTrue, 95 percentageFalse, percentageTrue) 96 } 97 98 func (a *aggregateResponseAssert) boolean(propName string, 99 count, totalFalse, totalTrue int64, 100 percentageFalse, percentageTrue float64, 101 ) assertFunc { 102 return a.typedBoolean(schema.DataTypeBoolean, propName, count, totalFalse, totalTrue, 103 percentageFalse, percentageTrue) 104 } 105 106 func (a *aggregateResponseAssert) typedBoolean0(dataType schema.DataType, propName string) assertFunc { 107 return func(response map[string]interface{}) bool { 108 if !a.assert.Contains(response, propName) { 109 return false 110 } 111 aggMap := response[propName].(map[string]interface{}) 112 return combinedAssert( 113 a.hasInt(aggMap, propName, "count", 0), 114 a.hasInt(aggMap, propName, "totalFalse", 0), 115 a.hasInt(aggMap, propName, "totalTrue", 0), 116 a.hasNil(aggMap, propName, "percentageFalse"), 117 a.hasNil(aggMap, propName, "percentageTrue"), 118 a.hasString(aggMap, propName, "type", string(dataType)), 119 ) 120 } 121 } 122 123 func (a *aggregateResponseAssert) booleanArray0(propName string) assertFunc { 124 return a.typedBoolean0(schema.DataTypeBooleanArray, propName) 125 } 126 127 func (a *aggregateResponseAssert) boolean0(propName string) assertFunc { 128 return a.typedBoolean0(schema.DataTypeBoolean, propName) 129 } 130 131 func (a *aggregateResponseAssert) typedInts(dataType schema.DataType, propName string, 132 count, maximum, minimum, mode, sum int64, 133 median, mean float64, 134 ) assertFunc { 135 return func(response map[string]interface{}) bool { 136 if !a.assert.Contains(response, propName) { 137 return false 138 } 139 aggMap := response[propName].(map[string]interface{}) 140 return combinedAssert( 141 a.hasInt(aggMap, propName, "count", count), 142 a.hasInt(aggMap, propName, "maximum", maximum), 143 a.hasInt(aggMap, propName, "minimum", minimum), 144 a.hasInt(aggMap, propName, "mode", mode), 145 a.hasInt(aggMap, propName, "sum", sum), 146 a.hasNumber(aggMap, propName, "median", median), 147 a.hasNumber(aggMap, propName, "mean", mean), 148 a.hasString(aggMap, propName, "type", string(dataType)), 149 ) 150 } 151 } 152 153 func (a *aggregateResponseAssert) intArray(propName string, 154 count, maximum, minimum, mode, sum int64, 155 median, mean float64, 156 ) assertFunc { 157 return a.typedInts(schema.DataTypeIntArray, propName, count, maximum, minimum, 158 mode, sum, median, mean) 159 } 160 161 func (a *aggregateResponseAssert) int(propName string, 162 count, maximum, minimum, mode, sum int64, 163 median, mean float64, 164 ) assertFunc { 165 return a.typedInts(schema.DataTypeInt, propName, count, maximum, minimum, 166 mode, sum, median, mean) 167 } 168 169 func (a *aggregateResponseAssert) typedInts0(dataType schema.DataType, propName string) assertFunc { 170 return func(response map[string]interface{}) bool { 171 if !a.assert.Contains(response, propName) { 172 return false 173 } 174 aggMap := response[propName].(map[string]interface{}) 175 return combinedAssert( 176 a.hasInt(aggMap, propName, "count", 0), 177 a.hasNil(aggMap, propName, "maximum"), 178 a.hasNil(aggMap, propName, "minimum"), 179 a.hasNil(aggMap, propName, "mode"), 180 a.hasNil(aggMap, propName, "sum"), 181 a.hasNil(aggMap, propName, "median"), 182 a.hasNil(aggMap, propName, "mean"), 183 a.hasString(aggMap, propName, "type", string(dataType)), 184 ) 185 } 186 } 187 188 func (a *aggregateResponseAssert) intArray0(propName string) assertFunc { 189 return a.typedInts0(schema.DataTypeIntArray, propName) 190 } 191 192 func (a *aggregateResponseAssert) int0(propName string) assertFunc { 193 return a.typedInts0(schema.DataTypeInt, propName) 194 } 195 196 func (a *aggregateResponseAssert) typedNumbers(dataType schema.DataType, propName string, 197 count int64, 198 maximum, minimum, mode, sum, median, mean float64, 199 ) assertFunc { 200 return func(response map[string]interface{}) bool { 201 if !a.assert.Contains(response, propName) { 202 return false 203 } 204 aggMap := response[propName].(map[string]interface{}) 205 return combinedAssert( 206 a.hasInt(aggMap, propName, "count", count), 207 a.hasNumber(aggMap, propName, "maximum", maximum), 208 a.hasNumber(aggMap, propName, "minimum", minimum), 209 a.hasNumber(aggMap, propName, "mode", mode), 210 a.hasNumber(aggMap, propName, "sum", sum), 211 a.hasNumber(aggMap, propName, "median", median), 212 a.hasNumber(aggMap, propName, "mean", mean), 213 a.hasString(aggMap, propName, "type", string(dataType)), 214 ) 215 } 216 } 217 218 func (a *aggregateResponseAssert) numberArray(propName string, 219 count int64, 220 maximum, minimum, mode, sum, median, mean float64, 221 ) assertFunc { 222 return a.typedNumbers(schema.DataTypeNumberArray, propName, count, maximum, minimum, 223 mode, sum, median, mean) 224 } 225 226 func (a *aggregateResponseAssert) number(propName string, 227 count int64, 228 maximum, minimum, mode, sum, median, mean float64, 229 ) assertFunc { 230 return a.typedNumbers(schema.DataTypeNumber, propName, count, maximum, minimum, 231 mode, sum, median, mean) 232 } 233 234 func (a *aggregateResponseAssert) typedNumbers0(dataType schema.DataType, propName string) assertFunc { 235 return func(response map[string]interface{}) bool { 236 if !a.assert.Contains(response, propName) { 237 return false 238 } 239 aggMap := response[propName].(map[string]interface{}) 240 return combinedAssert( 241 a.hasInt(aggMap, propName, "count", 0), 242 a.hasNil(aggMap, propName, "maximum"), 243 a.hasNil(aggMap, propName, "minimum"), 244 a.hasNil(aggMap, propName, "mode"), 245 a.hasNil(aggMap, propName, "sum"), 246 a.hasNil(aggMap, propName, "median"), 247 a.hasNil(aggMap, propName, "mean"), 248 a.hasString(aggMap, propName, "type", string(dataType)), 249 ) 250 } 251 } 252 253 func (a *aggregateResponseAssert) numberArray0(propName string) assertFunc { 254 return a.typedNumbers0(schema.DataTypeNumberArray, propName) 255 } 256 257 func (a *aggregateResponseAssert) number0(propName string) assertFunc { 258 return a.typedNumbers0(schema.DataTypeNumber, propName) 259 } 260 261 func (a *aggregateResponseAssert) dateArray(propName string, count int64) assertFunc { 262 return a.date(propName, count) 263 } 264 265 func (a *aggregateResponseAssert) date(propName string, count int64) assertFunc { 266 return func(response map[string]interface{}) bool { 267 if !a.assert.Contains(response, propName) { 268 return false 269 } 270 return a.hasInt(response[propName].(map[string]interface{}), propName, "count", count) 271 } 272 } 273 274 func (a *aggregateResponseAssert) dateArray0(propName string) assertFunc { 275 return a.date(propName, 0) 276 } 277 278 func (a *aggregateResponseAssert) date0(propName string) assertFunc { 279 return a.date(propName, 0) 280 } 281 282 func (a *aggregateResponseAssert) typedStrings(dataType schema.DataType, propName string, 283 count int64, 284 values []string, occurrences []int64, 285 ) assertFunc { 286 return func(response map[string]interface{}) bool { 287 if !a.assert.Contains(response, propName) { 288 return false 289 } 290 aggMap := response[propName].(map[string]interface{}) 291 return combinedAssert( 292 a.hasInt(aggMap, propName, "count", count), 293 a.hasString(aggMap, propName, "type", string(dataType)), 294 a.hasOccurrences(aggMap, propName, values, occurrences), 295 ) 296 } 297 } 298 299 func (a *aggregateResponseAssert) typedStrings0(dataType schema.DataType, propName string) assertFunc { 300 return func(response map[string]interface{}) bool { 301 if !a.assert.Contains(response, propName) { 302 return false 303 } 304 aggMap := response[propName].(map[string]interface{}) 305 return combinedAssert( 306 a.hasInt(aggMap, propName, "count", 0), 307 a.hasString(aggMap, propName, "type", string(dataType)), 308 a.hasOccurrences(aggMap, propName, nil, nil), 309 ) 310 } 311 } 312 313 func (a *aggregateResponseAssert) textArray(propName string, 314 count int64, 315 values []string, occurrences []int64, 316 ) assertFunc { 317 return a.typedStrings(schema.DataTypeTextArray, propName, count, values, occurrences) 318 } 319 320 func (a *aggregateResponseAssert) text(propName string, 321 count int64, 322 values []string, occurrences []int64, 323 ) assertFunc { 324 return a.typedStrings(schema.DataTypeText, propName, count, values, occurrences) 325 } 326 327 func (a *aggregateResponseAssert) textArray0(propName string) assertFunc { 328 return a.typedStrings0(schema.DataTypeTextArray, propName) 329 } 330 331 func (a *aggregateResponseAssert) text0(propName string) assertFunc { 332 return a.typedStrings0(schema.DataTypeText, propName) 333 } 334 335 func (a *aggregateResponseAssert) hasOccurrences(parentMap map[string]interface{}, 336 parentKey string, values []string, occurrences []int64, 337 ) bool { 338 key := "topOccurrences" 339 to, exists := parentMap[key] 340 if !exists { 341 return a.assert.Fail(fmt.Sprintf("'%s' does not have '%s'\n%#v", parentKey, key, parentMap)) 342 } 343 344 toArr := to.([]interface{}) 345 assertResults := make([]bool, len(values)) 346 for i := range values { 347 key := fmt.Sprintf("%s.%s[%d]", parentKey, key, i) 348 toSingle := toArr[i].(map[string]interface{}) 349 assertResults[i] = combinedAssert( 350 a.hasString(toSingle, key, "value", values[i]), 351 a.hasInt(toSingle, key, "occurs", occurrences[i]), 352 ) 353 } 354 return combinedAssert(assertResults...) 355 } 356 357 func (a *aggregateResponseAssert) hasNumber(parentMap map[string]interface{}, 358 parentKey, key string, expectedValue float64, 359 ) bool { 360 v, exist := parentMap[key] 361 if !exist { 362 return a.assert.Fail(fmt.Sprintf("'%s' does not have '%s'\n%#v", parentKey, key, parentMap)) 363 } 364 if v == nil { 365 return a.assert.Fail(fmt.Sprintf("'%s.%s' is nil", parentKey, key)) 366 } 367 if v, ok := v.(json.Number); ok { 368 if value, err := v.Float64(); err == nil { 369 if a.assert.InDelta(expectedValue, value, delta) { 370 return true 371 } 372 return a.assert.Fail(fmt.Sprintf("'%s.%s' of %#v is not equal to %#v", parentKey, key, value, expectedValue)) 373 } 374 } 375 return a.assert.Fail(fmt.Sprintf("'%s.%s' of %#v is not equal to %#v", parentKey, key, v, expectedValue)) 376 } 377 378 func (a *aggregateResponseAssert) hasInt(parentMap map[string]interface{}, 379 parentKey, key string, expectedValue int64, 380 ) bool { 381 v, exist := parentMap[key] 382 if !exist { 383 return a.assert.Fail(fmt.Sprintf("'%s' does not have '%s'\n%#v", parentKey, key, parentMap)) 384 } 385 if v == nil { 386 return a.assert.Fail(fmt.Sprintf("'%s.%s' is nil", parentKey, key)) 387 } 388 if v, ok := v.(json.Number); ok { 389 if value, err := v.Int64(); err == nil { 390 if value == expectedValue { 391 return true 392 } 393 return a.assert.Fail(fmt.Sprintf("'%s.%s' of %#v is not equal to %#v", parentKey, key, value, expectedValue)) 394 } 395 } 396 return a.assert.Fail(fmt.Sprintf("'%s.%s' of %#v is not equal to %#v", parentKey, key, v, expectedValue)) 397 } 398 399 func (a *aggregateResponseAssert) hasString(parentMap map[string]interface{}, 400 parentKey, key string, expectedValue string, 401 ) bool { 402 v, exist := parentMap[key] 403 if !exist { 404 return a.assert.Fail(fmt.Sprintf("'%s' does not have '%s'\n%#v", parentKey, key, parentMap)) 405 } 406 if v == nil { 407 return a.assert.Fail(fmt.Sprintf("'%s.%s' is nil", parentKey, key)) 408 } 409 if v != expectedValue { 410 return a.assert.Fail(fmt.Sprintf("'%s.%s' of %#v is not equal to %#v", parentKey, key, v, expectedValue)) 411 } 412 return true 413 } 414 415 func (a *aggregateResponseAssert) hasNil(parentMap map[string]interface{}, 416 parentKey, key string, 417 ) bool { 418 v, exist := parentMap[key] 419 if !exist { 420 return a.assert.Fail(fmt.Sprintf("'%s' does not have '%s'\n%#v", parentKey, key, parentMap)) 421 } 422 if v != nil { 423 return a.assert.Fail(fmt.Sprintf("'%s.%s' is not nil", parentKey, key)) 424 } 425 return true 426 } 427 428 func (a *aggregateResponseAssert) hasArray(parentMap map[string]interface{}, 429 parentKey, key string, expectedValue []interface{}, 430 ) bool { 431 v, exist := parentMap[key] 432 if !exist { 433 return a.assert.Fail(fmt.Sprintf("'%s' does not have '%s'\n%#v", parentKey, key, parentMap)) 434 } 435 if !a.assert.Equal(expectedValue, v) { 436 return a.assert.Fail(fmt.Sprintf("'%s.%s' of %#v is not equal to %#v", parentKey, key, v, expectedValue)) 437 } 438 return true 439 } 440 441 func combinedAssert(assertResults ...bool) bool { 442 for _, assertResult := range assertResults { 443 if !assertResult { 444 return false 445 } 446 } 447 return true 448 }