//------------------------------------------------------------------------------
// Lamp : Open source game middleware
// Copyright (C) 2004  Junpei Ohtani ( Email : junpee@users.sourceforge.jp )
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//------------------------------------------------------------------------------

/** @file
 * ハッシュマップのテスト実装
 * @author Junpee
 */

#include "Test/stdafx.h"
#include "Core/Container/HashMapTest.h"
#include <Core/Container/HashMap.h>
#include <Core/Utility/Timer.h>

//------------------------------------------------------------------------------
// テストスィートの取得
Test* HashMapTest::suite(){
	TestSuite* suite = new TestSuite("HashMapTest");
	suite->addTest(new TestCaller(HashMapTest, testBasic));
	return suite;
}
//------------------------------------------------------------------------------
// 基本テスト
void HashMapTest::testBasic(){
	// アイテム初期化
	Timer::Tick tick;
	tick = Timer::getTick();
	int itemSize = 3072;
	String* items = new String[itemSize];
	char table[] = {
		'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
		'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
		'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
		'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
		'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_'};
	for(int i = 0;i < itemSize;i++){
		items[i].format("%c%c%c%c%c%c%c",
			table[rand() % 63], table[rand() % 63],
			table[rand() % 63], table[rand() % 63],
			table[rand() % 63], table[rand() % 63],
			table[rand() % 63], table[rand() % 63]);
	}
//	DebugOut("\nInitialize %.2fms\n", Timer::getInterval(tick));

	// 追加
	tick = Timer::getTick();
	HashMap<String, String*> hashMap(1, 0.75f);
	TestAssert(hashMap.isEmpty());
	TestEquals(0, hashMap.getCount());
	TestEquals(0.75f, hashMap.getLoadFactor());
	for(int i = 0;i < itemSize;i++){
		TestAssert(hashMap.put(items[i], &items[i]));
	}
	TestAssert(!hashMap.isEmpty());
	TestEquals(3072, hashMap.getCount());
	TestEquals(4096, hashMap.getCapacity());
	TestEquals(0.75f, hashMap.getLoadFactor());
//	DebugOut("\nAdd %.2fms\n", Timer::getInterval(tick));

	// 追加
	HashMap<String, String*> hashMap2(1, 1.f);
	TestAssert(hashMap2.put(items[0], &items[0]));
	TestEquals(1, hashMap2.getCapacity());
	TestAssert(hashMap2.put(items[1], &items[1]));
	TestEquals(2, hashMap2.getCapacity());
	TestAssert(hashMap2.put(items[2], &items[2]));
	TestEquals(4, hashMap2.getCapacity());
	TestAssert(hashMap2.put(items[3], &items[3]));
	TestEquals(4, hashMap2.getCapacity());
	TestAssert(hashMap2.put(items[4], &items[4]));
	TestEquals(8, hashMap2.getCapacity());
	hashMap2.clear();

	// クローン
	tick = Timer::getTick();
	HashMap<String, String*> hashMapClone(128, 0.1f);
	TestAssert(hashMapClone.isEmpty());
	TestEquals(0, hashMapClone.getCount());
	TestEquals(128, hashMapClone.getCapacity());
	TestEquals(0.1f, hashMapClone.getLoadFactor());
	hashMap.cloneTo(&hashMapClone);
	TestAssert(!hashMapClone.isEmpty());
	TestEquals(3072, hashMapClone.getCount());
	TestEquals(4096, hashMapClone.getCapacity());
	TestEquals(0.75f, hashMapClone.getLoadFactor());
	hashMapClone.clear();
	TestEquals(0, hashMapClone.getCount());
	TestEquals(4096, hashMapClone.getCapacity());
	hashMapClone.trim();
	TestEquals(0, hashMapClone.getCount());
	TestEquals(1, hashMapClone.getCapacity());
//	DebugOut("\nClone %.2fms\n", Timer::getInterval(tick));

	// 配列化
	ArrayList< HashMap<String, String*>::HashData<String, String*> > array;
	hashMap.toArray(&array);
	TestEquals(itemSize, array.getCount());
	TestEquals(itemSize, array.getCapacity());

	tick = Timer::getTick();
	// 取得
	for(int i = 0;i < itemSize;i++){
		TestEquals(items[i], *hashMap.get(items[i]));
	}
//	DebugOut("\nGet %.2fms\n", Timer::getInterval(tick));

	// 削除
	tick = Timer::getTick();
	for(int i = 0;i < itemSize / 2;i++){
		TestEquals(items[i], *hashMap.remove(items[i]));
	}
//	DebugOut("\nRemove %.2fms\n", Timer::getInterval(tick));
	TestEquals(1536, hashMap.getCount());
	TestEquals(4096, hashMap.getCapacity());
	hashMap.trim();
	TestEquals(1536, hashMap.getCount());
	TestEquals(2048, hashMap.getCapacity());

	tick = Timer::getTick();
	hashMap.clear();
//	DebugOut("\nClear %.2fms\n", Timer::getInterval(tick));
	TestAssert(hashMap.isEmpty());
	TestEquals(0, hashMap.getCount());
	TestEquals(2048, hashMap.getCapacity());
	// 後始末
	delete[] items;
}
//------------------------------------------------------------------------------
