TraDemGen Logo  1.00.0
C++ Simulated Travel Demand Generation Library
 All Classes Namespaces Files Functions Variables Typedefs Friends Pages
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 // StdAir
19 #include <stdair/stdair_basic_types.hpp>
20 #include <stdair/basic/BasConst_General.hpp>
21 #include <stdair/basic/BasLogParams.hpp>
22 #include <stdair/basic/BasDBParams.hpp>
23 #include <stdair/basic/BasFileMgr.hpp>
24 #include <stdair/basic/ProgressStatusSet.hpp>
25 #include <stdair/bom/EventStruct.hpp>
26 #include <stdair/bom/BookingRequestStruct.hpp>
27 #include <stdair/service/Logger.hpp>
28 // TraDemGen
32 #include <trademgen/config/trademgen-paths.hpp>
33 
34 namespace boost_utf = boost::unit_test;
35 
36 // (Boost) Unit Test XML Report
37 std::ofstream utfReportStream ("DemandGenerationTestSuite_utfresults.xml");
38 
42 struct UnitTestConfig {
44  UnitTestConfig() {
45  boost_utf::unit_test_log.set_stream (utfReportStream);
46  boost_utf::unit_test_log.set_format (boost_utf::XML);
47  boost_utf::unit_test_log.set_threshold_level (boost_utf::log_test_units);
48  //boost_utf::unit_test_log.set_threshold_level (boost_utf::log_successful_tests);
49  }
50 
52  ~UnitTestConfig() {
53  }
54 };
55 
56 // Specific type definitions
57 typedef std::pair<stdair::Count_T, stdair::Count_T> NbOfEventsPair_T;
58 typedef std::map<const stdair::DemandStreamKeyStr_T,
59  NbOfEventsPair_T> NbOfEventsByDemandStreamMap_T;
60 
61 // //////////////////////////////////////////////////////////////////////
65 void testDemandGenerationHelper (const unsigned short iTestFlag,
66  const stdair::Filename_T& iDemandInputFilename,
67  const stdair::DemandGenerationMethod& iDemandGenerationMethod,
68  const bool isBuiltin) {
69 
70  // Seed for the random generation
71  const stdair::RandomSeed_T lRandomSeed = stdair::DEFAULT_RANDOM_SEED;
72 
73  // Output log File
74  std::ostringstream oStr;
75  oStr << "DemandGenerationTestSuite_" << iTestFlag << ".log";
76  const stdair::Filename_T lLogFilename (oStr.str());
77 
78  // Set the log parameters
79  std::ofstream logOutputFile;
80  // Open and clean the log outputfile
81  logOutputFile.open (lLogFilename.c_str());
82  logOutputFile.clear();
83 
84  // Initialise the TraDemGen service object
85  const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
86  TRADEMGEN::TRADEMGEN_Service trademgenService (lLogParams, lRandomSeed);
87 
97  NbOfEventsByDemandStreamMap_T lNbOfEventsMap;
98 
99  // Total number of events
100  stdair::Count_T lRefExpectedNbOfEvents (0);
101  stdair::Count_T lRefActualNbOfEvents (0);
102 
103  // Check whether or not a (CSV) input file should be read
104  if (isBuiltin == true) {
105 
106  // Build the default sample BOM tree (filled with demand streams) for TraDemGen
107  trademgenService.buildSampleBom();
108 
109  lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
110  value_type ("SIN-BKK 2010-Feb-08 Y",
111  NbOfEventsPair_T (4, 60)));
112  lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
113  value_type ("BKK-HKG 2010-Feb-08 Y",
114  NbOfEventsPair_T (4, 60)));
115  lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
116  value_type ("SIN-HKG 2010-Feb-08 Y",
117  NbOfEventsPair_T (4, 60)));
118 
119  // Total number of events, for the 3 demand streams: 180
120  lRefExpectedNbOfEvents = 180;
121  lRefActualNbOfEvents = 186;
122 
123  } else {
124 
125  // Create the DemandStream objects, and insert them within the BOM tree
126  const TRADEMGEN::DemandFilePath lDemandFilePath (iDemandInputFilename);
127  trademgenService.parseAndLoad (lDemandFilePath);
128 
129  lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
130  value_type ("SIN-HND 2010-Feb-08 Y",
131  NbOfEventsPair_T (1, 10)));
132  lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
133  value_type ("SIN-HND 2010-Feb-09 Y",
134  NbOfEventsPair_T (1, 10)));
135  lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
136  value_type ("SIN-BKK 2010-Feb-08 Y",
137  NbOfEventsPair_T (1, 10)));
138  lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T::
139  value_type ("SIN-BKK 2010-Feb-09 Y",
140  NbOfEventsPair_T (1, 10)));
141 
142  // Total number of events, for the 4 demand streams: 40
143  lRefExpectedNbOfEvents = 40;
144  lRefActualNbOfEvents = 40;
145  }
146 
147  // Retrieve the expected (mean value of the) number of events to be
148  // generated
149  const stdair::Count_T& lExpectedNbOfEventsToBeGenerated =
150  trademgenService.getExpectedTotalNumberOfRequestsToBeGenerated();
151 
152  BOOST_CHECK_EQUAL (lRefExpectedNbOfEvents,
153  std::floor (lExpectedNbOfEventsToBeGenerated));
154 
155  BOOST_CHECK_MESSAGE (lRefExpectedNbOfEvents ==
156  std::floor (lExpectedNbOfEventsToBeGenerated),
157  "Expected total number of requests to be generated: "
158  << lExpectedNbOfEventsToBeGenerated
159  << " (=> "
160  << std::floor (lExpectedNbOfEventsToBeGenerated)
161  << "). Reference value: " << lRefExpectedNbOfEvents);
162 
168  const stdair::Count_T& lActualNbOfEventsToBeGenerated =
169  trademgenService.generateFirstRequests(iDemandGenerationMethod);
170 
171  // DEBUG
172  STDAIR_LOG_DEBUG ("Expected number of events: "
173  << lExpectedNbOfEventsToBeGenerated << ", actual: "
174  << lActualNbOfEventsToBeGenerated);
175 
176  // Total number of events, for all the demand streams:
177  BOOST_CHECK_EQUAL (lRefActualNbOfEvents, lActualNbOfEventsToBeGenerated);
178 
179  BOOST_CHECK_MESSAGE (lRefActualNbOfEvents == lActualNbOfEventsToBeGenerated,
180  "Actual total number of requests to be generated: "
181  << lExpectedNbOfEventsToBeGenerated
182  << " (=> "
183  << std::floor (lExpectedNbOfEventsToBeGenerated)
184  << "). Reference value: " << lRefActualNbOfEvents);
185 
187  const bool isQueueDone = trademgenService.isQueueDone();
188  BOOST_REQUIRE_MESSAGE (isQueueDone == false,
189  "The event queue should not be empty.");
190 
198  stdair::Count_T idx = 1;
199  while (trademgenService.isQueueDone() == false) {
200 
201  // Get the next event from the event queue
202  stdair::EventStruct lEventStruct;
203  stdair::ProgressStatusSet lPPS = trademgenService.popEvent (lEventStruct);
204 
205  // DEBUG
206  STDAIR_LOG_DEBUG ("Poped event: '" << lEventStruct.describe() << "'.");
207 
208  // Extract the corresponding demand/booking request
209  const stdair::BookingRequestStruct& lPoppedRequest =
210  lEventStruct.getBookingRequest();
211 
212  // DEBUG
213  STDAIR_LOG_DEBUG ("Poped booking request: '"
214  << lPoppedRequest.describe() << "'.");
215 
216  // Retrieve the corresponding demand stream
217  const stdair::DemandGeneratorKey_T& lDemandStreamKey =
218  lPoppedRequest.getDemandGeneratorKey();
219 
220  // Check that the number of booking requests to be generated are correct
221  const NbOfEventsByDemandStreamMap_T::iterator itNbOfEventsMap =
222  lNbOfEventsMap.find (lDemandStreamKey);
223  BOOST_REQUIRE_MESSAGE (itNbOfEventsMap != lNbOfEventsMap.end(),
224  "The demand stream key '" << lDemandStreamKey
225  << "' is not expected in that test");
226 
236  const NbOfEventsPair_T& lNbOfEventsPair = itNbOfEventsMap->second;
237  stdair::Count_T lCurrentNbOfEvents = lNbOfEventsPair.first;
238  const stdair::Count_T& lExpectedTotalNbOfEvents = lNbOfEventsPair.second;
239 
240  // Assess whether more events should be generated for that demand stream
241  const bool stillHavingRequestsToBeGenerated = trademgenService.
242  stillHavingRequestsToBeGenerated (lDemandStreamKey, lPPS,
243  iDemandGenerationMethod);
244 
251  if (lCurrentNbOfEvents == 1) {
257  const stdair::ProgressStatus& lDemandStreamProgressStatus =
258  lPPS.getSpecificGeneratorStatus();
259  const stdair::Count_T& lNbOfRequests =
260  lDemandStreamProgressStatus.getExpectedNb();
261 
262  BOOST_CHECK_EQUAL (lNbOfRequests, lExpectedTotalNbOfEvents);
263  BOOST_CHECK_MESSAGE (lNbOfRequests == lExpectedTotalNbOfEvents,
264  "[" << lDemandStreamKey
265  << "] Total number of requests to be generated: "
266  << lNbOfRequests << "). Expected value: "
267  << lExpectedTotalNbOfEvents);
268  }
269 
270  // DEBUG
271  STDAIR_LOG_DEBUG ("=> [" << lDemandStreamKey << "][" << lCurrentNbOfEvents
272  << "/" << lExpectedTotalNbOfEvents
273  << "] is now processed. "
274  << "Still generate events for that demand stream? "
275  << stillHavingRequestsToBeGenerated);
276 
277  // If there are still events to be generated for that demand stream,
278  // generate and add them to the event queue
279  if (stillHavingRequestsToBeGenerated == true) {
280  const stdair::BookingRequestPtr_T lNextRequest_ptr =
281  trademgenService.generateNextRequest (lDemandStreamKey,
282  iDemandGenerationMethod);
283  assert (lNextRequest_ptr != NULL);
284 
290  const stdair::Duration_T lDuration =
291  lNextRequest_ptr->getRequestDateTime()
292  - lPoppedRequest.getRequestDateTime();
293  BOOST_REQUIRE_GT (lDuration.total_milliseconds(), 0);
294  BOOST_REQUIRE_MESSAGE (lDuration.total_milliseconds() > 0,
295  "[" << lDemandStreamKey
296  << "] The date-time of the generated event ("
297  << lNextRequest_ptr->getRequestDateTime()
298  << ") is lower than the date-time "
299  << "of the current event ("
300  << lPoppedRequest.getRequestDateTime() << ")");
301 
302  // DEBUG
303  STDAIR_LOG_DEBUG ("[" << lDemandStreamKey << "][" << lCurrentNbOfEvents
304  << "/" << lExpectedTotalNbOfEvents
305  << "] Added request: '" << lNextRequest_ptr->describe()
306  << "'. Is queue done? "
307  << trademgenService.isQueueDone());
308 
309  // Keep, within the dedicated map, the current counters of events updated.
310  ++lCurrentNbOfEvents;
311  itNbOfEventsMap->second = NbOfEventsPair_T (lCurrentNbOfEvents,
312  lExpectedTotalNbOfEvents);
313  }
314 
315  // Iterate
316  ++idx;
317  }
318  // Compensate for the last iteration
319  --idx;
320 
321  if (iDemandGenerationMethod == stdair::DemandGenerationMethod::STA_ORD) {
322  //
323  BOOST_CHECK_EQUAL (idx, lRefActualNbOfEvents);
324  BOOST_CHECK_MESSAGE (idx == lRefActualNbOfEvents,
325  "The total actual number of events is "
326  << lRefActualNbOfEvents << ", but " << idx
327  << " events have been generated");
328  }
329 
332  trademgenService.reset();
333 
334  // DEBUG
335  STDAIR_LOG_DEBUG ("End of the simulation");
336 
337  // Close the log file
338  logOutputFile.close();
339 
340 }
341 
342 
343 // /////////////// Main: Unit Test Suite //////////////
344 
345 // Set the UTF configuration (re-direct the output to a specific file)
346 BOOST_GLOBAL_FIXTURE (UnitTestConfig);
347 
348 // Start the test suite
349 BOOST_AUTO_TEST_SUITE (master_test_suite)
350 
351 
354 BOOST_AUTO_TEST_CASE (trademgen_simple_simulation_test) {
355 
356  // Input file name
357  const stdair::Filename_T lInputFilename (STDAIR_SAMPLE_DIR "/demand01.csv");
358 
359  // Generate the date time of the requests with the statistic order method.
360  const stdair::DemandGenerationMethod lDemandGenerationMethod (stdair::DemandGenerationMethod::STA_ORD);
361 
362  // State whether the BOM tree should be built-in or parsed from an input file
363  const bool isBuiltin = false;
364  BOOST_CHECK_NO_THROW (testDemandGenerationHelper(0,
365  lInputFilename,
366  lDemandGenerationMethod,
367  isBuiltin));
368 
369 }
370 
374 BOOST_AUTO_TEST_CASE (trademgen_missing_input_file_test) {
375 
376  // Input file name
377  const stdair::Filename_T lInputFilename (STDAIR_SAMPLE_DIR "/missingFile.csv");
378 
379  // Generate the date time of the requests with the statistic order method.
380  const stdair::DemandGenerationMethod lDemandGenerationMethod (stdair::DemandGenerationMethod::STA_ORD);
381 
382  // State whether the BOM tree should be built-in or parsed from an input file
383  const bool isBuiltin = false;
384  BOOST_CHECK_THROW (testDemandGenerationHelper(1,
385  lInputFilename,
386  lDemandGenerationMethod,
387  isBuiltin),
389 
390 }
391 
395 BOOST_AUTO_TEST_CASE (trademgen_default_bom_simulation_test) {
396 
397  // Generate the date time of the requests with the statistic order method.
398  const stdair::DemandGenerationMethod lDemandGenerationMethod (stdair::DemandGenerationMethod::STA_ORD);
399 
400  // State whether the BOM tree should be built-in or parsed from an input file
401  const bool isBuiltin = true;
402  BOOST_CHECK_NO_THROW (testDemandGenerationHelper(2,
403  " " ,
404  lDemandGenerationMethod,
405  isBuiltin));
406 
407 }
408 
412 BOOST_AUTO_TEST_CASE (trademgen_poisson_process_test) {
413 
414  // Generate the date time of the requests with the poisson process.
415  const stdair::DemandGenerationMethod lDemandGenerationMethod (stdair::DemandGenerationMethod::POI_PRO);
416 
417  // State whether the BOM tree should be built-in or parsed from an input file
418  const bool isBuiltin = true;
419  BOOST_CHECK_NO_THROW (testDemandGenerationHelper(3,
420  " " ,
421  lDemandGenerationMethod,
422  isBuiltin));
423 
424 }
425 
426 // End the test suite
427 BOOST_AUTO_TEST_SUITE_END()
428 
429