Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_fkey_sqlite3FkOldmask.c186 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdio.h>5 6/* Global database handle for allocations using sqlite3DbMalloc... */7static sqlite3 *gDb = NULL;8 9/* Unity setup/teardown */10void setUp(void) {11  int rc = sqlite3_open(":memory:", &gDb);12  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);13}14 15void tearDown(void) {16  if (gDb) {17    sqlite3_close(gDb);18    gDb = NULL;19  }20}21 22/* Helpers to build Table and FKey structures */23 24static Table* makeTable(sqlite3 *db, const char *zName, int nCol){25  Table *pTab = (Table*)sqlite3DbMallocZero(db, sizeof(Table));26  TEST_ASSERT_NOT_NULL(pTab);27  pTab->zName = sqlite3DbStrDup(db, zName ? zName : "t");28  pTab->nCol = (i16)nCol;29  pTab->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nCol);30  TEST_ASSERT_NOT_NULL(pTab->aCol);31  /* Ordinary table by default: tabFlags = 0 should suffice */32  pTab->tabFlags = 0;33  /* Link to main schema if available */34  if( db && db->nDb>0 ){35    pTab->pSchema = db->aDb[0].pSchema;36  }37  return pTab;38}39 40/* Allocate an FKey with nCol entries. fromCols[] holds iFrom values. */41static FKey* makeFKey(sqlite3 *db, Table *pFrom, int nCol, const int *fromCols){42  /* FKey has a flexible array member aCol[]. Allocate enough space. */43  size_t sz = sizeof(FKey) + (size_t)(nCol>0 ? (nCol-1) : 0) * sizeof(pFrom->u.tab.pFKey->aCol[0]);44  FKey *pFk = (FKey*)sqlite3DbMallocZero(db, sz);45  TEST_ASSERT_NOT_NULL(pFk);46  pFk->pFrom = pFrom;47  pFk->nCol = (i16)nCol;48  /* zTo is not used by sqlite3FkOldmask, but set something benign. */49  pFk->zTo = sqlite3DbStrDup(db, "parent");50  for(int i=0; i<nCol; i++){51    pFk->aCol[i].iFrom = fromCols[i];52    pFk->aCol[i].zCol = 0; /* not needed for this path */53  }54  return pFk;55}56 57/* Append an FKey to the pTab->u.tab.pFKey chain (outgoing FKs) */58static void appendOutgoingFKey(Table *pTab, FKey *pFk){59  if( pTab->u.tab.pFKey==0 ){60    pTab->u.tab.pFKey = pFk;61  }else{62    FKey *p = pTab->u.tab.pFKey;63    while( p->pNextFrom ) p = p->pNextFrom;64    p->pNextFrom = pFk;65  }66}67 68/* Free a Table and its outgoing FKey chain (allocated via sqlite3DbMalloc...). */69static void freeTableAndFKeys(sqlite3 *db, Table *pTab){70  if( !pTab ) return;71  /* Free outgoing FKeys */72  FKey *p = pTab->u.tab.pFKey;73  while( p ){74    FKey *pNext = p->pNextFrom;75    if( p->zTo ) sqlite3DbFree(db, p->zTo);76    sqlite3DbFree(db, p);77    p = pNext;78  }79  if( pTab->aCol ) sqlite3DbFree(db, pTab->aCol);80  if( pTab->zName ) sqlite3DbFree(db, pTab->zName);81  sqlite3DbFree(db, pTab);82}83 84/* Compute expected mask for given set of column indexes */85static u32 maskForCols(const int *cols, int n){86  u32 m = 0;87  for(int i=0; i<n; i++){88    m |= COLUMN_MASK(cols[i]);89  }90  return m;91}92 93/* Test 1: With foreign keys disabled, mask should be 0 even if FKs exist */94void test_sqlite3FkOldmask_returns_zero_when_foreign_keys_disabled(void){95  /* Arrange */96  Parse parse;97  memset(&parse, 0, sizeof(parse));98  parse.db = gDb;99 100  /* Explicitly ensure FK processing is disabled */101  gDb->flags &= ~SQLITE_ForeignKeys;102 103  Table *pTab = makeTable(gDb, "child", 8);104 105  int cols1[] = {1};106  int cols2[] = {3, 4};107  FKey *fk1 = makeFKey(gDb, pTab, 1, cols1);108  FKey *fk2 = makeFKey(gDb, pTab, 2, cols2);109  appendOutgoingFKey(pTab, fk1);110  appendOutgoingFKey(pTab, fk2);111 112  /* Act */113  u32 mask = sqlite3FkOldmask(&parse, pTab);114 115  /* Assert */116  TEST_ASSERT_EQUAL_HEX32(0, mask);117 118  /* Cleanup */119  freeTableAndFKeys(gDb, pTab);120}121 122/* Test 2: With foreign keys enabled, mask is union of child-side FK column bits */123void test_sqlite3FkOldmask_aggregates_mask_from_child_foreign_keys(void){124  /* Arrange */125  Parse parse;126  memset(&parse, 0, sizeof(parse));127  parse.db = gDb;128 129  gDb->flags |= SQLITE_ForeignKeys;130 131  Table *pTab = makeTable(gDb, "child", 16);132 133  int cols1[] = {0};134  int cols2[] = {2, 1, 5};135  int cols3[] = {5, 2}; /* duplicates to ensure union behavior */136  FKey *fk1 = makeFKey(gDb, pTab, 1, cols1);137  FKey *fk2 = makeFKey(gDb, pTab, 3, cols2);138  FKey *fk3 = makeFKey(gDb, pTab, 2, cols3);139  appendOutgoingFKey(pTab, fk1);140  appendOutgoingFKey(pTab, fk2);141  appendOutgoingFKey(pTab, fk3);142 143  /* Expected mask: bits for columns 0,1,2,5 */144  int expectedCols[] = {0,1,2,5};145  u32 expected = maskForCols(expectedCols, (int)(sizeof(expectedCols)/sizeof(expectedCols[0])));146 147  /* Act */148  u32 mask = sqlite3FkOldmask(&parse, pTab);149 150  /* Assert */151  TEST_ASSERT_EQUAL_HEX32(expected, mask);152 153  /* Cleanup */154  freeTableAndFKeys(gDb, pTab);155}156 157/* Test 3: With foreign keys enabled but no FKs at all, mask is 0 */158void test_sqlite3FkOldmask_returns_zero_when_no_foreign_keys(void){159  /* Arrange */160  Parse parse;161  memset(&parse, 0, sizeof(parse));162  parse.db = gDb;163 164  gDb->flags |= SQLITE_ForeignKeys;165 166  Table *pTab = makeTable(gDb, "no_fk", 10);167  /* No outgoing FKeys attached; incoming (parent) refs are not set in this test. */168 169  /* Act */170  u32 mask = sqlite3FkOldmask(&parse, pTab);171 172  /* Assert */173  TEST_ASSERT_EQUAL_HEX32(0, mask);174 175  /* Cleanup */176  freeTableAndFKeys(gDb, pTab);177}178 179/* Unity main */180int main(void){181  UNITY_BEGIN();182  RUN_TEST(test_sqlite3FkOldmask_returns_zero_when_foreign_keys_disabled);183  RUN_TEST(test_sqlite3FkOldmask_aggregates_mask_from_child_foreign_keys);184  RUN_TEST(test_sqlite3FkOldmask_returns_zero_when_no_foreign_keys);185  return UNITY_END();186}