AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdio.h>4#include <stdlib.h>5#include <string.h>6 7/* Helper: execute SQL and assert success */8static void exec_ok(sqlite3 *db, const char *zSql){9 char *zErr = NULL;10 int rc = sqlite3_exec(db, zSql, 0, 0, &zErr);11 if( zErr ){12 /* In case of error, include message in assertion for easier debugging */13 char buf[512];14 sqlite3_snprintf(sizeof(buf), buf, "SQL error: %s; SQL: %s", zErr, zSql);15 sqlite3_free(zErr);16 TEST_FAIL_MESSAGE(buf);17 }18 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);19}20 21/* Helper: allocate a temporary filename using sqlite3_mprintf.22 Caller must sqlite3_free() the returned string. */23static char* temp_filename(void){24 char tmpbuf[L_tmpnam];25 char *z = NULL;26 /* tmpnam returns a unique name. Not ideal for production, fine for tests. */27 if( tmpnam(tmpbuf) == NULL ){28 /* Fallback to a static name with random-ish suffix */29 int rnd = (int)sqlite3_randomness(0,0); /* Not reliable; avoid using this. */30 /* If tmpnam fails, just use a fixed name that hopefully works. */31 z = sqlite3_mprintf("sqlite_test_tmp.db");32 }else{33 z = sqlite3_mprintf("%s", tmpbuf);34 }35 return z;36}37 38void setUp(void) {39 /* no-op */40}41void tearDown(void) {42 /* no-op */43}44 45/* Test: "main" on an in-memory connection should be read/write (0). */46void test_sqlite3_db_readonly_main_rw_memory(void){47 sqlite3 *db = NULL;48 int rc = sqlite3_open(":memory:", &db);49 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);50 TEST_ASSERT_NOT_NULL(db);51 52 int ro = sqlite3_db_readonly(db, "main");53 TEST_ASSERT_EQUAL_INT(0, ro);54 55 sqlite3_close(db);56}57 58/* Test: Unknown database name should return -1. */59void test_sqlite3_db_readonly_unknown_db(void){60 sqlite3 *db = NULL;61 int rc = sqlite3_open(":memory:", &db);62 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);63 TEST_ASSERT_NOT_NULL(db);64 65 int ro = sqlite3_db_readonly(db, "nosuchdb");66 TEST_ASSERT_EQUAL_INT(-1, ro);67 68 sqlite3_close(db);69}70 71/* Test: "temp" before and after creating a TEMP table. */72void test_sqlite3_db_readonly_temp_before_and_after(void){73 sqlite3 *db = NULL;74 int rc = sqlite3_open(":memory:", &db);75 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);76 TEST_ASSERT_NOT_NULL(db);77 78 /* Before any temp object exists, expect -1 (no temp btree open). */79 int ro_before = sqlite3_db_readonly(db, "temp");80 TEST_ASSERT_EQUAL_INT(-1, ro_before);81 82 /* Create a temp table to open the temp btree. */83 exec_ok(db, "CREATE TEMP TABLE ttemp(x)");84 85 /* Now temp btree exists, expect read/write (0). */86 int ro_after = sqlite3_db_readonly(db, "temp");87 TEST_ASSERT_EQUAL_INT(0, ro_after);88 89 sqlite3_close(db);90}91 92/* Test: File-backed DB opened in read-only mode should return 1 for "main". */93void test_sqlite3_db_readonly_main_readonly_file(void){94 sqlite3 *db = NULL;95 char *zFile = temp_filename();96 TEST_ASSERT_NOT_NULL(zFile);97 98 /* Create the database file and ensure it exists with some content. */99 int rc = sqlite3_open(zFile, &db);100 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);101 TEST_ASSERT_NOT_NULL(db);102 exec_ok(db, "CREATE TABLE t(x)");103 sqlite3_close(db);104 db = NULL;105 106 /* Re-open read-only */107 rc = sqlite3_open_v2(zFile, &db, SQLITE_OPEN_READONLY, NULL);108 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);109 TEST_ASSERT_NOT_NULL(db);110 111 int ro = sqlite3_db_readonly(db, "main");112 TEST_ASSERT_EQUAL_INT(1, ro);113 114 sqlite3_close(db);115 /* Clean up the file. */116 remove(zFile);117 sqlite3_free(zFile);118}119 120/* Test: Attach a secondary database; it should be read/write (0). */121void test_sqlite3_db_readonly_attach_rw_db(void){122 sqlite3 *db = NULL;123 char *zFile = temp_filename();124 TEST_ASSERT_NOT_NULL(zFile);125 126 int rc = sqlite3_open(":memory:", &db);127 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);128 TEST_ASSERT_NOT_NULL(db);129 130 /* ATTACH with a quoted filename using %Q */131 char *zSql = sqlite3_mprintf("ATTACH %Q AS aux", zFile);132 TEST_ASSERT_NOT_NULL(zSql);133 exec_ok(db, zSql);134 sqlite3_free(zSql);135 136 /* Expect read/write (0) for the attached db "aux". */137 int ro = sqlite3_db_readonly(db, "aux");138 TEST_ASSERT_EQUAL_INT(0, ro);139 140 /* Detach and cleanup. */141 exec_ok(db, "DETACH aux");142 sqlite3_close(db);143 remove(zFile);144 sqlite3_free(zFile);145}146 147int main(void){148 UNITY_BEGIN();149 RUN_TEST(test_sqlite3_db_readonly_main_rw_memory);150 RUN_TEST(test_sqlite3_db_readonly_unknown_db);151 RUN_TEST(test_sqlite3_db_readonly_temp_before_and_after);152 RUN_TEST(test_sqlite3_db_readonly_main_readonly_file);153 RUN_TEST(test_sqlite3_db_readonly_attach_rw_db);154 return UNITY_END();155}