AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5#include <stdio.h>6 7/* Prototype of the global wrapper provided in the module */8void test_printfFunc(sqlite3_context *context, int argc, sqlite3_value **argv);9 10static sqlite3 *gDb = NULL;11static Vdbe *gVdbe = NULL;12static sqlite3_context gCtx;13static Mem gOut;14 15static Mem* makeText(const char *z){16 Mem *m = sqlite3ValueNew(gDb);17 TEST_ASSERT_NOT_NULL(m);18 /* -1 length means to compute strlen, SQLITE_TRANSIENT so SQLite copies data if needed */19 int rc = sqlite3VdbeMemSetStr(m, z, -1, SQLITE_UTF8, SQLITE_TRANSIENT);20 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);21 return m;22}23static Mem* makeInt64(sqlite3_int64 v){24 Mem *m = sqlite3ValueNew(gDb);25 TEST_ASSERT_NOT_NULL(m);26 sqlite3VdbeMemSetInt64(m, v);27 return m;28}29static Mem* makeDouble(double v){30 Mem *m = sqlite3ValueNew(gDb);31 TEST_ASSERT_NOT_NULL(m);32 sqlite3VdbeMemSetDouble(m, v);33 return m;34}35static Mem* makeNull(void){36 Mem *m = sqlite3ValueNew(gDb);37 TEST_ASSERT_NOT_NULL(m);38 sqlite3VdbeMemSetNull(m);39 return m;40}41static void freeVals(int n, Mem **vals){42 for(int i=0;i<n;i++){43 if(vals[i]) sqlite3ValueFree(vals[i]);44 }45}46static void runPrintf(int argc, Mem **argv){47 test_printfFunc(&gCtx, argc, (sqlite3_value**)argv);48}49static const char* resultText(void){50 const unsigned char *z = sqlite3_value_text((sqlite3_value*)&gOut);51 return (const char*)z;52}53 54void setUp(void) {55 int rc = sqlite3_open(":memory:", &gDb);56 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);57 gVdbe = sqlite3VdbeCreate(gDb);58 TEST_ASSERT_NOT_NULL(gVdbe);59 memset(&gCtx, 0, sizeof(gCtx));60 memset(&gOut, 0, sizeof(gOut));61 gOut.db = gDb; /* Ensure output Mem knows the db for allocations */62 gCtx.pVdbe = gVdbe; /* Needed for sqlite3_context_db_handle() */63 gCtx.pOut = &gOut; /* Where sqlite3_result_* will store output */64}65 66void tearDown(void) {67 sqlite3VdbeMemRelease(&gOut);68 memset(&gOut, 0, sizeof(gOut));69 if(gVdbe){70 sqlite3VdbeDelete(gVdbe);71 gVdbe = NULL;72 }73 if(gDb){74 sqlite3_close(gDb);75 gDb = NULL;76 }77}78 79/* Tests */80 81void test_printfFunc_literal_no_args(void){82 Mem *fmt = makeText("hello");83 Mem *argv[] = { fmt };84 runPrintf(1, argv);85 const char *got = resultText();86 TEST_ASSERT_NOT_NULL(got);87 TEST_ASSERT_EQUAL_STRING("hello", got);88 freeVals(1, argv);89}90 91void test_printfFunc_integer_decimal(void){92 Mem *fmt = makeText("num=%d");93 Mem *v1 = makeInt64(123);94 Mem *argv[] = { fmt, v1 };95 runPrintf(2, argv);96 const char *got = resultText();97 TEST_ASSERT_NOT_NULL(got);98 TEST_ASSERT_EQUAL_STRING("num=123", got);99 freeVals(2, argv);100}101 102void test_printfFunc_string_basic(void){103 Mem *fmt = makeText("[%s]");104 Mem *v1 = makeText("abc");105 Mem *argv[] = { fmt, v1 };106 runPrintf(2, argv);107 const char *got = resultText();108 TEST_ASSERT_NOT_NULL(got);109 TEST_ASSERT_EQUAL_STRING("[abc]", got);110 freeVals(2, argv);111}112 113void test_printfFunc_float_precision(void){114 Mem *fmt = makeText("%.2f");115 Mem *v1 = makeDouble(3.14159);116 Mem *argv[] = { fmt, v1 };117 runPrintf(2, argv);118 const char *got = resultText();119 TEST_ASSERT_NOT_NULL(got);120 TEST_ASSERT_EQUAL_STRING("3.14", got);121 freeVals(2, argv);122}123 124void test_printfFunc_escaped_percent_and_int(void){125 Mem *fmt = makeText("%%-%d");126 Mem *v1 = makeInt64(7);127 Mem *argv[] = { fmt, v1 };128 runPrintf(2, argv);129 const char *got = resultText();130 TEST_ASSERT_NOT_NULL(got);131 TEST_ASSERT_EQUAL_STRING("%-7", got);132 freeVals(2, argv);133}134 135void test_printfFunc_zero_padded_width(void){136 Mem *fmt = makeText("%06d");137 Mem *v1 = makeInt64(3);138 Mem *argv[] = { fmt, v1 };139 runPrintf(2, argv);140 const char *got = resultText();141 TEST_ASSERT_NOT_NULL(got);142 TEST_ASSERT_EQUAL_STRING("000003", got);143 freeVals(2, argv);144}145 146void test_printfFunc_multiple_mixed_args(void){147 Mem *fmt = makeText("%s %d %.1f");148 Mem *v1 = makeText("a");149 Mem *v2 = makeInt64(2);150 Mem *v3 = makeDouble(3.4);151 Mem *argv[] = { fmt, v1, v2, v3 };152 runPrintf(4, argv);153 const char *got = resultText();154 TEST_ASSERT_NOT_NULL(got);155 TEST_ASSERT_EQUAL_STRING("a 2 3.4", got);156 freeVals(4, argv);157}158 159void test_printfFunc_null_format_results_in_null_output(void){160 /* When the format is NULL, printfFunc does not set a result; output remains NULL */161 Mem *fmt = makeNull();162 Mem *argv[] = { fmt };163 /* Ensure output starts as NULL */164 sqlite3VdbeMemRelease(&gOut);165 memset(&gOut, 0, sizeof(gOut));166 gOut.db = gDb;167 168 runPrintf(1, argv);169 int t = sqlite3_value_type((sqlite3_value*)&gOut);170 TEST_ASSERT_EQUAL_INT(SQLITE_NULL, t);171 freeVals(1, argv);172}173 174void test_printfFunc_percent_Q_sql_quoting(void){175 Mem *fmt = makeText("%Q");176 Mem *v1 = makeText("O'Reilly");177 Mem *argv[] = { fmt, v1 };178 runPrintf(2, argv);179 const char *got = resultText();180 TEST_ASSERT_NOT_NULL(got);181 TEST_ASSERT_EQUAL_STRING("'O''Reilly'", got);182 freeVals(2, argv);183}184 185void test_printfFunc_extra_args_ignored(void){186 Mem *fmt = makeText("X");187 Mem *v1 = makeInt64(999);188 Mem *argv[] = { fmt, v1 };189 runPrintf(2, argv);190 const char *got = resultText();191 TEST_ASSERT_NOT_NULL(got);192 TEST_ASSERT_EQUAL_STRING("X", got);193 freeVals(2, argv);194}195 196void test_printfFunc_large_output(void){197 /* Create a large input string and ensure it passes through */198 const int N = 5000;199 char *big = (char*)sqlite3_malloc(N+1);200 TEST_ASSERT_NOT_NULL(big);201 memset(big, 'x', N);202 big[N] = '\0';203 204 Mem *fmt = makeText("%s");205 Mem *v1 = makeText(big);206 Mem *argv[] = { fmt, v1 };207 runPrintf(2, argv);208 const char *got = resultText();209 TEST_ASSERT_NOT_NULL(got);210 TEST_ASSERT_EQUAL_UINT32((uint32_t)N, (uint32_t)strlen(got));211 /* Spot check: first and last */212 TEST_ASSERT_EQUAL_CHAR('x', got[0]);213 TEST_ASSERT_EQUAL_CHAR('x', got[N-1]);214 215 sqlite3_free(big);216 freeVals(2, argv);217}218 219int main(void){220 UNITY_BEGIN();221 RUN_TEST(test_printfFunc_literal_no_args);222 RUN_TEST(test_printfFunc_integer_decimal);223 RUN_TEST(test_printfFunc_string_basic);224 RUN_TEST(test_printfFunc_float_precision);225 RUN_TEST(test_printfFunc_escaped_percent_and_int);226 RUN_TEST(test_printfFunc_zero_padded_width);227 RUN_TEST(test_printfFunc_multiple_mixed_args);228 RUN_TEST(test_printfFunc_null_format_results_in_null_output);229 RUN_TEST(test_printfFunc_percent_Q_sql_quoting);230 RUN_TEST(test_printfFunc_extra_args_ignored);231 RUN_TEST(test_printfFunc_large_output);232 return UNITY_END();233}