From cb4519e9c5848ca1cc000efd883e40fa5c21be8f Mon Sep 17 00:00:00 2001 From: Marijn van der Werf Date: Mon, 17 Oct 2016 10:21:53 +0200 Subject: [PATCH] Move support height testing --- test/testpaint/TestTrack.cpp | 332 +++++++++++++++++++++++++-------- test/testpaint/TestTrack.hpp | 3 - test/testpaint/intercept.h | 5 +- test/testpaint/intercept_2.cpp | 183 +----------------- 4 files changed, 263 insertions(+), 260 deletions(-) diff --git a/test/testpaint/TestTrack.cpp b/test/testpaint/TestTrack.cpp index 6adca06ad7..6f975a5337 100644 --- a/test/testpaint/TestTrack.cpp +++ b/test/testpaint/TestTrack.cpp @@ -18,11 +18,13 @@ #include #include "intercept.h" +#include "FunctionCall.hpp" +#include "GeneralSupportHeightCall.hpp" #include "Printer.hpp" +#include "SegmentSupportHeightCall.hpp" #include "String.hpp" #include "TestTrack.hpp" #include "Utils.hpp" -#include "FunctionCall.hpp" extern "C" { #include "../../src/ride/ride.h" @@ -68,23 +70,19 @@ static void CallNew( newPaintFunction(0, trackSequence, direction, height, mapElement); } +typedef uint8 (*TestFunction)(uint8, uint8, uint8, std::string *); + +static uint8 TestTrackElementPaintCalls(uint8 rideType, uint8 trackType, uint8 trackSequence, std::string *error); + +static uint8 TestTrackElementSegmentSupportHeight(uint8 rideType, uint8 trackType, uint8 trackSequence, std::string *error); + +static uint8 TestTrackElementGeneralSupportHeight(uint8 rideType, uint8 trackType, uint8 trackSequence, std::string *error); + uint8 TestTrack::TestPaintTrackElement(uint8 rideType, uint8 trackType) { if (!Utils::rideSupportsTrackType(rideType, trackType)) { return TEST_FAILED; } - - std::string error = ""; - uint8 retVal = TestPaintTrackElementCalls(rideType, trackType, &error); - - if (retVal != TEST_SUCCESS) { - printf("%s\n", error.c_str()); - } - - return retVal; -} - -uint8 TestTrack::TestPaintTrackElementCalls(uint8 rideType, uint8 trackType, std::string *error) { if (rideType == RIDE_TYPE_CHAIRLIFT) { if (trackType == TRACK_ELEM_BEGIN_STATION || trackType == TRACK_ELEM_MIDDLE_STATION || trackType == TRACK_ELEM_END_STATION) { @@ -93,6 +91,32 @@ uint8 TestTrack::TestPaintTrackElementCalls(uint8 rideType, uint8 trackType, std } } + int sequenceCount = Utils::getTrackSequenceCount(rideType, trackType); + std::string error = String::Format("rct2: 0x%08X\n", RideTypeTrackPaintFunctionsOld[rideType][trackType]); + + uint8 retVal = TEST_SUCCESS; + + static TestFunction functions[] = { + TestTrackElementPaintCalls, + TestTrackElementSegmentSupportHeight, + TestTrackElementGeneralSupportHeight + }; + + for (int trackSequence = 0; trackSequence < sequenceCount; trackSequence++) { + for (auto &&function : functions) { + retVal = function(rideType, trackType, trackSequence, &error); + } + + if (retVal != TEST_SUCCESS) { + printf("%s\n", error.c_str()); + return retVal; + } + } + + return retVal; +} + +static uint8 TestTrackElementPaintCalls(uint8 rideType, uint8 trackType, uint8 trackSequence, std::string *error) { uint8 rideIndex = 0; uint16 height = 3 * 16; @@ -108,11 +132,8 @@ uint8 TestTrack::TestPaintTrackElementCalls(uint8 rideType, uint8 trackType, std gSurfaceElement = &surfaceElement; gDidPassSurface = true; - intercept_reset_environment(); - - int sequenceCount = Utils::getTrackSequenceCount(rideType, trackType); - - *error += String::Format("rct2: 0x%08X\n", RideTypeTrackPaintFunctionsOld[rideType][trackType]); + Intercept2::ResetEnvironment(); + Intercept2::ResetTunnels(); function_call callBuffer[256] = {0}; int callCount = 0; @@ -128,77 +149,234 @@ uint8 TestTrack::TestPaintTrackElementCalls(uint8 rideType, uint8 trackType, std for (int currentRotation = 0; currentRotation < 4; currentRotation++) { gCurrentRotation = currentRotation; for (int direction = 0; direction < 4; direction++) { - for (int trackSequence = 0; trackSequence < sequenceCount; trackSequence++) { - RCT2_GLOBAL(0x009DE56A, sint16) = 64; // x - RCT2_GLOBAL(0x009DE56E, sint16) = 64; // y + RCT2_GLOBAL(0x009DE56A, sint16) = 64; // x + RCT2_GLOBAL(0x009DE56E, sint16) = 64; // y - std::string caseName = String::Format( - "[direction:%d trackSequence:%d chainLift:%d inverted:%d]", - direction, trackSequence, chainLift, inverted + std::string caseName = String::Format( + "[direction:%d trackSequence:%d chainLift:%d inverted:%d]", + direction, trackSequence, chainLift, inverted + ); + + intercept_clear_calls(); + Intercept2::ResetSupportHeights(); + + CallOriginal(rideType, trackType, direction, trackSequence, height, &mapElement); + + callCount = intercept_get_calls(callBuffer); + std::vector oldCalls; + oldCalls.insert(oldCalls.begin(), callBuffer, callBuffer + callCount); + + intercept_clear_calls(); + testpaint_clear_ignore(); + Intercept2::ResetSupportHeights(); + + CallNew(rideType, trackType, direction, trackSequence, height, &mapElement); + + if (testpaint_is_ignored(direction, trackSequence)) { + *error += String::Format("[ IGNORED ] %s\n", caseName.c_str()); + continue; + } + + callCount = intercept_get_calls(callBuffer); + std::vector newCalls; + newCalls.insert(newCalls.begin(), callBuffer, callBuffer + callCount); + + bool sucess = true; + if (oldCalls.size() != newCalls.size()) { + *error += String::Format( + "Call counts don't match (was %d, expected %d). %s\n", + newCalls.size(), oldCalls.size(), caseName.c_str() ); + sucess = false; + } else if (!FunctionCall::AssertsEquals(oldCalls, newCalls)) { + *error += String::Format("Calls don't match. %s\n", caseName.c_str()); + sucess = false; + } - intercept_clear_calls(); - intercept_reset_segment_heights(); + if (!sucess) { + *error += " Expected:\n"; + *error += Printer::PrintFunctionCalls(oldCalls, height); + *error += " Actual:\n"; + *error += Printer::PrintFunctionCalls(newCalls, height); - CallOriginal(rideType, trackType, direction, trackSequence, height, &mapElement); - - callCount = intercept_get_calls(callBuffer); - std::vector oldCalls; - oldCalls.insert(oldCalls.begin(), callBuffer, callBuffer + callCount); - - intercept_clear_calls(); - testpaint_clear_ignore(); - intercept_reset_segment_heights(); - - CallNew(rideType, trackType, direction, trackSequence, height, &mapElement); - - if (testpaint_is_ignored(direction, trackSequence)) { - *error += String::Format("[ IGNORED ] %s\n", caseName.c_str()); - continue; - } - - callCount = intercept_get_calls(callBuffer); - std::vector newCalls; - newCalls.insert(newCalls.begin(), callBuffer, callBuffer + callCount); - - bool sucess = true; - if (oldCalls.size() != newCalls.size()) { - *error += String::Format( - "Call counts don't match (was %d, expected %d). %s\n", - newCalls.size(), oldCalls.size(), caseName.c_str() - ); - sucess = false; - } else if (!FunctionCall::AssertsEquals(oldCalls, newCalls)) { - *error += String::Format("Calls don't match. %s\n", caseName.c_str()); - sucess = false; - } - - if (!sucess) { - *error += " Expected:\n"; - *error += Printer::PrintFunctionCalls(oldCalls, height); - *error += " Actual:\n"; - *error += Printer::PrintFunctionCalls(newCalls, height); - - return TEST_FAILED; - } + return TEST_FAILED; } } } - bool segmentSuccess = testSupportSegments(rideType, trackType); - if (!segmentSuccess) { - return TEST_FAILED; + return TEST_SUCCESS; +} + +static uint8 TestTrackElementSegmentSupportHeight(uint8 rideType, uint8 trackType, uint8 trackSequence, std::string *error) { + uint8 rideIndex = 0; + uint16 height = 3 * 16; + + rct_map_element mapElement = {0}; + mapElement.flags |= MAP_ELEMENT_FLAG_LAST_TILE; + mapElement.properties.track.type = trackType; + mapElement.base_height = height / 16; + g_currently_drawn_item = &mapElement; + + rct_map_element surfaceElement = {0}; + surfaceElement.type = MAP_ELEMENT_TYPE_SURFACE; + surfaceElement.base_height = 2; + gSurfaceElement = &surfaceElement; + gDidPassSurface = true; + + Intercept2::ResetEnvironment(); + Intercept2::ResetTunnels(); + + // TODO: Test Chainlift + // TODO: Test Maze + // TODO: Allow skip + + std::string state = String::Format("[trackSequence:%d chainLift:%d]", trackSequence, 0); + + std::vector tileSegmentSupportCalls[4]; + + for (int direction = 0; direction < 4; direction++) { + Intercept2::ResetSupportHeights(); + + CallOriginal(rideType, trackType, direction, trackSequence, height, &mapElement); + + tileSegmentSupportCalls[direction] = SegmentSupportHeightCall::getSegmentCalls(gSupportSegments, direction); } - bool tunnelSuccess = testTunnels(rideType, trackType); - if (!tunnelSuccess) { - return TEST_FAILED; + std::vector referenceCalls = tileSegmentSupportCalls[0]; + + if (!SegmentSupportHeightCall::CallsMatch(tileSegmentSupportCalls)) { + std::vector *found = SegmentSupportHeightCall::FindMostCommonSupportCall( + tileSegmentSupportCalls); + if (found != nullptr) { + referenceCalls = *found; + } else { + *error += String::Format("Original segment calls didn't match. %s\n", state.c_str()); + for (int direction = 0; direction < 4; direction++) { + *error += String::Format("# %d\n", direction); + *error += Printer::PrintSegmentSupportHeightCalls(tileSegmentSupportCalls[direction]); + } + return TEST_FAILED; + } } - bool verticalTunnelSuccess = testVerticalTunnels(rideType, trackType); - if (!verticalTunnelSuccess) { - return TEST_FAILED; + for (int direction = 0; direction < 4; direction++) { + Intercept2::ResetSupportHeights(); + + testpaint_clear_ignore(); + CallNew(rideType, trackType, direction, trackSequence, height, &mapElement); + if (testpaint_is_ignored(direction, trackSequence)) { + continue; + } + + std::vector newCalls = SegmentSupportHeightCall::getSegmentCalls(gSupportSegments, + direction); + if (!SegmentSupportHeightCall::CallsEqual(referenceCalls, newCalls)) { + *error += String::Format( + "Segment support heights didn't match. [direction:%d] %s\n", + direction, state.c_str() + ); + *error += " Expected:\n"; + *error += Printer::PrintSegmentSupportHeightCalls(referenceCalls); + *error += " Actual:\n"; + *error += Printer::PrintSegmentSupportHeightCalls(newCalls); + + return TEST_FAILED; + } } return TEST_SUCCESS; -} \ No newline at end of file +} + +static uint8 TestTrackElementGeneralSupportHeight(uint8 rideType, uint8 trackType, uint8 trackSequence, std::string *error) { + uint8 rideIndex = 0; + uint16 height = 3 * 16; + + rct_map_element mapElement = {0}; + mapElement.flags |= MAP_ELEMENT_FLAG_LAST_TILE; + mapElement.properties.track.type = trackType; + mapElement.base_height = height / 16; + g_currently_drawn_item = &mapElement; + + rct_map_element surfaceElement = {0}; + surfaceElement.type = MAP_ELEMENT_TYPE_SURFACE; + surfaceElement.base_height = 2; + gSurfaceElement = &surfaceElement; + gDidPassSurface = true; + + Intercept2::ResetEnvironment(); + Intercept2::ResetTunnels(); + + // TODO: Test Chainlift + // TODO: Test Maze + // TODO: Allow skip + + std::string state = String::Format("[trackSequence:%d chainLift:%d]", trackSequence, 0); + + SupportCall tileGeneralSupportCalls[4]; + for (int direction = 0; direction < 4; direction++) { + Intercept2::ResetSupportHeights(); + + CallOriginal(rideType, trackType, direction, trackSequence, height, &mapElement); + + tileGeneralSupportCalls[direction].height = -1; + tileGeneralSupportCalls[direction].slope = -1; + if (gSupport.height != 0) { + tileGeneralSupportCalls[direction].height = gSupport.height; + } + if (gSupport.slope != 0xFF) { + tileGeneralSupportCalls[direction].slope = gSupport.slope; + } + } + + SupportCall referenceGeneralSupportCall = tileGeneralSupportCalls[0]; + if (!GeneralSupportHeightCall::CallsMatch(tileGeneralSupportCalls)) { + SupportCall *found = GeneralSupportHeightCall::FindMostCommonSupportCall(tileGeneralSupportCalls); + if (found == nullptr) { + *error += String::Format("Original support calls didn't match. %s\n", state.c_str()); + for (int i = 0; i < 4; ++i) { + *error += String::Format("[%d, 0x%02X] ", tileGeneralSupportCalls[i].height, tileGeneralSupportCalls[i].slope); + } + *error += "\n"; + return TEST_FAILED; + } + referenceGeneralSupportCall = *found; + } + + for (int direction = 0; direction < 4; direction++) { + Intercept2::ResetSupportHeights(); + + testpaint_clear_ignore(); + CallNew(rideType, trackType, direction, trackSequence, height, &mapElement); + if (testpaint_is_ignored(direction, trackSequence)) { + continue; + } + + + if (referenceGeneralSupportCall.height != -1) { + if (gSupport.height != referenceGeneralSupportCall.height) { + *error += String::Format( + "General support heights didn't match. (expected height + %d, actual: height + %d) [direction:%d] %s\n", + referenceGeneralSupportCall.height - height, + gSupport.height - height, + direction, + state.c_str() + ); + return TEST_FAILED; + } + } + if (referenceGeneralSupportCall.slope != -1) { + if (gSupport.slope != referenceGeneralSupportCall.slope) { + *error += String::Format( + "General support slopes didn't match. (expected 0x%02X, actual: 0x%02X) [direction:%d] %s\n", + referenceGeneralSupportCall.slope, + gSupport.slope, + direction, + state.c_str() + ); + return TEST_FAILED; + } + } + } + + return TEST_SUCCESS; +} diff --git a/test/testpaint/TestTrack.hpp b/test/testpaint/TestTrack.hpp index 7f049766aa..7eb3ff1d07 100644 --- a/test/testpaint/TestTrack.hpp +++ b/test/testpaint/TestTrack.hpp @@ -23,7 +23,4 @@ class TestTrack { public: static uint8 TestPaintTrackElement(uint8 rideType, uint8 trackType); - -private: - static uint8 TestPaintTrackElementCalls(uint8 rideType, uint8 trackType, std::string * error); }; diff --git a/test/testpaint/intercept.h b/test/testpaint/intercept.h index 581482bae7..0aed39fcf7 100644 --- a/test/testpaint/intercept.h +++ b/test/testpaint/intercept.h @@ -81,7 +81,6 @@ extern "C" { #endif void initHooks(); - bool testSupportSegments(uint8 rideType, uint8 trackType); bool testTunnels(uint8 rideType, uint8 trackType); bool testVerticalTunnels(uint8 rideType, uint8 trackType); void intercept_clear_calls(); @@ -121,6 +120,10 @@ namespace Intercept2 }; sint16 getTunnelOffset(uint32 baseHeight, tunnel_entry calls[3]); + + void ResetEnvironment(); + void ResetTunnels(); + void ResetSupportHeights(); } #endif diff --git a/test/testpaint/intercept_2.cpp b/test/testpaint/intercept_2.cpp index 8fdd7cbba7..2673b0cb36 100644 --- a/test/testpaint/intercept_2.cpp +++ b/test/testpaint/intercept_2.cpp @@ -33,7 +33,7 @@ extern "C" { namespace Intercept2 { - static void ResetEnvironment() { + void ResetEnvironment() { gPaintInteractionType = VIEWPORT_INTERACTION_ITEM_RIDE; gTrackColours[SCHEME_TRACK] = DEFAULT_SCHEME_TRACK; gTrackColours[SCHEME_SUPPORTS] = DEFAULT_SCHEME_SUPPORTS; @@ -58,7 +58,7 @@ namespace Intercept2 g141E9DB = G141E9DB_FLAG_1 | G141E9DB_FLAG_2; } - static void ResetTunnels() { + void ResetTunnels() { gLeftTunnelCount = 0; gRightTunnelCount = 0; @@ -75,7 +75,7 @@ namespace Intercept2 gRightTunnels[0].type = 0xFF; } - static void ResetSegmentHeights() { + void ResetSupportHeights() { for (int s = 0; s < 9; ++s) { gSupportSegments[s].height = 0; @@ -86,11 +86,6 @@ namespace Intercept2 gSupport.slope = 0xFF; } - static void printSegmentSupports(utf8string out, size_t len, std::vector segmentCalls) - { - snprintf(out, len, "%s", Printer::PrintSegmentSupportHeightCalls(segmentCalls).c_str()); - } - static bool tunnelCallsLineUp(TunnelCall tunnelCalls[4][4]) { for (int side = 0; side < 4; ++side) { @@ -207,171 +202,6 @@ namespace Intercept2 printf("\n"); } - static bool testSupportSegments(uint8 rideType, uint8 trackType) - { - uint8 rideIndex = 0; - rct_map_element mapElement = {0}; - mapElement.flags |= MAP_ELEMENT_FLAG_LAST_TILE; - mapElement.properties.track.type = trackType; - mapElement.base_height = 3; - - g_currently_drawn_item = &mapElement; - - rct_map_element surfaceElement = {0}; - surfaceElement.flags |= MAP_ELEMENT_FLAG_LAST_TILE; - surfaceElement.type = MAP_ELEMENT_TYPE_SURFACE; - surfaceElement.base_height = 2; - - ResetEnvironment(); - ResetTunnels(); - - int height = 48; - - TRACK_PAINT_FUNCTION_GETTER newPaintGetter = RideTypeTrackPaintFunctions[rideType]; - int sequenceCount = Utils::getTrackSequenceCount(rideType, trackType); - - for (int chainLift = 0; chainLift < 2; chainLift++) { - if (chainLift == 0) { - mapElement.type &= ~0x80; - } else { - mapElement.type |= 0x80; - } - - for (int trackSequence = 0; trackSequence < sequenceCount; trackSequence++) { - std::vector tileSegmentSupportCalls[4]; - SupportCall tileGeneralSupportCalls[4]; - - for (int direction = 0; direction < 4; direction++) { - ResetSegmentHeights(); - - uint32 *trackDirectionList = (uint32 *)RideTypeTrackPaintFunctionsOld[rideType][trackType]; - - // Have to call from this point as it pushes esi and expects callee to pop it - RCT2_CALLPROC_X( - 0x006C4934, - rideType, - (int) trackDirectionList, - direction, - height, - (int) &mapElement, - rideIndex * sizeof(rct_ride), - trackSequence - ); - - tileSegmentSupportCalls[direction] = SegmentSupportHeightCall::getSegmentCalls(gSupportSegments, direction); - - tileGeneralSupportCalls[direction].height = -1; - tileGeneralSupportCalls[direction].slope = -1; - if (gSupport.height != 0) { - tileGeneralSupportCalls[direction].height = gSupport.height; - } - if (gSupport.slope != 0xFF) { - tileGeneralSupportCalls[direction].slope = gSupport.slope; - } - } - - std::vector referenceCalls = tileSegmentSupportCalls[0]; - - if (!SegmentSupportHeightCall::CallsMatch(tileSegmentSupportCalls)) { - std::vector *found = SegmentSupportHeightCall::FindMostCommonSupportCall(tileSegmentSupportCalls); - if (found != nullptr) { - referenceCalls = *found; - } else { - printf("Original segment calls didn't match. [trackSequence:%d chainLift:%d]\n", trackSequence, chainLift); - for (int i = 0; i < 4; i++) { - printf("# %d\n%s", i, Printer::PrintSegmentSupportHeightCalls(tileSegmentSupportCalls[i]).c_str()); - } - continue; - } - } - - for (int direction = 0; direction < 4; direction++) { - ResetSegmentHeights(); - - testpaint_clear_ignore(); - TRACK_PAINT_FUNCTION newPaintFunction = newPaintGetter(trackType, direction); - newPaintFunction(rideIndex, trackSequence, direction, height, &mapElement); - if (testpaint_is_ignored(direction, trackSequence)) { - continue; - } - - std::vector newCalls = SegmentSupportHeightCall::getSegmentCalls(gSupportSegments, - direction); - - if (!SegmentSupportHeightCall::CallsEqual(tileSegmentSupportCalls[0], newCalls)) { - // TODO put this into *error - utf8string diff = new utf8[2048]; - snprintf(diff, 2048, "<<< EXPECTED\n"); - printSegmentSupports(diff, 2048, tileSegmentSupportCalls[0]); - - size_t slen = strlen(diff); - if (slen < 2048) - snprintf(diff + slen, 2048 - slen, "====\n"); - printSegmentSupports(diff, 2048, newCalls); - - slen = strlen(diff); - if (slen < 2048) - snprintf(diff + strlen(diff), 2048 - slen, ">>> ACTUAL\n"); - - printf("Segment support heights didn't match. [direction:%d trackSequence:%d chainLift:%d]\n", direction, - trackSequence, chainLift); - printf("%s", diff); - delete[] diff; - return false; - } - } - - SupportCall referenceGeneralSupportCall = tileGeneralSupportCalls[0]; - - if (!GeneralSupportHeightCall::CallsMatch(tileGeneralSupportCalls)) { - SupportCall *found = GeneralSupportHeightCall::FindMostCommonSupportCall(tileGeneralSupportCalls); - if (found == nullptr) { - printf("Original support calls didn't match. [trackSequence:%d chainLift:%d]\n", trackSequence, chainLift); - for (int i = 0; i < 4; ++i) { - printf("[%d, 0x%02X] ", tileGeneralSupportCalls[i].height, tileGeneralSupportCalls[i].slope); - } - printf("\n"); - continue; - } - referenceGeneralSupportCall = *found; - } - - - for (int direction = 0; direction < 4; direction++) { - ResetSegmentHeights(); - - testpaint_clear_ignore(); - TRACK_PAINT_FUNCTION newPaintFunction = newPaintGetter(trackType, direction); - newPaintFunction(rideIndex, trackSequence, direction, height, &mapElement); - if (testpaint_is_ignored(direction, trackSequence)) { - continue; - } - - if (referenceGeneralSupportCall.height != -1) { - if (gSupport.height != referenceGeneralSupportCall.height) { - printf("General support heights didn't match. (expected height + %d, actual: height + %d) [direction:%d trackSequence:%d chainLift:%d]\n", - referenceGeneralSupportCall.height - height, - gSupport.height - height, - direction, - trackSequence, - chainLift); - return false; - } - } - if (referenceGeneralSupportCall.slope != -1) { - if (gSupport.slope != referenceGeneralSupportCall.slope) { - printf("General support slopes didn't match. [direction:%d trackSequence:%d chainLift:%d]\n", direction, - trackSequence, chainLift); - return false; - } - } - } - - } - } - return true; - } - static bool tunnelPatternsMatch(TunnelCall expected[4], TunnelCall actual[4]) { for (int side = 0; side < 4; side++) { @@ -709,11 +539,6 @@ namespace Intercept2 extern "C" { - bool testSupportSegments(uint8 rideType, uint8 trackType) - { - return Intercept2::testSupportSegments(rideType, trackType); - } - bool testTunnels(uint8 rideType, uint8 trackType) { return Intercept2::testTunnels(rideType, trackType); @@ -749,7 +574,7 @@ extern "C" } void intercept_reset_segment_heights() { - Intercept2::ResetSegmentHeights(); + Intercept2::ResetSupportHeights(); } void intercept_reset_tunnels() {