feat: implement mass balance validation for Story 7.1
- Added port_mass_flows to Component trait and implements for core components. - Added System::check_mass_balance and integrated it into the solver. - Restored connect methods for ExpansionValve, Compressor, and Pipe to fix integration tests. - Updated Python and C bindings for validation errors. - Updated sprint status and story documentation.
This commit is contained in:
156
bindings/c/tests/test_memory.c
Normal file
156
bindings/c/tests/test_memory.c
Normal file
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* Test: Memory leak detection
|
||||
*
|
||||
* This test should be run with valgrind or ASAN to detect memory leaks.
|
||||
*
|
||||
* Usage:
|
||||
* valgrind --leak-check=full --error-exitcode=1 ./test_memory
|
||||
*
|
||||
* Or compile with ASAN:
|
||||
* gcc -fsanitize=address -o test_memory test_memory.c -L../../../target/release -lentropyk_ffi
|
||||
* ./test_memory
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include "entropyk.h"
|
||||
|
||||
#define NUM_CYCLES 100
|
||||
|
||||
int main() {
|
||||
printf("Test: Memory leak detection\n");
|
||||
printf(" Run with: valgrind --leak-check=full ./test_memory\n\n");
|
||||
|
||||
/* Test 1: System lifecycle */
|
||||
printf(" Test 1: System create/free cycles (%d iterations)... ", NUM_CYCLES);
|
||||
for (int i = 0; i < NUM_CYCLES; i++) {
|
||||
EntropykSystem* sys = entropyk_system_create();
|
||||
assert(sys != NULL);
|
||||
entropyk_system_free(sys);
|
||||
}
|
||||
printf("PASS\n");
|
||||
|
||||
/* Test 2: Component lifecycle (not added to system) */
|
||||
printf(" Test 2: Component create/free cycles... ");
|
||||
for (int i = 0; i < NUM_CYCLES; i++) {
|
||||
double coeffs[10] = {0.85, 2.5, 500.0, 1500.0, -2.5, 1.8, 600.0, 1600.0, -3.0, 2.0};
|
||||
EntropykComponent* comp = entropyk_compressor_create(coeffs, 10);
|
||||
EntropykComponent* cond = entropyk_condenser_create(5000.0);
|
||||
EntropykComponent* evap = entropyk_evaporator_create(3000.0);
|
||||
EntropykComponent* valve = entropyk_expansion_valve_create();
|
||||
|
||||
assert(comp && cond && evap && valve);
|
||||
|
||||
entropyk_compressor_free(comp);
|
||||
entropyk_component_free(cond);
|
||||
entropyk_component_free(evap);
|
||||
entropyk_component_free(valve);
|
||||
}
|
||||
printf("PASS\n");
|
||||
|
||||
/* Test 3: Full system with components (ownership transfer) */
|
||||
printf(" Test 3: Full system lifecycle... ");
|
||||
for (int i = 0; i < NUM_CYCLES; i++) {
|
||||
EntropykSystem* sys = entropyk_system_create();
|
||||
assert(sys != NULL);
|
||||
|
||||
double coeffs[10] = {0.85, 2.5, 500.0, 1500.0, -2.5, 1.8, 600.0, 1600.0, -3.0, 2.0};
|
||||
EntropykComponent* comp = entropyk_compressor_create(coeffs, 10);
|
||||
EntropykComponent* cond = entropyk_condenser_create(5000.0);
|
||||
EntropykComponent* evap = entropyk_evaporator_create(3000.0);
|
||||
EntropykComponent* valve = entropyk_expansion_valve_create();
|
||||
|
||||
unsigned int comp_idx = entropyk_system_add_component(sys, comp);
|
||||
unsigned int cond_idx = entropyk_system_add_component(sys, cond);
|
||||
unsigned int evap_idx = entropyk_system_add_component(sys, evap);
|
||||
unsigned int valve_idx = entropyk_system_add_component(sys, valve);
|
||||
|
||||
(void)comp_idx; (void)cond_idx; (void)evap_idx; (void)valve_idx;
|
||||
|
||||
entropyk_system_free(sys);
|
||||
/* Note: Components are freed when system is freed (ownership transfer) */
|
||||
}
|
||||
printf("PASS\n");
|
||||
|
||||
/* Test 4: Solver result lifecycle */
|
||||
printf(" Test 4: Solver result lifecycle... ");
|
||||
for (int i = 0; i < NUM_CYCLES; i++) {
|
||||
EntropykSystem* sys = entropyk_system_create();
|
||||
|
||||
double coeffs[10] = {0.85, 2.5, 500.0, 1500.0, -2.5, 1.8, 600.0, 1600.0, -3.0, 2.0};
|
||||
EntropykComponent* comp = entropyk_compressor_create(coeffs, 10);
|
||||
EntropykComponent* cond = entropyk_condenser_create(5000.0);
|
||||
EntropykComponent* evap = entropyk_evaporator_create(3000.0);
|
||||
EntropykComponent* valve = entropyk_expansion_valve_create();
|
||||
|
||||
entropyk_system_add_component(sys, comp);
|
||||
entropyk_system_add_component(sys, cond);
|
||||
entropyk_system_add_component(sys, evap);
|
||||
entropyk_system_add_component(sys, valve);
|
||||
|
||||
entropyk_system_finalize(sys);
|
||||
|
||||
EntropykFallbackConfig config = {
|
||||
.newton = {10, 1e-4, false, 100},
|
||||
.picard = {20, 1e-3, 0.5}
|
||||
};
|
||||
|
||||
EntropykSolverResult* result = NULL;
|
||||
entropyk_solve_fallback(sys, &config, &result);
|
||||
|
||||
if (result != NULL) {
|
||||
entropyk_result_free(result);
|
||||
}
|
||||
|
||||
entropyk_system_free(sys);
|
||||
}
|
||||
printf("PASS\n");
|
||||
|
||||
/* Test 5: Null pointer handling (should not crash or leak) */
|
||||
printf(" Test 5: Null pointer handling... ");
|
||||
entropyk_system_free(NULL);
|
||||
entropyk_compressor_free(NULL);
|
||||
entropyk_component_free(NULL);
|
||||
entropyk_result_free(NULL);
|
||||
printf("PASS\n");
|
||||
|
||||
/* Test 6: State vector retrieval */
|
||||
printf(" Test 6: State vector allocation... ");
|
||||
EntropykSystem* sys = entropyk_system_create();
|
||||
double coeffs[10] = {0.85, 2.5, 500.0, 1500.0, -2.5, 1.8, 600.0, 1600.0, -3.0, 2.0};
|
||||
EntropykComponent* comp = entropyk_compressor_create(coeffs, 10);
|
||||
EntropykComponent* cond = entropyk_condenser_create(5000.0);
|
||||
EntropykComponent* evap = entropyk_evaporator_create(3000.0);
|
||||
EntropykComponent* valve = entropyk_expansion_valve_create();
|
||||
|
||||
entropyk_system_add_component(sys, comp);
|
||||
entropyk_system_add_component(sys, cond);
|
||||
entropyk_system_add_component(sys, evap);
|
||||
entropyk_system_add_component(sys, valve);
|
||||
entropyk_system_finalize(sys);
|
||||
|
||||
EntropykFallbackConfig config = {
|
||||
.newton = {10, 1e-4, false, 100},
|
||||
.picard = {20, 1e-3, 0.5}
|
||||
};
|
||||
|
||||
EntropykSolverResult* result = NULL;
|
||||
if (entropyk_solve_fallback(sys, &config, &result) == ENTROPYK_OK && result != NULL) {
|
||||
unsigned int len = 0;
|
||||
entropyk_result_get_state_vector(result, NULL, &len);
|
||||
if (len > 0) {
|
||||
double* state = (double*)malloc(len * sizeof(double));
|
||||
entropyk_result_get_state_vector(result, state, &len);
|
||||
free(state);
|
||||
}
|
||||
entropyk_result_free(result);
|
||||
}
|
||||
entropyk_system_free(sys);
|
||||
printf("PASS\n");
|
||||
|
||||
printf("\nAll memory tests PASSED\n");
|
||||
printf("If running under valgrind, check for 'ERROR SUMMARY: 0 errors'\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user