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