// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you 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. #include #include "butil/containers/optional.h" namespace { butil::optional empty_optional() { return {}; } TEST(OptionalTest, sanity) { { butil::optional empty; ASSERT_FALSE(empty); } { butil::optional empty{}; ASSERT_FALSE(empty); } { butil::optional empty = empty_optional(); ASSERT_FALSE(empty); } { butil::optional non_empty(42); ASSERT_TRUE(non_empty); ASSERT_TRUE(non_empty.has_value()); ASSERT_EQ(*non_empty, 42); } butil::optional opt_string = "abc"; ASSERT_TRUE(opt_string); ASSERT_EQ(*opt_string, "abc"); } TEST(OptionalTest, nullopt) { butil::optional empty(butil::nullopt); ASSERT_FALSE(empty); empty = 1; ASSERT_TRUE(empty); ASSERT_EQ(1, empty); empty = butil::nullopt; ASSERT_FALSE(empty); } TEST(OptionalTest, copy) { butil::optional op(1); ASSERT_TRUE(op); ASSERT_EQ(1, op); butil::optional non_empty(op); ASSERT_TRUE(non_empty); op = butil::nullopt; ASSERT_FALSE(op); butil::optional empty(op); ASSERT_FALSE(empty); non_empty = empty; ASSERT_FALSE(non_empty); op = 10; non_empty = op; ASSERT_TRUE(non_empty); ASSERT_EQ(10, non_empty); } TEST(OptionalTest, move) { butil::optional empty; ASSERT_FALSE(empty); butil::optional non_empty = 1; ASSERT_TRUE(non_empty); ASSERT_EQ(1, non_empty); butil::optional empty_move(std::move(empty)); ASSERT_FALSE(empty_move); butil::optional non_empty_move(std::move(non_empty)); ASSERT_TRUE(non_empty_move); ASSERT_EQ(1, non_empty_move); butil::optional empty_move_assign; empty_move_assign = std::move(empty); ASSERT_FALSE(empty_move_assign); } struct Obj {}; struct Convert { Convert() :default_ctor(false), move_ctor(false) { } explicit Convert(const Obj&) :default_ctor(true), move_ctor(false) { } explicit Convert(Obj&&) :default_ctor(true), move_ctor(true) { } bool default_ctor; bool move_ctor; }; struct ConvertFromOptional { ConvertFromOptional() :default_ctor(false), move_ctor(false), from_optional(false) { } ConvertFromOptional(const Obj&) :default_ctor(true), move_ctor(false), from_optional(false) { } ConvertFromOptional(Obj&&) :default_ctor(true), move_ctor(true), from_optional(false) { } ConvertFromOptional( const butil::optional&) :default_ctor(true), move_ctor(false), from_optional(true) { } ConvertFromOptional(butil::optional&&) :default_ctor(true), move_ctor(true), from_optional(true) { } bool default_ctor; bool move_ctor; bool from_optional; }; TEST(OptionalTest, convert) { butil::optional i_empty; ASSERT_FALSE(i_empty); butil::optional i(butil::in_place); ASSERT_TRUE(i); { butil::optional empty(i_empty); ASSERT_FALSE(empty); butil::optional opt_copy(i); ASSERT_TRUE(opt_copy); ASSERT_TRUE(opt_copy->default_ctor); ASSERT_FALSE(opt_copy->move_ctor); butil::optional opt_move(butil::optional{ butil::in_place }); ASSERT_TRUE(opt_move); ASSERT_TRUE(opt_move->default_ctor); ASSERT_TRUE(opt_move->move_ctor); } { static_assert( std::is_convertible, butil::optional>::value, ""); butil::optional opt0 = i_empty; ASSERT_TRUE(opt0); ASSERT_TRUE(opt0->default_ctor); ASSERT_FALSE(opt0->move_ctor); ASSERT_TRUE(opt0->from_optional); butil::optional opt1 = butil::optional(); ASSERT_TRUE(opt1); ASSERT_TRUE(opt1->default_ctor); ASSERT_TRUE(opt1->move_ctor); ASSERT_TRUE(opt1->from_optional); } } TEST(OptionalTest, value) { butil::optional opt_empty; butil::optional opt_double = 1.0; ASSERT_THROW(opt_empty.value(), butil::bad_optional_access); ASSERT_EQ(10.0, opt_empty.value_or(10)); ASSERT_EQ(1.0, opt_double.value()); ASSERT_EQ(1.0, opt_double.value_or(42)); ASSERT_EQ(10.0, butil::optional().value_or(10)); ASSERT_EQ(1.0, butil::optional(1).value_or(10)); } TEST(OptionalTest, emplace) { butil::optional opt_string; ASSERT_TRUE((std::is_same::value)); std::string& str = opt_string.emplace("abc"); ASSERT_EQ(&str, &opt_string.value()); } TEST(OptionalTest, swap) { butil::optional opt_empty, opt1 = 1, opt2 = 2; ASSERT_FALSE(opt_empty); ASSERT_TRUE(opt1); ASSERT_EQ(1, opt1.value()); ASSERT_TRUE(opt2); ASSERT_EQ(2, opt2.value()); swap(opt_empty, opt1); ASSERT_FALSE(opt1); ASSERT_TRUE(opt_empty); ASSERT_EQ(1, opt_empty.value()); ASSERT_TRUE(opt2); ASSERT_EQ(2, opt2.value()); swap(opt_empty, opt1); ASSERT_FALSE(opt_empty); ASSERT_TRUE(opt1); ASSERT_EQ(1, opt1.value()); ASSERT_TRUE(opt2); ASSERT_EQ(2, opt2.value()); swap(opt1, opt2); ASSERT_FALSE(opt_empty); ASSERT_TRUE(opt1); ASSERT_EQ(2, opt1.value()); ASSERT_TRUE(opt2); ASSERT_EQ(1, opt2.value()); ASSERT_TRUE(noexcept(opt1.swap(opt2))); ASSERT_TRUE(noexcept(swap(opt1, opt2))); } TEST(OptionalTest, make_optional) { auto opt_int = butil::make_optional(1); ASSERT_TRUE((std::is_same>::value)); ASSERT_EQ(1, opt_int); } TEST(OptionalTest, comparison) { butil::optional empty; butil::optional one = 1; butil::optional two = 2; ASSERT_TRUE(empty == empty); ASSERT_FALSE(empty == one); ASSERT_FALSE(empty == two); ASSERT_TRUE(empty == butil::nullopt); ASSERT_TRUE(one == one); ASSERT_FALSE(one == two); ASSERT_FALSE(one == butil::nullopt); ASSERT_TRUE(two == two); ASSERT_FALSE(two == butil::nullopt); ASSERT_FALSE(empty != empty); ASSERT_TRUE(empty != one); ASSERT_TRUE(empty != two); ASSERT_FALSE(empty != butil::nullopt); ASSERT_FALSE(one != one); ASSERT_TRUE(one != two); ASSERT_TRUE(one != butil::nullopt); ASSERT_FALSE(two != two); ASSERT_TRUE(two != butil::nullopt); ASSERT_FALSE(empty < empty); ASSERT_TRUE(empty < one); ASSERT_TRUE(empty < two); ASSERT_FALSE(empty < butil::nullopt); ASSERT_FALSE(one < one); ASSERT_TRUE(one < two); ASSERT_FALSE(one < butil::nullopt); ASSERT_FALSE(two < two); ASSERT_FALSE(two < butil::nullopt); ASSERT_TRUE(empty <= empty); ASSERT_TRUE(empty <= one); ASSERT_TRUE(empty <= two); ASSERT_TRUE(empty <= butil::nullopt); ASSERT_TRUE(one <= one); ASSERT_TRUE(one <= two); ASSERT_FALSE(one <= butil::nullopt); ASSERT_TRUE(two <= two); ASSERT_FALSE(two <= butil::nullopt); ASSERT_FALSE(empty > empty); ASSERT_FALSE(empty > one); ASSERT_FALSE(empty > two); ASSERT_FALSE(empty > butil::nullopt); ASSERT_FALSE(one > one); ASSERT_FALSE(one > two); ASSERT_TRUE(one > butil::nullopt); ASSERT_FALSE(two > two); ASSERT_TRUE(two > butil::nullopt); ASSERT_TRUE(empty >= empty); ASSERT_FALSE(empty >= one); ASSERT_FALSE(empty >= two); ASSERT_TRUE(empty >= butil::nullopt); ASSERT_TRUE(one >= one); ASSERT_FALSE(one >= two); ASSERT_TRUE(one >= butil::nullopt); ASSERT_TRUE(two >= two); ASSERT_TRUE(two >= butil::nullopt); } } // namespace