From 754800dfb3574478c44163acb20b736780ad5312 Mon Sep 17 00:00:00 2001 From: Dalton-V Date: Thu, 27 Aug 2026 08:04:03 -0500 Subject: [PATCH] PokemonHome add the missing test classes --- .../Inference/PokemonHome_BallReader.cpp | 42 +++++++++++++- .../Inference/PokemonHome_BallReader.h | 2 + .../PokemonHome_BoxGenderDetector.cpp | 33 +++++++++++ .../Inference/PokemonHome_BoxGenderDetector.h | 3 +- .../Inference/PokemonHome_ButtonDetector.cpp | 52 +++++++++++++++++ .../Inference/PokemonHome_ButtonDetector.h | 3 +- .../PokemonHome_GigantamaxDetector.cpp | 35 +++++++++++ .../PokemonHome_GigantamaxDetector.h | 2 + .../PokemonHome_SelectionArrowDetector.cpp | 58 +++++++++++++++++++ .../PokemonHome_SelectionArrowDetector.h | 2 + .../Source/PokemonHome/PokemonHome_Tests.cpp | 10 ++++ 11 files changed, 238 insertions(+), 4 deletions(-) diff --git a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_BallReader.cpp b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_BallReader.cpp index 279f48acca..e21dceb65d 100644 --- a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_BallReader.cpp +++ b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_BallReader.cpp @@ -5,15 +5,16 @@ */ #include "Kernels/Waterfill/Kernels_Waterfill_Session.h" +#include "CommonFramework/GlobalAutoPaths.h" #include "CommonFramework/ImageTypes/ImageViewRGB32.h" #include "CommonFramework/Notifications/ProgramInfo.h" +#include "CommonFramework/Recording/StreamHistorySession.h" #include "CommonFramework/Tools/ErrorDumper.h" #include "CommonTools/Images/BinaryImage_FilterRgb32.h" #include "CommonTools/ImageMatch/ImageCropper.h" #include "PokemonHome/Resources/PokemonHome_PokeballSprites.h" -//#include "PokemonSwSh/Resources/PokemonSwSh_PokeballSprites.h" -//#include "PokemonBDSP/Inference/PokemonBDSP_PokeballSpriteMatcher.h" #include "PokemonHome_BallReader.h" +#include "Tests/TestUtils.h" namespace PokemonAutomation{ namespace NintendoSwitch{ @@ -122,6 +123,43 @@ std::string BallReader::read_ball(const ImageViewRGB32& screen) const{ return sprite_result.results.begin()->second; } +class Test_BallReader : public UnitTest{ +public: + + Test_BallReader( + const std::string& image, + const std::string& expected + ) + : UnitTest("PokemonHome::BallReader - " + image) + , m_image(UNIT_TEST_RESOURCE_PATH() + image) + , m_expected(expected) + {} + + virtual UnitTestResult run(Logger& logger, CancellableScope& scope) const override{ + DummyAudioFeed audio_feed; + DummyVideoFeed video_feed; + StreamHistorySession history(logger); + DummyVideoOverlay video_overlay; + VideoStream stream(logger, audio_feed, video_feed, history, video_overlay); + ImageRGB32 image(m_image); + BallReader reader(stream); + std::string result = reader.read_ball(image); + + if (result == m_expected) + return true; + + return "Expected: " + m_expected + ", received: " + result; + }; + +private: + std::string m_image; + std::string m_expected; +}; + +void add_tests_BallReader(UnitTestDatabase& database){ + database.add("PokemonHome/SummaryScreen/annihilape_Regular.png", "poke-ball"); +} + } diff --git a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_BallReader.h b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_BallReader.h index 632a811300..b582c9c12b 100644 --- a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_BallReader.h +++ b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_BallReader.h @@ -8,6 +8,7 @@ #define PokemonAutomation_PokemonHome_BallReader_H #include +#include "Common/Cpp/TestRunners/UnitTestDatabase.h" #include "CommonFramework/ImageTypes/ImageRGB32.h" #include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" #include "CommonFramework/Tools/VideoStream.h" @@ -50,6 +51,7 @@ class BallReader{ OverlayBoxScope m_box_sprite; }; +void add_tests_BallReader(UnitTestDatabase& database); diff --git a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_BoxGenderDetector.cpp b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_BoxGenderDetector.cpp index 413e3edb4b..c2cff39010 100644 --- a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_BoxGenderDetector.cpp +++ b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_BoxGenderDetector.cpp @@ -5,6 +5,7 @@ */ #include "Common/Cpp/Color.h" +#include "CommonFramework/GlobalAutoPaths.h" #include "CommonFramework/StaticGlobals.h" #include "CommonFramework/ImageTools/ImageBoxes.h" #include "CommonFramework/ImageTypes/ImageRGB32.h" @@ -67,6 +68,38 @@ Pokemon::StatsHuntGenderFilter BoxGenderDetector::detect(const ImageViewRGB32& s return Pokemon::StatsHuntGenderFilter::Genderless; } +class Test_BoxGenderDetector : public UnitTest{ +public: + + Test_BoxGenderDetector( + const std::string& image, + Pokemon::StatsHuntGenderFilter expected + ) + : UnitTest("PokemonHome::BoxGenderDetector - " + image) + , m_image(UNIT_TEST_RESOURCE_PATH() + image) + , m_expected(expected) + {} + + virtual UnitTestResult run(Logger& logger, CancellableScope& scope) const override{ + ImageRGB32 image(m_image); + Pokemon::StatsHuntGenderFilter result = BoxGenderDetector::detect(image); + + if (result == m_expected) + return true; + + return "Expected: " + Pokemon::gender_to_string(m_expected) + ", received: " + Pokemon::gender_to_string(result); + }; + +private: + std::string m_image; + Pokemon::StatsHuntGenderFilter m_expected; +}; + +void add_tests_BoxGenderDetector(UnitTestDatabase& database){ + database.add("PokemonHome/SummaryScreen/annihilape_Regular.png", Pokemon::StatsHuntGenderFilter::Male); +} + + } } } diff --git a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_BoxGenderDetector.h b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_BoxGenderDetector.h index 082f4d2999..0dc8810968 100644 --- a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_BoxGenderDetector.h +++ b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_BoxGenderDetector.h @@ -7,6 +7,7 @@ #ifndef PokemonAutomation_PokemonHome_BoxGenderDetector_H #define PokemonAutomation_PokemonHome_BoxGenderDetector_H +#include "Common/Cpp/TestRunners/UnitTestDatabase.h" #include "Pokemon/Options/Pokemon_StatsHuntFilter.h" namespace PokemonAutomation{ @@ -26,7 +27,7 @@ class BoxGenderDetector{ static Pokemon::StatsHuntGenderFilter detect(const ImageViewRGB32& screen); }; - +void add_tests_BoxGenderDetector(UnitTestDatabase& database); } } diff --git a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_ButtonDetector.cpp b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_ButtonDetector.cpp index a0352b4461..a06902f0c0 100644 --- a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_ButtonDetector.cpp +++ b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_ButtonDetector.cpp @@ -5,10 +5,12 @@ */ #include "Kernels/Waterfill/Kernels_Waterfill_Types.h" +#include "CommonFramework/GlobalAutoPaths.h" #include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" #include "CommonTools/Images/WaterfillUtilities.h" #include "CommonTools/ImageMatch/WaterfillTemplateMatcher.h" #include "PokemonHome_ButtonDetector.h" +#include "Tests/TestUtils.h" //#include //using std::cout; @@ -155,6 +157,56 @@ bool ButtonDetector::detect(const ImageViewRGB32& screen){ return found; } +class Test_ButtonDetector : public UnitTest{ +public: + + Test_ButtonDetector( + const std::string& image, + std::optional expected + ) + : UnitTest("PokemonHome::ButtonDetector - " + image) + , m_image(UNIT_TEST_RESOURCE_PATH() + image) + , m_expected(expected) + {} + + virtual UnitTestResult run(Logger& logger, CancellableScope& scope) const override{ + DummyVideoOverlay video_overlay; + ImageRGB32 image(m_image); + ImageFloatBox box(0.100, 0.956, 0.107, 0.041); + ButtonDetector b_detector(COLOR_RED, ButtonType::ButtonB, box, &video_overlay); + ButtonDetector plus_detector(COLOR_RED, ButtonType::ButtonPlus, box, &video_overlay); + + const bool b_detected = b_detector.detect(image); + const bool plus_detected = plus_detector.detect(image); + const bool expected_b = m_expected && *m_expected == ButtonType::ButtonB; + const bool expected_plus = m_expected && *m_expected == ButtonType::ButtonPlus; + + if (b_detected == expected_b && plus_detected == expected_plus) + return true; + + std::string received; + if (b_detected && plus_detected){ + received = "ButtonB and ButtonPlus"; + }else if (b_detected){ + received = button_name(ButtonType::ButtonB); + }else if (plus_detected){ + received = button_name(ButtonType::ButtonPlus); + }else{ + received = "none"; + } + + return std::string("Expected: ") + (m_expected ? button_name(*m_expected) : "none") + + ", received: " + received; + }; + +private: + std::string m_image; + std::optional m_expected; +}; + +void add_tests_ButtonDetector(UnitTestDatabase& database){ + database.add("PokemonHome/SummaryScreen/annihilape_Regular.png", ButtonType::ButtonB); +} } } diff --git a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_ButtonDetector.h b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_ButtonDetector.h index ec13932079..d3b2928f18 100644 --- a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_ButtonDetector.h +++ b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_ButtonDetector.h @@ -8,9 +8,9 @@ #define PokemonAutomation_PokemonHome_ButtonDetector_H #include +#include "Common/Cpp/TestRunners/UnitTestDatabase.h" #include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" #include "CommonTools/VisualDetector.h" -#include "CommonTools/InferenceCallbacks/VisualInferenceCallback.h" namespace PokemonAutomation{ class Logger; @@ -63,6 +63,7 @@ class ButtonWatcher : public DetectorToFinder{ {} }; +void add_tests_ButtonDetector(UnitTestDatabase& database); } } diff --git a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_GigantamaxDetector.cpp b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_GigantamaxDetector.cpp index 4ac8da8414..998caf2b76 100644 --- a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_GigantamaxDetector.cpp +++ b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_GigantamaxDetector.cpp @@ -5,9 +5,11 @@ */ #include "Kernels/Waterfill/Kernels_Waterfill_Types.h" +#include "CommonFramework/GlobalAutoPaths.h" #include "CommonTools/ImageMatch/WaterfillTemplateMatcher.h" #include "CommonTools/Images/WaterfillUtilities.h" #include "PokemonHome_GigantamaxDetector.h" +#include "Tests/TestUtils.h" namespace PokemonAutomation{ namespace NintendoSwitch{ @@ -84,6 +86,39 @@ bool GigantamaxDetector::detect(const ImageViewRGB32& screen){ return found; } +class Test_GigantamaxDetector : public UnitTest{ +public: + + Test_GigantamaxDetector( + const std::string& image, + bool expected + ) + : UnitTest("PokemonHome::GigantamaxDetector - " + image) + , m_image(UNIT_TEST_RESOURCE_PATH() + image) + , m_expected(expected) + {} + + virtual UnitTestResult run(Logger& logger, CancellableScope& scope) const override{ + DummyVideoOverlay video_overlay; + ImageRGB32 image(m_image); + GigantamaxDetector detector(COLOR_BLACK, &video_overlay, ImageFloatBox(0.463, 0.09, 0.04, 0.06)); + bool result = detector.detect(image); + + if (result == m_expected) + return true; + + return "Expected: " + std::to_string(m_expected) + ", received: " + std::to_string(result); + }; + +private: + std::string m_image; + bool m_expected; +}; + +void add_tests_GigantamaxDetector(UnitTestDatabase& database){ + database.add("PokemonHome/SummaryScreen/annihilape_Regular.png", false); +} + } } diff --git a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_GigantamaxDetector.h b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_GigantamaxDetector.h index 313e9a00cc..ea8737ecff 100644 --- a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_GigantamaxDetector.h +++ b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_GigantamaxDetector.h @@ -8,6 +8,7 @@ #define PokemonAutomation_PokemonHome_GigantamaxDetector_H #include +#include "Common/Cpp/TestRunners/UnitTestDatabase.h" #include "CommonFramework/ImageTools/ImageBoxes.h" #include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" #include "CommonTools/VisualDetector.h" @@ -50,6 +51,7 @@ class GigantamaxWatcher : public DetectorToFinder{ {} }; +void add_tests_GigantamaxDetector(UnitTestDatabase& database); } } diff --git a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.cpp b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.cpp index 58c472e3bc..82086b5a7b 100644 --- a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.cpp +++ b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.cpp @@ -5,9 +5,11 @@ */ #include "Common/Cpp/Exceptions.h" +#include "CommonFramework/GlobalAutoPaths.h" #include "CommonTools/ImageMatch/WaterfillTemplateMatcher.h" #include "CommonTools/Images/WaterfillUtilities.h" #include "Kernels/Waterfill/Kernels_Waterfill_Types.h" +#include "Tests/TestUtils.h" #include "PokemonHome_SelectionArrowDetector.h" namespace PokemonAutomation{ @@ -103,6 +105,62 @@ bool SelectionArrowDetector::detect(const ImageViewRGB32& screen){ return found; } +class Test_SelectionArrowDetector : public UnitTest{ +public: + + Test_SelectionArrowDetector( + const std::string& image, + std::optional expected + ) + : UnitTest("PokemonHome::SelectionArrowDetector - " + image) + , m_image(UNIT_TEST_RESOURCE_PATH() + image) + , m_expected(expected) + {} + + virtual UnitTestResult run(Logger& logger, CancellableScope& scope) const override{ + DummyVideoOverlay video_overlay; + ImageRGB32 image(m_image); + SelectionArrowDetector right_detector(COLOR_BLACK, &video_overlay, SelectionArrowType::RIGHT, ImageFloatBox(0.463, 0.09, 0.04, 0.06)); + SelectionArrowDetector down_detector(COLOR_BLACK, &video_overlay, SelectionArrowType::DOWN, ImageFloatBox(0.463, 0.09, 0.04, 0.06)); + + const bool right_detected = right_detector.detect(image); + const bool down_detected = down_detector.detect(image); + + const bool expected_right = m_expected && *m_expected == SelectionArrowType::RIGHT; + const bool expected_down = m_expected && *m_expected == SelectionArrowType::DOWN; + + if (right_detected == expected_right && down_detected == expected_down) + return true; + + auto arrow_name = [](std::optional arrow){ + if (!arrow) + return std::string("none"); + return *arrow == SelectionArrowType::RIGHT + ? std::string("RIGHT") + : std::string("DOWN"); + }; + + std::optional result; + if (right_detected && down_detected){ + return "Expected: " + arrow_name(m_expected) + ", received: RIGHT and DOWN"; + }else if (right_detected){ + result = SelectionArrowType::RIGHT; + }else if (down_detected){ + result = SelectionArrowType::DOWN; + } + + return "Expected: " + arrow_name(m_expected) + ", received: " + arrow_name(result); + }; + +private: + std::string m_image; + std::optional m_expected; +}; + +void add_tests_SelectionArrowDetector(UnitTestDatabase& database){ + database.add("PokemonHome/SummaryScreen/annihilape_Regular.png", std::nullopt); +} + } } } \ No newline at end of file diff --git a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.h b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.h index 0f1f41223f..21c17b5693 100644 --- a/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.h +++ b/SerialPrograms/Source/PokemonHome/Inference/PokemonHome_SelectionArrowDetector.h @@ -8,6 +8,7 @@ #define PokemonAutomation_PokemonHome_SelectionArrowDetector_H #include +#include "Common/Cpp/TestRunners/UnitTestDatabase.h" #include "CommonFramework/ImageTools/ImageBoxes.h" #include "CommonFramework/VideoPipeline/VideoOverlayScopes.h" #include "CommonTools/VisualDetector.h" @@ -62,6 +63,7 @@ class SelectionArrowWatcher : public DetectorToFinder{ {} }; +void add_tests_SelectionArrowDetector(UnitTestDatabase& database); } } diff --git a/SerialPrograms/Source/PokemonHome/PokemonHome_Tests.cpp b/SerialPrograms/Source/PokemonHome/PokemonHome_Tests.cpp index 922e95583b..b2d1641242 100644 --- a/SerialPrograms/Source/PokemonHome/PokemonHome_Tests.cpp +++ b/SerialPrograms/Source/PokemonHome/PokemonHome_Tests.cpp @@ -5,8 +5,13 @@ */ #include "Common/Cpp/TestRunners/UnitTestDatabase.h" +#include "Inference/PokemonHome_BallReader.h" +#include "Inference/PokemonHome_BoxGenderDetector.h" #include "Inference/PokemonHome_BoxViewDetector.h" +#include "Inference/PokemonHome_ButtonDetector.h" +#include "Inference/PokemonHome_GigantamaxDetector.h" #include "Inference/PokemonHome_OriginMarkReader.h" +#include "Inference/PokemonHome_SelectionArrowDetector.h" #include "Inference/PokemonHome_SummaryScreenDetector.h" #include "Inference/PokemonHome_TeraTypeReader.h" #include "PokemonHome_Tests.h" @@ -17,8 +22,13 @@ namespace PokemonHome{ void add_tests(UnitTestDatabase& database){ + add_tests_BallReader(database); + add_tests_ButtonDetector(database); + add_tests_BoxGenderDetector(database); add_tests_BoxViewDetector(database); + add_tests_GigantamaxDetector(database); add_tests_OriginMarkReader(database); + add_tests_SelectionArrowDetector(database); add_tests_SummaryScreenDetector(database); add_tests_TeraTypeReader(database); }