BasicTests.cpp
Go to the documentation of this file.
1 #include <cppunit/extensions/HelperMacros.h>
2 #include <NovaDatabase/Table.h>
3 #include <boost/date_time/posix_time/posix_time.hpp>
4 #include <boost/shared_ptr.hpp>
5 
6 namespace BPT = boost::posix_time;
7 using namespace nova::database;
8 
10  "NovaDatabase/cxx/unittest/basicTestTable1.xml";
11 
13  "NovaDatabase/cxx/unittest/basicTestTable2.xml";
14 
16  "NovaDatabase/cxx/unittest/basicTestTable3.xml";
17 
18 class BasicTests : public CppUnit::TestFixture
19 {
20  CPPUNIT_TEST_SUITE(BasicTests);
21  CPPUNIT_TEST(populateDBTable);
22  CPPUNIT_TEST(testRowInsertWithAutoIncrColumn);
23  CPPUNIT_TEST(testColumnLookup);
24  CPPUNIT_TEST(testDistinctAndOrder);
25  CPPUNIT_TEST(testTableCreationAndDestruction);
26  CPPUNIT_TEST(testTableCreateFromDB);
27  CPPUNIT_TEST(testEmptyStringVsNULL);
28  CPPUNIT_TEST(testUpdateTwice);
29  CPPUNIT_TEST(testBooleanValidity);
30  CPPUNIT_TEST(cleanupDBTable);
31  CPPUNIT_TEST_SUITE_END();
32 
33 public:
34  void setUp();
35  void tearDown();
36 
37  void populateDBTable();
38  void testRowInsertWithAutoIncrColumn();
39  void testColumnLookup();
40  void testDistinctAndOrder();
41  void testTableCreationAndDestruction();
42  void testTableCreateFromDB();
43  void testEmptyStringVsNULL();
44  void testUpdateTwice();
45  void testBooleanValidity();
46  void cleanupDBTable();
47 
48 private:
49 
50  static boost::shared_ptr<Table> _dbt1;
51  static boost::shared_ptr<Table> _dbt2;
52  static boost::shared_ptr<Table> _dbt3;
53 };
54 
55 boost::shared_ptr<Table> BasicTests::_dbt1;
56 boost::shared_ptr<Table> BasicTests::_dbt2;
57 boost::shared_ptr<Table> BasicTests::_dbt3;
58 
59 void
61 {
62  // flush stdout to get progress markers to display in a timely way
63  std::cout.flush();
64 }
65 
66 void
68 {
69  // flush stdout to get progress markers to display in a timely way
70  std::cout.flush();
71 }
72 
73 void
75 {
76  CPPUNIT_ASSERT(_dbt2->ExistsInDB());
77  _dbt2->Clear();
78  CPPUNIT_ASSERT(_dbt2->LoadFromDB());
79 
80  // some random, but known, values
81  int initialRowCount = _dbt2->NRow();
82  int channel = 3 * (initialRowCount + 1);
83  time_t now = time(0);
84  int tmpVal = now % 10000;
85  float value1 = (float) (((double) tmpVal) / 100.0);
86  float value2 = (float) (((double) tmpVal) / 357.0);
87  std::string string1 = (((initialRowCount % 5) != 0) ? "three" : "one");
88 
89  // create the test row and store it in the database
90  boost::shared_ptr<Row> rowPtr(_dbt2->NewRow());
91  CPPUNIT_ASSERT(rowPtr->Set("channel", channel));
92  CPPUNIT_ASSERT(rowPtr->Set("value1", value1));
93  CPPUNIT_ASSERT(rowPtr->Set("value2", value2));
94  CPPUNIT_ASSERT(rowPtr->Set("string1", string1));
95  CPPUNIT_ASSERT(rowPtr->Set("string2", "two"));
96  _dbt2->AddRow(rowPtr.get());
97  CPPUNIT_ASSERT(_dbt2->WriteToDB());
98 
99  // verify that we can fetch the ID of the new row
100  int64_t idOfInsertedRow;
101  CPPUNIT_ASSERT(_dbt2->GetCurrSeqVal("id", idOfInsertedRow));
102 
103  // reload the table from the database
104  _dbt2->Clear();
105  CPPUNIT_ASSERT(_dbt2->LoadFromDB());
106  int newRowCount = _dbt2->NRow();
107 
108  // verify that the number of rows has increased by one
109  CPPUNIT_ASSERT(newRowCount == (initialRowCount + 1));
110 
111  // loop over the result set until we find the new row
112  // (testing of validity ranges will be done in a later test)
113  bool found = false;
114  for (int idx = 0; idx < newRowCount; ++idx) {
115  Row* row = _dbt2->GetRow(idx);
116  Column* col = row->Col("id");
117  int64_t rowId;
118  CPPUNIT_ASSERT(col->Get(rowId));
119  if (rowId == idOfInsertedRow) {
120  found = true;
121  int testChannelValue;
122  float testValue;
123 
124  col = row->Col("channel");
125  CPPUNIT_ASSERT(col->Get(testChannelValue));
126  CPPUNIT_ASSERT(testChannelValue == channel);
127 
128  col = row->Col("value1");
129  CPPUNIT_ASSERT(col->Get(testValue));
130  CPPUNIT_ASSERT(testValue > (0.99 * value1) &&
131  testValue < (1.01 * value1));
132 
133  col = row->Col("value2");
134  CPPUNIT_ASSERT(col->Get(testValue));
135  CPPUNIT_ASSERT(testValue > (0.99 * value2) &&
136  testValue < (1.01 * value2));
137 
138  break;
139  }
140  }
141  CPPUNIT_ASSERT(found);
142 
143  // test the lookup of a row by ID
144  _dbt2->Clear();
145  _dbt2->SetValidityRange("id", idOfInsertedRow);
146  CPPUNIT_ASSERT(_dbt2->LoadFromDB());
147  CPPUNIT_ASSERT(_dbt2->NRow() == 1);
148 }
149 
150 void
152 {
153  CPPUNIT_ASSERT(_dbt2->ExistsInDB());
154  _dbt2->Clear();
155  CPPUNIT_ASSERT(_dbt2->LoadFromDB());
156 
157  int nRow = _dbt2->NRow();
158  CPPUNIT_ASSERT(nRow > 0);
159 
160  // test individual columns
161  std::string columnValue;
162  Row* row = _dbt2->GetRow(0);
163  Column* col = row->Col("id");
164  CPPUNIT_ASSERT(col != 0);
165  CPPUNIT_ASSERT(col->Get(columnValue));
166  col = row->Col("channel");
167  CPPUNIT_ASSERT(col != 0);
168  CPPUNIT_ASSERT(col->Get(columnValue));
169  col = row->Col("value1");
170  CPPUNIT_ASSERT(col != 0);
171  CPPUNIT_ASSERT(col->Get(columnValue));
172  col = row->Col("value2");
173  CPPUNIT_ASSERT(col != 0);
174  CPPUNIT_ASSERT(col->Get(columnValue));
175  col = row->Col("inserttime");
176  CPPUNIT_ASSERT(col != 0);
177  CPPUNIT_ASSERT(col->Get(columnValue));
178  col = row->Col("insertuser");
179  CPPUNIT_ASSERT(col != 0);
180  CPPUNIT_ASSERT(col->Get(columnValue));
181 
182  // test the full set of columns
183  bool foundChannelColumn = false;
184  CPPUNIT_ASSERT(_dbt2->NCol() == 11);
185  for (int idx = 0; idx < _dbt2->NCol(); ++idx) {
186  Column& colRef = row->Col(idx);
187  std::string cname = colRef.Name();
188  if (cname != "nameid" && cname != "updateuser" &&
189  cname != "updatetime" && cname != "insertuser" &&
190  cname != "inserttime") {
191  CPPUNIT_ASSERT(colRef.Get(columnValue));
192  if (colRef.Name() == "channel") {
193  foundChannelColumn = true;
194  }
195  }
196  }
197  CPPUNIT_ASSERT(foundChannelColumn);
198 }
199 
200 void
202 {
203  CPPUNIT_ASSERT(_dbt2->ExistsInDB());
204 
205  _dbt2->Clear();
206  CPPUNIT_ASSERT(_dbt2->AddDistinctColumn("string1"));
207  CPPUNIT_ASSERT(_dbt2->LoadFromDB());
208  CPPUNIT_ASSERT(_dbt2->NRow() == 2);
209 
210  _dbt2->Clear();
211  CPPUNIT_ASSERT(_dbt2->AddDistinctColumn("string2"));
212  CPPUNIT_ASSERT(_dbt2->LoadFromDB());
213  CPPUNIT_ASSERT(_dbt2->NRow() == 2);
214 
215  _dbt2->Clear();
216  CPPUNIT_ASSERT(_dbt2->AddDistinctColumn("string1"));
217  CPPUNIT_ASSERT(_dbt2->AddDistinctColumn("string2"));
218  CPPUNIT_ASSERT(_dbt2->LoadFromDB());
219  CPPUNIT_ASSERT(_dbt2->NRow() == 3);
220 
221 
222  _dbt2->Clear();
223  CPPUNIT_ASSERT(_dbt2->AddOrderColumn("channel"));
224  CPPUNIT_ASSERT(_dbt2->LoadFromDB());
225 
226  int previousChannel = 999999999;
227  int channel;
228  for (int i=0; i<_dbt2->NRow(); ++i) {
229  CPPUNIT_ASSERT(_dbt2->GetRow(i)->Col("channel")->Get(channel));
230  CPPUNIT_ASSERT(channel <= previousChannel);
231  previousChannel = channel;
232  }
233 
234  _dbt2->Clear();
235  CPPUNIT_ASSERT(_dbt2->AddOrderColumn("channel"));
236  _dbt2->SetOrderAsc();
237  CPPUNIT_ASSERT(_dbt2->LoadFromDB());
238 
239  previousChannel = -1;
240  for (int i=0; i<_dbt2->NRow(); ++i) {
241  CPPUNIT_ASSERT(_dbt2->GetRow(i)->Col("channel")->Get(channel));
242  CPPUNIT_ASSERT(channel >= previousChannel);
243  previousChannel = channel;
244  }
245 
246  _dbt2->Clear();
247  CPPUNIT_ASSERT(_dbt2->AddOrderColumn("string2"));
248  CPPUNIT_ASSERT(_dbt2->AddOrderColumn("value2"));
249  _dbt2->SetOrderAsc();
250  CPPUNIT_ASSERT(_dbt2->LoadFromDB());
251 
252  double previousValue2 = -1.0;
253  double value2;
254  std::string previousString2 = "aaaaaa";
255  std::string string2;
256  for (int i=0; i<_dbt2->NRow(); ++i) {
257  CPPUNIT_ASSERT(_dbt2->GetRow(i)->Col("string2")->Get(string2));
258  CPPUNIT_ASSERT(string2 >= previousString2);
259  if (string2 == previousString2) {
260  CPPUNIT_ASSERT(_dbt2->GetRow(i)->Col("value2")->Get(value2));
261  CPPUNIT_ASSERT(value2 >= previousValue2);
262  previousValue2 = value2;
263  }
264  else {
265  previousValue2 = -1.0;
266  }
267  previousString2 = string2;
268  }
269 }
270 
271 void
273 {
274  boost::shared_ptr<Table> localDBTablePtr;
275 
276  for (int idx = 0; idx < 20; ++idx) {
277  //std::cout << "Table creation test, version 1, index "
278  // << idx << std::endl;
279  localDBTablePtr.reset(new Table(TABLE2_DEFINITION_FILE.c_str()));
280  CPPUNIT_ASSERT(localDBTablePtr->ExistsInDB());
281  }
282 
283  for (int idx = 0; idx < 20; ++idx) {
284  //std::cout << "Table creation test, version 1, index "
285  // << idx << std::endl;
286  localDBTablePtr.reset(new Table(TABLE2_DEFINITION_FILE.c_str()));
287  localDBTablePtr->GetConnection();
288  CPPUNIT_ASSERT(localDBTablePtr->ExistsInDB());
289  }
290 }
291 
292 void
294 {
295  boost::shared_ptr<Table> localDBTablePtr;
296 
297  localDBTablePtr.reset(new Table());
298  CPPUNIT_ASSERT(localDBTablePtr->CreateFromDB("public","hardware_position",
299  "ifdbprod.fnal.gov","nova_hardware",
300  "5432","nova_reader"));
301 }
302 
303 void
305 {
306  _dbt3->Clear();
307  Row* rowPtr = _dbt3->NewRow();
308 
309  CPPUNIT_ASSERT(rowPtr->Set("channel", 1024));
310  CPPUNIT_ASSERT(rowPtr->Set("value1", 3.1415));
311  CPPUNIT_ASSERT(rowPtr->Set("value2", 0.01));
312  CPPUNIT_ASSERT(! rowPtr->Set("string1", ""));
313  CPPUNIT_ASSERT(rowPtr->Set("string2", "NULL"));
314  _dbt3->AddRow(rowPtr);
315  CPPUNIT_ASSERT(_dbt3->WriteToDB());
316  delete rowPtr;
317 
318  _dbt3->Clear();
319  CPPUNIT_ASSERT(_dbt3->LoadFromDB());
320  int nRows = _dbt3->NRow();
321  rowPtr = _dbt3->GetRow(nRows-1);
322  CPPUNIT_ASSERT(rowPtr->Col("string1")->IsNull());
323  CPPUNIT_ASSERT(rowPtr->Col("string2")->IsNull());
324  _dbt3->Clear();
325 }
326 
327 void
329 {
330  _dbt3->Clear();
331  _dbt3->SetUser(getenv("USER"));
332  Row* rowPtr = _dbt3->NewRow();
333 
334  CPPUNIT_ASSERT(rowPtr->Set("channel", 2048));
335  CPPUNIT_ASSERT(rowPtr->Set("value1", 929.929));
336  CPPUNIT_ASSERT(rowPtr->Set("value2", 0.929));
337  CPPUNIT_ASSERT(rowPtr->Set("string1", "929"));
338  CPPUNIT_ASSERT(rowPtr->Set("string2", "92929"));
339  _dbt3->AddRow(rowPtr);
340  CPPUNIT_ASSERT(_dbt3->WriteToDB());
341  delete rowPtr;
342 
343  _dbt3->Clear();
344  CPPUNIT_ASSERT(_dbt3->LoadFromDB());
345  int nRows = _dbt3->NRow();
346  CPPUNIT_ASSERT(_dbt3->GetRow(nRows-1)->Update("channel",2049));
347  CPPUNIT_ASSERT(_dbt3->WriteToDB());
348  _dbt3->Clear();
349  CPPUNIT_ASSERT(_dbt3->LoadFromDB());
350  int myChan;
351  CPPUNIT_ASSERT(_dbt3->GetRow(nRows-1)->Col("channel")->Get(myChan));
352  CPPUNIT_ASSERT(myChan == 2049);
353  std::string updateUser, updateTime;
354  CPPUNIT_ASSERT(_dbt3->GetRow(nRows-1)->Col("updateuser")->Get(updateUser));
355  CPPUNIT_ASSERT(_dbt3->GetRow(nRows-1)->Col("updatetime")->Get(updateTime));
356  sleep(2);
357  CPPUNIT_ASSERT(_dbt3->GetRow(nRows-1)->Update("channel",2050));
358  CPPUNIT_ASSERT(_dbt3->WriteToDB());
359  _dbt3->Clear();
360  CPPUNIT_ASSERT(_dbt3->LoadFromDB());
361  CPPUNIT_ASSERT(_dbt3->GetRow(nRows-1)->Col("channel")->Get(myChan));
362  CPPUNIT_ASSERT(myChan == 2050);
363  std::string updateUser_save = updateUser;
364  std::string updateTime_save = updateTime;
365  CPPUNIT_ASSERT(_dbt3->GetRow(nRows-1)->Col("updateuser")->Get(updateUser));
366  CPPUNIT_ASSERT(_dbt3->GetRow(nRows-1)->Col("updatetime")->Get(updateTime));
367  CPPUNIT_ASSERT(updateUser_save == updateUser);
368 
369  BPT::ptime firstTime = BPT::time_from_string(updateTime_save);
370  BPT::ptime secondTime = BPT::time_from_string(updateTime);
371  BPT::time_duration timeDiff = secondTime - firstTime;
372  CPPUNIT_ASSERT(timeDiff.seconds() == 2 || timeDiff.seconds() == 3);
373 }
374 
375 void
377 {
378  CPPUNIT_ASSERT(_dbt1->ExistsInDB());
379 
380  _dbt1->Clear();
381  _dbt1->SetValidityRange("isenabled", true);
382  CPPUNIT_ASSERT(_dbt1->LoadFromDB());
383  CPPUNIT_ASSERT(_dbt1->NRow() == 2);
384 
385  _dbt1->Clear();
386  _dbt1->SetValidityRange("isenabled", false);
387  CPPUNIT_ASSERT(_dbt1->LoadFromDB());
388  CPPUNIT_ASSERT(_dbt1->NRow() == 1);
389 }
390 
391 void
393 {
394  // create the tables that are used in these tests
395  _dbt1.reset(new Table(TABLE1_DEFINITION_FILE.c_str()));
396  CPPUNIT_ASSERT(_dbt1->ExistsInDB());
397  _dbt1->Clear();
398  CPPUNIT_ASSERT(_dbt1->LoadFromDB());
399 
400  _dbt2.reset(new Table(TABLE2_DEFINITION_FILE.c_str()));
401  CPPUNIT_ASSERT(_dbt2->ExistsInDB());
402  _dbt2->Clear();
403  CPPUNIT_ASSERT(_dbt2->LoadFromDB());
404 
405  _dbt3.reset(new Table(TABLE3_DEFINITION_FILE.c_str()));
406  CPPUNIT_ASSERT(_dbt3->ExistsInDB());
407  _dbt3->Clear();
408  CPPUNIT_ASSERT(_dbt3->LoadFromDB());
409 
410  // create some filler rows, if needed
411  int nRow = _dbt2->NRow();
412  if (nRow == 0) {
413  boost::shared_ptr<Row> rowPtr(_dbt2->NewRow());
414  CPPUNIT_ASSERT(rowPtr->Set("channel", 101));
415  CPPUNIT_ASSERT(rowPtr->Set("value1", 5.0));
416  CPPUNIT_ASSERT(rowPtr->Set("value2", 42.6));
417  CPPUNIT_ASSERT(rowPtr->Set("string1", "one"));
418  CPPUNIT_ASSERT(rowPtr->Set("string2", "two"));
419  _dbt2->AddRow(rowPtr.get());
420  CPPUNIT_ASSERT(_dbt2->WriteToDB());
421  rowPtr.reset(_dbt2->NewRow());
422  CPPUNIT_ASSERT(rowPtr->Set("channel", 102));
423  CPPUNIT_ASSERT(rowPtr->Set("value1", 5.0));
424  CPPUNIT_ASSERT(rowPtr->Set("value2", 42.7));
425  CPPUNIT_ASSERT(rowPtr->Set("string1", "one"));
426  CPPUNIT_ASSERT(rowPtr->Set("string2", "four"));
427  _dbt2->AddRow(rowPtr.get());
428  CPPUNIT_ASSERT(_dbt2->WriteToDB());
429  rowPtr.reset(_dbt2->NewRow());
430  CPPUNIT_ASSERT(rowPtr->Set("channel", 103));
431  CPPUNIT_ASSERT(rowPtr->Set("value1", 5.0));
432  CPPUNIT_ASSERT(rowPtr->Set("value2", 42.8));
433  CPPUNIT_ASSERT(rowPtr->Set("string1", "one"));
434  CPPUNIT_ASSERT(rowPtr->Set("string2", "two"));
435  _dbt2->AddRow(rowPtr.get());
436  CPPUNIT_ASSERT(_dbt2->WriteToDB());
437  }
438 
439  nRow = _dbt1->NRow();
440  if (nRow == 0) {
441  boost::shared_ptr<Row> rowPtr(_dbt1->NewRow());
442  CPPUNIT_ASSERT(rowPtr->Set("Name", "AAA"));
443  CPPUNIT_ASSERT(rowPtr->Set("isEnabled", true));
444  _dbt1->AddRow(rowPtr.get());
445  CPPUNIT_ASSERT(_dbt1->WriteToDB());
446  rowPtr.reset(_dbt1->NewRow());
447  CPPUNIT_ASSERT(rowPtr->Set("Name", "BBB"));
448  CPPUNIT_ASSERT(rowPtr->Set("isEnabled", false));
449  _dbt1->AddRow(rowPtr.get());
450  CPPUNIT_ASSERT(_dbt1->WriteToDB());
451  rowPtr.reset(_dbt1->NewRow());
452  CPPUNIT_ASSERT(rowPtr->Set("Name", "CCC"));
453  CPPUNIT_ASSERT(rowPtr->Set("isEnabled", true));
454  _dbt1->AddRow(rowPtr.get());
455  CPPUNIT_ASSERT(_dbt1->WriteToDB());
456  }
457 
458  // clear the Table objects as a nicety
459  _dbt1->Clear();
460  _dbt2->Clear();
461  _dbt3->Clear();
462 }
463 
464 void
466 {
467  _dbt1.reset();
468  _dbt2.reset();
469  _dbt3.reset();
470 }
471 
473 CPPUNIT_REGISTRY_ADD_TO_DEFAULT("NovaDatabase");
bool Set(std::string cname, T value)
Definition: Row.h:30
void tearDown()
Definition: BasicTests.cpp:67
void populateDBTable()
Definition: BasicTests.cpp:392
const std::string TABLE2_DEFINITION_FILE
Definition: BasicTests.cpp:12
void testTableCreateFromDB()
Definition: BasicTests.cpp:293
void setUp()
Definition: BasicTests.cpp:60
void cleanupDBTable()
Definition: BasicTests.cpp:465
static boost::shared_ptr< Table > _dbt3
Definition: BasicTests.cpp:52
void Clear()
Definition: Row.cpp:61
void testUpdateTwice()
Definition: BasicTests.cpp:328
void testEmptyStringVsNULL()
Definition: BasicTests.cpp:304
void testTableCreationAndDestruction()
Definition: BasicTests.cpp:272
::xsd::cxx::tree::time< char, simple_type > time
Definition: Database.h:194
void testBooleanValidity()
Definition: BasicTests.cpp:376
const std::string TABLE3_DEFINITION_FILE
Definition: BasicTests.cpp:15
void testDistinctAndOrder()
Definition: BasicTests.cpp:201
Int_t col[ntarg]
Definition: Style.C:29
std::string getenv(std::string const &name)
void testColumnLookup()
Definition: BasicTests.cpp:151
bool Get(T &val) const
Definition: Column.h:53
OStream cout
Definition: OStream.cxx:6
CPPUNIT_REGISTRY_ADD_TO_DEFAULT("NovaDatabase")
::xsd::cxx::tree::string< char, simple_type > string
Definition: Database.h:154
static boost::shared_ptr< Table > _dbt2
Definition: BasicTests.cpp:51
std::string Name() const
Definition: Column.h:35
struct Table Table
Definition: TexBuilder.h:2
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(BasicTests,"NovaDatabase")
void testRowInsertWithAutoIncrColumn()
Definition: BasicTests.cpp:74
const std::string TABLE1_DEFINITION_FILE
Definition: BasicTests.cpp:9
static boost::shared_ptr< Table > _dbt1
Definition: BasicTests.cpp:50
Column & Col(int i)
Definition: Row.h:51