$treeview $search $mathjax
00001 00005 // ////////////////////////////////////////////////////////////////////// 00006 // Import section 00007 // ////////////////////////////////////////////////////////////////////// 00008 // STL 00009 #include <sstream> 00010 #include <fstream> 00011 #include <map> 00012 #include <cmath> 00013 // Boost Unit Test Framework (UTF) 00014 #define BOOST_TEST_DYN_LINK 00015 #define BOOST_TEST_MAIN 00016 #define BOOST_TEST_MODULE DemandGenerationTest 00017 #include <boost/test/unit_test.hpp> 00018 // StdAir 00019 #include <stdair/stdair_basic_types.hpp> 00020 #include <stdair/basic/BasConst_General.hpp> 00021 #include <stdair/basic/BasLogParams.hpp> 00022 #include <stdair/basic/BasDBParams.hpp> 00023 #include <stdair/basic/BasFileMgr.hpp> 00024 #include <stdair/basic/ProgressStatusSet.hpp> 00025 #include <stdair/bom/EventStruct.hpp> 00026 #include <stdair/bom/BookingRequestStruct.hpp> 00027 #include <stdair/service/Logger.hpp> 00028 // TraDemGen 00029 #include <trademgen/TRADEMGEN_Exceptions.hpp> 00030 #include <trademgen/TRADEMGEN_Service.hpp> 00031 #include <trademgen/bom/DemandStreamKey.hpp> 00032 #include <trademgen/config/trademgen-paths.hpp> 00033 00034 namespace boost_utf = boost::unit_test; 00035 00036 // (Boost) Unit Test XML Report 00037 std::ofstream utfReportStream ("DemandGenerationTestSuite_utfresults.xml"); 00038 00042 struct UnitTestConfig { 00044 UnitTestConfig() { 00045 boost_utf::unit_test_log.set_stream (utfReportStream); 00046 boost_utf::unit_test_log.set_format (boost_utf::XML); 00047 boost_utf::unit_test_log.set_threshold_level (boost_utf::log_test_units); 00048 //boost_utf::unit_test_log.set_threshold_level (boost_utf::log_successful_tests); 00049 } 00050 00052 ~UnitTestConfig() { 00053 } 00054 }; 00055 00056 // Specific type definitions 00057 typedef std::pair<stdair::Count_T, stdair::Count_T> NbOfEventsPair_T; 00058 typedef std::map<const stdair::DemandStreamKeyStr_T, 00059 NbOfEventsPair_T> NbOfEventsByDemandStreamMap_T; 00060 00061 // ////////////////////////////////////////////////////////////////////// 00065 void testDemandGenerationHelper (const unsigned short iTestFlag, 00066 const stdair::Filename_T& iDemandInputFilename, 00067 const stdair::DemandGenerationMethod& iDemandGenerationMethod, 00068 const bool isBuiltin) { 00069 00070 // Seed for the random generation 00071 const stdair::RandomSeed_T lRandomSeed = stdair::DEFAULT_RANDOM_SEED; 00072 00073 // Output log File 00074 std::ostringstream oStr; 00075 oStr << "DemandGenerationTestSuite_" << iTestFlag << ".log"; 00076 const stdair::Filename_T lLogFilename (oStr.str()); 00077 00078 // Set the log parameters 00079 std::ofstream logOutputFile; 00080 // Open and clean the log outputfile 00081 logOutputFile.open (lLogFilename.c_str()); 00082 logOutputFile.clear(); 00083 00084 // Initialise the TraDemGen service object 00085 const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile); 00086 TRADEMGEN::TRADEMGEN_Service trademgenService (lLogParams, lRandomSeed); 00087 00097 NbOfEventsByDemandStreamMap_T lNbOfEventsMap; 00098 00099 // Total number of events 00100 stdair::Count_T lRefExpectedNbOfEvents (0); 00101 stdair::Count_T lRefActualNbOfEvents (0); 00102 00103 // Check whether or not a (CSV) input file should be read 00104 if (isBuiltin == true) { 00105 00106 // Build the default sample BOM tree (filled with demand streams) for TraDemGen 00107 trademgenService.buildSampleBom(); 00108 00109 lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T:: 00110 value_type ("SIN-BKK 2010-Feb-08 Y", 00111 NbOfEventsPair_T (4, 60))); 00112 lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T:: 00113 value_type ("BKK-HKG 2010-Feb-08 Y", 00114 NbOfEventsPair_T (4, 60))); 00115 lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T:: 00116 value_type ("SIN-HKG 2010-Feb-08 Y", 00117 NbOfEventsPair_T (4, 60))); 00118 00119 // Total number of events, for the 3 demand streams: 180 00120 lRefExpectedNbOfEvents = 180; 00121 lRefActualNbOfEvents = 186; 00122 00123 } else { 00124 00125 // Create the DemandStream objects, and insert them within the BOM tree 00126 const TRADEMGEN::DemandFilePath lDemandFilePath (iDemandInputFilename); 00127 trademgenService.parseAndLoad (lDemandFilePath); 00128 00129 lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T:: 00130 value_type ("SIN-HND 2010-Feb-08 Y", 00131 NbOfEventsPair_T (1, 10))); 00132 lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T:: 00133 value_type ("SIN-HND 2010-Feb-09 Y", 00134 NbOfEventsPair_T (1, 10))); 00135 lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T:: 00136 value_type ("SIN-BKK 2010-Feb-08 Y", 00137 NbOfEventsPair_T (1, 10))); 00138 lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T:: 00139 value_type ("SIN-BKK 2010-Feb-09 Y", 00140 NbOfEventsPair_T (1, 10))); 00141 00142 // Total number of events, for the 4 demand streams: 40 00143 lRefExpectedNbOfEvents = 40; 00144 lRefActualNbOfEvents = 40; 00145 } 00146 00147 // Retrieve the expected (mean value of the) number of events to be 00148 // generated 00149 const stdair::Count_T& lExpectedNbOfEventsToBeGenerated = 00150 trademgenService.getExpectedTotalNumberOfRequestsToBeGenerated(); 00151 00152 BOOST_CHECK_EQUAL (lRefExpectedNbOfEvents, 00153 std::floor (lExpectedNbOfEventsToBeGenerated)); 00154 00155 BOOST_CHECK_MESSAGE (lRefExpectedNbOfEvents == 00156 std::floor (lExpectedNbOfEventsToBeGenerated), 00157 "Expected total number of requests to be generated: " 00158 << lExpectedNbOfEventsToBeGenerated 00159 << " (=> " 00160 << std::floor (lExpectedNbOfEventsToBeGenerated) 00161 << "). Reference value: " << lRefExpectedNbOfEvents); 00162 00168 const stdair::Count_T& lActualNbOfEventsToBeGenerated = 00169 trademgenService.generateFirstRequests(iDemandGenerationMethod); 00170 00171 // DEBUG 00172 STDAIR_LOG_DEBUG ("Expected number of events: " 00173 << lExpectedNbOfEventsToBeGenerated << ", actual: " 00174 << lActualNbOfEventsToBeGenerated); 00175 00176 // Total number of events, for all the demand streams: 00177 BOOST_CHECK_EQUAL (lRefActualNbOfEvents, lActualNbOfEventsToBeGenerated); 00178 00179 BOOST_CHECK_MESSAGE (lRefActualNbOfEvents == lActualNbOfEventsToBeGenerated, 00180 "Actual total number of requests to be generated: " 00181 << lExpectedNbOfEventsToBeGenerated 00182 << " (=> " 00183 << std::floor (lExpectedNbOfEventsToBeGenerated) 00184 << "). Reference value: " << lRefActualNbOfEvents); 00185 00187 const bool isQueueDone = trademgenService.isQueueDone(); 00188 BOOST_REQUIRE_MESSAGE (isQueueDone == false, 00189 "The event queue should not be empty."); 00190 00198 stdair::Count_T idx = 1; 00199 while (trademgenService.isQueueDone() == false) { 00200 00201 // Get the next event from the event queue 00202 stdair::EventStruct lEventStruct; 00203 stdair::ProgressStatusSet lPPS = trademgenService.popEvent (lEventStruct); 00204 00205 // DEBUG 00206 STDAIR_LOG_DEBUG ("Poped event: '" << lEventStruct.describe() << "'."); 00207 00208 // Extract the corresponding demand/booking request 00209 const stdair::BookingRequestStruct& lPoppedRequest = 00210 lEventStruct.getBookingRequest(); 00211 00212 // DEBUG 00213 STDAIR_LOG_DEBUG ("Poped booking request: '" 00214 << lPoppedRequest.describe() << "'."); 00215 00216 // Retrieve the corresponding demand stream 00217 const stdair::DemandGeneratorKey_T& lDemandStreamKey = 00218 lPoppedRequest.getDemandGeneratorKey(); 00219 00220 // Check that the number of booking requests to be generated are correct 00221 const NbOfEventsByDemandStreamMap_T::iterator itNbOfEventsMap = 00222 lNbOfEventsMap.find (lDemandStreamKey); 00223 BOOST_REQUIRE_MESSAGE (itNbOfEventsMap != lNbOfEventsMap.end(), 00224 "The demand stream key '" << lDemandStreamKey 00225 << "' is not expected in that test"); 00226 00236 const NbOfEventsPair_T& lNbOfEventsPair = itNbOfEventsMap->second; 00237 stdair::Count_T lCurrentNbOfEvents = lNbOfEventsPair.first; 00238 const stdair::Count_T& lExpectedTotalNbOfEvents = lNbOfEventsPair.second; 00239 00240 // Assess whether more events should be generated for that demand stream 00241 const bool stillHavingRequestsToBeGenerated = trademgenService. 00242 stillHavingRequestsToBeGenerated (lDemandStreamKey, lPPS, 00243 iDemandGenerationMethod); 00244 00251 if (lCurrentNbOfEvents == 1) { 00257 const stdair::ProgressStatus& lDemandStreamProgressStatus = 00258 lPPS.getSpecificGeneratorStatus(); 00259 const stdair::Count_T& lNbOfRequests = 00260 lDemandStreamProgressStatus.getExpectedNb(); 00261 00262 BOOST_CHECK_EQUAL (lNbOfRequests, lExpectedTotalNbOfEvents); 00263 BOOST_CHECK_MESSAGE (lNbOfRequests == lExpectedTotalNbOfEvents, 00264 "[" << lDemandStreamKey 00265 << "] Total number of requests to be generated: " 00266 << lNbOfRequests << "). Expected value: " 00267 << lExpectedTotalNbOfEvents); 00268 } 00269 00270 // DEBUG 00271 STDAIR_LOG_DEBUG ("=> [" << lDemandStreamKey << "][" << lCurrentNbOfEvents 00272 << "/" << lExpectedTotalNbOfEvents 00273 << "] is now processed. " 00274 << "Still generate events for that demand stream? " 00275 << stillHavingRequestsToBeGenerated); 00276 00277 // If there are still events to be generated for that demand stream, 00278 // generate and add them to the event queue 00279 if (stillHavingRequestsToBeGenerated == true) { 00280 const stdair::BookingRequestPtr_T lNextRequest_ptr = 00281 trademgenService.generateNextRequest (lDemandStreamKey, 00282 iDemandGenerationMethod); 00283 assert (lNextRequest_ptr != NULL); 00284 00290 const stdair::Duration_T lDuration = 00291 lNextRequest_ptr->getRequestDateTime() 00292 - lPoppedRequest.getRequestDateTime(); 00293 BOOST_REQUIRE_GT (lDuration.total_milliseconds(), 0); 00294 BOOST_REQUIRE_MESSAGE (lDuration.total_milliseconds() > 0, 00295 "[" << lDemandStreamKey 00296 << "] The date-time of the generated event (" 00297 << lNextRequest_ptr->getRequestDateTime() 00298 << ") is lower than the date-time " 00299 << "of the current event (" 00300 << lPoppedRequest.getRequestDateTime() << ")"); 00301 00302 // DEBUG 00303 STDAIR_LOG_DEBUG ("[" << lDemandStreamKey << "][" << lCurrentNbOfEvents 00304 << "/" << lExpectedTotalNbOfEvents 00305 << "] Added request: '" << lNextRequest_ptr->describe() 00306 << "'. Is queue done? " 00307 << trademgenService.isQueueDone()); 00308 00309 // Keep, within the dedicated map, the current counters of events updated. 00310 ++lCurrentNbOfEvents; 00311 itNbOfEventsMap->second = NbOfEventsPair_T (lCurrentNbOfEvents, 00312 lExpectedTotalNbOfEvents); 00313 } 00314 00315 // Iterate 00316 ++idx; 00317 } 00318 // Compensate for the last iteration 00319 --idx; 00320 00321 if (iDemandGenerationMethod == stdair::DemandGenerationMethod::STA_ORD) { 00322 // 00323 BOOST_CHECK_EQUAL (idx, lRefActualNbOfEvents); 00324 BOOST_CHECK_MESSAGE (idx == lRefActualNbOfEvents, 00325 "The total actual number of events is " 00326 << lRefActualNbOfEvents << ", but " << idx 00327 << " events have been generated"); 00328 } 00329 00332 trademgenService.reset(); 00333 00334 // DEBUG 00335 STDAIR_LOG_DEBUG ("End of the simulation"); 00336 00337 // Close the log file 00338 logOutputFile.close(); 00339 00340 } 00341 00342 00343 // /////////////// Main: Unit Test Suite ////////////// 00344 00345 // Set the UTF configuration (re-direct the output to a specific file) 00346 BOOST_GLOBAL_FIXTURE (UnitTestConfig); 00347 00348 // Start the test suite 00349 BOOST_AUTO_TEST_SUITE (master_test_suite) 00350 00351 00354 BOOST_AUTO_TEST_CASE (trademgen_simple_simulation_test) { 00355 00356 // Input file name 00357 const stdair::Filename_T lInputFilename (STDAIR_SAMPLE_DIR "/demand01.csv"); 00358 00359 // Generate the date time of the requests with the statistic order method. 00360 const stdair::DemandGenerationMethod lDemandGenerationMethod (stdair::DemandGenerationMethod::STA_ORD); 00361 00362 // State whether the BOM tree should be built-in or parsed from an input file 00363 const bool isBuiltin = false; 00364 BOOST_CHECK_NO_THROW (testDemandGenerationHelper(0, 00365 lInputFilename, 00366 lDemandGenerationMethod, 00367 isBuiltin)); 00368 00369 } 00370 00374 BOOST_AUTO_TEST_CASE (trademgen_missing_input_file_test) { 00375 00376 // Input file name 00377 const stdair::Filename_T lInputFilename (STDAIR_SAMPLE_DIR "/missingFile.csv"); 00378 00379 // Generate the date time of the requests with the statistic order method. 00380 const stdair::DemandGenerationMethod lDemandGenerationMethod (stdair::DemandGenerationMethod::STA_ORD); 00381 00382 // State whether the BOM tree should be built-in or parsed from an input file 00383 const bool isBuiltin = false; 00384 BOOST_CHECK_THROW (testDemandGenerationHelper(1, 00385 lInputFilename, 00386 lDemandGenerationMethod, 00387 isBuiltin), 00388 TRADEMGEN::DemandInputFileNotFoundException); 00389 00390 } 00391 00395 BOOST_AUTO_TEST_CASE (trademgen_default_bom_simulation_test) { 00396 00397 // Generate the date time of the requests with the statistic order method. 00398 const stdair::DemandGenerationMethod lDemandGenerationMethod (stdair::DemandGenerationMethod::STA_ORD); 00399 00400 // State whether the BOM tree should be built-in or parsed from an input file 00401 const bool isBuiltin = true; 00402 BOOST_CHECK_NO_THROW (testDemandGenerationHelper(2, 00403 " " , 00404 lDemandGenerationMethod, 00405 isBuiltin)); 00406 00407 } 00408 00412 BOOST_AUTO_TEST_CASE (trademgen_poisson_process_test) { 00413 00414 // Generate the date time of the requests with the poisson process. 00415 const stdair::DemandGenerationMethod lDemandGenerationMethod (stdair::DemandGenerationMethod::POI_PRO); 00416 00417 // State whether the BOM tree should be built-in or parsed from an input file 00418 const bool isBuiltin = true; 00419 BOOST_CHECK_NO_THROW (testDemandGenerationHelper(3, 00420 " " , 00421 lDemandGenerationMethod, 00422 isBuiltin)); 00423 00424 } 00425 00426 // End the test suite 00427 BOOST_AUTO_TEST_SUITE_END() 00428 00429