| 2219 | } cypher_edge_thread_ctx_t; |
| 2220 | |
| 2221 | static void *cypher_edge_props_concurrently(void *opaque) { |
| 2222 | cypher_edge_thread_ctx_t *ctx = opaque; |
| 2223 | cbm_store_t *store = setup_cypher_http_store(); |
| 2224 | if (!store) { |
| 2225 | return NULL; |
| 2226 | } |
| 2227 | |
| 2228 | /* Keep projection busy after the store scan has completed. A single-edge |
| 2229 | * query can be incidentally ordered by SQLite's internal mutexes, masking |
| 2230 | * the independent Cypher scratch-buffer race from TSan. */ |
| 2231 | cbm_node_t source = {.project = "test", |
| 2232 | .label = "Function", |
| 2233 | .name = "HandleOrder", |
| 2234 | .qualified_name = "test.main.HandleOrder", |
| 2235 | .file_path = "main.go", |
| 2236 | .start_line = 10, |
| 2237 | .end_line = 30}; |
| 2238 | int64_t source_id = cbm_store_upsert_node(store, &source); |
| 2239 | for (int i = 0; i < 256; i++) { |
| 2240 | char name[64]; |
| 2241 | char qualified_name[96]; |
| 2242 | snprintf(name, sizeof(name), "ConcurrentTarget%d", i); |
| 2243 | snprintf(qualified_name, sizeof(qualified_name), "test.concurrent.%s", name); |
| 2244 | cbm_node_t target = {.project = "test", |
| 2245 | .label = "Function", |
| 2246 | .name = name, |
| 2247 | .qualified_name = qualified_name, |
| 2248 | .file_path = "concurrent.go"}; |
| 2249 | int64_t target_id = cbm_store_upsert_node(store, &target); |
| 2250 | cbm_edge_t edge = { |
| 2251 | .project = "test", |
| 2252 | .source_id = source_id, |
| 2253 | .target_id = target_id, |
| 2254 | .type = "HTTP_CALLS", |
| 2255 | .properties_json = |
| 2256 | "{\"url_path\":\"/api/orders\",\"confidence\":0.85,\"method\":\"POST\"}"}; |
| 2257 | if (source_id < 0 || target_id < 0 || cbm_store_insert_edge(store, &edge) < 0) { |
| 2258 | cbm_store_close(store); |
| 2259 | return NULL; |
| 2260 | } |
| 2261 | } |
| 2262 | |
| 2263 | atomic_fetch_add_explicit(ctx->ready, 1, memory_order_release); |
| 2264 | while (atomic_load_explicit(ctx->start, memory_order_acquire) == 0) { |
| 2265 | cbm_usleep(1000); |
| 2266 | } |
| 2267 | ctx->succeeded = true; |
| 2268 | for (int i = 0; i < 128; i++) { |
| 2269 | cbm_cypher_result_t result = {0}; |
| 2270 | int rc = cbm_cypher_execute(store, |
| 2271 | "MATCH (a:Function)-[r:HTTP_CALLS]->(b:Function) " |
| 2272 | "RETURN r.url_path, r.confidence, r.method", |
| 2273 | "test", 0, &result); |
| 2274 | if (rc != 0 || result.row_count != 257 || |
| 2275 | strcmp(cypher_get_col(&result, 0, "r.url_path"), "/api/orders") != 0 || |
| 2276 | strcmp(cypher_get_col(&result, 0, "r.confidence"), "0.85") != 0 || |
| 2277 | strcmp(cypher_get_col(&result, 0, "r.method"), "POST") != 0) { |
| 2278 | ctx->succeeded = false; |
nothing calls this directly
no test coverage detected