aboutsummaryrefslogtreecommitdiff
path: root/src/base/test/optional_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/test/optional_test.cpp')
-rw-r--r--src/base/test/optional_test.cpp481
1 files changed, 481 insertions, 0 deletions
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