//------------------------------------------------------------------------------
// 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 <cstdio>
#include <exception>
#include <string>
#include <LampBasic.h>
#include "LampUnit/TestCase.h"
#include "LampUnit/TestResult.h"
#include "LampUnit/TestFailure.h"

namespace LampUnit{

//------------------------------------------------------------------------------
// コンストラクタ
TestCase::TestCase(Lamp::String name) : name_(name), result_(NULL){
}
//------------------------------------------------------------------------------
// コンストラクタ
TestCase::TestCase() : name_(""), result_(NULL){
}
//------------------------------------------------------------------------------
// テストを実行する
void TestCase::run(TestResult* result){
	result_ = result;
	result_->startTest(this);

	try{
		// テストのセットアップ
		setUp();

		// テストの実行
		try{
			runTest();
		}catch(std::exception& exception){
			TestFail(exception.what());
		}catch(...){
			TestFail("runTest() catchされていない例外が発生しました。");
		}

		// テストの後始末
		try{
			tearDown();
		}catch (...){
			TestFail("tearDown() catchされていない例外が発生しました。");
		}

	}catch(...){
		TestFail("setUp() catchされていない例外が発生しました。");
	}

	result_->endTest(this);
	result_ = NULL;
}
//------------------------------------------------------------------------------
// 失敗の追加
void TestCase::addFailure(
	const Lamp::String& message, const char* file, int line){
	TestFailure failure(this, message, file, line);
	result_->addFailure(failure);
}
//------------------------------------------------------------------------------
// 文字列の比較
bool TestCase::equals(const char* leftValue, const char* rightValue){
	if(leftValue == rightValue){ return true; }
	if((leftValue == NULL) || (rightValue == NULL)){ return false; }
	return (std::strcmp(leftValue, rightValue) == 0);
}
//------------------------------------------------------------------------------
// 値が同じでないメッセージ
Lamp::String TestCase::notEqualMessage(int expected, int actual){
	Lamp::String result;
	result.format(
		"期待される値は %d ですが実際の値は %d でした。",
		expected, actual);
	return result;
}
//------------------------------------------------------------------------------
// 値が同じでないメッセージ
Lamp::String TestCase::notEqualMessage(
	u_int expected, u_int actual){
	Lamp::String result;
	result.format(
		"期待される値は %u ですが実際の値は %u でした。",
		expected, actual);
	return result;
}
//------------------------------------------------------------------------------
// 値が同じでないメッセージ
Lamp::String TestCase::notEqualMessage(
	float expected, float actual, float epsilon){
	Lamp::String result;
	result.format(
		"期待される値は %.8f(0x%x) で、許容誤差は%.8fですが"
		"実際の値は %.8f(0x%x) でした。",
		expected, *(u_int*)&expected, epsilon, actual, *(u_int*)&actual);
	return result;
}
//------------------------------------------------------------------------------
// 値が同じでないメッセージ
Lamp::String TestCase::notEqualMessage(
	double expected, double actual, double epsilon){
	Lamp::String result;
	result.format(
		"期待される値は %.16f(0x%I64x) で、許容誤差は%.16fですが"
		"実際の値は %.16f(0x%I64x) でした。",
		expected, *(long long*)&expected, epsilon, actual, *(long long*)&actual);
	return result;
}
//------------------------------------------------------------------------------
// 文字列が同じでないメッセージ
Lamp::String TestCase::notEqualMessage(const char* expected, const char* actual){
	Lamp::String result("期待される文字列は ");
	if(expected == NULL){
		result.append("<NULL>");
	}else{
		result.append("\"").append(expected).append("\"");
	}
	result.append(" ですが実際の文字列は ");
	if(actual == NULL){
		result.append("<NULL>");
	}else{
		result.append("\"").append(actual).append("\"");
	}
	result.append(" でした。");
	return result;
}
//------------------------------------------------------------------------------
// 値が同じメッセージ
Lamp::String TestCase::equalMessage(int notExpected, int actual){
	Lamp::String result;
	result.format(
		"期待さない値は %d ですが実際の値は %d でした。",
		notExpected, actual);
	return result;
}
//------------------------------------------------------------------------------
// 値が同じメッセージ
Lamp::String TestCase::equalMessage(
	u_int notExpected, u_int actual){
	Lamp::String result;
	result.format(
		"期待さない値は %u ですが実際の値は %u でした。",
		notExpected, actual);
	return result;
}
//------------------------------------------------------------------------------
// 値が同じメッセージ
Lamp::String TestCase::equalMessage(
	float notExpected, float actual, float epsilon){
	Lamp::String result;
	result.format(
		"期待されない値は %.8f(0x%x) で、許容誤差は%.8fですが"
		"実際の値は %.8f(0x%x) でした。",
		notExpected, *(u_int*)&notExpected, epsilon, actual, *(u_int*)&actual);
	return result;
}
//------------------------------------------------------------------------------
// 値が同じメッセージ
Lamp::String TestCase::equalMessage(
	double notExpected, double actual, double epsilon){
	Lamp::String result;
	result.format(
		"期待されない値は %.16f(0x%I64x) で、許容誤差は%.16fですが"
		"実際の値は %.16f(0x%I64x) でした。",
		notExpected, *(long long*)&notExpected, epsilon,
		actual, *(long long*)&actual);
	return result;
}
//------------------------------------------------------------------------------
// 文字列が同じメッセージ
Lamp::String TestCase::equalMessage(const char* notExpected, const char* actual){
	Lamp::String result("期待されない文字列は ");
	if(notExpected == NULL){
		result.append("<NULL>");
	}else{
		result.append("\"").append(notExpected).append("\"");
	}
	result.append(" ですが実際の文字列は ");
	if(actual == NULL){
		result.append("<NULL>");
	}else{
		result.append("\"").append(actual).append("\"");
	}
	result.append(" でした。");
	return result;
}
//------------------------------------------------------------------------------
} // End of namespace LampUnit
//------------------------------------------------------------------------------
