UnitTests_HashMap.cpp #1

  • //
  • guest/
  • ququlala/
  • libsprawl/
  • mainline/
  • UnitTests/
  • UnitTests_HashMap.cpp
  • View
  • Commits
  • Open Download .zip Download (9 KB)
//#define SPRAWL_NO_VARIADIC_TEMPLATES

#include "../collections/HashMap.hpp"
#include "../string/String.hpp"

#include "gtest_helpers.hpp"
#include <gtest/gtest.h>

namespace CollectionTest
{
	class TestType
	{
	public:
		int key1;
		int key2;
		sprawl::String key3;

		int GetKey1() { return key1; }
		int GetKey2() { return key2; }
		sprawl::String GetKey3() { return key3; }

		TestType* operator->(){ return this; }

		TestType(int i, int j, sprawl::String const& k)
			: key1(i)
			, key2(j)
			, key3(k)
		{
			//
		}
	};

	int TestTypeAccessor(TestType* obj)
	{
		return obj->key2;
	}

	int TestTypeAccessor2(TestType const& obj)
	{
		return obj.key2;
	}
}

#include <memory>

using CollectionTest::TestType;
using CollectionTest::TestTypeAccessor;

class HashMapTest : public testing::Test
{
protected:
	virtual void SetUp() override
	{
		map.Insert(1, std::shared_ptr<TestType>(new TestType(1, 5, "str1")));
		map.Insert(2, std::shared_ptr<TestType>(new TestType(2, 6, "str2")));
		map.Insert(3, std::shared_ptr<TestType>(new TestType(3, 7, "str3")));
		map.Insert(4, std::shared_ptr<TestType>(new TestType(3, 8, "str4")));

		map2.Insert(1, std::shared_ptr<TestType>(new TestType(1, 5, "str1")));
		map2.Insert(2, std::shared_ptr<TestType>(new TestType(2, 6, "str2")));
		map2.Insert(3, std::shared_ptr<TestType>(new TestType(3, 7, "str3")));
		map2.Insert(4, std::shared_ptr<TestType>(new TestType(3, 8, "str4")));

		map3.Insert(1, std::shared_ptr<TestType>(new TestType(1, 5, "str1")));
		map3.Insert(2, std::shared_ptr<TestType>(new TestType(2, 6, "str2")));
		map3.Insert(3, std::shared_ptr<TestType>(new TestType(3, 7, "str3")));
		map3.Insert(4, std::shared_ptr<TestType>(new TestType(3, 8, "str4")));

		map4.Insert(1, TestType(1, 5, "str1"));
		map4.Insert(2, TestType(2, 6, "str2"));
		map4.Insert(3, TestType(3, 7, "str3"));
		map4.Insert(4, TestType(3, 8, "str4"));

		map5.Insert(1, TestType(1, 5, "str1"));
		map5.Insert(2, TestType(2, 6, "str2"));
		map5.Insert(3, TestType(3, 7, "str3"));
		map5.Insert(4, TestType(3, 8, "str4"));

		map6.Insert(1, TestType(1, 5, "str1"));
		map6.Insert(2, TestType(2, 6, "str2"));
		map6.Insert(3, TestType(3, 7, "str3"));
		map6.Insert(4, TestType(3, 8, "str4"));
	}

	sprawl::collections::HashMap<
		std::shared_ptr<TestType>
		, sprawl::KeyAccessor<std::shared_ptr<TestType>, int>
		, sprawl::PtrFunctionAccessor<TestType, int, &TestTypeAccessor, std::shared_ptr<TestType>>
		, sprawl::PtrMemberAccessor<TestType, sprawl::String, &TestType::GetKey3, std::shared_ptr<TestType>>
	> map;

	sprawl::collections::HashMap<
		std::shared_ptr<TestType>
		, sprawl::KeyAccessor<std::shared_ptr<TestType>, int>
		, sprawl::PtrFunctionAccessor<TestType, int, &TestTypeAccessor, std::shared_ptr<TestType>>
	> map2;

	sprawl::collections::HashMap<
		std::shared_ptr<TestType>
		, sprawl::KeyAccessor<std::shared_ptr<TestType>, int>
	> map3;

	sprawl::collections::HashMap<
		TestType
		, sprawl::KeyAccessor<TestType, int>
		, sprawl::FunctionAccessor<TestType, int, &TestTypeAccessor>
		, sprawl::MemberAccessor<TestType, sprawl::String, &TestType::GetKey3>
	> map4;

	sprawl::collections::HashMap<
		TestType
		, sprawl::KeyAccessor<TestType, int>
		, sprawl::FunctionAccessor<TestType, int, &TestTypeAccessor>
	> map5;

	sprawl::collections::HashMap<
		TestType
		, sprawl::KeyAccessor<TestType, int>
	> map6;
};

TEST_F(HashMapTest, LookupWorks)
{
	EXPECT_TRUE(map.Has<0>(1));
	EXPECT_TRUE(map.Has<0>(2));
	EXPECT_TRUE(map.Has<0>(3));
	EXPECT_TRUE(map.Has<0>(4));
	EXPECT_TRUE(map.Has<1>(5));
	EXPECT_TRUE(map.Has<1>(6));
	EXPECT_TRUE(map.Has<1>(7));
	EXPECT_TRUE(map.Has<1>(8));
	EXPECT_TRUE(map.Has("str1"));
	EXPECT_TRUE(map.Has("str2"));
	EXPECT_TRUE(map.Has("str3"));
	EXPECT_TRUE(map.Has("str4"));

	EXPECT_TRUE(map2.Has<0>(1));
	EXPECT_TRUE(map2.Has<0>(2));
	EXPECT_TRUE(map2.Has<0>(3));
	EXPECT_TRUE(map2.Has<0>(4));
	EXPECT_TRUE(map2.Has<1>(5));
	EXPECT_TRUE(map2.Has<1>(6));
	EXPECT_TRUE(map2.Has<1>(7));
	EXPECT_TRUE(map2.Has<1>(8));

	EXPECT_TRUE(map3.Has(1));
	EXPECT_TRUE(map3.Has(2));
	EXPECT_TRUE(map3.Has(3));
	EXPECT_TRUE(map3.Has(4));

	EXPECT_TRUE(map4.Has<0>(1));
	EXPECT_TRUE(map4.Has<0>(2));
	EXPECT_TRUE(map4.Has<0>(3));
	EXPECT_TRUE(map4.Has<0>(4));
	EXPECT_TRUE(map4.Has<1>(5));
	EXPECT_TRUE(map4.Has<1>(6));
	EXPECT_TRUE(map4.Has<1>(7));
	EXPECT_TRUE(map4.Has<1>(8));
	EXPECT_TRUE(map4.Has("str1"));
	EXPECT_TRUE(map4.Has("str2"));
	EXPECT_TRUE(map4.Has("str3"));
	EXPECT_TRUE(map4.Has("str4"));

	EXPECT_TRUE(map5.Has<0>(1));
	EXPECT_TRUE(map5.Has<0>(2));
	EXPECT_TRUE(map5.Has<0>(3));
	EXPECT_TRUE(map5.Has<0>(4));
	EXPECT_TRUE(map5.Has<1>(5));
	EXPECT_TRUE(map5.Has<1>(6));
	EXPECT_TRUE(map5.Has<1>(7));
	EXPECT_TRUE(map5.Has<1>(8));

	EXPECT_TRUE(map6.Has(1));
	EXPECT_TRUE(map6.Has(2));
	EXPECT_TRUE(map6.Has(3));
	EXPECT_TRUE(map6.Has(4));
}

TEST_F(HashMapTest, EraseWorks)
{
	map.Erase<0>(4);
	map2.Erase<0>(4);
	map3.Erase(4);
	map4.Erase<0>(4);
	map5.Erase<0>(4);
	map6.Erase(4);

	EXPECT_EQ(map.end(), map.find<0>(4));
	EXPECT_EQ(map.end(), map.find<1>(8));
	EXPECT_EQ(map.end(), map.find<2>("str4"));

	EXPECT_EQ(map2.end(), map2.find<0>(4));
	EXPECT_EQ(map2.end(), map2.find<1>(8));

	EXPECT_EQ(map3.end(), map3.find<0>(4));

	EXPECT_EQ(map4.end(), map4.find<0>(4));
	EXPECT_EQ(map4.end(), map4.find<1>(8));
	EXPECT_EQ(map4.end(), map4.find<2>("str4"));

	EXPECT_EQ(map5.end(), map5.find<0>(4));
	EXPECT_EQ(map5.end(), map5.find<1>(8));

	EXPECT_EQ(map6.end(), map6.find<0>(4));
}

TEST_F(HashMapTest, GetWorks)
{
	EXPECT_EQ(3, map.Get<0>(3)->key1);
	EXPECT_EQ(1, map.Get<1>(5)->key1);
	EXPECT_EQ(1, map.Get("str1")->key1);

	EXPECT_EQ(3, map2.Get<0>(3)->key1);
	EXPECT_EQ(1, map2.Get<1>(5)->key1);

	EXPECT_EQ(3, map3.Get<0>(3)->key1);

	EXPECT_EQ(3, map4.Get<0>(3)->key1);
	EXPECT_EQ(1, map4.Get<1>(5)->key1);
	EXPECT_EQ(1, map4.Get("str1")->key1);

	EXPECT_EQ(3, map5.Get<0>(3)->key1);
	EXPECT_EQ(1, map5.Get<1>(5)->key1);

	EXPECT_EQ(3, map6.Get<0>(3)->key1);
}

TEST(MultiKeyMapTest, MultipleKeyAccessorsWork)
{
	sprawl::collections::HashMap<
		int
		, sprawl::KeyAccessor<int, int>
		, sprawl::KeyAccessor<int, sprawl::String>
		, sprawl::KeyAccessor<int, double>
	> multiKeyMapTest;

	multiKeyMapTest.Insert(1, "one", 1.0, 1);
	multiKeyMapTest.Insert(2, "two", 2.0, 2);
	multiKeyMapTest.Insert(3, "three", 3.0, 3);
	multiKeyMapTest.Insert(4, "four", 4.0, 4);

	EXPECT_EQ(1, multiKeyMapTest.Get(1));
	EXPECT_EQ(1, multiKeyMapTest.Get("one"));
	EXPECT_EQ(1, multiKeyMapTest.Get(1.0));

	EXPECT_EQ(2, multiKeyMapTest.Get(2));
	EXPECT_EQ(2, multiKeyMapTest.Get("two"));
	EXPECT_EQ(2, multiKeyMapTest.Get(2.0));

	EXPECT_EQ(3, multiKeyMapTest.Get(3));
	EXPECT_EQ(3, multiKeyMapTest.Get("three"));
	EXPECT_EQ(3, multiKeyMapTest.Get(3.0));

	EXPECT_EQ(4, multiKeyMapTest.Get(4));
	EXPECT_EQ(4, multiKeyMapTest.Get("four"));
	EXPECT_EQ(4, multiKeyMapTest.Get(4.0));
}

//This just tests that these various aliases all compile. It doesn't run since it doesn't actually do anything; functionality's tested above.
void HashMapCompileTest()
{
	sprawl::collections::HashMap<TestType*, sprawl::KeyAccessor<TestType*, sprawl::String>> compileFailureWithImplicitConstruction;
	compileFailureWithImplicitConstruction.Insert("blah", nullptr);

	sprawl::collections::HashSet<sprawl::String> setTest;
	setTest.Insert("blah");

	sprawl::collections::BasicHashMap<sprawl::String, TestType*> basicHashMapCompileTest;
	basicHashMapCompileTest.Insert("blah", nullptr);

	sprawl::collections::BasicHashMap<long, long> copyConstructorTest;
	sprawl::collections::BasicHashMap<long, long> copyConstructorTest2(copyConstructorTest);
	copyConstructorTest2.Insert(0, 0);
	copyConstructorTest2.Get(0);

	sprawl::collections::FunctionHashMap<int, TestType, &TestTypeAccessor> functionHashMapCompileTest;
	functionHashMapCompileTest.Insert(TestType(1,2,"hi"));

	sprawl::collections::MemberHashMap<sprawl::String, TestType, &TestType::GetKey3> memberHashMapCompileTest;
	memberHashMapCompileTest.Insert(TestType(1,2,"hi"));

	sprawl::collections::PtrMemberHashMap<sprawl::String, TestType*, &TestType::GetKey3> ptrMemberHashMapCompileTest;
	ptrMemberHashMapCompileTest.Insert(new TestType(1,2,"hi"));

	sprawl::collections::PtrFunctionHashMap<int, TestType*, &TestTypeAccessor> ptrFunctionHashMapCompileTest;
	ptrFunctionHashMapCompileTest.Insert(new TestType(1,2,"hi"));

	sprawl::collections::PtrFunctionHashMap<int, std::shared_ptr<TestType>, &TestTypeAccessor> sharedPtrFunctionHashMapCompileTest;
	sharedPtrFunctionHashMapCompileTest.Insert(std::shared_ptr<TestType>(new TestType(1,2,"hi")));

	sprawl::collections::PtrMemberHashMap<sprawl::String, std::shared_ptr<TestType>, &TestType::GetKey3> sharedPtrMemberHashMapCompileTest;
	sharedPtrMemberHashMapCompileTest.Insert(std::shared_ptr<TestType>(new TestType(1,2,"hi")));
}
# Change User Description Committed
#1 23398 ququlala "Forking branch Mainline of shadauxcat-libsprawl to ququlala-libsprawl."
//guest/ShadauxCat/Sprawl/Mainline/UnitTests/UnitTests_HashMap.cpp
#9 16768 ShadauxCat Improvements to error handling in builds with exceptions disabled:

- In debug builds or with SPRAWL_ERRORSTATE_STRICT enabled, ErrorState will output a message to stderr and terminate if Get() is called when an error flag is set. (In release buils or with SPRAWL_ERRORSTATE_PERMISSIVE defined, Get() will return junk memory in this case.)
- In debug builds or with SPRAWL_ERRORSTATE_STRICT enabled, ErrorState will output a message to stderr and terminate if its destructor is called without checking the errorstate if an error is present (equivalent to an exception terminating the application if no catch() block is present for it).
- On linux builds and when running "Analyze" through visual studio, a warning will be issued if any function returning ErrorState has its return value ignored. (This only applies to builds with exceptions not enabled; when exceptions are enabled no warning is issued)
- Many functions that could return ErrorState were having their return values silently ignored in internal sprawl code so the user would not find out about errors if exceptions are disabled; now anything in sprawl code that calls a function returning ErrorState will either handle the error, or (in most cases) surface it back up to the user.
- As a positive side-effect of the warnings for ignoring ErrorState, several constructors that were capable of throwing exceptions are no longer capable of doing so.

#review-16769
#8 14163 ShadauxCat -Renamed HashMap functions to follow coding style.
Only begin, end, find, and variants are left lowercase, in keeping with C++ algorithm and range-based for support.
-Fixed some accounting issues with list and forwardlist; size wasn't properly being maintained.
-Made a small pedantic change to ThreadManager to ensure that m_numThreadsSynced got reset to 0 before the NotifyAll() to eliminate the miniscule potential for deadlock it would cause if it happened after another thread had already woken up.

#review-14164
#7 14146 ShadauxCat Moving a gtest-specific function out of String.hpp

#review-14147
#6 14144 ShadauxCat Switching unit tests to gtest.
100 is a decent number of tests to start with, but it needs to be more like 400 to test the current codebase.

#review-14145
#5 14081 ShadauxCat -Switching order of keys and values in HashMap::insert().
Keys now come first - a number of parameters equal to the number of keys. (Simple case is simply insert(key, value))
-Added move constructors to AccessorGroup so things can be inserted into the map via rvalue references
-Fixed ForwardList's copy constructor copying things in reverse and added a unit test to make sure it doesn't happen again.

#review-14079
#4 14068 ShadauxCat Fixed broken copy constructor in AccessorGroup with a KeyAccessor

#review-14069
#3 14066 ShadauxCat -Improved iterating in hashmap - range-based for now gives the ability to access both key and value instead of just value
-Slightly improved some of the template aliases
-Mega-deprecated VC11 support. Probably doesn't compile anymore. Maintaining it is too much of a headache.

#review-14067
#2 14015 ShadauxCat -Made reference counts in strings atomic
-Fixed an issue where items that were implicitly convertible to a hash map's value could not be inserted without explicit construction. (i.e., inserting a String object as map.insert("myString") would fail; it had to be map.insert(sprawl::String("myString")))
-Added template aliases for HashMap to simplify construction in simple single key/single value case
-Deprecated MSVC11 support.
#1 11496 ShadauxCat Initial checkin: Current states for csbuild and libSprawl