diff --git a/CMakeLists.txt b/CMakeLists.txt index c330522ea..f51a0b2d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,7 +38,10 @@ endif() # Build Tests conditionally if(BUILD_TESTS) - add_subdirectory(${CMAKE_SOURCE_DIR}/tests) + include(CTest) + enable_testing() # turns on CTest collection + add_subdirectory(tests/resource-tuner) + add_subdirectory(tests/contextual-classifier) endif() set(SERVER_LIBS "") diff --git a/tests/README.md b/tests/README.md index 7c19ddc24..c61658283 100644 --- a/tests/README.md +++ b/tests/README.md @@ -11,7 +11,7 @@ --- -## Quick Start +## Example ```cpp #include "mini.hpp" @@ -25,9 +25,9 @@ Build & run: mkdir build && cd build cmake .. -DBUILD_TESTS=ON make -./tests/RestuneComponentTests -./tests/RestuneIntegrationTests -./tests/RestuneUnitTests +./tests/resource-tuner/RestuneComponentTests +./tests/resource-tuner/RestuneIntegrationTests +./tests/resource-tuner/RestuneUnitTests ``` --- diff --git a/tests/contextual-classifier/CMakeLists.txt b/tests/contextual-classifier/CMakeLists.txt new file mode 100644 index 000000000..afeaa5f1d --- /dev/null +++ b/tests/contextual-classifier/CMakeLists.txt @@ -0,0 +1,60 @@ +# tests/contextual-classifier/CMakeLists.txt +if(BUILD_TESTS) + + # ---------------------------------------- + # Report directories & env (same pattern as resource-tuner) + # ---------------------------------------- + set(TEST_REPORT_DIR "${CMAKE_BINARY_DIR}/test-reports") + file(MAKE_DIRECTORY "${TEST_REPORT_DIR}") + set(TEST_REPORT_ENV "TEST_REPORT_DIR=${TEST_REPORT_DIR}") + + # Path to test framework (mini.hpp, testrunner.cpp, etc.) + set(FRAMEWORK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../framework") + + # ---------------------------------------- + # ContextualClassifierIntegrationTests + # ---------------------------------------- + add_executable(ContextualClassifierIntegrationTests + ${CMAKE_CURRENT_SOURCE_DIR}/Integration/IntegrationTests.cpp + # If you are using a shared runner TU (like testrunner.cpp), uncomment: + # ${FRAMEWORK_DIR}/testrunner.cpp + ) + + target_include_directories(ContextualClassifierIntegrationTests PRIVATE + ${FRAMEWORK_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/Integration + ${CMAKE_CURRENT_SOURCE_DIR}/include + ) + + target_link_libraries(ContextualClassifierIntegrationTests PRIVATE + # UrmAuxUtils + # UrmExtAPIs + # RestuneCore + # pthread + # yaml + ) + + # Mini.hpp default knobs (match your style) + target_compile_definitions(ContextualClassifierIntegrationTests PRIVATE + MTEST_DEFAULT_OUTPUT_TAP=0 + # MTEST_ENABLE_EXCEPTIONS=1 + ) + + # Install the test runner next to other test executables + install(TARGETS ContextualClassifierIntegrationTests + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + # ---------------------------------------- + # CTest registration (auto emit reports) + # ---------------------------------------- + add_test(NAME ContextualClassifierIntegration_All + COMMAND ContextualClassifierIntegrationTests + --report-json=${TEST_REPORT_DIR}/ctx_integration_all.json + --report-junit=${TEST_REPORT_DIR}/ctx_integration_all.junit.xml + --report-md=${TEST_REPORT_DIR}/ctx_integration_all.md) + + set_tests_properties(ContextualClassifierIntegration_All PROPERTIES + ENVIRONMENT "${TEST_REPORT_ENV};NO_COLOR=" + ) + +endif() diff --git a/tests/contextual-classifier/Integration/IntegrationTests.cpp b/tests/contextual-classifier/Integration/IntegrationTests.cpp new file mode 100644 index 000000000..52ec8d0a9 --- /dev/null +++ b/tests/contextual-classifier/Integration/IntegrationTests.cpp @@ -0,0 +1,162 @@ +// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. +// SPDX-License-Identifier: BSD-3-Clause-Clear + +// IntegrationTests.cpp +#include "../framework/mini.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "../include/test_helpers.hpp" + +using namespace test_helpers; +// --------------------------------------------------------------------- +// PASS: Init path (module load → cc_init → netlink subscribe) +// --------------------------------------------------------------------- +MT_TEST(Classifier, InitPath, "integration") { + MT_REQUIRE(ctx, service_restart()); + std::this_thread::sleep_for(std::chrono::milliseconds(kSettleMs)); + + const std::string logs = read_journal_last_seconds(kSinceSeconds); + MT_REQUIRE(ctx, !logs.empty()); + + // MT_REQUIRE(ctx, contains_line(logs, kInitEnter)); // registration fired + // MT_REQUIRE(ctx, contains_line(logs, kInitCall)); // dlopen+dlsym ok, cc_init invoked + MT_REQUIRE(ctx, contains_line(logs, kInitOk1)); // ContextualClassifier::Init() + MT_REQUIRE(ctx, contains_line(logs, kInitOk2)); // Netlink set_listen(true) +} + +// --------------------------------------------------------------------- +// PASS: Event delivery → worker consumes → classification starts +// --------------------------------------------------------------------- +MT_TEST(Classifier, EventDelivery, "integration") { + spawn_short_process(); + std::this_thread::sleep_for(std::chrono::milliseconds(kEventWaitMs)); + + const std::string logs = read_journal_last_seconds(kSinceSeconds); + MT_REQUIRE(ctx, !logs.empty()); + MT_REQUIRE(ctx, contains_regex(logs, kClassifyStartRe)); +} + +// --------------------------------------------------------------------- +// XFAIL: FastText model load (expected missing on current box) +// will XPASS once /etc/classifier/fasttext_model_supervised.bin exists +// --------------------------------------------------------------------- +MT_TEST_XFAIL(FastText, ModelLoads_XFail, "integration", "FastText model not installed") { + // Restart to capture model-load logs + MT_REQUIRE(ctx, service_restart()); + std::this_thread::sleep_for(std::chrono::milliseconds(kSettleMs)); + + const std::string logs = read_journal_last_seconds(kSinceSeconds); + MT_REQUIRE(ctx, !logs.empty()); + + // REQUIRE the model loaded line → currently absent → XFAIL + MT_REQUIRE(ctx, contains_line(logs, kFtModelLoaded)); +} + +// --------------------------------------------------------------------- +// XFAIL: FastText prediction (expected absent without model) +// will XPASS once prediction runs and logs "Prediction complete..." +// --------------------------------------------------------------------- +MT_TEST_XFAIL(FastText, Predict_XFail, "integration", "Prediction disabled (no model)") { + spawn_short_process(); + std::this_thread::sleep_for(std::chrono::milliseconds(kEventWaitMs)); + + const std::string logs = read_journal_last_seconds(kSinceSeconds); + MT_REQUIRE(ctx, !logs.empty()); + + // REQUIRE the prediction completion line → currently absent → XFAIL + MT_REQUIRE(ctx, contains_line(logs, kFtPredictDone)); +} + +// --------------------------------------------------------------------- +// XFAIL: Focused slice move success (expected to fail on this box) +// Success criteria we enforce here: +// - We saw a "Writing to Node:" attempt for focused/app slice, +// - AND we did NOT see "Call to write, Failed" in the same window. +// This will XPASS if your cgroup setup is fully correct. +// --------------------------------------------------------------------- +MT_TEST_XFAIL(Cgroups, FocusedSliceMove_XFail, "integration", + "Focused/app slice not provisioned on this host") { + spawn_short_process(); + std::this_thread::sleep_for(std::chrono::milliseconds(kEventWaitMs)); + + const std::string logs = read_journal_last_seconds(kSinceSeconds); + MT_REQUIRE(ctx, !logs.empty()); + + const bool wrote = contains_line(logs, kCgrpWriteTry); + const bool failed = contains_line(logs, kCgrpWriteFail); + + // REQUIRE "wrote" and NOT "failed" → expected to fail today → XFAIL. + MT_REQUIRE(ctx, wrote && !failed); +} + + +MT_TEST(Classifier, Netlink_RobustToEINTR, "integration") { + // Kick a classification first + spawn_short_process(); + std::this_thread::sleep_for(std::chrono::milliseconds(300)); + + // Send SIGUSR1 to the URM pid (best-effort; ignore rc) + (void)run_cmd("bash -lc 'pgrep -x urm | head -n1 | xargs -r -I{} kill -USR1 {}'"); + + // Trigger another event + spawn_short_process(); + std::this_thread::sleep_for(std::chrono::milliseconds(1500)); + + const std::string logs = read_journal_last_seconds(180); + MT_REQUIRE(ctx, !logs.empty()); + MT_REQUIRE(ctx, contains_regex(logs, kClassifyStartRe)); +} + +MT_TEST(Classifier, Queue_BackPressure, "integration") { + for (int i = 0; i < 50; ++i) spawn_short_process(); + std::this_thread::sleep_for(std::chrono::milliseconds(2500)); + + const std::string logs = read_journal_last_seconds(240); + MT_REQUIRE(ctx, !logs.empty()); + + // Count occurrences; must be > 0. + std::sregex_iterator it(logs.begin(), logs.end(), kClassifyStartRe), end; + int hits = std::distance(it, end); + MT_REQUIRE(ctx, hits > 0); +} + +MT_TEST(Classifier, Terminate_Restart_Clean, "integration") { + MT_REQUIRE(ctx, service_restart()); + std::this_thread::sleep_for(std::chrono::milliseconds(kSettleMs)); + const std::string logs = read_journal_last_seconds(120); +// MT_REQUIRE(ctx, contains_line(logs, kInitEnter)); + MT_REQUIRE(ctx, contains_line(logs, kInitOk2)); // listening for events +} + +MT_TEST(Classifier, IgnoreList_Basic, "integration") { + // sed/sh are commonly ignored per your logs; spawn both. + (void)run_cmd("bash -lc 'sh -c true; sed -n 1p /etc/hosts >/dev/null 2>&1'"); + std::this_thread::sleep_for(std::chrono::milliseconds(800)); + + const std::string logs = read_journal_last_seconds(120); + MT_REQUIRE(ctx, logs.find("Ignoring process: sh") != std::string::npos + || logs.find("Ignoring process: sed") != std::string::npos); +} + +MT_TEST_XFAIL(Signals, Config_Parsing_XFail, "integration", + "Test configs contain non-numeric fields (stol)") { + MT_REQUIRE(ctx, service_restart()); + std::this_thread::sleep_for(std::chrono::milliseconds(kSettleMs)); + const std::string logs = read_journal_last_seconds(120); + MT_REQUIRE(ctx, logs.find("Signal Parsing Failed with Error: stol") != std::string::npos); +} + +MT_TEST_XFAIL(Extractor, CSVDump_XFail, "integration", + "mDebugMode not enabled; no CSVs expected") { + spawn_short_process(); + std::this_thread::sleep_for(std::chrono::milliseconds(1200)); + // Look for *either* pruned or unfiltered CSVs (simple probe) + auto r = run_cmd("bash -lc 'ls /var/cache/pruned/*_proc_info* /var/cache/unfiltered/*_proc_info* 2>/dev/null | head -n1'"); + MT_REQUIRE(ctx, !r.out.empty()); // Will fail now → XFAIL +} diff --git a/tests/contextual-classifier/include/test_helpers.hpp b/tests/contextual-classifier/include/test_helpers.hpp new file mode 100644 index 000000000..42f1e75c7 --- /dev/null +++ b/tests/contextual-classifier/include/test_helpers.hpp @@ -0,0 +1,103 @@ +// tests/include/test_helpers.hpp +#ifndef TEST_HELPERS_HPP_INCLUDED +#define TEST_HELPERS_HPP_INCLUDED + +#include +#include +#include +#include +#include + +namespace test_helpers { + +// -------- Settings / constants -------- +inline constexpr const char* kService = "urm"; + +// ContextualClassifierInit.cpp (Init trace you added): +inline constexpr const char* kInitEnter = "InitTrace: ENTER module init"; +inline constexpr const char* kInitCall = "InitTrace: calling cc_init()"; + +// ContextualClassifier.cpp (Init path): +inline constexpr const char* kInitOk1 = "Classifier module init."; +inline constexpr const char* kInitOk2 = "Now listening for process events."; + +// ContextualClassifier.cpp (worker consumes events): +inline const std::regex kClassifyStartRe( + R"(ClassifyProcess:\s*Starting classification for PID:\s*\d+)", + std::regex::icase); + +// MLInference.cpp (FastText): +inline constexpr const char* kFtModelLoaded = "fastText model loaded. Embedding dimension:"; +inline constexpr const char* kFtPredictDone = "Prediction complete. PID:"; + +// URM cgroup move logs: +inline constexpr const char* kCgrpWriteTry = "moveProcessToCGroup: Writing to Node:"; +inline constexpr const char* kCgrpWriteFail = "moveProcessToCGroup: Call to write, Failed"; + +// Time windows (tuned for your box) +inline constexpr int kSinceSeconds = 240; // query last N seconds of journald +inline constexpr int kSettleMs = 1800; // wait after service restart +inline constexpr int kEventWaitMs = 1500; // wait after spawning an event + +// -------- Shell helpers -------- +struct CmdResult { + int exit_code{-1}; + std::string out; +}; + +// Run a shell command, capture stdout, and return exit code + output. +// Stderr redirected to /dev/null to keep logs stable. +static inline CmdResult run_cmd(const std::string& cmd) { + CmdResult cr; + std::array buf{}; + std::string full = cmd + " 2>/dev/null"; + if (FILE* fp = popen(full.c_str(), "r")) { + while (size_t n = fread(buf.data(), 1, buf.size(), fp)) { + cr.out.append(buf.data(), n); + } + cr.exit_code = pclose(fp); + } else { + cr.exit_code = -1; + } + return cr; +} + +static inline void spawn_short_process() { + (void)run_cmd("bash -lc 'sleep 1 & disown'"); +} + +// -------- Service / journald helpers -------- +static inline bool service_restart() { + (void)run_cmd("systemctl daemon-reload"); + auto rc = run_cmd(std::string("systemctl restart ") + kService); + return (rc.exit_code == 0); +} + +static inline std::string read_journal_last_seconds(int seconds) { + // Try unprivileged read first + { + std::string cmd = "journalctl -u " + std::string(kService) + + " --since \"-" + std::to_string(seconds) + "s\" -o short-iso"; + CmdResult r = run_cmd(cmd); + if (!r.out.empty()) return r.out; + } + // Fallback with sudo + { + std::string cmd = "sudo journalctl -u " + std::string(kService) + + " --since \"-" + std::to_string(seconds) + "s\" -o short-iso"; + return run_cmd(cmd).out; + } +} + +// -------- Log search helpers -------- +static inline bool contains_line(const std::string& logs, const char* needle) { + return logs.find(needle) != std::string::npos; +} + +static inline bool contains_regex(const std::string& logs, const std::regex& re) { + return std::regex_search(logs, re); +} + +} // namespace test_helpers + +#endif // TEST_HELPERS_HPP_INCLUDED diff --git a/tests/CMakeLists.txt b/tests/resource-tuner/CMakeLists.txt similarity index 84% rename from tests/CMakeLists.txt rename to tests/resource-tuner/CMakeLists.txt index e48e933d9..939d289e6 100644 --- a/tests/CMakeLists.txt +++ b/tests/resource-tuner/CMakeLists.txt @@ -8,6 +8,10 @@ if(BUILD_TESTS) # Optional: help the tests find a writable location through an env var set(TEST_REPORT_ENV "TEST_REPORT_DIR=${TEST_REPORT_DIR}") + + + # Put this near the top of the file (inside the if(BUILD_TESTS) block is fine) + set(FRAMEWORK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../framework") # Install Test Configs file(GLOB testConfigs "${CMAKE_CURRENT_SOURCE_DIR}/Configs/*.yaml") @@ -42,7 +46,7 @@ if(BUILD_TESTS) # --- Mini.hpp header-only unit/module/usecase tests --- set(COMPONENT_TEST_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/framework/testrunner.cpp + ${FRAMEWORK_DIR}/testrunner.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Component/ThreadPoolTests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Component/TimerTests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Component/SafeOpsTests.cpp @@ -63,7 +67,7 @@ add_executable(RestuneComponentTests ${COMPONENT_TEST_SOURCES}) # Make the header visible to the test sources target_include_directories(RestuneComponentTests PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/framework + ${FRAMEWORK_DIR} ) # Link any production libraries your tests depend on (adjust as needed) @@ -106,7 +110,7 @@ add_executable(RestuneIntegrationTests ) target_include_directories(RestuneIntegrationTests PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/framework # mini.hpp location + ${FRAMEWORK_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/Integration # local includes used by Integration tests # add other include dirs if your tests need them ) @@ -140,44 +144,41 @@ set_tests_properties(RestuneIntegrationTests_All PROPERTIES # all unit tests # ---------------------------------------- -# 1) One main TU that provides main() +# One main TU that provides main() set(RESTUNE_UNIT_MAIN - ${CMAKE_CURRENT_SOURCE_DIR}/framework/testrunner.cpp + ${FRAMEWORK_DIR}/testrunner.cpp ) -# 2) Test sources + shim + stubs + the real file under test for getResConf +# Test sources ++ the real file under test for getResConf set(RESTUNE_UNIT_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/unit/test_submitResProvisionRequest.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/unit/test_getResConf.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/unit/shims/SubmitShim.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Unit/test_submitResProvisionRequest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Unit/test_getResConf.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Unit/shims/SubmitShim.cpp ${CMAKE_SOURCE_DIR}/resource-tuner/core/ResourceRegistry.cpp ) -# Helpful debug output -message(STATUS "RESTUNE_UNIT_MAIN = ${RESTUNE_UNIT_MAIN}") -message(STATUS "RESTUNE_UNIT_SOURCES = ${RESTUNE_UNIT_SOURCES}") -# 3) Create the binary +# Create the binary add_executable(RestuneUnitTests ${RESTUNE_UNIT_MAIN} ${RESTUNE_UNIT_SOURCES} ) -# 4) Only the main TU should generate main(); the test TUs must not +# Only the main TU should generate main(); the test TUs must not set_source_files_properties( - ${CMAKE_CURRENT_SOURCE_DIR}/unit/test_submitResProvisionRequest.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/unit/test_getResConf.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Unit/test_submitResProvisionRequest.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Unit/test_getResConf.cpp PROPERTIES COMPILE_DEFINITIONS "MTEST_NO_MAIN=1" ) -# 5) Include paths for tests and core headers +# Include paths for tests and core headers target_include_directories(RestuneUnitTests PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/framework + ${FRAMEWORK_DIR} ${CMAKE_SOURCE_DIR}/resource-tuner/core/Include ${CMAKE_SOURCE_DIR}/modula/Common/Include ) -# 6) Link minimal libs only (do NOT link RestuneCore; shim+stubs avoid heavy initializers) +# Link minimal libs only (do NOT link RestuneCore; shim+stubs avoid heavy initializers) target_link_libraries(RestuneUnitTests PRIVATE UrmAuxUtils UrmExtAPIs @@ -185,12 +186,12 @@ target_link_libraries(RestuneUnitTests PRIVATE RestuneCore ) -# 7) mini.hpp default behavior +# mini.hpp default behavior target_compile_definitions(RestuneUnitTests PRIVATE MTEST_DEFAULT_OUTPUT_TAP=0 ) -# 8) Install & register with CTest +# Install & register with CTest install(TARGETS RestuneUnitTests RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/tests/Component/ClientDataManagerTests.cpp b/tests/resource-tuner/Component/ClientDataManagerTests.cpp similarity index 100% rename from tests/Component/ClientDataManagerTests.cpp rename to tests/resource-tuner/Component/ClientDataManagerTests.cpp diff --git a/tests/Component/CocoTableTests.cpp b/tests/resource-tuner/Component/CocoTableTests.cpp similarity index 100% rename from tests/Component/CocoTableTests.cpp rename to tests/resource-tuner/Component/CocoTableTests.cpp diff --git a/tests/Component/DeviceInfoTests.cpp b/tests/resource-tuner/Component/DeviceInfoTests.cpp similarity index 100% rename from tests/Component/DeviceInfoTests.cpp rename to tests/resource-tuner/Component/DeviceInfoTests.cpp diff --git a/tests/Component/ExtensionIntfTests.cpp b/tests/resource-tuner/Component/ExtensionIntfTests.cpp similarity index 100% rename from tests/Component/ExtensionIntfTests.cpp rename to tests/resource-tuner/Component/ExtensionIntfTests.cpp diff --git a/tests/Component/MemoryPoolTests.cpp b/tests/resource-tuner/Component/MemoryPoolTests.cpp similarity index 100% rename from tests/Component/MemoryPoolTests.cpp rename to tests/resource-tuner/Component/MemoryPoolTests.cpp diff --git a/tests/Component/MiscTests.cpp b/tests/resource-tuner/Component/MiscTests.cpp similarity index 100% rename from tests/Component/MiscTests.cpp rename to tests/resource-tuner/Component/MiscTests.cpp diff --git a/tests/Component/ParserTests.cpp b/tests/resource-tuner/Component/ParserTests.cpp similarity index 100% rename from tests/Component/ParserTests.cpp rename to tests/resource-tuner/Component/ParserTests.cpp diff --git a/tests/Component/RateLimiterTests.cpp b/tests/resource-tuner/Component/RateLimiterTests.cpp similarity index 100% rename from tests/Component/RateLimiterTests.cpp rename to tests/resource-tuner/Component/RateLimiterTests.cpp diff --git a/tests/Component/RequestMapTests.cpp b/tests/resource-tuner/Component/RequestMapTests.cpp similarity index 100% rename from tests/Component/RequestMapTests.cpp rename to tests/resource-tuner/Component/RequestMapTests.cpp diff --git a/tests/Component/RequestQueueTests.cpp b/tests/resource-tuner/Component/RequestQueueTests.cpp similarity index 100% rename from tests/Component/RequestQueueTests.cpp rename to tests/resource-tuner/Component/RequestQueueTests.cpp diff --git a/tests/Component/SafeOpsTests.cpp b/tests/resource-tuner/Component/SafeOpsTests.cpp similarity index 100% rename from tests/Component/SafeOpsTests.cpp rename to tests/resource-tuner/Component/SafeOpsTests.cpp diff --git a/tests/Component/ThreadPoolTests.cpp b/tests/resource-tuner/Component/ThreadPoolTests.cpp similarity index 100% rename from tests/Component/ThreadPoolTests.cpp rename to tests/resource-tuner/Component/ThreadPoolTests.cpp diff --git a/tests/Component/TimerTests.cpp b/tests/resource-tuner/Component/TimerTests.cpp similarity index 100% rename from tests/Component/TimerTests.cpp rename to tests/resource-tuner/Component/TimerTests.cpp diff --git a/tests/Configs/Baseline.yaml b/tests/resource-tuner/Configs/Baseline.yaml similarity index 100% rename from tests/Configs/Baseline.yaml rename to tests/resource-tuner/Configs/Baseline.yaml diff --git a/tests/Configs/ExtFeaturesConfig.yaml b/tests/resource-tuner/Configs/ExtFeaturesConfig.yaml similarity index 100% rename from tests/Configs/ExtFeaturesConfig.yaml rename to tests/resource-tuner/Configs/ExtFeaturesConfig.yaml diff --git a/tests/Configs/InitConfig.yaml b/tests/resource-tuner/Configs/InitConfig.yaml similarity index 100% rename from tests/Configs/InitConfig.yaml rename to tests/resource-tuner/Configs/InitConfig.yaml diff --git a/tests/Configs/InvalidSyntax.yaml b/tests/resource-tuner/Configs/InvalidSyntax.yaml similarity index 100% rename from tests/Configs/InvalidSyntax.yaml rename to tests/resource-tuner/Configs/InvalidSyntax.yaml diff --git a/tests/Configs/PerApp.yaml b/tests/resource-tuner/Configs/PerApp.yaml similarity index 100% rename from tests/Configs/PerApp.yaml rename to tests/resource-tuner/Configs/PerApp.yaml diff --git a/tests/Configs/PropertiesConfig.yaml b/tests/resource-tuner/Configs/PropertiesConfig.yaml similarity index 100% rename from tests/Configs/PropertiesConfig.yaml rename to tests/resource-tuner/Configs/PropertiesConfig.yaml diff --git a/tests/Configs/ResourceSysFsNodes/cluster_type_resource_0_cluster_id.txt b/tests/resource-tuner/Configs/ResourceSysFsNodes/cluster_type_resource_0_cluster_id.txt similarity index 100% rename from tests/Configs/ResourceSysFsNodes/cluster_type_resource_0_cluster_id.txt rename to tests/resource-tuner/Configs/ResourceSysFsNodes/cluster_type_resource_0_cluster_id.txt diff --git a/tests/Configs/ResourceSysFsNodes/cluster_type_resource_1_cluster_id.txt b/tests/resource-tuner/Configs/ResourceSysFsNodes/cluster_type_resource_1_cluster_id.txt similarity index 100% rename from tests/Configs/ResourceSysFsNodes/cluster_type_resource_1_cluster_id.txt rename to tests/resource-tuner/Configs/ResourceSysFsNodes/cluster_type_resource_1_cluster_id.txt diff --git a/tests/Configs/ResourceSysFsNodes/cluster_type_resource_2_cluster_id.txt b/tests/resource-tuner/Configs/ResourceSysFsNodes/cluster_type_resource_2_cluster_id.txt similarity index 100% rename from tests/Configs/ResourceSysFsNodes/cluster_type_resource_2_cluster_id.txt rename to tests/resource-tuner/Configs/ResourceSysFsNodes/cluster_type_resource_2_cluster_id.txt diff --git a/tests/Configs/ResourceSysFsNodes/cluster_type_resource_3_cluster_id.txt b/tests/resource-tuner/Configs/ResourceSysFsNodes/cluster_type_resource_3_cluster_id.txt similarity index 100% rename from tests/Configs/ResourceSysFsNodes/cluster_type_resource_3_cluster_id.txt rename to tests/resource-tuner/Configs/ResourceSysFsNodes/cluster_type_resource_3_cluster_id.txt diff --git a/tests/Configs/ResourceSysFsNodes/cluster_type_resource_4_cluster_id.txt b/tests/resource-tuner/Configs/ResourceSysFsNodes/cluster_type_resource_4_cluster_id.txt similarity index 100% rename from tests/Configs/ResourceSysFsNodes/cluster_type_resource_4_cluster_id.txt rename to tests/resource-tuner/Configs/ResourceSysFsNodes/cluster_type_resource_4_cluster_id.txt diff --git a/tests/Configs/ResourceSysFsNodes/cluster_type_resource_5_cluster_id.txt b/tests/resource-tuner/Configs/ResourceSysFsNodes/cluster_type_resource_5_cluster_id.txt similarity index 100% rename from tests/Configs/ResourceSysFsNodes/cluster_type_resource_5_cluster_id.txt rename to tests/resource-tuner/Configs/ResourceSysFsNodes/cluster_type_resource_5_cluster_id.txt diff --git a/tests/Configs/ResourceSysFsNodes/cluster_type_resource_6_cluster_id.txt b/tests/resource-tuner/Configs/ResourceSysFsNodes/cluster_type_resource_6_cluster_id.txt similarity index 100% rename from tests/Configs/ResourceSysFsNodes/cluster_type_resource_6_cluster_id.txt rename to tests/resource-tuner/Configs/ResourceSysFsNodes/cluster_type_resource_6_cluster_id.txt diff --git a/tests/Configs/ResourceSysFsNodes/cluster_type_resource_7_cluster_id.txt b/tests/resource-tuner/Configs/ResourceSysFsNodes/cluster_type_resource_7_cluster_id.txt similarity index 100% rename from tests/Configs/ResourceSysFsNodes/cluster_type_resource_7_cluster_id.txt rename to tests/resource-tuner/Configs/ResourceSysFsNodes/cluster_type_resource_7_cluster_id.txt diff --git a/tests/Configs/ResourceSysFsNodes/cluster_type_resource_8_cluster_id.txt b/tests/resource-tuner/Configs/ResourceSysFsNodes/cluster_type_resource_8_cluster_id.txt similarity index 100% rename from tests/Configs/ResourceSysFsNodes/cluster_type_resource_8_cluster_id.txt rename to tests/resource-tuner/Configs/ResourceSysFsNodes/cluster_type_resource_8_cluster_id.txt diff --git a/tests/Configs/ResourceSysFsNodes/cluster_type_resource_9_cluster_id.txt b/tests/resource-tuner/Configs/ResourceSysFsNodes/cluster_type_resource_9_cluster_id.txt similarity index 100% rename from tests/Configs/ResourceSysFsNodes/cluster_type_resource_9_cluster_id.txt rename to tests/resource-tuner/Configs/ResourceSysFsNodes/cluster_type_resource_9_cluster_id.txt diff --git a/tests/Configs/ResourceSysFsNodes/scaling_max_freq.txt b/tests/resource-tuner/Configs/ResourceSysFsNodes/scaling_max_freq.txt similarity index 100% rename from tests/Configs/ResourceSysFsNodes/scaling_max_freq.txt rename to tests/resource-tuner/Configs/ResourceSysFsNodes/scaling_max_freq.txt diff --git a/tests/Configs/ResourceSysFsNodes/scaling_min_freq.txt b/tests/resource-tuner/Configs/ResourceSysFsNodes/scaling_min_freq.txt similarity index 100% rename from tests/Configs/ResourceSysFsNodes/scaling_min_freq.txt rename to tests/resource-tuner/Configs/ResourceSysFsNodes/scaling_min_freq.txt diff --git a/tests/Configs/ResourceSysFsNodes/sched_util_clamp_max.txt b/tests/resource-tuner/Configs/ResourceSysFsNodes/sched_util_clamp_max.txt similarity index 100% rename from tests/Configs/ResourceSysFsNodes/sched_util_clamp_max.txt rename to tests/resource-tuner/Configs/ResourceSysFsNodes/sched_util_clamp_max.txt diff --git a/tests/Configs/ResourceSysFsNodes/sched_util_clamp_min.txt b/tests/resource-tuner/Configs/ResourceSysFsNodes/sched_util_clamp_min.txt similarity index 100% rename from tests/Configs/ResourceSysFsNodes/sched_util_clamp_min.txt rename to tests/resource-tuner/Configs/ResourceSysFsNodes/sched_util_clamp_min.txt diff --git a/tests/Configs/ResourceSysFsNodes/target_test_resource1.txt b/tests/resource-tuner/Configs/ResourceSysFsNodes/target_test_resource1.txt similarity index 100% rename from tests/Configs/ResourceSysFsNodes/target_test_resource1.txt rename to tests/resource-tuner/Configs/ResourceSysFsNodes/target_test_resource1.txt diff --git a/tests/Configs/ResourceSysFsNodes/target_test_resource2.txt b/tests/resource-tuner/Configs/ResourceSysFsNodes/target_test_resource2.txt similarity index 100% rename from tests/Configs/ResourceSysFsNodes/target_test_resource2.txt rename to tests/resource-tuner/Configs/ResourceSysFsNodes/target_test_resource2.txt diff --git a/tests/Configs/ResourceSysFsNodes/target_test_resource3.txt b/tests/resource-tuner/Configs/ResourceSysFsNodes/target_test_resource3.txt similarity index 100% rename from tests/Configs/ResourceSysFsNodes/target_test_resource3.txt rename to tests/resource-tuner/Configs/ResourceSysFsNodes/target_test_resource3.txt diff --git a/tests/Configs/ResourceSysFsNodes/target_test_resource4.txt b/tests/resource-tuner/Configs/ResourceSysFsNodes/target_test_resource4.txt similarity index 100% rename from tests/Configs/ResourceSysFsNodes/target_test_resource4.txt rename to tests/resource-tuner/Configs/ResourceSysFsNodes/target_test_resource4.txt diff --git a/tests/Configs/ResourceSysFsNodes/target_test_resource5.txt b/tests/resource-tuner/Configs/ResourceSysFsNodes/target_test_resource5.txt similarity index 100% rename from tests/Configs/ResourceSysFsNodes/target_test_resource5.txt rename to tests/resource-tuner/Configs/ResourceSysFsNodes/target_test_resource5.txt diff --git a/tests/Configs/ResourcesConfig.yaml b/tests/resource-tuner/Configs/ResourcesConfig.yaml similarity index 100% rename from tests/Configs/ResourcesConfig.yaml rename to tests/resource-tuner/Configs/ResourcesConfig.yaml diff --git a/tests/Configs/ResourcesConfigAddOn.yaml b/tests/resource-tuner/Configs/ResourcesConfigAddOn.yaml similarity index 100% rename from tests/Configs/ResourcesConfigAddOn.yaml rename to tests/resource-tuner/Configs/ResourcesConfigAddOn.yaml diff --git a/tests/Configs/SignalsConfig.yaml b/tests/resource-tuner/Configs/SignalsConfig.yaml similarity index 100% rename from tests/Configs/SignalsConfig.yaml rename to tests/resource-tuner/Configs/SignalsConfig.yaml diff --git a/tests/Configs/SignalsConfigAddOn.yaml b/tests/resource-tuner/Configs/SignalsConfigAddOn.yaml similarity index 100% rename from tests/Configs/SignalsConfigAddOn.yaml rename to tests/resource-tuner/Configs/SignalsConfigAddOn.yaml diff --git a/tests/Configs/TargetConfig.yaml b/tests/resource-tuner/Configs/TargetConfig.yaml similarity index 100% rename from tests/Configs/TargetConfig.yaml rename to tests/resource-tuner/Configs/TargetConfig.yaml diff --git a/tests/Configs/TargetConfigDup.yaml b/tests/resource-tuner/Configs/TargetConfigDup.yaml similarity index 100% rename from tests/Configs/TargetConfigDup.yaml rename to tests/resource-tuner/Configs/TargetConfigDup.yaml diff --git a/tests/Integration/IntegrationTests.cpp b/tests/resource-tuner/Integration/IntegrationTests.cpp similarity index 96% rename from tests/Integration/IntegrationTests.cpp rename to tests/resource-tuner/Integration/IntegrationTests.cpp index 513a624ab..b327a3a05 100644 --- a/tests/Integration/IntegrationTests.cpp +++ b/tests/resource-tuner/Integration/IntegrationTests.cpp @@ -1,6 +1,6 @@ // Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. // SPDX-License-Identifier: BSD-3-Clause-Clear - +#include #include "ErrCodes.h" #include "UrmPlatformAL.h" #include "Utils.h" @@ -1020,60 +1020,91 @@ MT_TEST(Integration, TestSingleClientSequentialRequests, "request-application") LOG_END } - -// Wrap as a mini.hpp test: Same client process, two threads issue concurrent requests (higher wins), then reset MT_TEST(Integration, TestMultipleClientTIDsConcurrentRequests, "request-application") { (void)ctx; // silence unused parameter warning LOG_START - std::string testResourceName = "/etc/urm/tests/nodes/scaling_max_freq.txt"; - int32_t testResourceOriginalValue = 114; - int64_t handle; - std::string value; - int32_t originalValue, newValue; + // --- Test configuration --- + const std::string testResourceName = "/etc/urm/tests/nodes/scaling_max_freq.txt"; + const int32_t expectedOriginalValue = 114; + const int32_t valueThread = 664; + const int32_t valueMain = 702; // Expect "higher wins" => 702 + const auto reqTtlMs = 6000; // tuneResources TTL + const auto applyWait = std::chrono::seconds(5); + const auto resetWait = std::chrono::seconds(8); + + // --- Helpers --- + auto read_int = [&](const std::string& path) -> int32_t { + std::string s = AuxRoutines::readFromFile(path); + return C_STOI(s); + }; - value = AuxRoutines::readFromFile(testResourceName); - originalValue = C_STOI(value); + auto poll_until = [&](int32_t expected, + std::chrono::milliseconds timeout, + std::chrono::milliseconds interval = std::chrono::milliseconds(100)) -> bool + { + auto start = std::chrono::steady_clock::now(); + while (std::chrono::steady_clock::now() - start < timeout) { + int32_t v = read_int(testResourceName); + if (v == expected) return true; + std::this_thread::sleep_for(interval); + } + return false; + }; + + // --- Capture original --- + int32_t originalValue = read_int(testResourceName); std::cout << LOG_BASE << testResourceName << " Original Value: " << originalValue << std::endl; - MT_REQUIRE_EQ(ctx, originalValue, testResourceOriginalValue); + MT_REQUIRE_EQ(ctx, originalValue, expectedOriginalValue); + + // --- Start concurrent request in worker thread --- std::thread th([&]{ SysResource* resourceList1 = new SysResource[1]; - memset(&resourceList1[0], 0, sizeof(SysResource)); + std::memset(&resourceList1[0], 0, sizeof(SysResource)); resourceList1[0].mResCode = 0x80ff0003; resourceList1[0].mOptionalInfo = 0; resourceList1[0].mNumValues = 1; - resourceList1[0].mResValue.value = 664; - handle = tuneResources(6000, RequestPriority::REQ_PRIORITY_HIGH, 1, resourceList1); - std::cout << LOG_BASE << "Handle Returned: " << handle << std::endl; - delete resourceList1; + resourceList1[0].mResValue.value = valueThread; + + int64_t handle1 = tuneResources(reqTtlMs, RequestPriority::REQ_PRIORITY_HIGH, 1, resourceList1); + std::cout << LOG_BASE << "Handle Returned (thread): " << handle1 << std::endl; + + delete[] resourceList1; // FIX: correct array delete }); + // --- Main thread request --- SysResource* resourceList2 = new SysResource[1]; - memset(&resourceList2[0], 0, sizeof(SysResource)); + std::memset(&resourceList2[0], 0, sizeof(SysResource)); resourceList2[0].mResCode = 0x80ff0003; resourceList2[0].mOptionalInfo = 0; resourceList2[0].mNumValues = 1; - resourceList2[0].mResValue.value = 702; - handle = tuneResources(6000, RequestPriority::REQ_PRIORITY_HIGH, 1, resourceList2); - std::cout << LOG_BASE << "Handle Returned: " << handle << std::endl; + resourceList2[0].mResValue.value = valueMain; + + int64_t handle2 = tuneResources(reqTtlMs, RequestPriority::REQ_PRIORITY_HIGH, 1, resourceList2); + std::cout << LOG_BASE << "Handle Returned (main): " << handle2 << std::endl; - std::this_thread::sleep_for(std::chrono::seconds(2)); - value = AuxRoutines::readFromFile(testResourceName); - newValue = C_STOI(value); - std::cout << LOG_BASE << testResourceName << " Configured Value: " << newValue << std::endl; - MT_REQUIRE_EQ(ctx, newValue, 702); - std::this_thread::sleep_for(std::chrono::seconds(6)); - value = AuxRoutines::readFromFile(testResourceName); - newValue = C_STOI(value); - std::cout << LOG_BASE << testResourceName << " Reset Value: " << newValue << std::endl; - MT_REQUIRE_EQ(ctx, newValue, testResourceOriginalValue); - th.join(); delete[] resourceList2; + // --- Ensure thread is joined BEFORE any assertion that might exit early --- + if (th.joinable()) th.join(); + + // --- Verify "higher wins" (expect 702) with a poll to avoid flakiness --- + bool configuredOk = poll_until(valueMain, std::chrono::duration_cast(applyWait)); + int32_t configuredValue = read_int(testResourceName); + std::cout << LOG_BASE << testResourceName << " Configured Value: " << configuredValue << std::endl; + + // If poll failed, assert on the last observed value so the log shows it + MT_REQUIRE_EQ(ctx, configuredOk ? valueMain : configuredValue, valueMain); + + // --- Verify reset after TTL (6s) with some buffer --- + bool resetOk = poll_until(expectedOriginalValue, std::chrono::duration_cast(resetWait)); + int32_t resetValue = read_int(testResourceName); + std::cout << LOG_BASE << testResourceName << " Reset Value: " << resetValue << std::endl; + MT_REQUIRE_EQ(ctx, resetOk ? expectedOriginalValue : resetValue, expectedOriginalValue); + LOG_END } - // Wrap as a mini.hpp test: Infinite duration tune, then valid untune → node resets MT_TEST(Integration, TestInfiniteDurationTuneRequestAndValidUntuning, "request-application") { (void)ctx; // silence unused parameter warning diff --git a/tests/Integration/StateDetectionTests.cpp b/tests/resource-tuner/Integration/StateDetectionTests.cpp similarity index 100% rename from tests/Integration/StateDetectionTests.cpp rename to tests/resource-tuner/Integration/StateDetectionTests.cpp diff --git a/tests/unit/shims/SubmitShim.cpp b/tests/resource-tuner/Unit/shims/SubmitShim.cpp similarity index 100% rename from tests/unit/shims/SubmitShim.cpp rename to tests/resource-tuner/Unit/shims/SubmitShim.cpp diff --git a/tests/unit/test_getResConf.cpp b/tests/resource-tuner/Unit/test_getResConf.cpp similarity index 100% rename from tests/unit/test_getResConf.cpp rename to tests/resource-tuner/Unit/test_getResConf.cpp diff --git a/tests/unit/test_submitResProvisionRequest.cpp b/tests/resource-tuner/Unit/test_submitResProvisionRequest.cpp similarity index 100% rename from tests/unit/test_submitResProvisionRequest.cpp rename to tests/resource-tuner/Unit/test_submitResProvisionRequest.cpp diff --git a/tests/Utils/Baseline.cpp b/tests/resource-tuner/Utils/Baseline.cpp similarity index 100% rename from tests/Utils/Baseline.cpp rename to tests/resource-tuner/Utils/Baseline.cpp diff --git a/tests/Utils/Include/JoiningThread.h b/tests/resource-tuner/Utils/Include/JoiningThread.h similarity index 100% rename from tests/Utils/Include/JoiningThread.h rename to tests/resource-tuner/Utils/Include/JoiningThread.h diff --git a/tests/Utils/Include/TestAggregator.h b/tests/resource-tuner/Utils/Include/TestAggregator.h similarity index 100% rename from tests/Utils/Include/TestAggregator.h rename to tests/resource-tuner/Utils/Include/TestAggregator.h diff --git a/tests/Utils/Include/TestBaseline.h b/tests/resource-tuner/Utils/Include/TestBaseline.h similarity index 100% rename from tests/Utils/Include/TestBaseline.h rename to tests/resource-tuner/Utils/Include/TestBaseline.h diff --git a/tests/Utils/Include/TestInitReset.h b/tests/resource-tuner/Utils/Include/TestInitReset.h similarity index 100% rename from tests/Utils/Include/TestInitReset.h rename to tests/resource-tuner/Utils/Include/TestInitReset.h diff --git a/tests/Utils/Include/TestUtils.h b/tests/resource-tuner/Utils/Include/TestUtils.h similarity index 100% rename from tests/Utils/Include/TestUtils.h rename to tests/resource-tuner/Utils/Include/TestUtils.h diff --git a/tests/Utils/Setup.cpp b/tests/resource-tuner/Utils/Setup.cpp similarity index 100% rename from tests/Utils/Setup.cpp rename to tests/resource-tuner/Utils/Setup.cpp diff --git a/tests/Utils/TestAggregator.cpp b/tests/resource-tuner/Utils/TestAggregator.cpp similarity index 100% rename from tests/Utils/TestAggregator.cpp rename to tests/resource-tuner/Utils/TestAggregator.cpp diff --git a/tests/unit/stubs/RegistryStubs.cpp b/tests/unit/stubs/RegistryStubs.cpp deleted file mode 100644 index 7cb2444ff..000000000 --- a/tests/unit/stubs/RegistryStubs.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. -// SPDX-License-Identifier: BSD-3-Clause-Clear - - -// -------------- TargetRegistry stubs -------------- -std::shared_ptr TargetRegistry::targetRegistryInstance = nullptr; -TargetRegistry::TargetRegistry() {} -TargetRegistry::~TargetRegistry() {} - -void TargetRegistry::getClusterIDs(std::vector& out) { - out.clear(); // test: no clusters -} -void TargetRegistry::getCGroupNames(std::vector& out) { - out.clear(); // test: no cgroups -} - -// -------------- Default lifecycle callbacks -------------- -void defaultClusterLevelApplierCb(void*) {} -void defaultClusterLevelTearCb(void*) {} -void defaultCoreLevelApplierCb(void*) {} -void defaultCoreLevelTearCb(void*) {} -void defaultCGroupLevelApplierCb(void*) {} -void defaultCGroupLevelTearCb(void*) {} -void defaultGlobalLevelApplierCb(void*) {} -void defaultGlobalLevelTearCb(void*) {} -