OpenDNSSEC-enforcer  1.4.10
test_database.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008-2009 Nominet UK. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26 
27 /*+
28  * test_database.c - Test Database Functions
29  *
30  * Description:
31  * Tests the various database functions.
32  *
33  * There are no separate tests for connection and disconnection; of
34  * necessity, the tests must connect to the database in order to run.
35  *
36  * N.B. The various environment variables to control database access must
37  * be set before running this code - see "test_routines_database" for
38  * details.
39 -*/
40 
41 #include <stdlib.h>
42 
43 #include "CUnit/Basic.h"
44 
45 #include "ksm/database.h"
46 #include "ksm/database_statement.h"
47 #include "test_routines.h"
48 
49 
50 /*+
51  * TestDbExecuteSql - Check Execution of SQL
52  *
53  * Description:
54  * Executes an SQL statement but does not attempt to do anything else.
55  * This just checks that the basic connection and execution is OK.
56 -*/
57 
58 static void TestDbExecuteSql(void)
59 {
60  DB_RESULT result; /* Result object */
61  char* sql; /* Constructed query */
62  int status; /* Status return */
63 
64  sql = DqsCountInit("TEST_BASIC");
65  DqsEnd(&sql);
66  status = DbExecuteSql(DbHandle(), sql, &result);
67  CU_ASSERT_EQUAL(status, 0);
68  DqsFree(sql);
69 
70  DbFreeResult(result);
71 
72  return;
73 }
74 
75 
76 /*+
77  * TestDatabaseAccess - Check Functions in database_access.c
78  *
79  * Description:
80  * Executes an SQL query statement and accesses the result. This
81  * checks more or less all the functions in database_access.c
82 -*/
83 
84 static void TestDatabaseAccess(void)
85 {
86  DB_RESULT result; /* Result object */
87  DB_ROW row; /* Row object */
88  char* sql; /* Constructed query */
89  int status; /* Status return */
90  char* string; /* String from the row */
91 
92  sql = DqsInit("TEST_BASIC");
93  DqsOrderBy(&sql, "SVALUE");
94  DqsEnd(&sql);
95  status = DbExecuteSql(DbHandle(), sql, &result);
96  CU_ASSERT_EQUAL(status, 0);
97  DqsFree(sql);
98 
99  /*
100  * Fetch each row and check the SVALUE field:
101  *
102  * The first fetch checks that the function copes with a NULL field.
103  */
104 
105  status = DbFetchRow(result, &row);
106  CU_ASSERT_EQUAL(status, 0);
107  status = DbString(row, 2, &string);
108  CU_ASSERT_EQUAL(status, 0);
109  CU_ASSERT_PTR_NULL(string);
110  DbFreeRow(row);
111 
112  /* Second row */
113 
114  status = DbFetchRow(result, &row);
115  CU_ASSERT_EQUAL(status, 0);
116  status = DbString(row, 2, &string);
117  CU_ASSERT_EQUAL(status, 0);
118  CU_ASSERT_STRING_EQUAL(string, "ABC");
119  DbStringFree(string);
120  DbFreeRow(row);
121 
122  /* Last row */
123 
124  status = DbFetchRow(result, &row);
125  CU_ASSERT_EQUAL(status, 0);
126  status = DbString(row, 2, &string);
127  CU_ASSERT_EQUAL(status, 0);
128  CU_ASSERT_STRING_EQUAL(string, "DEF");
129  DbStringFree(string);
130  DbFreeRow(row);
131 
132  /* Fetch again should indicate end of file */
133 
134  status = DbFetchRow(result, &row);
135  CU_ASSERT_EQUAL(status, -1);
136  /* TODO put back
137  CU_ASSERT_PTR_NULL(row); */
138 
139  /* Free up the result set */
140 
141  DbFreeResult(result);
142 
143  return;
144 }
145 
146 
147 /*+
148  * TestDbExecuteSqlNoResult
149  *
150  * Description:
151  * Tests the named function by adding a row to the table, and checking
152  * that the insertion succeeded.
153 -*/
154 
155 static void TestDbExecuteSqlNoResult(void)
156 {
157  int rowcount; /* Number of rows returned */
158  char* sql; /* Constructed query */
159  int status; /* Status return */
160  int where = 0; /* WHERE clause count */
161 
162  sql = DisInit("TEST_BASIC");
163  DisAppendInt(&sql, 400);
164  DisAppendString(&sql, "GHI");
165  DisAppendString(&sql, NULL);
166  DisEnd(&sql);
167  status = DbExecuteSqlNoResult(DbHandle(), sql);
168  CU_ASSERT_EQUAL(status, 0);
169  DisFree(sql);
170 
171  /* Check that our row got into the table */
172 
173  sql = DqsCountInit("TEST_BASIC");
174  DqsConditionInt(&sql, "IVALUE", DQS_COMPARE_EQ, 400, where++);
175  DqsEnd(&sql);
176  status = DbIntQuery(DbHandle(), &rowcount, sql);
177  CU_ASSERT_EQUAL(status, 0);
178  DqsFree(sql);
179 
180  CU_ASSERT_EQUAL(rowcount, 1);
181 
182  return;
183 }
184 
185 
186 /*+
187  * TestDbIntQuery - Check Integer Query
188  *
189  * Description:
190  * Extracts a row from the database and extracts an integer field from it.
191  * This test also checks DbInt().
192 -*/
193 
194 static void TestDbIntQuery(void)
195 {
196  int rowcount; /* Number of rows returned */
197  char* sql; /* Constructed query */
198  int status; /* Status return */
199  int where = 0; /* WHERE clause count */
200 
201  /* Check that only one row has IVALUE = 200 */
202 
203  sql = DqsCountInit("TEST_BASIC");
204  DqsConditionInt(&sql, "IVALUE", DQS_COMPARE_EQ, 200, where++);
205  DqsEnd(&sql);
206  status = DbIntQuery(DbHandle(), &rowcount, sql);
207  DqsFree(sql);
208 
209  CU_ASSERT_EQUAL(status, 0);
210 
211  CU_ASSERT_EQUAL(rowcount, 1);
212 
213  return;
214 }
215 
216 
217 /*+
218  * TestDbStringBuffer
219  *
220  * Description:
221  * Tests DbStringBuffer by getting a known value into a user buffer.
222 -*/
223 
224 static void TestDbStringBuffer(void)
225 {
226  char buffer[128]; /* User buffer */
227  DB_RESULT result; /* Result object */
228  DB_ROW row; /* Row object */
229  char* sql; /* Constructed query */
230  int status; /* Status return */
231  int where = 0; /* WHERE clause index */
232 
233  sql = DqsInit("TEST_BASIC");
234  DqsConditionString(&sql, "SVALUE", DQS_COMPARE_EQ, "ABC", where++);
235  DqsEnd(&sql);
236  status = DbExecuteSql(DbHandle(), sql, &result);
237  CU_ASSERT_EQUAL(status, 0);
238  DqsFree(sql);
239 
240  /* Fetch the only row and get the value from the SVALUE field */
241 
242  status = DbFetchRow(result, &row);
243  CU_ASSERT_EQUAL(status, 0);
244  status = DbStringBuffer(row, 2, buffer, sizeof(buffer));
245  CU_ASSERT_EQUAL(status, 0);
246  CU_ASSERT_STRING_EQUAL(buffer, "ABC");
247  DbFreeRow(row);
248 
249  /* Fetch again should indicate end of file */
250 
251  status = DbFetchRow(result, &row);
252  CU_ASSERT_EQUAL(status, -1);
253  /* TODO put back
254  CU_ASSERT_PTR_NULL(row); */
255 
256  /* Tidy up */
257 
258  DbFreeResult(result);
259 
260  return;
261 }
262 
263 
264 /*+
265  * TestDbLastRowId - Check last Row ID
266  *
267  * Description:
268  * Inserts two rows and checks that the row IDs differ by one. Doing the
269  * test this way does not assume anything about what is currently in the
270  * database.
271 -*/
272 
273 static void TestDbLastRowId(void)
274 {
275  DB_ID first_id = 0; /* ID of first insertion */
276  DB_ID second_id = 0; /* ID of second insertion */
277  char* sql = NULL; /* SQL statement */
278  int status; /* Status return */
279 
280  /* Construct the insertion statement */
281 
282  sql = DisInit("TEST_BASIC");
283  CU_ASSERT_PTR_NOT_NULL(sql);
284 
285  DisAppendInt(&sql, 500);
286  DisAppendString(&sql, "XYZZY");
287  DisAppendString(&sql, "20090101");
288  DisEnd(&sql);
289 
290  /* Insert and store row IDs */
291 
292  status = DbExecuteSqlNoResult(DbHandle(), sql);
293  CU_ASSERT_EQUAL(status, 0);
294 
295  status = DbLastRowId(DbHandle(), &first_id);
296  CU_ASSERT_EQUAL(status, 0);
297  CU_ASSERT_NOT_EQUAL(first_id, 0);
298 
299  status = DbExecuteSqlNoResult(DbHandle(), sql);
300  CU_ASSERT_EQUAL(status, 0);
301 
302  status = DbLastRowId(DbHandle(), &second_id);
303  CU_ASSERT_EQUAL(status, 0);
304  CU_ASSERT_EQUAL(second_id, (first_id + 1));
305 
306  /* ... and tidy up */
307 
308  DisFree(sql);
309 
310  return;
311 
312 }
313 
314 static void TestDbCommit(void)
315 {
316  int rowcount; /* Number of rows returned */
317  char* sql; /* Constructed query */
318  int status; /* Status return */
319  int where = 0; /* WHERE clause count */
320 
321  status = DbBeginTransaction();
322  CU_ASSERT_EQUAL(status, 0);
323 
324  sql = DisInit("TEST_BASIC");
325  DisAppendInt(&sql, 600);
326  DisAppendString(&sql, "JKL");
327  DisAppendString(&sql, NULL);
328  DisEnd(&sql);
329  status = DbExecuteSqlNoResult(DbHandle(), sql);
330  CU_ASSERT_EQUAL(status, 0);
331  DisFree(sql);
332 
333  status = DbCommit();
334  CU_ASSERT_EQUAL(status, 0);
335 
336  /* Check that our row got into the table */
337 
338  sql = DqsCountInit("TEST_BASIC");
339  DqsConditionInt(&sql, "IVALUE", DQS_COMPARE_EQ, 600, where++);
340  DqsEnd(&sql);
341  status = DbIntQuery(DbHandle(), &rowcount, sql);
342  CU_ASSERT_EQUAL(status, 0);
343  DqsFree(sql);
344 
345  CU_ASSERT_EQUAL(rowcount, 1);
346 
347  return;
348 }
349 
350 static void TestDbRollback(void)
351 {
352  int rowcount; /* Number of rows returned */
353  char* sql; /* Constructed query */
354  int status; /* Status return */
355  int where = 0; /* WHERE clause count */
356 
357  status = DbBeginTransaction();
358  CU_ASSERT_EQUAL(status, 0);
359 
360  sql = DisInit("TEST_BASIC");
361  DisAppendInt(&sql, 700);
362  DisAppendString(&sql, "MNO");
363  DisAppendString(&sql, NULL);
364  DisEnd(&sql);
365  status = DbExecuteSqlNoResult(DbHandle(), sql);
366  CU_ASSERT_EQUAL(status, 0);
367  DisFree(sql);
368 
369  /* Check that our row got into the table */
370  sql = DqsCountInit("TEST_BASIC");
371  DqsConditionInt(&sql, "IVALUE", DQS_COMPARE_EQ, 700, where++);
372  DqsEnd(&sql);
373  status = DbIntQuery(DbHandle(), &rowcount, sql);
374  CU_ASSERT_EQUAL(status, 0);
375  CU_ASSERT_EQUAL(rowcount, 1);
376 
377  /* Do the rollback */
378  status = DbRollback();
379  CU_ASSERT_EQUAL(status, 0);
380 
381  /* Check that our row has now gone */
382  status = DbIntQuery(DbHandle(), &rowcount, sql);
383  CU_ASSERT_EQUAL(status, 0);
384  CU_ASSERT_EQUAL(rowcount, 0);
385  DqsFree(sql);
386 
387  return;
388 }
389 
390 static void TestDbDateDiff(void)
391 {
392  char buffer[128];
393  char small_buffer[16];
394  char* datetime = "2010-01-01 12:00:00";
395  int deltat = 120;
396  int status = 0;
397 
398  /* One with a positive difference */
399  status = DbDateDiff(datetime, deltat, 1, buffer, 128);
400 
401  CU_ASSERT_EQUAL(status, 0);
402 
403 #ifdef USE_MYSQL
404  CU_ASSERT_STRING_EQUAL(buffer, "DATE_ADD('2010-01-01 12:00:00', INTERVAL 120 SECOND)");
405 #else
406  CU_ASSERT_STRING_EQUAL(buffer, "DATETIME('2010-01-01 12:00:00', '+120 SECONDS')");
407 #endif /* USE_MYSQL */
408 
409  /* One with a negative difference */
410  status = DbDateDiff(datetime, deltat, -1, buffer, 128);
411 
412  CU_ASSERT_EQUAL(status, 0);
413 
414 #ifdef USE_MYSQL
415  CU_ASSERT_STRING_EQUAL(buffer, "DATE_ADD('2010-01-01 12:00:00', INTERVAL -120 SECOND)");
416 #else
417  CU_ASSERT_STRING_EQUAL(buffer, "DATETIME('2010-01-01 12:00:00', '-120 SECONDS')");
418 #endif /* USE_MYSQL */
419 
420  /* One that fails because the buffer is too small */
421  status = DbDateDiff(datetime, deltat, 1, small_buffer, 16);
422 
423  CU_ASSERT_EQUAL(status, 1);
424 
425  return;
426 }
427 
428 /*+
429  * TestDdb - Create Test Suite
430  *
431  * Description:
432  * Adds the test suite to the CUnit test registry and adds all the tests
433  * to it.
434  *
435  * Arguments:
436  * None.
437  *
438  * Returns:
439  * int
440  * Return status. 0 => Success.
441  */
442 
443 int TestDb(void); /* Declaration */
444 int TestDb(void)
445 {
446  struct test_testdef tests[] = {
447  {"TestDbExecuteSql", TestDbExecuteSql},
448  {"TestDatabaseAccess", TestDatabaseAccess},
449  {"TestDbExecuteSqlNoResult", TestDbExecuteSqlNoResult},
450  {"TestDbIntQuery", TestDbIntQuery},
451  {"TestDbStringBuffer", TestDbStringBuffer},
452  {"TestDbLastRowId", TestDbLastRowId},
453  {"TestDbCommit", TestDbCommit},
454  {"TestDbRollback", TestDbRollback},
455  {"TestDbDateDiff", TestDbDateDiff},
456  {NULL, NULL}
457  };
458 
459  return TcuCreateSuite("Db", TdbSetup, TdbTeardown, tests);
460 }
void DbFreeResult(DB_RESULT result)
int DbRollback(void)
int DbFetchRow(DB_RESULT result, DB_ROW *row)
int TcuCreateSuite(const char *title, int(*init)(), int(*teardown)(), struct test_testdef *tests)
int TestDb(void)
void DqsOrderBy(char **query, const char *field)
Definition: dq_string.c:277
void DqsFree(char *query)
Definition: dq_string.c:320
char * DqsCountInit(const char *table)
Definition: dq_string.c:90
DB_HANDLE DbHandle(void)
int DbString(DB_ROW row, int field_index, char **result)
void DqsConditionInt(char **query, const char *field, DQS_COMPARISON compare, int value, int index)
Definition: dq_string.c:224
int DbCommit(void)
int DbLastRowId(DB_HANDLE handle, DB_ID *id)
unsigned long DB_ID
Definition: database.h:78
void DisAppendString(char **sql, const char *what)
Definition: di_string.c:142
void DbFreeRow(DB_ROW row)
int DbExecuteSql(DB_HANDLE handle, const char *stmt_str, DB_RESULT *result)
void DisEnd(char **sql)
Definition: di_string.c:170
int DbStringBuffer(DB_ROW row, int field_index, char *buffer, size_t buflen)
int DbIntQuery(DB_HANDLE handle, int *value, const char *query)
int TdbTeardown(void)
int DbDateDiff(const char *start, int delta, int sign, char *buffer, size_t buflen)
char * DqsInit(const char *table)
Definition: dq_string.c:61
void DisFree(char *sql)
Definition: di_string.c:191
int TdbSetup(void)
char * DisInit(const char *table)
Definition: di_string.c:65
void DisAppendInt(char **sql, int what)
Definition: di_string.c:131
void DqsEnd(char **query)
Definition: dq_string.c:299
int DbBeginTransaction(void)
int DbExecuteSqlNoResult(DB_HANDLE handle, const char *stmt_str)
void DqsConditionString(char **query, const char *field, DQS_COMPARISON compare, const char *value, int index)
Definition: dq_string.c:238
void DbStringFree(char *string)