AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6static sqlite3 *gDb = NULL;7 8/* Unity setUp/tearDown */9void setUp(void) {10 int rc = sqlite3_open(":memory:", &gDb);11 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);12 TEST_ASSERT_NOT_NULL(gDb);13}14void tearDown(void) {15 if (gDb) {16 sqlite3_close(gDb);17 gDb = NULL;18 }19}20 21/* Helper: allocate and populate Column.zCnName with name[\0type][\0coll][\0] */22static void allocZCnName(Column *pCol, const char *zName, const char *zType, const char *zColl){23 memset(pCol, 0, sizeof(*pCol));24 int nName = (int)strlen(zName);25 int nType = zType ? (int)strlen(zType) : 0;26 int nColl = zColl ? (int)strlen(zColl) : 0;27 int total = nName + 1 + (zType ? (nType + 1) : 0) + (zColl ? (nColl + 1) : 0);28 29 char *z = (char*)sqlite3DbMallocZero(gDb, total);30 TEST_ASSERT_NOT_NULL(z);31 32 int off = 0;33 memcpy(z + off, zName, nName);34 off += nName;35 z[off++] = '\0';36 37 if (zType) {38 memcpy(z + off, zType, nType);39 off += nType;40 z[off++] = '\0';41 pCol->colFlags |= COLFLAG_HASTYPE;42 }43 if (zColl) {44 memcpy(z + off, zColl, nColl);45 off += nColl;46 z[off++] = '\0';47 pCol->colFlags |= COLFLAG_HASCOLL;48 }49 50 pCol->zCnName = z;51}52 53/* Test 1: Append collating sequence when there is only a name (no type) */54void test_sqlite3ColumnSetColl_appends_coll_without_type(void) {55 Column c;56 const char *zName = "a";57 const char *zColl = "BINARY";58 allocZCnName(&c, zName, NULL, NULL);59 TEST_ASSERT_EQUAL_STRING(zName, c.zCnName);60 TEST_ASSERT_EQUAL(0, (c.colFlags & (COLFLAG_HASTYPE|COLFLAG_HASCOLL)));61 62 sqlite3ColumnSetColl(gDb, &c, zColl);63 64 /* Verify content: "a\0BINARY\0" */65 TEST_ASSERT_EQUAL_STRING(zName, c.zCnName);66 int n = (int)strlen(c.zCnName) + 1;67 TEST_ASSERT_EQUAL_STRING(zColl, c.zCnName + n);68 TEST_ASSERT_NOT_EQUAL(0, (c.colFlags & COLFLAG_HASCOLL));69 70 sqlite3DbFree(gDb, c.zCnName);71}72 73/* Test 2: Append collating sequence after type when COLFLAG_HASTYPE is set */74void test_sqlite3ColumnSetColl_appends_coll_after_type(void) {75 Column c;76 const char *zName = "col";77 const char *zType = "TEXT";78 const char *zColl = "NOCASE";79 allocZCnName(&c, zName, zType, NULL);80 TEST_ASSERT_NOT_EQUAL(0, (c.colFlags & COLFLAG_HASTYPE));81 TEST_ASSERT_EQUAL(0, (c.colFlags & COLFLAG_HASCOLL));82 83 sqlite3ColumnSetColl(gDb, &c, zColl);84 85 /* Verify content: "col\0TEXT\0NOCASE\0" */86 TEST_ASSERT_EQUAL_STRING(zName, c.zCnName);87 int n = (int)strlen(c.zCnName) + 1;88 TEST_ASSERT_EQUAL_STRING(zType, c.zCnName + n);89 n += (int)strlen(zType) + 1;90 TEST_ASSERT_EQUAL_STRING(zColl, c.zCnName + n);91 92 /* Flags: HASTYPE preserved, HASCOLL set */93 TEST_ASSERT_NOT_EQUAL(0, (c.colFlags & COLFLAG_HASTYPE));94 TEST_ASSERT_NOT_EQUAL(0, (c.colFlags & COLFLAG_HASCOLL));95 96 sqlite3DbFree(gDb, c.zCnName);97}98 99/* Test 3: Replace existing collating sequence when both type and coll are present */100void test_sqlite3ColumnSetColl_replaces_existing_coll_with_type(void) {101 Column c;102 const char *zName = "x";103 const char *zType = "INTEGER";104 const char *zInitialColl = "BINARY";105 const char *zNewColl = "NOCASE";106 allocZCnName(&c, zName, zType, zInitialColl);107 TEST_ASSERT_NOT_EQUAL(0, (c.colFlags & COLFLAG_HASTYPE));108 TEST_ASSERT_NOT_EQUAL(0, (c.colFlags & COLFLAG_HASCOLL));109 110 sqlite3ColumnSetColl(gDb, &c, zNewColl);111 112 /* Verify content: "x\0INTEGER\0NOCASE\0" */113 TEST_ASSERT_EQUAL_STRING(zName, c.zCnName);114 int n = (int)strlen(c.zCnName) + 1;115 TEST_ASSERT_EQUAL_STRING(zType, c.zCnName + n);116 n += (int)strlen(zType) + 1;117 TEST_ASSERT_EQUAL_STRING(zNewColl, c.zCnName + n);118 119 /* Flags preserved/updated */120 TEST_ASSERT_NOT_EQUAL(0, (c.colFlags & COLFLAG_HASTYPE));121 TEST_ASSERT_NOT_EQUAL(0, (c.colFlags & COLFLAG_HASCOLL));122 123 sqlite3DbFree(gDb, c.zCnName);124}125 126/* Test 4: Replace existing collating sequence when no type is present */127void test_sqlite3ColumnSetColl_replaces_existing_coll_without_type(void) {128 Column c;129 const char *zName = "y";130 const char *zInitialColl = "BINARY";131 const char *zNewColl = "RTRIM";132 allocZCnName(&c, zName, NULL, zInitialColl);133 TEST_ASSERT_EQUAL(0, (c.colFlags & COLFLAG_HASTYPE));134 TEST_ASSERT_NOT_EQUAL(0, (c.colFlags & COLFLAG_HASCOLL));135 136 sqlite3ColumnSetColl(gDb, &c, zNewColl);137 138 /* Verify content: "y\0RTRIM\0" */139 TEST_ASSERT_EQUAL_STRING(zName, c.zCnName);140 int n = (int)strlen(c.zCnName) + 1;141 TEST_ASSERT_EQUAL_STRING(zNewColl, c.zCnName + n);142 143 /* Flags: HASCOLL set (remains set), HASTYPE still not set */144 TEST_ASSERT_EQUAL(0, (c.colFlags & COLFLAG_HASTYPE));145 TEST_ASSERT_NOT_EQUAL(0, (c.colFlags & COLFLAG_HASCOLL));146 147 sqlite3DbFree(gDb, c.zCnName);148}149 150/* Helper to build a long collation name */151static char *makeLongCollName(int n){152 char *z = (char*)sqlite3_malloc(n+1);153 TEST_ASSERT_NOT_NULL(z);154 for(int i=0;i<n;i++) z[i] = (char)('a' + (i%26));155 z[n] = '\0';156 return z;157}158 159/* Test 5: Handle long collation names (ensures realloc and correct placement) */160void test_sqlite3ColumnSetColl_handles_long_collation_name(void) {161 Column c;162 const char *zName = "z";163 allocZCnName(&c, zName, NULL, NULL);164 165 char *zLong = makeLongCollName(1024);166 sqlite3ColumnSetColl(gDb, &c, zLong);167 168 /* Verify placement after name */169 TEST_ASSERT_EQUAL_STRING(zName, c.zCnName);170 int n = (int)strlen(c.zCnName) + 1;171 TEST_ASSERT_EQUAL_STRING(zLong, c.zCnName + n);172 TEST_ASSERT_NOT_EQUAL(0, (c.colFlags & COLFLAG_HASCOLL));173 174 sqlite3DbFree(gDb, c.zCnName);175 sqlite3_free(zLong);176}177 178int main(void) {179 UNITY_BEGIN();180 RUN_TEST(test_sqlite3ColumnSetColl_appends_coll_without_type);181 RUN_TEST(test_sqlite3ColumnSetColl_appends_coll_after_type);182 RUN_TEST(test_sqlite3ColumnSetColl_replaces_existing_coll_with_type);183 RUN_TEST(test_sqlite3ColumnSetColl_replaces_existing_coll_without_type);184 RUN_TEST(test_sqlite3ColumnSetColl_handles_long_collation_name);185 return UNITY_END();186}