AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5#include <stdio.h>6 7static void finalize_if_needed(sqlite3_stmt **ppStmt){8 if( ppStmt && *ppStmt ){9 int frc = sqlite3_finalize(*ppStmt);10 TEST_ASSERT_EQUAL_INT(SQLITE_OK, frc);11 *ppStmt = NULL;12 }13}14 15void setUp(void) {16 /* Setup code here, or leave empty */17}18 19void tearDown(void) {20 /* Cleanup code here, or leave empty */21}22 23/* Basic prepare with nBytes = -1 (NUL-terminated SQL) */24void test_sqlite3_prepare_basic_ok_nbytes_minus1(void) {25 sqlite3 *db = NULL;26 int rc = sqlite3_open(":memory:", &db);27 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);28 29 const char *sql = "SELECT 1;";30 sqlite3_stmt *stmt = NULL;31 const char *tail = NULL;32 33 rc = sqlite3_prepare(db, sql, -1, &stmt, &tail);34 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);35 TEST_ASSERT_NOT_NULL(stmt);36 TEST_ASSERT_NOT_NULL(tail);37 TEST_ASSERT_EQUAL_CHAR('\0', *tail);38 39 finalize_if_needed(&stmt);40 sqlite3_close(db);41}42 43/* Multi-statement SQL: tail should point to the next statement */44void test_sqlite3_prepare_multi_statement_tail_points_to_next(void) {45 sqlite3 *db = NULL;46 int rc = sqlite3_open(":memory:", &db);47 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);48 49 const char *sql = "SELECT 1;SELECT 2;";50 sqlite3_stmt *stmt = NULL;51 const char *tail = NULL;52 53 rc = sqlite3_prepare(db, sql, -1, &stmt, &tail);54 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);55 TEST_ASSERT_NOT_NULL(stmt);56 TEST_ASSERT_NOT_NULL(tail);57 /* The tail should begin at "SELECT 2;" */58 TEST_ASSERT_EQUAL_STRING_LEN("SELECT 2;", tail, 9);59 60 finalize_if_needed(&stmt);61 sqlite3_close(db);62}63 64/* Empty SQL string with nBytes = 0: should return OK with NULL stmt and tail at start */65void test_sqlite3_prepare_empty_string_nbytes_zero(void) {66 sqlite3 *db = NULL;67 int rc = sqlite3_open(":memory:", &db);68 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);69 70 const char empty[] = "";71 sqlite3_stmt *stmt = (sqlite3_stmt*)0xDEADBEEF; /* ensure it's cleared */72 const char *tail = NULL;73 74 rc = sqlite3_prepare(db, empty, 0, &stmt, &tail);75 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);76 TEST_ASSERT_NULL(stmt);77 TEST_ASSERT_NOT_NULL(tail);78 TEST_ASSERT_EQUAL_PTR(empty, tail);79 80 sqlite3_close(db);81}82 83/* nBytes shorter than full string: parse only the prefix and tail equals zSql+nBytes */84void test_sqlite3_prepare_with_nbytes_prefix_only(void) {85 sqlite3 *db = NULL;86 int rc = sqlite3_open(":memory:", &db);87 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);88 89 const char *sql = "SELECT 1; SELECT 2;";90 /* "SELECT 1;" is 9 bytes (including the semicolon) */91 int nBytes = 9;92 sqlite3_stmt *stmt = NULL;93 const char *tail = NULL;94 95 rc = sqlite3_prepare(db, sql, nBytes, &stmt, &tail);96 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);97 TEST_ASSERT_NOT_NULL(stmt);98 TEST_ASSERT_NOT_NULL(tail);99 TEST_ASSERT_EQUAL_PTR(sql + nBytes, tail);100 101 finalize_if_needed(&stmt);102 sqlite3_close(db);103}104 105/* Misuse: zSql == NULL should return SQLITE_MISUSE and clear *ppStmt */106void test_sqlite3_prepare_null_sql_misuse(void) {107 sqlite3 *db = NULL;108 int rc = sqlite3_open(":memory:", &db);109 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);110 111 sqlite3_stmt *stmt = (sqlite3_stmt*)0xBADF00D;112 const char *tail = NULL;113 114 rc = sqlite3_prepare(db, NULL, -1, &stmt, &tail);115 TEST_ASSERT_EQUAL_INT(SQLITE_MISUSE, rc);116 TEST_ASSERT_NULL(stmt);117 118 sqlite3_close(db);119}120 121/* Too-long SQL: enforce SQLITE_LIMIT_SQL_LENGTH and expect SQLITE_TOOBIG */122void test_sqlite3_prepare_too_long_hits_limit(void) {123 sqlite3 *db = NULL;124 int rc = sqlite3_open(":memory:", &db);125 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);126 127 /* Set a very small SQL length limit */128 int oldLimit = sqlite3_limit(db, SQLITE_LIMIT_SQL_LENGTH, 20);129 (void)oldLimit; /* old limit not used further, DB will be closed */130 131 const char *sql = "SELECT 1; SELECT 2; SELECT 3;";132 sqlite3_stmt *stmt = NULL;133 const char *tail = NULL;134 135 rc = sqlite3_prepare(db, sql, (int)strlen(sql), &stmt, &tail);136 TEST_ASSERT_EQUAL_INT(SQLITE_TOOBIG, rc);137 TEST_ASSERT_NULL(stmt);138 139 sqlite3_close(db);140}141 142/* Syntax error in SQL should return SQLITE_ERROR and no statement */143void test_sqlite3_prepare_syntax_error_returns_error(void) {144 sqlite3 *db = NULL;145 int rc = sqlite3_open(":memory:", &db);146 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);147 148 const char *badsql = "SELEC 1;"; /* misspelled SELECT */149 sqlite3_stmt *stmt = NULL;150 const char *tail = NULL;151 152 rc = sqlite3_prepare(db, badsql, -1, &stmt, &tail);153 TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, rc);154 TEST_ASSERT_NULL(stmt);155 156 sqlite3_close(db);157}158 159/* Passing NULL pzTail is allowed and should still succeed for valid SQL */160void test_sqlite3_prepare_null_pzTail_ok(void) {161 sqlite3 *db = NULL;162 int rc = sqlite3_open(":memory:", &db);163 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);164 165 const char *sql = "SELECT 1;";166 sqlite3_stmt *stmt = NULL;167 168 rc = sqlite3_prepare(db, sql, -1, &stmt, NULL);169 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);170 TEST_ASSERT_NOT_NULL(stmt);171 172 finalize_if_needed(&stmt);173 sqlite3_close(db);174}175 176int main(void) {177 UNITY_BEGIN();178 RUN_TEST(test_sqlite3_prepare_basic_ok_nbytes_minus1);179 RUN_TEST(test_sqlite3_prepare_multi_statement_tail_points_to_next);180 RUN_TEST(test_sqlite3_prepare_empty_string_nbytes_zero);181 RUN_TEST(test_sqlite3_prepare_with_nbytes_prefix_only);182 RUN_TEST(test_sqlite3_prepare_null_sql_misuse);183 RUN_TEST(test_sqlite3_prepare_too_long_hits_limit);184 RUN_TEST(test_sqlite3_prepare_syntax_error_returns_error);185 RUN_TEST(test_sqlite3_prepare_null_pzTail_ok);186 return UNITY_END();187}