AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4 5static sqlite3 *gDb = NULL;6 7void setUp(void) {8 int rc = sqlite3_open(":memory:", &gDb);9 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);10 TEST_ASSERT_NOT_NULL(gDb);11}12 13void tearDown(void) {14 if (gDb) {15 int rc = sqlite3_close(gDb);16 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);17 gDb = NULL;18 }19}20 21/* Helper to initialize a stack-based StrAccum/sqlite3_str with a caller buffer */22static void initAccum(StrAccum *p, char *buf, int bufSize, int mxAlloc){23 sqlite3StrAccumInit(p, gDb, buf, bufSize, mxAlloc);24}25 26/* Basic append within preallocated buffer (no enlarge) */27void test_sqlite3_str_append_basic_copy(void) {28 StrAccum acc;29 char buf[64];30 initAccum(&acc, buf, (int)sizeof(buf), 1000000);31 sqlite3_str *p = (sqlite3_str*)&acc;32 33 sqlite3_str_append(p, "Hello", 5);34 TEST_ASSERT_EQUAL_INT(5, sqlite3_str_length(p));35 char *s = sqlite3_str_value(p);36 TEST_ASSERT_NOT_NULL(s);37 TEST_ASSERT_EQUAL_INT(0, memcmp("Hello", s, 5));38 TEST_ASSERT_EQUAL_CHAR('\0', s[5]);39 40 sqlite3_str_append(p, " World", 6);41 TEST_ASSERT_EQUAL_INT(11, sqlite3_str_length(p));42 s = sqlite3_str_value(p);43 TEST_ASSERT_NOT_NULL(s);44 TEST_ASSERT_EQUAL_STRING("Hello World", s);45 46 sqlite3_str_reset(p);47}48 49/* Appending zero bytes should be a no-op (z non-NULL) */50void test_sqlite3_str_append_zero_N_noop_nonnull(void) {51 StrAccum acc;52 char buf[32];53 initAccum(&acc, buf, (int)sizeof(buf), 1000000);54 sqlite3_str *p = (sqlite3_str*)&acc;55 56 sqlite3_str_append(p, "ABC", 3);57 TEST_ASSERT_EQUAL_INT(3, sqlite3_str_length(p));58 char *s0 = sqlite3_str_value(p);59 TEST_ASSERT_NOT_NULL(s0);60 TEST_ASSERT_EQUAL_STRING_LEN("ABC", s0, 3);61 62 sqlite3_str_append(p, "ignored", 0); /* N==0 should do nothing */63 TEST_ASSERT_EQUAL_INT(3, sqlite3_str_length(p));64 char *s1 = sqlite3_str_value(p);65 TEST_ASSERT_NOT_NULL(s1);66 TEST_ASSERT_EQUAL_STRING("ABC", s1);67 68 sqlite3_str_reset(p);69}70 71/* Appending zero bytes with z==NULL should also be a no-op */72void test_sqlite3_str_append_zero_N_with_null_ptr(void) {73 StrAccum acc;74 char buf[16];75 initAccum(&acc, buf, (int)sizeof(buf), 1000000);76 sqlite3_str *p = (sqlite3_str*)&acc;77 78 sqlite3_str_append(p, "X", 1);79 TEST_ASSERT_EQUAL_INT(1, sqlite3_str_length(p));80 char *s0 = sqlite3_str_value(p);81 TEST_ASSERT_NOT_NULL(s0);82 TEST_ASSERT_EQUAL_STRING_LEN("X", s0, 1);83 84 sqlite3_str_append(p, NULL, 0); /* Allowed by function contract */85 TEST_ASSERT_EQUAL_INT(1, sqlite3_str_length(p));86 char *s1 = sqlite3_str_value(p);87 TEST_ASSERT_NOT_NULL(s1);88 TEST_ASSERT_EQUAL_STRING_LEN("X", s1, 1);89 90 sqlite3_str_reset(p);91}92 93/* Append that forces enlargement (within mxAlloc) */94void test_sqlite3_str_append_enlarge_within_limit(void) {95 StrAccum acc;96 char base[4]; /* Small base to force enlarge */97 initAccum(&acc, base, (int)sizeof(base), 1000000);98 sqlite3_str *p = (sqlite3_str*)&acc;99 100 /* This append is larger than the base buffer, so enlargement is required */101 const char *payload = "12345678";102 sqlite3_str_append(p, payload, 8);103 TEST_ASSERT_EQUAL_INT(8, sqlite3_str_length(p));104 105 char *s = sqlite3_str_value(p);106 TEST_ASSERT_NOT_NULL(s);107 TEST_ASSERT_EQUAL_STRING_LEN(payload, s, 8);108 109 /* If enlargement occurred, the backing pointer should not be the base array */110 TEST_ASSERT_TRUE(s != base);111 112 sqlite3_str_reset(p);113}114 115/* Append that exceeds mxAlloc should set an error and not modify content */116void test_sqlite3_str_append_exceed_mxAlloc_sets_error(void) {117 StrAccum acc;118 char base[8];119 int mxAlloc = 10; /* small limit */120 initAccum(&acc, base, (int)sizeof(base), mxAlloc);121 sqlite3_str *p = (sqlite3_str*)&acc;122 123 const char *tooBig = "01234567890"; /* 11 bytes > mxAlloc */124 sqlite3_str_append(p, tooBig, 11);125 126 int ec = sqlite3_str_errcode(p);127 TEST_ASSERT_NOT_EQUAL(SQLITE_OK, ec);128 TEST_ASSERT_EQUAL_INT(SQLITE_TOOBIG, ec); /* Expect SQLITE_TOOBIG due to mxAlloc limit */129 130 /* Length should remain 0 and value should be NULL after error */131 TEST_ASSERT_EQUAL_INT(0, sqlite3_str_length(p));132 char *s = sqlite3_str_value(p);133 TEST_ASSERT_NULL(s);134 135 /* Subsequent appends should be no-ops (still error) */136 sqlite3_str_append(p, "abc", 3);137 TEST_ASSERT_EQUAL_INT(0, sqlite3_str_length(p));138 TEST_ASSERT_EQUAL_INT(ec, sqlite3_str_errcode(p));139 140 sqlite3_str_reset(p);141}142 143/* Multiple sequential appends accumulate correctly (staying within base buffer) */144void test_sqlite3_str_append_multiple_accumulate(void) {145 StrAccum acc;146 char base[16];147 initAccum(&acc, base, (int)sizeof(base), 1000000);148 sqlite3_str *p = (sqlite3_str*)&acc;149 150 sqlite3_str_append(p, "XY", 2);151 sqlite3_str_append(p, "XY", 2);152 sqlite3_str_append(p, "XY", 2);153 TEST_ASSERT_EQUAL_INT(6, sqlite3_str_length(p));154 155 char *s = sqlite3_str_value(p);156 TEST_ASSERT_NOT_NULL(s);157 TEST_ASSERT_EQUAL_STRING_LEN("XYXYXY", s, 6);158 159 sqlite3_str_reset(p);160}161 162int main(void) {163 UNITY_BEGIN();164 RUN_TEST(test_sqlite3_str_append_basic_copy);165 RUN_TEST(test_sqlite3_str_append_zero_N_noop_nonnull);166 RUN_TEST(test_sqlite3_str_append_zero_N_with_null_ptr);167 RUN_TEST(test_sqlite3_str_append_enlarge_within_limit);168 RUN_TEST(test_sqlite3_str_append_exceed_mxAlloc_sets_error);169 RUN_TEST(test_sqlite3_str_append_multiple_accumulate);170 return UNITY_END();171}