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