github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/query/functions/utils/group_test.go (about) 1 // Copyright (c) 2018 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package utils 22 23 import ( 24 "testing" 25 26 "github.com/m3db/m3/src/query/block" 27 "github.com/m3db/m3/src/query/models" 28 "github.com/m3db/m3/src/query/test/compare" 29 ) 30 31 var collectTest = []struct { 32 name string 33 matching []string 34 tagLists []models.Tags 35 withTagsExpectedIndices [][]int 36 withTagsExpectedTags []models.Tags 37 withoutTagsExpectedIndices [][]int 38 withoutTagsExpectedTags []models.Tags 39 }{ 40 { 41 "noMatching", 42 []string{}, 43 multiTagsFromMaps([]map[string]string{ 44 {"a": "1"}, 45 {"a": "1", "b": "2", "c": "4"}, 46 {"b": "2"}, 47 {"a": "1", "b": "2", "c": "3"}, 48 {"a": "1", "b": "2", "d": "3"}, 49 {"c": "d"}, 50 }), 51 [][]int{{0, 1, 2, 3, 4, 5}}, 52 []models.Tags{models.EmptyTags()}, 53 [][]int{{0}, {3}, {1}, {4}, {2}, {5}}, 54 multiTagsFromMaps([]map[string]string{ 55 {"a": "1"}, 56 {"a": "1", "b": "2", "c": "3"}, 57 {"a": "1", "b": "2", "c": "4"}, 58 {"a": "1", "b": "2", "d": "3"}, 59 {"b": "2"}, 60 {"c": "d"}, 61 }), 62 }, 63 { 64 "no equal Matching", 65 []string{"f", "g", "h"}, 66 multiTagsFromMaps([]map[string]string{ 67 {"a": "1"}, 68 {"a": "1", "b": "2", "c": "4"}, 69 {"b": "2"}, 70 {"a": "1", "b": "2", "c": "3"}, 71 {"a": "1", "b": "2", "d": "3"}, 72 {"c": "d"}, 73 }), 74 [][]int{{0, 1, 2, 3, 4, 5}}, 75 multiTagsFromMaps([]map[string]string{{}}), 76 [][]int{{0}, {3}, {1}, {4}, {2}, {5}}, 77 multiTagsFromMaps([]map[string]string{ 78 {"a": "1"}, 79 {"a": "1", "b": "2", "c": "3"}, 80 {"a": "1", "b": "2", "c": "4"}, 81 {"a": "1", "b": "2", "d": "3"}, 82 {"b": "2"}, 83 {"c": "d"}, 84 }), 85 }, 86 { 87 "one matching", 88 []string{"a"}, 89 multiTagsFromMaps([]map[string]string{ 90 {"a": "1"}, 91 {"a": "1", "b": "2", "c": "4"}, 92 {"b": "2"}, 93 {"a": "1", "b": "2", "c": "3"}, 94 {"a": "1", "b": "2", "d": "3"}, 95 {"c": "d"}, 96 }), 97 [][]int{{2, 5}, {0, 1, 3, 4}}, 98 multiTagsFromMaps([]map[string]string{ 99 {}, 100 {"a": "1"}, 101 }), 102 [][]int{{0}, {2}, {3}, {1}, {4}, {5}}, 103 multiTagsFromMaps([]map[string]string{ 104 {}, 105 {"b": "2"}, 106 {"b": "2", "c": "3"}, 107 {"b": "2", "c": "4"}, 108 {"b": "2", "d": "3"}, 109 {"c": "d"}, 110 }), 111 }, 112 { 113 "same tag matching", 114 []string{"a", "a"}, 115 multiTagsFromMaps([]map[string]string{ 116 {"a": "1"}, 117 {"a": "1", "b": "2", "c": "4"}, 118 {"b": "2"}, 119 {"a": "1", "b": "2", "c": "3"}, 120 {"a": "1", "b": "2", "d": "3"}, 121 {"c": "d"}, 122 }), 123 [][]int{{2, 5}, {0, 1, 3, 4}}, 124 multiTagsFromMaps([]map[string]string{ 125 {}, 126 {"a": "1"}, 127 }), 128 [][]int{{0}, {2}, {3}, {1}, {4}, {5}}, 129 multiTagsFromMaps([]map[string]string{ 130 {}, 131 {"b": "2"}, 132 {"b": "2", "c": "3"}, 133 {"b": "2", "c": "4"}, 134 {"b": "2", "d": "3"}, 135 {"c": "d"}, 136 }), 137 }, 138 { 139 "diffMatching", 140 []string{"a"}, 141 multiTagsFromMaps([]map[string]string{ 142 {"a": "1"}, 143 {"a": "2", "b": "2", "c": "4"}, 144 {"a": "2"}, 145 {"a": "1", "b": "2", "c": "3"}, 146 {"a": "1", "b": "2", "d": "3"}, 147 {"a": "d"}, 148 }), 149 [][]int{{0, 3, 4}, {1, 2}, {5}}, 150 multiTagsFromMaps([]map[string]string{ 151 {"a": "1"}, 152 {"a": "2"}, 153 {"a": "d"}, 154 }), 155 [][]int{{0, 2, 5}, {3}, {1}, {4}}, 156 multiTagsFromMaps([]map[string]string{ 157 {}, 158 {"b": "2", "c": "3"}, 159 {"b": "2", "c": "4"}, 160 {"b": "2", "d": "3"}, 161 }), 162 }, 163 { 164 "someMatching", 165 []string{"a", "b"}, 166 multiTagsFromMaps([]map[string]string{ 167 {"a": "1"}, 168 {"a": "1", "b": "2", "c": "4"}, 169 {"b": "2"}, 170 {"a": "1", "b": "2", "c": "3"}, 171 {"a": "1", "b": "2", "d": "3"}, 172 {"c": "3"}, 173 }), 174 [][]int{{5}, {0}, {1, 3, 4}, {2}}, 175 multiTagsFromMaps([]map[string]string{ 176 {}, 177 {"a": "1"}, 178 {"a": "1", "b": "2"}, 179 {"b": "2"}, 180 }), 181 [][]int{{0, 2}, {3, 5}, {1}, {4}}, 182 multiTagsFromMaps([]map[string]string{ 183 {}, 184 {"c": "3"}, 185 {"c": "4"}, 186 {"d": "3"}, 187 }), 188 }, 189 { 190 "functionMatching", 191 []string{"a"}, 192 multiTagsFromMaps([]map[string]string{ 193 {"a": "1"}, 194 {"a": "1"}, 195 {"a": "1", "b": "2"}, 196 {"a": "2", "b": "2"}, 197 {"b": "2"}, 198 {"c": "3"}, 199 }), 200 [][]int{{4, 5}, {0, 1, 2}, {3}}, 201 multiTagsFromMaps([]map[string]string{ 202 {}, 203 {"a": "1"}, 204 {"a": "2"}, 205 }), 206 [][]int{{0, 1}, {2, 3, 4}, {5}}, 207 multiTagsFromMaps([]map[string]string{ 208 {}, 209 {"b": "2"}, 210 {"c": "3"}, 211 }), 212 }, 213 { 214 "different matching", 215 []string{"a", "b"}, 216 multiTagsFromMaps([]map[string]string{ 217 {"a": "1", "c": "3", "d": "4"}, 218 {"b": "1", "c": "3", "d": "5"}, 219 {"b": "1", "c": "3", "d": "6"}, 220 }), 221 [][]int{{0}, {1, 2}}, 222 multiTagsFromMaps([]map[string]string{ 223 {"a": "1"}, 224 {"b": "1"}, 225 }), 226 [][]int{{0}, {1}, {2}}, 227 multiTagsFromMaps([]map[string]string{ 228 {"c": "3", "d": "4"}, 229 {"c": "3", "d": "5"}, 230 {"c": "3", "d": "6"}, 231 }), 232 }, 233 { 234 "metrics name", 235 []string{"a"}, 236 multiTagsFromMaps([]map[string]string{ 237 {"__name__": "foo", "a": "1"}, 238 {"__name__": "foo", "a": "1", "b": "2", "c": "4"}, 239 {"__name__": "foo", "b": "2"}, 240 {"__name__": "foo", "a": "1", "b": "2", "c": "3"}, 241 {"__name__": "foo", "a": "1", "b": "2", "d": "3"}, 242 {"__name__": "foo", "c": "d"}, 243 }), 244 [][]int{{2, 5}, {0, 1, 3, 4}}, 245 multiTagsFromMaps([]map[string]string{ 246 {}, 247 {"a": "1"}, 248 }), 249 [][]int{{0}, {2}, {3}, {1}, {4}, {5}}, 250 multiTagsFromMaps([]map[string]string{ 251 {}, 252 {"b": "2"}, 253 {"b": "2", "c": "3"}, 254 {"b": "2", "c": "4"}, 255 {"b": "2", "d": "3"}, 256 {"c": "d"}, 257 }), 258 }, 259 } 260 261 func testCollect(t *testing.T, without bool) { 262 for _, tt := range collectTest { 263 name := tt.name + " with tags" 264 if without { 265 name = tt.name + " without tags" 266 } 267 268 t.Run(name, func(t *testing.T) { 269 metas := make([]block.SeriesMeta, len(tt.tagLists)) 270 for i, tagList := range tt.tagLists { 271 metas[i] = block.SeriesMeta{Tags: tagList} 272 } 273 274 match := make([][]byte, len(tt.matching)) 275 for i, m := range tt.matching { 276 match[i] = []byte(m) 277 } 278 279 bName := []byte(name) 280 buckets, collected := GroupSeries(match, without, bName, metas) 281 expectedTags := tt.withTagsExpectedTags 282 expectedIndicies := tt.withTagsExpectedIndices 283 if without { 284 expectedTags = tt.withoutTagsExpectedTags 285 expectedIndicies = tt.withoutTagsExpectedIndices 286 } 287 288 expectedMetas := make([]block.SeriesMeta, len(expectedTags)) 289 for i, tags := range expectedTags { 290 expectedMetas[i] = block.SeriesMeta{ 291 Tags: tags, 292 Name: bName, 293 } 294 } 295 296 compare.CompareListsInOrder(t, collected, expectedMetas, buckets, expectedIndicies) 297 }) 298 } 299 } 300 301 func TestCollectWithTags(t *testing.T) { 302 testCollect(t, false) 303 } 304 305 func TestCollectWithoutTags(t *testing.T) { 306 testCollect(t, true) 307 } 308 309 func multiTagsFromMaps(tagMaps []map[string]string) []models.Tags { 310 tags := make([]models.Tags, len(tagMaps)) 311 for i, m := range tagMaps { 312 tags[i] = models.EmptyTags() 313 for n, v := range m { 314 tags[i] = tags[i].AddTag(models.Tag{Name: []byte(n), Value: []byte(v)}) 315 } 316 } 317 318 return tags 319 }