1package query_test 2 3import ( 4 "testing" 5 "time" 6 7 "github.com/google/go-cmp/cmp" 8 "github.com/influxdata/influxdb/query" 9 "github.com/influxdata/influxql" 10) 11 12// Ensure that a float iterator can be created for a count() call. 13func TestCallIterator_Count_Float(t *testing.T) { 14 itr, _ := query.NewCallIterator( 15 &FloatIterator{Points: []query.FloatPoint{ 16 {Name: "cpu", Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 17 {Name: "cpu", Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 18 {Name: "cpu", Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 19 {Name: "cpu", Time: 5, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 20 21 {Name: "cpu", Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 22 {Name: "cpu", Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 23 {Name: "mem", Time: 23, Value: 10, Tags: ParseTags("region=us-west,host=hostB")}, 24 }}, 25 query.IteratorOptions{ 26 Expr: MustParseExpr(`count("value")`), 27 Dimensions: []string{"host"}, 28 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 29 Ordered: true, 30 Ascending: true, 31 }, 32 ) 33 34 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 35 t.Fatalf("unexpected error: %s", err) 36 } else if diff := cmp.Diff(a, [][]query.Point{ 37 {&query.IntegerPoint{Name: "cpu", Time: 0, Value: 3, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 38 {&query.IntegerPoint{Name: "cpu", Time: 5, Value: 1, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 39 {&query.IntegerPoint{Name: "cpu", Time: 0, Value: 1, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 40 {&query.IntegerPoint{Name: "cpu", Time: 20, Value: 1, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 41 {&query.IntegerPoint{Name: "mem", Time: 20, Value: 1, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 42 }); diff != "" { 43 t.Fatalf("unexpected points:\n%s", diff) 44 } 45} 46 47// Ensure that an integer iterator can be created for a count() call. 48func TestCallIterator_Count_Integer(t *testing.T) { 49 itr, _ := query.NewCallIterator( 50 &IntegerIterator{Points: []query.IntegerPoint{ 51 {Name: "cpu", Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 52 {Name: "cpu", Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 53 {Name: "cpu", Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 54 {Name: "cpu", Time: 5, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 55 56 {Name: "cpu", Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 57 {Name: "cpu", Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 58 {Name: "mem", Time: 23, Value: 10, Tags: ParseTags("region=us-west,host=hostB")}, 59 }}, 60 query.IteratorOptions{ 61 Expr: MustParseExpr(`count("value")`), 62 Dimensions: []string{"host"}, 63 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 64 Ordered: true, 65 Ascending: true, 66 }, 67 ) 68 69 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 70 t.Fatalf("unexpected error: %s", err) 71 } else if diff := cmp.Diff(a, [][]query.Point{ 72 {&query.IntegerPoint{Name: "cpu", Time: 0, Value: 3, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 73 {&query.IntegerPoint{Name: "cpu", Time: 5, Value: 1, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 74 {&query.IntegerPoint{Name: "cpu", Time: 0, Value: 1, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 75 {&query.IntegerPoint{Name: "cpu", Time: 20, Value: 1, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 76 {&query.IntegerPoint{Name: "mem", Time: 20, Value: 1, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 77 }); diff != "" { 78 t.Fatalf("unexpected points:\n%s", diff) 79 } 80} 81 82// Ensure that an unsigned iterator can be created for a count() call. 83func TestCallIterator_Count_Unsigned(t *testing.T) { 84 itr, _ := query.NewCallIterator( 85 &UnsignedIterator{Points: []query.UnsignedPoint{ 86 {Name: "cpu", Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 87 {Name: "cpu", Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 88 {Name: "cpu", Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 89 {Name: "cpu", Time: 5, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 90 91 {Name: "cpu", Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 92 {Name: "cpu", Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 93 {Name: "mem", Time: 23, Value: 10, Tags: ParseTags("region=us-west,host=hostB")}, 94 }}, 95 query.IteratorOptions{ 96 Expr: MustParseExpr(`count("value")`), 97 Dimensions: []string{"host"}, 98 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 99 Ordered: true, 100 Ascending: true, 101 }, 102 ) 103 104 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 105 t.Fatalf("unexpected error: %s", err) 106 } else if diff := cmp.Diff(a, [][]query.Point{ 107 {&query.IntegerPoint{Name: "cpu", Time: 0, Value: 3, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 108 {&query.IntegerPoint{Name: "cpu", Time: 5, Value: 1, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 109 {&query.IntegerPoint{Name: "cpu", Time: 0, Value: 1, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 110 {&query.IntegerPoint{Name: "cpu", Time: 20, Value: 1, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 111 {&query.IntegerPoint{Name: "mem", Time: 20, Value: 1, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 112 }); diff != "" { 113 t.Fatalf("unexpected points:\n%s", diff) 114 } 115} 116 117// Ensure that a string iterator can be created for a count() call. 118func TestCallIterator_Count_String(t *testing.T) { 119 itr, _ := query.NewCallIterator( 120 &StringIterator{Points: []query.StringPoint{ 121 {Name: "cpu", Time: 0, Value: "d", Tags: ParseTags("region=us-east,host=hostA")}, 122 {Name: "cpu", Time: 2, Value: "b", Tags: ParseTags("region=us-east,host=hostA")}, 123 {Name: "cpu", Time: 1, Value: "b", Tags: ParseTags("region=us-west,host=hostA")}, 124 {Name: "cpu", Time: 5, Value: "e", Tags: ParseTags("region=us-east,host=hostA")}, 125 126 {Name: "cpu", Time: 1, Value: "c", Tags: ParseTags("region=us-west,host=hostB")}, 127 {Name: "cpu", Time: 23, Value: "a", Tags: ParseTags("region=us-west,host=hostB")}, 128 {Name: "mem", Time: 23, Value: "b", Tags: ParseTags("region=us-west,host=hostB")}, 129 }}, 130 query.IteratorOptions{ 131 Expr: MustParseExpr(`count("value")`), 132 Dimensions: []string{"host"}, 133 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 134 Ordered: true, 135 Ascending: true, 136 }, 137 ) 138 139 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 140 t.Fatalf("unexpected error: %s", err) 141 } else if diff := cmp.Diff(a, [][]query.Point{ 142 {&query.IntegerPoint{Name: "cpu", Time: 0, Value: 3, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 143 {&query.IntegerPoint{Name: "cpu", Time: 5, Value: 1, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 144 {&query.IntegerPoint{Name: "cpu", Time: 0, Value: 1, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 145 {&query.IntegerPoint{Name: "cpu", Time: 20, Value: 1, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 146 {&query.IntegerPoint{Name: "mem", Time: 20, Value: 1, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 147 }); diff != "" { 148 t.Fatalf("unexpected points:\n%s", diff) 149 } 150} 151 152// Ensure that a boolean iterator can be created for a count() call. 153func TestCallIterator_Count_Boolean(t *testing.T) { 154 itr, _ := query.NewCallIterator( 155 &BooleanIterator{Points: []query.BooleanPoint{ 156 {Name: "cpu", Time: 0, Value: true, Tags: ParseTags("region=us-east,host=hostA")}, 157 {Name: "cpu", Time: 2, Value: false, Tags: ParseTags("region=us-east,host=hostA")}, 158 {Name: "cpu", Time: 1, Value: true, Tags: ParseTags("region=us-west,host=hostA")}, 159 {Name: "cpu", Time: 5, Value: false, Tags: ParseTags("region=us-east,host=hostA")}, 160 161 {Name: "cpu", Time: 1, Value: true, Tags: ParseTags("region=us-west,host=hostB")}, 162 {Name: "cpu", Time: 23, Value: false, Tags: ParseTags("region=us-west,host=hostB")}, 163 {Name: "mem", Time: 23, Value: true, Tags: ParseTags("region=us-west,host=hostB")}, 164 }}, 165 query.IteratorOptions{ 166 Expr: MustParseExpr(`count("value")`), 167 Dimensions: []string{"host"}, 168 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 169 Ordered: true, 170 Ascending: true, 171 }, 172 ) 173 174 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 175 t.Fatalf("unexpected error: %s", err) 176 } else if diff := cmp.Diff(a, [][]query.Point{ 177 {&query.IntegerPoint{Name: "cpu", Time: 0, Value: 3, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 178 {&query.IntegerPoint{Name: "cpu", Time: 5, Value: 1, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 179 {&query.IntegerPoint{Name: "cpu", Time: 0, Value: 1, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 180 {&query.IntegerPoint{Name: "cpu", Time: 20, Value: 1, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 181 {&query.IntegerPoint{Name: "mem", Time: 20, Value: 1, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 182 }); diff != "" { 183 t.Fatalf("unexpected points:\n%s", diff) 184 } 185} 186 187// Ensure that a float iterator can be created for a min() call. 188func TestCallIterator_Min_Float(t *testing.T) { 189 itr, _ := query.NewCallIterator( 190 &FloatIterator{Points: []query.FloatPoint{ 191 {Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 192 {Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 193 {Time: 4, Value: 12, Tags: ParseTags("region=us-east,host=hostA")}, 194 {Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 195 {Time: 5, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 196 197 {Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 198 {Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 199 }}, 200 query.IteratorOptions{ 201 Expr: MustParseExpr(`min("value")`), 202 Dimensions: []string{"host"}, 203 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 204 Ordered: true, 205 Ascending: true, 206 }, 207 ) 208 209 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 210 t.Fatalf("unexpected error: %s", err) 211 } else if diff := cmp.Diff(a, [][]query.Point{ 212 {&query.FloatPoint{Time: 1, Value: 10, Tags: ParseTags("host=hostA"), Aggregated: 4}}, 213 {&query.FloatPoint{Time: 5, Value: 20, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 214 {&query.FloatPoint{Time: 1, Value: 11, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 215 {&query.FloatPoint{Time: 23, Value: 8, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 216 }); diff != "" { 217 t.Fatalf("unexpected points:\n%s", diff) 218 } 219} 220 221// Ensure that a integer iterator can be created for a min() call. 222func TestCallIterator_Min_Integer(t *testing.T) { 223 itr, _ := query.NewCallIterator( 224 &IntegerIterator{Points: []query.IntegerPoint{ 225 {Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 226 {Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 227 {Time: 4, Value: 12, Tags: ParseTags("region=us-east,host=hostA")}, 228 {Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 229 {Time: 5, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 230 231 {Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 232 {Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 233 }}, 234 query.IteratorOptions{ 235 Expr: MustParseExpr(`min("value")`), 236 Dimensions: []string{"host"}, 237 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 238 Ordered: true, 239 Ascending: true, 240 }, 241 ) 242 243 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 244 t.Fatalf("unexpected error: %s", err) 245 } else if diff := cmp.Diff(a, [][]query.Point{ 246 {&query.IntegerPoint{Time: 1, Value: 10, Tags: ParseTags("host=hostA"), Aggregated: 4}}, 247 {&query.IntegerPoint{Time: 5, Value: 20, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 248 {&query.IntegerPoint{Time: 1, Value: 11, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 249 {&query.IntegerPoint{Time: 23, Value: 8, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 250 }); diff != "" { 251 t.Fatalf("unexpected points:\n%s", diff) 252 } 253} 254 255// Ensure that a unsigned iterator can be created for a min() call. 256func TestCallIterator_Min_Unsigned(t *testing.T) { 257 itr, _ := query.NewCallIterator( 258 &UnsignedIterator{Points: []query.UnsignedPoint{ 259 {Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 260 {Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 261 {Time: 4, Value: 12, Tags: ParseTags("region=us-east,host=hostA")}, 262 {Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 263 {Time: 5, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 264 265 {Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 266 {Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 267 }}, 268 query.IteratorOptions{ 269 Expr: MustParseExpr(`min("value")`), 270 Dimensions: []string{"host"}, 271 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 272 Ordered: true, 273 Ascending: true, 274 }, 275 ) 276 277 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 278 t.Fatalf("unexpected error: %s", err) 279 } else if diff := cmp.Diff(a, [][]query.Point{ 280 {&query.UnsignedPoint{Time: 1, Value: 10, Tags: ParseTags("host=hostA"), Aggregated: 4}}, 281 {&query.UnsignedPoint{Time: 5, Value: 20, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 282 {&query.UnsignedPoint{Time: 1, Value: 11, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 283 {&query.UnsignedPoint{Time: 23, Value: 8, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 284 }); diff != "" { 285 t.Fatalf("unexpected points:\n%s", diff) 286 } 287} 288 289// Ensure that a boolean iterator can be created for a min() call. 290func TestCallIterator_Min_Boolean(t *testing.T) { 291 itr, _ := query.NewCallIterator( 292 &BooleanIterator{Points: []query.BooleanPoint{ 293 {Time: 0, Value: true, Tags: ParseTags("region=us-east,host=hostA")}, 294 {Time: 2, Value: false, Tags: ParseTags("region=us-east,host=hostA")}, 295 {Time: 1, Value: true, Tags: ParseTags("region=us-west,host=hostA")}, 296 {Time: 5, Value: false, Tags: ParseTags("region=us-east,host=hostA")}, 297 298 {Time: 1, Value: false, Tags: ParseTags("region=us-west,host=hostB")}, 299 {Time: 23, Value: true, Tags: ParseTags("region=us-west,host=hostB")}, 300 }}, 301 query.IteratorOptions{ 302 Expr: MustParseExpr(`min("value")`), 303 Dimensions: []string{"host"}, 304 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 305 Ordered: true, 306 Ascending: true, 307 }, 308 ) 309 310 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 311 t.Fatalf("unexpected error: %s", err) 312 } else if diff := cmp.Diff(a, [][]query.Point{ 313 {&query.BooleanPoint{Time: 2, Value: false, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 314 {&query.BooleanPoint{Time: 5, Value: false, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 315 {&query.BooleanPoint{Time: 1, Value: false, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 316 {&query.BooleanPoint{Time: 23, Value: true, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 317 }); diff != "" { 318 t.Fatalf("unexpected points:\n%s", diff) 319 } 320} 321 322// Ensure that a float iterator can be created for a max() call. 323func TestCallIterator_Max_Float(t *testing.T) { 324 itr, _ := query.NewCallIterator( 325 &FloatIterator{Points: []query.FloatPoint{ 326 {Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 327 {Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 328 {Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 329 {Time: 5, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 330 331 {Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 332 {Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 333 }}, 334 query.IteratorOptions{ 335 Expr: MustParseExpr(`max("value")`), 336 Dimensions: []string{"host"}, 337 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 338 Ordered: true, 339 Ascending: true, 340 }, 341 ) 342 343 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 344 t.Fatalf("unexpected error: %s", err) 345 } else if diff := cmp.Diff(a, [][]query.Point{ 346 {&query.FloatPoint{Time: 0, Value: 15, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 347 {&query.FloatPoint{Time: 5, Value: 20, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 348 {&query.FloatPoint{Time: 1, Value: 11, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 349 {&query.FloatPoint{Time: 23, Value: 8, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 350 }); diff != "" { 351 t.Fatalf("unexpected points:\n%s", diff) 352 } 353} 354 355// Ensure that a integer iterator can be created for a max() call. 356func TestCallIterator_Max_Integer(t *testing.T) { 357 itr, _ := query.NewCallIterator( 358 &IntegerIterator{Points: []query.IntegerPoint{ 359 {Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 360 {Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 361 {Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 362 {Time: 5, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 363 364 {Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 365 {Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 366 }}, 367 query.IteratorOptions{ 368 Expr: MustParseExpr(`max("value")`), 369 Dimensions: []string{"host"}, 370 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 371 Ordered: true, 372 Ascending: true, 373 }, 374 ) 375 376 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 377 t.Fatalf("unexpected error: %s", err) 378 } else if diff := cmp.Diff(a, [][]query.Point{ 379 {&query.IntegerPoint{Time: 0, Value: 15, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 380 {&query.IntegerPoint{Time: 5, Value: 20, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 381 {&query.IntegerPoint{Time: 1, Value: 11, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 382 {&query.IntegerPoint{Time: 23, Value: 8, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 383 }); diff != "" { 384 t.Fatalf("unexpected points:\n%s", diff) 385 } 386} 387 388// Ensure that a unsigned iterator can be created for a max() call. 389func TestCallIterator_Max_Unsigned(t *testing.T) { 390 itr, _ := query.NewCallIterator( 391 &UnsignedIterator{Points: []query.UnsignedPoint{ 392 {Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 393 {Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 394 {Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 395 {Time: 5, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 396 397 {Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 398 {Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 399 }}, 400 query.IteratorOptions{ 401 Expr: MustParseExpr(`max("value")`), 402 Dimensions: []string{"host"}, 403 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 404 Ordered: true, 405 Ascending: true, 406 }, 407 ) 408 409 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 410 t.Fatalf("unexpected error: %s", err) 411 } else if diff := cmp.Diff(a, [][]query.Point{ 412 {&query.UnsignedPoint{Time: 0, Value: 15, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 413 {&query.UnsignedPoint{Time: 5, Value: 20, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 414 {&query.UnsignedPoint{Time: 1, Value: 11, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 415 {&query.UnsignedPoint{Time: 23, Value: 8, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 416 }); diff != "" { 417 t.Fatalf("unexpected points:\n%s", diff) 418 } 419} 420 421// Ensure that a boolean iterator can be created for a max() call. 422func TestCallIterator_Max_Boolean(t *testing.T) { 423 itr, _ := query.NewCallIterator( 424 &BooleanIterator{Points: []query.BooleanPoint{ 425 {Time: 0, Value: true, Tags: ParseTags("region=us-east,host=hostA")}, 426 {Time: 2, Value: false, Tags: ParseTags("region=us-east,host=hostA")}, 427 {Time: 1, Value: true, Tags: ParseTags("region=us-west,host=hostA")}, 428 {Time: 5, Value: false, Tags: ParseTags("region=us-east,host=hostA")}, 429 430 {Time: 1, Value: false, Tags: ParseTags("region=us-west,host=hostB")}, 431 {Time: 23, Value: true, Tags: ParseTags("region=us-west,host=hostB")}, 432 }}, 433 query.IteratorOptions{ 434 Expr: MustParseExpr(`max("value")`), 435 Dimensions: []string{"host"}, 436 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 437 Ordered: true, 438 Ascending: true, 439 }, 440 ) 441 442 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 443 t.Fatalf("unexpected error: %s", err) 444 } else if diff := cmp.Diff(a, [][]query.Point{ 445 {&query.BooleanPoint{Time: 0, Value: true, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 446 {&query.BooleanPoint{Time: 5, Value: false, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 447 {&query.BooleanPoint{Time: 1, Value: false, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 448 {&query.BooleanPoint{Time: 23, Value: true, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 449 }); diff != "" { 450 t.Fatalf("unexpected points:\n%s", diff) 451 } 452} 453 454// Ensure that a float iterator can be created for a sum() call. 455func TestCallIterator_Sum_Float(t *testing.T) { 456 itr, _ := query.NewCallIterator( 457 &FloatIterator{Points: []query.FloatPoint{ 458 {Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 459 {Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 460 {Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 461 {Time: 5, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 462 463 {Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 464 {Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 465 }}, 466 query.IteratorOptions{ 467 Expr: MustParseExpr(`sum("value")`), 468 Dimensions: []string{"host"}, 469 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 470 Ordered: true, 471 Ascending: true, 472 }, 473 ) 474 475 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 476 t.Fatalf("unexpected error: %s", err) 477 } else if diff := cmp.Diff(a, [][]query.Point{ 478 {&query.FloatPoint{Time: 0, Value: 35, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 479 {&query.FloatPoint{Time: 5, Value: 20, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 480 {&query.FloatPoint{Time: 0, Value: 11, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 481 {&query.FloatPoint{Time: 20, Value: 8, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 482 }); diff != "" { 483 t.Fatalf("unexpected points:\n%s", diff) 484 } 485} 486 487// Ensure that an integer iterator can be created for a sum() call. 488func TestCallIterator_Sum_Integer(t *testing.T) { 489 itr, _ := query.NewCallIterator( 490 &IntegerIterator{Points: []query.IntegerPoint{ 491 {Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 492 {Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 493 {Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 494 {Time: 5, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 495 496 {Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 497 {Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 498 }}, 499 query.IteratorOptions{ 500 Expr: MustParseExpr(`sum("value")`), 501 Dimensions: []string{"host"}, 502 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 503 Ordered: true, 504 Ascending: true, 505 }, 506 ) 507 508 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 509 t.Fatalf("unexpected error: %s", err) 510 } else if diff := cmp.Diff(a, [][]query.Point{ 511 {&query.IntegerPoint{Time: 0, Value: 35, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 512 {&query.IntegerPoint{Time: 5, Value: 20, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 513 {&query.IntegerPoint{Time: 0, Value: 11, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 514 {&query.IntegerPoint{Time: 20, Value: 8, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 515 }); diff != "" { 516 t.Fatalf("unexpected points:\n%s", diff) 517 } 518} 519 520// Ensure that an unsigned iterator can be created for a sum() call. 521func TestCallIterator_Sum_Unsigned(t *testing.T) { 522 itr, _ := query.NewCallIterator( 523 &UnsignedIterator{Points: []query.UnsignedPoint{ 524 {Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 525 {Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 526 {Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 527 {Time: 5, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 528 529 {Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 530 {Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 531 }}, 532 query.IteratorOptions{ 533 Expr: MustParseExpr(`sum("value")`), 534 Dimensions: []string{"host"}, 535 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 536 Ordered: true, 537 Ascending: true, 538 }, 539 ) 540 541 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 542 t.Fatalf("unexpected error: %s", err) 543 } else if diff := cmp.Diff(a, [][]query.Point{ 544 {&query.UnsignedPoint{Time: 0, Value: 35, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 545 {&query.UnsignedPoint{Time: 5, Value: 20, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 546 {&query.UnsignedPoint{Time: 0, Value: 11, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 547 {&query.UnsignedPoint{Time: 20, Value: 8, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 548 }); diff != "" { 549 t.Fatalf("unexpected points:\n%s", diff) 550 } 551} 552 553// Ensure that a float iterator can be created for a first() call. 554func TestCallIterator_First_Float(t *testing.T) { 555 itr, _ := query.NewCallIterator( 556 &FloatIterator{Points: []query.FloatPoint{ 557 {Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 558 {Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 559 {Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 560 {Time: 6, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 561 562 {Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 563 {Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 564 }}, 565 query.IteratorOptions{ 566 Expr: MustParseExpr(`first("value")`), 567 Dimensions: []string{"host"}, 568 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 569 Ordered: true, 570 Ascending: true, 571 }, 572 ) 573 574 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 575 t.Fatalf("unexpected error: %s", err) 576 } else if diff := cmp.Diff(a, [][]query.Point{ 577 {&query.FloatPoint{Time: 0, Value: 15, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 578 {&query.FloatPoint{Time: 6, Value: 20, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 579 {&query.FloatPoint{Time: 1, Value: 11, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 580 {&query.FloatPoint{Time: 23, Value: 8, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 581 }); diff != "" { 582 t.Fatalf("unexpected points:\n%s", diff) 583 } 584} 585 586// Ensure that an integer iterator can be created for a first() call. 587func TestCallIterator_First_Integer(t *testing.T) { 588 itr, _ := query.NewCallIterator( 589 &IntegerIterator{Points: []query.IntegerPoint{ 590 {Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 591 {Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 592 {Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 593 {Time: 6, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 594 595 {Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 596 {Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 597 }}, 598 query.IteratorOptions{ 599 Expr: MustParseExpr(`first("value")`), 600 Dimensions: []string{"host"}, 601 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 602 Ordered: true, 603 Ascending: true, 604 }, 605 ) 606 607 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 608 t.Fatalf("unexpected error: %s", err) 609 } else if diff := cmp.Diff(a, [][]query.Point{ 610 {&query.IntegerPoint{Time: 0, Value: 15, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 611 {&query.IntegerPoint{Time: 6, Value: 20, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 612 {&query.IntegerPoint{Time: 1, Value: 11, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 613 {&query.IntegerPoint{Time: 23, Value: 8, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 614 }); diff != "" { 615 t.Fatalf("unexpected points:\n%s", diff) 616 } 617} 618 619// Ensure that an unsigned iterator can be created for a first() call. 620func TestCallIterator_First_Unsigned(t *testing.T) { 621 itr, _ := query.NewCallIterator( 622 &UnsignedIterator{Points: []query.UnsignedPoint{ 623 {Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 624 {Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 625 {Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 626 {Time: 6, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 627 628 {Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 629 {Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 630 }}, 631 query.IteratorOptions{ 632 Expr: MustParseExpr(`first("value")`), 633 Dimensions: []string{"host"}, 634 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 635 Ordered: true, 636 Ascending: true, 637 }, 638 ) 639 640 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 641 t.Fatalf("unexpected error: %s", err) 642 } else if diff := cmp.Diff(a, [][]query.Point{ 643 {&query.UnsignedPoint{Time: 0, Value: 15, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 644 {&query.UnsignedPoint{Time: 6, Value: 20, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 645 {&query.UnsignedPoint{Time: 1, Value: 11, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 646 {&query.UnsignedPoint{Time: 23, Value: 8, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 647 }); diff != "" { 648 t.Fatalf("unexpected points:\n%s", diff) 649 } 650} 651 652// Ensure that a string iterator can be created for a first() call. 653func TestCallIterator_First_String(t *testing.T) { 654 itr, _ := query.NewCallIterator( 655 &StringIterator{Points: []query.StringPoint{ 656 {Time: 2, Value: "b", Tags: ParseTags("region=us-east,host=hostA")}, 657 {Time: 0, Value: "d", Tags: ParseTags("region=us-east,host=hostA")}, 658 {Time: 1, Value: "b", Tags: ParseTags("region=us-west,host=hostA")}, 659 {Time: 6, Value: "e", Tags: ParseTags("region=us-east,host=hostA")}, 660 661 {Time: 1, Value: "c", Tags: ParseTags("region=us-west,host=hostB")}, 662 {Time: 23, Value: "a", Tags: ParseTags("region=us-west,host=hostB")}, 663 }}, 664 query.IteratorOptions{ 665 Expr: MustParseExpr(`first("value")`), 666 Dimensions: []string{"host"}, 667 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 668 Ordered: true, 669 Ascending: true, 670 }, 671 ) 672 673 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 674 t.Fatalf("unexpected error: %s", err) 675 } else if diff := cmp.Diff(a, [][]query.Point{ 676 {&query.StringPoint{Time: 0, Value: "d", Tags: ParseTags("host=hostA"), Aggregated: 3}}, 677 {&query.StringPoint{Time: 6, Value: "e", Tags: ParseTags("host=hostA"), Aggregated: 1}}, 678 {&query.StringPoint{Time: 1, Value: "c", Tags: ParseTags("host=hostB"), Aggregated: 1}}, 679 {&query.StringPoint{Time: 23, Value: "a", Tags: ParseTags("host=hostB"), Aggregated: 1}}, 680 }); diff != "" { 681 t.Fatalf("unexpected points:\n%s", diff) 682 } 683} 684 685// Ensure that a boolean iterator can be created for a first() call. 686func TestCallIterator_First_Boolean(t *testing.T) { 687 itr, _ := query.NewCallIterator( 688 &BooleanIterator{Points: []query.BooleanPoint{ 689 {Time: 2, Value: false, Tags: ParseTags("region=us-east,host=hostA")}, 690 {Time: 0, Value: true, Tags: ParseTags("region=us-east,host=hostA")}, 691 {Time: 1, Value: false, Tags: ParseTags("region=us-west,host=hostA")}, 692 {Time: 6, Value: false, Tags: ParseTags("region=us-east,host=hostA")}, 693 694 {Time: 1, Value: true, Tags: ParseTags("region=us-west,host=hostB")}, 695 {Time: 23, Value: false, Tags: ParseTags("region=us-west,host=hostB")}, 696 }}, 697 query.IteratorOptions{ 698 Expr: MustParseExpr(`first("value")`), 699 Dimensions: []string{"host"}, 700 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 701 Ordered: true, 702 Ascending: true, 703 }, 704 ) 705 706 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 707 t.Fatalf("unexpected error: %s", err) 708 } else if diff := cmp.Diff(a, [][]query.Point{ 709 {&query.BooleanPoint{Time: 0, Value: true, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 710 {&query.BooleanPoint{Time: 6, Value: false, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 711 {&query.BooleanPoint{Time: 1, Value: true, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 712 {&query.BooleanPoint{Time: 23, Value: false, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 713 }); diff != "" { 714 t.Fatalf("unexpected points:\n%s", diff) 715 } 716} 717 718// Ensure that a float iterator can be created for a last() call. 719func TestCallIterator_Last_Float(t *testing.T) { 720 itr, _ := query.NewCallIterator( 721 &FloatIterator{Points: []query.FloatPoint{ 722 {Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 723 {Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 724 {Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 725 {Time: 6, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 726 727 {Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 728 {Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 729 }}, 730 query.IteratorOptions{ 731 Expr: MustParseExpr(`last("value")`), 732 Dimensions: []string{"host"}, 733 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 734 Ordered: true, 735 Ascending: true, 736 }, 737 ) 738 739 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 740 t.Fatalf("unexpected error: %s", err) 741 } else if diff := cmp.Diff(a, [][]query.Point{ 742 {&query.FloatPoint{Time: 2, Value: 10, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 743 {&query.FloatPoint{Time: 6, Value: 20, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 744 {&query.FloatPoint{Time: 1, Value: 11, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 745 {&query.FloatPoint{Time: 23, Value: 8, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 746 }); diff != "" { 747 t.Fatalf("unexpected points:\n%s", diff) 748 } 749} 750 751// Ensure that an integer iterator can be created for a last() call. 752func TestCallIterator_Last_Integer(t *testing.T) { 753 itr, _ := query.NewCallIterator( 754 &IntegerIterator{Points: []query.IntegerPoint{ 755 {Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 756 {Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 757 {Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 758 {Time: 6, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 759 760 {Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 761 {Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 762 }}, 763 query.IteratorOptions{ 764 Expr: MustParseExpr(`last("value")`), 765 Dimensions: []string{"host"}, 766 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 767 Ordered: true, 768 Ascending: true, 769 }, 770 ) 771 772 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 773 t.Fatalf("unexpected error: %s", err) 774 } else if diff := cmp.Diff(a, [][]query.Point{ 775 {&query.IntegerPoint{Time: 2, Value: 10, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 776 {&query.IntegerPoint{Time: 6, Value: 20, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 777 {&query.IntegerPoint{Time: 1, Value: 11, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 778 {&query.IntegerPoint{Time: 23, Value: 8, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 779 }); diff != "" { 780 t.Fatalf("unexpected points:\n%s", diff) 781 } 782} 783 784// Ensure that an unsigned iterator can be created for a last() call. 785func TestCallIterator_Last_Unsigned(t *testing.T) { 786 itr, _ := query.NewCallIterator( 787 &UnsignedIterator{Points: []query.UnsignedPoint{ 788 {Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 789 {Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 790 {Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 791 {Time: 6, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 792 793 {Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 794 {Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 795 }}, 796 query.IteratorOptions{ 797 Expr: MustParseExpr(`last("value")`), 798 Dimensions: []string{"host"}, 799 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 800 Ordered: true, 801 Ascending: true, 802 }, 803 ) 804 805 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 806 t.Fatalf("unexpected error: %s", err) 807 } else if diff := cmp.Diff(a, [][]query.Point{ 808 {&query.UnsignedPoint{Time: 2, Value: 10, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 809 {&query.UnsignedPoint{Time: 6, Value: 20, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 810 {&query.UnsignedPoint{Time: 1, Value: 11, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 811 {&query.UnsignedPoint{Time: 23, Value: 8, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 812 }); diff != "" { 813 t.Fatalf("unexpected points:\n%s", diff) 814 } 815} 816 817// Ensure that a string iterator can be created for a last() call. 818func TestCallIterator_Last_String(t *testing.T) { 819 itr, _ := query.NewCallIterator( 820 &StringIterator{Points: []query.StringPoint{ 821 {Time: 2, Value: "b", Tags: ParseTags("region=us-east,host=hostA")}, 822 {Time: 0, Value: "d", Tags: ParseTags("region=us-east,host=hostA")}, 823 {Time: 1, Value: "b", Tags: ParseTags("region=us-west,host=hostA")}, 824 {Time: 6, Value: "e", Tags: ParseTags("region=us-east,host=hostA")}, 825 826 {Time: 1, Value: "c", Tags: ParseTags("region=us-west,host=hostB")}, 827 {Time: 23, Value: "a", Tags: ParseTags("region=us-west,host=hostB")}, 828 }}, 829 query.IteratorOptions{ 830 Expr: MustParseExpr(`last("value")`), 831 Dimensions: []string{"host"}, 832 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 833 Ordered: true, 834 Ascending: true, 835 }, 836 ) 837 838 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 839 t.Fatalf("unexpected error: %s", err) 840 } else if diff := cmp.Diff(a, [][]query.Point{ 841 {&query.StringPoint{Time: 2, Value: "b", Tags: ParseTags("host=hostA"), Aggregated: 3}}, 842 {&query.StringPoint{Time: 6, Value: "e", Tags: ParseTags("host=hostA"), Aggregated: 1}}, 843 {&query.StringPoint{Time: 1, Value: "c", Tags: ParseTags("host=hostB"), Aggregated: 1}}, 844 {&query.StringPoint{Time: 23, Value: "a", Tags: ParseTags("host=hostB"), Aggregated: 1}}, 845 }); diff != "" { 846 t.Fatalf("unexpected points:\n%s", diff) 847 } 848} 849 850// Ensure that a boolean iterator can be created for a last() call. 851func TestCallIterator_Last_Boolean(t *testing.T) { 852 itr, _ := query.NewCallIterator( 853 &BooleanIterator{Points: []query.BooleanPoint{ 854 {Time: 2, Value: false, Tags: ParseTags("region=us-east,host=hostA")}, 855 {Time: 0, Value: true, Tags: ParseTags("region=us-east,host=hostA")}, 856 {Time: 1, Value: false, Tags: ParseTags("region=us-west,host=hostA")}, 857 {Time: 6, Value: false, Tags: ParseTags("region=us-east,host=hostA")}, 858 859 {Time: 1, Value: true, Tags: ParseTags("region=us-west,host=hostB")}, 860 {Time: 23, Value: false, Tags: ParseTags("region=us-west,host=hostB")}, 861 }}, 862 query.IteratorOptions{ 863 Expr: MustParseExpr(`last("value")`), 864 Dimensions: []string{"host"}, 865 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 866 Ordered: true, 867 Ascending: true, 868 }, 869 ) 870 871 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 872 t.Fatalf("unexpected error: %s", err) 873 } else if diff := cmp.Diff(a, [][]query.Point{ 874 {&query.BooleanPoint{Time: 2, Value: false, Tags: ParseTags("host=hostA"), Aggregated: 3}}, 875 {&query.BooleanPoint{Time: 6, Value: false, Tags: ParseTags("host=hostA"), Aggregated: 1}}, 876 {&query.BooleanPoint{Time: 1, Value: true, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 877 {&query.BooleanPoint{Time: 23, Value: false, Tags: ParseTags("host=hostB"), Aggregated: 1}}, 878 }); diff != "" { 879 t.Fatalf("unexpected points:\n%s", diff) 880 } 881} 882 883// Ensure that a float iterator can be created for a mode() call. 884func TestCallIterator_Mode_Float(t *testing.T) { 885 itr, _ := query.NewModeIterator(&FloatIterator{Points: []query.FloatPoint{ 886 {Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 887 {Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 888 {Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 889 {Time: 3, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 890 {Time: 4, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 891 {Time: 6, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 892 {Time: 7, Value: 21, Tags: ParseTags("region=us-east,host=hostA")}, 893 {Time: 8, Value: 21, Tags: ParseTags("region=us-east,host=hostA")}, 894 895 {Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 896 {Time: 22, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 897 {Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 898 {Time: 24, Value: 25, Tags: ParseTags("region=us-west,host=hostB")}, 899 }}, 900 query.IteratorOptions{ 901 Expr: MustParseExpr(`mode("value")`), 902 Dimensions: []string{"host"}, 903 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 904 Ordered: true, 905 Ascending: true, 906 }, 907 ) 908 909 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 910 t.Fatalf("unexpected error: %s", err) 911 } else if diff := cmp.Diff(a, [][]query.Point{ 912 {&query.FloatPoint{Time: 0, Value: 10, Tags: ParseTags("host=hostA"), Aggregated: 0}}, 913 {&query.FloatPoint{Time: 5, Value: 21, Tags: ParseTags("host=hostA"), Aggregated: 0}}, 914 {&query.FloatPoint{Time: 1, Value: 11, Tags: ParseTags("host=hostB"), Aggregated: 0}}, 915 {&query.FloatPoint{Time: 20, Value: 8, Tags: ParseTags("host=hostB"), Aggregated: 0}}, 916 }); diff != "" { 917 t.Fatalf("unexpected points:\n%s", diff) 918 } 919} 920 921// Ensure that a integer iterator can be created for a mode() call. 922func TestCallIterator_Mode_Integer(t *testing.T) { 923 itr, _ := query.NewModeIterator(&IntegerIterator{Points: []query.IntegerPoint{ 924 {Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 925 {Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 926 {Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 927 {Time: 3, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 928 {Time: 4, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 929 {Time: 6, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 930 {Time: 7, Value: 21, Tags: ParseTags("region=us-east,host=hostA")}, 931 {Time: 8, Value: 21, Tags: ParseTags("region=us-east,host=hostA")}, 932 {Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 933 {Time: 22, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 934 {Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 935 {Time: 24, Value: 25, Tags: ParseTags("region=us-west,host=hostB")}, 936 }}, 937 query.IteratorOptions{ 938 Expr: MustParseExpr(`mode("value")`), 939 Dimensions: []string{"host"}, 940 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 941 Ordered: true, 942 Ascending: true, 943 }, 944 ) 945 946 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 947 t.Fatalf("unexpected error: %s", err) 948 } else if diff := cmp.Diff(a, [][]query.Point{ 949 {&query.IntegerPoint{Time: 0, Value: 10, Tags: ParseTags("host=hostA")}}, 950 {&query.IntegerPoint{Time: 5, Value: 21, Tags: ParseTags("host=hostA")}}, 951 {&query.IntegerPoint{Time: 1, Value: 11, Tags: ParseTags("host=hostB")}}, 952 {&query.IntegerPoint{Time: 20, Value: 8, Tags: ParseTags("host=hostB")}}, 953 }); diff != "" { 954 t.Fatalf("unexpected points:\n%s", diff) 955 } 956} 957 958// Ensure that a unsigned iterator can be created for a mode() call. 959func TestCallIterator_Mode_Unsigned(t *testing.T) { 960 itr, _ := query.NewModeIterator(&UnsignedIterator{Points: []query.UnsignedPoint{ 961 {Time: 0, Value: 15, Tags: ParseTags("region=us-east,host=hostA")}, 962 {Time: 1, Value: 10, Tags: ParseTags("region=us-west,host=hostA")}, 963 {Time: 2, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 964 {Time: 3, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 965 {Time: 4, Value: 10, Tags: ParseTags("region=us-east,host=hostA")}, 966 {Time: 6, Value: 20, Tags: ParseTags("region=us-east,host=hostA")}, 967 {Time: 7, Value: 21, Tags: ParseTags("region=us-east,host=hostA")}, 968 {Time: 8, Value: 21, Tags: ParseTags("region=us-east,host=hostA")}, 969 {Time: 1, Value: 11, Tags: ParseTags("region=us-west,host=hostB")}, 970 {Time: 22, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 971 {Time: 23, Value: 8, Tags: ParseTags("region=us-west,host=hostB")}, 972 {Time: 24, Value: 25, Tags: ParseTags("region=us-west,host=hostB")}, 973 }}, 974 query.IteratorOptions{ 975 Expr: MustParseExpr(`mode("value")`), 976 Dimensions: []string{"host"}, 977 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 978 Ordered: true, 979 Ascending: true, 980 }, 981 ) 982 983 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 984 t.Fatalf("unexpected error: %s", err) 985 } else if diff := cmp.Diff(a, [][]query.Point{ 986 {&query.UnsignedPoint{Time: 0, Value: 10, Tags: ParseTags("host=hostA")}}, 987 {&query.UnsignedPoint{Time: 5, Value: 21, Tags: ParseTags("host=hostA")}}, 988 {&query.UnsignedPoint{Time: 1, Value: 11, Tags: ParseTags("host=hostB")}}, 989 {&query.UnsignedPoint{Time: 20, Value: 8, Tags: ParseTags("host=hostB")}}, 990 }); diff != "" { 991 t.Fatalf("unexpected points:\n%s", diff) 992 } 993} 994 995// Ensure that a string iterator can be created for a mode() call. 996func TestCallIterator_Mode_String(t *testing.T) { 997 itr, _ := query.NewModeIterator(&StringIterator{Points: []query.StringPoint{ 998 {Time: 0, Value: "15", Tags: ParseTags("region=us-east,host=hostA")}, 999 {Time: 1, Value: "10", Tags: ParseTags("region=us-west,host=hostA")}, 1000 {Time: 2, Value: "10", Tags: ParseTags("region=us-east,host=hostA")}, 1001 {Time: 3, Value: "10", Tags: ParseTags("region=us-east,host=hostA")}, 1002 {Time: 4, Value: "10", Tags: ParseTags("region=us-east,host=hostA")}, 1003 {Time: 6, Value: "20", Tags: ParseTags("region=us-east,host=hostA")}, 1004 {Time: 7, Value: "21", Tags: ParseTags("region=us-east,host=hostA")}, 1005 {Time: 7, Value: "21", Tags: ParseTags("region=us-east,host=hostA")}, 1006 1007 {Time: 1, Value: "11", Tags: ParseTags("region=us-west,host=hostB")}, 1008 {Time: 22, Value: "8", Tags: ParseTags("region=us-west,host=hostB")}, 1009 {Time: 23, Value: "8", Tags: ParseTags("region=us-west,host=hostB")}, 1010 {Time: 24, Value: "25", Tags: ParseTags("region=us-west,host=hostB")}, 1011 }}, 1012 query.IteratorOptions{ 1013 Expr: MustParseExpr(`mode("value")`), 1014 Dimensions: []string{"host"}, 1015 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 1016 Ordered: true, 1017 Ascending: true, 1018 }, 1019 ) 1020 1021 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 1022 t.Fatalf("unexpected error: %s", err) 1023 } else if diff := cmp.Diff(a, [][]query.Point{ 1024 {&query.StringPoint{Time: 0, Value: "10", Tags: ParseTags("host=hostA")}}, 1025 {&query.StringPoint{Time: 5, Value: "21", Tags: ParseTags("host=hostA")}}, 1026 {&query.StringPoint{Time: 1, Value: "11", Tags: ParseTags("host=hostB")}}, 1027 {&query.StringPoint{Time: 20, Value: "8", Tags: ParseTags("host=hostB")}}, 1028 }); diff != "" { 1029 t.Fatalf("unexpected points:\n%s", diff) 1030 } 1031} 1032 1033// Ensure that a boolean iterator can be created for a modBooleanl. 1034func TestCallIterator_Mode_Boolean(t *testing.T) { 1035 itr, _ := query.NewModeIterator(&BooleanIterator{Points: []query.BooleanPoint{ 1036 {Time: 0, Value: true, Tags: ParseTags("region=us-east,host=hostA")}, 1037 {Time: 1, Value: true, Tags: ParseTags("region=us-west,host=hostA")}, 1038 {Time: 2, Value: true, Tags: ParseTags("region=us-east,host=hostA")}, 1039 {Time: 3, Value: true, Tags: ParseTags("region=us-east,host=hostA")}, 1040 {Time: 4, Value: false, Tags: ParseTags("region=us-east,host=hostA")}, 1041 {Time: 6, Value: false, Tags: ParseTags("region=us-east,host=hostA")}, 1042 {Time: 7, Value: false, Tags: ParseTags("region=us-east,host=hostA")}, 1043 {Time: 8, Value: false, Tags: ParseTags("region=us-east,host=hostA")}, 1044 1045 {Time: 1, Value: false, Tags: ParseTags("region=us-west,host=hostB")}, 1046 {Time: 22, Value: false, Tags: ParseTags("region=us-west,host=hostB")}, 1047 {Time: 23, Value: true, Tags: ParseTags("region=us-west,host=hostB")}, 1048 {Time: 24, Value: true, Tags: ParseTags("region=us-west,host=hostB")}, 1049 }}, 1050 query.IteratorOptions{ 1051 Expr: MustParseExpr(`mode("value")`), 1052 Dimensions: []string{"host"}, 1053 Interval: query.Interval{Duration: 5 * time.Nanosecond}, 1054 Ordered: true, 1055 Ascending: true, 1056 }, 1057 ) 1058 1059 if a, err := Iterators([]query.Iterator{itr}).ReadAll(); err != nil { 1060 t.Fatalf("unexpected error: %s", err) 1061 } else if diff := cmp.Diff(a, [][]query.Point{ 1062 {&query.BooleanPoint{Time: 0, Value: true, Tags: ParseTags("host=hostA")}}, 1063 {&query.BooleanPoint{Time: 5, Value: false, Tags: ParseTags("host=hostA")}}, 1064 {&query.BooleanPoint{Time: 1, Value: false, Tags: ParseTags("host=hostB")}}, 1065 {&query.BooleanPoint{Time: 20, Value: true, Tags: ParseTags("host=hostB")}}, 1066 }); diff != "" { 1067 t.Fatalf("unexpected points:\n%s", diff) 1068 } 1069} 1070 1071func TestNewCallIterator_UnsupportedExprName(t *testing.T) { 1072 _, err := query.NewCallIterator( 1073 &FloatIterator{}, 1074 query.IteratorOptions{ 1075 Expr: MustParseExpr(`foobar("value")`), 1076 }, 1077 ) 1078 1079 if err == nil || err.Error() != "unsupported function call: foobar" { 1080 t.Errorf("unexpected error: %s", err) 1081 } 1082} 1083 1084func BenchmarkCountIterator_1K(b *testing.B) { benchmarkCountIterator(b, 1000) } 1085func BenchmarkCountIterator_100K(b *testing.B) { benchmarkCountIterator(b, 100000) } 1086func BenchmarkCountIterator_1M(b *testing.B) { benchmarkCountIterator(b, 1000000) } 1087 1088func benchmarkCountIterator(b *testing.B, pointN int) { 1089 benchmarkCallIterator(b, query.IteratorOptions{ 1090 Expr: MustParseExpr("count(value)"), 1091 StartTime: influxql.MinTime, 1092 EndTime: influxql.MaxTime, 1093 }, pointN) 1094} 1095 1096func benchmarkCallIterator(b *testing.B, opt query.IteratorOptions, pointN int) { 1097 b.ReportAllocs() 1098 1099 for i := 0; i < b.N; i++ { 1100 // Create a lightweight point generator. 1101 p := query.FloatPoint{Name: "cpu", Value: 100} 1102 input := FloatPointGenerator{ 1103 N: pointN, 1104 Fn: func(i int) *query.FloatPoint { return &p }, 1105 } 1106 1107 // Execute call against input. 1108 itr, err := query.NewCallIterator(&input, opt) 1109 if err != nil { 1110 b.Fatal(err) 1111 } 1112 query.DrainIterator(itr) 1113 } 1114} 1115 1116func BenchmarkSampleIterator_1k(b *testing.B) { benchmarkSampleIterator(b, 1000) } 1117func BenchmarkSampleIterator_100k(b *testing.B) { benchmarkSampleIterator(b, 100000) } 1118func BenchmarkSampleIterator_1M(b *testing.B) { benchmarkSampleIterator(b, 1000000) } 1119 1120func benchmarkSampleIterator(b *testing.B, pointN int) { 1121 b.ReportAllocs() 1122 1123 // Create a lightweight point generator. 1124 p := query.FloatPoint{Name: "cpu"} 1125 input := FloatPointGenerator{ 1126 N: pointN, 1127 Fn: func(i int) *query.FloatPoint { 1128 p.Value = float64(i) 1129 return &p 1130 }, 1131 } 1132 1133 for i := 0; i < b.N; i++ { 1134 // Execute call against input. 1135 itr, err := query.NewSampleIterator(&input, query.IteratorOptions{}, 100) 1136 if err != nil { 1137 b.Fatal(err) 1138 } 1139 query.DrainIterator(itr) 1140 } 1141} 1142 1143func BenchmarkDistinctIterator_1K(b *testing.B) { benchmarkDistinctIterator(b, 1000) } 1144func BenchmarkDistinctIterator_100K(b *testing.B) { benchmarkDistinctIterator(b, 100000) } 1145func BenchmarkDistinctIterator_1M(b *testing.B) { benchmarkDistinctIterator(b, 1000000) } 1146 1147func benchmarkDistinctIterator(b *testing.B, pointN int) { 1148 b.ReportAllocs() 1149 1150 for i := 0; i < b.N; i++ { 1151 // Create a lightweight point generator. 1152 p := query.FloatPoint{Name: "cpu"} 1153 input := FloatPointGenerator{ 1154 N: pointN, 1155 Fn: func(i int) *query.FloatPoint { 1156 p.Value = float64(i % 10) 1157 return &p 1158 }, 1159 } 1160 1161 // Execute call against input. 1162 itr, err := query.NewDistinctIterator(&input, query.IteratorOptions{}) 1163 if err != nil { 1164 b.Fatal(err) 1165 } 1166 query.DrainIterator(itr) 1167 } 1168} 1169 1170func BenchmarkModeIterator_1K(b *testing.B) { benchmarkModeIterator(b, 1000) } 1171func BenchmarkModeIterator_100K(b *testing.B) { benchmarkModeIterator(b, 100000) } 1172func BenchmarkModeIterator_1M(b *testing.B) { benchmarkModeIterator(b, 1000000) } 1173 1174func benchmarkModeIterator(b *testing.B, pointN int) { 1175 b.ReportAllocs() 1176 1177 for i := 0; i < b.N; i++ { 1178 // Create a lightweight point generator. 1179 p := query.FloatPoint{Name: "cpu"} 1180 input := FloatPointGenerator{ 1181 N: pointN, 1182 Fn: func(i int) *query.FloatPoint { 1183 p.Value = float64(10) 1184 return &p 1185 }, 1186 } 1187 1188 // Execute call against input. 1189 itr, err := query.NewModeIterator(&input, query.IteratorOptions{}) 1190 if err != nil { 1191 b.Fatal(err) 1192 } 1193 query.DrainIterator(itr) 1194 } 1195} 1196 1197type FloatPointGenerator struct { 1198 i int 1199 N int 1200 Fn func(i int) *query.FloatPoint 1201} 1202 1203func (g *FloatPointGenerator) Close() error { return nil } 1204func (g *FloatPointGenerator) Stats() query.IteratorStats { return query.IteratorStats{} } 1205 1206func (g *FloatPointGenerator) Next() (*query.FloatPoint, error) { 1207 if g.i == g.N { 1208 return nil, nil 1209 } 1210 p := g.Fn(g.i) 1211 g.i++ 1212 return p, nil 1213} 1214