| 2093 | } cypher_edge_thread_ctx_t; |
| 2094 | |
| 2095 | static void *cypher_edge_props_concurrently(void *opaque) { |
| 2096 | cypher_edge_thread_ctx_t *ctx = opaque; |
| 2097 | cbm_store_t *store = setup_cypher_http_store(); |
| 2098 | if (!store) { |
| 2099 | return NULL; |
| 2100 | } |
| 2101 | |
| 2102 | /* Keep projection busy after the store scan has completed. A single-edge |
| 2103 | * query can be incidentally ordered by SQLite's internal mutexes, masking |
| 2104 | * the independent Cypher scratch-buffer race from TSan. */ |
| 2105 | cbm_node_t source = {.project = "test", |
| 2106 | .label = "Function", |
| 2107 | .name = "HandleOrder", |
| 2108 | .qualified_name = "test.main.HandleOrder", |
| 2109 | .file_path = "main.go", |
| 2110 | .start_line = 10, |
| 2111 | .end_line = 30}; |
| 2112 | int64_t source_id = cbm_store_upsert_node(store, &source); |
| 2113 | for (int i = 0; i < 256; i++) { |
| 2114 | char name[64]; |
| 2115 | char qualified_name[96]; |
| 2116 | snprintf(name, sizeof(name), "ConcurrentTarget%d", i); |
| 2117 | snprintf(qualified_name, sizeof(qualified_name), "test.concurrent.%s", name); |
| 2118 | cbm_node_t target = {.project = "test", |
| 2119 | .label = "Function", |
| 2120 | .name = name, |
| 2121 | .qualified_name = qualified_name, |
| 2122 | .file_path = "concurrent.go"}; |
| 2123 | int64_t target_id = cbm_store_upsert_node(store, &target); |
| 2124 | cbm_edge_t edge = { |
| 2125 | .project = "test", |
| 2126 | .source_id = source_id, |
| 2127 | .target_id = target_id, |
| 2128 | .type = "HTTP_CALLS", |
| 2129 | .properties_json = |
| 2130 | "{\"url_path\":\"/api/orders\",\"confidence\":0.85,\"method\":\"POST\"}"}; |
| 2131 | if (source_id < 0 || target_id < 0 || cbm_store_insert_edge(store, &edge) < 0) { |
| 2132 | cbm_store_close(store); |
| 2133 | return NULL; |
| 2134 | } |
| 2135 | } |
| 2136 | |
| 2137 | atomic_fetch_add_explicit(ctx->ready, 1, memory_order_release); |
| 2138 | while (atomic_load_explicit(ctx->start, memory_order_acquire) == 0) { |
| 2139 | cbm_usleep(1000); |
| 2140 | } |
| 2141 | ctx->succeeded = true; |
| 2142 | for (int i = 0; i < 128; i++) { |
| 2143 | cbm_cypher_result_t result = {0}; |
| 2144 | int rc = cbm_cypher_execute(store, |
| 2145 | "MATCH (a:Function)-[r:HTTP_CALLS]->(b:Function) " |
| 2146 | "RETURN r.url_path, r.confidence, r.method", |
| 2147 | "test", 0, &result); |
| 2148 | if (rc != 0 || result.row_count != 257 || |
| 2149 | strcmp(cypher_get_col(&result, 0, "r.url_path"), "/api/orders") != 0 || |
| 2150 | strcmp(cypher_get_col(&result, 0, "r.confidence"), "0.85") != 0 || |
| 2151 | strcmp(cypher_get_col(&result, 0, "r.method"), "POST") != 0) { |
| 2152 | ctx->succeeded = false; |
nothing calls this directly
no test coverage detected