diff options
Diffstat (limited to 'Utilities/cmcppdap/src/any_test.cpp')
-rw-r--r-- | Utilities/cmcppdap/src/any_test.cpp | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/Utilities/cmcppdap/src/any_test.cpp b/Utilities/cmcppdap/src/any_test.cpp new file mode 100644 index 0000000..7dfb73c --- /dev/null +++ b/Utilities/cmcppdap/src/any_test.cpp @@ -0,0 +1,262 @@ +// Copyright 2019 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 "dap/any.h" +#include "dap/typeof.h" +#include "dap/types.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace dap { + +struct AnyTestObject { + dap::integer i; + dap::number n; +}; + +DAP_STRUCT_TYPEINFO(AnyTestObject, + "AnyTestObject", + DAP_FIELD(i, "i"), + DAP_FIELD(n, "n")); + +inline bool operator==(const AnyTestObject& a, const AnyTestObject& b) { + return a.i == b.i && a.n == b.n; +} + +} // namespace dap + +namespace { + +template <typename T> +struct TestValue {}; + +template <> +struct TestValue<dap::null> { + static const dap::null value; +}; +template <> +struct TestValue<dap::integer> { + static const dap::integer value; +}; +template <> +struct TestValue<dap::boolean> { + static const dap::boolean value; +}; +template <> +struct TestValue<dap::number> { + static const dap::number value; +}; +template <> +struct TestValue<dap::string> { + static const dap::string value; +}; +template <> +struct TestValue<dap::array<dap::string>> { + static const dap::array<dap::string> value; +}; +template <> +struct TestValue<dap::AnyTestObject> { + static const dap::AnyTestObject value; +}; + +const dap::null TestValue<dap::null>::value = nullptr; +const dap::integer TestValue<dap::integer>::value = 20; +const dap::boolean TestValue<dap::boolean>::value = true; +const dap::number TestValue<dap::number>::value = 123.45; +const dap::string TestValue<dap::string>::value = "hello world"; +const dap::array<dap::string> TestValue<dap::array<dap::string>>::value = { + "one", "two", "three"}; +const dap::AnyTestObject TestValue<dap::AnyTestObject>::value = {10, 20.30}; + +} // namespace + +TEST(Any, EmptyConstruct) { + dap::any any; + ASSERT_TRUE(any.is<dap::null>()); + ASSERT_FALSE(any.is<dap::boolean>()); + ASSERT_FALSE(any.is<dap::integer>()); + ASSERT_FALSE(any.is<dap::number>()); + ASSERT_FALSE(any.is<dap::object>()); + ASSERT_FALSE(any.is<dap::string>()); + ASSERT_FALSE(any.is<dap::array<dap::integer>>()); + ASSERT_FALSE(any.is<dap::AnyTestObject>()); +} + +TEST(Any, Boolean) { + dap::any any(dap::boolean(true)); + ASSERT_TRUE(any.is<dap::boolean>()); + ASSERT_EQ(any.get<dap::boolean>(), dap::boolean(true)); +} + +TEST(Any, Integer) { + dap::any any(dap::integer(10)); + ASSERT_TRUE(any.is<dap::integer>()); + ASSERT_EQ(any.get<dap::integer>(), dap::integer(10)); +} + +TEST(Any, Number) { + dap::any any(dap::number(123.0f)); + ASSERT_TRUE(any.is<dap::number>()); + ASSERT_EQ(any.get<dap::number>(), dap::number(123.0f)); +} + +TEST(Any, String) { + dap::any any(dap::string("hello world")); + ASSERT_TRUE(any.is<dap::string>()); + ASSERT_EQ(any.get<dap::string>(), dap::string("hello world")); +} + +TEST(Any, Array) { + using array = dap::array<dap::integer>; + dap::any any(array({10, 20, 30})); + ASSERT_TRUE(any.is<array>()); + ASSERT_EQ(any.get<array>(), array({10, 20, 30})); +} + +TEST(Any, Object) { + dap::object o; + o["one"] = dap::integer(1); + o["two"] = dap::integer(2); + o["three"] = dap::integer(3); + dap::any any(o); + ASSERT_TRUE(any.is<dap::object>()); + if (any.is<dap::object>()) { + auto got = any.get<dap::object>(); + ASSERT_EQ(got.size(), 3U); + ASSERT_EQ(got.count("one"), 1U); + ASSERT_EQ(got.count("two"), 1U); + ASSERT_EQ(got.count("three"), 1U); + ASSERT_TRUE(got["one"].is<dap::integer>()); + ASSERT_TRUE(got["two"].is<dap::integer>()); + ASSERT_TRUE(got["three"].is<dap::integer>()); + ASSERT_EQ(got["one"].get<dap::integer>(), dap::integer(1)); + ASSERT_EQ(got["two"].get<dap::integer>(), dap::integer(2)); + ASSERT_EQ(got["three"].get<dap::integer>(), dap::integer(3)); + } +} + +TEST(Any, TestObject) { + dap::any any(dap::AnyTestObject{5, 3.0}); + ASSERT_TRUE(any.is<dap::AnyTestObject>()); + ASSERT_EQ(any.get<dap::AnyTestObject>().i, 5); + ASSERT_EQ(any.get<dap::AnyTestObject>().n, 3.0); +} + +template <typename T> +class AnyT : public ::testing::Test { + protected: + template <typename T0, + typename = std::enable_if<std::is_same<T, T0>::value && + !std::is_same<T0, dap::null>::value>> + void check_val(const dap::any& any, const T0& expect) { + ASSERT_EQ(any.is<T>(), any.is<T0>()); + ASSERT_EQ(any.get<T>(), expect); + } + + // Special case for Null assignment, as we can assign nullptr_t to any but + // can't `get()` it + template <typename = dap::null> + void check_val(const dap::any& any, const dap::null& expect) { + ASSERT_EQ(nullptr, expect); + ASSERT_TRUE(any.is<dap::null>()); + } + + void check_type(const dap::any& any) { + ASSERT_EQ(any.is<dap::null>(), (std::is_same<T, dap::null>::value)); + ASSERT_EQ(any.is<dap::integer>(), (std::is_same<T, dap::integer>::value)); + ASSERT_EQ(any.is<dap::boolean>(), (std::is_same<T, dap::boolean>::value)); + ASSERT_EQ(any.is<dap::number>(), (std::is_same<T, dap::number>::value)); + ASSERT_EQ(any.is<dap::string>(), (std::is_same<T, dap::string>::value)); + ASSERT_EQ(any.is<dap::array<dap::string>>(), + (std::is_same<T, dap::array<dap::string>>::value)); + ASSERT_EQ(any.is<dap::AnyTestObject>(), + (std::is_same<T, dap::AnyTestObject>::value)); + } +}; +TYPED_TEST_SUITE_P(AnyT); + +TYPED_TEST_P(AnyT, CopyConstruct) { + auto val = TestValue<TypeParam>::value; + dap::any any(val); + this->check_type(any); + this->check_val(any, val); +} + +TYPED_TEST_P(AnyT, MoveConstruct) { + auto val = TestValue<TypeParam>::value; + dap::any any(std::move(val)); + this->check_type(any); + this->check_val(any, val); +} + +TYPED_TEST_P(AnyT, Assign) { + auto val = TestValue<TypeParam>::value; + dap::any any; + any = val; + this->check_type(any); + this->check_val(any, val); +} + +TYPED_TEST_P(AnyT, MoveAssign) { + auto val = TestValue<TypeParam>::value; + dap::any any; + any = std::move(val); + this->check_type(any); + this->check_val(any, val); +} + +TYPED_TEST_P(AnyT, RepeatedAssign) { + dap::string str = "hello world"; + auto val = TestValue<TypeParam>::value; + dap::any any; + any = str; + any = val; + this->check_type(any); + this->check_val(any, val); +} + +TYPED_TEST_P(AnyT, RepeatedMoveAssign) { + dap::string str = "hello world"; + auto val = TestValue<TypeParam>::value; + dap::any any; + any = std::move(str); + any = std::move(val); + this->check_type(any); + this->check_val(any, val); +} + +REGISTER_TYPED_TEST_SUITE_P(AnyT, + CopyConstruct, + MoveConstruct, + Assign, + MoveAssign, + RepeatedAssign, + RepeatedMoveAssign); + +using AnyTypes = ::testing::Types<dap::null, + dap::integer, + dap::boolean, + dap::number, + dap::string, + dap::array<dap::string>, + dap::AnyTestObject>; +INSTANTIATE_TYPED_TEST_SUITE_P(T, AnyT, AnyTypes); + +TEST(Any, Reset) { + dap::any any(dap::integer(10)); + ASSERT_TRUE(any.is<dap::integer>()); + any.reset(); + ASSERT_FALSE(any.is<dap::integer>()); +} |