TraDemGen Logo  1.00.2
C++ Simulated Travel Demand Generation Library
DemandGenerationTestSuite.cpp
Go to the documentation of this file.
1 
5 // //////////////////////////////////////////////////////////////////////
6 // Import section
7 // //////////////////////////////////////////////////////////////////////
8 // STL
9 #include <sstream>
10 #include <fstream>
11 #include <map>
12 #include <cmath>
13 // Boost Unit Test Framework (UTF)
14 #define BOOST_TEST_DYN_LINK
15 #define BOOST_TEST_MAIN
16 #define BOOST_TEST_MODULE DemandGenerationTest
17 #include <boost/test/unit_test.hpp>
18 #include <boost/version.hpp>
19 // StdAir
20 #include <stdair/stdair_basic_types.hpp>
21 #include <stdair/basic/BasConst_General.hpp>
22 #include <stdair/basic/BasLogParams.hpp>
23 #include <stdair/basic/BasDBParams.hpp>
24 #include <stdair/basic/BasFileMgr.hpp>
25 #include <stdair/basic/ProgressStatusSet.hpp>
26 #include <stdair/bom/EventStruct.hpp>
27 #include <stdair/bom/BookingRequestStruct.hpp>
28 #include <stdair/service/Logger.hpp>
29 // TraDemGen
34 
35 namespace boost_utf = boost::unit_test;
36 
37 // (Boost) Unit Test XML Report
38 std::ofstream utfReportStream ("DemandGenerationTestSuite_utfresults.xml");
39 
43 struct UnitTestConfig {
45  UnitTestConfig() {
46  boost_utf::unit_test_log.set_stream (utfReportStream);
47 #if BOOST_VERSION >= 105900
48  boost_utf::unit_test_log.set_format (boost_utf::OF_XML);
49 #else
50  boost_utf::unit_test_log.set_format (boost_utf::XML);
51 #endif
52  boost_utf::unit_test_log.set_threshold_level (boost_utf::log_test_units);
53  //boost_utf::unit_test_log.set_threshold_level (boost_utf::log_successful_tests);
54  }
55 
57  ~UnitTestConfig() {
58  }
59 };
60 
61 // Specific type definitions
62 typedef std::pair<stdair::Count_T, stdair::Count_T> NbOfEventsPair_T;
63 typedef std::map<const stdair::DemandStreamKeyStr_T,
64  NbOfEventsPair_T> NbOfEventsByDemandStreamMap_T;
65 
66 // //////////////////////////////////////////////////////////////////////
70 void testDemandGenerationHelper (const unsigned short iTestFlag,
71  const stdair::Filename_T& iDemandInputFilename,
72  const stdair::DemandGenerationMethod& iDemandGenerationMethod,
73  const bool isBuiltin) {
74 
75  // Seed for the random generation
76  const stdair::RandomSeed_T lRandomSeed = stdair::DEFAULT_RANDOM_SEED;
77 
78  // Output log File
79  std::ostringstream oStr;
80  oStr << "DemandGenerationTestSuite_" << iTestFlag << ".log";
81  const stdair::Filename_T lLogFilename (oStr.str());
82 
83  // Set the log parameters
84  std::ofstream logOutputFile;
85  // Open and clean the log outputfile
86  logOutputFile.open (lLogFilename.c_str());
87  logOutputFile.clear();
88 
89  // Initialise the TraDemGen service object
90  const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
91  TRADEMGEN::TRADEMGEN_Service trademgenService (lLogParams, lRandomSeed);
92 
102  NbOfEventsByDemandStreamMap_T lNbOfEventsMap;
103 
104  // Total number of events
105  stdair::Count_T lRefExpectedNbOfEvents (0);
106  stdair::Count_T lRefActualNbOfEvents (0);
107 
108  // Check whether or not a (CSV) input file should be read
109  if (isBuiltin == true) {
110 
111  // Build the default sample BOM tree (filled with demand streams) for TraDemGen
112  trademgenService.buildSampleBom();
113 
114  lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
115  value_type ("SIN-BKK 2010-Feb-08 Y",
116  NbOfEventsPair_T (4, 60)));
117  lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
118  value_type ("BKK-HKG 2010-Feb-08 Y",
119  NbOfEventsPair_T (4, 60)));
120  lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
121  value_type ("SIN-HKG 2010-Feb-08 Y",
122  NbOfEventsPair_T (4, 60)));
123 
124  // Total number of events, for the 3 demand streams: 180
125  lRefExpectedNbOfEvents = 180;
126  lRefActualNbOfEvents = 186;
127 
128  } else {
129 
130  // Create the DemandStream objects, and insert them within the BOM tree
131  const TRADEMGEN::DemandFilePath lDemandFilePath (iDemandInputFilename);
132  trademgenService.parseAndLoad (lDemandFilePath);
133 
134  lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
135  value_type ("SIN-HND 2010-Feb-08 Y",
136  NbOfEventsPair_T (1, 10)));
137  lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
138  value_type ("SIN-HND 2010-Feb-09 Y",
139  NbOfEventsPair_T (1, 10)));
140  lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
141  value_type ("SIN-BKK 2010-Feb-08 Y",
142  NbOfEventsPair_T (1, 10)));
143  lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
144  value_type ("SIN-BKK 2010-Feb-09 Y",
145  NbOfEventsPair_T (1, 10)));
146 
147  // Total number of events, for the 4 demand streams: 40
148  lRefExpectedNbOfEvents = 40;
149  lRefActualNbOfEvents = 40;
150  }
151 
152  // Retrieve the expected (mean value of the) number of events to be
153  // generated
154  const stdair::Count_T& lExpectedNbOfEventsToBeGenerated =
155  trademgenService.getExpectedTotalNumberOfRequestsToBeGenerated();
156 
157  BOOST_CHECK_EQUAL (lRefExpectedNbOfEvents,
158  std::floor (lExpectedNbOfEventsToBeGenerated));
159 
160  BOOST_CHECK_MESSAGE (lRefExpectedNbOfEvents ==
161  std::floor (lExpectedNbOfEventsToBeGenerated),
162  "Expected total number of requests to be generated: "
163  << lExpectedNbOfEventsToBeGenerated
164  << " (=> "
165  << std::floor (lExpectedNbOfEventsToBeGenerated)
166  << "). Reference value: " << lRefExpectedNbOfEvents);
167 
173  const stdair::Count_T& lActualNbOfEventsToBeGenerated =
174  trademgenService.generateFirstRequests(iDemandGenerationMethod);
175 
176  // DEBUG
177  STDAIR_LOG_DEBUG ("Expected number of events: "
178  << lExpectedNbOfEventsToBeGenerated << ", actual: "
179  << lActualNbOfEventsToBeGenerated);
180 
181  // Total number of events, for all the demand streams:
182  BOOST_CHECK_EQUAL (lRefActualNbOfEvents, lActualNbOfEventsToBeGenerated);
183 
184  BOOST_CHECK_MESSAGE (lRefActualNbOfEvents == lActualNbOfEventsToBeGenerated,
185  "Actual total number of requests to be generated: "
186  << lExpectedNbOfEventsToBeGenerated
187  << " (=> "
188  << std::floor (lExpectedNbOfEventsToBeGenerated)
189  << "). Reference value: " << lRefActualNbOfEvents);
190 
192  const bool isQueueDone = trademgenService.isQueueDone();
193  BOOST_REQUIRE_MESSAGE (isQueueDone == false,
194  "The event queue should not be empty.");
195 
203  stdair::Count_T idx = 1;
204  while (trademgenService.isQueueDone() == false) {
205 
206  // Get the next event from the event queue
207  stdair::EventStruct lEventStruct;
208  stdair::ProgressStatusSet lPPS = trademgenService.popEvent (lEventStruct);
209 
210  // DEBUG
211  STDAIR_LOG_DEBUG ("Poped event: '" << lEventStruct.describe() << "'.");
212 
213  // Extract the corresponding demand/booking request
214  const stdair::BookingRequestStruct& lPoppedRequest =
215  lEventStruct.getBookingRequest();
216 
217  // DEBUG
218  STDAIR_LOG_DEBUG ("Poped booking request: '"
219  << lPoppedRequest.describe() << "'.");
220 
221  // Retrieve the corresponding demand stream
222  const stdair::DemandGeneratorKey_T& lDemandStreamKey =
223  lPoppedRequest.getDemandGeneratorKey();
224 
225  // Check that the number of booking requests to be generated are correct
226  const NbOfEventsByDemandStreamMap_T::iterator itNbOfEventsMap =
227  lNbOfEventsMap.find (lDemandStreamKey);
228  BOOST_REQUIRE_MESSAGE (itNbOfEventsMap != lNbOfEventsMap.end(),
229  "The demand stream key '" << lDemandStreamKey
230  << "' is not expected in that test");
231 
241  const NbOfEventsPair_T& lNbOfEventsPair = itNbOfEventsMap->second;
242  stdair::Count_T lCurrentNbOfEvents = lNbOfEventsPair.first;
243  const stdair::Count_T& lExpectedTotalNbOfEvents = lNbOfEventsPair.second;
244 
245  // Assess whether more events should be generated for that demand stream
246  const bool stillHavingRequestsToBeGenerated = trademgenService.
247  stillHavingRequestsToBeGenerated (lDemandStreamKey, lPPS,
248  iDemandGenerationMethod);
249 
256  if (lCurrentNbOfEvents == 1) {
262  const stdair::ProgressStatus& lDemandStreamProgressStatus =
263  lPPS.getSpecificGeneratorStatus();
264  const stdair::Count_T& lNbOfRequests =
265  lDemandStreamProgressStatus.getExpectedNb();
266 
267  BOOST_CHECK_EQUAL (lNbOfRequests, lExpectedTotalNbOfEvents);
268  BOOST_CHECK_MESSAGE (lNbOfRequests == lExpectedTotalNbOfEvents,
269  "[" << lDemandStreamKey
270  << "] Total number of requests to be generated: "
271  << lNbOfRequests << "). Expected value: "
272  << lExpectedTotalNbOfEvents);
273  }
274 
275  // DEBUG
276  STDAIR_LOG_DEBUG ("=> [" << lDemandStreamKey << "][" << lCurrentNbOfEvents
277  << "/" << lExpectedTotalNbOfEvents
278  << "] is now processed. "
279  << "Still generate events for that demand stream? "
280  << stillHavingRequestsToBeGenerated);
281 
282  // If there are still events to be generated for that demand stream,
283  // generate and add them to the event queue
284  if (stillHavingRequestsToBeGenerated == true) {
285  const stdair::BookingRequestPtr_T lNextRequest_ptr =
286  trademgenService.generateNextRequest (lDemandStreamKey,
287  iDemandGenerationMethod);
288  assert (lNextRequest_ptr != NULL);
289 
295  const stdair::Duration_T lDuration =
296  lNextRequest_ptr->getRequestDateTime()
297  - lPoppedRequest.getRequestDateTime();
298  BOOST_REQUIRE_GT (lDuration.total_milliseconds(), 0);
299  BOOST_REQUIRE_MESSAGE (lDuration.total_milliseconds() > 0,
300  "[" << lDemandStreamKey
301  << "] The date-time of the generated event ("
302  << lNextRequest_ptr->getRequestDateTime()
303  << ") is lower than the date-time "
304  << "of the current event ("
305  << lPoppedRequest.getRequestDateTime() << ")");
306 
307  // DEBUG
308  STDAIR_LOG_DEBUG ("[" << lDemandStreamKey << "][" << lCurrentNbOfEvents
309  << "/" << lExpectedTotalNbOfEvents
310  << "] Added request: '" << lNextRequest_ptr->describe()
311  << "'. Is queue done? "
312  << trademgenService.isQueueDone());
313 
314  // Keep, within the dedicated map, the current counters of events updated.
315  ++lCurrentNbOfEvents;
316  itNbOfEventsMap->second = NbOfEventsPair_T (lCurrentNbOfEvents,
317  lExpectedTotalNbOfEvents);
318  }
319 
320  // Iterate
321  ++idx;
322  }
323  // Compensate for the last iteration
324  --idx;
325 
326  if (iDemandGenerationMethod == stdair::DemandGenerationMethod::STA_ORD) {
327  //
328  BOOST_CHECK_EQUAL (idx, lRefActualNbOfEvents);
329  BOOST_CHECK_MESSAGE (idx == lRefActualNbOfEvents,
330  "The total actual number of events is "
331  << lRefActualNbOfEvents << ", but " << idx
332  << " events have been generated");
333  }
334 
337  trademgenService.reset();
338 
339  // DEBUG
340  STDAIR_LOG_DEBUG ("End of the simulation");
341 
342  // Close the log file
343  logOutputFile.close();
344 
345 }
346 
347 
348 // /////////////// Main: Unit Test Suite //////////////
349 
350 // Set the UTF configuration (re-direct the output to a specific file)
351 BOOST_GLOBAL_FIXTURE (UnitTestConfig);
352 
353 // Start the test suite
354 BOOST_AUTO_TEST_SUITE (master_test_suite)
355 
356 
359 BOOST_AUTO_TEST_CASE (trademgen_simple_simulation_test) {
360 
361  // Input file name
362  const stdair::Filename_T lInputFilename (STDAIR_SAMPLE_DIR "/demand01.csv");
363 
364  // Generate the date time of the requests with the statistic order method.
365  const stdair::DemandGenerationMethod lDemandGenerationMethod (stdair::DemandGenerationMethod::STA_ORD);
366 
367  // State whether the BOM tree should be built-in or parsed from an input file
368  const bool isBuiltin = false;
369  BOOST_CHECK_NO_THROW (testDemandGenerationHelper(0,
370  lInputFilename,
371  lDemandGenerationMethod,
372  isBuiltin));
373 
374 }
375 
379 BOOST_AUTO_TEST_CASE (trademgen_missing_input_file_test) {
380 
381  // Input file name
382  const stdair::Filename_T lInputFilename (STDAIR_SAMPLE_DIR "/missingFile.csv");
383 
384  // Generate the date time of the requests with the statistic order method.
385  const stdair::DemandGenerationMethod lDemandGenerationMethod (stdair::DemandGenerationMethod::STA_ORD);
386 
387  // State whether the BOM tree should be built-in or parsed from an input file
388  const bool isBuiltin = false;
389  BOOST_CHECK_THROW (testDemandGenerationHelper(1,
390  lInputFilename,
391  lDemandGenerationMethod,
392  isBuiltin),
394 
395 }
396 
400 BOOST_AUTO_TEST_CASE (trademgen_default_bom_simulation_test) {
401 
402  // Generate the date time of the requests with the statistic order method.
403  const stdair::DemandGenerationMethod lDemandGenerationMethod (stdair::DemandGenerationMethod::STA_ORD);
404 
405  // State whether the BOM tree should be built-in or parsed from an input file
406  const bool isBuiltin = true;
407  BOOST_CHECK_NO_THROW (testDemandGenerationHelper(2,
408  " " ,
409  lDemandGenerationMethod,
410  isBuiltin));
411 
412 }
413 
417 BOOST_AUTO_TEST_CASE (trademgen_poisson_process_test) {
418 
419  // Generate the date time of the requests with the poisson process.
420  const stdair::DemandGenerationMethod lDemandGenerationMethod (stdair::DemandGenerationMethod::POI_PRO);
421 
422  // State whether the BOM tree should be built-in or parsed from an input file
423  const bool isBuiltin = true;
424  BOOST_CHECK_NO_THROW (testDemandGenerationHelper(3,
425  " " ,
426  lDemandGenerationMethod,
427  isBuiltin));
428 
429 }
430 
431 // End the test suite
432 BOOST_AUTO_TEST_SUITE_END()
433 
434 
class holding the services related to Travel Demand Generation.
#define STDAIR_SAMPLE_DIR