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 abrupt saturation. 101 */ 102TEST(SatCounterTest, Saturate) 103{ 104 const unsigned bits = 3; 105 const unsigned max_value = (1 << bits) - 1; 106 SatCounter counter(bits); 107 counter++; 108 ASSERT_FALSE(counter.isSaturated()); 109 110 // Make sure the value added is what was missing to saturate 111 const unsigned diff = counter.saturate(); 112 ASSERT_EQ(diff, max_value - 1); 113 ASSERT_TRUE(counter.isSaturated()); 114} 115 116/** 117 * Test back and forth against an int. 118 */ 119TEST(SatCounterTest, IntComparison) 120{ 121 const unsigned bits = 3; 122 SatCounter counter(bits); 123 int value = 0; 124 125 ASSERT_EQ(counter++, value++); 126 ASSERT_EQ(counter++, value++); 127 ASSERT_EQ(counter--, value--); 128 ASSERT_EQ(counter++, value++); 129 ASSERT_EQ(counter++, value++); 130 ASSERT_EQ(counter--, value--); 131 ASSERT_EQ(counter++, value++); 132 ASSERT_EQ(counter--, value--); 133 ASSERT_EQ(counter--, value--); 134 ASSERT_EQ(counter++, value++); 135 ASSERT_EQ(counter--, value--); 136 ASSERT_EQ(counter--, value--); 137 ASSERT_EQ(counter, 0); 138} 139 140/** 141 * Test shift operators. 142 */ 143TEST(SatCounterTest, Shift) 144{ 145 const unsigned bits = 3; 146 const unsigned max_value = (1 << bits) - 1; 147 const unsigned initial_value = 1; 148 SatCounter counter(bits, initial_value); 149 SatCounter other(bits, initial_value); 150 // The saturated shift value is just enough to saturate, since greater 151 // values could generate undefined behavior 152 SatCounter saturated_counter(bits, bits); 153 int value = initial_value; 154 155 // Test random shifts 156 counter <<= 2; 157 value <<= 2; 158 ASSERT_EQ(counter, value); 159 counter >>= 1; 160 value >>= 1; 161 ASSERT_EQ(counter, value); 162 163 // Test saturation 164 counter <<= bits; 165 ASSERT_EQ(counter, max_value); 166 167 // Test zeroing 168 counter >>= bits; 169 ASSERT_EQ(counter, 0); 170 171 // Test saturation against other saturating counter 172 counter.reset(); 173 value = initial_value; 174 counter <<= other; 175 value <<= other; 176 ASSERT_EQ(counter, value); 177 counter <<= saturated_counter; 178 value = max_value; 179 ASSERT_EQ(counter, max_value); 180 181 // Test zeroing against other saturating counter 182 counter >>= other; 183 value >>= other; 184 ASSERT_EQ(counter, value); 185 counter >>= saturated_counter; 186 ASSERT_EQ(counter, 0); 187} 188 189/** 190 * Test both pre and post operators. 191 */ 192TEST(SatCounterTest, PrePostOperators) 193{ 194 const unsigned bits = 3; 195 const unsigned max_value = (1 << bits) - 1; 196 SatCounter counter_pre(bits); 197 SatCounter counter_post(bits); 198 199 for (int i = 0; i < 2*max_value; i++) { 200 counter_post++; 201 SatCounter value_pre = ++counter_pre; 202 ASSERT_EQ(counter_post, value_pre); 203 } 204 205 ASSERT_EQ(counter_pre, max_value); 206 ASSERT_EQ(counter_post, max_value); 207 208 for (int i = 0; i < 2*max_value; i++) { 209 counter_post--; 210 SatCounter value_pre = --counter_pre; 211 ASSERT_EQ(counter_post, value_pre); 212 } 213 214 ASSERT_EQ(counter_pre, 0); 215 ASSERT_EQ(counter_post, 0); 216} 217 218/** 219 * Test copy and move for both constructor and assignment. 220 */ 221TEST(SatCounterTest, CopyMove) 222{ 223 const unsigned bits = 3; 224 const unsigned max_value = (1 << bits) - 1; 225 const unsigned initial_value = 1; 226 SatCounter counter(bits, initial_value); 227 SatCounter deep_copy(1); 228 SatCounter counter_copy(2); 229 230 // Increase counter value so that we can check if the inner counter is 231 // being copied 232 counter++; 233 234 // Copy counter using both the copy constructor and the copy assignment 235 SatCounter counter_copy_constructor(counter); 236 deep_copy = counter_copy = counter; 237 ASSERT_EQ(counter_copy_constructor, initial_value + 1); 238 ASSERT_EQ(counter_copy, initial_value + 1); 239 ASSERT_EQ(deep_copy, initial_value + 1); 240 241 // Make sure max value is the same for all of them, and that modifying 242 // the copies does not modify the original 243 for (int i = 0; i < 2*max_value; i++) { 244 counter_copy_constructor++; 245 counter_copy++; 246 deep_copy++; 247 } 248 ASSERT_EQ(counter, initial_value + 1); 249 ASSERT_EQ(counter_copy_constructor, max_value); 250 ASSERT_EQ(counter_copy, max_value); 251 ASSERT_EQ(deep_copy, max_value); 252 253 // Make sure initial value is the same for all of them 254 counter_copy_constructor.reset(); 255 counter_copy.reset(); 256 deep_copy.reset(); 257 ASSERT_EQ(counter_copy_constructor, initial_value); 258 ASSERT_EQ(counter_copy, initial_value); 259 ASSERT_EQ(deep_copy, initial_value); 260 261 // Now check move 262 SatCounter counter_move_constructor(std::move(counter)); 263 ASSERT_EQ(counter, 0); 264 ASSERT_EQ(counter_move_constructor, initial_value + 1); 265 266 SatCounter counter_move(bits); 267 counter_move = std::move(counter_move_constructor); 268 ASSERT_EQ(counter_move_constructor, 0); 269 ASSERT_EQ(counter_move, initial_value + 1); 270} 271 272/** 273 * Test add-assignment and subtract assignment. 274 */ 275TEST(SatCounterTest, AddSubAssignment) 276{ 277 const unsigned bits = 3; 278 const unsigned max_value = (1 << bits) - 1; 279 SatCounter counter(bits); 280 SatCounter other(bits, 2); 281 SatCounter saturated_counter(bits, max_value); 282 int value = 0; 283 284 // Test add-assignment for a few random values and then saturate 285 counter += 2; 286 value += 2; 287 ASSERT_EQ(counter, value); 288 counter += 3; 289 value += 3; 290 ASSERT_EQ(counter, value); 291 counter += max_value; 292 value = max_value; 293 ASSERT_EQ(counter, value); 294 295 // Test subtract-assignment for a few random values until back to zero 296 counter -= 2; 297 value -= 2; 298 ASSERT_EQ(counter, value); 299 counter -= 3; 300 value -= 3; 301 ASSERT_EQ(counter, value); 302 counter -= max_value; 303 value = 0; 304 ASSERT_EQ(counter, value); 305 306 // Test add-assignment of other saturating counter 307 counter += other; 308 value += other; 309 ASSERT_EQ(counter, value); 310 counter += saturated_counter; 311 value = max_value; 312 ASSERT_EQ(counter, saturated_counter); 313 314 // Test subtract-assignment of other saturating counter 315 counter -= other; 316 value -= other; 317 ASSERT_EQ(counter, value); 318 counter -= saturated_counter; 319 ASSERT_EQ(counter, 0); 320} 321 322