1717
1818#include <stdlib.h>
1919#include <string.h>
20+ #include <stdint.h>
2021#include <stdatomic.h>
2122#include "foundation/compat_thread.h"
2223#include <fcntl.h>
@@ -1284,13 +1285,41 @@ static void cleanup_cross_maven_fixture(cross_maven_fixture_t *fx) {
12841285
12851286extern bool cbm_cross_repo_maven_grow_array (void * * items , int * cap , size_t elem_size ,
12861287 void * (* realloc_fn )(void * , size_t ));
1288+ extern bool cbm_cross_repo_project_list_alloc (char * * * out , int cap ,
1289+ void * (* malloc_fn )(size_t ));
12871290
12881291static void * test_maven_realloc_fails (void * ptr , size_t size ) {
12891292 (void )ptr ;
12901293 (void )size ;
12911294 return NULL ;
12921295}
12931296
1297+ static int g_test_maven_realloc_calls ;
1298+
1299+ static void * test_maven_realloc_records_call (void * ptr , size_t size ) {
1300+ (void )size ;
1301+ g_test_maven_realloc_calls ++ ;
1302+ return ptr ;
1303+ }
1304+
1305+ static void * test_project_list_malloc_fails (size_t size ) {
1306+ (void )size ;
1307+ return NULL ;
1308+ }
1309+
1310+ TEST (cross_repo_project_list_initial_alloc_failure_returns_empty ) {
1311+ char * * projects = (char * * )1 ;
1312+
1313+ ASSERT_FALSE (cbm_cross_repo_project_list_alloc (& projects , 32 , test_project_list_malloc_fails ));
1314+ ASSERT_NULL (projects );
1315+
1316+ projects = (char * * )1 ;
1317+ ASSERT_FALSE (cbm_cross_repo_project_list_alloc (& projects , 0 , test_project_list_malloc_fails ));
1318+ ASSERT_NULL (projects );
1319+
1320+ PASS ();
1321+ }
1322+
12941323TEST (cross_repo_maven_failed_growth_preserves_capacity ) {
12951324 int cap = 32 ;
12961325 char * items = malloc ((size_t )cap );
@@ -1307,6 +1336,24 @@ TEST(cross_repo_maven_failed_growth_preserves_capacity) {
13071336 PASS ();
13081337}
13091338
1339+ TEST (cross_repo_maven_growth_rejects_byte_overflow_before_realloc ) {
1340+ int cap = 2 ;
1341+ char * items = malloc (1 );
1342+ ASSERT_NOT_NULL (items );
1343+ void * original = items ;
1344+ g_test_maven_realloc_calls = 0 ;
1345+
1346+ ASSERT_FALSE (cbm_cross_repo_maven_grow_array (
1347+ (void * * )& items , & cap , (SIZE_MAX / (size_t )(cap * PAIR_LEN )) + 1 ,
1348+ test_maven_realloc_records_call ));
1349+ ASSERT_EQ (g_test_maven_realloc_calls , 0 );
1350+ ASSERT_EQ (cap , 2 );
1351+ ASSERT_EQ (items == original , 1 );
1352+
1353+ free (items );
1354+ PASS ();
1355+ }
1356+
13101357TEST (cross_repo_maven_dependency_creates_library_edges ) {
13111358 const char * provider_pom = "<project><modelVersion>4.0.0</modelVersion>"
13121359 "<groupId>com.example.platform</groupId>"
@@ -1493,7 +1540,16 @@ TEST(cross_repo_maven_cleanup_preserves_unrelated_nodes) {
14931540 .start_line = 1 ,
14941541 .end_line = 1 ,
14951542 .properties_json = "{}" };
1543+ cbm_node_t prefixed_function = {.project = "consumer" ,
1544+ .label = "Function" ,
1545+ .name = "PrefixedFunction" ,
1546+ .qualified_name = "__library__manual_function_should_stay" ,
1547+ .file_path = "src/manual.c" ,
1548+ .start_line = 1 ,
1549+ .end_line = 1 ,
1550+ .properties_json = "{}" };
14961551 ASSERT_GT (cbm_store_upsert_node (consumer , & unrelated ), 0 );
1552+ ASSERT_GT (cbm_store_upsert_node (consumer , & prefixed_function ), 0 );
14971553 cbm_store_close (consumer );
14981554
14991555 const char * targets [] = {"provider" };
@@ -1503,12 +1559,49 @@ TEST(cross_repo_maven_cleanup_preserves_unrelated_nodes) {
15031559 consumer = cbm_store_open_path (fx .consumer_db );
15041560 ASSERT_NOT_NULL (consumer );
15051561 ASSERT_TRUE (node_exists_by_qn (consumer , "consumer" , "xxlibraryzz_should_stay" ));
1562+ ASSERT_TRUE (node_exists_by_qn (consumer , "consumer" , "__library__manual_function_should_stay" ));
15061563 cbm_store_close (consumer );
15071564
15081565 cleanup_cross_maven_fixture (& fx );
15091566 PASS ();
15101567}
15111568
1569+ TEST (cross_repo_maven_provider_rerun_preserves_incoming_used_by ) {
1570+ const char * provider_pom = "<project><modelVersion>4.0.0</modelVersion>"
1571+ "<groupId>com.example.platform</groupId>"
1572+ "<artifactId>shared-library</artifactId>"
1573+ "<version>1.0.0</version></project>" ;
1574+ const char * consumer_pom =
1575+ "<project><modelVersion>4.0.0</modelVersion>"
1576+ "<groupId>app</groupId><artifactId>consumer</artifactId>"
1577+ "<dependencies><dependency><groupId>com.example.platform</groupId>"
1578+ "<artifactId>shared-library</artifactId><version>1.0.0</version>"
1579+ "</dependency></dependencies></project>" ;
1580+ cross_maven_fixture_t fx ;
1581+ ASSERT_EQ (setup_cross_maven_fixture (& fx , provider_pom , consumer_pom ), 0 );
1582+
1583+ const char * provider_targets [] = {"provider" };
1584+ cbm_cross_repo_result_t result = cbm_cross_repo_match ("consumer" , provider_targets , 1 );
1585+ ASSERT_EQ (result .library_edges , 1 );
1586+
1587+ cbm_store_t * provider = cbm_store_open_path (fx .provider_db );
1588+ ASSERT_NOT_NULL (provider );
1589+ ASSERT_EQ (count_edges_by_type (provider , "provider" , "CROSS_LIBRARY_USED_BY" ), 1 );
1590+ cbm_store_close (provider );
1591+
1592+ const char * consumer_targets [] = {"consumer" };
1593+ result = cbm_cross_repo_match ("provider" , consumer_targets , 1 );
1594+ ASSERT_EQ (result .library_edges , 0 );
1595+
1596+ provider = cbm_store_open_path (fx .provider_db );
1597+ ASSERT_NOT_NULL (provider );
1598+ ASSERT_EQ (count_edges_by_type (provider , "provider" , "CROSS_LIBRARY_USED_BY" ), 1 );
1599+ cbm_store_close (provider );
1600+
1601+ cleanup_cross_maven_fixture (& fx );
1602+ PASS ();
1603+ }
1604+
15121605TEST (cross_repo_maven_removed_dependency_clears_provider_used_by ) {
15131606 const char * provider_pom = "<project><modelVersion>4.0.0</modelVersion>"
15141607 "<groupId>com.example.platform</groupId>"
@@ -6591,13 +6684,16 @@ SUITE(pipeline) {
65916684 /* FastAPI Depends edge tracking (PR #66 port) */
65926685 RUN_TEST (pipeline_fastapi_depends_edges );
65936686 /* Cross-repo library dependency linking */
6687+ RUN_TEST (cross_repo_project_list_initial_alloc_failure_returns_empty );
65946688 RUN_TEST (cross_repo_maven_failed_growth_preserves_capacity );
6689+ RUN_TEST (cross_repo_maven_growth_rejects_byte_overflow_before_realloc );
65956690 RUN_TEST (cross_repo_maven_dependency_creates_library_edges );
65966691 RUN_TEST (cross_repo_maven_dependency_escapes_library_edge_props );
65976692 RUN_TEST (cross_repo_maven_dependency_management_does_not_create_library_edge );
65986693 RUN_TEST (cross_repo_maven_commented_dependency_does_not_create_library_edge );
65996694 RUN_TEST (cross_repo_maven_plugin_dependency_does_not_create_library_edge );
66006695 RUN_TEST (cross_repo_maven_cleanup_preserves_unrelated_nodes );
6696+ RUN_TEST (cross_repo_maven_provider_rerun_preserves_incoming_used_by );
66016697 RUN_TEST (cross_repo_maven_removed_dependency_clears_provider_used_by );
66026698 RUN_TEST (cross_repo_maven_long_coordinates_do_not_collide );
66036699 RUN_TEST (cross_repo_maven_fixture_restores_cache_dir );
0 commit comments