$treeview $search $mathjax
*/ // ////////////////////////////////////////////////////////////////////// // Import section // ////////////////////////////////////////////////////////////////////// // STL #include <sstream> #include <fstream> #include <map> #include <cmath> // Boost Unit Test Framework (UTF) #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MAIN #define BOOST_TEST_MODULE DemandGenerationTest #include <boost/test/unit_test.hpp> // StdAir #include <stdair/stdair_basic_types.hpp> #include <stdair/basic/BasConst_General.hpp> #include <stdair/basic/BasLogParams.hpp> #include <stdair/basic/BasDBParams.hpp> #include <stdair/basic/BasFileMgr.hpp> #include <stdair/basic/ProgressStatusSet.hpp> #include <stdair/bom/EventStruct.hpp> #include <stdair/bom/BookingRequestStruct.hpp> #include <stdair/service/Logger.hpp> // TraDemGen #include <trademgen/TRADEMGEN_Exceptions.hpp> #include <trademgen/TRADEMGEN_Service.hpp> #include <trademgen/bom/DemandStreamKey.hpp> #include <trademgen/config/trademgen-paths.hpp> namespace boost_utf = boost::unit_test; // (Boost) Unit Test XML Report std::ofstream utfReportStream ("DemandGenerationTestSuite_utfresults.xml"); struct UnitTestConfig { UnitTestConfig() { boost_utf::unit_test_log.set_stream (utfReportStream); boost_utf::unit_test_log.set_format (boost_utf::XML); boost_utf::unit_test_log.set_threshold_level (boost_utf::log_test_units); //boost_utf::unit_test_log.set_threshold_level (boost_utf::log_successful_tests); } ~UnitTestConfig() { } }; // Specific type definitions typedef std::pair<stdair::Count_T, stdair::Count_T> NbOfEventsPair_T; typedef std::map<const stdair::DemandStreamKeyStr_T, NbOfEventsPair_T> NbOfEventsByDemandStreamMap_T; // ////////////////////////////////////////////////////////////////////// void testDemandGenerationHelper (const unsigned short iTestFlag, const stdair::Filename_T& iDemandInputFilename, const stdair::DemandGenerationMethod& iDemandGenerationMethod, const bool isBuiltin) { // Seed for the random generation const stdair::RandomSeed_T lRandomSeed = stdair::DEFAULT_RANDOM_SEED; // Output log File std::ostringstream oStr; oStr << "DemandGenerationTestSuite_" << iTestFlag << ".log"; const stdair::Filename_T lLogFilename (oStr.str()); // Set the log parameters std::ofstream logOutputFile; // Open and clean the log outputfile logOutputFile.open (lLogFilename.c_str()); logOutputFile.clear(); // Initialise the TraDemGen service object const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile); TRADEMGEN::TRADEMGEN_Service trademgenService (lLogParams, lRandomSeed); NbOfEventsByDemandStreamMap_T lNbOfEventsMap; // Total number of events stdair::Count_T lRefExpectedNbOfEvents (0); stdair::Count_T lRefActualNbOfEvents (0); // Check whether or not a (CSV) input file should be read if (isBuiltin == true) { // Build the default sample BOM tree (filled with demand streams) for TraDemGen trademgenService.buildSampleBom(); lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T:: value_type ("SIN-BKK 2010-Feb-08 Y", NbOfEventsPair_T (4, 60))); lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T:: value_type ("BKK-HKG 2010-Feb-08 Y", NbOfEventsPair_T (4, 60))); lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T:: value_type ("SIN-HKG 2010-Feb-08 Y", NbOfEventsPair_T (4, 60))); // Total number of events, for the 3 demand streams: 180 lRefExpectedNbOfEvents = 180; lRefActualNbOfEvents = 186; } else { // Create the DemandStream objects, and insert them within the BOM tree const TRADEMGEN::DemandFilePath lDemandFilePath (iDemandInputFilename); trademgenService.parseAndLoad (lDemandFilePath); lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T:: value_type ("SIN-HND 2010-Feb-08 Y", NbOfEventsPair_T (1, 10))); lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T:: value_type ("SIN-HND 2010-Feb-09 Y", NbOfEventsPair_T (1, 10))); lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T:: value_type ("SIN-BKK 2010-Feb-08 Y", NbOfEventsPair_T (1, 10))); lNbOfEventsMap.insert (NbOfEventsByDemandStreamMap_T:: value_type ("SIN-BKK 2010-Feb-09 Y", NbOfEventsPair_T (1, 10))); // Total number of events, for the 4 demand streams: 40 lRefExpectedNbOfEvents = 40; lRefActualNbOfEvents = 40; } // Retrieve the expected (mean value of the) number of events to be // generated const stdair::Count_T& lExpectedNbOfEventsToBeGenerated = trademgenService.getExpectedTotalNumberOfRequestsToBeGenerated(); BOOST_CHECK_EQUAL (lRefExpectedNbOfEvents, std::floor (lExpectedNbOfEventsToBeGenerated)); BOOST_CHECK_MESSAGE (lRefExpectedNbOfEvents == std::floor (lExpectedNbOfEventsToBeGenerated), "Expected total number of requests to be generated: " << lExpectedNbOfEventsToBeGenerated << " (=> " << std::floor (lExpectedNbOfEventsToBeGenerated) << "). Reference value: " << lRefExpectedNbOfEvents); const stdair::Count_T& lActualNbOfEventsToBeGenerated = trademgenService.generateFirstRequests(iDemandGenerationMethod); // DEBUG STDAIR_LOG_DEBUG ("Expected number of events: " << lExpectedNbOfEventsToBeGenerated << ", actual: " << lActualNbOfEventsToBeGenerated); // Total number of events, for all the demand streams: BOOST_CHECK_EQUAL (lRefActualNbOfEvents, lActualNbOfEventsToBeGenerated); BOOST_CHECK_MESSAGE (lRefActualNbOfEvents == lActualNbOfEventsToBeGenerated, "Actual total number of requests to be generated: " << lExpectedNbOfEventsToBeGenerated << " (=> " << std::floor (lExpectedNbOfEventsToBeGenerated) << "). Reference value: " << lRefActualNbOfEvents); const bool isQueueDone = trademgenService.isQueueDone(); BOOST_REQUIRE_MESSAGE (isQueueDone == false, "The event queue should not be empty."); stdair::Count_T idx = 1; while (trademgenService.isQueueDone() == false) { // Get the next event from the event queue stdair::EventStruct lEventStruct; stdair::ProgressStatusSet lPPS = trademgenService.popEvent (lEventStruct); // DEBUG STDAIR_LOG_DEBUG ("Poped event: '" << lEventStruct.describe() << "'."); // Extract the corresponding demand/booking request const stdair::BookingRequestStruct& lPoppedRequest = lEventStruct.getBookingRequest(); // DEBUG STDAIR_LOG_DEBUG ("Poped booking request: '" << lPoppedRequest.describe() << "'."); // Retrieve the corresponding demand stream const stdair::DemandGeneratorKey_T& lDemandStreamKey = lPoppedRequest.getDemandGeneratorKey(); // Check that the number of booking requests to be generated are correct const NbOfEventsByDemandStreamMap_T::iterator itNbOfEventsMap = lNbOfEventsMap.find (lDemandStreamKey); BOOST_REQUIRE_MESSAGE (itNbOfEventsMap != lNbOfEventsMap.end(), "The demand stream key '" << lDemandStreamKey << "' is not expected in that test"); const NbOfEventsPair_T& lNbOfEventsPair = itNbOfEventsMap->second; stdair::Count_T lCurrentNbOfEvents = lNbOfEventsPair.first; const stdair::Count_T& lExpectedTotalNbOfEvents = lNbOfEventsPair.second; // Assess whether more events should be generated for that demand stream const bool stillHavingRequestsToBeGenerated = trademgenService. stillHavingRequestsToBeGenerated (lDemandStreamKey, lPPS, iDemandGenerationMethod); if (lCurrentNbOfEvents == 1) { const stdair::ProgressStatus& lDemandStreamProgressStatus = lPPS.getSpecificGeneratorStatus(); const stdair::Count_T& lNbOfRequests = lDemandStreamProgressStatus.getExpectedNb(); BOOST_CHECK_EQUAL (lNbOfRequests, lExpectedTotalNbOfEvents); BOOST_CHECK_MESSAGE (lNbOfRequests == lExpectedTotalNbOfEvents, "[" << lDemandStreamKey << "] Total number of requests to be generated: " << lNbOfRequests << "). Expected value: " << lExpectedTotalNbOfEvents); } // DEBUG STDAIR_LOG_DEBUG ("=> [" << lDemandStreamKey << "][" << lCurrentNbOfEvents << "/" << lExpectedTotalNbOfEvents << "] is now processed. " << "Still generate events for that demand stream? " << stillHavingRequestsToBeGenerated); // If there are still events to be generated for that demand stream, // generate and add them to the event queue if (stillHavingRequestsToBeGenerated == true) { const stdair::BookingRequestPtr_T lNextRequest_ptr = trademgenService.generateNextRequest (lDemandStreamKey, iDemandGenerationMethod); assert (lNextRequest_ptr != NULL); const stdair::Duration_T lDuration = lNextRequest_ptr->getRequestDateTime() - lPoppedRequest.getRequestDateTime(); BOOST_REQUIRE_GT (lDuration.total_milliseconds(), 0); BOOST_REQUIRE_MESSAGE (lDuration.total_milliseconds() > 0, "[" << lDemandStreamKey << "] The date-time of the generated event (" << lNextRequest_ptr->getRequestDateTime() << ") is lower than the date-time " << "of the current event (" << lPoppedRequest.getRequestDateTime() << ")"); // DEBUG STDAIR_LOG_DEBUG ("[" << lDemandStreamKey << "][" << lCurrentNbOfEvents << "/" << lExpectedTotalNbOfEvents << "] Added request: '" << lNextRequest_ptr->describe() << "'. Is queue done? " << trademgenService.isQueueDone()); // Keep, within the dedicated map, the current counters of events updated. ++lCurrentNbOfEvents; itNbOfEventsMap->second = NbOfEventsPair_T (lCurrentNbOfEvents, lExpectedTotalNbOfEvents); } // Iterate ++idx; } // Compensate for the last iteration --idx; if (iDemandGenerationMethod == stdair::DemandGenerationMethod::STA_ORD) { // BOOST_CHECK_EQUAL (idx, lRefActualNbOfEvents); BOOST_CHECK_MESSAGE (idx == lRefActualNbOfEvents, "The total actual number of events is " << lRefActualNbOfEvents << ", but " << idx << " events have been generated"); } trademgenService.reset(); // DEBUG STDAIR_LOG_DEBUG ("End of the simulation"); // Close the log file logOutputFile.close(); } // /////////////// Main: Unit Test Suite ////////////// // Set the UTF configuration (re-direct the output to a specific file) BOOST_GLOBAL_FIXTURE (UnitTestConfig); // Start the test suite BOOST_AUTO_TEST_SUITE (master_test_suite) BOOST_AUTO_TEST_CASE (trademgen_simple_simulation_test) { // Input file name const stdair::Filename_T lInputFilename (STDAIR_SAMPLE_DIR "/demand01.csv"); // Generate the date time of the requests with the statistic order method. const stdair::DemandGenerationMethod lDemandGenerationMethod (stdair::DemandGenerationMethod::STA_ORD); // State whether the BOM tree should be built-in or parsed from an input file const bool isBuiltin = false; BOOST_CHECK_NO_THROW (testDemandGenerationHelper(0, lInputFilename, lDemandGenerationMethod, isBuiltin)); } BOOST_AUTO_TEST_CASE (trademgen_missing_input_file_test) { // Input file name const stdair::Filename_T lInputFilename (STDAIR_SAMPLE_DIR "/missingFile.csv"); // Generate the date time of the requests with the statistic order method. const stdair::DemandGenerationMethod lDemandGenerationMethod (stdair::DemandGenerationMethod::STA_ORD); // State whether the BOM tree should be built-in or parsed from an input file const bool isBuiltin = false; BOOST_CHECK_THROW (testDemandGenerationHelper(1, lInputFilename, lDemandGenerationMethod, isBuiltin), TRADEMGEN::DemandInputFileNotFoundException); } BOOST_AUTO_TEST_CASE (trademgen_default_bom_simulation_test) { // Generate the date time of the requests with the statistic order method. const stdair::DemandGenerationMethod lDemandGenerationMethod (stdair::DemandGenerationMethod::STA_ORD); // State whether the BOM tree should be built-in or parsed from an input file const bool isBuiltin = true; BOOST_CHECK_NO_THROW (testDemandGenerationHelper(2, " " , lDemandGenerationMethod, isBuiltin)); } BOOST_AUTO_TEST_CASE (trademgen_poisson_process_test) { // Generate the date time of the requests with the poisson process. const stdair::DemandGenerationMethod lDemandGenerationMethod (stdair::DemandGenerationMethod::POI_PRO); // State whether the BOM tree should be built-in or parsed from an input file const bool isBuiltin = true; BOOST_CHECK_NO_THROW (testDemandGenerationHelper(3, " " , lDemandGenerationMethod, isBuiltin)); } // End the test suite BOOST_AUTO_TEST_SUITE_END() /*!