sat_counter.test.cc revision 13962
1/*
2 * Copyright (c) 2019 Inria
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 * Authors: Daniel Carvalho
29 */
30
31#include <gtest/gtest.h>
32
33#include <utility>
34
35#include "base/sat_counter.hh"
36
37/**
38 * Test if the maximum value is indeed the maximum value reachable.
39 */
40TEST(SatCounterTest, MaximumValue)
41{
42    const unsigned bits = 3;
43    const unsigned max_value = (1 << bits) - 1;
44    SatCounter counter(bits);
45
46    for (int i = 0; i < 2*max_value; i++) {
47        counter++;
48    }
49
50    ASSERT_EQ(counter, max_value);
51}
52
53/**
54 * Test if the minimum value is indeed the mimimum value reachable.
55 */
56TEST(SatCounterTest, MinimumValue)
57{
58    const unsigned bits = 3;
59    SatCounter counter(bits);
60
61    for (int i = 0; i < 2; i++) {
62        counter--;
63    }
64
65    ASSERT_EQ(counter, 0);
66}
67
68/**
69 * Test initializing the counter with a value, updating it and then resetting.
70 */
71TEST(SatCounterTest, InitialValue)
72{
73    const unsigned bits = 3;
74    const unsigned initial_value = 4;
75    SatCounter counter(bits, initial_value);
76    ASSERT_EQ(counter, initial_value);
77    counter++;
78    counter.reset();
79    ASSERT_EQ(counter, initial_value);
80}
81
82/**
83 * Test calculating saturation percentile.
84 */
85TEST(SatCounterTest, SaturationPercentile)
86{
87    const unsigned bits = 3;
88    const unsigned max_value = (1 << bits) - 1;
89    SatCounter counter(bits);
90
91    ASSERT_FALSE(counter.isSaturated());
92    for (double value = 0.0; value <= max_value; value++, counter++) {
93        const double saturation = value / max_value;
94        ASSERT_DOUBLE_EQ(counter.calcSaturation(), saturation);
95    }
96    ASSERT_TRUE(counter.isSaturated());
97}
98
99/**
100 * Test back and forth against an int.
101 */
102TEST(SatCounterTest, IntComparison)
103{
104    const unsigned bits = 3;
105    SatCounter counter(bits);
106    int value = 0;
107
108    ASSERT_EQ(counter++, value++);
109    ASSERT_EQ(counter++, value++);
110    ASSERT_EQ(counter--, value--);
111    ASSERT_EQ(counter++, value++);
112    ASSERT_EQ(counter++, value++);
113    ASSERT_EQ(counter--, value--);
114    ASSERT_EQ(counter++, value++);
115    ASSERT_EQ(counter--, value--);
116    ASSERT_EQ(counter--, value--);
117    ASSERT_EQ(counter++, value++);
118    ASSERT_EQ(counter--, value--);
119    ASSERT_EQ(counter--, value--);
120    ASSERT_EQ(counter, 0);
121}
122
123/**
124 * Test shift operators.
125 */
126TEST(SatCounterTest, Shift)
127{
128    const unsigned bits = 3;
129    const unsigned max_value = (1 << bits) - 1;
130    const unsigned initial_value = 1;
131    SatCounter counter(bits, initial_value);
132    SatCounter other(bits, initial_value);
133    // The saturated shift value is just enough to saturate, since greater
134    // values could generate undefined behavior
135    SatCounter saturated_counter(bits, bits);
136    int value = initial_value;
137
138    // Test random shifts
139    counter <<= 2;
140    value <<= 2;
141    ASSERT_EQ(counter, value);
142    counter >>= 1;
143    value >>= 1;
144    ASSERT_EQ(counter, value);
145
146    // Test saturation
147    counter <<= bits;
148    ASSERT_EQ(counter, max_value);
149
150    // Test zeroing
151    counter >>= bits;
152    ASSERT_EQ(counter, 0);
153
154    // Test saturation against other saturating counter
155    counter.reset();
156    value = initial_value;
157    counter <<= other;
158    value <<= other;
159    ASSERT_EQ(counter, value);
160    counter <<= saturated_counter;
161    value = max_value;
162    ASSERT_EQ(counter, max_value);
163
164    // Test zeroing against other saturating counter
165    counter >>= other;
166    value >>= other;
167    ASSERT_EQ(counter, value);
168    counter >>= saturated_counter;
169    ASSERT_EQ(counter, 0);
170}
171
172/**
173 * Test both pre and post operators.
174 */
175TEST(SatCounterTest, PrePostOperators)
176{
177    const unsigned bits = 3;
178    const unsigned max_value = (1 << bits) - 1;
179    SatCounter counter_pre(bits);
180    SatCounter counter_post(bits);
181
182    for (int i = 0; i < 2*max_value; i++) {
183        counter_post++;
184        SatCounter value_pre = ++counter_pre;
185        ASSERT_EQ(counter_post, value_pre);
186    }
187
188    ASSERT_EQ(counter_pre, max_value);
189    ASSERT_EQ(counter_post, max_value);
190
191    for (int i = 0; i < 2*max_value; i++) {
192        counter_post--;
193        SatCounter value_pre = --counter_pre;
194        ASSERT_EQ(counter_post, value_pre);
195    }
196
197    ASSERT_EQ(counter_pre, 0);
198    ASSERT_EQ(counter_post, 0);
199}
200
201/**
202 * Test copy and move for both constructor and assignment.
203 */
204TEST(SatCounterTest, CopyMove)
205{
206    const unsigned bits = 3;
207    const unsigned max_value = (1 << bits) - 1;
208    const unsigned initial_value = 1;
209    SatCounter counter(bits, initial_value);
210    SatCounter deep_copy(1);
211    SatCounter counter_copy(2);
212
213    // Increase counter value so that we can check if the inner counter is
214    // being copied
215    counter++;
216
217    // Copy counter using both the copy constructor and the copy assignment
218    SatCounter counter_copy_constructor(counter);
219    deep_copy = counter_copy = counter;
220    ASSERT_EQ(counter_copy_constructor, initial_value + 1);
221    ASSERT_EQ(counter_copy, initial_value + 1);
222    ASSERT_EQ(deep_copy, initial_value + 1);
223
224    // Make sure max value is the same for all of them, and that modifying
225    // the copies does not modify the original
226    for (int i = 0; i < 2*max_value; i++) {
227        counter_copy_constructor++;
228        counter_copy++;
229        deep_copy++;
230    }
231    ASSERT_EQ(counter, initial_value + 1);
232    ASSERT_EQ(counter_copy_constructor, max_value);
233    ASSERT_EQ(counter_copy, max_value);
234    ASSERT_EQ(deep_copy, max_value);
235
236    // Make sure initial value is the same for all of them
237    counter_copy_constructor.reset();
238    counter_copy.reset();
239    deep_copy.reset();
240    ASSERT_EQ(counter_copy_constructor, initial_value);
241    ASSERT_EQ(counter_copy, initial_value);
242    ASSERT_EQ(deep_copy, initial_value);
243
244    // Now check move
245    SatCounter counter_move_constructor(std::move(counter));
246    ASSERT_EQ(counter, 0);
247    ASSERT_EQ(counter_move_constructor, initial_value + 1);
248
249    SatCounter counter_move(bits);
250    counter_move = std::move(counter_move_constructor);
251    ASSERT_EQ(counter_move_constructor, 0);
252    ASSERT_EQ(counter_move, initial_value + 1);
253}
254
255/**
256 * Test add-assignment and subtract assignment.
257 */
258TEST(SatCounterTest, AddSubAssignment)
259{
260    const unsigned bits = 3;
261    const unsigned max_value = (1 << bits) - 1;
262    SatCounter counter(bits);
263    SatCounter other(bits, 2);
264    SatCounter saturated_counter(bits, max_value);
265    int value = 0;
266
267    // Test add-assignment for a few random values and then saturate
268    counter += 2;
269    value += 2;
270    ASSERT_EQ(counter, value);
271    counter += 3;
272    value += 3;
273    ASSERT_EQ(counter, value);
274    counter += max_value;
275    value = max_value;
276    ASSERT_EQ(counter, value);
277
278    // Test subtract-assignment for a few random values until back to zero
279    counter -= 2;
280    value -= 2;
281    ASSERT_EQ(counter, value);
282    counter -= 3;
283    value -= 3;
284    ASSERT_EQ(counter, value);
285    counter -= max_value;
286    value = 0;
287    ASSERT_EQ(counter, value);
288
289    // Test add-assignment of other saturating counter
290    counter += other;
291    value += other;
292    ASSERT_EQ(counter, value);
293    counter += saturated_counter;
294    value = max_value;
295    ASSERT_EQ(counter, saturated_counter);
296
297    // Test subtract-assignment of other saturating counter
298    counter -= other;
299    value -= other;
300    ASSERT_EQ(counter, value);
301    counter -= saturated_counter;
302    ASSERT_EQ(counter, 0);
303}
304
305