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