| 1945 | } cypher_edge_thread_ctx_t; |
| 1946 | |
| 1947 | static void *cypher_edge_props_concurrently(void *opaque) { |
| 1948 | cypher_edge_thread_ctx_t *ctx = opaque; |
| 1949 | cbm_store_t *store = setup_cypher_http_store(); |
| 1950 | if (!store) { |
| 1951 | return NULL; |
| 1952 | } |
| 1953 | |
| 1954 | /* Keep projection busy after the store scan has completed. A single-edge |
| 1955 | * query can be incidentally ordered by SQLite's internal mutexes, masking |
| 1956 | * the independent Cypher scratch-buffer race from TSan. */ |
| 1957 | cbm_node_t source = {.project = "test", |
| 1958 | .label = "Function", |
| 1959 | .name = "HandleOrder", |
| 1960 | .qualified_name = "test.main.HandleOrder", |
| 1961 | .file_path = "main.go", |
| 1962 | .start_line = 10, |
| 1963 | .end_line = 30}; |
| 1964 | int64_t source_id = cbm_store_upsert_node(store, &source); |
| 1965 | for (int i = 0; i < 256; i++) { |
| 1966 | char name[64]; |
| 1967 | char qualified_name[96]; |
| 1968 | snprintf(name, sizeof(name), "ConcurrentTarget%d", i); |
| 1969 | snprintf(qualified_name, sizeof(qualified_name), "test.concurrent.%s", name); |
| 1970 | cbm_node_t target = {.project = "test", |
| 1971 | .label = "Function", |
| 1972 | .name = name, |
| 1973 | .qualified_name = qualified_name, |
| 1974 | .file_path = "concurrent.go"}; |
| 1975 | int64_t target_id = cbm_store_upsert_node(store, &target); |
| 1976 | cbm_edge_t edge = { |
| 1977 | .project = "test", |
| 1978 | .source_id = source_id, |
| 1979 | .target_id = target_id, |
| 1980 | .type = "HTTP_CALLS", |
| 1981 | .properties_json = |
| 1982 | "{\"url_path\":\"/api/orders\",\"confidence\":0.85,\"method\":\"POST\"}"}; |
| 1983 | if (source_id < 0 || target_id < 0 || cbm_store_insert_edge(store, &edge) < 0) { |
| 1984 | cbm_store_close(store); |
| 1985 | return NULL; |
| 1986 | } |
| 1987 | } |
| 1988 | |
| 1989 | atomic_fetch_add_explicit(ctx->ready, 1, memory_order_release); |
| 1990 | while (atomic_load_explicit(ctx->start, memory_order_acquire) == 0) { |
| 1991 | cbm_usleep(1000); |
| 1992 | } |
| 1993 | ctx->succeeded = true; |
| 1994 | for (int i = 0; i < 128; i++) { |
| 1995 | cbm_cypher_result_t result = {0}; |
| 1996 | int rc = cbm_cypher_execute(store, |
| 1997 | "MATCH (a:Function)-[r:HTTP_CALLS]->(b:Function) " |
| 1998 | "RETURN r.url_path, r.confidence, r.method", |
| 1999 | "test", 0, &result); |
| 2000 | if (rc != 0 || result.row_count != 257 || |
| 2001 | strcmp(cypher_get_col(&result, 0, "r.url_path"), "/api/orders") != 0 || |
| 2002 | strcmp(cypher_get_col(&result, 0, "r.confidence"), "0.85") != 0 || |
| 2003 | strcmp(cypher_get_col(&result, 0, "r.method"), "POST") != 0) { |
| 2004 | ctx->succeeded = false; |
nothing calls this directly
no test coverage detected