File size: 4,233 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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "sqliteInt.h"
#include "unity.h"
#include <string.h>
#include <stdlib.h>

/* Wrapper provided in the module for the static function */
extern void test_renameColumnParseError(
  sqlite3_context *pCtx,
  const char *zWhen,
  sqlite3_value *pType,
  sqlite3_value *pObject,
  Parse *pParse
);

static void init_text_value(sqlite3 *db, Mem *pMem, const char *z){
  memset(pMem, 0, sizeof(*pMem));
  /* Initialize Mem with the database so allocations are safe */
  sqlite3VdbeMemInit(pMem, db, 0);
  /* Set as a UTF-8 string; SQLITE_STATIC since z is a literal in tests */
  sqlite3VdbeMemSetStr(pMem, z, -1, SQLITE_UTF8, SQLITE_STATIC);
}

void setUp(void) {
  /* Setup code here, or leave empty */
}

void tearDown(void) {
  /* Cleanup code here, or leave empty */
}

static void common_check_and_cleanup(
  sqlite3 *db, Mem *pType, Mem *pObj, Mem *pOut,
  const char *expected
){
  const unsigned char *zResU8 = sqlite3_value_text((sqlite3_value*)pOut);
  TEST_ASSERT_NOT_NULL(zResU8);
  TEST_ASSERT_EQUAL_STRING(expected, (const char*)zResU8);

  /* Release memory held by Mems */
  sqlite3VdbeMemRelease(pType);
  sqlite3VdbeMemRelease(pObj);
  sqlite3VdbeMemRelease(pOut);

  /* Close DB */
  sqlite3_close(db);
}

void test_renameColumnParseError_basic_no_when(void) {
  sqlite3 *db = NULL;
  int rc = sqlite3_open(":memory:", &db);
  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);

  /* Prepare input values */
  Mem typeMem, objMem, outMem;
  init_text_value(db, &typeMem, "table");
  init_text_value(db, &objMem, "t1");
  sqlite3VdbeMemInit(&outMem, db, 0);

  sqlite3_context ctx;
  memset(&ctx, 0, sizeof(ctx));
  ctx.db = db;
  ctx.pOut = &outMem;

  Parse parse;
  memset(&parse, 0, sizeof(parse));
  parse.db = db;
  parse.zErrMsg = (char*)"no such column x";

  /* Call the wrapper */
  test_renameColumnParseError(&ctx, "", (sqlite3_value*)&typeMem, (sqlite3_value*)&objMem, &parse);

  /* Validate: isError set and message formatted correctly */
  TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, ctx.isError);
  const char *expected = "error in table t1: no such column x";
  common_check_and_cleanup(db, &typeMem, &objMem, &outMem, expected);
}

void test_renameColumnParseError_with_when(void) {
  sqlite3 *db = NULL;
  int rc = sqlite3_open(":memory:", &db);
  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);

  Mem typeMem, objMem, outMem;
  init_text_value(db, &typeMem, "trigger");
  init_text_value(db, &objMem, "tr1");
  sqlite3VdbeMemInit(&outMem, db, 0);

  sqlite3_context ctx;
  memset(&ctx, 0, sizeof(ctx));
  ctx.db = db;
  ctx.pOut = &outMem;

  Parse parse;
  memset(&parse, 0, sizeof(parse));
  parse.db = db;
  parse.zErrMsg = (char*)"parse error";

  const char *zWhen = "after rename";

  test_renameColumnParseError(&ctx, zWhen, (sqlite3_value*)&typeMem, (sqlite3_value*)&objMem, &parse);

  TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, ctx.isError);
  const char *expected = "error in trigger tr1 after rename: parse error";
  common_check_and_cleanup(db, &typeMem, &objMem, &outMem, expected);
}

void test_renameColumnParseError_special_chars_and_spaces(void) {
  sqlite3 *db = NULL;
  int rc = sqlite3_open(":memory:", &db);
  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);

  Mem typeMem, objMem, outMem;
  init_text_value(db, &typeMem, "view");
  init_text_value(db, &objMem, "my view");
  sqlite3VdbeMemInit(&outMem, db, 0);

  sqlite3_context ctx;
  memset(&ctx, 0, sizeof(ctx));
  ctx.db = db;
  ctx.pOut = &outMem;

  Parse parse;
  memset(&parse, 0, sizeof(parse));
  parse.db = db;
  /* Include characters that could interfere if not handled (%, :, quotes) */
  parse.zErrMsg = (char*)"bad token % at position: 3 in \"SELECT\"";

  const char *zWhen = "on line 1";

  test_renameColumnParseError(&ctx, zWhen, (sqlite3_value*)&typeMem, (sqlite3_value*)&objMem, &parse);

  TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, ctx.isError);
  const char *expected = "error in view my view on line 1: bad token % at position: 3 in \"SELECT\"";
  common_check_and_cleanup(db, &typeMem, &objMem, &outMem, expected);
}

int main(void) {
  UNITY_BEGIN();
  RUN_TEST(test_renameColumnParseError_basic_no_when);
  RUN_TEST(test_renameColumnParseError_with_when);
  RUN_TEST(test_renameColumnParseError_special_chars_and_spaces);
  return UNITY_END();
}