Skip to content

Commit 3128c18

Browse files
committed
test: add llm_chat_vtab test and improve test utilities
Introduces a new test, test_llm_chat_vtab, to verify the llm_chat virtual table functionality and memory usage. Adds the exec_select_rows helper for row-counting and verbose output. Updates test_llm_chat_respond_repeated to use varied prompts and more detailed context usage queries. Removes redundant SQLITE_ENABLE_LOAD_EXTENSION macro definition.
1 parent e492310 commit 3128c18

File tree

1 file changed

+99
-6
lines changed

1 file changed

+99
-6
lines changed

tests/c/unittest.c

Lines changed: 99 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
#ifndef SQLITE_ENABLE_LOAD_EXTENSION
2-
#define SQLITE_ENABLE_LOAD_EXTENSION 1
3-
#endif
41
#include "sqlite3.h"
52

63
#include <stdbool.h>
@@ -69,6 +66,10 @@ static int open_db_and_load(const test_env *env, sqlite3 **out_db) {
6966
return SQLITE_OK;
7067
}
7168

69+
// ---------------------------------------------------------------------
70+
// Helper utilities
71+
// ---------------------------------------------------------------------
72+
7273
typedef struct {
7374
const test_env *env;
7475
} exec_userdata;
@@ -120,6 +121,45 @@ static int exec_expect_ok(const test_env *env, sqlite3 *db, const char *sql) {
120121
return 0;
121122
}
122123

124+
static int exec_select_rows(const test_env *env, sqlite3 *db, const char *sql, int *rows_out) {
125+
if (env->verbose) {
126+
printf("[SQL] %s\n", sql);
127+
}
128+
sqlite3_stmt *stmt = NULL;
129+
int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL);
130+
if (rc != SQLITE_OK) {
131+
fprintf(stderr, "sqlite3_prepare_v2 failed (%d): %s\n", rc, sqlite3_errmsg(db));
132+
if (stmt) sqlite3_finalize(stmt);
133+
return 1;
134+
}
135+
int row_count = 0;
136+
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW) {
137+
row_count++;
138+
if (env->verbose) {
139+
printf("[SQL][ROW] ");
140+
int cols = sqlite3_column_count(stmt);
141+
for (int i = 0; i < cols; ++i) {
142+
const char *name = sqlite3_column_name(stmt, i);
143+
const unsigned char *val = sqlite3_column_text(stmt, i);
144+
printf("%s=%s%s", name ? name : "(null)", val ? (const char *)val : "NULL", (i + 1 < cols) ? ", " : "");
145+
}
146+
printf("\n");
147+
}
148+
}
149+
if (rc != SQLITE_DONE) {
150+
fprintf(stderr, "sqlite3_step failed (%d): %s\n", rc, sqlite3_errmsg(db));
151+
sqlite3_finalize(stmt);
152+
return 1;
153+
}
154+
sqlite3_finalize(stmt);
155+
if (rows_out) *rows_out = row_count;
156+
return 0;
157+
}
158+
159+
// ---------------------------------------------------------------------
160+
// Tests
161+
// ---------------------------------------------------------------------
162+
123163
static int test_issue15_chat_without_context(const test_env *env) {
124164
sqlite3 *db = NULL;
125165
if (open_db_and_load(env, &db) != SQLITE_OK) {
@@ -144,7 +184,7 @@ static int test_llm_chat_respond_repeated(const test_env *env) {
144184
sqlite3_close(db);
145185
return 1;
146186
}
147-
if (exec_expect_ok(env, db, "SELECT llm_context_create('context_size=32000');") != 0) {
187+
if (exec_expect_ok(env, db, "SELECT llm_context_create('context_size=1000');") != 0) {
148188
sqlite3_close(db);
149189
return 1;
150190
}
@@ -154,13 +194,18 @@ static int test_llm_chat_respond_repeated(const test_env *env) {
154194
}
155195

156196
const int iterations = 3;
197+
char *prompts[] = {
198+
"SELECT llm_chat_respond('Hi');",
199+
"SELECT llm_chat_respond('How are you?');",
200+
"SELECT llm_chat_respond('Again');"
201+
};
157202
for (int i = 0; i < iterations; ++i) {
158-
if (exec_expect_ok(env, db, "SELECT llm_chat_respond('Hello world');") != 0) {
203+
if (exec_expect_ok(env, db, prompts[i]) != 0) {
159204
sqlite3_close(db);
160205
return 1;
161206
}
162207

163-
if (exec_expect_ok(env, db, "SELECT llm_context_usage();") != 0) {
208+
if (exec_expect_ok(env, db, "SELECT llm_context_used() AS context_used, llm_context_size() AS context_size, CAST(llm_context_used() AS FLOAT)/CAST(llm_context_size() AS FLOAT) || '%' AS 'context_usage_percentage';") != 0) {
164209
sqlite3_close(db);
165210
return 1;
166211
}
@@ -199,9 +244,57 @@ static int test_llm_chat_respond_repeated(const test_env *env) {
199244
return 0;
200245
}
201246

247+
static int test_llm_chat_vtab(const test_env *env) {
248+
sqlite3 *db = NULL;
249+
if (open_db_and_load(env, &db) != SQLITE_OK) {
250+
return 1;
251+
}
252+
253+
const char *model = env->model_path ? env->model_path : DEFAULT_MODEL_PATH;
254+
char sqlbuf[512];
255+
snprintf(sqlbuf, sizeof(sqlbuf), "SELECT llm_model_load('%s');", model);
256+
if (exec_expect_ok(env, db, sqlbuf) != 0) goto fail;
257+
if (exec_expect_ok(env, db, "SELECT llm_context_create('context_size=1000');") != 0) goto fail;
258+
if (exec_expect_ok(env, db, "SELECT llm_chat_create();") != 0) goto fail;
259+
int rows = 0;
260+
if (exec_select_rows(env, db, "SELECT * FROM llm_chat('Hi');", &rows) != 0) goto fail;
261+
if (rows <= 0) {
262+
fprintf(stderr, "[chat_vtab] expected rows but got %d\n", rows);
263+
goto fail;
264+
}
265+
rows = 0;
266+
if (exec_select_rows(env, db, "SELECT * FROM llm_chat('How are you');", &rows) != 0) goto fail;
267+
if (rows <= 0) {
268+
fprintf(stderr, "[chat_vtab] expected rows but got %d\n", rows);
269+
goto fail;
270+
}
271+
if (exec_expect_ok(env, db, "SELECT llm_chat_free();") != 0) goto fail;
272+
if (exec_expect_ok(env, db, "SELECT llm_context_free();") != 0) goto fail;
273+
if (exec_expect_ok(env, db, "SELECT llm_model_free();") != 0) goto fail;
274+
sqlite3_close(db);
275+
276+
sqlite3_int64 current = 0;
277+
sqlite3_int64 highwater = 0;
278+
if (sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &current, &highwater, 0) != SQLITE_OK) {
279+
fprintf(stderr, "[chat_vtab] sqlite3_status64 failed\n");
280+
return 1;
281+
}
282+
if (current > 0 || highwater <= 0) {
283+
fprintf(stderr, "[chat_vtab] invalid memory stats: current=%lld highwater=%lld\n",
284+
(long long)current, (long long)highwater);
285+
return 1;
286+
}
287+
return 0;
288+
289+
fail:
290+
if (db) sqlite3_close(db);
291+
return 1;
292+
}
293+
202294
static const test_case TESTS[] = {
203295
{"issue15_llm_chat_without_context", test_issue15_chat_without_context},
204296
{"llm_chat_respond_repeated", test_llm_chat_respond_repeated},
297+
{"llm_chat_vtab", test_llm_chat_vtab},
205298
};
206299

207300
int main(int argc, char **argv) {

0 commit comments

Comments
 (0)