FOSSology  4.4.0
Open Source License Compliance by Open Source Software
test_libfossdbmanager.c
1 /*
2  Author: Daniele Fognini
3  SPDX-FileCopyrightText: © 2014 Siemens AG
4 
5  SPDX-License-Identifier: GPL-2.0-only
6 */
7 
8 #include <libfossdbmanager.h>
9 
10 /* library includes */
11 #include <string.h>
12 #include <stdio.h>
13 #include <unistd.h>
14 #include <glib.h>
15 #include <libfossdb.h>
16 #include <fcntl.h>
17 #include <sys/stat.h>
18 
19 /* cunit includes */
20 #include <CUnit/CUnit.h>
21 
22 #define TESTABLE2(x, y) x "line" #y "_run"
23 #define TESTABLE1(s, i) TESTABLE2(s,i)
24 #define TESTTABLE TESTABLE1("test_db_manager_",__LINE__)
25 
26 extern char* dbConf;
27 
28 /* <0 unable to perform check
29  * 0 does not exists
30  * >0 exists
31  */
32 int _tableExists(fo_dbManager* dbManager, char* tableName)
33 {
34  PGresult* result = fo_dbManager_Exec_printf(
35  dbManager,
36  "SELECT EXISTS("
37  " SELECT * "
38  " FROM information_schema.tables "
39  " WHERE "
40  " table_name = '%s'"
41  ")",
42  tableName
43  );
44 
45  if (!result)
46  return -1;
47 
48  if (PQntuples(result) == 0)
49  {
50  PQclear(result);
51  return -1;
52  } else
53  {
54  int exists = (strcmp("t", PQgetvalue(result, 0, 0)) == 0);
55  PQclear(result);
56  return exists ? 1 : 0;
57  }
58 }
59 
60 int _assertFileLines(const char* fileName, const char* expectedContent, int id)
61 {
62  int result = 0;
63  int fd = open(fileName, O_RDONLY);
64  if (fd)
65  {
66  char buffer[2048];
67  ssize_t n = read(fd, buffer, sizeof(buffer) - 1);
68  if (n >= 0)
69  {
70  buffer[n] = '\0';
71  int patternMatch = g_pattern_match_simple(expectedContent, buffer);
72  CU_ASSERT_TRUE(patternMatch);
73 #define SEP "\n------------------------\n"
74  if (!patternMatch)
75  {
76  printf("error expecting log matching" SEP "%s" SEP "in file: '%s' for test #%d\n", expectedContent, fileName, id);
77  printf(SEP "got" SEP "%.*s" SEP, MIN((int) sizeof(buffer), (int) n), buffer);
78  } else
79  {
80  result = 1;
81  }
82 #undef SEP
83  } else
84  {
85  CU_FAIL("can not read file");
86  printf("can not read '%s'\n", fileName);
87  }
88  close(fd);
89  } else
90  {
91  CU_FAIL("can not open file");
92  printf("can not read '%s'\n", fileName);
93  }
94  return result;
95 }
96 
97 void _setLogFileForTest(fo_dbManager* dbManager, char* logFile)
98 {
99  int logFd = open(logFile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
100  if (logFd > 0)
101  {
102  close(logFd);
103  fo_dbManager_setLogFile(dbManager, logFile);
104  } else
105  {
106  CU_FAIL("could not truncate logFile, can not test log output");
107  }
108 }
109 
110 int _getTestTable(fo_dbManager* dbManager, char** resultTableName, const char* columns)
111 {
112  char* result = NULL;
113  int i = 0;
114  while ((!result) && (i < 100))
115  {
116  result = g_strdup_printf("%s_%d", *resultTableName, i++);
117  int tableExists = _tableExists(dbManager, result);
118  if (tableExists < 0)
119  {
120  g_free(result);
121  return 0;
122  } else if (tableExists > 0)
123  {
124  g_free(result);
125  result = NULL;
126  }
127  }
128  if (result)
129  {
130  PGresult* createResult = fo_dbManager_Exec_printf(
131  dbManager, "CREATE TABLE %s (%s)", result, columns);
132  if (createResult)
133  {
134  PQclear(createResult);
135  *resultTableName = result;
136  return 1;
137  } else
138  {
139  g_free(result);
140  return 0;
141  }
142  } else
143  {
144  return 0;
145  }
146 }
147 
148 void test_prepare()
149 {
150  PGconn* pgConn;
151  char* ErrorBuf;
152 
153  pgConn = fo_dbconnect(dbConf, &ErrorBuf);
155 
156  char* testTableName = TESTTABLE;
157  if (_getTestTable(dbManager, &testTableName, "a int, b bigint, c varchar"))
158  {
159 #define COUNT 3
160  fo_dbManager_PreparedStatement* first = NULL;
161  char* queryInsert = g_strdup_printf(
162  "INSERT INTO %s (a,b,c) VALUES($1,$2,$3)", testTableName);
163  char* querySelect = g_strdup_printf(
164  "SELECT a,b,c FROM %s WHERE a = $1 AND b = $2 AND c = $3", testTableName);
165 
166  CU_ASSERT_TRUE(COUNT > 1);
167  int j;
168  for (j = 0; j < COUNT; j++)
169  {
170 #undef COUNT
171  fo_dbManager_PreparedStatement* stmtInsert = fo_dbManager_PrepareStamement(
172  dbManager,
173  "testprepare:insert",
174  queryInsert,
175  int, long, char*
176  );
177  /* check that prepared statements are cached inside dbManager */
178  if (!first)
179  {
180  first = stmtInsert;
181  } else
182  {
183  CU_ASSERT_EQUAL(first, stmtInsert);
184  }
185 
186  CU_ASSERT_STRING_EQUAL(fo_dbManager_printStatement(stmtInsert),
187  "{ name: 'testprepare:insert', parameterTypes: [[0]={int, %d}, [1]={long, %ld}, [2]={char*, %s}]}");
188 
189  fo_dbManager_PreparedStatement* stmtSelect = fo_dbManager_PrepareStamement(
190  dbManager,
191  "testprepare:select",
192  querySelect,
193  int, long, char*
194  );
195 
196  CU_ASSERT_STRING_EQUAL(fo_dbManager_printStatement(stmtSelect),
197  "{ name: 'testprepare:select', parameterTypes: [[0]={int, %d}, [1]={long, %ld}, [2]={char*, %s}]}");
198 
199  int a = j;
200  long b = j * 4;
201  char* c = g_strdup_printf("f%d", j);
202  PGresult* insert = fo_dbManager_ExecPrepared(stmtInsert, a, b, c);
203  if (insert)
204  {
205  PGresult* result = fo_dbManager_ExecPrepared(stmtSelect, a, b, c);
206  if (result)
207  {
208  CU_ASSERT_EQUAL_FATAL(PQntuples(result), 1);
209  CU_ASSERT_EQUAL(atoi(PQgetvalue(result, 0, 0)), a);
210  CU_ASSERT_EQUAL(atol(PQgetvalue(result, 0, 1)), b);
211  CU_ASSERT_STRING_EQUAL(PQgetvalue(result, 0, 2), c);
212 
213  PQclear(result);
214  } else
215  {
216  CU_FAIL("select failed");
217  }
218  PQclear(insert);
219  } else
220  {
221  CU_FAIL("insert failed");
222  }
223  g_free(c);
224  }
225  g_free(querySelect);
226  g_free(queryInsert);
227 
228  fo_dbManager_Exec_printf(dbManager,
229  "DROP TABLE %s",
230  testTableName
231  );
232  } else
233  {
234  CU_FAIL("could not get test table");
235  }
236 
238  PQfinish(pgConn);
239 }
240 
241 PGresult* _insertPrepared(fo_dbManager* dbManager, char* queryInsert, void** data, int a, long b)
242 {
243  fo_dbManager_PreparedStatement* stmtInsert = fo_dbManager_PrepareStamement(
244  dbManager,
245  "testprepare:insertPerf",
246  queryInsert,
247  int, long
248  );
249  return fo_dbManager_ExecPrepared(stmtInsert, a, b);
250 }
251 
252 PGresult* _insertPreparedCached(fo_dbManager* dbManager, char* queryInsert, void** data, int a, long b)
253 {
254  if (*data)
255  {
256  return fo_dbManager_ExecPrepared(*data, a, b);
257  } else
258  {
259  fo_dbManager_PreparedStatement* stmtInsert = fo_dbManager_PrepareStamement(
260  dbManager,
261  "testprepare:insertPerfCached",
262  queryInsert,
263  int, long
264  );
265  *data = stmtInsert;
266  return fo_dbManager_ExecPrepared(stmtInsert, a, b);
267  }
268 }
269 
270 PGresult* _insertPrintf(fo_dbManager* dbManager, char* queryInsert, void** data, int a, long b)
271 {
272  return fo_dbManager_Exec_printf(
273  dbManager,
274  queryInsert,
275  a, b
276  );
277 }
278 
279 PGresult* _insertWithFunction(
280  PGresult* (* insertFunction)(fo_dbManager*, char*, void**, int, long),
282  char* queryInsert,
283  char* testTableName,
284  int count)
285 {
286 
287  char* testTableNameVar = g_strdup(testTableName);
288 
289  PGresult* result = NULL;
290  if (_getTestTable(dbManager, &testTableNameVar, "a int, b bigint, c timestamp DEFAULT CURRENT_TIMESTAMP"))
291  {
292  char* queryInsertWithTable = g_strdup_printf(queryInsert, testTableNameVar);
293  void* data = NULL;
294 
295  int j;
296  for (j = 0; j < count; j++)
297  {
298  int a = j;
299  long b = j * 4;
300  PGresult* insert = (*insertFunction)(dbManager, queryInsertWithTable, &data, a, b);
301  if (insert)
302  {
303  PQclear(insert);
304  } else
305  {
306  CU_FAIL("insert failed");
307  break;
308  }
309  }
310 
311  result = fo_dbManager_Exec_printf(
312  dbManager,
313  "SELECT MAX(c) - MIN(c) FROM %s", testTableNameVar);
314 
315  fo_dbManager_Exec_printf(dbManager,
316  "DROP TABLE %s",
317  testTableNameVar
318  );
319  } else
320  {
321  CU_FAIL("could not get test table");
322  }
323 
324  g_free(testTableNameVar);
325 
326  return result;
327 }
328 
329 void test_perf()
330 {
331  PGconn* pgConn;
332  char* ErrorBuf;
333 
334  pgConn = fo_dbconnect(dbConf, &ErrorBuf);
335  fo_dbManager* dbManager1 = fo_dbManager_new(pgConn);
336  fo_dbManager* dbManager2 = fo_dbManager_new(pgConn);
337  fo_dbManager* dbManager3 = fo_dbManager_new(pgConn);
338 
339 
340  char* testTableNamePrepared = TESTTABLE;
341  char* testTableNamePreparedCached = TESTTABLE;
342  char* testTableNamePrintf = TESTTABLE;
343 
344  char* queryInsertPrepared = "INSERT INTO %s (a,b) VALUES($1,$2)";
345  char* queryInsertPrintf = "INSERT INTO %s (a,b) VALUES(%d,%ld)";
346 
347  int i;
348  for (i = 0; i < 21; i++)
349  {
350  PGresult* (* insertFunction)(fo_dbManager* dbManager, char* queryInsert, void** data, int a, long b);
351  char* testTableName;
352  char* queryInsert;
353  int count = 500 + 500 * (i / 3) * (i / 3);
354  char* name;
356  switch (i % 3)
357  {
358  case 1:
359  insertFunction = _insertPrepared;
360  testTableName = testTableNamePrepared;
361  queryInsert = queryInsertPrepared;
362  name = "prepared";
363  dbManager = dbManager1;
364  break;
365  case 2:
366  insertFunction = _insertPreparedCached;
367  testTableName = testTableNamePreparedCached;
368  queryInsert = queryInsertPrepared;
369  name = "prepared (ext.cache)";
370  dbManager = dbManager2;
371  break;
372  default:
373  insertFunction = _insertPrintf;
374  testTableName = testTableNamePrintf;
375  queryInsert = queryInsertPrintf;
376  name = "static";
377  dbManager = dbManager3;
378  }
379  if (i % 3 == 0)
380  {
381  printf("timing inserts: %d\t", count);
382  }
383  printf("%s: ", name);
384 
385  PGresult* timeResult = _insertWithFunction(insertFunction, dbManager, queryInsert, testTableName, count);
386 
387  if (timeResult)
388  {
389  if (PQntuples(timeResult) > 0)
390  {
391  printf("%s", PQgetvalue(timeResult, 0, 0));
392  } else
393  {
394  CU_FAIL("error in querying timings");
395  }
396  PQclear(timeResult);
397  } else
398  {
399  CU_FAIL("error in querying timings");
400  }
401  if (i % 3 == 2)
402  printf("\n");
403  else
404  printf("\t");
405  }
406 
407  fo_dbManager_free(dbManager1);
408  fo_dbManager_free(dbManager2);
409  fo_dbManager_free(dbManager3);
410  PQfinish(pgConn);
411 }
412 
413 void test_simple_inject()
414 {
415  PGconn* pgConn;
416  char* ErrorBuf;
417 
418  pgConn = fo_dbconnect(dbConf, &ErrorBuf);
420 
421  char* testTableName = TESTTABLE;
422  if (_getTestTable(dbManager, &testTableName, "a int, b bigint, c varchar"))
423  {
424  int a = 0;
425  long b = 1;
426  char* attemptInject = g_strdup_printf(
427  "a'; INSERT INTO %s (a,b,c) VALUES (42,0,'2",
428  testTableName
429  );
430 
431  char* escaped = fo_dbManager_StringEscape(dbManager, attemptInject);
432  PGresult* insert = fo_dbManager_Exec_printf(dbManager,
433  "INSERT INTO %s (a,b,c) VALUES (%d,%ld,'%s')",
434  testTableName,
435  a, b, escaped
436  );
437  g_free(escaped);
438 
439  if (insert)
440  {
441 
442  PGresult* select = fo_dbManager_Exec_printf(dbManager,
443  "SELECT c FROM %s",
444  testTableName
445  );
446  if (select)
447  {
448  int count = PQntuples(select);
449  switch (count)
450  {
451  case 0:
452  CU_FAIL("no result, but 1 expected");
453  break;
454  case 1:
455  CU_ASSERT_EQUAL(
456  0,
457  strncmp(
458  "a'; INSERT INTO",
459  PQgetvalue(select, 0, 0),
460  strlen("a'; INSERT INTO")
461  )
462  );
463  break;
464  default:
465  CU_FAIL("could sql inject");
466  }
467 
468  PQclear(select);
469  } else
470  {
471  CU_FAIL("could not select");
472  }
473 
474  PQclear(insert);
475  } else
476  {
477  CU_FAIL("could not insert valid values");
478  }
479 
480  fo_dbManager_Exec_printf(dbManager,
481  "DROP TABLE %s",
482  testTableName
483  );
484  } else
485  {
486  CU_FAIL("could not get test table");
487  }
488 
490  PQfinish(pgConn);
491 }
492 
493 void test_fork_error()
494 {
495  fo_dbManager* dbManager = fo_dbManager_new_withConf(NULL, "not a file.conf");
496  char* logFile = "/tmp/" TESTTABLE;
497  _setLogFileForTest(dbManager, logFile);
498 
499  fo_dbManager_fork(dbManager);
500 
502 
503  _assertFileLines(
504  logFile,
505  "FATAL: Can not open connection\n"
506  "Database conf file: not a file.conf, No such file or directory\n"
507  "While forking dbManager using config: 'not a file.conf'\n",
508  0
509  );
510 }
511 
512 void test_fork()
513 {
514  PGconn* pgConn;
515  char* ErrorBuf;
516 
517  pgConn = fo_dbconnect(dbConf, &ErrorBuf);
518  fo_dbManager* dbManager0 = fo_dbManager_new_withConf(pgConn, dbConf);
519 
520  char* testTableName = TESTTABLE;
521  if (_getTestTable(dbManager0, &testTableName, "a int, b bigint, c varchar"))
522  {
523  fo_dbManager* dbManager1 = fo_dbManager_fork(dbManager0);
524 
525  CU_ASSERT_NOT_EQUAL(dbManager0, dbManager1);
526  CU_ASSERT_PTR_NOT_NULL(fo_dbManager_getWrappedConnection(dbManager1));
527  CU_ASSERT_NOT_EQUAL(fo_dbManager_getWrappedConnection(dbManager0),
528  fo_dbManager_getWrappedConnection(dbManager1));
529 
530  char* queryInsert = g_strdup_printf(
531  "INSERT INTO %s (a,b,c) VALUES($1,$2,$3)", testTableName);
532 
533  fo_dbManager_PreparedStatement* stmtInsert0 = fo_dbManager_PrepareStamement(
534  dbManager0,
535  "testfork",
536  queryInsert,
537  int, long, char*
538  );
539 
540  if (dbManager1)
541  {
542  fo_dbManager_PreparedStatement* stmtInsert1 = fo_dbManager_PrepareStamement(
543  dbManager1,
544  "testfork",
545  queryInsert,
546  int, long, char*
547  );
548  CU_ASSERT_PTR_NOT_NULL(stmtInsert1);
549  CU_ASSERT_NOT_EQUAL(stmtInsert0, stmtInsert1);
550 
551  int a = 1;
552  long b = 2;
553  char* c = "a";
554  CU_ASSERT_PTR_NOT_NULL(fo_dbManager_ExecPrepared(
555  stmtInsert0,
556  a, b, c
557  ));
558  CU_ASSERT_PTR_NOT_NULL(fo_dbManager_ExecPrepared(
559  stmtInsert1,
560  a + 1, b, c
561  ));
562 
563  PQfinish(fo_dbManager_getWrappedConnection(dbManager1));
564  fo_dbManager_free(dbManager1);
565  } else
566  {
567  CU_FAIL("coud not fork dbManager");
568  }
569  fo_dbManager_Exec_printf(dbManager0,
570  "DROP TABLE %s",
571  testTableName
572  );
573  } else
574  {
575  CU_FAIL("could not get test table");
576  }
577 
578  fo_dbManager_free(dbManager0);
579  PQfinish(pgConn);
580 }
581 
582 void _test_wrongQueries_runner(char* (* test)(fo_dbManager**, const char*), int testNumber)
583 {
584  PGconn* pgConn;
585  char* ErrorBuf;
586 
587  pgConn = fo_dbconnect(dbConf, &ErrorBuf);
588  fo_dbManager* dbManager = fo_dbManager_new_withConf(pgConn, dbConf);
589 
590  char* testTable = g_strdup_printf(TESTTABLE "runner_%d", testNumber);
591  int gotTable = _getTestTable(dbManager, &testTable, "a int, b bigint");
592 
593  if (gotTable)
594  {
595  fo_dbManager* dbManagerTest = fo_dbManager_fork(dbManager);
596  char* logFile = g_strdup_printf("./%s.log", testTable);
597  _setLogFileForTest(dbManagerTest, logFile);
598 
599  char* expectedLog = (*test)(&dbManagerTest, testTable);
600 
601  if (dbManagerTest)
602  fo_dbManager_finish(dbManagerTest);
603 
604  if (_assertFileLines(logFile, expectedLog, testNumber))
605  {
606  fo_dbManager_Exec_printf(dbManager, "DROP TABLE %s", testTable);
607  unlink(logFile);
608  }
609 
610  fo_dbManager_finish(dbManager);
611 
612  g_free(logFile);
613  g_free(expectedLog);
614  g_free(testTable);
615 
616  } else
617  {
618  CU_FAIL("could not get test table");
619  printf("could not get test table" " for test %d\n", testNumber);
620  fo_dbManager_finish(dbManager);
621  }
622 }
623 
624 char* _test_wrongQueries_SyntaxError0(fo_dbManager** dbManager, const char* testTableName)
625 {
626  CU_ASSERT_PTR_NULL(fo_dbManager_Exec_printf(*dbManager,
627  "CREATE TABLE 's' (id integer, 's' integer"));
628 
629  return g_strdup(
630  "ERROR: * syntax error at or near \"'s'\"\n"
631  "* CREATE TABLE 's' (id integer, 's' integer\n"
632  "*^\n"
633  "On: CREATE TABLE 's' (id integer, 's' integer\n"
634  );
635 }
636 
637 
638 char* _test_wrongQueries_SyntaxError(fo_dbManager** dbManager, const char* testTableName)
639 {
640  CU_ASSERT_PTR_NULL(fo_dbManager_Exec_printf(*dbManager,
641  "INSERT INTO wrong (id,'%s') VALUES (%d,5)",
642  "value",
643  6));
644 
645  return g_strdup(
646  "ERROR: * syntax error at or near \"'value'\"\n"
647  "* INSERT INTO wrong (id,'value') VALUES (6,5)\n"
648  "*^\n"
649  "On: INSERT INTO wrong (id,'value') VALUES (6,5)\n"
650  );
651 }
652 
653 char* _test_wrongQueries_noConnectionToServer(fo_dbManager** dbManager, const char* testTableName)
654 {
655  PQfinish(fo_dbManager_getWrappedConnection(*dbManager));
656  CU_ASSERT_PTR_NULL(fo_dbManager_Exec_printf(*dbManager,
657  "CREATE TABLE new_table_with_a_null_connection"));
658 
660  *dbManager = NULL;
661 
662  return g_strdup(
663  "FATAL: no connection to the server\n"
664  "On: CREATE TABLE new_table_with_a_null_connection\n"
665  );
666 }
667 
668 char* _test_wrongQueries_noConnectionToServerOnPrepare(fo_dbManager** dbManager, const char* testTableName)
669 {
670  PQfinish(fo_dbManager_getWrappedConnection(*dbManager));
671 
672  char* query = g_strdup_printf("SELECT * FROM %s", testTableName);
673  fo_dbManager_PreparedStatement* statement = fo_dbManager_PrepareStamement(
674  *dbManager,
675  "noConnPrepare",
676  query
677  );
678  g_free(query);
679 
680  CU_ASSERT_PTR_NULL(statement);
681 
683  *dbManager = NULL;
684 
685  return g_strdup_printf(
686  "FATAL: no connection to the server\n"
687  "Preparing of '{ name: 'noConnPrepare', parameterTypes: []}' AS 'SELECT * FROM %s'\n",
688  testTableName
689  );
690 }
691 
692 char* _test_wrongQueries_noConnectionToServerOnExecute(fo_dbManager** dbManager, const char* testTableName)
693 {
694  char* query = g_strdup_printf("SELECT * FROM %s", testTableName);
695  fo_dbManager_PreparedStatement* statement = fo_dbManager_PrepareStamement(
696  *dbManager,
697  "noConn",
698  query
699  );
700  g_free(query);
701 
702  CU_ASSERT_PTR_NOT_NULL_FATAL(statement);
703 
704  PQfinish(fo_dbManager_getWrappedConnection(*dbManager));
705 
706  CU_ASSERT_PTR_NULL(fo_dbManager_ExecPrepared(statement));
707 
709  *dbManager = NULL;
710 
711  return g_strdup(
712  "FATAL: no connection to the server\n"
713  "Executing prepared '{ name: 'noConn', parameterTypes: []}' with params {}\n"
714  );
715 }
716 
717 char* _test_wrongQueries_noParametersFor1ParameterStmt(fo_dbManager** dbManager, const char* testTableName)
718 {
719  char* query = g_strdup_printf("SELECT a FROM %s WHERE a=$1", testTableName);
720  CU_ASSERT_PTR_NULL(fo_dbManager_ExecPrepared(
721  fo_dbManager_PrepareStamement(
722  *dbManager,
723  "name2",
724  query
725  )
726  ));
727  g_free(query);
728 
729  return g_strdup(
730  "ERROR: ERROR: bind message supplies 0 parameters, but prepared statement \"name2\" requires 1\n"
731  "Executing prepared '{ name: 'name2', parameterTypes: []}' with params {}\n"
732  );
733 }
734 
735 char* _test_wrongQueries_prepareWithNotExistingColumn(fo_dbManager** dbManager, const char* testTableName)
736 {
737  char* query = g_strdup_printf("SELECT c FROM %s WHERE a=$1", testTableName);
738  CU_ASSERT_PTR_NULL(fo_dbManager_PrepareStamement(
739  *dbManager,
740  "name",
741  query
742  ));
743  g_free(query);
744 
745  return g_strdup_printf(
746  "ERROR: * column \"c\" does not exist\n"
747  "*SELECT c FROM %s WHERE *\n"
748  "*^\n"
749  "Preparing of '{ name: 'name', parameterTypes: []}' AS 'SELECT c FROM %s WHERE a=$1'\n",
750  testTableName, testTableName
751  );
752 }
753 
754 char* _test_wrongQueries_2ParametersForNoParametersQuery(fo_dbManager** dbManager, const char* testTableName)
755 {
756  char* query = g_strdup_printf("SELECT a FROM %s WHERE a=1", testTableName);
757  CU_ASSERT_PTR_NULL(fo_dbManager_ExecPrepared(
758  fo_dbManager_PrepareStamement(
759  *dbManager,
760  "name3",
761  query,
762  int, size_t
763  ),
764  (int) 5, (size_t) 6
765  ));
766  g_free(query);
767 
768  return g_strdup(
769  "ERROR: ERROR: bind message supplies 2 parameters, but prepared statement \"name3\" requires 0\n"
770  "Executing prepared '{ name: 'name3', parameterTypes: [[0]={int, %d}, [1]={size_t, %zu}]}' with params {[0]='5', [1]='6'}\n"
771  );
772 }
773 
774 char* _test_wrongQueries_unparsableTypes(fo_dbManager** dbManager, const char* testTableName)
775 {
776  CU_ASSERT_PTR_NULL(fo_dbManager_PrepareStamement(
777  *dbManager,
778  "name4",
779  "irrelevant",
780  int, ,long
781  ));
782 
783  return g_strdup(
784  "FATAL: dbManager could not comprehend parameter types 'int, ,long'\n"
785  "Trying to prepare 'name4' as 'irrelevant'\n"
786  );
787 }
788 
789 char* _test_wrongQueries_transactions(fo_dbManager** dbManager, const char* testTableName)
790 {
791  fo_dbManager_ignoreWarnings(*dbManager, 1);
792 
793  CU_ASSERT_TRUE(fo_dbManager_begin(*dbManager));
794  CU_ASSERT_TRUE(fo_dbManager_begin(*dbManager));
795 
796  PQclear(fo_dbManager_Exec_printf(*dbManager, "INSERT INTO %s (a, b) VALUES (1,2)", testTableName));
797  CU_ASSERT_TRUE(fo_dbManager_commit(*dbManager));
798 
799  CU_ASSERT_TRUE(fo_dbManager_begin(*dbManager));
800  PQclear(fo_dbManager_Exec_printf(*dbManager, "INSERT INTO %s (a, b) VALUES (1,2)", testTableName));
801  PQclear(fo_dbManager_Exec_printf(*dbManager, "INSERT INTO %s (a, c) VALUES (1,2)", testTableName));
802  PQclear(fo_dbManager_Exec_printf(*dbManager, "INSERT INTO %s (a, b) VALUES (1,2)", testTableName));
803 
804  CU_ASSERT_TRUE(fo_dbManager_rollback(*dbManager));
805 
806  PGresult* res = fo_dbManager_Exec_printf(*dbManager, "SELECT * FROM %s", testTableName);
807 
808  CU_ASSERT_TRUE(PQntuples(res)==1);
809  PQclear(res);
810 
811  return g_strdup_printf(
812  "ERROR: ERROR: column \"c\" of relation \"%s\" does not exist\n"
813  "LINE 1: *\n"
814  "*^\n"
815  "On: INSERT INTO %s (a, c) VALUES (1,2)\n"
816  "ERROR: ERROR: current transaction is aborted, commands ignored until end of transaction block\n"
817  "On: INSERT INTO %s (a, b) VALUES (1,2)\n", testTableName, testTableName, testTableName
818  );
819 }
820 
821 void test_wrongQueries()
822 {
823  int testNumber = 0;
824  _test_wrongQueries_runner(_test_wrongQueries_SyntaxError0, ++testNumber);
825  _test_wrongQueries_runner(_test_wrongQueries_SyntaxError, ++testNumber);
826  _test_wrongQueries_runner(_test_wrongQueries_noConnectionToServer, ++testNumber);
827  _test_wrongQueries_runner(_test_wrongQueries_noConnectionToServerOnPrepare, ++testNumber);
828  _test_wrongQueries_runner(_test_wrongQueries_noConnectionToServerOnExecute, ++testNumber);
829  _test_wrongQueries_runner(_test_wrongQueries_prepareWithNotExistingColumn, ++testNumber);
830  _test_wrongQueries_runner(_test_wrongQueries_noParametersFor1ParameterStmt, ++testNumber);
831  _test_wrongQueries_runner(_test_wrongQueries_2ParametersForNoParametersQuery, ++testNumber);
832  _test_wrongQueries_runner(_test_wrongQueries_unparsableTypes, ++testNumber);
833  _test_wrongQueries_runner(_test_wrongQueries_transactions, ++testNumber);
834 }
835 
836 void test_executeNull()
837 {
838  CU_ASSERT_PTR_NULL(
840  NULL
841  )
842  );
843 }
844 
845 void test_stringEscape_corners()
846 {
847  PGconn* pgConn;
848  char* ErrorBuf;
849 
850  pgConn = fo_dbconnect(dbConf, &ErrorBuf);
852 
853  char* empty = fo_dbManager_StringEscape(dbManager, "");
854  CU_ASSERT_PTR_NOT_NULL_FATAL(empty);
855  CU_ASSERT_EQUAL(strlen(empty), 0);
856  free(empty);
857 
858  char* onlyQuotes = fo_dbManager_StringEscape(dbManager, "''''''");
859  CU_ASSERT_PTR_NOT_NULL_FATAL(onlyQuotes);
860  CU_ASSERT_TRUE(strlen(onlyQuotes) > 0);
861  free(onlyQuotes);
862 
864  PQfinish(pgConn);
865 }
866 
867 void test_parsing()
868 {
869  GArray* result;
870 
871  CU_ASSERT_TRUE(fo_dbManager_parseParamStr("", &result));
872  CU_ASSERT_EQUAL(result->len, 0);
873  g_array_free(result, TRUE);
874 
875  CU_ASSERT_TRUE(fo_dbManager_parseParamStr(" ", &result));
876  CU_ASSERT_EQUAL(result->len, 0);
877  g_array_free(result, TRUE);
878 
879  CU_ASSERT_TRUE(fo_dbManager_parseParamStr("\n", &result));
880  CU_ASSERT_EQUAL(result->len, 0);
881  g_array_free(result, TRUE);
882 
883  CU_ASSERT_FALSE(fo_dbManager_parseParamStr(",", &result));
884  CU_ASSERT_EQUAL(result->len, 0);
885  g_array_free(result, TRUE);
886 
887  CU_ASSERT_TRUE(fo_dbManager_parseParamStr("int", &result));
888  CU_ASSERT_EQUAL(result->len, 1);
889  g_array_free(result, TRUE);
890 
891  CU_ASSERT_TRUE(fo_dbManager_parseParamStr(" int ", &result));
892  CU_ASSERT_EQUAL(result->len, 1);
893  g_array_free(result, TRUE);
894 
895  CU_ASSERT_TRUE(fo_dbManager_parseParamStr("long, int\t ,unsigned\n\t int ,long ", &result));
896  CU_ASSERT_EQUAL(result->len, 4);
897  g_array_free(result, TRUE);
898 
899  CU_ASSERT_TRUE(fo_dbManager_parseParamStr("unsigned int", &result));
900  CU_ASSERT_EQUAL(result->len, 1);
901  g_array_free(result, TRUE);
902 
903  CU_ASSERT_FALSE(fo_dbManager_parseParamStr("unsignedint", &result));
904  CU_ASSERT_EQUAL(result->len, 0);
905  g_array_free(result, TRUE);
906 
907  CU_ASSERT_FALSE(fo_dbManager_parseParamStr("int,", &result));
908  CU_ASSERT_EQUAL(result->len, 0);
909  g_array_free(result, TRUE);
910 
911  CU_ASSERT_FALSE(fo_dbManager_parseParamStr("int,,long", &result));
912  CU_ASSERT_EQUAL(result->len, 0);
913  g_array_free(result, TRUE);
914 
915  CU_ASSERT_FALSE(fo_dbManager_parseParamStr("int, ,long", &result));
916  CU_ASSERT_EQUAL(result->len, 0);
917  g_array_free(result, TRUE);
918 
919  CU_ASSERT_FALSE(fo_dbManager_parseParamStr("int a", &result));
920  CU_ASSERT_EQUAL(result->len, 0);
921  g_array_free(result, TRUE);
922 
923  CU_ASSERT_FALSE(fo_dbManager_parseParamStr("i", &result));
924  CU_ASSERT_EQUAL(result->len, 0);
925  g_array_free(result, TRUE);
926 
927  CU_ASSERT_FALSE(fo_dbManager_parseParamStr("in", &result));
928  CU_ASSERT_EQUAL(result->len, 0);
929  g_array_free(result, TRUE);
930 
931  CU_ASSERT_FALSE(fo_dbManager_parseParamStr("inta", &result));
932  CU_ASSERT_EQUAL(result->len, 0);
933  g_array_free(result, TRUE);
934 
935  CU_ASSERT_FALSE(fo_dbManager_parseParamStr("long, inta , int ,long", &result));
936  CU_ASSERT_EQUAL(result->len, 0);
937  g_array_free(result, TRUE);
938 }
939 
940 /* ************************************************************************** */
941 /* *** cunit test info ****************************************************** */
942 /* ************************************************************************** */
943 CU_TestInfo libfossdbmanager_testcases[] =
944  {
945  {"prepare", test_prepare},
946  {"simple injection", test_simple_inject},
947  {"handling of wrong queries", test_wrongQueries},
948  {"execute a null statement", test_executeNull},
949  {"strange string escaping", test_stringEscape_corners},
950  {"parsing types", test_parsing},
951 // { "performance test", test_perf },
952  {"fork dbManager", test_fork},
953  {"fork dbManager without configuration", test_fork_error},
954  CU_TEST_INFO_NULL
955  };
PGconn * pgConn
Database connection.
Definition: adj2nest.c:86
PGconn * fo_dbconnect(char *DBConfFile, char **ErrorBuf)
Connect to a database. The default is Db.conf.
Definition: libfossdb.c:29
char buffer[2048]
The last thing received from the scheduler.
#define MIN(a, b)
Min of two.
Definition: licenses.c:64
fo_dbManager * dbManager
fo_dbManager object
Definition: process.c:16
PGresult * fo_dbManager_ExecPrepared(fo_dbManager_PreparedStatement *preparedStatement,...)
Execute a prepared statement.
Definition: standalone.c:36
fo_dbManager * fo_dbManager_new(PGconn *dbConnection)
Create and initialize new fo_dbManager object.
Definition: standalone.c:33
void fo_dbManager_free(fo_dbManager *dbManager)
Un-allocate the memory from a DB manager.
Definition: standalone.c:34
int exists
Default not exists.
Definition: run_tests.c:20