Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
tests_analyze_sampleCopy.c288 linesDownload Raw Back to tests
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* The target function is static in analyze.c; a wrapper named test_sampleCopy7** is provided by the module for testing.8*/9#ifdef SQLITE_ENABLE_STAT410typedef struct StatAccum StatAccum;11typedef struct StatSample StatSample;12 13/* Duplicate the struct layouts from analyze.c so we can construct inputs.14   These must match exactly for ABI compatibility. */15struct StatSample {16  tRowcnt *anDLt;                 /* sqlite_stat4.nDLt */17#ifdef SQLITE_ENABLE_STAT418  tRowcnt *anEq;                  /* sqlite_stat4.nEq */19  tRowcnt *anLt;                  /* sqlite_stat4.nLt */20  union {21    i64 iRowid;                   /* Rowid in main table of the key */22    u8 *aRowid;                   /* Key for WITHOUT ROWID tables */23  } u;24  u32 nRowid;                     /* Sizeof aRowid[] */25  u8 isPSample;                   /* True if a periodic sample */26  int iCol;                       /* If !isPSample, the reason for inclusion */27  u32 iHash;                      /* Tiebreaker hash */28#endif29};30 31struct StatAccum {32  sqlite3 *db;              /* Database connection, for malloc() */33  tRowcnt nEst;34  tRowcnt nRow;35  int nLimit;36  int nCol;                 /* Number of columns in index + pk/rowid */37  int nKeyCol;38  u8 nSkipAhead;39  StatSample current;40#ifdef SQLITE_ENABLE_STAT441  tRowcnt nPSample;42  int mxSample;43  u32 iPrn;44  StatSample *aBest;45  int iMin;46  int nSample;47  int nMaxEqZero;48  int iGet;49  StatSample *a;50#endif51};52 53extern void test_sampleCopy(StatAccum*, StatSample*, StatSample*);54#endif /* SQLITE_ENABLE_STAT4 */55 56void setUp(void) {57  /* no-op */58}59 60void tearDown(void) {61  /* no-op */62}63 64#ifdef SQLITE_ENABLE_STAT465 66/* Helper to allocate StatSample arrays */67static void allocSampleArrays(StatSample *pS, int nCol){68  size_t n = sizeof(tRowcnt) * (size_t)nCol;69  pS->anEq = (tRowcnt*)sqlite3_malloc(n);70  pS->anLt = (tRowcnt*)sqlite3_malloc(n);71  pS->anDLt = (tRowcnt*)sqlite3_malloc(n);72  TEST_ASSERT_NOT_NULL(pS->anEq);73  TEST_ASSERT_NOT_NULL(pS->anLt);74  TEST_ASSERT_NOT_NULL(pS->anDLt);75}76 77static void freeSampleArrays(StatSample *pS){78  if( pS->anEq ) sqlite3_free(pS->anEq);79  if( pS->anLt ) sqlite3_free(pS->anLt);80  if( pS->anDLt ) sqlite3_free(pS->anDLt);81  pS->anEq = pS->anLt = pS->anDLt = 0;82}83 84/* Initialize arrays with simple patterns for verification */85static void fillArrays(StatSample *pS, int nCol, tRowcnt base){86  int i;87  for(i=0; i<nCol; i++){88    pS->anEq[i]  = base + (tRowcnt)i;89    pS->anLt[i]  = base + (tRowcnt)(100 + i);90    pS->anDLt[i] = base + (tRowcnt)(200 + i);91  }92}93 94static void assertArraysEqual(const StatSample *a, const StatSample *b, int nCol){95  TEST_ASSERT_NOT_NULL(a->anEq);96  TEST_ASSERT_NOT_NULL(a->anLt);97  TEST_ASSERT_NOT_NULL(a->anDLt);98  TEST_ASSERT_NOT_NULL(b->anEq);99  TEST_ASSERT_NOT_NULL(b->anLt);100  TEST_ASSERT_NOT_NULL(b->anDLt);101  TEST_ASSERT_EQUAL_INT(0, memcmp(a->anEq,  b->anEq,  sizeof(tRowcnt)*(size_t)nCol));102  TEST_ASSERT_EQUAL_INT(0, memcmp(a->anLt,  b->anLt,  sizeof(tRowcnt)*(size_t)nCol));103  TEST_ASSERT_EQUAL_INT(0, memcmp(a->anDLt, b->anDLt, sizeof(tRowcnt)*(size_t)nCol));104}105 106/* Test: Copy fields and arrays; deep-copy blob rowid */107void test_sampleCopy_copies_blob_rowid_and_arrays(void){108  sqlite3 *db = 0;109  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));110 111  const int nCol = 3;112  StatAccum acc;113  memset(&acc, 0, sizeof(acc));114  acc.db = db;115  acc.nCol = nCol;116 117  StatSample fromS, toS;118  memset(&fromS, 0, sizeof(fromS));119  memset(&toS, 0, sizeof(toS));120 121  allocSampleArrays(&fromS, nCol);122  allocSampleArrays(&toS, nCol);123 124  fromS.isPSample = 1;125  fromS.iCol = 2;126  fromS.iHash = 0xC0FFEE01u;127  fillArrays(&fromS, nCol, (tRowcnt)10);128 129  /* Source has a blob rowid. */130  fromS.nRowid = 4;131  fromS.u.aRowid = (u8*)sqlite3DbMallocRawNN(db, fromS.nRowid);132  TEST_ASSERT_NOT_NULL(fromS.u.aRowid);133  fromS.u.aRowid[0] = 0x11;134  fromS.u.aRowid[1] = 0x22;135  fromS.u.aRowid[2] = 0x33;136  fromS.u.aRowid[3] = 0x44;137 138  /* Destination pre-populated with different values and pre-existing blob */139  toS.isPSample = 0;140  toS.iCol = 0;141  toS.iHash = 0;142  fillArrays(&toS, nCol, (tRowcnt)0);143 144  toS.nRowid = 2;145  toS.u.aRowid = (u8*)sqlite3DbMallocRawNN(db, toS.nRowid);146  TEST_ASSERT_NOT_NULL(toS.u.aRowid);147  toS.u.aRowid[0] = 0xAA;148  toS.u.aRowid[1] = 0xBB;149 150  test_sampleCopy(&acc, &toS, &fromS);151 152  /* Verify simple fields */153  TEST_ASSERT_EQUAL_UINT8(fromS.isPSample, toS.isPSample);154  TEST_ASSERT_EQUAL_INT(fromS.iCol, toS.iCol);155  TEST_ASSERT_EQUAL_UINT32(fromS.iHash, toS.iHash);156 157  /* Verify arrays copied */158  assertArraysEqual(&fromS, &toS, nCol);159 160  /* Verify blob rowid deep copy */161  TEST_ASSERT_EQUAL_UINT(fromS.nRowid, toS.nRowid);162  TEST_ASSERT_NOT_NULL(toS.u.aRowid);163  TEST_ASSERT_NOT_EQUAL(fromS.u.aRowid, toS.u.aRowid);164  TEST_ASSERT_EQUAL_INT(0, memcmp(fromS.u.aRowid, toS.u.aRowid, fromS.nRowid));165 166  /* Cleanup */167  sqlite3DbFree(db, fromS.u.aRowid);168  sqlite3DbFree(db, toS.u.aRowid);169  freeSampleArrays(&fromS);170  freeSampleArrays(&toS);171  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_close(db));172}173 174/* Test: Copy with integer rowid; ensure destination blob rowid is replaced */175void test_sampleCopy_replaces_blob_with_int_rowid(void){176  sqlite3 *db = 0;177  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));178 179  const int nCol = 4;180  StatAccum acc;181  memset(&acc, 0, sizeof(acc));182  acc.db = db;183  acc.nCol = nCol;184 185  StatSample fromS, toS;186  memset(&fromS, 0, sizeof(fromS));187  memset(&toS, 0, sizeof(toS));188 189  allocSampleArrays(&fromS, nCol);190  allocSampleArrays(&toS, nCol);191 192  fillArrays(&fromS, nCol, (tRowcnt)50);193  fromS.isPSample = 0;194  fromS.iCol = 7;195  fromS.iHash = 0xABCDEF12u;196 197  /* Source uses integer rowid */198  fromS.nRowid = 0;199  fromS.u.iRowid = (i64)0x123456789ABCDEFiULL;200 201  /* Destination currently has a blob rowid to be replaced */202  toS.nRowid = 3;203  toS.u.aRowid = (u8*)sqlite3DbMallocRawNN(db, toS.nRowid);204  TEST_ASSERT_NOT_NULL(toS.u.aRowid);205  toS.u.aRowid[0] = 1; toS.u.aRowid[1] = 2; toS.u.aRowid[2] = 3;206 207  test_sampleCopy(&acc, &toS, &fromS);208 209  /* Verify fields and arrays copied */210  TEST_ASSERT_EQUAL_UINT8(fromS.isPSample, toS.isPSample);211  TEST_ASSERT_EQUAL_INT(fromS.iCol, toS.iCol);212  TEST_ASSERT_EQUAL_UINT32(fromS.iHash, toS.iHash);213  assertArraysEqual(&fromS, &toS, nCol);214 215  /* Verify integer rowid set on destination */216  TEST_ASSERT_EQUAL_UINT(0, toS.nRowid);217  TEST_ASSERT_EQUAL_INT64(fromS.u.iRowid, toS.u.iRowid);218 219  /* Cleanup (toS had its blob freed inside sampleCopy) */220  freeSampleArrays(&fromS);221  freeSampleArrays(&toS);222  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_close(db));223}224 225/* Test: Deep copy semantics for blob rowid - mutate source after copy */226void test_sampleCopy_deep_copy_rowid_blob_mutation_source_does_not_affect_dest(void){227  sqlite3 *db = 0;228  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_open(":memory:", &db));229 230  const int nCol = 2;231  StatAccum acc;232  memset(&acc, 0, sizeof(acc));233  acc.db = db;234  acc.nCol = nCol;235 236  StatSample fromS, toS;237  memset(&fromS, 0, sizeof(fromS));238  memset(&toS, 0, sizeof(toS));239 240  allocSampleArrays(&fromS, nCol);241  allocSampleArrays(&toS, nCol);242  fillArrays(&fromS, nCol, (tRowcnt)5);243 244  /* Source blob rowid */245  fromS.nRowid = 5;246  fromS.u.aRowid = (u8*)sqlite3DbMallocRawNN(db, fromS.nRowid);247  TEST_ASSERT_NOT_NULL(fromS.u.aRowid);248  for(int i=0;i<fromS.nRowid;i++) fromS.u.aRowid[i] = (u8)(0xA0 + i);249 250  test_sampleCopy(&acc, &toS, &fromS);251 252  /* Mutate source rowid after copy */253  for(int i=0;i<fromS.nRowid;i++) fromS.u.aRowid[i] ^= 0xFF;254 255  /* Destination should remain with original bytes */256  TEST_ASSERT_EQUAL_UINT(fromS.nRowid, toS.nRowid);257  for(int i=0;i<toS.nRowid;i++){258    TEST_ASSERT_EQUAL_HEX8((u8)(0xA0 + i), toS.u.aRowid[i]);259  }260 261  /* Cleanup */262  sqlite3DbFree(db, fromS.u.aRowid);263  sqlite3DbFree(db, toS.u.aRowid);264  freeSampleArrays(&fromS);265  freeSampleArrays(&toS);266  TEST_ASSERT_EQUAL_INT(SQLITE_OK, sqlite3_close(db));267}268 269#else /* !SQLITE_ENABLE_STAT4 */270 271/* If STAT4 is not enabled, the function under test does not exist. */272void test_sampleCopy_skipped_without_STAT4(void){273  TEST_ASSERT_TRUE(1);274}275 276#endif /* SQLITE_ENABLE_STAT4 */277 278int main(void) {279  UNITY_BEGIN();280#ifdef SQLITE_ENABLE_STAT4281  RUN_TEST(test_sampleCopy_copies_blob_rowid_and_arrays);282  RUN_TEST(test_sampleCopy_replaces_blob_with_int_rowid);283  RUN_TEST(test_sampleCopy_deep_copy_rowid_blob_mutation_source_does_not_affect_dest);284#else285  RUN_TEST(test_sampleCopy_skipped_without_STAT4);286#endif287  return UNITY_END();288}