X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2Ftest%2FTraitsTest.cpp;h=fa6b663749fc43e880baa06d31706364ca3bf1f2;hb=0917b8bd56401f43683061111d91a7cf0b194491;hp=83ffb43dfea9887fb23cb3362a5d24116b80162b;hpb=7d1d6185e473b56c9e7421e2e65cea54436b576d;p=folly.git diff --git a/folly/test/TraitsTest.cpp b/folly/test/TraitsTest.cpp index 83ffb43d..fa6b6637 100644 --- a/folly/test/TraitsTest.cpp +++ b/folly/test/TraitsTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2015 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,15 +14,37 @@ * limitations under the License. */ -#include #include -#include -#include +#include +#include +#include +#include + +#include +#include using namespace folly; using namespace std; +namespace { + +FOLLY_CREATE_HAS_MEMBER_TYPE_TRAITS(has_member_type_x, x); +} + +TEST(Traits, has_member_type) { + struct membership_no {}; + struct membership_yes { + using x = void; + }; + + EXPECT_TRUE((is_same>::value)); + EXPECT_TRUE((is_same>::value)); +} + +// Note: FOLLY_CREATE_HAS_MEMBER_FN_TRAITS tests are in +// folly/test/HasMemberFnTraitsTest.cpp. + struct T1 {}; // old-style IsRelocatable, below struct T2 {}; // old-style IsRelocatable, below struct T3 { typedef std::true_type IsRelocatable; }; @@ -48,7 +70,7 @@ TEST(Traits, scalars) { TEST(Traits, containers) { EXPECT_TRUE (IsRelocatable>::value); - EXPECT_FALSE((IsRelocatable>::value)); + EXPECT_TRUE((IsRelocatable>::value)); EXPECT_TRUE ((IsRelocatable>::value)); } @@ -65,8 +87,8 @@ TEST(Traits, typedefd) { } TEST(Traits, unset) { - EXPECT_FALSE(IsRelocatable::value); - EXPECT_FALSE(IsRelocatable::value); + EXPECT_TRUE(IsRelocatable::value); + EXPECT_TRUE(IsRelocatable::value); } TEST(Traits, bitprop) { @@ -81,6 +103,25 @@ TEST(Traits, bitAndInit) { EXPECT_FALSE(IsZeroInitializable>::value); } +TEST(Trait, logicOperators) { + static_assert(Conjunction::value, ""); + static_assert(!Conjunction::value, ""); + static_assert(is_same::type, true_type>::value, ""); + static_assert(is_same::type, false_type>::value, ""); + static_assert(Conjunction::value, ""); + static_assert(!Conjunction::value, ""); + + static_assert(Disjunction::value, ""); + static_assert(!Disjunction::value, ""); + static_assert(is_same::type, true_type>::value, ""); + static_assert(is_same::type, false_type>::value, ""); + static_assert(Disjunction::value, ""); + static_assert(Disjunction::value, ""); + + static_assert(!Negation::value, ""); + static_assert(Negation::value, ""); +} + TEST(Traits, is_negative) { EXPECT_TRUE(folly::is_negative(-1)); EXPECT_FALSE(folly::is_negative(0)); @@ -110,11 +151,88 @@ TEST(Traits, relational) { EXPECT_FALSE((folly::greater_than(254u))); } -int main(int argc, char ** argv) { - testing::InitGoogleTest(&argc, argv); - gflags::ParseCommandLineFlags(&argc, &argv, true); - if (FLAGS_benchmark) { - folly::runBenchmarks(); - } - return RUN_ALL_TESTS(); +#if FOLLY_HAVE_INT128_T + +TEST(Traits, int128) { + EXPECT_TRUE( + (::std::is_same<::std::make_unsigned<__int128_t>::type, __uint128_t>:: + value)); + EXPECT_TRUE(( + ::std::is_same<::std::make_signed<__int128_t>::type, __int128_t>::value)); + EXPECT_TRUE( + (::std::is_same<::std::make_unsigned<__uint128_t>::type, __uint128_t>:: + value)); + EXPECT_TRUE( + (::std::is_same<::std::make_signed<__uint128_t>::type, __int128_t>:: + value)); + EXPECT_TRUE((::std::is_arithmetic<__int128_t>::value)); + EXPECT_TRUE((::std::is_arithmetic<__uint128_t>::value)); + EXPECT_TRUE((::std::is_integral<__int128_t>::value)); + EXPECT_TRUE((::std::is_integral<__uint128_t>::value)); + EXPECT_FALSE((::std::is_unsigned<__int128_t>::value)); + EXPECT_TRUE((::std::is_signed<__int128_t>::value)); + EXPECT_TRUE((::std::is_unsigned<__uint128_t>::value)); + EXPECT_FALSE((::std::is_signed<__uint128_t>::value)); + EXPECT_TRUE((::std::is_fundamental<__int128_t>::value)); + EXPECT_TRUE((::std::is_fundamental<__uint128_t>::value)); + EXPECT_TRUE((::std::is_scalar<__int128_t>::value)); + EXPECT_TRUE((::std::is_scalar<__uint128_t>::value)); +} + +#endif // FOLLY_HAVE_INT128_T + +template +void testIsRelocatable(Args&&... args) { + if (!IsRelocatable::value) return; + + // We use placement new on zeroed memory to avoid garbage subsections + char vsrc[sizeof(T)] = { 0 }; + char vdst[sizeof(T)] = { 0 }; + char vcpy[sizeof(T)]; + + T* src = new (vsrc) T(std::forward(args)...); + SCOPE_EXIT { src->~T(); }; + std::memcpy(vcpy, vsrc, sizeof(T)); + T deep(*src); + T* dst = new (vdst) T(std::move(*src)); + SCOPE_EXIT { dst->~T(); }; + + EXPECT_EQ(deep, *dst); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" + EXPECT_EQ(deep, *reinterpret_cast(vcpy)); +#pragma GCC diagnostic pop + + // This test could technically fail; however, this is what relocation + // almost always means, so it's a good test to have + EXPECT_EQ(std::memcmp(vcpy, vdst, sizeof(T)), 0); +} + +TEST(Traits, actuallyRelocatable) { + // Ensure that we test stack and heap allocation for strings with in-situ + // capacity + testIsRelocatable("1"); + testIsRelocatable(sizeof(std::string) + 1, 'x'); + + testIsRelocatable>(5, 'g'); +} + +namespace { +// has_value_type::value is true if T has a nested type `value_type` +template +struct has_value_type : std::false_type {}; + +template +struct has_value_type> + : std::true_type {}; +} + +TEST(Traits, void_t) { + EXPECT_TRUE((::std::is_same, void>::value)); + EXPECT_TRUE((::std::is_same, void>::value)); + EXPECT_TRUE((::std::is_same, void>::value)); + EXPECT_TRUE( + (::std::is_same, void>::value)); + EXPECT_TRUE((::has_value_type::value)); + EXPECT_FALSE((::has_value_type::value)); }