/*! * Copyright 2018 XGBoost contributors */ #include #include #include #include "test_span.h" namespace xgboost { namespace common { TEST(Span, TestStatus) { int status = 1; TestTestStatus {&status}(); ASSERT_EQ(status, -1); } TEST(Span, DlfConstructors) { // Dynamic extent { Span s; ASSERT_EQ(s.size(), 0); ASSERT_EQ(s.data(), nullptr); Span cs; ASSERT_EQ(cs.size(), 0); ASSERT_EQ(cs.data(), nullptr); } // Static extent { Span s; ASSERT_EQ(s.size(), 0); ASSERT_EQ(s.data(), nullptr); Span cs; ASSERT_EQ(cs.size(), 0); ASSERT_EQ(cs.data(), nullptr); } // Init list. { Span s {}; ASSERT_EQ(s.size(), 0); ASSERT_EQ(s.data(), nullptr); Span cs {}; ASSERT_EQ(cs.size(), 0); ASSERT_EQ(cs.data(), nullptr); } } TEST(Span, FromNullPtr) { // dynamic extent { Span s {nullptr, static_cast::index_type>(0)}; ASSERT_EQ(s.size(), 0); ASSERT_EQ(s.data(), nullptr); Span cs {nullptr, static_cast::index_type>(0)}; ASSERT_EQ(cs.size(), 0); ASSERT_EQ(cs.data(), nullptr); } // static extent { Span s {nullptr, static_cast::index_type>(0)}; ASSERT_EQ(s.size(), 0); ASSERT_EQ(s.data(), nullptr); Span cs {nullptr, static_cast::index_type>(0)}; ASSERT_EQ(cs.size(), 0); ASSERT_EQ(cs.data(), nullptr); } } TEST(Span, FromPtrLen) { float arr[16]; InitializeRange(arr, arr+16); // static extent { Span s (arr, 16); ASSERT_EQ (s.size(), 16); ASSERT_EQ (s.data(), arr); for (Span::index_type i = 0; i < 16; ++i) { ASSERT_EQ (s[i], arr[i]); } Span cs (arr, 16); ASSERT_EQ (cs.size(), 16); ASSERT_EQ (cs.data(), arr); for (Span::index_type i = 0; i < 16; ++i) { ASSERT_EQ (cs[i], arr[i]); } } // dynamic extent { Span s (arr, 16); ASSERT_EQ (s.size(), 16); ASSERT_EQ (s.data(), arr); for (size_t i = 0; i < 16; ++i) { ASSERT_EQ (s[i], arr[i]); } Span cs (arr, 16); ASSERT_EQ (cs.size(), 16); ASSERT_EQ (cs.data(), arr); for (Span::index_type i = 0; i < 16; ++i) { ASSERT_EQ (cs[i], arr[i]); } } } TEST(SpanDeathTest, FromPtrLen) { float arr[16]; InitializeRange(arr, arr+16); { auto lazy = [=]() {Span tmp (arr, 5);}; EXPECT_DEATH(lazy(), ""); } } TEST(Span, FromFirstLast) { float arr[16]; InitializeRange(arr, arr+16); // dynamic extent { Span s (arr, arr + 16); ASSERT_EQ (s.size(), 16); ASSERT_EQ (s.data(), arr); ASSERT_EQ (s.data() + s.size(), arr + 16); for (size_t i = 0; i < 16; ++i) { ASSERT_EQ (s[i], arr[i]); } Span cs (arr, arr + 16); ASSERT_EQ (cs.size(), 16); ASSERT_EQ (cs.data(), arr); ASSERT_EQ (cs.data() + cs.size(), arr + 16); for (size_t i = 0; i < 16; ++i) { ASSERT_EQ (cs[i], arr[i]); } } // static extent { Span s (arr, arr + 16); ASSERT_EQ (s.size(), 16); ASSERT_EQ (s.data(), arr); ASSERT_EQ (s.data() + s.size(), arr + 16); for (size_t i = 0; i < 16; ++i) { ASSERT_EQ (s[i], arr[i]); } Span cs (arr, arr + 16); ASSERT_EQ (cs.size(), 16); ASSERT_EQ (cs.data(), arr); ASSERT_EQ (cs.data() + cs.size(), arr + 16); for (size_t i = 0; i < 16; ++i) { ASSERT_EQ (cs[i], arr[i]); } } } struct BaseClass { virtual void operator()() {} }; struct DerivedClass : public BaseClass { void operator()() override {} }; TEST(Span, FromOther) { // convert constructor { Span derived; Span base { derived }; ASSERT_EQ(base.size(), derived.size()); ASSERT_EQ(base.data(), derived.data()); } float arr[16]; InitializeRange(arr, arr + 16); // default copy constructor { Span s0 (arr); Span s1 (s0); ASSERT_EQ(s0.size(), s1.size()); ASSERT_EQ(s0.data(), s1.data()); } } TEST(Span, FromArray) { float arr[16]; InitializeRange(arr, arr + 16); { Span s (arr); ASSERT_EQ(&arr[0], s.data()); ASSERT_EQ(s.size(), 16); for (size_t i = 0; i < 16; ++i) { ASSERT_EQ(arr[i], s[i]); } } { Span s (arr); ASSERT_EQ(&arr[0], s.data()); ASSERT_EQ(s.size(), 16); for (size_t i = 0; i < 16; ++i) { ASSERT_EQ(arr[i], s[i]); } } } TEST(Span, FromContainer) { std::vector vec (16); InitializeRange(vec.begin(), vec.end()); Span s(vec); ASSERT_EQ(s.size(), vec.size()); ASSERT_EQ(s.data(), vec.data()); bool res = std::equal(vec.begin(), vec.end(), s.begin()); ASSERT_TRUE(res); } TEST(Span, Assignment) { int status = 1; TestAssignment{&status}(); ASSERT_EQ(status, 1); } TEST(SpanIter, Construct) { int status = 1; TestIterConstruct{&status}(); ASSERT_EQ(status, 1); } TEST(SpanIter, Ref) { int status = 1; TestIterRef{&status}(); ASSERT_EQ(status, 1); } TEST(SpanIter, Calculate) { int status = 1; TestIterCalculate{&status}(); ASSERT_EQ(status, 1); } TEST(SpanIter, Compare) { int status = 1; TestIterCompare{&status}(); ASSERT_EQ(status, 1); } TEST(Span, BeginEnd) { int status = 1; TestBeginEnd{&status}(); ASSERT_EQ(status, 1); } TEST(Span, RBeginREnd) { int status = 1; TestRBeginREnd{&status}(); ASSERT_EQ(status, 1); } TEST(Span, ElementAccess) { float arr[16]; InitializeRange(arr, arr + 16); Span s (arr); size_t j = 0; for (auto i : s) { ASSERT_EQ(i, arr[j]); ++j; } } TEST(SpanDeathTest, ElementAccess) { float arr[16]; InitializeRange(arr, arr + 16); Span s (arr); EXPECT_DEATH(s[16], ""); EXPECT_DEATH(s[-1], ""); EXPECT_DEATH(s(16), ""); EXPECT_DEATH(s(-1), ""); } TEST(Span, Obversers) { int status = 1; TestObservers{&status}(); ASSERT_EQ(status, 1); } TEST(Span, FrontBack) { { float arr[4] {0, 1, 2, 3}; Span s(arr); ASSERT_EQ(s.front(), 0); ASSERT_EQ(s.back(), 3); } { std::vector arr {0, 1, 2, 3}; Span s(arr); ASSERT_EQ(s.front(), 0); ASSERT_EQ(s.back(), 3); } } TEST(SpanDeathTest, FrontBack) { { Span s; EXPECT_DEATH(s.front(), ""); EXPECT_DEATH(s.back(), ""); } { Span s; EXPECT_DEATH(s.front(), ""); EXPECT_DEATH(s.back(), ""); } } TEST(Span, FirstLast) { // static extent { float arr[16]; InitializeRange(arr, arr + 16); Span s (arr); Span first = s.first<4>(); ASSERT_EQ(first.size(), 4); ASSERT_EQ(first.data(), arr); for (size_t i = 0; i < first.size(); ++i) { ASSERT_EQ(first[i], arr[i]); } } { float arr[16]; InitializeRange(arr, arr + 16); Span s (arr); Span last = s.last<4>(); ASSERT_EQ(last.size(), 4); ASSERT_EQ(last.data(), arr + 12); for (size_t i = 0; i < last.size(); ++i) { ASSERT_EQ(last[i], arr[i+12]); } } // dynamic extent { float *arr = new float[16]; InitializeRange(arr, arr + 16); Span s (arr, 16); Span first = s.first(4); ASSERT_EQ(first.size(), 4); ASSERT_EQ(first.data(), s.data()); for (size_t i = 0; i < first.size(); ++i) { ASSERT_EQ(first[i], s[i]); } delete [] arr; } { float *arr = new float[16]; InitializeRange(arr, arr + 16); Span s (arr, 16); Span last = s.last(4); ASSERT_EQ(last.size(), 4); ASSERT_EQ(last.data(), s.data() + 12); for (size_t i = 0; i < last.size(); ++i) { ASSERT_EQ(s[12 + i], last[i]); } delete [] arr; } } TEST(SpanDeathTest, FirstLast) { // static extent { float arr[16]; InitializeRange(arr, arr + 16); Span s (arr); auto constexpr kOne = static_cast::index_type>(-1); EXPECT_DEATH(s.first(), ""); EXPECT_DEATH(s.first<17>(), ""); EXPECT_DEATH(s.first<32>(), ""); } { float arr[16]; InitializeRange(arr, arr + 16); Span s (arr); auto constexpr kOne = static_cast::index_type>(-1); EXPECT_DEATH(s.last(), ""); EXPECT_DEATH(s.last<17>(), ""); EXPECT_DEATH(s.last<32>(), ""); } // dynamic extent { float *arr = new float[16]; InitializeRange(arr, arr + 16); Span s (arr, 16); EXPECT_DEATH(s.first(-1), ""); EXPECT_DEATH(s.first(17), ""); EXPECT_DEATH(s.first(32), ""); delete [] arr; } { float *arr = new float[16]; InitializeRange(arr, arr + 16); Span s (arr, 16); EXPECT_DEATH(s.last(-1), ""); EXPECT_DEATH(s.last(17), ""); EXPECT_DEATH(s.last(32), ""); delete [] arr; } } TEST(Span, Subspan) { int arr[16] {0}; Span s1 (arr); auto s2 = s1.subspan<4>(); ASSERT_EQ(s1.size() - 4, s2.size()); auto s3 = s1.subspan(2, 4); ASSERT_EQ(s1.data() + 2, s3.data()); ASSERT_EQ(s3.size(), 4); auto s4 = s1.subspan(2, dynamic_extent); ASSERT_EQ(s1.data() + 2, s4.data()); ASSERT_EQ(s4.size(), s1.size() - 2); } TEST(SpanDeathTest, Subspan) { int arr[16] {0}; Span s1 (arr); EXPECT_DEATH(s1.subspan(-1, 0), ""); EXPECT_DEATH(s1.subspan(17, 0), ""); auto constexpr kOne = static_cast::index_type>(-1); EXPECT_DEATH(s1.subspan(), ""); EXPECT_DEATH(s1.subspan<17>(), ""); } TEST(Span, Compare) { int status = 1; TestCompare{&status}(); ASSERT_EQ(status, 1); } TEST(Span, AsBytes) { int status = 1; TestAsBytes{&status}(); ASSERT_EQ(status, 1); } TEST(Span, AsWritableBytes) { int status = 1; TestAsWritableBytes{&status}(); ASSERT_EQ(status, 1); } TEST(Span, Empty) { { Span s {nullptr, static_cast::index_type>(0)}; auto res = s.subspan(0); ASSERT_EQ(res.data(), nullptr); ASSERT_EQ(res.size(), 0); res = s.subspan(0, 0); ASSERT_EQ(res.data(), nullptr); ASSERT_EQ(res.size(), 0); } { Span s {nullptr, static_cast::index_type>(0)}; auto res = s.subspan(0); ASSERT_EQ(res.data(), nullptr); ASSERT_EQ(res.size(), 0); res = s.subspan(0, 0); ASSERT_EQ(res.data(), nullptr); ASSERT_EQ(res.size(), 0); } } TEST(SpanDeathTest, Empty) { std::vector data(1, 0); ASSERT_TRUE(data.data()); Span s{data.data(), Span::index_type(0)}; // ok to define 0 size span. EXPECT_DEATH(s[0], ""); // not ok to use it. } } // namespace common } // namespace xgboost