/* * libfud * Copyright 2024 Dominick Allen * * 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 * * 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 "fud_vector.hpp" #include "gtest/gtest.h" namespace fud { TEST(VectorTest, TrivialVector) { Vector intVector{}; ASSERT_EQ(intVector.size(), 0); ASSERT_EQ(intVector.capacity(), 0); ASSERT_TRUE(intVector.ref(0).isError()); ASSERT_EQ(intVector.resize(10), FudStatus::Success); ASSERT_EQ(intVector.size(), 10); ASSERT_EQ(intVector.capacity(), 10); ASSERT_TRUE(intVector.ref(0).isOkay()); ASSERT_EQ(intVector.ref(0).getOkay(), 0); intVector.get(0).takeOkay().get() = 10; ASSERT_EQ(intVector.ref(0).getOkay(), 10); } struct NonTrivial { static thread_local int counter; NonTrivial() { counter++; } explicit NonTrivial(int val) : value{val} { counter++; } NonTrivial(const NonTrivial&) = delete; NonTrivial(NonTrivial&& rhs) : value{rhs.value}, destroyed{rhs.destroyed} { rhs.destroyed = true; } ~NonTrivial() { if (!destroyed) { counter--; destroyed = true; } } NonTrivial& operator=(const NonTrivial& rhs) = delete; NonTrivial& operator=(NonTrivial&& rhs) { value = rhs.value; destroyed = rhs.destroyed; rhs.destroyed = true; return *this; } int value{0}; bool destroyed{false}; }; int thread_local NonTrivial::counter = 0; TEST(VectorTest, NonTrivialVector) { auto& counter = NonTrivial::counter; counter = 0; Vector nonTrivialVector{}; ASSERT_EQ(nonTrivialVector.size(), 0); ASSERT_EQ(nonTrivialVector.capacity(), 0); ASSERT_TRUE(nonTrivialVector.ref(0).isError()); ASSERT_EQ(counter, 0); ASSERT_EQ(nonTrivialVector.resize(10), FudStatus::Success); ASSERT_EQ(nonTrivialVector.size(), 10); ASSERT_EQ(nonTrivialVector.capacity(), 10); ASSERT_EQ(counter, 10); ASSERT_TRUE(nonTrivialVector.ref(0).isOkay()); ASSERT_EQ(nonTrivialVector.ref(0).getOkay().get().value, 0); nonTrivialVector.get(0).takeOkay().get().value = 10; ASSERT_EQ(nonTrivialVector.ref(0).getOkay().get().value, 10); ASSERT_EQ(nonTrivialVector.pushBack(NonTrivial{42}), FudStatus::Success); ASSERT_EQ(nonTrivialVector.size(), 11); ASSERT_GE(nonTrivialVector.capacity(), 11); ASSERT_EQ(counter, 11); auto capacity = nonTrivialVector.capacity(); ASSERT_EQ(nonTrivialVector.reserve(SIZE_MAX / sizeof(NonTrivial)), FudStatus::AllocFailure); ASSERT_EQ(nonTrivialVector.capacity(), capacity); { auto popResult{nonTrivialVector.popBack()}; ASSERT_TRUE(popResult.isOkay()); auto value{popResult.takeOkay()}; ASSERT_EQ(value.value, 42); ASSERT_EQ(counter, 11); } ASSERT_EQ(counter, 10); ASSERT_EQ(nonTrivialVector.eraseBack(), FudStatus::Success); ASSERT_EQ(counter, 9); int val = 1; for (auto& element: nonTrivialVector) { element.value = val; val++; } ASSERT_EQ(nonTrivialVector.insert(3, NonTrivial{13}), FudStatus::Success); for (size_t idx = 0; idx < 3; ++idx) { ASSERT_EQ(nonTrivialVector[idx].value, idx + 1); } ASSERT_EQ(counter, 10); ASSERT_EQ(nonTrivialVector[3].value, 13); for (size_t idx = 4; idx < nonTrivialVector.size(); ++idx) { ASSERT_EQ(nonTrivialVector[idx].value, idx); } ASSERT_EQ(counter, nonTrivialVector.size()); ASSERT_EQ(nonTrivialVector.erase(3), FudStatus::Success); for (size_t idx = 0; idx < nonTrivialVector.size(); ++idx) { EXPECT_EQ(nonTrivialVector[idx].value, idx + 1); } ASSERT_EQ(counter, nonTrivialVector.size()); } } // namespace fud