annotate mrjunejune/test/conversation_store_test.c @ 273:e02e2036ef84 default tip

add Layer 2 JRPG component system Add reusable content and window modals, an isolated component sandbox, shared cyberpunk scroll areas, production-safe cache freshness, and server-rendered JRPG panel state. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Sat, 08 Aug 2026 02:08:08 -0700
parents 04fee26ecce0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
1 #include "mrjunejune/conversation_store.h"
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
2 #include "deita/deita.h"
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
3
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
4 #include <assert.h>
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
5 #include <stdio.h>
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
6 #include <string.h>
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
7 #include <unistd.h>
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
8
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
9 /* Helper to create and fill a temp DB file path */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
10 static void make_temp_db(char *out, size_t cap)
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
11 {
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
12 snprintf(out, cap, "/tmp/mrjunejune-store-test-XXXXXX");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
13 int fd = mkstemp(out);
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
14 assert(fd >= 0);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
15 close(fd);
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
16 }
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
17
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
18 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
19 /* Original (legacy-API) tests */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
20 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
21
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
22 static void test_legacy_api(const char *database_path)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
23 {
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
24 Conversation_Store *p_store = Conversation_Store_Create(database_path);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
25 assert(p_store);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
26
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
27 char conversation_id[37];
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
28 assert(Conversation_Store_Create_Conversation(
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
29 p_store, "First quest", conversation_id) == CONVERSATION_STORE_OK);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
30 assert(strlen(conversation_id) == 36);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
31
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
32 Dowa_Arena *p_arena = Dowa_Arena_Create(16 * 1024);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
33 Conversation_Record record;
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
34 assert(Conversation_Store_Get(
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
35 p_store, conversation_id, &record, p_arena) == CONVERSATION_STORE_OK);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
36 assert(strcmp(record.id, conversation_id) == 0);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
37 assert(strcmp(record.title, "First quest") == 0);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
38 assert(Dowa_Array_Length(record.turns) == 0);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
39 Dowa_Arena_Free(p_arena);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
40
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
41 assert(Conversation_Store_Update_Title(
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
42 p_store, conversation_id, "Renamed quest") == CONVERSATION_STORE_OK);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
43 assert(Conversation_Store_Begin_Turn(
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
44 p_store, conversation_id, "request-1", "Hello Epi")
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
45 == CONVERSATION_STORE_OK);
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
46 assert(Conversation_Store_Begin_Turn(
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
47 p_store, conversation_id, "request-2", "Overlapping")
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
48 == CONVERSATION_STORE_CONFLICT);
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
49 assert(Conversation_Store_Complete_Turn(
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
50 p_store, conversation_id, "request-1", "Hello traveler", 12, 4)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
51 == CONVERSATION_STORE_OK);
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
52
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
53 assert(Conversation_Store_Begin_Turn(
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
54 p_store, conversation_id, "request-2", "Try again")
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
55 == CONVERSATION_STORE_OK);
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
56 assert(Conversation_Store_Fail_Turn(
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
57 p_store, conversation_id, "request-2", "cancelled", TRUE)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
58 == CONVERSATION_STORE_OK);
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
59
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
60 p_arena = Dowa_Arena_Create(32 * 1024);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
61 assert(Conversation_Store_Get(
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
62 p_store, conversation_id, &record, p_arena) == CONVERSATION_STORE_OK);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
63 assert(strcmp(record.title, "Renamed quest") == 0);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
64 assert(Dowa_Array_Length(record.turns) == 4);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
65 assert(strcmp(record.turns[0].role, "user") == 0);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
66 assert(strcmp(record.turns[0].content, "Hello Epi") == 0);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
67 assert(strcmp(record.turns[1].role, "assistant") == 0);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
68 assert(strcmp(record.turns[1].content, "Hello traveler") == 0);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
69 assert(record.turns[1].input_tokens == 12);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
70 assert(record.turns[1].output_tokens == 4);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
71 assert(strcmp(record.turns[3].status, "aborted") == 0);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
72 Dowa_Arena_Free(p_arena);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
73
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
74 assert(Conversation_Store_Begin_Turn(
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
75 p_store, conversation_id, "request-3", "Interrupted")
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
76 == CONVERSATION_STORE_OK);
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
77 Conversation_Store_Destroy(p_store);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
78 p_store = Conversation_Store_Create(database_path);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
79 assert(p_store);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
80 assert(Conversation_Store_Begin_Turn(
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
81 p_store, conversation_id, "request-4", "Recovered")
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
82 == CONVERSATION_STORE_OK);
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
83 assert(Conversation_Store_Complete_Turn(
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
84 p_store, conversation_id, "request-4", "Recovered answer", 1, 1)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
85 == CONVERSATION_STORE_OK);
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
86
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
87 p_arena = Dowa_Arena_Create(32 * 1024);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
88 assert(Conversation_Store_Get(
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
89 p_store, conversation_id, &record, p_arena) == CONVERSATION_STORE_OK);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
90 assert(Dowa_Array_Length(record.turns) == 8);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
91 assert(strcmp(record.turns[5].status, "failed") == 0);
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
92 assert(strcmp(record.turns[5].error_message,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
93 "Interrupted by server restart") == 0);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
94 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
95
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
96 assert(Conversation_Store_Delete(p_store, conversation_id)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
97 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
98 p_arena = Dowa_Arena_Create(4096);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
99 assert(Conversation_Store_Get(p_store, conversation_id, &record, p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
100 == CONVERSATION_STORE_NOT_FOUND);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
101 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
102
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
103 Conversation_Store_Destroy(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
104 printf(" legacy API tests PASS\n");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
105 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
106
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
107 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
108 /* Migration test: create a DB with old schema (no owner cols), then */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
109 /* re-open and verify migration ran, all rows preserved as legacy. */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
110 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
111
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
112 static void test_migration_from_old_schema(void)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
113 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
114 char db_path[64];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
115 make_temp_db(db_path, sizeof(db_path));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
116
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
117 /* Simulate an old-schema DB by inserting a row directly */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
118 Conversation_Store *p_store = Conversation_Store_Create(db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
119 assert(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
120
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
121 /* Create a conversation using the legacy API (will be owner_kind='legacy') */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
122 char legacy_id[37];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
123 assert(Conversation_Store_Create_Conversation(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
124 p_store, "Old conversation", legacy_id) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
125 Conversation_Store_Destroy(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
126
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
127 /* Re-open: migration should be idempotent */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
128 p_store = Conversation_Store_Create(db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
129 assert(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
130
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
131 /* Legacy row must still be accessible via legacy API */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
132 Dowa_Arena *p_arena = Dowa_Arena_Create(8192);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
133 Conversation_Record record;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
134 assert(Conversation_Store_Get(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
135 p_store, legacy_id, &record, p_arena) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
136 assert(strcmp(record.title, "Old conversation") == 0);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
137 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
138
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
139 /* Owner-aware GET must return NOT_FOUND for a user trying to access a legacy row */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
140 Conversation_Owner user_owner = {CONVERSATION_OWNER_KIND_USER, "user-uuid-abc-0000000000000000000000"};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
141 p_arena = Dowa_Arena_Create(4096);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
142 assert(Conversation_Store_Get_Owned(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
143 p_store, legacy_id, &user_owner, &record, p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
144 == CONVERSATION_STORE_NOT_FOUND);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
145 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
146
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
147 Conversation_Store_Destroy(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
148 unlink(db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
149 printf(" migration from old schema PASS\n");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
150 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
151
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
152 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
153 /* Owned CRUD and isolation tests */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
154 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
155
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
156 static void test_owned_crud_and_isolation(void)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
157 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
158 char db_path[64];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
159 make_temp_db(db_path, sizeof(db_path));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
160 Conversation_Store *p_store = Conversation_Store_Create(db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
161 assert(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
162
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
163 Conversation_Owner user_a = {CONVERSATION_OWNER_KIND_USER, "aaaaaaaa-0000-0000-0000-000000000001"};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
164 Conversation_Owner user_b = {CONVERSATION_OWNER_KIND_USER, "bbbbbbbb-0000-0000-0000-000000000002"};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
165 Conversation_Owner guest_c = {CONVERSATION_OWNER_KIND_GUEST, "cccccccc-0000-0000-0000-000000000003"};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
166
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
167 char id_a[37], id_b[37], id_c[37];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
168 assert(Conversation_Store_Create_Owned(p_store, "A's chat", &user_a, id_a) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
169 assert(Conversation_Store_Create_Owned(p_store, "B's chat", &user_b, id_b) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
170 assert(Conversation_Store_Create_Owned(p_store, "Guest C", &guest_c, id_c) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
171
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
172 /* Owner A can get their own */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
173 Dowa_Arena *p_arena = Dowa_Arena_Create(16 * 1024);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
174 Conversation_Record record;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
175 assert(Conversation_Store_Get_Owned(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
176 p_store, id_a, &user_a, &record, p_arena) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
177 assert(strcmp(record.title, "A's chat") == 0);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
178 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
179
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
180 /* Owner B cannot get A's conversation (returns NOT_FOUND, no leak) */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
181 p_arena = Dowa_Arena_Create(4096);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
182 assert(Conversation_Store_Get_Owned(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
183 p_store, id_a, &user_b, &record, p_arena) == CONVERSATION_STORE_NOT_FOUND);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
184 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
185
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
186 /* Guest C cannot get user A's conversation */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
187 p_arena = Dowa_Arena_Create(4096);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
188 assert(Conversation_Store_Get_Owned(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
189 p_store, id_a, &guest_c, &record, p_arena) == CONVERSATION_STORE_NOT_FOUND);
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
190 Dowa_Arena_Free(p_arena);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
191
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
192 /* A can update their own title */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
193 assert(Conversation_Store_Update_Title_Owned(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
194 p_store, id_a, &user_a, "A's renamed chat") == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
195 /* B cannot update A's title */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
196 assert(Conversation_Store_Update_Title_Owned(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
197 p_store, id_a, &user_b, "B tries to rename") == CONVERSATION_STORE_NOT_FOUND);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
198
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
199 /* A can begin a turn */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
200 assert(Conversation_Store_Begin_Turn_Owned(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
201 p_store, id_a, &user_a, "req-a-1", "Hello from A") == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
202 /* B cannot begin a turn on A's conversation */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
203 assert(Conversation_Store_Begin_Turn_Owned(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
204 p_store, id_a, &user_b, "req-b-1", "B intrudes") == CONVERSATION_STORE_NOT_FOUND);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
205 /* Complete the turn */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
206 assert(Conversation_Store_Complete_Turn(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
207 p_store, id_a, "req-a-1", "Response for A", 5, 2) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
208
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
209 /* A can delete their own */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
210 assert(Conversation_Store_Delete_Owned(p_store, id_a, &user_a) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
211 /* B cannot delete A's (now gone) conversation */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
212 assert(Conversation_Store_Delete_Owned(p_store, id_a, &user_b) == CONVERSATION_STORE_NOT_FOUND);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
213
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
214 /* Legacy creation is rejected */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
215 Conversation_Owner bad_legacy = {CONVERSATION_OWNER_KIND_LEGACY, ""};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
216 char throwaway[37];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
217 assert(Conversation_Store_Create_Owned(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
218 p_store, "Bad", &bad_legacy, throwaway) == CONVERSATION_STORE_ERROR);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
219
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
220 Conversation_Store_Destroy(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
221 unlink(db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
222 printf(" owned CRUD and isolation PASS\n");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
223 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
224
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
225 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
226 /* Paginated listing and cursor tests */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
227 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
228
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
229 static void test_list_and_cursor(void)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
230 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
231 char db_path[64];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
232 make_temp_db(db_path, sizeof(db_path));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
233 Conversation_Store *p_store = Conversation_Store_Create(db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
234 assert(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
235
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
236 Conversation_Owner owner = {CONVERSATION_OWNER_KIND_USER, "11111111-0000-0000-0000-000000000001"};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
237 Conversation_Owner other = {CONVERSATION_OWNER_KIND_USER, "22222222-0000-0000-0000-000000000002"};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
238
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
239 /* Create 5 conversations for owner, 1 for other */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
240 char ids[5][37];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
241 for (int i = 0; i < 5; i++)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
242 assert(Conversation_Store_Create_Owned(p_store, "Chat", &owner, ids[i]) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
243 char other_id[37];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
244 assert(Conversation_Store_Create_Owned(p_store, "Other chat", &other, other_id) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
245
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
246 /* List without cursor, limit 3 */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
247 Dowa_Arena *p_arena = Dowa_Arena_Create(32 * 1024);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
248 Conversation_Summary *summaries = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
249 int32 count = 0;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
250 assert(Conversation_Store_List(p_store, &owner, 0, NULL, 3, &summaries, &count, p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
251 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
252 assert(count == 3);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
253 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
254
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
255 /* List all 5 with limit 10 */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
256 p_arena = Dowa_Arena_Create(32 * 1024);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
257 assert(Conversation_Store_List(p_store, &owner, 0, NULL, 10, &summaries, &count, p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
258 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
259 assert(count == 5);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
260
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
261 /* Use cursor from end of first page */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
262 Conversation_Summary *last_first_page = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
263 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
264 p_arena = Dowa_Arena_Create(32 * 1024);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
265 assert(Conversation_Store_List(p_store, &owner, 0, NULL, 3, &summaries, &count, p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
266 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
267 assert(count == 3);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
268 last_first_page = &summaries[2];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
269 int64 cur_ts = last_first_page->updated_at;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
270 char cur_id[37];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
271 strncpy(cur_id, last_first_page->id, sizeof(cur_id) - 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
272 cur_id[36] = '\0';
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
273 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
274
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
275 p_arena = Dowa_Arena_Create(32 * 1024);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
276 assert(Conversation_Store_List(p_store, &owner, cur_ts, cur_id, 10, &summaries, &count, p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
277 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
278 assert(count == 2);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
279 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
280
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
281 /* Other owner's conversation is NOT in owner's list */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
282 p_arena = Dowa_Arena_Create(32 * 1024);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
283 assert(Conversation_Store_List(p_store, &other, 0, NULL, 10, &summaries, &count, p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
284 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
285 assert(count == 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
286 assert(strcmp(summaries[0].id, other_id) == 0);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
287 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
288
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
289 /* Legacy owner returns empty list */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
290 Conversation_Owner legacy_owner = {CONVERSATION_OWNER_KIND_LEGACY, ""};
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
291 p_arena = Dowa_Arena_Create(4096);
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
292 assert(Conversation_Store_List(p_store, &legacy_owner, 0, NULL, 10, &summaries, &count, p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
293 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
294 assert(count == 0);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
295 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
296
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
297 /* Limit is capped at 50 */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
298 p_arena = Dowa_Arena_Create(32 * 1024);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
299 assert(Conversation_Store_List(p_store, &owner, 0, NULL, 200, &summaries, &count, p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
300 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
301 assert(count == 5); /* only 5 exist, so < 50 */
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
302 Dowa_Arena_Free(p_arena);
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
303
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
304 Conversation_Store_Destroy(p_store);
264
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
305 unlink(db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
306 printf(" list and cursor pagination PASS\n");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
307 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
308
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
309 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
310 /* Legacy claim tests */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
311 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
312
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
313 static void test_claim_legacy(void)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
314 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
315 char db_path[64];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
316 make_temp_db(db_path, sizeof(db_path));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
317 Conversation_Store *p_store = Conversation_Store_Create(db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
318 assert(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
319
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
320 /* Create a legacy row via the legacy API */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
321 char legacy_id[37];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
322 assert(Conversation_Store_Create_Conversation(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
323 p_store, "Unclaimed adventure", legacy_id) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
324
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
325 /* Claim as user */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
326 const char *user_id = "33333333-0000-0000-0000-000000000099";
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
327 assert(Conversation_Store_Claim_Legacy(p_store, legacy_id, user_id)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
328 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
329
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
330 /* Now accessible via owned API */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
331 Dowa_Arena *p_arena = Dowa_Arena_Create(8192);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
332 Conversation_Record record;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
333 Conversation_Owner claimed_owner = {CONVERSATION_OWNER_KIND_USER, {0}};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
334 strncpy(claimed_owner.id, user_id, sizeof(claimed_owner.id) - 1);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
335 assert(Conversation_Store_Get_Owned(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
336 p_store, legacy_id, &claimed_owner, &record, p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
337 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
338 assert(strcmp(record.title, "Unclaimed adventure") == 0);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
339 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
340
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
341 /* Cannot claim again (CONFLICT: already user-owned) */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
342 assert(Conversation_Store_Claim_Legacy(p_store, legacy_id, user_id)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
343 == CONVERSATION_STORE_CONFLICT);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
344
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
345 /* Non-existent conversation returns NOT_FOUND */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
346 assert(Conversation_Store_Claim_Legacy(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
347 p_store, "00000000-0000-0000-0000-000000000000", user_id)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
348 == CONVERSATION_STORE_NOT_FOUND);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
349
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
350 Conversation_Store_Destroy(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
351 unlink(db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
352 printf(" legacy claim PASS\n");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
353 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
354
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
355 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
356 /* Atomic/idempotent guest-to-user transfer test */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
357 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
358
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
359 static void test_guest_transfer(void)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
360 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
361 char db_path[64];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
362 make_temp_db(db_path, sizeof(db_path));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
363 Conversation_Store *p_store = Conversation_Store_Create(db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
364 assert(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
365
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
366 const char *guest_id = "44444444-0000-0000-0000-000000000001";
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
367 const char *user_id = "55555555-0000-0000-0000-000000000001";
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
368 Conversation_Owner guest_owner = {CONVERSATION_OWNER_KIND_GUEST, {0}};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
369 Conversation_Owner user_owner = {CONVERSATION_OWNER_KIND_USER, {0}};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
370 strncpy(guest_owner.id, guest_id, 36);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
371 strncpy(user_owner.id, user_id, 36);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
372
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
373 /* Create 3 guest conversations */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
374 char gid1[37], gid2[37], gid3[37];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
375 assert(Conversation_Store_Create_Owned(p_store, "Guest chat 1", &guest_owner, gid1) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
376 assert(Conversation_Store_Create_Owned(p_store, "Guest chat 2", &guest_owner, gid2) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
377 assert(Conversation_Store_Create_Owned(p_store, "Guest chat 3", &guest_owner, gid3) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
378
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
379 /* Transfer guest to user */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
380 assert(Conversation_Store_Transfer_Guest_To_User(p_store, guest_id, user_id)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
381 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
382
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
383 /* All three now belong to user */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
384 Dowa_Arena *p_arena = Dowa_Arena_Create(8192);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
385 Conversation_Record record;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
386 assert(Conversation_Store_Get_Owned(p_store, gid1, &user_owner, &record, p_arena) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
387 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
388 p_arena = Dowa_Arena_Create(8192);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
389 assert(Conversation_Store_Get_Owned(p_store, gid2, &user_owner, &record, p_arena) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
390 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
391 p_arena = Dowa_Arena_Create(8192);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
392 assert(Conversation_Store_Get_Owned(p_store, gid3, &user_owner, &record, p_arena) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
393 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
394
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
395 /* Guest can no longer see them */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
396 p_arena = Dowa_Arena_Create(4096);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
397 assert(Conversation_Store_Get_Owned(p_store, gid1, &guest_owner, &record, p_arena) == CONVERSATION_STORE_NOT_FOUND);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
398 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
399
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
400 /* Idempotent: running again succeeds (no-op) */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
401 assert(Conversation_Store_Transfer_Guest_To_User(p_store, guest_id, user_id)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
402 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
403
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
404 Conversation_Store_Destroy(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
405 unlink(db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
406 printf(" atomic/idempotent guest transfer PASS\n");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
407 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
408
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
409 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
410 /* Transfer-then-stale-guest-create: race-safety test */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
411 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
412
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
413 static void test_transfer_stale_guest_create(void)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
414 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
415 char db_path[64];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
416 make_temp_db(db_path, sizeof(db_path));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
417 Conversation_Store *p_store = Conversation_Store_Create(db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
418 assert(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
419
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
420 const char *guest_id = "66666666-0000-0000-0000-000000000001";
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
421 const char *user_id = "77777777-0000-0000-0000-000000000001";
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
422 Conversation_Owner guest_owner = {CONVERSATION_OWNER_KIND_GUEST, {0}};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
423 Conversation_Owner user_owner = {CONVERSATION_OWNER_KIND_USER, {0}};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
424 strncpy(guest_owner.id, guest_id, 36);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
425 strncpy(user_owner.id, user_id, 36);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
426
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
427 /* Create one conversation as guest before transfer */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
428 char pre_transfer_id[37];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
429 assert(Conversation_Store_Create_Owned(p_store, "Pre-transfer", &guest_owner, pre_transfer_id)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
430 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
431
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
432 /* Transfer guest to user (records mapping) */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
433 assert(Conversation_Store_Transfer_Guest_To_User(p_store, guest_id, user_id)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
434 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
435
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
436 /* Stale guest create: arrives after transfer (simulates race) */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
437 char stale_id[37];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
438 assert(Conversation_Store_Create_Owned(p_store, "Stale guest create", &guest_owner, stale_id)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
439 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
440
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
441 /* The stale create must be owned by the mapped user, not the guest */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
442 Dowa_Arena *p_arena = Dowa_Arena_Create(8192);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
443 Conversation_Record record;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
444 /* User can see the stale-created conversation */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
445 assert(Conversation_Store_Get_Owned(p_store, stale_id, &user_owner, &record, p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
446 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
447 assert(strcmp(record.title, "Stale guest create") == 0);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
448 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
449
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
450 /* Guest can no longer see the stale-created conversation */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
451 p_arena = Dowa_Arena_Create(4096);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
452 assert(Conversation_Store_Get_Owned(p_store, stale_id, &guest_owner, &record, p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
453 == CONVERSATION_STORE_NOT_FOUND);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
454 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
455
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
456 /* Pre-transfer conversation also belongs to user */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
457 p_arena = Dowa_Arena_Create(8192);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
458 assert(Conversation_Store_Get_Owned(p_store, pre_transfer_id, &user_owner, &record, p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
459 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
460 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
461
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
462 Conversation_Store_Destroy(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
463 unlink(db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
464 printf(" transfer then stale guest create → owned by user PASS\n");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
465 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
466
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
467 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
468 /* Conflicting transfer mapping test */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
469 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
470
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
471 static void test_transfer_conflict(void)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
472 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
473 char db_path[64];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
474 make_temp_db(db_path, sizeof(db_path));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
475 Conversation_Store *p_store = Conversation_Store_Create(db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
476 assert(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
477
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
478 const char *guest_id = "88888888-0000-0000-0000-000000000001";
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
479 const char *user_a_id = "aaaaaaaa-1111-0000-0000-000000000001";
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
480 const char *user_b_id = "bbbbbbbb-2222-0000-0000-000000000001";
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
481
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
482 /* First transfer: guest → user A */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
483 assert(Conversation_Store_Transfer_Guest_To_User(p_store, guest_id, user_a_id)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
484 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
485
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
486 /* Idempotent: same mapping again must succeed */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
487 assert(Conversation_Store_Transfer_Guest_To_User(p_store, guest_id, user_a_id)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
488 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
489
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
490 /* Conflicting transfer: guest → user B must fail with CONFLICT */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
491 assert(Conversation_Store_Transfer_Guest_To_User(p_store, guest_id, user_b_id)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
492 == CONVERSATION_STORE_CONFLICT);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
493
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
494 Conversation_Store_Destroy(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
495 unlink(db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
496 printf(" conflicting transfer mapping returns CONFLICT PASS\n");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
497 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
498
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
499 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
500 /* Index DESC migration test */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
501 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
502
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
503 static void test_index_desc_migration(void)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
504 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
505 char db_path[64];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
506 make_temp_db(db_path, sizeof(db_path));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
507
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
508 /* Open twice to verify migration is idempotent */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
509 Conversation_Store *p_store = Conversation_Store_Create(db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
510 assert(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
511 Conversation_Store_Destroy(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
512
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
513 /* Re-open: migrations must be idempotent */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
514 p_store = Conversation_Store_Create(db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
515 assert(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
516
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
517 /* Verify the listing still works (index is usable) after migration 3 */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
518 Conversation_Owner owner = {CONVERSATION_OWNER_KIND_USER, "cccccccc-3333-0000-0000-000000000001"};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
519 char id1[37], id2[37];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
520 assert(Conversation_Store_Create_Owned(p_store, "Alpha", &owner, id1) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
521 assert(Conversation_Store_Create_Owned(p_store, "Beta", &owner, id2) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
522
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
523 Dowa_Arena *p_arena = Dowa_Arena_Create(32 * 1024);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
524 Conversation_Summary *summaries = NULL;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
525 int32 count = 0;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
526 assert(Conversation_Store_List(p_store, &owner, 0, NULL, 10, &summaries, &count, p_arena)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
527 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
528 /* Both conversations present */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
529 assert(count == 2);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
530 /* Ordering must be stable: both IDs must appear */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
531 assert(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
532 (strcmp(summaries[0].id, id1) == 0 || strcmp(summaries[0].id, id2) == 0) &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
533 (strcmp(summaries[1].id, id1) == 0 || strcmp(summaries[1].id, id2) == 0) &&
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
534 strcmp(summaries[0].id, summaries[1].id) != 0);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
535 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
536
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
537 Conversation_Store_Destroy(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
538 unlink(db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
539 printf(" index DESC migration applied and listing order correct PASS\n");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
540 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
541
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
542 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
543 /* Transfer_Atomic: conversations + quota cleared in one transaction */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
544 /* ------------------------------------------------------------------ */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
545
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
546 /*
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
547 * We exercise Transfer_Guest_To_User_Atomic by inserting synthetic quota
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
548 * rows directly via a secondary connection (since the conversation store
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
549 * and auth store share the same SQLite file) and verifying that after the
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
550 * atomic transfer the reservation rows are gone and output_tokens_reserved
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
551 * is decremented.
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
552 */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
553 static void test_transfer_atomic_quota_cleanup(void)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
554 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
555 char db_path[64];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
556 make_temp_db(db_path, sizeof(db_path));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
557
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
558 Conversation_Store *p_store = Conversation_Store_Create(db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
559 assert(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
560
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
561 /* Seed guest identity, usage, and reservation rows via a raw connection
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
562 * to simulate what the auth store would have written (in production both
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
563 * stores share the same SQLite file). */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
564 Deita_Connection *p_conn =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
565 Deita_Connection_Create(DEITA_DATABASE_TYPE_SQLITE3, db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
566 assert(p_conn);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
567 Deita_Query_Execute_Update(p_conn,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
568 "PRAGMA foreign_keys = OFF;"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
569 "PRAGMA journal_mode = WAL;");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
570
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
571 /* Create auth tables that share the same file in production. */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
572 Deita_Query_Execute_Update(p_conn,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
573 "CREATE TABLE IF NOT EXISTS guest_identities ("
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
574 " id TEXT PRIMARY KEY,"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
575 " ip_binding_digest TEXT NOT NULL,"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
576 " created_at INTEGER NOT NULL DEFAULT (strftime('%s','now')),"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
577 " last_seen_at INTEGER NOT NULL DEFAULT (strftime('%s','now')),"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
578 " expires_at INTEGER NOT NULL"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
579 ");");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
580 Deita_Query_Execute_Update(p_conn,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
581 "CREATE TABLE IF NOT EXISTS guest_usage ("
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
582 " guest_id TEXT NOT NULL,"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
583 " window_start INTEGER NOT NULL,"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
584 " count INTEGER NOT NULL DEFAULT 0,"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
585 " turns_used INTEGER NOT NULL DEFAULT 0,"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
586 " output_tokens_used INTEGER NOT NULL DEFAULT 0,"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
587 " output_tokens_reserved INTEGER NOT NULL DEFAULT 0,"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
588 " PRIMARY KEY (guest_id, window_start)"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
589 ");");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
590 Deita_Query_Execute_Update(p_conn,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
591 "CREATE TABLE IF NOT EXISTS guest_usage_reservations ("
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
592 " request_id TEXT PRIMARY KEY,"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
593 " guest_id TEXT NOT NULL,"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
594 " window_start INTEGER NOT NULL,"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
595 " output_tokens_reserved INTEGER NOT NULL DEFAULT 0,"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
596 " reserved_at INTEGER NOT NULL DEFAULT (strftime('%s','now')),"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
597 " expires_at INTEGER NOT NULL"
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
598 ");");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
599
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
600 const char *gid = "aaaabbbb-cccc-4000-8000-111111111111";
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
601 const char *uid = "ddddeeee-ffff-4000-8000-222222222222";
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
602 const char *rid1 = "rrrr1111-0000-4000-8000-000000000001";
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
603 const char *rid2 = "rrrr2222-0000-4000-8000-000000000002";
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
604
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
605 /* guest_identities */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
606 const char *gid_p[] = {gid};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
607 Deita_Query_Execute_Update_Prepared(p_conn,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
608 "INSERT OR IGNORE INTO guest_identities "
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
609 "(id, ip_binding_digest, expires_at) VALUES (?, 'x', 9999999999)",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
610 1, gid_p);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
611
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
612 /* guest_usage: 2 turns used, 300 tokens reserved */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
613 const char *gu_p[] = {gid};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
614 Deita_Query_Execute_Update_Prepared(p_conn,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
615 "INSERT OR REPLACE INTO guest_usage "
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
616 "(guest_id, window_start, count, turns_used, output_tokens_used, "
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
617 " output_tokens_reserved) VALUES (?, 1700524800, 2, 2, 0, 300)",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
618 1, gu_p);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
619
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
620 /* Two reservation rows (100 + 200 = 300 total) */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
621 const char *r1_p[] = {rid1, gid};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
622 Deita_Query_Execute_Update_Prepared(p_conn,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
623 "INSERT OR REPLACE INTO guest_usage_reservations "
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
624 "(request_id, guest_id, window_start, output_tokens_reserved, expires_at) "
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
625 "VALUES (?, ?, 1700524800, 100, 9999999999)",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
626 2, r1_p);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
627 const char *r2_p[] = {rid2, gid};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
628 Deita_Query_Execute_Update_Prepared(p_conn,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
629 "INSERT OR REPLACE INTO guest_usage_reservations "
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
630 "(request_id, guest_id, window_start, output_tokens_reserved, expires_at) "
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
631 "VALUES (?, ?, 1700524800, 200, 9999999999)",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
632 2, r2_p);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
633 Deita_Connection_Close(p_conn);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
634
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
635 /* Create one guest conversation */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
636 Conversation_Owner g_owner = {CONVERSATION_OWNER_KIND_GUEST, ""};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
637 strncpy(g_owner.id, gid, 36);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
638 char conv_id[37];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
639 assert(Conversation_Store_Create_Owned(p_store, "G conv", &g_owner, conv_id)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
640 == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
641
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
642 /* Atomic transfer */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
643 assert(Conversation_Store_Transfer_Guest_To_User_Atomic(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
644 p_store, gid, uid) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
645
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
646 /* Verify: conversation now belongs to user */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
647 Conversation_Owner u_owner = {CONVERSATION_OWNER_KIND_USER, ""};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
648 strncpy(u_owner.id, uid, 36);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
649 Dowa_Arena *p_arena = Dowa_Arena_Create(8 * 1024);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
650 Conversation_Record rec;
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
651 assert(Conversation_Store_Get_Owned(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
652 p_store, conv_id, &u_owner, &rec, p_arena) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
653 Dowa_Arena_Free(p_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
654
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
655 /* Verify: quota reservation rows deleted and output_tokens_reserved = 0 */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
656 Dowa_Arena *chk_arena = Dowa_Arena_Create(4096);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
657 Deita_Connection *p_chk =
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
658 Deita_Connection_Create(DEITA_DATABASE_TYPE_SQLITE3, db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
659 assert(p_chk);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
660 Deita_Query_Execute_Update(p_chk, "PRAGMA journal_mode = WAL;");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
661
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
662 const char *chk_gid[] = {gid};
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
663 Deita_Result_Set *rs = Deita_Query_Execute_Prepared(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
664 p_chk,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
665 "SELECT output_tokens_reserved FROM guest_usage WHERE guest_id = ?",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
666 1, chk_gid, chk_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
667 assert(rs && Deita_Result_Set_Next(rs));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
668 assert(Deita_Result_Set_Get_Integer(rs, 0) == 0);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
669 Deita_Result_Set_Free(rs);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
670
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
671 rs = Deita_Query_Execute_Prepared(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
672 p_chk,
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
673 "SELECT COUNT(*) FROM guest_usage_reservations WHERE guest_id = ?",
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
674 1, chk_gid, chk_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
675 assert(rs && Deita_Result_Set_Next(rs));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
676 assert(Deita_Result_Set_Get_Integer(rs, 0) == 0);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
677 Deita_Result_Set_Free(rs);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
678
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
679 Deita_Connection_Close(p_chk);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
680 Dowa_Arena_Free(chk_arena);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
681
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
682 /* Idempotent: re-run same transfer is a no-op */
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
683 assert(Conversation_Store_Transfer_Guest_To_User_Atomic(
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
684 p_store, gid, uid) == CONVERSATION_STORE_OK);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
685
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
686 Conversation_Store_Destroy(p_store);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
687 unlink(db_path);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
688 printf(" transfer_atomic_quota_cleanup PASS\n");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
689 }
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
690
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
691 int main(void)
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
692 {
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
693 printf("conversation_store tests:\n");
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
694
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
695 char legacy_db[64];
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
696 make_temp_db(legacy_db, sizeof(legacy_db));
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
697 test_legacy_api(legacy_db);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
698 unlink(legacy_db);
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
699
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
700 test_migration_from_old_schema();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
701 test_owned_crud_and_isolation();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
702 test_list_and_cursor();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
703 test_claim_legacy();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
704 test_guest_transfer();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
705 test_transfer_stale_guest_create();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
706 test_transfer_conflict();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
707 test_index_desc_migration();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
708 test_transfer_atomic_quota_cleanup();
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
709
04fee26ecce0 add authenticated JRPG conversation platform
MrJuneJune <me@mrjunejune.com>
parents: 260
diff changeset
710 printf("All conversation store tests passed\n");
260
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
711 return 0;
1f9877b637e9 Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
diff changeset
712 }