diff options
Diffstat (limited to 'src/base/test')
-rw-r--r-- | src/base/test/bit_stream_test.cpp | 141 | ||||
-rw-r--r-- | src/base/test/bottom_n_test.cpp | 99 | ||||
-rw-r--r-- | src/base/test/math_utils_test.cpp | 78 | ||||
-rw-r--r-- | src/base/test/optional_test.cpp | 481 | ||||
-rw-r--r-- | src/base/test/string_utils_test.cpp | 110 | ||||
-rw-r--r-- | src/base/test/type_traits_test.cpp | 128 | ||||
-rw-r--r-- | src/base/test/uint128_test.cpp | 140 |
7 files changed, 1177 insertions, 0 deletions
diff --git a/src/base/test/bit_stream_test.cpp b/src/base/test/bit_stream_test.cpp new file mode 100644 index 0000000..0c4b3c9 --- /dev/null +++ b/src/base/test/bit_stream_test.cpp @@ -0,0 +1,141 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/base/bit_stream.h" + +#include <gtest/gtest.h> + +namespace astc_codec { +namespace base { + +namespace { + static constexpr uint64_t kAllBits = 0xFFFFFFFFFFFFFFFF; + static constexpr uint64_t k40Bits = 0x000000FFFFFFFFFF; +} + +TEST(BitStream, Decode) { + { + BitStream<uint64_t> stream(0, 1); + + uint64_t bits = kAllBits; + EXPECT_TRUE(stream.GetBits(1, &bits)); + EXPECT_EQ(bits, 0); + EXPECT_FALSE(stream.GetBits(1, &bits)); + } + + { + BitStream<uint64_t> stream(0b1010101010101010, 32); + EXPECT_EQ(stream.Bits(), 32); + + uint64_t bits = 0; + EXPECT_TRUE(stream.GetBits(1, &bits)); + EXPECT_EQ(bits, 0); + + EXPECT_TRUE(stream.GetBits(3, &bits)); + EXPECT_EQ(bits, 0b101); + + EXPECT_TRUE(stream.GetBits(8, &bits)); + EXPECT_EQ(bits, 0b10101010); + + EXPECT_EQ(stream.Bits(), 20); + + EXPECT_TRUE(stream.GetBits(20, &bits)); + EXPECT_EQ(bits, 0b1010); + EXPECT_EQ(stream.Bits(), 0); + } + + { + BitStream<uint64_t> stream(kAllBits, 64); + EXPECT_EQ(stream.Bits(), 64); + + uint64_t bits = 0; + EXPECT_TRUE(stream.GetBits(64, &bits)); + EXPECT_EQ(bits, kAllBits); + EXPECT_EQ(stream.Bits(), 0); + } + + { + BitStream<uint64_t> stream(kAllBits, 64); + EXPECT_EQ(stream.Bits(), 64); + + uint64_t bits = 0; + EXPECT_TRUE(stream.GetBits(40, &bits)); + EXPECT_EQ(bits, k40Bits); + EXPECT_EQ(stream.Bits(), 24); + } + + { + BitStream<uint64_t> stream(kAllBits, 32); + + uint64_t bits = 0; + EXPECT_TRUE(stream.GetBits(0, &bits)); + EXPECT_EQ(bits, 0); + EXPECT_TRUE(stream.GetBits(32, &bits)); + EXPECT_EQ(bits, k40Bits & 0xFFFFFFFF); + EXPECT_TRUE(stream.GetBits(0, &bits)); + EXPECT_EQ(bits, 0); + EXPECT_EQ(stream.Bits(), 0); + } +} + +TEST(BitStream, Encode) { + { + BitStream<uint64_t> stream; + + stream.PutBits(0, 1); + stream.PutBits(0b11, 2); + EXPECT_EQ(stream.Bits(), 3); + + uint64_t bits = 0; + EXPECT_TRUE(stream.GetBits(3, &bits)); + EXPECT_EQ(bits, 0b110); + } + + { + BitStream<uint64_t> stream; + + uint64_t bits = 0; + stream.PutBits(kAllBits, 64); + EXPECT_EQ(stream.Bits(), 64); + + EXPECT_TRUE(stream.GetBits(64, &bits)); + EXPECT_EQ(bits, kAllBits); + EXPECT_EQ(stream.Bits(), 0); + } + + { + BitStream<uint64_t> stream; + stream.PutBits(kAllBits, 40); + + uint64_t bits = 0; + EXPECT_TRUE(stream.GetBits(40, &bits)); + EXPECT_EQ(bits, k40Bits); + EXPECT_EQ(stream.Bits(), 0); + } + + { + BitStream<uint64_t> stream; + stream.PutBits(0, 0); + stream.PutBits(kAllBits, 32); + stream.PutBits(0, 0); + + uint64_t bits = 0; + EXPECT_TRUE(stream.GetBits(32, &bits)); + EXPECT_EQ(bits, k40Bits & 0xFFFFFFFF); + EXPECT_EQ(stream.Bits(), 0); + } +} + +} // namespace base +} // namespace astc_codec diff --git a/src/base/test/bottom_n_test.cpp b/src/base/test/bottom_n_test.cpp new file mode 100644 index 0000000..8a48d30 --- /dev/null +++ b/src/base/test/bottom_n_test.cpp @@ -0,0 +1,99 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/base/bottom_n.h" + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +namespace astc_codec { +namespace base { + +using ::testing::ElementsAre; + +template<typename T, size_t N> +static void pushAll(BottomN<T>& heap, const T (&arr)[N]) { + for (auto i : arr) { + heap.Push(i); + } +} + +TEST(BottomN, Sort) { + { + BottomN<int> heap(10); + EXPECT_TRUE(heap.Empty()); + pushAll(heap, {1, 2}); + + EXPECT_EQ(heap.Size(), 2); + EXPECT_FALSE(heap.Empty()); + EXPECT_THAT(heap.Pop(), ElementsAre(1, 2)); + } + + { + BottomN<int> heap(6); + pushAll(heap, {1, 4, 3, 2, 2, 1}); + + EXPECT_EQ(heap.Size(), 6); + EXPECT_THAT(heap.Pop(), ElementsAre(1, 1, 2, 2, 3, 4)); + } +} + +TEST(BottomN, Bounds) { + { + BottomN<int> heap(4); + pushAll(heap, {1, 2, 3, 4}); + EXPECT_EQ(heap.Size(), 4); + + heap.Push(0); + EXPECT_EQ(heap.Size(), 4); + + EXPECT_THAT(heap.Pop(), ElementsAre(0, 1, 2, 3)); + } + + { + BottomN<int> heap(4); + pushAll(heap, {4, 3, 2, 1}); + EXPECT_EQ(heap.Size(), 4); + + pushAll(heap, {4, 4, 4, 4}); + EXPECT_EQ(heap.Size(), 4); + + EXPECT_THAT(heap.Pop(), ElementsAre(1, 2, 3, 4)); + } + + { + BottomN<int> heap(4); + pushAll(heap, {4, 3, 2, 1}); + EXPECT_EQ(heap.Size(), 4); + + pushAll(heap, {5, 5, 5, 5}); + EXPECT_EQ(heap.Size(), 4); + + EXPECT_THAT(heap.Pop(), ElementsAre(1, 2, 3, 4)); + } + + { + BottomN<int> heap(4); + pushAll(heap, {4, 3, 2, 1}); + EXPECT_EQ(heap.Size(), 4); + + pushAll(heap, {0, 0, 0, 0}); + EXPECT_EQ(heap.Size(), 4); + + EXPECT_THAT(heap.Pop(), ElementsAre(0, 0, 0, 0)); + } +} + +} // namespace base +} // namespace astc_codec diff --git a/src/base/test/math_utils_test.cpp b/src/base/test/math_utils_test.cpp new file mode 100644 index 0000000..0371e11 --- /dev/null +++ b/src/base/test/math_utils_test.cpp @@ -0,0 +1,78 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/base/math_utils.h" + +#include <gtest/gtest.h> + +namespace astc_codec { +namespace base { + +TEST(MathUtils, Log2Floor) { + EXPECT_EQ(-1, Log2Floor(0)); + + for (int i = 0; i < 32; i++) { + uint32_t n = 1U << i; + EXPECT_EQ(i, Log2Floor(n)); + if (n > 2) { + EXPECT_EQ(i - 1, Log2Floor(n - 1)); + EXPECT_EQ(i, Log2Floor(n + 1)); + } + } +} + +TEST(MathUtils, CountOnes) { + EXPECT_EQ(0, CountOnes(0)); + EXPECT_EQ(1, CountOnes(1)); + EXPECT_EQ(32, CountOnes(static_cast<uint32_t>(~0U))); + EXPECT_EQ(1, CountOnes(0x8000000)); + + for (int i = 0; i < 32; i++) { + EXPECT_EQ(1, CountOnes(1U << i)); + EXPECT_EQ(31, CountOnes(static_cast<uint32_t>(~0U) ^ (1U << i))); + } +} + +TEST(MathUtils, ReverseBits) { + EXPECT_EQ(ReverseBits(0u), 0u); + EXPECT_EQ(ReverseBits(1u), 1u << 31); + EXPECT_EQ(ReverseBits(0xffffffff), 0xffffffff); + EXPECT_EQ(ReverseBits(0x00000001), 0x80000000); + EXPECT_EQ(ReverseBits(0x80000000), 0x00000001); + EXPECT_EQ(ReverseBits(0xaaaaaaaa), 0x55555555); + EXPECT_EQ(ReverseBits(0x55555555), 0xaaaaaaaa); + EXPECT_EQ(ReverseBits(0x7d5d7f53), 0xcafebabe); + EXPECT_EQ(ReverseBits(0xcafebabe), 0x7d5d7f53); +} + +TEST(MathUtils, GetBits) { + EXPECT_EQ(GetBits(0u, 0, 1), 0u); + EXPECT_EQ(GetBits(0u, 0, 32), 0u); + EXPECT_EQ(GetBits(0x00000001u, 0, 1), 0x00000001); + EXPECT_EQ(GetBits(0x00000001u, 0, 32), 0x00000001); + EXPECT_EQ(GetBits(0x00000001u, 1, 31), 0x00000000); + EXPECT_EQ(GetBits(0x00000001u, 31, 1), 0x00000000); + + EXPECT_DEBUG_DEATH(GetBits(0x00000000u, 1, 32), ""); + EXPECT_DEBUG_DEATH(GetBits(0x00000000u, 32, 0), ""); + EXPECT_DEBUG_DEATH(GetBits(0x00000000u, 32, 1), ""); + + EXPECT_EQ(GetBits(0XFFFFFFFFu, 0, 4), 0x0000000F); + EXPECT_EQ(GetBits(0XFFFFFFFFu, 16, 16), 0xFFFF); + EXPECT_EQ(GetBits(0x80000000u, 31, 1), 1); + EXPECT_EQ(GetBits(0xCAFEBABEu, 24, 8), 0xCA); +} + +} // namespace base +} // namespace astc_codec diff --git a/src/base/test/optional_test.cpp b/src/base/test/optional_test.cpp new file mode 100644 index 0000000..1eeefbd --- /dev/null +++ b/src/base/test/optional_test.cpp @@ -0,0 +1,481 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/base/optional.h" + +#include <gtest/gtest.h> + +#include <memory> +#include <vector> + +namespace astc_codec { +namespace base { + +TEST(Optional, TypeProperties) { + // Making sure optional has the correct alignment and doesn't waste too much + // space + + static_assert(sizeof(Optional<bool>) == 2, "bad Optional<bool> size"); + static_assert(std::alignment_of<Optional<bool>>::value == + std::alignment_of<bool>::value, + "bad Optional<bool> alignment"); + + static_assert(sizeof(Optional<char>) == 2, "bad Optional<char> size"); + static_assert(std::alignment_of<Optional<char>>::value == + std::alignment_of<char>::value, + "bad Optional<char> alignment"); + + static_assert(sizeof(Optional<int16_t>) == 4, "bad Optional<int16_t> size"); + static_assert(std::alignment_of<Optional<int16_t>>::value == + std::alignment_of<int16_t>::value, + "bad Optional<int16_t> alignment"); + + static_assert(sizeof(Optional<int32_t>) == 8, "bad Optional<int32_t> size"); + static_assert(std::alignment_of<Optional<int32_t>>::value == + std::alignment_of<int32_t>::value, + "bad Optional<int32_t> alignment"); + + static_assert(sizeof(Optional<int64_t>) == 16, "bad Optional<int64_t> size"); + static_assert(std::alignment_of<Optional<int64_t>>::value == + std::alignment_of<int64_t>::value, + "bad Optional<int64_t> alignment"); + + struct S128 { + int64_t data[2]; + }; + + static_assert(sizeof(Optional<S128>) == 3 * sizeof(int64_t), + "bad Optional<S128> size"); + static_assert(std::alignment_of<Optional<S128>>::value == + std::alignment_of<S128>::value, + "bad Optional<S128> alignment"); +} + +TEST(Optional, ConstructFromValue) { + { + Optional<int> o; + EXPECT_FALSE(o); + } + { + Optional<int> o = {}; + EXPECT_FALSE(o); + } + { + Optional<int> o = kNullopt; + EXPECT_FALSE(o); + } + { + Optional<int> o(1); + EXPECT_TRUE(o); + EXPECT_EQ(1, *o); + } + { + // check the std::decay<> constructor + Optional<int> o = static_cast<const short&>(1); + EXPECT_TRUE(o); + EXPECT_EQ(1, *o); + } + { + Optional<int> o = 1; + EXPECT_TRUE(o); + EXPECT_EQ(1, *o); + } + { + Optional<int> o{1}; + EXPECT_TRUE(o); + EXPECT_EQ(1, *o); + } + { + short val = 10; + Optional<int> o = val; + EXPECT_TRUE(o); + EXPECT_EQ(10, *o); + } + { + Optional<std::vector<int>> o(kInplace, 10); + EXPECT_TRUE(o); + EXPECT_EQ((std::vector<int>(10)), *o); + } + { + Optional<std::vector<int>> o(kInplace, {1, 2, 3, 4}); + EXPECT_TRUE(o); + EXPECT_EQ((std::vector<int>{1, 2, 3, 4}), *o); + } +} + +TEST(Optional, ConstructFromOptional) { + { + Optional<int> o = Optional<int>(); + EXPECT_FALSE(o); + } + { + Optional<short> o2; + Optional<int> o(o2); + EXPECT_FALSE(o); + } + { + Optional<short> o2 = 42; + Optional<int> o(o2); + EXPECT_TRUE(o); + EXPECT_EQ(42, *o); + } + { + Optional<int> o(Optional<int>(1)); + EXPECT_TRUE(o); + EXPECT_EQ(1, *o); + } + { + Optional<int> o2 = 2; + Optional<int> o = o2; + EXPECT_TRUE(o); + EXPECT_EQ(2, *o); + } + { + Optional<std::vector<int>> o2 = std::vector<int>{20, 30, 40}; + Optional<std::vector<int>> o = o2; + EXPECT_TRUE(o); + EXPECT_EQ((std::vector<int>{20, 30, 40}), *o); + } +} + +TEST(Optional, Assign) { + { + Optional<int> o; + o = 1; + EXPECT_TRUE(o); + EXPECT_EQ(1, *o); + + o = 2; + EXPECT_TRUE(o); + EXPECT_EQ(2, *o); + + o = kNullopt; + EXPECT_FALSE(o); + + o = Optional<int>(10); + EXPECT_TRUE(o); + EXPECT_EQ(10, *o); + + Optional<int> o2; + o = o2; + EXPECT_FALSE(o); + + o = 2u; + EXPECT_TRUE(o); + EXPECT_EQ(2, *o); + + o = Optional<short>(); + EXPECT_FALSE(o); + + o = Optional<short>(20); + EXPECT_TRUE(o); + EXPECT_EQ(20, *o); + + Optional<short> o3(200); + o = o3; + EXPECT_TRUE(o); + EXPECT_EQ(200, *o); + + o = {}; + EXPECT_FALSE(o); + + // check the std::decay<> assignment + o = static_cast<const short&>(1); + EXPECT_TRUE(o); + EXPECT_EQ(1, *o); + } +} + +TEST(Optional, MakeOptional) { + { + auto o = makeOptional(1); + static_assert(std::is_same<decltype(o), Optional<int>>::value, + "Bad type deduction in makeOptional()"); + EXPECT_TRUE(o); + EXPECT_EQ(1, *o); + } + { + auto o = makeOptional(std::vector<char>{'1', '2'}); + static_assert(std::is_same<decltype(o), Optional<std::vector<char>>>::value, + "Bad type deduction in makeOptional()"); + EXPECT_TRUE(o); + EXPECT_EQ((std::vector<char>{'1', '2'}), *o); + } + { + // check std::decay<> in the factory function + auto o = makeOptional("String"); + static_assert(std::is_same<decltype(o), Optional<const char*>>::value, + "Bad type deduction in makeOptional()"); + EXPECT_TRUE(o); + EXPECT_STREQ("String", *o); + } + { + auto o = makeOptional<std::string>("String"); + static_assert(std::is_same<decltype(o), Optional<std::string>>::value, + "Bad type deduction in makeOptional()"); + EXPECT_TRUE(o); + EXPECT_STREQ("String", o->c_str()); + } + { + auto o = makeOptional<std::string>(5, 'b'); + static_assert(std::is_same<decltype(o), Optional<std::string>>::value, + "Bad type deduction in makeOptional()"); + EXPECT_TRUE(o); + EXPECT_STREQ("bbbbb", o->c_str()); + } + { + auto o = makeOptional<std::string>(); + static_assert(std::is_same<decltype(o), Optional<std::string>>::value, + "Bad type deduction in makeOptional()"); + EXPECT_TRUE(o); + EXPECT_STREQ("", o->c_str()); + } +} + +TEST(Optional, Move) { + auto o = makeOptional(std::unique_ptr<int>(new int(10))); + { + decltype(o) o2 = std::move(o); + EXPECT_TRUE(o); + EXPECT_TRUE(o2); + EXPECT_FALSE(bool(*o)); + EXPECT_TRUE(bool(*o2)); + EXPECT_EQ(10, **o2); + + decltype(o) o3; + o3 = std::move(o2); + EXPECT_TRUE(o2); + EXPECT_TRUE(o3); + EXPECT_FALSE(bool(*o2)); + EXPECT_TRUE(bool(*o3)); + EXPECT_EQ(10, **o3); + + o3 = std::move(o2); + EXPECT_TRUE(o2); + EXPECT_TRUE(o3); + EXPECT_FALSE(bool(*o2)); + EXPECT_FALSE(bool(*o3)); + } + + { + decltype(o) o1; + decltype(o) o2 = std::move(o1); + EXPECT_FALSE(o1); + EXPECT_FALSE(o2); + + o2 = std::move(o1); + EXPECT_FALSE(o1); + EXPECT_FALSE(o2); + + decltype(o) o3{kInplace, new int(20)}; + o3 = std::move(o1); + EXPECT_FALSE(o1); + EXPECT_FALSE(o3); + } +} + +TEST(Optional, Value) { + auto o = makeOptional(1); + EXPECT_EQ(1, o.value()); + EXPECT_EQ(1, o.valueOr(2)); + + o = kNullopt; + EXPECT_EQ(2, o.valueOr(2)); +} + +TEST(Optional, Clear) { + auto o = makeOptional(1); + o.clear(); + EXPECT_FALSE(o); + + o.clear(); + EXPECT_FALSE(o); +} + +TEST(Optional, Emplace) { + auto o = makeOptional(std::vector<int>{1, 2, 3, 4}); + o.emplace(3, 1); + EXPECT_TRUE(o); + EXPECT_EQ((std::vector<int>{1, 1, 1}), *o); + EXPECT_EQ(3U, o->capacity()); + + o.clear(); + o.emplace({1, 2}); + EXPECT_TRUE(o); + EXPECT_EQ((std::vector<int>{1, 2}), *o); + EXPECT_EQ(2U, o->capacity()); +} + +TEST(Optional, Reset) { + auto o = makeOptional(std::vector<int>{1, 2, 3, 4}); + o.reset(std::vector<int>{4, 3}); + EXPECT_TRUE(o); + EXPECT_EQ((std::vector<int>{4, 3}), *o); + EXPECT_EQ(2U, o->capacity()); + + o.clear(); + o.reset(std::vector<int>{1}); + EXPECT_EQ((std::vector<int>{1}), *o); + EXPECT_EQ(1U, o->capacity()); +} + +TEST(Optional, CompareEqual) { + EXPECT_TRUE(makeOptional(1) == makeOptional(1)); + EXPECT_TRUE(makeOptional(1) == 1); + EXPECT_TRUE(1 == makeOptional(1)); + EXPECT_FALSE(makeOptional(1) == makeOptional(2)); + EXPECT_FALSE(makeOptional(2) == 1); + EXPECT_FALSE(2 == makeOptional(1)); + EXPECT_TRUE(makeOptional(1) != makeOptional(2)); + EXPECT_TRUE(makeOptional(1) != 2); + EXPECT_TRUE(1 != makeOptional(2)); + + EXPECT_FALSE(makeOptional(1) == kNullopt); + EXPECT_FALSE(makeOptional(1) == Optional<int>()); + EXPECT_FALSE(kNullopt == makeOptional(1)); + EXPECT_FALSE(Optional<int>() == makeOptional(1)); + EXPECT_TRUE(makeOptional(1) != kNullopt); + EXPECT_TRUE(makeOptional(1) != Optional<int>()); + EXPECT_TRUE(kNullopt != makeOptional(1)); + EXPECT_TRUE(Optional<int>() != makeOptional(1)); + + EXPECT_TRUE(kNullopt == Optional<int>()); + EXPECT_TRUE(kNullopt == Optional<char*>()); + EXPECT_FALSE(kNullopt != Optional<int>()); + EXPECT_FALSE(kNullopt != Optional<char*>()); + EXPECT_TRUE(Optional<int>() == Optional<int>()); + EXPECT_FALSE(Optional<int>() != Optional<int>()); +} + +TEST(Optional, CompareLess) { + EXPECT_TRUE(makeOptional(1) < makeOptional(2)); + EXPECT_TRUE(1 < makeOptional(2)); + EXPECT_TRUE(makeOptional(1) < 2); + + EXPECT_FALSE(makeOptional(1) < makeOptional(1)); + EXPECT_FALSE(1 < makeOptional(1)); + EXPECT_FALSE(makeOptional(1) < 1); + EXPECT_FALSE(makeOptional(2) < makeOptional(1)); + EXPECT_FALSE(2 < makeOptional(1)); + EXPECT_FALSE(makeOptional(2) < 1); + + EXPECT_TRUE(kNullopt < makeOptional(2)); + EXPECT_TRUE(Optional<int>() < makeOptional(2)); + EXPECT_TRUE(Optional<int>() < 2); + EXPECT_FALSE(makeOptional(2) < kNullopt); + EXPECT_FALSE(makeOptional(2) < Optional<int>()); + EXPECT_FALSE(2 < Optional<int>()); + + EXPECT_FALSE(kNullopt < Optional<int>()); + EXPECT_FALSE(Optional<int>() < kNullopt); +} + +TEST(Optional, Destruction) { + // create a reference counting class to check if we delete everything + // we've created + struct Track { + Track(int& val) : mVal(val) { ++mVal.get(); } + Track(std::initializer_list<int*> vals) : mVal(**vals.begin()) { + ++mVal.get(); + } + Track(const Track& other) : mVal(other.mVal) { ++mVal.get(); } + Track(Track&& other) : mVal(other.mVal) { ++mVal.get(); } + Track& operator=(const Track& other) { + --mVal.get(); + mVal = other.mVal; + ++mVal.get(); + return *this; + } + Track& operator=(Track&& other) { + --mVal.get(); + mVal = other.mVal; + ++mVal.get(); + return *this; + } + + ~Track() { --mVal.get(); } + + std::reference_wrapper<int> mVal; + }; + + int counter = 0; + { + auto o = makeOptional(Track(counter)); + EXPECT_EQ(1, counter); + } + EXPECT_EQ(0, counter); + + { + auto o = makeOptional(Track(counter)); + EXPECT_EQ(1, counter); + o.clear(); + EXPECT_EQ(0, counter); + } + EXPECT_EQ(0, counter); + + { + auto o = makeOptional(Track(counter)); + EXPECT_EQ(1, counter); + int counter2 = 0; + o.emplace(counter2); + EXPECT_EQ(0, counter); + EXPECT_EQ(1, counter2); + o = Track(counter); + EXPECT_EQ(1, counter); + EXPECT_EQ(0, counter2); + + auto o2 = o; + EXPECT_EQ(2, counter); + EXPECT_EQ(0, counter2); + } + EXPECT_EQ(0, counter); + + { + auto o = makeOptional(Track(counter)); + auto o2 = std::move(o); + EXPECT_EQ(2, counter); + o = o2; + EXPECT_EQ(2, counter); + } + EXPECT_EQ(0, counter); + + int counter2 = 0; + { + Optional<Track> o; + o.emplace(counter); + EXPECT_EQ(1, counter); + + o.emplace(counter2); + EXPECT_EQ(0, counter); + EXPECT_EQ(1, counter2); + } + EXPECT_EQ(0, counter); + EXPECT_EQ(0, counter2); + + { + Optional<Track> o; + o.emplace({&counter}); + EXPECT_EQ(1, counter); + + counter2 = 0; + o.emplace({&counter2}); + EXPECT_EQ(0, counter); + EXPECT_EQ(1, counter2); + } + EXPECT_EQ(0, counter); + EXPECT_EQ(0, counter2); +} + +} // namespace base +} // namespace astc_codec diff --git a/src/base/test/string_utils_test.cpp b/src/base/test/string_utils_test.cpp new file mode 100644 index 0000000..209da54 --- /dev/null +++ b/src/base/test/string_utils_test.cpp @@ -0,0 +1,110 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/base/string_utils.h" + +#include <gtest/gtest.h> + +#include <list> +#include <string> +#include <vector> + +namespace astc_codec { +namespace base { + +TEST(StringUtils, Split) { + std::vector<std::string> results; + + auto testFunc = [&results](std::string&& s) { + results.push_back(std::move(s)); + }; + + Split("", "abc", testFunc); + EXPECT_EQ(results.size(), 1); + + Split("abc", "", testFunc); + EXPECT_EQ(results.size(), 1); + + results.clear(); + Split("abc", "a", testFunc); + EXPECT_EQ(results.size(), 2); + EXPECT_EQ(results[0], ""); + EXPECT_EQ(results[1], "bc"); + + results.clear(); + Split("aaa", "a", testFunc); + EXPECT_EQ(4, results.size()); + EXPECT_EQ("", results[0]); + EXPECT_EQ("", results[1]); + EXPECT_EQ("", results[2]); + EXPECT_EQ("", results[3]); + + results.clear(); + Split("1a2a3a4", "a", testFunc); + EXPECT_EQ(4, results.size()); + EXPECT_EQ("1", results[0]); + EXPECT_EQ("2", results[1]); + EXPECT_EQ("3", results[2]); + EXPECT_EQ("4", results[3]); + + results.clear(); + Split("1a2aa3a4", "a", testFunc); + EXPECT_EQ(5, results.size()); + EXPECT_EQ("1", results[0]); + EXPECT_EQ("2", results[1]); + EXPECT_EQ("", results[2]); + EXPECT_EQ("3", results[3]); + EXPECT_EQ("4", results[4]); + + results.clear(); + Split("The quick brown fox jumped over the lazy dog", + " ", testFunc); + EXPECT_EQ(9, results.size()); + EXPECT_EQ("The", results[0]); + EXPECT_EQ("quick", results[1]); + EXPECT_EQ("brown", results[2]); + EXPECT_EQ("fox", results[3]); + EXPECT_EQ("jumped", results[4]); + EXPECT_EQ("over", results[5]); + EXPECT_EQ("the", results[6]); + EXPECT_EQ("lazy", results[7]); + EXPECT_EQ("dog", results[8]); + + results.clear(); + Split("a; b; c; d", "; ", testFunc); + EXPECT_EQ(4, results.size()); + EXPECT_EQ("a", results[0]); + EXPECT_EQ("b", results[1]); + EXPECT_EQ("c", results[2]); + EXPECT_EQ("d", results[3]); +} + +TEST(StringUtils, ParseInt32) { + EXPECT_EQ(ParseInt32("0", -1), 0); + EXPECT_EQ(ParseInt32("100", -1), 100); + EXPECT_EQ(ParseInt32("-100", -1), -100); + + EXPECT_EQ(ParseInt32("", -1), -1); + EXPECT_EQ(ParseInt32("a", -1), -1); + EXPECT_EQ(ParseInt32("10x1", -1), 10); + + EXPECT_EQ(ParseInt32("2147483647", -1), 2147483647); + EXPECT_EQ(ParseInt32("2147483648", -1), 2147483647); + + EXPECT_EQ(ParseInt32("-2147483648", -1), -2147483648); + EXPECT_EQ(ParseInt32("-2147483649", -1), -2147483648); +} + +} // namespace base +} // namespace astc_codec diff --git a/src/base/test/type_traits_test.cpp b/src/base/test/type_traits_test.cpp new file mode 100644 index 0000000..b858c01 --- /dev/null +++ b/src/base/test/type_traits_test.cpp @@ -0,0 +1,128 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/base/type_traits.h" + +#include <gtest/gtest.h> + +#include <array> +#include <functional> +#include <list> +#include <vector> + +namespace astc_codec { +namespace base { + +TEST(TypeTraits, IsCallable) { + class C; + C* c = nullptr; + + auto lambda = [c](bool) -> C* { return nullptr; }; + + static_assert(is_callable_as<void(), void()>::value, "simple function"); + static_assert(is_callable_as<void (&)(), void()>::value, + "function reference"); + static_assert(is_callable_as<void (*)(), void()>::value, "function pointer"); + static_assert(is_callable_as<int(C&, C*), int(C&, C*)>::value, + "function with arguments and return type"); + static_assert(is_callable_as<decltype(lambda), C*(bool)>::value, "lambda"); + static_assert(is_callable_as<std::function<bool(int)>, bool(int)>::value, + "std::function"); + + static_assert(!is_callable_as<int, void()>::value, + "int should not be callable"); + static_assert(!is_callable_as<C, void()>::value, "incomplete type"); + static_assert(!is_callable_as<void(), void(int)>::value, + "different arguments"); + static_assert(!is_callable_as<int(), void()>::value, + "different return types"); + static_assert(!is_callable_as<int(), short()>::value, + "slightly different return types"); + static_assert(!is_callable_as<int(int), int(int, int)>::value, + "more arguments"); + static_assert(!is_callable_as<int(int, int), int(int)>::value, + "less arguments"); + + static_assert(!is_callable_as<int(int), int>::value, + "bad required signature"); + + static_assert(is_callable_with_args<void(), void()>::value, + "simple function"); + static_assert(is_callable_with_args<void (&)(), void()>::value, + "function reference"); + static_assert(is_callable_with_args<void (*)(), void()>::value, + "function pointer"); + static_assert(is_callable_with_args<int(C&, C*), int(C&, C*)>::value, + "function with arguments and return type"); + static_assert(is_callable_with_args<decltype(lambda), C*(bool)>::value, + "lambda"); + static_assert( + is_callable_with_args<std::function<bool(int)>, bool(int)>::value, + "std::function"); + + static_assert(!is_callable_with_args<int, void()>::value, + "int should not be callable"); + static_assert(!is_callable_with_args<C, void()>::value, "incomplete type"); + static_assert(!is_callable_with_args<void(), void(int)>::value, + "different arguments"); + static_assert(is_callable_with_args<int(), void()>::value, + "different return types are ignored"); + static_assert(is_callable_with_args<int(), short()>::value, + "slightly different return types are ignored"); + static_assert(!is_callable_with_args<int(int), int(int, int)>::value, + "more arguments"); + static_assert(!is_callable_with_args<int(int, int), int(int)>::value, + "less arguments"); + + static_assert(!is_callable_with_args<int(int), int>::value, + "bad required signature"); +} + +TEST(TypeTraits, IsTemplateInstantiation) { + static_assert(!is_template_instantiation_of<int, std::vector>::value, + "int is not an instance of vector"); + static_assert(!is_template_instantiation_of<std::list<std::vector<int>>, + std::vector>::value, + "list is not an instance of vector"); + + static_assert( + is_template_instantiation_of<std::vector<int>, std::vector>::value, + "std::vector<int> is an instance of vector"); + static_assert( + is_template_instantiation_of<std::vector<std::vector<std::vector<int>>>, + std::vector>::value, + "nested std::vector<> is an instance of vector"); +} + +TEST(TypeTraits, IsRange) { + static_assert(is_range<std::vector<int>>::value, + "vector<> should be detected as a range"); + static_assert(is_range<const std::list<std::function<void()>>>::value, + "const list<> should be detected as a range"); + static_assert(is_range<std::array<std::vector<int>, 10>>::value, + "array<> should be detected as a range"); + char arr[100]; + static_assert(is_range<decltype(arr)>::value, + "C array should be detected as a range"); + static_assert(is_range<decltype("string")>::value, + "String literal should be detected as a range"); + + static_assert(!is_range<int>::value, "int shouldn't be a range"); + static_assert(!is_range<int*>::value, "int* shouldn't be a range"); + static_assert(!is_range<const int*>::value, + "even const int* shouldn't be a range"); +} + +} // namespace base +} // namespace astc_codec diff --git a/src/base/test/uint128_test.cpp b/src/base/test/uint128_test.cpp new file mode 100644 index 0000000..0a52244 --- /dev/null +++ b/src/base/test/uint128_test.cpp @@ -0,0 +1,140 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/base/uint128.h" + +#include <gtest/gtest.h> + +namespace astc_codec { +namespace base { + +TEST(UInt128, Equality) { + const UInt128 zero(0); + const UInt128 max64(~0ULL); + + EXPECT_EQ(zero, zero); + EXPECT_NE(zero, max64); + EXPECT_EQ(zero, UInt128(0)); + EXPECT_NE(zero, UInt128(1)); + EXPECT_EQ(max64, max64); +} + +TEST(UInt128, Shifting) { + const UInt128 max64(~0ULL); + const UInt128 upper64(~0ULL, 0); + EXPECT_EQ(upper64.HighBits(), ~0ULL); + EXPECT_EQ(upper64.LowBits(), 0); + + EXPECT_EQ(upper64 >> 64, max64); + + EXPECT_EQ(UInt128(1) << 1, UInt128(2)); + EXPECT_EQ(UInt128(0) << 0, UInt128(0)); + EXPECT_EQ(max64 << 0, max64); + EXPECT_EQ(max64 >> 0, max64); + EXPECT_EQ(upper64 << 0, upper64); + EXPECT_EQ(upper64 >> 0, upper64); + + { + const UInt128 bit63 = UInt128(1ULL << 62) << 1; + EXPECT_EQ(bit63.LowBits(), 1ULL << 63); + EXPECT_EQ(bit63.HighBits(), 0); + } + + { + const UInt128 bit64 = UInt128(1ULL << 63) << 1; + EXPECT_EQ(bit64.LowBits(), 0); + EXPECT_EQ(bit64.HighBits(), 1); + EXPECT_EQ(bit64 >> 1, UInt128(1ULL << 63)); + } + + { + const UInt128 overshift = max64 << 128; + EXPECT_EQ(overshift.HighBits(), 0); + EXPECT_EQ(overshift.LowBits(), 0); + } + + { + const UInt128 overlap = upper64 >> 32; + EXPECT_EQ(overlap.HighBits(), 0x00000000FFFFFFFF); + EXPECT_EQ(overlap.LowBits(), 0xFFFFFFFF00000000); + } + + { + const UInt128 overlap = max64 << 32; + EXPECT_EQ(overlap.HighBits(), 0x00000000FFFFFFFF); + EXPECT_EQ(overlap.LowBits(), 0xFFFFFFFF00000000); + } +} + +TEST(UInt128, LargeShift) { + const UInt128 base(0xFF); + EXPECT_EQ(base << 64, UInt128(0xFFULL, 0)); + EXPECT_EQ(base << 72, UInt128(0xFF00ULL, 0)); + EXPECT_EQ(base << 80, UInt128(0xFF0000ULL, 0)); + EXPECT_EQ(base << 88, UInt128(0xFF000000ULL, 0)); + EXPECT_EQ(base << 96, UInt128(0xFF00000000ULL, 0)); + EXPECT_EQ(base << 104, UInt128(0xFF0000000000ULL, 0)); + EXPECT_EQ(base << 112, UInt128(0xFF000000000000ULL, 0)); + EXPECT_EQ(base << 120, UInt128(0xFF00000000000000ULL, 0)); + + const UInt128 upper(0xFF00000000000000ULL, 0); + EXPECT_EQ(upper >> 64, UInt128(0, 0xFF00000000000000ULL)); + EXPECT_EQ(upper >> 72, UInt128(0, 0xFF000000000000ULL)); + EXPECT_EQ(upper >> 80, UInt128(0, 0xFF0000000000ULL)); + EXPECT_EQ(upper >> 88, UInt128(0, 0xFF00000000ULL)); + EXPECT_EQ(upper >> 96, UInt128(0, 0xFF000000ULL)); + EXPECT_EQ(upper >> 104, UInt128(0, 0xFF0000ULL)); + EXPECT_EQ(upper >> 112, UInt128(0, 0xFF00ULL)); + EXPECT_EQ(upper >> 120, UInt128(0, 0xFFULL)); +} + +TEST(UInt128, BooleanOperators) { + const UInt128 allOnes(~0ULL, ~0ULL); + EXPECT_EQ(allOnes.HighBits(), ~0ULL); + EXPECT_EQ(allOnes.LowBits(), ~0ULL); + + EXPECT_EQ(~allOnes, UInt128(0)); + EXPECT_EQ(~UInt128(0), allOnes); + + EXPECT_EQ(UInt128(0xFFFF00) & UInt128(0x00FFFF), UInt128(0x00FF00)); + EXPECT_EQ(UInt128(0xFFFF00) | UInt128(0x00FFFF), UInt128(0xFFFFFF)); + EXPECT_EQ(UInt128(0xFFFF00) ^ UInt128(0x00FFFF), UInt128(0xFF00FF)); +} + +TEST(UInt128, Addition) { + const UInt128 bit63(1ULL << 63); + + EXPECT_EQ(UInt128(1) + 1, UInt128(2)); + EXPECT_EQ(bit63 + bit63, UInt128(1) << 64); + + const UInt128 carryUp = UInt128(~0ULL) + 1; + EXPECT_EQ(carryUp.HighBits(), 1); + EXPECT_EQ(carryUp.LowBits(), 0); + + const UInt128 allOnes(~0ULL, ~0ULL); + EXPECT_EQ(allOnes + 1, UInt128(0)); +} + +TEST(UInt128, Subtraction) { + const UInt128 bit64 = UInt128(1) << 64; + EXPECT_EQ(bit64 - 1, UInt128(~0ULL)); + + EXPECT_EQ(UInt128(1) - 1, UInt128(0)); + + const UInt128 allOnes(~0ULL, ~0ULL); + EXPECT_EQ(UInt128(0) - 1, allOnes); +} + +} // namespace base +} // namespace astc_codec |