File size: 3,403 Bytes
7510827
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include "sqliteInt.h"
#include "unity.h"
#include <stdlib.h>
#include <string.h>

static sqlite3 *gDb = NULL;

static FuncDef* mustFindFunc(const char *zName, int nArg){
  FuncDef *pDef = sqlite3FindFunction(gDb, zName, nArg, SQLITE_UTF8, 0);
  TEST_ASSERT_MESSAGE(pDef != NULL, "Expected function not found");
  TEST_ASSERT_EQUAL_INT_MESSAGE(nArg, pDef->nArg, "Function arity mismatch");
  return pDef;
}

void setUp(void) {
  int rc;
  /* Ensure the ALTER functions are registered before a connection is opened */
  sqlite3AlterFunctions();
  rc = sqlite3_open(":memory:", &gDb);
  TEST_ASSERT_EQUAL_INT_MESSAGE(SQLITE_OK, rc, "sqlite3_open failed");
}

void tearDown(void) {
  if( gDb ){
    sqlite3_close(gDb);
    gDb = NULL;
  }
}

void test_sqlite3AlterFunctions_registers_all_expected_functions(void){
  struct {
    const char *zName;
    int nArg;
  } aFuncs[] = {
    { "sqlite_rename_column",     9 },
    { "sqlite_rename_table",      7 },
    { "sqlite_rename_test",       7 },
    { "sqlite_drop_column",       3 },
    { "sqlite_rename_quotefix",   2 },
    { "sqlite_drop_constraint",   2 },
    { "sqlite_fail",              2 },
    { "sqlite_add_constraint",    3 },
    { "sqlite_find_constraint",   2 },
  };
  for(size_t i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
    FuncDef *pDef = mustFindFunc(aFuncs[i].zName, aFuncs[i].nArg);
    /* Internal functions should be flagged as such and should have an xSFunc */
    TEST_ASSERT_MESSAGE((pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0,
                        "Function not flagged as internal");
    TEST_ASSERT_MESSAGE(pDef->xSFunc != NULL, "xSFunc should be non-NULL for internal scalar");
  }
}

void test_sqlite3AlterFunctions_case_insensitive_lookup(void){
  FuncDef *p1 = sqlite3FindFunction(gDb, "SQLITE_RENAME_TABLE", 7, SQLITE_UTF8, 0);
  TEST_ASSERT_NOT_NULL(p1);
  TEST_ASSERT_EQUAL_INT(7, p1->nArg);
  TEST_ASSERT_TRUE((p1->funcFlags & SQLITE_FUNC_INTERNAL)!=0);
}

void test_sqlite3AlterFunctions_wrong_arity_returns_null(void){
  /* These internal functions have fixed arity; wrong arity should not resolve */
  FuncDef *pBad1 = sqlite3FindFunction(gDb, "sqlite_rename_table", 6, SQLITE_UTF8, 0);
  FuncDef *pBad2 = sqlite3FindFunction(gDb, "sqlite_drop_column", 2, SQLITE_UTF8, 0);
  TEST_ASSERT_NULL(pBad1);
  TEST_ASSERT_NULL(pBad2);
}

void test_sqlite3AlterFunctions_idempotent_registration(void){
  /* Call the registrar again; lookups must still succeed */
  sqlite3AlterFunctions();

  FuncDef *p1 = sqlite3FindFunction(gDb, "sqlite_add_constraint", 3, SQLITE_UTF8, 0);
  TEST_ASSERT_NOT_NULL(p1);
  TEST_ASSERT_TRUE((p1->funcFlags & SQLITE_FUNC_INTERNAL)!=0);

  FuncDef *p2 = sqlite3FindFunction(gDb, "sqlite_find_constraint", 2, SQLITE_UTF8, 0);
  TEST_ASSERT_NOT_NULL(p2);
  TEST_ASSERT_TRUE((p2->funcFlags & SQLITE_FUNC_INTERNAL)!=0);
}

void test_sqlite3AlterFunctions_unknown_function_not_found(void){
  FuncDef *p = sqlite3FindFunction(gDb, "sqlite_nonexistent", 1, SQLITE_UTF8, 0);
  TEST_ASSERT_NULL(p);
}

int main(void) {
  UNITY_BEGIN();
  RUN_TEST(test_sqlite3AlterFunctions_registers_all_expected_functions);
  RUN_TEST(test_sqlite3AlterFunctions_case_insensitive_lookup);
  RUN_TEST(test_sqlite3AlterFunctions_wrong_arity_returns_null);
  RUN_TEST(test_sqlite3AlterFunctions_idempotent_registration);
  RUN_TEST(test_sqlite3AlterFunctions_unknown_function_not_found);
  return UNITY_END();
}