Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,25 @@ debug_dual_flac_LDADD = \
$(top_builddir)/src/core/libpsymp3-core.a \
$(AM_LDFLAGS)

test_memory_optimizer_SOURCES = test_memory_optimizer.cpp
test_memory_optimizer_LDADD = \
libtest_utilities.a \
$(top_builddir)/src/io/file/libpsymp3-io-file.a \
$(top_builddir)/src/io/libpsymp3-io.a \
$(top_builddir)/src/debug.o \
$(top_builddir)/src/core/libpsymp3-core.a \
$(AM_LDFLAGS)

test_memory_leak_prevention_SOURCES = test_memory_leak_prevention.cpp
test_memory_leak_prevention_LDADD = \
libtest_utilities.a \
$(top_builddir)/src/io/file/libpsymp3-io-file.a \
$(top_builddir)/src/io/http/libpsymp3-io-http.a \
$(top_builddir)/src/io/libpsymp3-io.a \
$(top_builddir)/src/debug.o \
$(top_builddir)/src/core/libpsymp3-core.a \
$(AM_LDFLAGS)

debug_bit_extraction_SOURCES = debug_bit_extraction.cpp
debug_bit_extraction_LDADD = $(AM_LDFLAGS)

Expand Down Expand Up @@ -553,7 +572,7 @@ endif
check_PROGRAMS += test_codec_selection_validation_simple

# Performance and thread safety tests
check_PROGRAMS += test_codec_performance test_codec_thread_safety test_codec_concurrent_instances test_codec_performance_simple test_codec_thread_safety_simple test_threading_safety_baseline test_audio_thread_safety test_audio_threading_pattern test_iohandler_thread_safety_comprehensive test_iohandler_memory_deadlock_prevention test_memory_pool_manager_integration test_memory_pool_manager_thread_safety_comprehensive test_memory_pool_manager_basic_threading test_memory_pool_allocation_failure test_surface_thread_safety test_surface_performance_regression test_system_wide_threading_integration test_threading_performance_regression
check_PROGRAMS += test_codec_performance test_codec_thread_safety test_codec_concurrent_instances test_codec_performance_simple test_codec_thread_safety_simple test_threading_safety_baseline test_audio_thread_safety test_audio_threading_pattern test_iohandler_thread_safety_comprehensive test_iohandler_memory_deadlock_prevention test_memory_pool_manager_integration test_memory_pool_manager_thread_safety_comprehensive test_memory_pool_manager_basic_threading test_memory_pool_allocation_failure test_surface_thread_safety test_surface_performance_regression test_system_wide_threading_integration test_threading_performance_regression test_memory_optimizer test_memory_leak_prevention

Comment on lines +575 to 576
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding test_memory_leak_prevention to check_PROGRAMS means it will run under make check (since TESTS = $(check_PROGRAMS) in this Makefile). tests/test_memory_leak_prevention.cpp performs real HTTP requests (e.g., to httpbin.org), which makes the test suite dependent on external network availability and can be flaky/fail in CI or offline builds. Consider keeping it as a manual/debug test (buildable but not in TESTS), or refactor it to avoid external network (mock server/fixture, or gate execution behind an env var/feature check).

Suggested change
check_PROGRAMS += test_codec_performance test_codec_thread_safety test_codec_concurrent_instances test_codec_performance_simple test_codec_thread_safety_simple test_threading_safety_baseline test_audio_thread_safety test_audio_threading_pattern test_iohandler_thread_safety_comprehensive test_iohandler_memory_deadlock_prevention test_memory_pool_manager_integration test_memory_pool_manager_thread_safety_comprehensive test_memory_pool_manager_basic_threading test_memory_pool_allocation_failure test_surface_thread_safety test_surface_performance_regression test_system_wide_threading_integration test_threading_performance_regression test_memory_optimizer test_memory_leak_prevention
check_PROGRAMS += test_codec_performance test_codec_thread_safety test_codec_concurrent_instances test_codec_performance_simple test_codec_thread_safety_simple test_threading_safety_baseline test_audio_thread_safety test_audio_threading_pattern test_iohandler_thread_safety_comprehensive test_iohandler_memory_deadlock_prevention test_memory_pool_manager_integration test_memory_pool_manager_thread_safety_comprehensive test_memory_pool_manager_basic_threading test_memory_pool_allocation_failure test_surface_thread_safety test_surface_performance_regression test_system_wide_threading_integration test_threading_performance_regression test_memory_optimizer
# Network-dependent manual/debug test; keep buildable but do not run under `make check`
noinst_PROGRAMS += test_memory_leak_prevention

Copilot uses AI. Check for mistakes.
# SimplePCMCodec integration tests
check_PROGRAMS += test_simplepcmcodec_integration_minimal test_simplepcmcodec_real_integration test_simplepcmcodec_comprehensive_integration
Expand Down
76 changes: 67 additions & 9 deletions tests/test_memory_optimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,8 @@ void testBoundedQueue() {
}

// Get stats
auto stats = queue.getStats();
std::cout << "Queue stats: " << stats.current_items << " items, "
<< stats.current_memory_bytes << " bytes, "
<< stats.total_items_pushed << " pushed, "
<< stats.total_items_dropped << " dropped" << std::endl;
std::cout << "Queue size: " << queue.size() << " items, "
<< queue.memoryUsage() << " bytes" << std::endl;

// Pop items
int value;
Expand All @@ -98,9 +95,8 @@ void testBoundedQueue() {
}

// Get stats after pop
stats = queue.getStats();
std::cout << "Queue stats after pop: " << stats.current_items << " items, "
<< stats.current_memory_bytes << " bytes" << std::endl;
std::cout << "Queue size after pop: " << queue.size() << " items, "
<< queue.memoryUsage() << " bytes" << std::endl;

std::cout << "BoundedQueue test completed." << std::endl;
}
Expand All @@ -124,7 +120,7 @@ void testMemoryTracker() {
std::cout << " Total physical memory: " << (stats.total_physical_memory / (1024 * 1024)) << " MB" << std::endl;
std::cout << " Available physical memory: " << (stats.available_physical_memory / (1024 * 1024)) << " MB" << std::endl;
std::cout << " Process memory usage: " << (stats.process_memory_usage / (1024 * 1024)) << " MB" << std::endl;
std::cout << " Memory pressure level: " << stats.memory_pressure_level << "%" << std::endl;
std::cout << " Memory pressure level: " << tracker.getMemoryPressureLevel() << "%" << std::endl;

// Allocate some memory to change pressure
std::vector<std::vector<uint8_t>> memory_blocks;
Expand All @@ -145,6 +141,65 @@ void testMemoryTracker() {
std::cout << "MemoryTracker test completed." << std::endl;
}

// Test the MemoryOptimizer Core functionality
void testMemoryOptimizerCore() {
std::cout << "Testing MemoryOptimizer Core functionality..." << std::endl;

MemoryOptimizer& optimizer = MemoryOptimizer::getInstance();
IOBufferPool& pool = IOBufferPool::getInstance();

// Initial state
pool.clear();
std::cout << "Initial pool size: " << pool.getStats().at("current_pool_size") << " bytes" << std::endl;

// Set memory limits for MemoryOptimizer
optimizer.setMemoryLimits(1024 * 1024, 512 * 1024); // 1MB total, 512KB buffer

// Register some allocations to simulate usage
optimizer.registerAllocation(500 * 1024, "test_component1");
optimizer.registerAllocation(200 * 1024, "test_component2");

auto mem_stats = optimizer.getMemoryStats();
std::cout << "MemoryOptimizer total usage: " << mem_stats["total_memory_usage"] << " bytes" << std::endl;

// Populate the IOBufferPool
std::vector<IOBufferPool::Buffer> buffers;
for (int i = 0; i < 50; i++) {
buffers.push_back(pool.acquire(8192)); // 8KB buffers
}

// Release them back to populate the pool
for (auto& buffer : buffers) {
buffer.release();
}
buffers.clear();

std::cout << "Pool size before optimization: " << pool.getStats().at("current_pool_size") << " bytes" << std::endl;

// Set a critical memory pressure level
// Memory usage is 716800 bytes, total limit is 1MB. (716KB / 1024KB = 70%)
// Let's force optimization manually or change memory limits to trigger pressure
optimizer.setMemoryLimits(700 * 1024, 512 * 1024);

// Call optimizeMemoryUsage
optimizer.optimizeMemoryUsage();

std::cout << "Pool size after optimization: " << pool.getStats().at("current_pool_size") << " bytes" << std::endl;

// Assert cache trimming
if (pool.getStats().at("current_pool_size") >= 65536) {
std::cerr << "Assertion failed: Pool size was not trimmed during optimization!" << std::endl;
std::exit(1);
}
Comment on lines +179 to +193
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

testMemoryOptimizerCore() assumes lowering setMemoryLimits() and calling optimizeMemoryUsage() will immediately perform aggressive trimming and drop current_pool_size below 65536. In MemoryOptimizer, the optimization behavior depends on the cached m_memory_pressure_level, which is only recomputed by the monitoring thread (every 5s), so this test is timing-dependent and will often run with Normal pressure (where the pool limit becomes m_max_total_memory/4, i.e. ~175KB here) and fail. Make the assertion deterministic by either (a) waiting/polling until optimizer.getMemoryPressureLevel() reaches the expected level before optimizing, or (b) asserting current_pool_size is <= the expected max derived from the current pressure level and m_max_total_memory, instead of a hard-coded 64KB threshold.

Copilot uses AI. Check for mistakes.

// Clean up
pool.clear();
optimizer.registerDeallocation(500 * 1024, "test_component1");
optimizer.registerDeallocation(200 * 1024, "test_component2");

std::cout << "MemoryOptimizer Core test completed." << std::endl;
}

// Main test function
int main() {
std::srand(static_cast<unsigned int>(std::time(nullptr)));
Expand All @@ -161,6 +216,9 @@ int main() {
testMemoryTracker();
std::cout << std::endl;

testMemoryOptimizerCore();
std::cout << std::endl;

std::cout << "All tests completed." << std::endl;

return 0;
Expand Down
Loading