capnproto

FORK: Cap'n Proto serialization/RPC system - core tools and C++ library
git clone https://git.neptards.moe/neptards/capnproto.git
Log | Files | Refs | README | LICENSE

units-test.c++ (14753B)


      1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
      2 // Licensed under the MIT License:
      3 //
      4 // Permission is hereby granted, free of charge, to any person obtaining a copy
      5 // of this software and associated documentation files (the "Software"), to deal
      6 // in the Software without restriction, including without limitation the rights
      7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      8 // copies of the Software, and to permit persons to whom the Software is
      9 // furnished to do so, subject to the following conditions:
     10 //
     11 // The above copyright notice and this permission notice shall be included in
     12 // all copies or substantial portions of the Software.
     13 //
     14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     20 // THE SOFTWARE.
     21 
     22 #include "units.h"
     23 #include <kj/compat/gtest.h>
     24 #include <iostream>
     25 
     26 namespace kj {
     27 namespace {
     28 
     29 class Bytes;
     30 class KiB;
     31 class MiB;
     32 
     33 typedef Quantity<int, Bytes> ByteCount;
     34 typedef Quantity<int, KiB> KiBCount;
     35 typedef Quantity<int, MiB> MiBCount;
     36 
     37 constexpr ByteCount BYTE KJ_UNUSED = unit<ByteCount>();
     38 constexpr KiBCount KIB = unit<KiBCount>();
     39 constexpr MiBCount MIB = unit<MiBCount>();
     40 
     41 constexpr UnitRatio<int, Bytes, KiB> BYTES_PER_KIB KJ_UNUSED = 1024 * BYTE / KIB;
     42 constexpr UnitRatio<int, Bytes, MiB> BYTES_PER_MIB KJ_UNUSED = 1024 * 1024 * BYTE / MIB;
     43 constexpr auto KIB_PER_MIB = 1024 * KIB / MIB;
     44 
     45 template <typename T, typename U>
     46 kj::String KJ_STRINGIFY(Quantity<T, U> value) {
     47   return kj::str(value / unit<Quantity<T, U>>());
     48 }
     49 
     50 TEST(UnitMeasure, Basics) {
     51   KiBCount k = 15 * KIB;
     52   EXPECT_EQ(15, k / KIB);
     53   EXPECT_EQ(16 * KIB, k + KIB);
     54 
     55   k += KIB;
     56   k *= 2048;
     57 
     58   EXPECT_EQ(32 * MIB, k / KIB_PER_MIB);
     59 
     60   EXPECT_TRUE(2 * KIB < 4 * KIB);
     61   EXPECT_FALSE(8 * KIB < 4 * KIB);
     62 }
     63 
     64 template <typename T, typename U>
     65 static void assertSameType() {
     66   U u;
     67   T* t = &u;
     68   *t = 0;
     69 }
     70 
     71 TEST(UnitMeasure, AtLeastUInt) {
     72   assertSameType<uint8_t , AtLeastUInt< 2>>();
     73   assertSameType<uint8_t , AtLeastUInt< 3>>();
     74   assertSameType<uint8_t , AtLeastUInt< 4>>();
     75   assertSameType<uint8_t , AtLeastUInt< 5>>();
     76   assertSameType<uint8_t , AtLeastUInt< 6>>();
     77   assertSameType<uint8_t , AtLeastUInt< 7>>();
     78   assertSameType<uint8_t , AtLeastUInt< 8>>();
     79   assertSameType<uint16_t, AtLeastUInt< 9>>();
     80   assertSameType<uint16_t, AtLeastUInt<10>>();
     81   assertSameType<uint16_t, AtLeastUInt<13>>();
     82   assertSameType<uint16_t, AtLeastUInt<16>>();
     83   assertSameType<uint32_t, AtLeastUInt<17>>();
     84   assertSameType<uint32_t, AtLeastUInt<23>>();
     85   assertSameType<uint32_t, AtLeastUInt<24>>();
     86   assertSameType<uint32_t, AtLeastUInt<25>>();
     87   assertSameType<uint32_t, AtLeastUInt<32>>();
     88   assertSameType<uint64_t, AtLeastUInt<33>>();
     89   assertSameType<uint64_t, AtLeastUInt<40>>();
     90   assertSameType<uint64_t, AtLeastUInt<41>>();
     91   assertSameType<uint64_t, AtLeastUInt<47>>();
     92   assertSameType<uint64_t, AtLeastUInt<48>>();
     93   assertSameType<uint64_t, AtLeastUInt<52>>();
     94   assertSameType<uint64_t, AtLeastUInt<64>>();
     95 
     96   // COMPILE ERROR: assertSameType<uint64_t, AtLeastUInt<65>>();
     97 }
     98 
     99 TEST(UnitMeasure, BoundedConst) {
    100   // TODO(someday): Some script should attempt to compile this test once with each "COMPILE ERROR"
    101   //   line restored to verify that they actually error out.
    102 
    103   KJ_EXPECT((bounded<456>() + bounded<123>()).unwrap() == 456 + 123);
    104   KJ_EXPECT((bounded<456>() - bounded<123>()).unwrap() == 456 - 123);
    105   KJ_EXPECT((bounded<456>() * bounded<123>()).unwrap() == 456 * 123);
    106   KJ_EXPECT((bounded<456>() / bounded<123>()).unwrap() == 456 / 123);
    107   KJ_EXPECT((bounded<456>() % bounded<123>()).unwrap() == 456 % 123);
    108   KJ_EXPECT((bounded<456>() << bounded<5>()).unwrap() == 456 << 5);
    109   KJ_EXPECT((bounded<456>() >> bounded<2>()).unwrap() == 456 >> 2);
    110 
    111   KJ_EXPECT(bounded<123>() == bounded<123>());
    112   KJ_EXPECT(bounded<123>() != bounded<456>());
    113   KJ_EXPECT(bounded<123>() <  bounded<456>());
    114   KJ_EXPECT(bounded<456>() >  bounded<123>());
    115   KJ_EXPECT(bounded<123>() <= bounded<456>());
    116   KJ_EXPECT(bounded<456>() >= bounded<123>());
    117 
    118   KJ_EXPECT(!(bounded<123>() == bounded<456>()));
    119   KJ_EXPECT(!(bounded<123>() != bounded<123>()));
    120   KJ_EXPECT(!(bounded<456>() <  bounded<123>()));
    121   KJ_EXPECT(!(bounded<123>() >  bounded<456>()));
    122   KJ_EXPECT(!(bounded<456>() <= bounded<123>()));
    123   KJ_EXPECT(!(bounded<123>() >= bounded<456>()));
    124 
    125   {
    126     uint16_t succ = unbound(bounded<12345>());
    127     KJ_EXPECT(succ == 12345);
    128 
    129     // COMPILE ERROR: uint8_t err KJ_UNUSED = unbound(bounded<12345>());
    130   }
    131 
    132   // COMPILE ERROR: auto err1 KJ_UNUSED = bounded<(0xffffffffffffffffull)>() + bounded<1>();
    133   // COMPILE ERROR: auto err2 KJ_UNUSED = bounded<1>() - bounded<2>();
    134   // COMPILE ERROR: auto err3 KJ_UNUSED = bounded<(1ull << 60)>() * bounded<(1ull << 60)>();
    135   // COMPILE ERROR: auto err4 KJ_UNUSED = bounded<1>() / bounded<0>();
    136   // COMPILE ERROR: auto err5 KJ_UNUSED = bounded<1>() % bounded<0>();
    137   // COMPILE ERROR: auto err6 KJ_UNUSED = bounded<1>() << bounded<64>();
    138   // COMPILE ERROR: auto err7 KJ_UNUSED = bounded<(1ull << 60)>() << bounded<4>();
    139   // COMPILE ERROR: auto err8 KJ_UNUSED = bounded<1>() >> bounded<64>();
    140 
    141   // COMPILE ERROR: boundedAdd<0xffffffffffffffffull, 1>();
    142   // COMPILE ERROR: boundedSub<1, 2>();
    143   // COMPILE ERROR: boundedMul<0x100000000, 0x100000000>();
    144   // COMPILE ERROR: boundedLShift<0x10, 60>();
    145 }
    146 
    147 template <uint value, typename T = uint>
    148 constexpr Bounded<value, T> boundedValue(NoInfer<T> runtimeValue = value) {
    149   return Bounded<value, T>(runtimeValue, unsafe);
    150 }
    151 
    152 TEST(UnitMeasure, Bounded) {
    153   // TODO(someday): Some script should attempt to compile this test once with each "COMPILE ERROR"
    154   //   line restored to verify that they actually error out.
    155 
    156   KJ_EXPECT((boundedValue<456>() + boundedValue<123>()).unwrap() == 456 + 123);
    157   KJ_EXPECT(boundedValue<456>().subtractChecked(boundedValue<123>(), [](){}).unwrap() == 456 - 123);
    158   KJ_EXPECT((boundedValue<456>() * boundedValue<123>()).unwrap() == 456 * 123);
    159   KJ_EXPECT((boundedValue<456>() / boundedValue<123>()).unwrap() == 456 / 123);
    160   KJ_EXPECT((boundedValue<456>() % boundedValue<123>()).unwrap() == 456 % 123);
    161 
    162 
    163   {
    164     Bounded<123, uint8_t> succ KJ_UNUSED;
    165     // COMPILE ERROR: Bounded<1234, uint8_t> err KJ_UNUSED;
    166     // COMPILE ERROR: auto err KJ_UNUSED = boundedValue<0xffffffffull>() + boundedValue<1>();
    167   }
    168 
    169   {
    170     Bounded<123, uint8_t> succ1 KJ_UNUSED = boundedValue<123>();
    171     Bounded<123, uint8_t> succ2 KJ_UNUSED = boundedValue<122>();
    172     Bounded<123, uint8_t> succ3 KJ_UNUSED = boundedValue<0>();
    173     // COMPILE ERROR: Bounded<123, uint8_t> err KJ_UNUSED = boundedValue<124>();
    174     // COMPILE ERROR: Bounded<123, uint8_t> err KJ_UNUSED = boundedValue<125>();
    175     // COMPILE ERROR: Bounded<123, uint8_t> err KJ_UNUSED = boundedValue<123456>();
    176   }
    177 
    178   Bounded<123, uint8_t> foo;
    179   foo = boundedValue<123>();
    180   foo = boundedValue<122>();
    181   foo = boundedValue<0>();
    182   // COMPILE ERROR: foo = boundedValue<124>();
    183   // COMPILE ERROR: foo = boundedValue<125>();
    184   // COMPILE ERROR: foo = boundedValue<123456>();
    185 
    186   assertMax<122>(foo, []() {});
    187   // COMPILE ERROR: assertMax<123>(foo, []() {});
    188   // COMPILE ERROR: assertMax<124>(foo, []() {});
    189 
    190   assertMaxBits<6>(foo, []() {});
    191   // COMPILE ERROR: assertMaxBits<7>(foo, []() {});
    192   // COMPILE ERROR: assertMaxBits<8>(foo, []() {});
    193 
    194   Bounded<12, uint8_t> bar;
    195   // COMPILE ERROR: bar = foo;
    196   // COMPILE ERROR: bar = foo.assertMax<13>([]() {});
    197   bool caught = false;
    198   foo = boundedValue<13>();
    199   bar = foo.assertMax<12>([&]() { caught = true; });
    200   KJ_EXPECT(caught);
    201 
    202   foo = boundedValue<100>() + boundedValue<23>();
    203   // COMPILE ERROR: foo = boundedValue<100>() + boundedValue<24>();
    204 
    205   bar = boundedValue<3>() * boundedValue<4>();
    206   // COMPILE ERROR: bar = boundedValue<2>() * boundedValue<7>();
    207 
    208   foo.subtractChecked(boundedValue<122>(), []() { KJ_FAIL_EXPECT(""); });
    209   foo.subtractChecked(boundedValue<123>(), []() { KJ_FAIL_EXPECT(""); });
    210   caught = false;
    211   foo.subtractChecked(boundedValue<124>(), [&]() { caught = true; });
    212   KJ_EXPECT(caught);
    213 
    214   {
    215     Bounded<65535, uint16_t> succ1 KJ_UNUSED = bounded((uint16_t)123);
    216     // COMPILE ERROR: Bounded<65534, uint16_t> err KJ_UNUSED = bounded((uint16_t)123);
    217   }
    218 
    219   uint old = foo.unwrap();
    220   foo = foo * unit<decltype(foo)>();
    221   KJ_EXPECT(foo.unwrap() == old);
    222 
    223   {
    224     Bounded<1234, uint16_t> x = bounded<123>();
    225     uint16_t succ = unbound(x);
    226     KJ_EXPECT(succ == 123);
    227 
    228     // COMPILE ERROR: uint8_t err KJ_UNUSED = unbound(x);
    229   }
    230 }
    231 
    232 TEST(UnitMeasure, BoundedVsGuardedConst) {
    233   // TODO(someday): Some script should attempt to compile this test once with each "COMPILE ERROR"
    234   //   line restored to verify that they actually error out.
    235 
    236   KJ_EXPECT((boundedValue<456>() + bounded<123>()).unwrap() == 456 + 123);
    237   KJ_EXPECT(boundedValue<456>().subtractChecked(bounded<123>(), [](){}).unwrap() == 456 - 123);
    238   KJ_EXPECT((boundedValue<456>() * bounded<123>()).unwrap() == 456 * 123);
    239   KJ_EXPECT((boundedValue<456>() / bounded<123>()).unwrap() == 456 / 123);
    240   KJ_EXPECT((boundedValue<456>() % bounded<123>()).unwrap() == 456 % 123);
    241 
    242   {
    243     Bounded<123, uint8_t> succ1 KJ_UNUSED = bounded<123>();
    244     Bounded<123, uint8_t> succ2 KJ_UNUSED = bounded<122>();
    245     Bounded<123, uint8_t> succ3 KJ_UNUSED = bounded<0>();
    246     // COMPILE ERROR: Bounded<123, uint8_t> err KJ_UNUSED = bounded<124>();
    247     // COMPILE ERROR: Bounded<123, uint8_t> err KJ_UNUSED = bounded<125>();
    248     // COMPILE ERROR: Bounded<123, uint8_t> err KJ_UNUSED = bounded<123456>();
    249   }
    250 
    251   Bounded<123, uint8_t> foo;
    252   foo = bounded<123>();
    253   foo = bounded<122>();
    254   foo = bounded<0>();
    255   // COMPILE ERROR: foo = bounded<124>();
    256   // COMPILE ERROR: foo = bounded<125>();
    257   // COMPILE ERROR: foo = bounded<123456>();
    258 
    259   Bounded<16, uint8_t> bar;
    260   // COMPILE ERROR: bar = foo >> bounded<2>();
    261   bar = foo >> bounded<3>();
    262 
    263   // COMPILE ERROR: foo = bar << bounded<3>();
    264   foo = bar << bounded<2>();
    265 }
    266 
    267 TEST(UnitMeasure, BoundedRange) {
    268   uint expected = 0;
    269   for (auto i: zeroTo(bounded<10>())) {
    270     Bounded<10, uint8_t> value = i;
    271     KJ_EXPECT(unbound(value) == expected++);
    272   }
    273   KJ_EXPECT(expected == 10);
    274 
    275   expected = 0;
    276   for (auto i: zeroTo(bounded((uint8_t)10))) {
    277     Bounded<255, uint8_t> value = i;
    278     KJ_EXPECT(unbound(value) == expected++);
    279   }
    280   KJ_EXPECT(expected == 10);
    281 
    282   expected = 3;
    283   for (auto i: range(bounded((uint8_t)3), bounded((uint8_t)10))) {
    284     Bounded<255, uint8_t> value = i;
    285     KJ_EXPECT(unbound(value) == expected++);
    286   }
    287   KJ_EXPECT(expected == 10);
    288 }
    289 
    290 TEST(UnitMeasure, BoundedQuantity) {
    291   auto BYTES = unit<Quantity<Bounded<12345, uint16_t>, byte>>();
    292 
    293   uint expected = 0;
    294   for (auto i: zeroTo(bounded<10>() * BYTES)) {
    295     Quantity<Bounded<10, uint8_t>, byte> value = i;
    296     KJ_EXPECT(unbound(value / BYTES) == expected++);
    297   }
    298   KJ_EXPECT(expected == 10);
    299 
    300   expected = 0;
    301   for (auto i: zeroTo(bounded((uint8_t)10) * BYTES)) {
    302     Quantity<Bounded<255, uint8_t>, byte> value = i;
    303     KJ_EXPECT(unbound(value / BYTES) == expected++);
    304   }
    305   KJ_EXPECT(expected == 10);
    306 
    307   expected = 3;
    308   for (auto i: range(bounded((uint8_t)3) * BYTES, bounded((uint8_t)10) * BYTES)) {
    309     Quantity<Bounded<255, uint8_t>, byte> value = i;
    310     KJ_EXPECT(unbound(value / BYTES) == expected++);
    311   }
    312   KJ_EXPECT(expected == 10);
    313 }
    314 
    315 template <typename T>
    316 void assertTypeAndValue(T a, T b) { KJ_EXPECT(a == b); }
    317 
    318 TEST(UnitMeasure, BoundedMinMax) {
    319   assertTypeAndValue(bounded<5>(), kj::max(bounded<4>(), bounded<5>()));
    320   assertTypeAndValue(bounded<5>(), kj::max(bounded<5>(), bounded<4>()));
    321   assertTypeAndValue(bounded<4>(), kj::max(bounded<4>(), bounded<4>()));
    322 
    323   assertTypeAndValue(bounded<4>(), kj::min(bounded<4>(), bounded<5>()));
    324   assertTypeAndValue(bounded<4>(), kj::min(bounded<5>(), bounded<4>()));
    325   assertTypeAndValue(bounded<4>(), kj::min(bounded<4>(), bounded<4>()));
    326 
    327   typedef uint8_t t1;
    328   typedef uint16_t t2;
    329 
    330   assertTypeAndValue(boundedValue<5,t2>(3), kj::max(boundedValue<4,t2>(3), boundedValue<5,t1>(2)));
    331   assertTypeAndValue(boundedValue<5,t2>(3), kj::max(boundedValue<5,t1>(2), boundedValue<4,t2>(3)));
    332   assertTypeAndValue(boundedValue<4,t2>(3), kj::max(boundedValue<4,t2>(3), boundedValue<4,t2>(3)));
    333 
    334   assertTypeAndValue(boundedValue<4,t2>(2), kj::min(boundedValue<4,t2>(3), boundedValue<5,t1>(2)));
    335   assertTypeAndValue(boundedValue<4,t2>(2), kj::min(boundedValue<5,t1>(2), boundedValue<4,t2>(3)));
    336   assertTypeAndValue(boundedValue<4,t2>(3), kj::min(boundedValue<4,t2>(3), boundedValue<4,t2>(3)));
    337 
    338   assertTypeAndValue(boundedValue<5,t1>(4), kj::max(bounded<4>(), boundedValue<5,t1>(2)));
    339   assertTypeAndValue(boundedValue<5,t1>(4), kj::max(boundedValue<5,t1>(2), bounded<4>()));
    340 
    341   assertTypeAndValue(boundedValue<4,t1>(2), kj::min(bounded<4>(), boundedValue<5,t1>(2)));
    342   assertTypeAndValue(boundedValue<4,t1>(2), kj::min(boundedValue<5,t1>(2), bounded<4>()));
    343 
    344   // These two are degenerate cases. Currently they fail to compile but meybe they shouldn't?
    345 //  assertTypeAndValue(bounded<5>(), kj::max(boundedValue<4,t2>(3), bounded<5>()));
    346 //  assertTypeAndValue(bounded<5>(), kj::max(bounded<5>(), boundedValue<4,t2>(3)));
    347 
    348   assertTypeAndValue(boundedValue<4,t2>(3), kj::min(boundedValue<4,t2>(3), bounded<5>()));
    349   assertTypeAndValue(boundedValue<4,t2>(3), kj::min(bounded<5>(), boundedValue<4,t2>(3)));
    350 }
    351 
    352 #if !_MSC_VER  // MSVC barfs on this test and I just don't have time to care.
    353 KJ_TEST("compare bounded quantities of different bounds") {
    354   auto foo = boundedValue<12345, uint>(123) * unit<Quantity<BoundedConst<1>, byte>>();
    355   auto bar = boundedValue<54321, uint>(123) * unit<Quantity<BoundedConst<1>, byte>>();
    356   auto baz = bounded<123>() * unit<Quantity<BoundedConst<1>, byte>>();
    357 
    358   KJ_EXPECT(foo == foo);
    359   KJ_EXPECT(foo == bar);
    360   KJ_EXPECT(foo == baz);
    361   KJ_EXPECT(bar == foo);
    362   KJ_EXPECT(bar == bar);
    363   KJ_EXPECT(bar == baz);
    364   KJ_EXPECT(baz == foo);
    365   KJ_EXPECT(baz == bar);
    366   KJ_EXPECT(baz == baz);
    367 
    368   auto denom = unit<Quantity<BoundedConst<1>, int>>();
    369 
    370   KJ_EXPECT(foo / denom == foo / denom);
    371   KJ_EXPECT(foo / denom == bar / denom);
    372   KJ_EXPECT(foo / denom == baz / denom);
    373   KJ_EXPECT(bar / denom == foo / denom);
    374   KJ_EXPECT(bar / denom == bar / denom);
    375   KJ_EXPECT(bar / denom == baz / denom);
    376   KJ_EXPECT(baz / denom == foo / denom);
    377   KJ_EXPECT(baz / denom == bar / denom);
    378   KJ_EXPECT(baz / denom == baz / denom);
    379 }
    380 #endif
    381 
    382 }  // namespace
    383 }  // namespace kj