// Copyright 2017 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/base/template-utils.h" #include "test/unittests/test-utils.h" namespace v8 { namespace base { namespace template_utils_unittest { //////////////////////////// // Test make_array. //////////////////////////// namespace { template void CheckArrayEquals(const std::array& arr1, const std::array& arr2) { for (size_t i = 0; i < Size; ++i) { CHECK_EQ(arr1[i], arr2[i]); } } } // namespace TEST(TemplateUtilsTest, MakeArraySimple) { auto computed_array = base::make_array<3>([](int i) { return 1 + (i * 3); }); std::array expected{{1, 4, 7}}; CheckArrayEquals(computed_array, expected); } namespace { constexpr int doubleIntValue(int i) { return i * 2; } } // namespace TEST(TemplateUtilsTest, MakeArrayConstexpr) { constexpr auto computed_array = base::make_array<3>(doubleIntValue); constexpr std::array expected{{0, 2, 4}}; CheckArrayEquals(computed_array, expected); } //////////////////////////// // Test pass_value_or_ref. //////////////////////////// // Wrap into this helper struct, such that the type is printed on errors. template struct CheckIsSame { static_assert(std::is_same::value, "test failure"); }; #define TEST_PASS_VALUE_OR_REF0(remove_extend, expected, given) \ static_assert( \ sizeof(CheckIsSame::type>) > 0, \ "check") #define TEST_PASS_VALUE_OR_REF(expected, given) \ static_assert( \ sizeof(CheckIsSame::type>) > 0, \ "check") TEST_PASS_VALUE_OR_REF(int, int&); TEST_PASS_VALUE_OR_REF(int, int&&); TEST_PASS_VALUE_OR_REF(const char*, const char[14]); TEST_PASS_VALUE_OR_REF(const char*, const char*&&); TEST_PASS_VALUE_OR_REF(const char*, const char (&)[14]); TEST_PASS_VALUE_OR_REF(const std::string&, std::string); TEST_PASS_VALUE_OR_REF(const std::string&, std::string&); TEST_PASS_VALUE_OR_REF(const std::string&, const std::string&); TEST_PASS_VALUE_OR_REF(int, const int); TEST_PASS_VALUE_OR_REF(int, const int&); TEST_PASS_VALUE_OR_REF(const int*, const int*); TEST_PASS_VALUE_OR_REF(const int*, const int* const); TEST_PASS_VALUE_OR_REF0(false, const char[14], const char[14]); TEST_PASS_VALUE_OR_REF0(false, const char[14], const char (&)[14]); TEST_PASS_VALUE_OR_REF0(false, const std::string&, std::string); TEST_PASS_VALUE_OR_REF0(false, const std::string&, std::string&); TEST_PASS_VALUE_OR_REF0(false, const std::string&, const std::string&); TEST_PASS_VALUE_OR_REF0(false, int, const int); TEST_PASS_VALUE_OR_REF0(false, int, const int&); ////////////////////////////// // Test has_output_operator. ////////////////////////////// // Intrinsic types: static_assert(has_output_operator::value, "int can be output"); static_assert(has_output_operator::value, "void* can be output"); static_assert(has_output_operator::value, "int can be output"); // Classes: class TestClass1 {}; class TestClass2 {}; extern std::ostream& operator<<(std::ostream& str, const TestClass2&); class TestClass3 {}; extern std::ostream& operator<<(std::ostream& str, TestClass3); static_assert(!has_output_operator::value, "TestClass1 can not be output"); static_assert(has_output_operator::value, "non-const TestClass2 can be output"); static_assert(has_output_operator::value, "const TestClass2 can be output"); static_assert(has_output_operator::value, "non-const TestClass3 can be output"); static_assert(has_output_operator::value, "const TestClass3 can be output"); } // namespace template_utils_unittest } // namespace base } // namespace v8