717c881a88a0622735739c070cdbf6e38156d84a
[gem5.git] / src / base / stats / storage.test.cc
1 /*
2 * Copyright (c) 2021 Daniel R. Carvalho
3 * All rights reserved
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <gtest/gtest-spi.h>
30 #include <gtest/gtest.h>
31
32 #include <cmath>
33
34 #include "base/gtest/cur_tick_fake.hh"
35 #include "base/stats/storage.hh"
36
37 // Instantiate the fake class to have a valid curTick of 0
38 GTestTickHandler tickHandler;
39
40 /** Increases the current tick by one. */
41 void increaseTick() { tickHandler.setCurTick(curTick() + 1); }
42
43 /** A pair of value and its number of samples, used for sampling. */
44 struct ValueSamples
45 {
46 Stats::Counter value;
47 Stats::Counter numSamples;
48
49 ValueSamples(Stats::Counter value, Stats::Counter num_samples)
50 : value(value), numSamples(num_samples)
51 {
52 }
53 };
54
55 /**
56 * A mocked info class.
57 * @todo There is no real dependency on the info class, so this must be
58 * removed on a cleanup.
59 */
60 class MockInfo : public Stats::Info
61 {
62 public:
63 MockInfo(Stats::StorageParams* storage_params)
64 : Stats::Info()
65 {
66 this->storageParams = storage_params;
67 }
68 ~MockInfo() = default;
69
70 bool check() const override { return true; }
71 void prepare() override { }
72 void reset() override { }
73 bool zero() const override { return true; }
74 void visit(Stats::Output &visitor) override { }
75 };
76
77 /** Test setting and getting a value to the storage. */
78 TEST(StatsStatStorTest, SetValueResult)
79 {
80 Stats::StatStor stor(nullptr);
81 Stats::Counter val;
82
83 val = 10;
84 stor.set(val);
85 ASSERT_EQ(stor.value(), val);
86 ASSERT_EQ(stor.result(), Stats::Result(val));
87
88 val = 1234;
89 stor.set(val);
90 ASSERT_EQ(stor.value(), val);
91 ASSERT_EQ(stor.result(), Stats::Result(val));
92 }
93
94 /** Test if prepare does not change the value. */
95 TEST(StatsStatStorTest, Prepare)
96 {
97 Stats::StatStor stor(nullptr);
98 Stats::Counter val;
99
100 val = 10;
101 stor.set(val);
102 stor.prepare(nullptr);
103 ASSERT_EQ(stor.value(), val);
104 ASSERT_EQ(stor.result(), Stats::Result(val));
105 }
106
107 /** Test whether incrementing and decrementing work as expected. */
108 TEST(StatsStatStorTest, IncDec)
109 {
110 Stats::StatStor stor(nullptr);
111 Stats::Counter diff_val = 10;
112 Stats::Counter val = 0;
113
114 stor.inc(diff_val);
115 val += diff_val;
116 ASSERT_EQ(stor.value(), val);
117
118 stor.inc(diff_val);
119 val += diff_val;
120 ASSERT_EQ(stor.value(), val);
121
122 stor.dec(diff_val);
123 val -= diff_val;
124 ASSERT_EQ(stor.value(), val);
125
126 stor.dec(diff_val);
127 val -= diff_val;
128 ASSERT_EQ(stor.value(), val);
129 }
130
131 /**
132 * Test whether zero is correctly set as the reset value. The test order is
133 * to check if it is initially zero on creation, then it is made non zero,
134 * and finally reset to zero.
135 */
136 TEST(StatsStatStorTest, ZeroReset)
137 {
138 Stats::StatStor stor(nullptr);
139 Stats::Counter val = 10;
140
141 ASSERT_TRUE(stor.zero());
142
143 stor.reset(nullptr);
144 ASSERT_TRUE(stor.zero());
145
146 stor.reset(nullptr);
147 stor.inc(val);
148 ASSERT_FALSE(stor.zero());
149 }
150
151 /** Test setting and getting a value to the storage. */
152 TEST(StatsAvgStorTest, SetValueResult)
153 {
154 Stats::AvgStor stor(nullptr);
155 Stats::Counter val;
156 Stats::Result total = 0;
157 Tick last_reset = 0;
158 Tick last_tick = 0;
159
160 val = 10;
161 stor.set(val);
162 last_tick = curTick();
163 ASSERT_EQ(stor.value(), val);
164 ASSERT_EQ(stor.result(), Stats::Result(total + val) /
165 Stats::Result(curTick() - last_reset + 1));
166 increaseTick();
167
168 total += val * (curTick() - last_tick);
169 val = 1234;
170 stor.set(val);
171 last_tick = curTick();
172 ASSERT_EQ(stor.value(), val);
173 ASSERT_EQ(stor.result(), Stats::Result(total + val) /
174 Stats::Result(curTick() - last_reset + 1));
175 increaseTick();
176 }
177
178 /**
179 * Test whether getting the result in a different tick triggers an assertion.
180 */
181 TEST(StatsAvgStorDeathTest, Result)
182 {
183 Stats::AvgStor stor(nullptr);
184 increaseTick();
185 ASSERT_DEATH(stor.result(), ".+");
186 }
187
188 /**
189 * Test whether getting the result in a different tick does not trigger an
190 * assertion if storage is prepared.
191 */
192 TEST(StatsAvgStorTest, Prepare)
193 {
194 Stats::AvgStor stor(nullptr);
195 Stats::Counter val = 10;
196 Stats::Result total = 0;
197 Tick last_reset = 0;
198 Tick last_tick = 0;
199
200 val = 10;
201 stor.set(val);
202 last_tick = curTick();
203 ASSERT_EQ(stor.value(), val);
204 ASSERT_EQ(stor.result(), Stats::Result(total + val) /
205 Stats::Result(curTick() - last_reset + 1));
206 increaseTick();
207
208 total += val * (curTick() - last_tick);
209 stor.prepare(nullptr);
210 last_tick = curTick();
211 ASSERT_EQ(stor.value(), val);
212 ASSERT_EQ(stor.result(), Stats::Result(total + val) /
213 Stats::Result(curTick() - last_reset + 1));
214 increaseTick();
215 }
216
217 /** Test whether incrementing and decrementing work as expected. */
218 TEST(StatsAvgStorTest, IncDec)
219 {
220 Stats::AvgStor stor(nullptr);
221 Stats::Counter diff_val = 10;
222 Stats::Counter val = 0;
223
224 stor.set(diff_val);
225 val += diff_val;
226 ASSERT_EQ(stor.value(), val);
227
228 stor.inc(diff_val);
229 val += diff_val;
230 ASSERT_EQ(stor.value(), val);
231
232 stor.inc(diff_val);
233 val += diff_val;
234 ASSERT_EQ(stor.value(), val);
235
236 stor.dec(diff_val);
237 val -= diff_val;
238 ASSERT_EQ(stor.value(), val);
239
240 stor.dec(diff_val);
241 val -= diff_val;
242 ASSERT_EQ(stor.value(), val);
243 }
244
245 /**
246 * Test whether zero is correctly set as the reset value. The test order is
247 * to check if it is initially zero on creation, then it is made non zero,
248 * and finally reset to zero.
249 */
250 TEST(StatsAvgStorTest, ZeroReset)
251 {
252 Stats::AvgStor stor(nullptr);
253 Stats::Counter val = 10;
254
255 ASSERT_TRUE(stor.zero());
256
257 stor.reset(nullptr);
258 ASSERT_TRUE(stor.zero());
259
260 // Set current value to val, reset total and increase tick, so that the
261 // next call to set will update the total to be different from zero
262 stor.inc(val);
263 stor.reset(nullptr);
264 increaseTick();
265 stor.inc(val);
266 ASSERT_FALSE(stor.zero());
267 }
268
269 /**
270 * Test that an assertion is thrown when no bucket size is provided before
271 * sampling.
272 */
273 TEST(StatsDistStorDeathTest, NoBucketSize)
274 {
275 Stats::Counter val = 10;
276 Stats::Counter num_samples = 5;
277 Stats::DistStor::Params params;
278 MockInfo info(&params);
279 Stats::DistStor stor(&info);
280 ASSERT_DEATH(stor.sample(val, num_samples), ".+");
281 }
282
283 /**
284 * Test whether zero is correctly set as the reset value. The test order is
285 * to check if it is initially zero on creation, then it is made non zero,
286 * and finally reset to zero.
287 */
288 TEST(StatsDistStorTest, ZeroReset)
289 {
290 Stats::DistStor::Params params;
291 params.bucket_size = 10;
292 MockInfo info(&params);
293 Stats::DistStor stor(&info);
294 Stats::Counter val = 10;
295 Stats::Counter num_samples = 5;
296
297 ASSERT_TRUE(stor.zero());
298
299 stor.reset(&info);
300 stor.sample(val, num_samples);
301 ASSERT_FALSE(stor.zero());
302
303 stor.reset(&info);
304 ASSERT_TRUE(stor.zero());
305 }
306
307 /**
308 * Test that the size of this storage is equal to its counters vector's size,
309 * and that after it has been set, nothing can modify it.
310 */
311 TEST(StatsDistStorTest, Size)
312 {
313 Stats::Counter val = 10;
314 Stats::Counter num_samples = 5;
315 Stats::Counter size = 20;
316 Stats::DistData data;
317
318 Stats::DistStor::Params params;
319 params.bucket_size = 1;
320 params.buckets = size;
321 MockInfo info(&params);
322 Stats::DistStor stor(&info);
323
324 ASSERT_EQ(stor.size(), size);
325 stor.sample(val, num_samples);
326 ASSERT_EQ(stor.size(), size);
327 stor.prepare(&info, data);
328 ASSERT_EQ(stor.size(), size);
329 stor.reset(&info);
330 ASSERT_EQ(stor.size(), size);
331 stor.zero();
332 ASSERT_EQ(stor.size(), size);
333 }
334
335 /**
336 * Compare both dist datas to see if their contents match.
337 *
338 * @param data The data being tested.
339 * @param expected_data The ground truth.
340 * @param no_log Whether log should not be compared.
341 */
342 void
343 checkExpectedDistData(const Stats::DistData& data,
344 const Stats::DistData& expected_data, bool no_log = true)
345 {
346 ASSERT_EQ(data.type, expected_data.type);
347 ASSERT_EQ(data.min, expected_data.min);
348 ASSERT_EQ(data.max, expected_data.max);
349 ASSERT_EQ(data.bucket_size, expected_data.bucket_size);
350 ASSERT_EQ(data.min_val, expected_data.min_val);
351 ASSERT_EQ(data.max_val, expected_data.max_val);
352 ASSERT_EQ(data.sum, expected_data.sum);
353 ASSERT_EQ(data.squares, expected_data.squares);
354 if (!no_log) {
355 ASSERT_EQ(data.logs, expected_data.logs);
356 }
357 ASSERT_EQ(data.samples, expected_data.samples);
358 ASSERT_EQ(data.cvec.size(), expected_data.cvec.size());
359 for (int i = 0; i < expected_data.cvec.size(); i++) {
360 ASSERT_EQ(data.cvec[i], expected_data.cvec[i]);
361 }
362 }
363
364 /**
365 * Auxiliary function that finishes preparing the DistStor's expected values,
366 * perform the calls to the storage's sample, and compares the expected data.
367 *
368 * @param params The params containing the number of buckets.
369 * @param values The value-num_sample pairs to be sampled.
370 * @param num_values Number of values in the values array.
371 * @param expected_data Expected data after sampling, with the following values
372 * setup to the expected values: bucket_size, min, max_val, and cvec.
373 */
374 void
375 prepareCheckDistStor(Stats::DistStor::Params& params, ValueSamples* values,
376 int num_values, Stats::DistData& expected_data)
377 {
378 MockInfo info(&params);
379 Stats::DistStor stor(&info);
380
381 Stats::Counter val;
382 Stats::DistData data;
383
384 expected_data.min = params.min;
385 expected_data.max = params.max;
386 expected_data.sum = 0;
387 expected_data.squares = 0;
388 expected_data.logs = 0;
389 expected_data.samples = 0;
390
391 // Populate storage with more data
392 for (int i = 0; i < num_values; i++) {
393 stor.sample(values[i].value, values[i].numSamples);
394
395 val = values[i].value * values[i].numSamples;
396 expected_data.sum += val;
397 expected_data.squares += values[i].value * val;
398 expected_data.samples += values[i].numSamples;
399 }
400 stor.prepare(&info, data);
401
402 // DistStor does not use log
403 checkExpectedDistData(data, expected_data, true);
404 }
405
406 /** Test setting and getting value from storage. */
407 TEST(StatsDistStorTest, SamplePrepareSingle)
408 {
409 Stats::DistStor::Params params;
410 params.min = 0;
411 params.max = 99;
412 params.bucket_size = 5;
413 params.buckets = 20;
414
415 ValueSamples values[] = {{10, 5}};
416 int num_values = sizeof(values) / sizeof(ValueSamples);
417
418 // Setup expected data
419 Stats::DistData expected_data;
420 expected_data.type = Stats::Dist;
421 expected_data.bucket_size = params.bucket_size;
422 expected_data.underflow = 0;
423 expected_data.overflow = 0;
424 expected_data.min_val = 10;
425 expected_data.max_val = 10;
426 expected_data.cvec.clear();
427 expected_data.cvec.resize(params.buckets);
428 expected_data.cvec[2] = 5;
429
430 prepareCheckDistStor(params, values, num_values, expected_data);
431 }
432
433 /** Test setting and getting value from storage with multiple values. */
434 TEST(StatsDistStorTest, SamplePrepareMultiple)
435 {
436 Stats::DistStor::Params params;
437 params.min = 0;
438 params.max = 99;
439 params.bucket_size = 5;
440 params.buckets = 20;
441
442 // There are 20 buckets: [0,5[, [5,10[, [10,15[, ..., [95,100[.
443 // We test that values that pass the maximum bucket value (1234, 12345678,
444 // 100) are added to the overflow counter, and that the ones below the
445 // minimum bucket value (-10, -1) are added to the underflow counter.
446 // The extremes (0 and 99) are added to check if they go to the first and
447 // last buckets.
448 ValueSamples values[] = {{10, 5}, {1234, 2}, {12345678, 99}, {-10, 4},
449 {17, 17}, {52, 63}, {18, 11}, {0, 1}, {99, 15}, {-1, 200}, {100, 50}};
450 int num_values = sizeof(values) / sizeof(ValueSamples);
451
452 // Setup variables that should always match params' values
453 Stats::DistData expected_data;
454 expected_data.type = Stats::Dist;
455 expected_data.min_val = -10;
456 expected_data.max_val = 12345678;
457 expected_data.bucket_size = params.bucket_size;
458 expected_data.underflow = 204;
459 expected_data.overflow = 151;
460 expected_data.sum = 0;
461 expected_data.squares = 0;
462 expected_data.samples = 0;
463 expected_data.cvec.clear();
464 expected_data.cvec.resize(params.buckets);
465 expected_data.cvec[0] = 1;
466 expected_data.cvec[2] = 5;
467 expected_data.cvec[3] = 17+11;
468 expected_data.cvec[10] = 63;
469 expected_data.cvec[19] = 15;
470
471 prepareCheckDistStor(params, values, num_values, expected_data);
472 }
473
474 /** Test resetting storage. */
475 TEST(StatsDistStorTest, Reset)
476 {
477 Stats::DistStor::Params params;
478 params.min = 0;
479 params.max = 99;
480 params.bucket_size = 5;
481 params.buckets = 20;
482 MockInfo info(&params);
483 Stats::DistStor stor(&info);
484
485 // Populate storage with random samples
486 ValueSamples values[] = {{10, 5}, {1234, 2}, {12345678, 99}, {-10, 4},
487 {17, 17}, {52, 63}, {18, 11}, {0, 1}, {99, 15}, {-1, 200}, {100, 50}};
488 int num_values = sizeof(values) / sizeof(ValueSamples);
489 for (int i = 0; i < num_values; i++) {
490 stor.sample(values[i].value, values[i].numSamples);
491 }
492
493 // Reset storage, and make sure all data has been cleared
494 stor.reset(&info);
495 Stats::DistData data;
496 stor.prepare(&info, data);
497
498 Stats::DistData expected_data;
499 expected_data.type = Stats::Dist;
500 expected_data.bucket_size = params.bucket_size;
501 expected_data.underflow = 0;
502 expected_data.overflow = 0;
503 expected_data.min = params.min;
504 expected_data.max = params.max;
505 expected_data.min_val = 0;
506 expected_data.max_val = 0;
507 expected_data.sum = 0;
508 expected_data.squares = 0;
509 expected_data.samples = 0;
510 expected_data.cvec.clear();
511 expected_data.cvec.resize(params.buckets);
512
513 checkExpectedDistData(data, expected_data, true);
514 }
515
516 /**
517 * Test that an assertion is thrown when no bucket size is provided before
518 * sampling.
519 */
520 TEST(StatsHistStorDeathTest, NoBucketSize)
521 {
522 Stats::Counter val = 10;
523 Stats::Counter num_samples = 5;
524
525 // If no bucket size is specified, it is 0 by default
526 Stats::HistStor::Params params;
527 MockInfo info(&params);
528 Stats::HistStor stor(&info);
529 ASSERT_DEATH(stor.sample(val, num_samples), ".+");
530 }
531
532 /**
533 * Test whether zero is correctly set as the reset value. The test order is
534 * to check if it is initially zero on creation, then it is made non zero,
535 * and finally reset to zero.
536 */
537 TEST(StatsHistStorTest, ZeroReset)
538 {
539 Stats::HistStor::Params params;
540 params.buckets = 10;
541 MockInfo info(&params);
542 Stats::HistStor stor(&info);
543 Stats::Counter val = 10;
544 Stats::Counter num_samples = 5;
545
546 ASSERT_TRUE(stor.zero());
547
548 stor.reset(&info);
549 stor.sample(val, num_samples);
550 ASSERT_FALSE(stor.zero());
551
552 stor.reset(&info);
553 ASSERT_TRUE(stor.zero());
554 }
555
556 /**
557 * Test that the size of this storage is equal to its counters vector's size,
558 * and that after it has been set, nothing can modify it.
559 */
560 TEST(StatsHistStorTest, Size)
561 {
562 Stats::Counter val = 10;
563 Stats::Counter num_samples = 5;
564 Stats::DistData data;
565 Stats::size_type sizes[] = {2, 10, 1234};
566
567 // If no bucket size is specified, it is 0 by default
568 {
569 Stats::HistStor::Params params;
570 MockInfo info(&params);
571 Stats::HistStor stor(&info);
572
573 ASSERT_EQ(stor.size(), 0);
574 stor.prepare(&info, data);
575 ASSERT_EQ(stor.size(), 0);
576 stor.reset(&info);
577 ASSERT_EQ(stor.size(), 0);
578 stor.zero();
579 ASSERT_EQ(stor.size(), 0);
580 }
581
582 for (int i = 0; i < (sizeof(sizes) / sizeof(Stats::size_type)); i++) {
583 Stats::HistStor::Params params;
584 params.buckets = sizes[i];
585 MockInfo info(&params);
586 Stats::HistStor stor(&info);
587
588 ASSERT_EQ(stor.size(), sizes[i]);
589 stor.sample(val, num_samples);
590 ASSERT_EQ(stor.size(), sizes[i]);
591 stor.prepare(&info, data);
592 ASSERT_EQ(stor.size(), sizes[i]);
593 stor.reset(&info);
594 ASSERT_EQ(stor.size(), sizes[i]);
595 stor.zero();
596 ASSERT_EQ(stor.size(), sizes[i]);
597 }
598 }
599
600 /**
601 * Auxiliary function that finishes preparing the HistStor's expected values,
602 * perform the calls to the storage's sample, and compares the expected data.
603 *
604 * @param params The params containing the number of buckets.
605 * @param values The value-num_sample pairs to be sampled.
606 * @param num_values Number of values in the values array.
607 * @param expected_data Expected data after sampling, with the following values
608 * setup to the expected values: bucket_size, min, max_val, and cvec.
609 */
610 void
611 prepareCheckHistStor(Stats::HistStor::Params& params, ValueSamples* values,
612 int num_values, Stats::DistData& expected_data)
613 {
614 MockInfo info(&params);
615 Stats::HistStor stor(&info);
616
617 Stats::Counter val;
618 Stats::DistData data;
619 bool no_log = false;
620
621 expected_data.min_val = expected_data.min;
622 expected_data.max = expected_data.max_val + expected_data.bucket_size - 1;
623 expected_data.sum = 0;
624 expected_data.squares = 0;
625 expected_data.logs = 0;
626 expected_data.samples = 0;
627
628 // Populate storage with more data
629 for (int i = 0; i < num_values; i++) {
630 stor.sample(values[i].value, values[i].numSamples);
631
632 val = values[i].value * values[i].numSamples;
633 expected_data.sum += val;
634 expected_data.squares += values[i].value * val;
635 if (values[i].value < 0) {
636 // Negative values don't have log, so mark log check to be skipped
637 no_log = true;
638 } else {
639 expected_data.logs +=
640 std::log(values[i].value) * values[i].numSamples;
641 }
642 expected_data.samples += values[i].numSamples;
643 }
644 stor.prepare(&info, data);
645 checkExpectedDistData(data, expected_data, no_log);
646 }
647
648 /**
649 * Test samples that fit in the initial buckets, and therefore do not need
650 * to grow up.
651 */
652 TEST(StatsHistStorTest, SamplePrepareFit)
653 {
654 Stats::HistStor::Params params;
655 params.buckets = 4;
656
657 // Setup expected data for the hand-carved values given. The final buckets
658 // will be divided at:
659 // Bkt0=[0,1[ , Bkt1=[1,2[, Bkt2=[2,3[, Bkt3=[3,4[
660 ValueSamples values[] = {{0, 5}, {1, 2}, {2, 99}, {3, 4}};
661 const int num_values = sizeof(values) / sizeof(ValueSamples);
662 Stats::DistData expected_data;
663 expected_data.type = Stats::Hist;
664 expected_data.bucket_size = 1;
665 expected_data.min = 0;
666 expected_data.max_val = 3;
667 expected_data.cvec.clear();
668 expected_data.cvec.resize(params.buckets);
669 expected_data.cvec[0] = 5;
670 expected_data.cvec[1] = 2;
671 expected_data.cvec[2] = 99;
672 expected_data.cvec[3] = 4;
673
674 prepareCheckHistStor(params, values, num_values, expected_data);
675 }
676
677 /**
678 * Test samples that do not fit in the initial buckets, and therefore have
679 * to grow up once.
680 */
681 TEST(StatsHistStorTest, SamplePrepareSingleGrowUp)
682 {
683 Stats::HistStor::Params params;
684 params.buckets = 4;
685
686 // Setup expected data for the hand-carved values given. Since there
687 // are four buckets, and the highest value is 4, the bucket size will
688 // grow to be 2. The final buckets will be divided at:
689 // Bkt0=[0,2[ , Bkt1=[2,4[, Bkt2=[4,6[, Bkt3=[6,8[
690 ValueSamples values[] = {{0, 5}, {1, 2}, {2, 99}, {4, 4}};
691 const int num_values = sizeof(values) / sizeof(ValueSamples);
692 Stats::DistData expected_data;
693 expected_data.type = Stats::Hist;
694 expected_data.bucket_size = 2;
695 expected_data.min = 0;
696 expected_data.max_val = 6;
697 expected_data.cvec.clear();
698 expected_data.cvec.resize(params.buckets);
699 expected_data.cvec[0] = 5+2;
700 expected_data.cvec[1] = 99;
701 expected_data.cvec[2] = 4;
702 expected_data.cvec[3] = 0;
703
704 prepareCheckHistStor(params, values, num_values, expected_data);
705 }
706
707 /**
708 * Test samples that do not fit in the initial buckets, and therefore have
709 * to grow up a few times.
710 */
711 TEST(StatsHistStorTest, SamplePrepareMultipleGrowUp)
712 {
713 Stats::HistStor::Params params;
714 params.buckets = 4;
715
716 // Setup expected data for the hand-carved values given. Since there
717 // are four buckets, and the highest value is 4, the bucket size will
718 // grow thrice to become 8. The final buckets will be divided at:
719 // Bkt0=[0,8[ , Bkt1=[8,16[, Bkt2=[16,24[, Bkt3=[24,32[
720 ValueSamples values[] = {{0, 5}, {1, 2}, {2, 99}, {16, 4}};
721 const int num_values = sizeof(values) / sizeof(ValueSamples);
722 Stats::DistData expected_data;
723 expected_data.type = Stats::Hist;
724 expected_data.bucket_size = 8;
725 expected_data.min = 0;
726 expected_data.max_val = 24;
727 expected_data.cvec.clear();
728 expected_data.cvec.resize(params.buckets);
729 expected_data.cvec[0] = 5+2+99;
730 expected_data.cvec[1] = 0;
731 expected_data.cvec[2] = 4;
732 expected_data.cvec[3] = 0;
733
734 prepareCheckHistStor(params, values, num_values, expected_data);
735 }
736
737 /**
738 * Test samples that have a negative value, and therefore do not fit in the
739 * initial buckets. Since this involves using negative values, the logs
740 * become irrelevant.
741 */
742 TEST(StatsHistStorTest, SamplePrepareGrowDownOddBuckets)
743 {
744 Stats::HistStor::Params params;
745 params.buckets = 5;
746
747 // Setup expected data for the hand-carved values given. Since there
748 // is a negative value, the min bucket will change, and the bucket size
749 // will grow to be 2. The final buckets will be divided at:
750 // Bkt0=[-4,-2[ , Bkt1=[-2,-0[, Bkt2=[0,2[, Bkt3=[2,4[, Bkt4=[4,6[
751 ValueSamples values[] =
752 {{0, 5}, {1, 2}, {2, 99}, {3, 12}, {4, 33}, {-1, 4}};
753 const int num_values = sizeof(values) / sizeof(ValueSamples);
754 Stats::DistData expected_data;
755 expected_data.type = Stats::Hist;
756 expected_data.bucket_size = 2;
757 expected_data.min = -4;
758 expected_data.max_val = 4;
759 expected_data.cvec.clear();
760 expected_data.cvec.resize(params.buckets);
761 expected_data.cvec[0] = 0;
762 expected_data.cvec[1] = 4;
763 expected_data.cvec[2] = 5+2;
764 expected_data.cvec[3] = 99+12;
765 expected_data.cvec[4] = 33;
766
767 prepareCheckHistStor(params, values, num_values, expected_data);
768 }
769
770 /**
771 * Test samples that have a negative value, and therefore do not fit in the
772 * initial buckets. Since this involves using negative values, the logs
773 * become irrelevant.
774 */
775 TEST(StatsHistStorTest, SamplePrepareGrowDownEvenBuckets)
776 {
777 Stats::HistStor::Params params;
778 params.buckets = 4;
779
780 // Setup expected data for the hand-carved values given. Since there
781 // is a negative value, the min bucket will change, and the bucket size
782 // will grow to be 2. The final buckets will be divided at:
783 // Bkt0=[-4,-2[ , Bkt1=[-2,0[, Bkt2=[0,2[, Bkt3=[2,4[
784 ValueSamples values[] = {{0, 5}, {1, 2}, {2, 99}, {-1, 4}};
785 const int num_values = sizeof(values) / sizeof(ValueSamples);
786 Stats::DistData expected_data;
787 expected_data.type = Stats::Hist;
788 expected_data.bucket_size = 2;
789 expected_data.min = -4;
790 expected_data.max_val = 2;
791 expected_data.cvec.clear();
792 expected_data.cvec.resize(params.buckets);
793 expected_data.cvec[0] = 0;
794 expected_data.cvec[1] = 4;
795 expected_data.cvec[2] = 5+2;
796 expected_data.cvec[3] = 99;
797
798 prepareCheckHistStor(params, values, num_values, expected_data);
799 }
800
801 /**
802 * Test samples that have one low negative value, and therefore do not fit
803 * in the initial buckets and have to grow down a few times. Since this
804 * involves using negative values, the logs become irrelevant.
805 */
806 TEST(StatsHistStorTest, SamplePrepareGrowDownGrowOutOddBuckets)
807 {
808 Stats::HistStor::Params params;
809 params.buckets = 5;
810
811 // Setup expected data for the hand-carved values given. Since there
812 // is a negative value, the min bucket will change, and the bucket size
813 // will grow to be 8. The final buckets will be divided at:
814 // Bkt0=[-16,-8[ , Bkt1=[-8,0[, Bkt2=[0,8[, Bkt3=[8,16[, Bkt4=[16,24[
815 ValueSamples values[] =
816 {{0, 5}, {1, 2}, {2, 99}, {3, 12}, {4, 33}, {-12, 4}};
817 const int num_values = sizeof(values) / sizeof(ValueSamples);
818 Stats::DistData expected_data;
819 expected_data.type = Stats::Hist;
820 expected_data.bucket_size = 8;
821 expected_data.min = -16;
822 expected_data.max_val = 16;
823 expected_data.cvec.clear();
824 expected_data.cvec.resize(params.buckets);
825 expected_data.cvec[0] = 4;
826 expected_data.cvec[1] = 0;
827 expected_data.cvec[2] = 5+2+99+12+33;
828 expected_data.cvec[3] = 0;
829 expected_data.cvec[4] = 0;
830
831 prepareCheckHistStor(params, values, num_values, expected_data);
832 }
833
834 /**
835 * Test samples that have one low negative value, and therefore do not fit
836 * in the initial buckets and have to grow down a few times. Since this
837 * involves using negative values, the logs become irrelevant.
838 */
839 TEST(StatsHistStorTest, SamplePrepareGrowDownGrowOutEvenBuckets)
840 {
841 Stats::HistStor::Params params;
842 params.buckets = 4;
843
844 // Setup expected data for the hand-carved values given. Since there
845 // is a negative value, the min bucket will change, and the bucket size
846 // will grow to be 8. The final buckets will be divided at:
847 // Bkt0=[-16,-8[ , Bkt1=[-8,0[, Bkt2=[0,8[, Bkt3=[8,16[
848 ValueSamples values[] =
849 {{0, 5}, {1, 2}, {2, 99}, {3, 12}, {-12, 4}};
850 const int num_values = sizeof(values) / sizeof(ValueSamples);
851 Stats::DistData expected_data;
852 expected_data.type = Stats::Hist;
853 expected_data.bucket_size = 8;
854 expected_data.min = -16;
855 expected_data.max_val = 8;
856 expected_data.cvec.clear();
857 expected_data.cvec.resize(params.buckets);
858 expected_data.cvec[0] = 4;
859 expected_data.cvec[1] = 0;
860 expected_data.cvec[2] = 5+2+99+12;
861 expected_data.cvec[3] = 0;
862
863 prepareCheckHistStor(params, values, num_values, expected_data);
864 }
865
866 /**
867 * Test a complex sample set with negative values, and therefore multiple
868 * grows will happen. Since this involves using negative values, the logs
869 * become irrelevant.
870 */
871 TEST(StatsHistStorTest, SamplePrepareMultipleGrowOddBuckets)
872 {
873 Stats::HistStor::Params params;
874 params.buckets = 5;
875
876 // Setup expected data for the hand-carved values given. This adds quite
877 // a few positive and negative samples, and the bucket size will grow to
878 // be 64. The final buckets will be divided at:
879 // Bkt0=[-128,-64[ , Bkt1=[-64,0[, Bkt2=[0,64[, Bkt3=[64,128[,
880 // Bkt4=[128,192[
881 ValueSamples values[] =
882 {{0, 5}, {7, 2}, {31, 99}, {-8, 12}, {127, 4}, {-120, 53}, {-50, 1}};
883 const int num_values = sizeof(values) / sizeof(ValueSamples);
884 Stats::DistData expected_data;
885 expected_data.type = Stats::Hist;
886 expected_data.bucket_size = 64;
887 expected_data.min = -128;
888 expected_data.max_val = 128;
889 expected_data.cvec.clear();
890 expected_data.cvec.resize(params.buckets);
891 expected_data.cvec[0] = 53;
892 expected_data.cvec[1] = 12+1;
893 expected_data.cvec[2] = 5+2+99;
894 expected_data.cvec[3] = 4;
895 expected_data.cvec[4] = 0;
896
897 prepareCheckHistStor(params, values, num_values, expected_data);
898 }
899
900 /**
901 * Test a complex sample set with negative values, and therefore multiple
902 * grows will happen. Since this involves using negative values, the logs
903 * become irrelevant.
904 */
905 TEST(StatsHistStorTest, SamplePrepareMultipleGrowEvenBuckets)
906 {
907 Stats::HistStor::Params params;
908 params.buckets = 4;
909
910 // Setup expected data for the hand-carved values given. This adds quite
911 // a few positive and negative samples, and the bucket size will grow to
912 // be 64. The final buckets will be divided at:
913 // Bkt0=[-128,-64[ , Bkt1=[-64,0[, Bkt2=[0,64[, Bkt3=[64,128[
914 ValueSamples values[] =
915 {{0, 5}, {7, 2}, {31, 99}, {-8, 12}, {127, 4}, {-120, 53}, {-50, 1}};
916 const int num_values = sizeof(values) / sizeof(ValueSamples);
917 Stats::DistData expected_data;
918 expected_data.type = Stats::Hist;
919 expected_data.bucket_size = 64;
920 expected_data.min = -128;
921 expected_data.max_val = 64;
922 expected_data.cvec.clear();
923 expected_data.cvec.resize(params.buckets);
924 expected_data.cvec[0] = 53;
925 expected_data.cvec[1] = 12+1;
926 expected_data.cvec[2] = 5+2+99;
927 expected_data.cvec[3] = 4;
928
929 prepareCheckHistStor(params, values, num_values, expected_data);
930 }
931
932 /** Test resetting storage. */
933 TEST(StatsHistStorTest, Reset)
934 {
935 Stats::HistStor::Params params;
936 params.buckets = 4;
937 MockInfo info(&params);
938 Stats::HistStor stor(&info);
939
940 // Setup expected data for the hand-carved values given. This adds quite
941 // a few positive and negative samples, and the bucket size will grow to
942 // be 64. The final buckets will be divided at:
943 // Bkt0=[-128,-64[ , Bkt1=[-64,0[, Bkt2=[0,64[, Bkt3=[64,128[
944 ValueSamples values[] =
945 {{0, 5}, {7, 2}, {31, 99}, {-8, 12}, {127, 4}, {-120, 53}, {-50, 1}};
946 const int num_values = sizeof(values) / sizeof(ValueSamples);
947 for (int i = 0; i < num_values; i++) {
948 stor.sample(values[i].value, values[i].numSamples);
949 }
950
951 // Reset storage, and make sure all data has been cleared:
952 // Bkt0=[0,1[ , Bkt1=[1,2[, Bkt2=[2,3[, Bkt3=[3,4[
953 stor.reset(&info);
954 Stats::DistData expected_data;
955 expected_data.type = Stats::Hist;
956 expected_data.bucket_size = 1;
957 expected_data.min = 0;
958 expected_data.max_val = 3;
959 expected_data.cvec.clear();
960 expected_data.cvec.resize(params.buckets);
961 prepareCheckHistStor(params, values, 0, expected_data);
962 }
963
964 /** Test whether adding storages with different sizes triggers an assertion. */
965 TEST(StatsHistStorDeathTest, AddDifferentSize)
966 {
967 Stats::HistStor::Params params;
968 params.buckets = 4;
969 MockInfo info(&params);
970 Stats::HistStor stor(&info);
971
972 Stats::HistStor::Params params2;
973 params2.buckets = 5;
974 MockInfo info2(&params2);
975 Stats::HistStor stor2(&info2);
976
977 ASSERT_DEATH(stor.add(&stor2), ".+");
978 }
979
980 /** Test whether adding storages with different min triggers an assertion. */
981 TEST(StatsHistStorDeathTest, AddDifferentMin)
982 {
983 Stats::HistStor::Params params;
984 params.buckets = 4;
985 MockInfo info(&params);
986 Stats::HistStor stor(&info);
987 stor.sample(-1, 3);
988
989 // On creation, the storage's min is zero
990 Stats::HistStor::Params params2;
991 params2.buckets = 4;
992 MockInfo info2(&params2);
993 Stats::HistStor stor2(&info2);
994
995 ASSERT_DEATH(stor.add(&stor2), ".+");
996 }
997
998 /** Test merging two histograms. */
999 TEST(StatsHistStorTest, Add)
1000 {
1001 Stats::HistStor::Params params;
1002 params.buckets = 4;
1003 MockInfo info(&params);
1004
1005 // Setup first storage. Buckets are:
1006 // Bkt0=[0,16[, Bkt1=[16,32[, Bkt2=[32,48[, Bkt3=[58,64[
1007 Stats::HistStor stor(&info);
1008 ValueSamples values[] = {{0, 5}, {3, 2}, {20, 37}, {32, 18}};
1009 int num_values = sizeof(values) / sizeof(ValueSamples);
1010 for (int i = 0; i < num_values; i++) {
1011 stor.sample(values[i].value, values[i].numSamples);
1012 }
1013 Stats::DistData data;
1014 stor.prepare(&info, data);
1015
1016 // Setup second storage. Buckets are:
1017 // Bkt0=[0,32[, Bkt1=[32,64[, Bkt2=[64,96[, Bkt3=[96,128[
1018 Stats::HistStor stor2(&info);
1019 ValueSamples values2[] = {{10, 10}, {0, 1}, {80, 4}, {17, 100}, {95, 79}};
1020 int num_values2 = sizeof(values2) / sizeof(ValueSamples);
1021 for (int i = 0; i < num_values2; i++) {
1022 stor2.sample(values2[i].value, values2[i].numSamples);
1023 }
1024 Stats::DistData data2;
1025 stor2.prepare(&info, data2);
1026
1027 // Perform the merge
1028 stor.add(&stor2);
1029 Stats::DistData merge_data;
1030 stor.prepare(&info, merge_data);
1031
1032 // Setup expected data. Buckets are:
1033 // Bkt0=[0,32[, Bkt1=[32,64[, Bkt2=[64,96[, Bkt3=[96,128[
1034 Stats::DistData expected_data;
1035 expected_data.type = Stats::Hist;
1036 expected_data.bucket_size = 32;
1037 expected_data.min = 0;
1038 expected_data.max = 127;
1039 expected_data.min_val = 0;
1040 expected_data.max_val = 96;
1041 expected_data.cvec.clear();
1042 expected_data.cvec.resize(params.buckets);
1043 expected_data.cvec[0] = 5+2+37+10+1+100;
1044 expected_data.cvec[1] = 18;
1045 expected_data.cvec[2] = 4+79;
1046 expected_data.cvec[3] = 0;
1047 expected_data.sum = data.sum + data2.sum;
1048 expected_data.squares = data.squares + data2.squares;
1049 expected_data.logs = data.squares + data2.logs;
1050 expected_data.samples = data.samples + data2.samples;
1051
1052 // Compare results
1053 checkExpectedDistData(merge_data, expected_data, false);
1054 }
1055
1056 /**
1057 * Test whether zero is correctly set as the reset value. The test order is
1058 * to check if it is initially zero on creation, then it is made non zero,
1059 * and finally reset to zero.
1060 */
1061 TEST(StatsSampleStorTest, ZeroReset)
1062 {
1063 Stats::SampleStor stor(nullptr);
1064 Stats::Counter val = 10;
1065 Stats::Counter num_samples = 5;
1066
1067 ASSERT_TRUE(stor.zero());
1068
1069 stor.reset(nullptr);
1070 stor.sample(val, num_samples);
1071 ASSERT_FALSE(stor.zero());
1072
1073 stor.reset(nullptr);
1074 ASSERT_TRUE(stor.zero());
1075 }
1076
1077 /** Test setting and getting value from storage. */
1078 TEST(StatsSampleStorTest, SamplePrepare)
1079 {
1080 Stats::SampleStor stor(nullptr);
1081 ValueSamples values[] = {{10, 5}, {1234, 2}, {0xFFFFFFFF, 18}};
1082 int num_values = sizeof(values) / sizeof(ValueSamples);
1083 Stats::Counter val;
1084 Stats::DistData data;
1085 Stats::DistData expected_data;
1086 Stats::DistParams params(Stats::Deviation);
1087 MockInfo info(&params);
1088
1089 // Simple test with one value being sampled
1090 stor.sample(values[0].value, values[0].numSamples);
1091 stor.prepare(&info, data);
1092 val = values[0].value * values[0].numSamples;
1093 expected_data.type = Stats::Deviation;
1094 expected_data.sum = val;
1095 expected_data.squares = values[0].value * val;
1096 expected_data.samples = values[0].numSamples;
1097 ASSERT_EQ(data.type, expected_data.type);
1098 ASSERT_EQ(data.sum, expected_data.sum);
1099 ASSERT_EQ(data.squares, expected_data.squares);
1100 ASSERT_EQ(data.samples, expected_data.samples);
1101
1102 // Reset storage, and make sure all data has been cleared
1103 expected_data.sum = 0;
1104 expected_data.squares = 0;
1105 expected_data.samples = 0;
1106 stor.reset(nullptr);
1107 stor.prepare(&info, data);
1108 ASSERT_EQ(data.type, expected_data.type);
1109 ASSERT_EQ(data.sum, expected_data.sum);
1110 ASSERT_EQ(data.squares, expected_data.squares);
1111 ASSERT_EQ(data.samples, expected_data.samples);
1112
1113 // Populate storage with more data
1114 for (int i = 0; i < num_values; i++) {
1115 stor.sample(values[i].value, values[i].numSamples);
1116
1117 val = values[i].value * values[i].numSamples;
1118 expected_data.sum += val;
1119 expected_data.squares += values[i].value * val;
1120 expected_data.samples += values[i].numSamples;
1121 }
1122 stor.prepare(&info, data);
1123 ASSERT_EQ(data.type, expected_data.type);
1124 ASSERT_EQ(data.sum, expected_data.sum);
1125 ASSERT_EQ(data.squares, expected_data.squares);
1126 ASSERT_EQ(data.samples, expected_data.samples);
1127 }
1128
1129 /** The size is always 1, no matter which functions have been called. */
1130 TEST(StatsSampleStorTest, Size)
1131 {
1132 Stats::SampleStor stor(nullptr);
1133 Stats::Counter val = 10;
1134 Stats::Counter num_samples = 5;
1135 Stats::DistData data;
1136 Stats::DistParams params(Stats::Deviation);
1137 MockInfo info(&params);
1138
1139 ASSERT_EQ(stor.size(), 1);
1140 stor.sample(val, num_samples);
1141 ASSERT_EQ(stor.size(), 1);
1142 stor.prepare(&info, data);
1143 ASSERT_EQ(stor.size(), 1);
1144 stor.reset(nullptr);
1145 ASSERT_EQ(stor.size(), 1);
1146 stor.zero();
1147 ASSERT_EQ(stor.size(), 1);
1148 }
1149
1150 /**
1151 * Test whether zero is correctly set as the reset value. The test order is
1152 * to check if it is initially zero on creation, then it is made non zero,
1153 * and finally reset to zero.
1154 */
1155 TEST(StatsAvgSampleStorTest, ZeroReset)
1156 {
1157 Stats::AvgSampleStor stor(nullptr);
1158 Stats::Counter val = 10;
1159 Stats::Counter num_samples = 5;
1160
1161 ASSERT_TRUE(stor.zero());
1162
1163 stor.reset(nullptr);
1164 stor.sample(val, num_samples);
1165 ASSERT_FALSE(stor.zero());
1166
1167 stor.reset(nullptr);
1168 ASSERT_TRUE(stor.zero());
1169 }
1170
1171 /** Test setting and getting value from storage. */
1172 TEST(StatsAvgSampleStorTest, SamplePrepare)
1173 {
1174 Stats::AvgSampleStor stor(nullptr);
1175 ValueSamples values[] = {{10, 5}, {1234, 2}, {0xFFFFFFFF, 18}};
1176 int num_values = sizeof(values) / sizeof(ValueSamples);
1177 Stats::Counter val;
1178 Stats::DistData data;
1179 Stats::DistData expected_data;
1180 Stats::DistParams params(Stats::Deviation);
1181 MockInfo info(&params);
1182
1183 // Simple test with one value being sampled
1184 stor.sample(values[0].value, values[0].numSamples);
1185 stor.prepare(&info, data);
1186 val = values[0].value * values[0].numSamples;
1187 expected_data.type = Stats::Deviation;
1188 expected_data.sum = val;
1189 expected_data.squares = values[0].value * val;
1190 ASSERT_EQ(data.type, expected_data.type);
1191 ASSERT_EQ(data.sum, expected_data.sum);
1192 ASSERT_EQ(data.squares, expected_data.squares);
1193 ASSERT_EQ(data.samples, curTick());
1194
1195 increaseTick();
1196
1197 // Reset storage, and make sure all data has been cleared
1198 expected_data.sum = 0;
1199 expected_data.squares = 0;
1200 stor.reset(nullptr);
1201 stor.prepare(&info, data);
1202 ASSERT_EQ(data.type, expected_data.type);
1203 ASSERT_EQ(data.sum, expected_data.sum);
1204 ASSERT_EQ(data.squares, expected_data.squares);
1205 ASSERT_EQ(data.samples, curTick());
1206
1207 increaseTick();
1208
1209 // Populate storage with more data
1210 for (int i = 0; i < num_values; i++) {
1211 stor.sample(values[i].value, values[i].numSamples);
1212
1213 val = values[i].value * values[i].numSamples;
1214 expected_data.sum += val;
1215 expected_data.squares += values[i].value * val;
1216 }
1217 stor.prepare(&info, data);
1218 ASSERT_EQ(data.type, expected_data.type);
1219 ASSERT_EQ(data.sum, expected_data.sum);
1220 ASSERT_EQ(data.squares, expected_data.squares);
1221 ASSERT_EQ(data.samples, curTick());
1222 }
1223
1224 /** The size is always 1, no matter which functions have been called. */
1225 TEST(StatsAvgSampleStorTest, Size)
1226 {
1227 Stats::AvgSampleStor stor(nullptr);
1228 Stats::Counter val = 10;
1229 Stats::Counter num_samples = 5;
1230 Stats::DistData data;
1231 Stats::DistParams params(Stats::Deviation);
1232 MockInfo info(&params);
1233
1234 ASSERT_EQ(stor.size(), 1);
1235 stor.sample(val, num_samples);
1236 ASSERT_EQ(stor.size(), 1);
1237 stor.prepare(&info, data);
1238 ASSERT_EQ(stor.size(), 1);
1239 stor.reset(nullptr);
1240 ASSERT_EQ(stor.size(), 1);
1241 stor.zero();
1242 ASSERT_EQ(stor.size(), 1);
1243 }
1244
1245 /**
1246 * Test whether zero is correctly set as the reset value. The test order is
1247 * to check if it is initially zero on creation, then it is made non zero,
1248 * and finally reset to zero.
1249 */
1250 TEST(StatsSparseHistStorTest, ZeroReset)
1251 {
1252 Stats::SparseHistStor stor(nullptr);
1253 Stats::Counter val = 10;
1254 Stats::Counter num_samples = 5;
1255
1256 ASSERT_TRUE(stor.zero());
1257
1258 stor.reset(nullptr);
1259 stor.sample(val, num_samples);
1260 ASSERT_FALSE(stor.zero());
1261
1262 stor.reset(nullptr);
1263 ASSERT_TRUE(stor.zero());
1264 }
1265
1266 /** Test setting and getting value from storage. */
1267 TEST(StatsSparseHistStorTest, SamplePrepare)
1268 {
1269 Stats::SparseHistStor stor(nullptr);
1270 ValueSamples values[] = {{10, 5}, {1234, 2}, {0xFFFFFFFF, 18}};
1271 int num_values = sizeof(values) / sizeof(ValueSamples);
1272 Stats::Counter total_samples;
1273 Stats::SparseHistData data;
1274
1275 // Simple test with one value being sampled
1276 stor.sample(values[0].value, values[0].numSamples);
1277 stor.prepare(nullptr, data);
1278 ASSERT_EQ(stor.size(), 1);
1279 ASSERT_EQ(data.cmap.size(), 1);
1280 ASSERT_EQ(data.cmap[values[0].value], values[0].numSamples);
1281 ASSERT_EQ(data.samples, values[0].numSamples);
1282
1283 // Reset storage, and make sure all data has been cleared
1284 stor.reset(nullptr);
1285 stor.prepare(nullptr, data);
1286 ASSERT_EQ(stor.size(), 0);
1287 ASSERT_EQ(data.cmap.size(), 0);
1288 ASSERT_EQ(data.samples, 0);
1289
1290 // Populate storage with more data
1291 for (int i = 0; i < num_values; i++) {
1292 stor.sample(values[i].value, values[i].numSamples);
1293 }
1294 stor.prepare(nullptr, data);
1295 total_samples = 0;
1296 ASSERT_EQ(stor.size(), num_values);
1297 ASSERT_EQ(data.cmap.size(), num_values);
1298 for (int i = 0; i < num_values; i++) {
1299 ASSERT_EQ(data.cmap[values[i].value], values[i].numSamples);
1300 total_samples += values[i].numSamples;
1301 }
1302 ASSERT_EQ(data.samples, total_samples);
1303 }