/* * libfud * Copyright 2025 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_hash_map.hpp" #include "fud_string.hpp" #include "fud_vector.hpp" // #include "test_common.hpp" #include "gtest/gtest.h" namespace fud { Vector testStrings() { Vector stringList{Vector::withCapacity(9).takeOkay()}; fudAssert(stringList.pushBack(String::makeFromCString("foo").takeOkay()) == FudStatus::Success); fudAssert(stringList.pushBack(String::makeFromCString("bar").takeOkay()) == FudStatus::Success); fudAssert(stringList.pushBack(String::makeFromCString("baz").takeOkay()) == FudStatus::Success); fudAssert(stringList.pushBack(String::makeFromCString("qux").takeOkay()) == FudStatus::Success); fudAssert(stringList.pushBack(String::makeFromCString("Tom").takeOkay()) == FudStatus::Success); fudAssert(stringList.pushBack(String::makeFromCString("Dick").takeOkay()) == FudStatus::Success); fudAssert(stringList.pushBack(String::makeFromCString("Harry").takeOkay()) == FudStatus::Success); fudAssert(stringList.pushBack(String::makeFromCString("Alice").takeOkay()) == FudStatus::Success); fudAssert(stringList.pushBack(String::makeFromCString("Bob").takeOkay()) == FudStatus::Success); return stringList; } Vector testStringViews() { Vector stringList{Vector::withCapacity(9).takeOkay()}; fudAssert(stringList.pushBack(StringView::makeFromCString("foo")) == FudStatus::Success); fudAssert(stringList.pushBack(StringView::makeFromCString("bar")) == FudStatus::Success); fudAssert(stringList.pushBack(StringView::makeFromCString("baz")) == FudStatus::Success); fudAssert(stringList.pushBack(StringView::makeFromCString("qux")) == FudStatus::Success); fudAssert(stringList.pushBack(StringView::makeFromCString("Tom")) == FudStatus::Success); fudAssert(stringList.pushBack(StringView::makeFromCString("Dick")) == FudStatus::Success); fudAssert(stringList.pushBack(StringView::makeFromCString("Harry")) == FudStatus::Success); fudAssert(stringList.pushBack(StringView::makeFromCString("Alice")) == FudStatus::Success); fudAssert(stringList.pushBack(StringView::makeFromCString("Bob")) == FudStatus::Success); return stringList; } TEST(FudHash, InsertMoveKeyMoveValue) { auto stringList{testStrings()}; HashMap mapInt2String{}; for (int index = 0; index < static_cast(stringList.size()); ++index) { auto insertStatus = mapInt2String.insert(index * 1, String::from(stringList[index]).takeOkay()); EXPECT_EQ(insertStatus, FudStatus::Success); } EXPECT_EQ(mapInt2String.size(), stringList.size()); EXPECT_GT(mapInt2String.capacity(), mapInt2String.size()); const String invalid{String::makeFromCString("Invalid").takeOkay()}; for (int index = 0; index < static_cast(stringList.size()); ++index) { EXPECT_EQ(mapInt2String.getConstRef(index).valueOr(invalid), stringList[index]); } } TEST(FudHash, InsertMoveKeyCopyValue) { auto stringList{testStrings()}; HashMap mapString2Int{}; for (int index = 0; index < static_cast(stringList.size()); ++index) { auto insertStatus = mapString2Int.insert(String::from(stringList[index]).takeOkay(), index * 1); EXPECT_EQ(insertStatus, FudStatus::Success); } EXPECT_EQ(mapString2Int.size(), stringList.size()); EXPECT_GT(mapString2Int.capacity(), mapString2Int.size()); for (int index = 0; index < static_cast(stringList.size()); ++index) { const int invalid = -1; EXPECT_EQ(mapString2Int.getConstRef(stringList[index]).valueOr(invalid), index); } for (int index = 0; index < static_cast(stringList.size()); ++index) { int invalid = -1; int& refVal = mapString2Int.getRef(stringList[index]).mutValueOr(invalid); refVal *= 2; EXPECT_EQ(mapString2Int.getConstRef(stringList[index]).valueOr(invalid), index * 2); } } TEST(FudHash, InsertCopyKeyMoveValue) { auto stringList{testStrings()}; HashMap mapInt2String{}; for (int index = 0; index < static_cast(stringList.size()); ++index) { auto insertStatus = mapInt2String.insert(index, String::from(stringList[index]).takeOkay()); EXPECT_EQ(insertStatus, FudStatus::Success); } EXPECT_EQ(mapInt2String.size(), stringList.size()); EXPECT_GT(mapInt2String.capacity(), mapInt2String.size()); const String invalid{String::makeFromCString("Invalid").takeOkay()}; for (int index = 0; index < static_cast(stringList.size()); ++index) { EXPECT_EQ(mapInt2String.getConstRef(index).valueOr(invalid), stringList[index]); } } TEST(FudHash, InsertCopyKeyCopyValue) { auto stringViewList{testStringViews()}; HashMap mapView2Int{}; for (int index = 0; index < static_cast(stringViewList.size()); ++index) { auto insertStatus = mapView2Int.insert(stringViewList[index], index); EXPECT_EQ(insertStatus, FudStatus::Success); } EXPECT_EQ(mapView2Int.size(), stringViewList.size()); EXPECT_GT(mapView2Int.capacity(), mapView2Int.size()); for (int index = 0; index < static_cast(stringViewList.size()); ++index) { const int invalid = -1; EXPECT_EQ(mapView2Int.getConstRef(stringViewList[index]).valueOr(invalid), index); } } TEST(FudHash, RemoveKeyConstRef) { auto stringList{testStrings()}; HashMap mapString2Int{}; for (int index = 0; index < static_cast(stringList.size()); ++index) { auto insertStatus = mapString2Int.insert(String::from(stringList[index]).takeOkay(), index * 1); EXPECT_EQ(insertStatus, FudStatus::Success); } EXPECT_EQ(mapString2Int.size(), stringList.size()); EXPECT_GT(mapString2Int.capacity(), mapString2Int.size()); for (int index = 0; index < static_cast(stringList.size()); ++index) { const int invalid = -1; EXPECT_EQ(mapString2Int.get(stringList[index]).valueOr(invalid), index); } for (const auto& entry : stringList) { EXPECT_EQ(mapString2Int.remove(entry), FudStatus::Success); } for (const auto& entry : stringList) { EXPECT_EQ(mapString2Int.remove(entry), FudStatus::NotFound); } for (const auto& entry : stringList) { const int invalid = -1; EXPECT_EQ(mapString2Int.get(entry).valueOr(invalid), invalid); } } TEST(FudHash, RemoveKeyMoveRef) { auto stringList{testStrings()}; HashMap mapInt2String{}; for (int index = 0; index < static_cast(stringList.size()); ++index) { auto insertStatus = mapInt2String.insert(index, String::from(stringList[index]).takeOkay()); EXPECT_EQ(insertStatus, FudStatus::Success); } EXPECT_EQ(mapInt2String.size(), stringList.size()); EXPECT_GT(mapInt2String.capacity(), mapInt2String.size()); const String invalid{String::makeFromCString("Invalid").takeOkay()}; for (int index = 0; index < static_cast(stringList.size()); ++index) { EXPECT_EQ(mapInt2String.getConstRef(index).valueOr(invalid), stringList[index]); } for (int index = 0; index < stringList.size(); ++index) { EXPECT_EQ(mapInt2String.remove(index * 1), FudStatus::Success); } for (int index = 0; index < stringList.size(); ++index) { EXPECT_EQ(mapInt2String.remove(index * 1), FudStatus::NotFound); } for (int index = 0; index < static_cast(stringList.size()); ++index) { EXPECT_EQ(mapInt2String.getConstRef(index).valueOr(invalid), invalid); } } } // namespace fud