blob: 8038105c7a855b69f4e3ba259bc5699b0eaf313a [file]
// 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 <gtest/gtest.h>
#include "butil/containers/optional.h"
namespace {
butil::optional<int> empty_optional() {
return {};
}
TEST(OptionalTest, sanity) {
{
butil::optional<int> empty;
ASSERT_FALSE(empty);
}
{
butil::optional<int> empty{};
ASSERT_FALSE(empty);
}
{
butil::optional<int> empty = empty_optional();
ASSERT_FALSE(empty);
}
{
butil::optional<int> non_empty(42);
ASSERT_TRUE(non_empty);
ASSERT_TRUE(non_empty.has_value());
ASSERT_EQ(*non_empty, 42);
}
butil::optional<std::string> opt_string = "abc";
ASSERT_TRUE(opt_string);
ASSERT_EQ(*opt_string, "abc");
}
TEST(OptionalTest, nullopt) {
butil::optional<int> 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<int> op(1);
ASSERT_TRUE(op);
ASSERT_EQ(1, op);
butil::optional<int> non_empty(op);
ASSERT_TRUE(non_empty);
op = butil::nullopt;
ASSERT_FALSE(op);
butil::optional<int> 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<int> empty;
ASSERT_FALSE(empty);
butil::optional<int> non_empty = 1;
ASSERT_TRUE(non_empty);
ASSERT_EQ(1, non_empty);
butil::optional<int> empty_move(std::move(empty));
ASSERT_FALSE(empty_move);
butil::optional<int> non_empty_move(std::move(non_empty));
ASSERT_TRUE(non_empty_move);
ASSERT_EQ(1, non_empty_move);
butil::optional<int> 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<Obj>&)
:default_ctor(true), move_ctor(false), from_optional(true) { }
ConvertFromOptional(butil::optional<Obj>&&)
:default_ctor(true), move_ctor(true), from_optional(true) { }
bool default_ctor;
bool move_ctor;
bool from_optional;
};
TEST(OptionalTest, convert) {
butil::optional<Obj> i_empty;
ASSERT_FALSE(i_empty);
butil::optional<Obj> i(butil::in_place);
ASSERT_TRUE(i);
{
butil::optional<Convert> empty(i_empty);
ASSERT_FALSE(empty);
butil::optional<Convert> opt_copy(i);
ASSERT_TRUE(opt_copy);
ASSERT_TRUE(opt_copy->default_ctor);
ASSERT_FALSE(opt_copy->move_ctor);
butil::optional<Convert> opt_move(butil::optional<Obj>{ 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<Obj>,
butil::optional<ConvertFromOptional>>::value,
"");
butil::optional<ConvertFromOptional> opt0 = i_empty;
ASSERT_TRUE(opt0);
ASSERT_TRUE(opt0->default_ctor);
ASSERT_FALSE(opt0->move_ctor);
ASSERT_TRUE(opt0->from_optional);
butil::optional<ConvertFromOptional> opt1 = butil::optional<Obj>();
ASSERT_TRUE(opt1);
ASSERT_TRUE(opt1->default_ctor);
ASSERT_TRUE(opt1->move_ctor);
ASSERT_TRUE(opt1->from_optional);
}
}
TEST(OptionalTest, value) {
butil::optional<double> opt_empty;
butil::optional<double> 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<double>().value_or(10));
ASSERT_EQ(1.0, butil::optional<double>(1).value_or(10));
}
TEST(OptionalTest, emplace) {
butil::optional<std::string> opt_string;
ASSERT_TRUE((std::is_same<std::string&, decltype(opt_string.emplace("abc"))>::value));
std::string& str = opt_string.emplace("abc");
ASSERT_EQ(&str, &opt_string.value());
}
TEST(OptionalTest, swap) {
butil::optional<int> 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<decltype(opt_int), butil::optional<int>>::value));
ASSERT_EQ(1, opt_int);
}
TEST(OptionalTest, comparison) {
butil::optional<int> empty;
butil::optional<int> one = 1;
butil::optional<int> 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