From f05d85181109840dea131f46258f4cf2f747eb41 Mon Sep 17 00:00:00 2001 From: Marco Costa Date: Mon, 1 Jun 2015 21:41:40 -0400 Subject: [PATCH] Create simple test framework * Run all tests by passing "test" as a command line argument to 'openrct2' * Using CuTest 1.5 as a test framework --- lib/cutest/CuTest.c | 339 +++++++++++++++++++++++++++++ lib/cutest/CuTest.h | 116 ++++++++++ lib/cutest/license.txt | 38 ++++ projects/libs/libs.vcxproj | 4 +- projects/libs/libs.vcxproj.filters | 9 + projects/openrct2.vcxproj | 6 +- projects/openrct2.vcxproj.filters | 17 ++ src/cmdline.c | 10 +- src/management/finance.c | 20 ++ src/management/finance.h | 4 + src/openrct2.c | 6 + src/openrct2.h | 3 +- src/scenario.h | 1 + src/scenario_list.c | 2 +- src/test/management/finance_test.c | 60 +++++ src/test/management/finance_test.h | 30 +++ src/test/tests.c | 54 +++++ src/test/tests.h | 43 ++++ 18 files changed, 757 insertions(+), 5 deletions(-) create mode 100644 lib/cutest/CuTest.c create mode 100644 lib/cutest/CuTest.h create mode 100644 lib/cutest/license.txt create mode 100644 src/test/management/finance_test.c create mode 100644 src/test/management/finance_test.h create mode 100644 src/test/tests.c create mode 100644 src/test/tests.h diff --git a/lib/cutest/CuTest.c b/lib/cutest/CuTest.c new file mode 100644 index 0000000000..8f611991a8 --- /dev/null +++ b/lib/cutest/CuTest.c @@ -0,0 +1,339 @@ +#include +#include +#include +#include +#include +#include + +#include "CuTest.h" + +/*-------------------------------------------------------------------------* + * CuStr + *-------------------------------------------------------------------------*/ + +char* CuStrAlloc(int size) +{ + char* newStr = (char*) malloc( sizeof(char) * (size) ); + return newStr; +} + +char* CuStrCopy(const char* old) +{ + int len = strlen(old); + char* newStr = CuStrAlloc(len + 1); + strcpy(newStr, old); + return newStr; +} + +/*-------------------------------------------------------------------------* + * CuString + *-------------------------------------------------------------------------*/ + +void CuStringInit(CuString* str) +{ + str->length = 0; + str->size = STRING_MAX; + str->buffer = (char*) malloc(sizeof(char) * str->size); + str->buffer[0] = '\0'; +} + +CuString* CuStringNew(void) +{ + CuString* str = (CuString*) malloc(sizeof(CuString)); + str->length = 0; + str->size = STRING_MAX; + str->buffer = (char*) malloc(sizeof(char) * str->size); + str->buffer[0] = '\0'; + return str; +} + +void CuStringDelete(CuString *str) +{ + if (!str) return; + free(str->buffer); + free(str); +} + +void CuStringResize(CuString* str, int newSize) +{ + str->buffer = (char*) realloc(str->buffer, sizeof(char) * newSize); + str->size = newSize; +} + +void CuStringAppend(CuString* str, const char* text) +{ + int length; + + if (text == NULL) { + text = "NULL"; + } + + length = strlen(text); + if (str->length + length + 1 >= str->size) + CuStringResize(str, str->length + length + 1 + STRING_INC); + str->length += length; + strcat(str->buffer, text); +} + +void CuStringAppendChar(CuString* str, char ch) +{ + char text[2]; + text[0] = ch; + text[1] = '\0'; + CuStringAppend(str, text); +} + +void CuStringAppendFormat(CuString* str, const char* format, ...) +{ + va_list argp; + char buf[HUGE_STRING_LEN]; + va_start(argp, format); + vsprintf(buf, format, argp); + va_end(argp); + CuStringAppend(str, buf); +} + +void CuStringInsert(CuString* str, const char* text, int pos) +{ + int length = strlen(text); + if (pos > str->length) + pos = str->length; + if (str->length + length + 1 >= str->size) + CuStringResize(str, str->length + length + 1 + STRING_INC); + memmove(str->buffer + pos + length, str->buffer + pos, (str->length - pos) + 1); + str->length += length; + memcpy(str->buffer + pos, text, length); +} + +/*-------------------------------------------------------------------------* + * CuTest + *-------------------------------------------------------------------------*/ + +void CuTestInit(CuTest* t, const char* name, TestFunction function) +{ + t->name = CuStrCopy(name); + t->failed = 0; + t->ran = 0; + t->message = NULL; + t->function = function; + t->jumpBuf = NULL; +} + +CuTest* CuTestNew(const char* name, TestFunction function) +{ + CuTest* tc = CU_ALLOC(CuTest); + CuTestInit(tc, name, function); + return tc; +} + +void CuTestDelete(CuTest *t) +{ + if (!t) return; + free(t->name); + free(t); +} + +void CuTestRun(CuTest* tc) +{ + jmp_buf buf; + tc->jumpBuf = &buf; + if (setjmp(buf) == 0) + { + tc->ran = 1; + (tc->function)(tc); + } + tc->jumpBuf = 0; +} + +static void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string) +{ + char buf[HUGE_STRING_LEN]; + + sprintf(buf, "%s:%d: ", file, line); + CuStringInsert(string, buf, 0); + + tc->failed = 1; + tc->message = string->buffer; + if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0); +} + +void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message) +{ + CuString string; + + CuStringInit(&string); + if (message2 != NULL) + { + CuStringAppend(&string, message2); + CuStringAppend(&string, ": "); + } + CuStringAppend(&string, message); + CuFailInternal(tc, file, line, &string); +} + +void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition) +{ + if (condition) return; + CuFail_Line(tc, file, line, NULL, message); +} + +void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, + const char* expected, const char* actual) +{ + CuString string; + if ((expected == NULL && actual == NULL) || + (expected != NULL && actual != NULL && + strcmp(expected, actual) == 0)) + { + return; + } + + CuStringInit(&string); + if (message != NULL) + { + CuStringAppend(&string, message); + CuStringAppend(&string, ": "); + } + CuStringAppend(&string, "expected <"); + CuStringAppend(&string, expected); + CuStringAppend(&string, "> but was <"); + CuStringAppend(&string, actual); + CuStringAppend(&string, ">"); + CuFailInternal(tc, file, line, &string); +} + +void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, + int expected, int actual) +{ + char buf[STRING_MAX]; + if (expected == actual) return; + sprintf(buf, "expected <%d> but was <%d>", expected, actual); + CuFail_Line(tc, file, line, message, buf); +} + +void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, + double expected, double actual, double delta) +{ + char buf[STRING_MAX]; + if (fabs(expected - actual) <= delta) return; + sprintf(buf, "expected <%f> but was <%f>", expected, actual); + + CuFail_Line(tc, file, line, message, buf); +} + +void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, + void* expected, void* actual) +{ + char buf[STRING_MAX]; + if (expected == actual) return; + sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual); + CuFail_Line(tc, file, line, message, buf); +} + + +/*-------------------------------------------------------------------------* + * CuSuite + *-------------------------------------------------------------------------*/ + +void CuSuiteInit(CuSuite* testSuite) +{ + testSuite->count = 0; + testSuite->failCount = 0; + memset(testSuite->list, 0, sizeof(testSuite->list)); +} + +CuSuite* CuSuiteNew(void) +{ + CuSuite* testSuite = CU_ALLOC(CuSuite); + CuSuiteInit(testSuite); + return testSuite; +} + +void CuSuiteDelete(CuSuite *testSuite) +{ + unsigned int n; + for (n=0; n < MAX_TEST_CASES; n++) + { + if (testSuite->list[n]) + { + CuTestDelete(testSuite->list[n]); + } + } + free(testSuite); + +} + +void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase) +{ + assert(testSuite->count < MAX_TEST_CASES); + testSuite->list[testSuite->count] = testCase; + testSuite->count++; +} + +void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2) +{ + int i; + for (i = 0 ; i < testSuite2->count ; ++i) + { + CuTest* testCase = testSuite2->list[i]; + CuSuiteAdd(testSuite, testCase); + } +} + +void CuSuiteRun(CuSuite* testSuite) +{ + int i; + for (i = 0 ; i < testSuite->count ; ++i) + { + CuTest* testCase = testSuite->list[i]; + CuTestRun(testCase); + if (testCase->failed) { testSuite->failCount += 1; } + } +} + +void CuSuiteSummary(CuSuite* testSuite, CuString* summary) +{ + int i; + for (i = 0 ; i < testSuite->count ; ++i) + { + CuTest* testCase = testSuite->list[i]; + CuStringAppend(summary, testCase->failed ? "F" : "."); + } + CuStringAppend(summary, "\n\n"); +} + +void CuSuiteDetails(CuSuite* testSuite, CuString* details) +{ + int i; + int failCount = 0; + + if (testSuite->failCount == 0) + { + int passCount = testSuite->count - testSuite->failCount; + const char* testWord = passCount == 1 ? "test" : "tests"; + CuStringAppendFormat(details, "OK (%d %s)\n", passCount, testWord); + } + else + { + if (testSuite->failCount == 1) + CuStringAppend(details, "There was 1 failure:\n"); + else + CuStringAppendFormat(details, "There were %d failures:\n", testSuite->failCount); + + for (i = 0 ; i < testSuite->count ; ++i) + { + CuTest* testCase = testSuite->list[i]; + if (testCase->failed) + { + failCount++; + CuStringAppendFormat(details, "%d) %s: %s\n", + failCount, testCase->name, testCase->message); + } + } + CuStringAppend(details, "\n!!!FAILURES!!!\n"); + + CuStringAppendFormat(details, "Runs: %d ", testSuite->count); + CuStringAppendFormat(details, "Passes: %d ", testSuite->count - testSuite->failCount); + CuStringAppendFormat(details, "Fails: %d\n", testSuite->failCount); + } +} diff --git a/lib/cutest/CuTest.h b/lib/cutest/CuTest.h new file mode 100644 index 0000000000..8b32773d2b --- /dev/null +++ b/lib/cutest/CuTest.h @@ -0,0 +1,116 @@ +#ifndef CU_TEST_H +#define CU_TEST_H + +#include +#include + +#define CUTEST_VERSION "CuTest 1.5" + +/* CuString */ + +char* CuStrAlloc(int size); +char* CuStrCopy(const char* old); + +#define CU_ALLOC(TYPE) ((TYPE*) malloc(sizeof(TYPE))) + +#define HUGE_STRING_LEN 8192 +#define STRING_MAX 256 +#define STRING_INC 256 + +typedef struct +{ + int length; + int size; + char* buffer; +} CuString; + +void CuStringInit(CuString* str); +CuString* CuStringNew(void); +void CuStringRead(CuString* str, const char* path); +void CuStringAppend(CuString* str, const char* text); +void CuStringAppendChar(CuString* str, char ch); +void CuStringAppendFormat(CuString* str, const char* format, ...); +void CuStringInsert(CuString* str, const char* text, int pos); +void CuStringResize(CuString* str, int newSize); +void CuStringDelete(CuString* str); + +/* CuTest */ + +typedef struct CuTest CuTest; + +typedef void (*TestFunction)(CuTest *); + +struct CuTest +{ + char* name; + TestFunction function; + int failed; + int ran; + const char* message; + jmp_buf *jumpBuf; +}; + +void CuTestInit(CuTest* t, const char* name, TestFunction function); +CuTest* CuTestNew(const char* name, TestFunction function); +void CuTestRun(CuTest* tc); +void CuTestDelete(CuTest *t); + +/* Internal versions of assert functions -- use the public versions */ +void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message); +void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition); +void CuAssertStrEquals_LineMsg(CuTest* tc, + const char* file, int line, const char* message, + const char* expected, const char* actual); +void CuAssertIntEquals_LineMsg(CuTest* tc, + const char* file, int line, const char* message, + int expected, int actual); +void CuAssertDblEquals_LineMsg(CuTest* tc, + const char* file, int line, const char* message, + double expected, double actual, double delta); +void CuAssertPtrEquals_LineMsg(CuTest* tc, + const char* file, int line, const char* message, + void* expected, void* actual); + +/* public assert functions */ + +#define CuFail(tc, ms) CuFail_Line( (tc), __FILE__, __LINE__, NULL, (ms)) +#define CuAssert(tc, ms, cond) CuAssert_Line((tc), __FILE__, __LINE__, (ms), (cond)) +#define CuAssertTrue(tc, cond) CuAssert_Line((tc), __FILE__, __LINE__, "assert failed", (cond)) + +#define CuAssertStrEquals(tc,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) +#define CuAssertStrEquals_Msg(tc,ms,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) +#define CuAssertIntEquals(tc,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) +#define CuAssertIntEquals_Msg(tc,ms,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) +#define CuAssertDblEquals(tc,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac),(dl)) +#define CuAssertDblEquals_Msg(tc,ms,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac),(dl)) +#define CuAssertPtrEquals(tc,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac)) +#define CuAssertPtrEquals_Msg(tc,ms,ex,ac) CuAssertPtrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac)) + +#define CuAssertPtrNotNull(tc,p) CuAssert_Line((tc),__FILE__,__LINE__,"null pointer unexpected",(p != NULL)) +#define CuAssertPtrNotNullMsg(tc,msg,p) CuAssert_Line((tc),__FILE__,__LINE__,(msg),(p != NULL)) + +/* CuSuite */ + +#define MAX_TEST_CASES 1024 + +#define SUITE_ADD_TEST(SUITE,TEST) CuSuiteAdd(SUITE, CuTestNew(#TEST, TEST)) + +typedef struct +{ + int count; + CuTest* list[MAX_TEST_CASES]; + int failCount; + +} CuSuite; + + +void CuSuiteInit(CuSuite* testSuite); +CuSuite* CuSuiteNew(void); +void CuSuiteDelete(CuSuite *testSuite); +void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase); +void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2); +void CuSuiteRun(CuSuite* testSuite); +void CuSuiteSummary(CuSuite* testSuite, CuString* summary); +void CuSuiteDetails(CuSuite* testSuite, CuString* details); + +#endif /* CU_TEST_H */ diff --git a/lib/cutest/license.txt b/lib/cutest/license.txt new file mode 100644 index 0000000000..fd81689df4 --- /dev/null +++ b/lib/cutest/license.txt @@ -0,0 +1,38 @@ +NOTE + +The license is based on the zlib/libpng license. For more details see +http://www.opensource.org/licenses/zlib-license.html. The intent of the +license is to: + +- keep the license as simple as possible +- encourage the use of CuTest in both free and commercial applications + and libraries +- keep the source code together +- give credit to the CuTest contributors for their work + +If you ship CuTest in source form with your source distribution, the +following license document must be included with it in unaltered form. +If you find CuTest useful we would like to hear about it. + +LICENSE + +Copyright (c) 2003 Asim Jalis + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software in +a product, an acknowledgment in the product documentation would be +appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not +be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. diff --git a/projects/libs/libs.vcxproj b/projects/libs/libs.vcxproj index 61f4192ac0..4ede5f73ef 100644 --- a/projects/libs/libs.vcxproj +++ b/projects/libs/libs.vcxproj @@ -46,7 +46,7 @@ $(SolutionDir)..\build\$(Configuration)\ $(SolutionDir)..\obj\$(ProjectName)\$(Configuration)\ - ..\..\lib\libcurl\include;..\..\lib\jansson;$(IncludePath) + ..\..\lib\libcurl\include;..\..\lib\jansson;..\..\lib\cutest\CuTest.h;$(IncludePath) ..\..\lib\libcurl\lib;$(LibraryPath) @@ -92,6 +92,7 @@ TurnOffAllWarnings TurnOffAllWarnings + @@ -111,6 +112,7 @@ + diff --git a/projects/libs/libs.vcxproj.filters b/projects/libs/libs.vcxproj.filters index aa45a3eec6..3f0add7eba 100644 --- a/projects/libs/libs.vcxproj.filters +++ b/projects/libs/libs.vcxproj.filters @@ -19,6 +19,9 @@ {16ee6cb9-307a-4e8a-8261-a69d91b17739} + + {92e56bd7-37be-465c-9212-3b6cfb8cf7c9} + @@ -63,6 +66,9 @@ jansson + + cutest + @@ -113,5 +119,8 @@ jansson + + cutest + \ No newline at end of file diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj index 7ffaf599b9..d4730df9bb 100644 --- a/projects/openrct2.vcxproj +++ b/projects/openrct2.vcxproj @@ -83,6 +83,8 @@ + + @@ -216,6 +218,8 @@ + + @@ -278,7 +282,7 @@ $(SolutionDir)..\obj\$(ProjectName)\$(Configuration)\ - $(SolutionDir)..\lib;$(SolutionDir)..\lib\libspeex;$(SolutionDir)..\lib\sdl\include;$(SolutionDir)..\lib\libcurl\include;$(SolutionDir)..\lib\jansson;$(IncludePath) + $(SolutionDir)..\lib;$(SolutionDir)..\lib\libspeex;$(SolutionDir)..\lib\sdl\include;$(SolutionDir)..\lib\libcurl\include;$(SolutionDir)..\lib\jansson;$(SolutionDir)..\lib\cutest;$(IncludePath) $(SolutionDir)..\lib\sdl\lib\x86;$(SolutionDir)..\lib\libcurl\lib;$(LibraryPath) $(SolutionDir)..\build\$(Configuration)\ $(SolutionDir)..\obj\$(ProjectName)\$(Configuration)\ diff --git a/projects/openrct2.vcxproj.filters b/projects/openrct2.vcxproj.filters index b4708cd894..251ebe5351 100644 --- a/projects/openrct2.vcxproj.filters +++ b/projects/openrct2.vcxproj.filters @@ -44,6 +44,12 @@ {ae88ed08-902b-4167-a78c-9b521ce67749} + + {9b842d7a-225e-4ba9-807d-1cb6ebacbdd0} + + + {73238872-312d-437f-8497-7cb66466d835} + @@ -455,6 +461,11 @@ Source\Windows + + Source\Test + + + Source\Test\Management @@ -671,5 +682,11 @@ Source\Interface + + Source\Test + + + Source\Test\Management + \ No newline at end of file diff --git a/src/cmdline.c b/src/cmdline.c index b61452922f..9dd01d4e2f 100644 --- a/src/cmdline.c +++ b/src/cmdline.c @@ -123,6 +123,13 @@ static int cmdline_for_edit(const char **argv, int argc) return 0; } +static int cmdline_for_test(const char **argv, int argc) +{ + gOpenRCT2StartupAction = STARTUP_ACTION_TEST; + gOpenRCT2Headless = true; + return 0; +} + static int cmdline_for_none(const char **argv, int argc) { assert(argc >= 1); @@ -141,7 +148,8 @@ struct { const char *firstArg; cmdline_action action; } cmdline_table[] = { { "intro", cmdline_for_intro }, { "edit", cmdline_for_edit }, { "sprite", cmdline_for_sprite }, - { "screenshot", cmdline_for_screenshot } + { "screenshot", cmdline_for_screenshot }, + { "test", cmdline_for_test } }; static int cmdline_call_action(const char **argv, int argc) diff --git a/src/management/finance.c b/src/management/finance.c index 708dbb0582..00db151578 100644 --- a/src/management/finance.c +++ b/src/management/finance.c @@ -258,6 +258,26 @@ void finance_set_loan(money32 loan) game_do_command(0, GAME_COMMAND_FLAG_APPLY, 0, loan, GAME_COMMAND_SET_CURRENT_LOAN, 0, 0); } +money32 finance_get_initial_cash() +{ + return RCT2_GLOBAL(RCT2_ADDRESS_INITIAL_CASH, money32); +} + +money32 finance_get_current_loan() +{ + return RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_LOAN, money32); +} + +money32 finance_get_maximum_loan() +{ + return RCT2_GLOBAL(RCT2_ADDRESS_MAXIMUM_LOAN, money32); +} + +money32 finance_get_current_cash() +{ + return DECRYPT_MONEY(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, money32)); +} + /** * * rct2: 0x0069DFB3 diff --git a/src/management/finance.h b/src/management/finance.h index 9a8b10e24a..e16d04d787 100644 --- a/src/management/finance.h +++ b/src/management/finance.h @@ -60,6 +60,10 @@ void finance_shift_expenditure_table(); void sub_69E869(); void finance_set_loan(money32 loan); +money32 finance_get_initial_cash(); +money32 finance_get_current_loan(); +money32 finance_get_maximum_loan(); +money32 finance_get_current_cash(); void game_command_set_current_loan(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); #endif \ No newline at end of file diff --git a/src/openrct2.c b/src/openrct2.c index 6721a5e008..2dca14c33b 100644 --- a/src/openrct2.c +++ b/src/openrct2.c @@ -30,6 +30,7 @@ #include "platform/platform.h" #include "util/sawyercoding.h" #include "world/mapgen.h" +#include "test/tests.h" int gOpenRCT2StartupAction = STARTUP_ACTION_TITLE; char gOpenRCT2StartupActionPath[512] = { 0 }; @@ -186,6 +187,11 @@ void openrct2_launch() editor_load_landscape(gOpenRCT2StartupActionPath); } break; + case STARTUP_ACTION_TEST: + gExitCode = run_all_tests(); + openrct2_dispose(); + exit(gExitCode); + return; } openrct2_loop(); } diff --git a/src/openrct2.h b/src/openrct2.h index d2452d5389..1b6e137d30 100644 --- a/src/openrct2.h +++ b/src/openrct2.h @@ -27,7 +27,8 @@ enum { STARTUP_ACTION_INTRO, STARTUP_ACTION_TITLE, STARTUP_ACTION_OPEN, - STARTUP_ACTION_EDIT + STARTUP_ACTION_EDIT, + STARTUP_ACTION_TEST }; extern int gOpenRCT2StartupAction; diff --git a/src/scenario.h b/src/scenario.h index 91eb1caeef..3ef3ce16fd 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -402,6 +402,7 @@ extern rct_scenario_basic *gScenarioList; int scenario_scores_save(); void scenario_load_list(); +rct_scenario_basic *get_scenario_by_filename(const char *filename); int scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *info); int scenario_load(const char *path); int scenario_load_and_play(const rct_scenario_basic *scenario); diff --git a/src/scenario_list.c b/src/scenario_list.c index eb2cc8fb24..c14ec713e4 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -32,7 +32,7 @@ static void scenario_list_sort(); static int scenario_list_sort_compare(const void *a, const void *b); static int scenario_scores_load(); -static rct_scenario_basic *get_scenario_by_filename(const char *filename) +rct_scenario_basic *get_scenario_by_filename(const char *filename) { int i; for (i = 0; i < gScenarioListCount; i++) diff --git a/src/test/management/finance_test.c b/src/test/management/finance_test.c new file mode 100644 index 0000000000..bc14d637ac --- /dev/null +++ b/src/test/management/finance_test.c @@ -0,0 +1,60 @@ +/***************************************************************************** +* Copyright (c) 2015 Marco Costa +* OpenRCT2, an open source clone of Roller Coaster Tycoon 2. +* +* This file is part of OpenRCT2. +* +* OpenRCT2 is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. + +* This program 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 General Public License for more details. + +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*****************************************************************************/ + +#include "../../addresses.h" +#include "../../openrct2.h" +#include "../../scenario.h" + +#include "../../management/finance.h" +#include "finance_test.h" + +void test_finance_setup(CuTest* tc) { + test_load_scenario(tc, "Build your own Six Flags Park.SC6"); +} + +void test_finance_loan_increase(CuTest* tc) { + money32 initialCash = finance_get_current_cash(); + money32 initialLoan = finance_get_current_loan(); + + money32 newLoan = finance_get_maximum_loan(); + finance_set_loan(newLoan); + + money32 actual = finance_get_current_loan(); + CuAssertIntEquals(tc, newLoan, actual); + + money32 actualCash = finance_get_current_cash(); + CuAssertIntEquals(tc, initialCash + newLoan - initialLoan, actualCash); +} + +void test_finance_loan_pay_back(CuTest* tc) { + money32 initialCash = finance_get_current_cash(); + money32 initialLoan = finance_get_current_loan(); + + money32 newLoan = MONEY(0, 00); + finance_set_loan(newLoan); + + money32 actual = finance_get_current_loan(); + CuAssertIntEquals(tc, newLoan, actual); + + money32 actualCash = finance_get_current_cash(); + CuAssertIntEquals(tc, MONEY(0, 00), actualCash); +} + + diff --git a/src/test/management/finance_test.h b/src/test/management/finance_test.h new file mode 100644 index 0000000000..700a79ebc9 --- /dev/null +++ b/src/test/management/finance_test.h @@ -0,0 +1,30 @@ +/***************************************************************************** +* Copyright (c) 2015 Marco Costa +* OpenRCT2, an open source clone of Roller Coaster Tycoon 2. +* +* This file is part of OpenRCT2. +* +* OpenRCT2 is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. + +* This program 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 General Public License for more details. + +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*****************************************************************************/ + +#ifndef _FINANCE_TEST_H_ +#define _FINANCE_TEST_H_ + +#include "../tests.h" + +void test_finance_setup(CuTest* tc); +void test_finance_loan_increase(CuTest* tc); +void test_finance_loan_pay_back(CuTest* tc); + +#endif \ No newline at end of file diff --git a/src/test/tests.c b/src/test/tests.c new file mode 100644 index 0000000000..5b7764a2bb --- /dev/null +++ b/src/test/tests.c @@ -0,0 +1,54 @@ +/***************************************************************************** +* Copyright (c) 2015 Marco Costa +* OpenRCT2, an open source clone of Roller Coaster Tycoon 2. +* +* This file is part of OpenRCT2. +* +* OpenRCT2 is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. + +* This program 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 General Public License for more details. + +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*****************************************************************************/ + +#include "management/finance_test.h" + +CuSuite* new_suite(void) +{ + CuSuite* suite = CuSuiteNew(); + + // Test Finance + SUITE_ADD_TEST(suite, test_finance_setup); + SUITE_ADD_TEST(suite, test_finance_loan_increase); + SUITE_ADD_TEST(suite, test_finance_loan_pay_back); + + // Future Tests: + // Test X + // SUITE_ADD_TEST(suite, test_X_setup); + // SUITE_ADD_TEST(suite, test_X_Y); + // SUITE_ADD_TEST(suite, test_X_Z); + + return suite; +} + +int run_all_tests(void) +{ + CuString *output = CuStringNew(); + CuSuite* suite = CuSuiteNew(); + + CuSuiteAddSuite(suite, new_suite()); + + CuSuiteRun(suite); + CuSuiteSummary(suite, output); + CuSuiteDetails(suite, output); + printf("Test results:\n%s\n", output->buffer); + + return suite->failCount > 0; +} diff --git a/src/test/tests.h b/src/test/tests.h new file mode 100644 index 0000000000..b661defbba --- /dev/null +++ b/src/test/tests.h @@ -0,0 +1,43 @@ +/***************************************************************************** +* Copyright (c) 2015 Marco Costa +* OpenRCT2, an open source clone of Roller Coaster Tycoon 2. +* +* This file is part of OpenRCT2. +* +* OpenRCT2 is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. + +* This program 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 General Public License for more details. + +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*****************************************************************************/ + +#ifndef _TESTS_H_ +#define _TESTS_H_ + +#include + +#include + +#include "../scenario.h" + +int run_all_tests(); + +/* + * Test utilities + */ +static void test_load_scenario(CuTest* tc, const char* file_name) { + const rct_scenario_basic* scenario = get_scenario_by_filename(file_name); + if (scenario == NULL) { + CuFail(tc, "Could not load scenario"); + } + scenario_load_and_play(scenario); +} + +#endif \ No newline at end of file