GroveEngine/tests/modules/LeakTestModule.cpp
StillHammer 9105610b29 feat: Add integration tests 8-10 & fix CTest configuration
Added three new integration test scenarios:
- Test 08: Config Hot-Reload (dynamic configuration updates)
- Test 09: Module Dependencies (dependency injection & cascade reload)
- Test 10: Multi-Version Coexistence (canary deployment & progressive migration)

Fixes:
- Fixed CTest working directory for all tests (add WORKING_DIRECTORY)
- Fixed module paths to use relative paths (./ prefix)
- Fixed IModule.h comments for clarity

New test modules:
- ConfigurableModule (for config reload testing)
- BaseModule, DependentModule, IndependentModule (for dependency testing)
- GameLogicModuleV1/V2/V3 (for multi-version testing)

Test coverage now includes 10 comprehensive integration scenarios covering
hot-reload, chaos testing, stress testing, race conditions, memory leaks,
error recovery, limits, config reload, dependencies, and multi-versioning.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 07:34:15 +08:00

125 lines
3.6 KiB
C++

// ============================================================================
// LeakTestModule.cpp - Module for memory leak detection testing
// ============================================================================
#include "grove/IModule.h"
#include "grove/IDataNode.h"
#include "grove/JsonDataNode.h"
#include "grove/JsonDataValue.h"
#include <vector>
#include <string>
#include <algorithm>
#include <memory>
#include <nlohmann/json.hpp>
namespace grove {
class LeakTestModule : public IModule {
private:
std::vector<uint8_t> workBuffer;
int processCount = 0;
int lastChecksum = 0;
IIO* io = nullptr;
ITaskScheduler* scheduler = nullptr;
std::unique_ptr<IDataNode> config;
public:
LeakTestModule() = default;
~LeakTestModule() override = default;
void process(const IDataNode& input) override {
processCount++;
// Simulate real workload with allocations (1 MB working buffer)
workBuffer.resize(1024 * 1024);
std::fill(workBuffer.begin(), workBuffer.end(),
static_cast<uint8_t>(processCount % 256));
// Small temporary allocations (simulate logging/processing)
std::vector<std::string> logs;
logs.reserve(100);
for (int i = 0; i < 100; i++) {
logs.push_back("Process iteration " + std::to_string(processCount));
}
// Simulate some data processing
int sum = 0;
for (size_t i = 0; i < workBuffer.size(); i += 1024) {
sum += workBuffer[i];
}
lastChecksum = sum;
}
void setConfiguration(const IDataNode& configNode, IIO* ioPtr, ITaskScheduler* schedulerPtr) override {
this->io = ioPtr;
this->scheduler = schedulerPtr;
config = std::make_unique<JsonDataNode>("config", nlohmann::json::object());
}
const IDataNode& getConfiguration() override {
if (!config) {
config = std::make_unique<JsonDataNode>("config", nlohmann::json::object());
}
return *config;
}
std::unique_ptr<IDataNode> getHealthStatus() override {
nlohmann::json health = {
{"status", "healthy"},
{"processCount", processCount},
{"lastChecksum", lastChecksum},
{"bufferSize", workBuffer.size()}
};
return std::make_unique<JsonDataNode>("health", health);
}
void shutdown() override {
// Clean up
workBuffer.clear();
workBuffer.shrink_to_fit();
}
std::unique_ptr<IDataNode> getState() override {
nlohmann::json state = {
{"processCount", processCount},
{"lastChecksum", lastChecksum}
};
return std::make_unique<JsonDataNode>("state", state);
}
void setState(const IDataNode& state) override {
processCount = state.getInt("processCount", 0);
lastChecksum = state.getInt("lastChecksum", 0);
// Note: We don't need to restore stateBlob, it's just for testing memory
// during serialization
}
std::string getType() const override {
return "LeakTestModule";
}
bool isIdle() const override {
return true;
}
};
} // namespace grove
// ============================================================================
// Module Factory
// ============================================================================
extern "C" {
grove::IModule* createModule() {
return new grove::LeakTestModule();
}
void destroyModule(grove::IModule* module) {
delete module;
}
} // extern "C"