HELLO·Android
系统源代码
IT资讯
技术文章
我的收藏
注册
登录
-
我收藏的文章
创建代码块
我的代码块
我的账号
Android 10
|
10.0.0_r6
下载
查看原文件
收藏
根目录
external
perfetto
src
base
optional_unittest.cc
/* * Copyright (C) 2018 The Android Open Source Project * * 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 * * http://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. */ // Comparisions of floats is used extensively in this file. Ignore warnings // as we want to stay close to Chromium. #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wfloat-equal" #include
#include
#include
#include
#include
#include
#include "perfetto/base/optional.h" using ::testing::ElementsAre; namespace perfetto { namespace base { namespace { // Object used to test complex object with Optional
in addition of the move // semantics. class TestObject { public: enum class State { DEFAULT_CONSTRUCTED, VALUE_CONSTRUCTED, COPY_CONSTRUCTED, MOVE_CONSTRUCTED, MOVED_FROM, COPY_ASSIGNED, MOVE_ASSIGNED, SWAPPED, }; TestObject() : foo_(0), bar_(0.0), state_(State::DEFAULT_CONSTRUCTED) {} TestObject(int foo, double bar) : foo_(foo), bar_(bar), state_(State::VALUE_CONSTRUCTED) {} TestObject(const TestObject& other) : foo_(other.foo_), bar_(other.bar_), state_(State::COPY_CONSTRUCTED), move_ctors_count_(other.move_ctors_count_) {} TestObject(TestObject&& other) : foo_(std::move(other.foo_)), bar_(std::move(other.bar_)), state_(State::MOVE_CONSTRUCTED), move_ctors_count_(other.move_ctors_count_ + 1) { other.state_ = State::MOVED_FROM; } TestObject& operator=(const TestObject& other) { foo_ = other.foo_; bar_ = other.bar_; state_ = State::COPY_ASSIGNED; move_ctors_count_ = other.move_ctors_count_; return *this; } TestObject& operator=(TestObject&& other) { foo_ = other.foo_; bar_ = other.bar_; state_ = State::MOVE_ASSIGNED; move_ctors_count_ = other.move_ctors_count_; other.state_ = State::MOVED_FROM; return *this; } void Swap(TestObject* other) { using std::swap; swap(foo_, other->foo_); swap(bar_, other->bar_); swap(move_ctors_count_, other->move_ctors_count_); state_ = State::SWAPPED; other->state_ = State::SWAPPED; } bool operator==(const TestObject& other) const { return std::tie(foo_, bar_) == std::tie(other.foo_, other.bar_); } bool operator!=(const TestObject& other) const { return !(*this == other); } int foo() const { return foo_; } State state() const { return state_; } int move_ctors_count() const { return move_ctors_count_; } private: int foo_; double bar_; State state_; int move_ctors_count_ = 0; }; // Implementing Swappable concept. void swap(TestObject& lhs, TestObject& rhs) { lhs.Swap(&rhs); } class NonTriviallyDestructible { ~NonTriviallyDestructible() {} }; class DeletedDefaultConstructor { public: DeletedDefaultConstructor() = delete; DeletedDefaultConstructor(int foo) : foo_(foo) {} int foo() const { return foo_; } private: int foo_; }; class DeletedCopy { public: explicit DeletedCopy(int foo) : foo_(foo) {} DeletedCopy(const DeletedCopy&) = delete; DeletedCopy(DeletedCopy&&) = default; DeletedCopy& operator=(const DeletedCopy&) = delete; DeletedCopy& operator=(DeletedCopy&&) = default; int foo() const { return foo_; } private: int foo_; }; class DeletedMove { public: explicit DeletedMove(int foo) : foo_(foo) {} DeletedMove(const DeletedMove&) = default; DeletedMove(DeletedMove&&) = delete; DeletedMove& operator=(const DeletedMove&) = default; DeletedMove& operator=(DeletedMove&&) = delete; int foo() const { return foo_; } private: int foo_; }; class NonTriviallyDestructibleDeletedCopyConstructor { public: explicit NonTriviallyDestructibleDeletedCopyConstructor(int foo) : foo_(foo) {} NonTriviallyDestructibleDeletedCopyConstructor( const NonTriviallyDestructibleDeletedCopyConstructor&) = delete; NonTriviallyDestructibleDeletedCopyConstructor( NonTriviallyDestructibleDeletedCopyConstructor&&) = default; ~NonTriviallyDestructibleDeletedCopyConstructor() {} int foo() const { return foo_; } private: int foo_; }; class DeleteNewOperators { public: void* operator new(size_t) = delete; void* operator new(size_t, void*) = delete; void* operator new[](size_t) = delete; void* operator new[](size_t, void*) = delete; }; } // anonymous namespace static_assert(std::is_trivially_destructible
>::value, "OptionalIsTriviallyDestructible"); static_assert( !std::is_trivially_destructible
>::value, "OptionalIsTriviallyDestructible"); static_assert(sizeof(Optional
) == sizeof(internal::OptionalBase
), "internal::{Copy,Move}{Constructible,Assignable} structs " "should be 0-sized"); TEST(OptionalTest, DefaultConstructor) { { constexpr Optional
o; EXPECT_FALSE(o); } { Optional
o; EXPECT_FALSE(o); } { Optional
o; EXPECT_FALSE(o); } } TEST(OptionalTest, CopyConstructor) { { constexpr Optional
first(0.1f); constexpr Optional
other(first); EXPECT_TRUE(other); EXPECT_EQ(other.value(), 0.1f); EXPECT_EQ(first, other); } { Optional
first("foo"); Optional
other(first); EXPECT_TRUE(other); EXPECT_EQ(other.value(), "foo"); EXPECT_EQ(first, other); } { const Optional
first("foo"); Optional
other(first); EXPECT_TRUE(other); EXPECT_EQ(other.value(), "foo"); EXPECT_EQ(first, other); } { Optional
first(TestObject(3, 0.1)); Optional
other(first); EXPECT_TRUE(!!other); EXPECT_TRUE(other.value() == TestObject(3, 0.1)); EXPECT_TRUE(first == other); } } TEST(OptionalTest, ValueConstructor) { { constexpr float value = 0.1f; constexpr Optional
o(value); EXPECT_TRUE(o); EXPECT_EQ(value, o.value()); } { std::string value("foo"); Optional
o(value); EXPECT_TRUE(o); EXPECT_EQ(value, o.value()); } { TestObject value(3, 0.1); Optional
o(value); EXPECT_TRUE(o); EXPECT_EQ(TestObject::State::COPY_CONSTRUCTED, o->state()); EXPECT_EQ(value, o.value()); } } TEST(OptionalTest, MoveConstructor) { { constexpr Optional
first(0.1f); constexpr Optional
second(std::move(first)); EXPECT_TRUE(second.has_value()); EXPECT_EQ(second.value(), 0.1f); EXPECT_TRUE(first.has_value()); } { Optional
first("foo"); Optional
second(std::move(first)); EXPECT_TRUE(second.has_value()); EXPECT_EQ("foo", second.value()); EXPECT_TRUE(first.has_value()); } { Optional
first(TestObject(3, 0.1)); Optional
second(std::move(first)); EXPECT_TRUE(second.has_value()); EXPECT_EQ(TestObject::State::MOVE_CONSTRUCTED, second->state()); EXPECT_TRUE(TestObject(3, 0.1) == second.value()); EXPECT_TRUE(first.has_value()); EXPECT_EQ(TestObject::State::MOVED_FROM, first->state()); } // Even if copy constructor is deleted, move constructor needs to work. // Note that it couldn't be constexpr. { Optional
first(in_place, 42); Optional
second(std::move(first)); EXPECT_TRUE(second.has_value()); EXPECT_EQ(42, second->foo()); EXPECT_TRUE(first.has_value()); } { Optional
first(in_place, 42); Optional
second(std::move(first)); EXPECT_TRUE(second.has_value()); EXPECT_EQ(42, second->foo()); EXPECT_TRUE(first.has_value()); } { Optional
first(in_place, 42); Optional
second( std::move(first)); EXPECT_TRUE(second.has_value()); EXPECT_EQ(42, second->foo()); EXPECT_TRUE(first.has_value()); } } TEST(OptionalTest, MoveValueConstructor) { { constexpr float value = 0.1f; constexpr Optional
o(std::move(value)); EXPECT_TRUE(o); EXPECT_EQ(0.1f, o.value()); } { float value = 0.1f; Optional
o(std::move(value)); EXPECT_TRUE(o); EXPECT_EQ(0.1f, o.value()); } { std::string value("foo"); Optional
o(std::move(value)); EXPECT_TRUE(o); EXPECT_EQ("foo", o.value()); } { TestObject value(3, 0.1); Optional
o(std::move(value)); EXPECT_TRUE(o); EXPECT_EQ(TestObject::State::MOVE_CONSTRUCTED, o->state()); EXPECT_EQ(TestObject(3, 0.1), o.value()); } } TEST(OptionalTest, ConvertingCopyConstructor) { { Optional
first(1); Optional
second(first); EXPECT_TRUE(second.has_value()); EXPECT_EQ(1.0, second.value()); } // Make sure explicit is not marked for convertible case. { Optional
o(1); ignore_result
>(o); } } TEST(OptionalTest, ConvertingMoveConstructor) { { Optional
first(1); Optional
second(std::move(first)); EXPECT_TRUE(second.has_value()); EXPECT_EQ(1.0, second.value()); } // Make sure explicit is not marked for convertible case. { Optional
o(1); ignore_result
>(std::move(o)); } { class Test1 { public: explicit Test1(int foo) : foo_(foo) {} int foo() const { return foo_; } private: int foo_; }; // Not copyable but convertible from Test1. class Test2 { public: Test2(const Test2&) = delete; explicit Test2(Test1&& other) : bar_(other.foo()) {} double bar() const { return bar_; } private: double bar_; }; Optional
first(in_place, 42); Optional
second(std::move(first)); EXPECT_TRUE(second.has_value()); EXPECT_EQ(42.0, second->bar()); } } TEST(OptionalTest, ConstructorForwardArguments) { { constexpr Optional
a(base::in_place, 0.1f); EXPECT_TRUE(a); EXPECT_EQ(0.1f, a.value()); } { Optional
a(base::in_place, 0.1f); EXPECT_TRUE(a); EXPECT_EQ(0.1f, a.value()); } { Optional
a(base::in_place, "foo"); EXPECT_TRUE(a); EXPECT_EQ("foo", a.value()); } { Optional
a(base::in_place, 0, 0.1); EXPECT_TRUE(!!a); EXPECT_TRUE(TestObject(0, 0.1) == a.value()); } } TEST(OptionalTest, ConstructorForwardInitListAndArguments) { { Optional
> opt(in_place, {3, 1}); EXPECT_TRUE(opt); EXPECT_THAT(*opt, ElementsAre(3, 1)); EXPECT_EQ(2u, opt->size()); } { Optional
> opt(in_place, {3, 1}, std::allocator
()); EXPECT_TRUE(opt); EXPECT_THAT(*opt, ElementsAre(3, 1)); EXPECT_EQ(2u, opt->size()); } } TEST(OptionalTest, ForwardConstructor) { { Optional
a(1); EXPECT_TRUE(a.has_value()); EXPECT_EQ(1.0, a.value()); } // Test that default type of 'U' is value_type. { struct TestData { int a; double b; bool c; }; Optional
a({1, 2.0, true}); EXPECT_TRUE(a.has_value()); EXPECT_EQ(1, a->a); EXPECT_EQ(2.0, a->b); EXPECT_TRUE(a->c); } // If T has a constructor with a param Optional
, and another ctor with a // param U, then T(Optional
) should be used for Optional
(Optional
) // constructor. { enum class ParamType { DEFAULT_CONSTRUCTED, COPY_CONSTRUCTED, MOVE_CONSTRUCTED, INT, IN_PLACE, OPTIONAL_INT, }; struct Test { Test() : param_type(ParamType::DEFAULT_CONSTRUCTED) {} Test(const Test&) : param_type(ParamType::COPY_CONSTRUCTED) {} Test(Test&&) : param_type(ParamType::MOVE_CONSTRUCTED) {} explicit Test(int) : param_type(ParamType::INT) {} explicit Test(in_place_t) : param_type(ParamType::IN_PLACE) {} explicit Test(Optional
) : param_type(ParamType::OPTIONAL_INT) {} ParamType param_type; }; // Overload resolution with copy-conversion constructor. { const Optional
arg(in_place, 1); Optional
testee(arg); EXPECT_EQ(ParamType::OPTIONAL_INT, testee->param_type); } // Overload resolution with move conversion constructor. { Optional
testee(Optional
(in_place, 1)); EXPECT_EQ(ParamType::OPTIONAL_INT, testee->param_type); } // Default constructor should be used. { Optional
testee(in_place); EXPECT_EQ(ParamType::DEFAULT_CONSTRUCTED, testee->param_type); } } { struct Test { Test(int) {} // NOLINT(runtime/explicit) }; // If T is convertible from U, it is not marked as explicit. static_assert(std::is_convertible
::value, "Int should be convertible to Test."); ([](Optional
) {})(1); } } TEST(OptionalTest, NulloptConstructor) { constexpr Optional
a(base::nullopt); EXPECT_FALSE(a); } TEST(OptionalTest, AssignValue) { { Optional
a; EXPECT_FALSE(a); a = 0.1f; EXPECT_TRUE(a); Optional
b(0.1f); EXPECT_TRUE(a == b); } { Optional
a; EXPECT_FALSE(a); a = std::string("foo"); EXPECT_TRUE(a); Optional
b(std::string("foo")); EXPECT_EQ(a, b); } { Optional
a; EXPECT_FALSE(!!a); a = TestObject(3, 0.1); EXPECT_TRUE(!!a); Optional
b(TestObject(3, 0.1)); EXPECT_TRUE(a == b); } { Optional
a = TestObject(4, 1.0); EXPECT_TRUE(!!a); a = TestObject(3, 0.1); EXPECT_TRUE(!!a); Optional
b(TestObject(3, 0.1)); EXPECT_TRUE(a == b); } } TEST(OptionalTest, AssignObject) { { Optional
a; Optional
b(0.1f); a = b; EXPECT_TRUE(a); EXPECT_EQ(a.value(), 0.1f); EXPECT_EQ(a, b); } { Optional
a; Optional
b("foo"); a = b; EXPECT_TRUE(a); EXPECT_EQ(a.value(), "foo"); EXPECT_EQ(a, b); } { Optional
a; Optional
b(TestObject(3, 0.1)); a = b; EXPECT_TRUE(!!a); EXPECT_TRUE(a.value() == TestObject(3, 0.1)); EXPECT_TRUE(a == b); } { Optional
a(TestObject(4, 1.0)); Optional
b(TestObject(3, 0.1)); a = b; EXPECT_TRUE(!!a); EXPECT_TRUE(a.value() == TestObject(3, 0.1)); EXPECT_TRUE(a == b); } { Optional
a(in_place, 42); Optional
b; b = a; EXPECT_TRUE(!!a); EXPECT_TRUE(!!b); EXPECT_EQ(a->foo(), b->foo()); } { Optional
a(in_place, 42); Optional
b(in_place, 1); b = a; EXPECT_TRUE(!!a); EXPECT_TRUE(!!b); EXPECT_EQ(a->foo(), b->foo()); } // Converting assignment. { Optional
a(in_place, 1); Optional
b; b = a; EXPECT_TRUE(!!a); EXPECT_TRUE(!!b); EXPECT_EQ(1, a.value()); EXPECT_EQ(1.0, b.value()); } { Optional
a(in_place, 42); Optional
b(in_place, 1); b = a; EXPECT_TRUE(!!a); EXPECT_TRUE(!!b); EXPECT_EQ(42, a.value()); EXPECT_EQ(42.0, b.value()); } { Optional
a; Optional
b(in_place, 1); b = a; EXPECT_FALSE(!!a); EXPECT_FALSE(!!b); } } TEST(OptionalTest, AssignObject_rvalue) { { Optional
a; Optional
b(0.1f); a = std::move(b); EXPECT_TRUE(a); EXPECT_TRUE(b); EXPECT_EQ(0.1f, a.value()); } { Optional
a; Optional
b("foo"); a = std::move(b); EXPECT_TRUE(a); EXPECT_TRUE(b); EXPECT_EQ("foo", a.value()); } { Optional
a; Optional
b(TestObject(3, 0.1)); a = std::move(b); EXPECT_TRUE(!!a); EXPECT_TRUE(!!b); EXPECT_TRUE(TestObject(3, 0.1) == a.value()); EXPECT_EQ(TestObject::State::MOVE_CONSTRUCTED, a->state()); EXPECT_EQ(TestObject::State::MOVED_FROM, b->state()); } { Optional
a(TestObject(4, 1.0)); Optional
b(TestObject(3, 0.1)); a = std::move(b); EXPECT_TRUE(!!a); EXPECT_TRUE(!!b); EXPECT_TRUE(TestObject(3, 0.1) == a.value()); EXPECT_EQ(TestObject::State::MOVE_ASSIGNED, a->state()); EXPECT_EQ(TestObject::State::MOVED_FROM, b->state()); } { Optional
a(in_place, 42); Optional
b; b = std::move(a); EXPECT_TRUE(!!a); EXPECT_TRUE(!!b); EXPECT_EQ(42, b->foo()); } { Optional
a(in_place, 42); Optional
b(in_place, 1); b = std::move(a); EXPECT_TRUE(!!a); EXPECT_TRUE(!!b); EXPECT_EQ(42, b->foo()); } // Converting assignment. { Optional
a(in_place, 1); Optional
b; b = std::move(a); EXPECT_TRUE(!!a); EXPECT_TRUE(!!b); EXPECT_EQ(1.0, b.value()); } { Optional
a(in_place, 42); Optional
b(in_place, 1); b = std::move(a); EXPECT_TRUE(!!a); EXPECT_TRUE(!!b); EXPECT_EQ(42.0, b.value()); } { Optional
a; Optional
b(in_place, 1); b = std::move(a); EXPECT_FALSE(!!a); EXPECT_FALSE(!!b); } } TEST(OptionalTest, AssignNull) { { Optional
a(0.1f); Optional
b(0.2f); a = base::nullopt; b = base::nullopt; EXPECT_EQ(a, b); } { Optional
a("foo"); Optional
b("bar"); a = base::nullopt; b = base::nullopt; EXPECT_EQ(a, b); } { Optional
a(TestObject(3, 0.1)); Optional
b(TestObject(4, 1.0)); a = base::nullopt; b = base::nullopt; EXPECT_TRUE(a == b); } } TEST(OptionalTest, AssignOverload) { struct Test1 { enum class State { CONSTRUCTED, MOVED, }; State state = State::CONSTRUCTED; }; // Here, Optional
can be assigned from Optioanl
. // In case of move, marks MOVED to Test1 instance. struct Test2 { enum class State { DEFAULT_CONSTRUCTED, COPY_CONSTRUCTED_FROM_TEST1, MOVE_CONSTRUCTED_FROM_TEST1, COPY_ASSIGNED_FROM_TEST1, MOVE_ASSIGNED_FROM_TEST1, }; Test2() = default; explicit Test2(const Test1&) : state(State::COPY_CONSTRUCTED_FROM_TEST1) {} explicit Test2(Test1&& test1) : state(State::MOVE_CONSTRUCTED_FROM_TEST1) { test1.state = Test1::State::MOVED; } Test2& operator=(const Test1&) { state = State::COPY_ASSIGNED_FROM_TEST1; return *this; } Test2& operator=(Test1&& test1) { state = State::MOVE_ASSIGNED_FROM_TEST1; test1.state = Test1::State::MOVED; return *this; } State state = State::DEFAULT_CONSTRUCTED; }; { Optional
a(in_place); Optional
b; b = a; EXPECT_TRUE(!!a); EXPECT_TRUE(!!b); EXPECT_EQ(Test1::State::CONSTRUCTED, a->state); EXPECT_EQ(Test2::State::COPY_CONSTRUCTED_FROM_TEST1, b->state); } { Optional
a(in_place); Optional
b(in_place); b = a; EXPECT_TRUE(!!a); EXPECT_TRUE(!!b); EXPECT_EQ(Test1::State::CONSTRUCTED, a->state); EXPECT_EQ(Test2::State::COPY_ASSIGNED_FROM_TEST1, b->state); } { Optional
a(in_place); Optional
b; b = std::move(a); EXPECT_TRUE(!!a); EXPECT_TRUE(!!b); EXPECT_EQ(Test1::State::MOVED, a->state); EXPECT_EQ(Test2::State::MOVE_CONSTRUCTED_FROM_TEST1, b->state); } { Optional
a(in_place); Optional
b(in_place); b = std::move(a); EXPECT_TRUE(!!a); EXPECT_TRUE(!!b); EXPECT_EQ(Test1::State::MOVED, a->state); EXPECT_EQ(Test2::State::MOVE_ASSIGNED_FROM_TEST1, b->state); } // Similar to Test2, but Test3 also has copy/move ctor and assign operators // from Optional
, too. In this case, for a = b where a is // Optional
and b is Optional
, // Optional
::operator=(U&&) where U is Optional
should be used // rather than Optional
::operator=(Optional
&&) where U is Test1. struct Test3 { enum class State { DEFAULT_CONSTRUCTED, COPY_CONSTRUCTED_FROM_TEST1, MOVE_CONSTRUCTED_FROM_TEST1, COPY_CONSTRUCTED_FROM_OPTIONAL_TEST1, MOVE_CONSTRUCTED_FROM_OPTIONAL_TEST1, COPY_ASSIGNED_FROM_TEST1, MOVE_ASSIGNED_FROM_TEST1, COPY_ASSIGNED_FROM_OPTIONAL_TEST1, MOVE_ASSIGNED_FROM_OPTIONAL_TEST1, }; Test3() = default; explicit Test3(const Test1&) : state(State::COPY_CONSTRUCTED_FROM_TEST1) {} explicit Test3(Test1&& test1) : state(State::MOVE_CONSTRUCTED_FROM_TEST1) { test1.state = Test1::State::MOVED; } explicit Test3(const Optional
&) : state(State::COPY_CONSTRUCTED_FROM_OPTIONAL_TEST1) {} explicit Test3(Optional
&& test1) : state(State::MOVE_CONSTRUCTED_FROM_OPTIONAL_TEST1) { // In the following senarios, given |test1| should always have value. PERFETTO_DCHECK(test1.has_value()); test1->state = Test1::State::MOVED; } Test3& operator=(const Test1&) { state = State::COPY_ASSIGNED_FROM_TEST1; return *this; } Test3& operator=(Test1&& test1) { state = State::MOVE_ASSIGNED_FROM_TEST1; test1.state = Test1::State::MOVED; return *this; } Test3& operator=(const Optional
&) { state = State::COPY_ASSIGNED_FROM_OPTIONAL_TEST1; return *this; } Test3& operator=(Optional
&& test1) { state = State::MOVE_ASSIGNED_FROM_OPTIONAL_TEST1; // In the following senarios, given |test1| should always have value. PERFETTO_DCHECK(test1.has_value()); test1->state = Test1::State::MOVED; return *this; } State state = State::DEFAULT_CONSTRUCTED; }; { Optional
a(in_place); Optional
b; b = a; EXPECT_TRUE(!!a); EXPECT_TRUE(!!b); EXPECT_EQ(Test1::State::CONSTRUCTED, a->state); EXPECT_EQ(Test3::State::COPY_CONSTRUCTED_FROM_OPTIONAL_TEST1, b->state); } { Optional
a(in_place); Optional
b(in_place); b = a; EXPECT_TRUE(!!a); EXPECT_TRUE(!!b); EXPECT_EQ(Test1::State::CONSTRUCTED, a->state); EXPECT_EQ(Test3::State::COPY_ASSIGNED_FROM_OPTIONAL_TEST1, b->state); } { Optional
a(in_place); Optional
b; b = std::move(a); EXPECT_TRUE(!!a); EXPECT_TRUE(!!b); EXPECT_EQ(Test1::State::MOVED, a->state); EXPECT_EQ(Test3::State::MOVE_CONSTRUCTED_FROM_OPTIONAL_TEST1, b->state); } { Optional
a(in_place); Optional
b(in_place); b = std::move(a); EXPECT_TRUE(!!a); EXPECT_TRUE(!!b); EXPECT_EQ(Test1::State::MOVED, a->state); EXPECT_EQ(Test3::State::MOVE_ASSIGNED_FROM_OPTIONAL_TEST1, b->state); } } TEST(OptionalTest, OperatorStar) { { Optional
a(0.1f); EXPECT_EQ(a.value(), *a); } { Optional
a("foo"); EXPECT_EQ(a.value(), *a); } { Optional
a(TestObject(3, 0.1)); EXPECT_EQ(a.value(), *a); } } TEST(OptionalTest, OperatorStar_rvalue) { EXPECT_EQ(0.1f, *Optional
(0.1f)); EXPECT_EQ(std::string("foo"), *Optional
("foo")); EXPECT_TRUE(TestObject(3, 0.1) == *Optional
(TestObject(3, 0.1))); } TEST(OptionalTest, OperatorArrow) { Optional
a(TestObject(3, 0.1)); EXPECT_EQ(a->foo(), 3); } TEST(OptionalTest, Value_rvalue) { EXPECT_EQ(0.1f, Optional
(0.1f).value()); EXPECT_EQ(std::string("foo"), Optional
("foo").value()); EXPECT_TRUE(TestObject(3, 0.1) == Optional
(TestObject(3, 0.1)).value()); } TEST(OptionalTest, ValueOr) { { Optional
a; EXPECT_EQ(0.0f, a.value_or(0.0f)); a = 0.1f; EXPECT_EQ(0.1f, a.value_or(0.0f)); a = base::nullopt; EXPECT_EQ(0.0f, a.value_or(0.0f)); } // value_or() can be constexpr. { constexpr Optional
a(in_place, 1); constexpr int value = a.value_or(10); EXPECT_EQ(1, value); } { constexpr Optional
a; constexpr int value = a.value_or(10); EXPECT_EQ(10, value); } { Optional
a; EXPECT_EQ("bar", a.value_or("bar")); a = std::string("foo"); EXPECT_EQ(std::string("foo"), a.value_or("bar")); a = base::nullopt; EXPECT_EQ(std::string("bar"), a.value_or("bar")); } { Optional
a; EXPECT_TRUE(a.value_or(TestObject(1, 0.3)) == TestObject(1, 0.3)); a = TestObject(3, 0.1); EXPECT_TRUE(a.value_or(TestObject(1, 0.3)) == TestObject(3, 0.1)); a = base::nullopt; EXPECT_TRUE(a.value_or(TestObject(1, 0.3)) == TestObject(1, 0.3)); } } TEST(OptionalTest, Swap_bothNoValue) { Optional
a, b; a.swap(b); EXPECT_FALSE(a); EXPECT_FALSE(b); EXPECT_TRUE(TestObject(42, 0.42) == a.value_or(TestObject(42, 0.42))); EXPECT_TRUE(TestObject(42, 0.42) == b.value_or(TestObject(42, 0.42))); } TEST(OptionalTest, Swap_inHasValue) { Optional
a(TestObject(1, 0.3)); Optional
b; a.swap(b); EXPECT_FALSE(a); EXPECT_TRUE(!!b); EXPECT_TRUE(TestObject(42, 0.42) == a.value_or(TestObject(42, 0.42))); EXPECT_TRUE(TestObject(1, 0.3) == b.value_or(TestObject(42, 0.42))); } TEST(OptionalTest, Swap_outHasValue) { Optional
a; Optional
b(TestObject(1, 0.3)); a.swap(b); EXPECT_TRUE(!!a); EXPECT_FALSE(!!b); EXPECT_TRUE(TestObject(1, 0.3) == a.value_or(TestObject(42, 0.42))); EXPECT_TRUE(TestObject(42, 0.42) == b.value_or(TestObject(42, 0.42))); } TEST(OptionalTest, Swap_bothValue) { Optional
a(TestObject(0, 0.1)); Optional
b(TestObject(1, 0.3)); a.swap(b); EXPECT_TRUE(!!a); EXPECT_TRUE(!!b); EXPECT_TRUE(TestObject(1, 0.3) == a.value_or(TestObject(42, 0.42))); EXPECT_TRUE(TestObject(0, 0.1) == b.value_or(TestObject(42, 0.42))); EXPECT_EQ(TestObject::State::SWAPPED, a->state()); EXPECT_EQ(TestObject::State::SWAPPED, b->state()); } TEST(OptionalTest, Emplace) { { Optional
a(0.1f); EXPECT_EQ(0.3f, a.emplace(0.3f)); EXPECT_TRUE(a); EXPECT_EQ(0.3f, a.value()); } { Optional
a("foo"); EXPECT_EQ("bar", a.emplace("bar")); EXPECT_TRUE(a); EXPECT_EQ("bar", a.value()); } { Optional
a(TestObject(0, 0.1)); EXPECT_EQ(TestObject(1, 0.2), a.emplace(TestObject(1, 0.2))); EXPECT_TRUE(!!a); EXPECT_TRUE(TestObject(1, 0.2) == a.value()); } { Optional
> a; auto& ref = a.emplace({2, 3}); static_assert(std::is_same
&, decltype(ref)>::value, ""); EXPECT_TRUE(a); EXPECT_THAT(*a, ElementsAre(2, 3)); EXPECT_EQ(&ref, &*a); } { Optional
> a; auto& ref = a.emplace({4, 5}, std::allocator
()); static_assert(std::is_same
&, decltype(ref)>::value, ""); EXPECT_TRUE(a); EXPECT_THAT(*a, ElementsAre(4, 5)); EXPECT_EQ(&ref, &*a); } } TEST(OptionalTest, Equals_TwoEmpty) { Optional
a; Optional
b; EXPECT_TRUE(a == b); } TEST(OptionalTest, Equals_TwoEquals) { Optional
a(1); Optional
b(1); EXPECT_TRUE(a == b); } TEST(OptionalTest, Equals_OneEmpty) { Optional
a; Optional
b(1); EXPECT_FALSE(a == b); } TEST(OptionalTest, Equals_TwoDifferent) { Optional
a(0); Optional
b(1); EXPECT_FALSE(a == b); } TEST(OptionalTest, Equals_DifferentType) { Optional
a(0); Optional
b(0); EXPECT_TRUE(a == b); } TEST(OptionalTest, NotEquals_TwoEmpty) { Optional
a; Optional
b; EXPECT_FALSE(a != b); } TEST(OptionalTest, NotEquals_TwoEquals) { Optional
a(1); Optional
b(1); EXPECT_FALSE(a != b); } TEST(OptionalTest, NotEquals_OneEmpty) { Optional
a; Optional
b(1); EXPECT_TRUE(a != b); } TEST(OptionalTest, NotEquals_TwoDifferent) { Optional
a(0); Optional
b(1); EXPECT_TRUE(a != b); } TEST(OptionalTest, NotEquals_DifferentType) { Optional
a(0); Optional
b(0.0); EXPECT_FALSE(a != b); } TEST(OptionalTest, Less_LeftEmpty) { Optional
l; Optional
r(1); EXPECT_TRUE(l < r); } TEST(OptionalTest, Less_RightEmpty) { Optional
l(1); Optional
r; EXPECT_FALSE(l < r); } TEST(OptionalTest, Less_BothEmpty) { Optional
l; Optional
r; EXPECT_FALSE(l < r); } TEST(OptionalTest, Less_BothValues) { { Optional
l(1); Optional
r(2); EXPECT_TRUE(l < r); } { Optional
l(2); Optional
r(1); EXPECT_FALSE(l < r); } { Optional
l(1); Optional
r(1); EXPECT_FALSE(l < r); } } TEST(OptionalTest, Less_DifferentType) { Optional
l(1); Optional
r(2.0); EXPECT_TRUE(l < r); } TEST(OptionalTest, LessEq_LeftEmpty) { Optional
l; Optional
r(1); EXPECT_TRUE(l <= r); } TEST(OptionalTest, LessEq_RightEmpty) { Optional
l(1); Optional
r; EXPECT_FALSE(l <= r); } TEST(OptionalTest, LessEq_BothEmpty) { Optional
l; Optional
r; EXPECT_TRUE(l <= r); } TEST(OptionalTest, LessEq_BothValues) { { Optional
l(1); Optional
r(2); EXPECT_TRUE(l <= r); } { Optional
l(2); Optional
r(1); EXPECT_FALSE(l <= r); } { Optional
l(1); Optional
r(1); EXPECT_TRUE(l <= r); } } TEST(OptionalTest, LessEq_DifferentType) { Optional
l(1); Optional
r(2.0); EXPECT_TRUE(l <= r); } TEST(OptionalTest, Greater_BothEmpty) { Optional
l; Optional
r; EXPECT_FALSE(l > r); } TEST(OptionalTest, Greater_LeftEmpty) { Optional
l; Optional
r(1); EXPECT_FALSE(l > r); } TEST(OptionalTest, Greater_RightEmpty) { Optional
l(1); Optional
r; EXPECT_TRUE(l > r); } TEST(OptionalTest, Greater_BothValue) { { Optional
l(1); Optional
r(2); EXPECT_FALSE(l > r); } { Optional
l(2); Optional
r(1); EXPECT_TRUE(l > r); } { Optional
l(1); Optional
r(1); EXPECT_FALSE(l > r); } } TEST(OptionalTest, Greater_DifferentType) { Optional
l(1); Optional
r(2.0); EXPECT_FALSE(l > r); } TEST(OptionalTest, GreaterEq_BothEmpty) { Optional
l; Optional
r; EXPECT_TRUE(l >= r); } TEST(OptionalTest, GreaterEq_LeftEmpty) { Optional
l; Optional
r(1); EXPECT_FALSE(l >= r); } TEST(OptionalTest, GreaterEq_RightEmpty) { Optional
l(1); Optional
r; EXPECT_TRUE(l >= r); } TEST(OptionalTest, GreaterEq_BothValue) { { Optional
l(1); Optional
r(2); EXPECT_FALSE(l >= r); } { Optional
l(2); Optional