Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_alter_sqlite3AlterAddConstraint.c198 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3 4#include <stdlib.h>5#include <string.h>6#include <stdio.h>7 8/* Helpers */9static int exec_sql(sqlite3 *db, const char *sql, char **pzErr){10  return sqlite3_exec(db, sql, 0, 0, pzErr);11}12 13static void assert_exec_ok(sqlite3 *db, const char *sql){14  char *zErr = NULL;15  int rc = exec_sql(db, sql, &zErr);16  if( zErr ){17    /* Ensure any error message is freed even if rc==SQLITE_OK (unlikely) */18    sqlite3_free(zErr);19    zErr = NULL;20  }21  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, sql);22}23 24static int exec_expect_error_contains(sqlite3 *db, const char *sql, const char *needle, int *pRcOut){25  char *zErr = NULL;26  int rc = exec_sql(db, sql, &zErr);27  if( pRcOut ) *pRcOut = rc;28  int ok = (rc!=SQLITE_OK) && (zErr!=NULL) && (strstr(zErr, needle)!=0);29  if( zErr ) sqlite3_free(zErr);30  return ok;31}32 33static char *get_table_sql(sqlite3 *db, const char *zName){34  sqlite3_stmt *pStmt = NULL;35  const char *zSql = "SELECT sql FROM sqlite_schema WHERE name=?1";36  if( sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0)!=SQLITE_OK ){37    return NULL;38  }39  sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);40  char *zOut = NULL;41  if( sqlite3_step(pStmt)==SQLITE_ROW ){42    const unsigned char *z = sqlite3_column_text(pStmt, 0);43    if( z ){44      zOut = sqlite3_mprintf("%s", z);45    }46  }47  sqlite3_finalize(pStmt);48  return zOut;49}50 51/* Unity fixtures */52void setUp(void) {53  /* empty */54}55void tearDown(void) {56  /* empty */57}58 59/* Test: Successful ALTER adds named constraint and enforces it for new rows */60void test_sqlite3AlterAddConstraint_add_named_and_enforce(void){61  sqlite3 *db = NULL;62  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));63 64  assert_exec_ok(db, "CREATE TABLE t1(x)");65  assert_exec_ok(db, "INSERT INTO t1 VALUES(1)");66 67  /* Add a named CHECK constraint */68  assert_exec_ok(db, "ALTER TABLE t1 ADD CONSTRAINT ck_pos CHECK(x>0)");69 70  /* Inserting a violating row should now fail */71  int rc = SQLITE_OK;72  TEST_ASSERT_TRUE_MESSAGE(73    exec_expect_error_contains(db, "INSERT INTO t1 VALUES(0)", "CHECK constraint failed", &rc),74    "Expected CHECK constraint failure on INSERT after ALTER"75  );76  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_CONSTRAINT, rc, "Expected SQLITE_CONSTRAINT");77 78  /* Valid insert still succeeds */79  assert_exec_ok(db, "INSERT INTO t1 VALUES(2)");80 81  /* Adding another constraint with the same name should fail */82  TEST_ASSERT_TRUE_MESSAGE(83    exec_expect_error_contains(db,84      "ALTER TABLE t1 ADD CONSTRAINT ck_pos CHECK(x<10)",85      "already exists",86      NULL87    ),88    "Expected duplicate constraint name error"89  );90 91  sqlite3_close(db);92}93 94/* Test: ALTER fails if existing rows violate the new CHECK expression */95void test_sqlite3AlterAddConstraint_violation_on_alter(void){96  sqlite3 *db = NULL;97  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));98 99  assert_exec_ok(db, "CREATE TABLE t2(x)");100  assert_exec_ok(db, "INSERT INTO t2 VALUES(-1)");101 102  /* This should fail because existing row violates x>0 */103  int rc = SQLITE_OK;104  TEST_ASSERT_TRUE_MESSAGE(105    exec_expect_error_contains(db,106      "ALTER TABLE t2 ADD CHECK(x>0)",107      "constraint failed",108      &rc109    ),110    "Expected 'constraint failed' during ALTER due to existing data"111  );112  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_CONSTRAINT, rc, "Expected SQLITE_CONSTRAINT");113 114  /* Schema should not be modified */115  char *zSchema = get_table_sql(db, "t2");116  TEST_ASSERT_NOT_NULL(zSchema);117  TEST_ASSERT_TRUE(strstr(zSchema, "CHECK")==NULL);118  sqlite3_free(zSchema);119 120  sqlite3_close(db);121}122 123/* Test: Trailing '--' is trimmed but trailing '/* ... *\/' comment is preserved */124void test_sqlite3AlterAddConstraint_trim_line_comment_preserve_c_comment(void){125  sqlite3 *db = NULL;126  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));127 128  assert_exec_ok(db, "CREATE TABLE t3(x)");129  assert_exec_ok(db, "INSERT INTO t3 VALUES(1)");130 131  /* Trailing C-style comment should be preserved; trailing -- comment removed */132  assert_exec_ok(db, "ALTER TABLE t3 ADD CHECK (x>0) /*C-keep*/ -- line-drop");133 134  char *zSchema = get_table_sql(db, "t3");135  TEST_ASSERT_NOT_NULL(zSchema);136 137  /* Ensure C-style comment present, '--' tail absent */138  TEST_ASSERT_NOT_NULL_MESSAGE(strstr(zSchema, "/*C-keep*/"), "Expected C-style comment preserved in schema SQL");139  TEST_ASSERT_NULL_MESSAGE(strstr(zSchema, "-- line-drop"), "Expected '--' trailing comment removed from schema SQL");140 141  sqlite3_free(zSchema);142  sqlite3_close(db);143}144 145/* Direct call smoke test: invoke sqlite3AlterAddConstraint with constructed Parse/SrcList/Tokens */146void test_sqlite3AlterAddConstraint_direct_call_smoke(void){147  sqlite3 *db = NULL;148  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));149  assert_exec_ok(db, "CREATE TABLE t4(a)");150 151  /* Prepare Parse with a Vdbe */152  Parse p;153  memset(&p, 0, sizeof(p));154  p.db = db;155  /* Ensure there is a VDBE to receive generated bytecode */156  sqlite3GetVdbe(&p);157  TEST_ASSERT_NOT_NULL(p.pVdbe);158 159  /* Build a SrcList referring to table t4 */160  Token tTbl = { "t4", 2 };161  SrcList *pSrc = sqlite3SrcListAppend(db, 0, &tTbl, 0);162  TEST_ASSERT_NOT_NULL(pSrc);163  TEST_ASSERT_EQUAL_INT(1, pSrc->nSrc);164 165  /* Construct constraint text and tokens */166  const char *zCons = "CONSTRAINT ckx CHECK(a>0) /*preserve*/ -- trim";167  Token firstTok;168  firstTok.z = zCons;169  firstTok.n = (int)strlen(zCons);170  Token nameTok = { "ckx", 3 };171  const char *zExpr = "a>0";172  int nExpr = 3;173 174  /* Set sLastToken to mark the end of the constraint text buffer */175  p.sLastToken.z = zCons + strlen(zCons);176  p.sLastToken.n = 0;177 178  /* Invoke the target function directly */179  sqlite3AlterAddConstraint(&p, pSrc, &firstTok, &nameTok, zExpr, nExpr);180 181  /* Basic sanity: no parse errors recorded and VDBE remains allocated */182  TEST_ASSERT_NOT_NULL(p.pVdbe);183  TEST_ASSERT_EQUAL_INT(0, p.nErr);184 185  /* Cleanup */186  sqlite3SrcListDelete(db, pSrc);187  sqlite3VdbeDelete(p.pVdbe);188  sqlite3_close(db);189}190 191int main(void) {192  UNITY_BEGIN();193  RUN_TEST(test_sqlite3AlterAddConstraint_add_named_and_enforce);194  RUN_TEST(test_sqlite3AlterAddConstraint_violation_on_alter);195  RUN_TEST(test_sqlite3AlterAddConstraint_trim_line_comment_preserve_c_comment);196  RUN_TEST(test_sqlite3AlterAddConstraint_direct_call_smoke);197  return UNITY_END();198}