![]() |
RTBKit
0.9
Open-source framework to create real-time ad bidding systems.
|
00001 /* redis_banker_test.cc 00002 Sunil Rottoo, 4th April 2012 00003 Copyright (c) 2012 Datacratic. All rights reserved. 00004 00005 Test for the banker class. 00006 */ 00007 00008 #define BOOST_TEST_MAIN 00009 #define BOOST_TEST_DYN_LINK 00010 00011 #include <boost/test/unit_test.hpp> 00012 #include "jml/arch/format.h" 00013 #include "jml/arch/exception_handler.h" 00014 #include "jml/utils/guard.h" 00015 #include "rtbkit/plugins/bidding_agent/bidding_agent.h" 00016 #include "rtbkit/core/banker/redis_banker.h" 00017 #include "rtbkit/common/auction.h" 00018 #include "rtbkit/core/router/router.h" 00019 #include "jml/utils/environment.h" 00020 #include "jml/arch/timers.h" 00021 #include "dataflow/work_scheduler.h" 00022 #include <future> 00023 #include "soa/service/testing/redis_temporary_server.h" 00024 #include <boost/thread/thread.hpp> 00025 00026 00027 using namespace std; 00028 using namespace ML; 00029 using namespace Datacratic; 00030 using namespace RTBKIT; 00031 using namespace Redis; 00032 00033 const StrategyInfo & getStrategyInfo(const RedisBanker &theBanker, 00034 const std::string &campaign, const std::string &strategy) 00035 { 00036 const Campaigns &theCampaigns = theBanker.getCampaigns(); 00037 Campaigns::const_iterator found = theCampaigns.find(campaign); 00038 BOOST_CHECK(found != theCampaigns.end()); 00039 00040 const Strategies &memStrategies = 00041 theCampaigns.find(campaign)->second.strategies_; 00042 const StrategyInfo &stratinfo = memStrategies.find(strategy)->second; 00043 return stratinfo; 00044 } 00045 00046 BOOST_AUTO_TEST_CASE( test_banker_new_campaign ) 00047 { 00048 auto s = std::make_shared<ServiceProxies>(); 00049 RedisTemporaryServer redis; 00050 RedisBanker banker("bankerTest", "b", s, redis); 00051 RedisBudgetController controller("bankerTest", redis); 00052 00053 auto campaign = banker.getCampaignStatusJson("hello", ""); 00054 cerr << campaign << endl; 00055 00056 auto strategy = banker.getCampaignStatusJson("hello", "world"); 00057 cerr << strategy << endl; 00058 00059 BOOST_CHECK_EQUAL(banker.authorizeBid("hello", "world", "one", MicroUSD(1)), 00060 false); 00061 00062 controller.topupTransferSync("hello", "world", MicroUSD(10)); 00063 } 00064 00065 BOOST_AUTO_TEST_CASE( test_transfer_all_remaining ) 00066 { 00067 // Test for ADGR-188 00068 // When we try to transfer more to a strategy than is available, we 00069 // should not simply fail, but transfer all that we can 00070 00071 auto s = std::make_shared<ServiceProxies>(); 00072 RedisTemporaryServer redis; 00073 RedisBudgetController controller("bankerTest", redis); 00074 controller.addCampaignSync("testCampaign"); 00075 controller.addStrategySync("testCampaign", "testStrategy"); 00076 controller.setBudgetSync("testCampaign", MicroUSD(1000)); 00077 controller.topupTransferSync("testCampaign", "testStrategy", 00078 MicroUSD(10000)); 00079 00080 RedisBanker banker("bankerTest", "b", s, redis); 00081 00082 banker.sync(); 00083 Json::Value status = banker.getCampaignStatusJson("testCampaign", ""); 00084 00085 cerr << status << endl; 00086 00087 BOOST_CHECK_EQUAL(status["available"]["micro-USD"].asInt(), 0); 00088 BOOST_CHECK_EQUAL(status["strategies"][0]["available"]["micro-USD"].asInt(), 1000); 00089 BOOST_CHECK_EQUAL(status["strategies"][0]["transferred"]["micro-USD"].asInt(), 1000); 00090 } 00091 00092 #if 1 00093 BOOST_AUTO_TEST_CASE( test_banker_basic ) 00094 { 00095 { 00096 std::string campaignName = "TestCampaign"; 00097 std::string campaign2 = "TestCampaign2"; 00098 std::string campaign3 = "TestCampaign3"; 00099 std::string campaign4 = "TestCampaign4"; 00100 std::string campaign5 = "TestCampaign5"; 00101 std::string campaign6 = "TestCampaign6"; 00102 std::string campaign7 = "TestCampaign7"; 00103 std::string strategy1 = "strategy1"; 00104 std::string strategy2 = "strategy2"; 00105 00106 string campaignPrefix = "bankerTest"; 00107 00108 RedisTemporaryServer redis; 00109 00110 Redis::AsyncConnection dbConn(redis); 00111 00112 auto REDIS_CHECK_CAMPAIGN_EQUAL = [&](const string &key, const string &hash, 00113 uint64_t value) 00114 { 00115 Reply reply = dbConn.exec(HGET(campaignPrefix + ":" + key, key)).reply(); 00116 if (reply.type() != ARRAY) 00117 { 00118 return false; 00119 } 00120 if (reply.length() == 0) 00121 { 00122 return false; 00123 } 00124 cerr << "reply is " << reply << endl; 00125 //uint64_t readValue = boost::lexical_cast<uint64_t>(reply[]) 00126 return true; 00127 }; 00128 00129 unsigned testNum = 1; 00130 00131 auto s = std::make_shared<ServiceProxies>(); 00132 { 00133 // add two campaigns - one with no strategies and one with 2 strategies 00134 // and make sure they load property 00135 auto runCommand = [&] (Redis::Command command) 00136 { 00137 Reply reply1 = dbConn.exec(command).reply(); 00138 //cerr << "command = " << command << endl; 00139 //cerr << "reply1.type() = " << reply1.type() << endl; 00140 //cerr << "reply1.asJson() = " << reply1.asJson() << endl; 00141 //cerr << "reply1 = " << reply1 << endl; 00142 BOOST_CHECK_EQUAL(reply1.asString(), "OK"); 00143 }; 00144 00145 auto setCampaign = [&] (std::string campaign, 00146 uint64_t available) 00147 { 00148 runCommand(HMSET(campaignPrefix + ":" + campaign, 00149 "available:micro-USD", available)); 00150 }; 00151 00152 auto setStrategy = [&] (std::string campaign, std::string strategy, 00153 uint64_t available, 00154 uint64_t spent, 00155 uint64_t transferred) 00156 { 00157 runCommand(HMSET(campaignPrefix + ":" + campaign 00158 + ":" + strategy, 00159 "available:micro-USD", available, 00160 "spent:micro-USD", spent, 00161 "transferred:micro-USD", transferred)); 00162 }; 00163 00164 setCampaign("TestCampaign6", 1000000); 00165 00166 setCampaign("TestCampaign7", 2000000); 00167 setStrategy("TestCampaign7", "strategy1", 100000, 100000, 200000); 00168 setStrategy("TestCampaign7", "strategy2", 0, 200000, 200000); 00169 00170 setCampaign("TestCampaign4", 1000000); 00171 setStrategy("TestCampaign4", "strategy1", 90000, 10000, 100000); 00172 } 00173 00174 // Check that if we supply the wrong redis port we fail to connect 00175 BOOST_CHECK_THROW(RedisBanker("xxx", "b", s, 00176 Redis::Address::tcp("dev2", 6377)), 00177 ML::Exception); 00178 // Check that if we supply the wrong redis hostname we fail to connect 00179 BOOST_CHECK_THROW(RedisBanker("xxx", "b", s, 00180 Redis::Address::tcp("fred", 6379)), 00181 ML::Exception); 00182 00183 // Now create a valid banker 00184 cerr <<"Creating banker and loading all campaigns" << endl; 00185 00186 RedisBanker theBanker("bankerTest", "b", s, redis); 00187 RedisBudgetController theController("bankerTest", redis); 00188 cerr << "done creating banker" << endl; 00189 { 00190 Json::Value result = theBanker.dumpAllCampaignsJson(); 00191 00192 BOOST_CHECK_EQUAL(result.isMember(campaign6), true); 00193 00194 cerr << "All Campaigns: " << result << endl; 00195 cerr << "\t" << testNum++ << ". Checking that campaign 6 was loaded correctly." 00196 << endl; 00197 theController.addCampaignSync(campaign6); 00198 00199 // Make sure that we have the correct values 00200 CampaignInfo campaign = theBanker.getCampaignDebug(campaign6); 00201 BOOST_CHECK_EQUAL(campaign.available_,MicroUSD(1000000)); 00202 REDIS_CHECK_CAMPAIGN_EQUAL(campaign6, "available_", 1000000); 00203 BOOST_CHECK(campaign.transferred_.empty()); 00204 // Make sure that there are no strategies 00205 const Strategies &strats = campaign.strategies_; 00206 BOOST_CHECK_EQUAL(strats.size(), 0); 00207 } 00208 { 00209 cerr << "\t" << testNum++ << ". Checking that campaign7 was loaded correctly." 00210 << endl; 00211 theController.addCampaignSync(campaign7); 00212 CampaignInfo campaign = theBanker.getCampaignDebug(campaign7); 00213 00214 // Make sure that we have the correct values 00215 BOOST_CHECK_EQUAL(campaign.available_,MicroUSD(2000000)); 00216 BOOST_CHECK_EQUAL(campaign.transferred_,MicroUSD(400000)); 00217 // Make sure that both strategies are in there 00218 const Strategies &strats = campaign.strategies_; 00219 BOOST_CHECK_EQUAL(strats.size(), 2); 00220 Strategies::const_iterator found1 = strats.find(strategy1); 00221 BOOST_CHECK(found1 != strats.end()); 00222 if(found1 != strats.end()) 00223 { 00224 BOOST_CHECK_EQUAL(found1->second.available_, MicroUSD(100000)); 00225 BOOST_CHECK_EQUAL(found1->second.spent_, MicroUSD(100000)); 00226 BOOST_CHECK_EQUAL(found1->second.transferred_, MicroUSD(200000)); 00227 } 00228 Strategies::const_iterator found2 = strats.find(strategy2); 00229 BOOST_CHECK(found2 != strats.end()); 00230 if(found2 != strats.end()) 00231 { 00232 BOOST_CHECK_EQUAL(found2->second.available_, MicroUSD(0)); 00233 BOOST_CHECK_EQUAL(found2->second.spent_, MicroUSD(200000)); 00234 BOOST_CHECK_EQUAL(found2->second.transferred_, MicroUSD(200000)); 00235 } 00236 BOOST_CHECK_EQUAL(campaign.spent_, 00237 found1->second.spent_ + found2->second.spent_); 00238 } 00239 // Check that we do not accept a campaign that is an empty string 00240 auto addCampaign1 = [&]() 00241 { 00242 theController.addCampaignSync(""); 00243 }; 00244 BOOST_CHECK_THROW(addCampaign1(), BankerException); 00245 00246 // Now add a valid campaign 00247 { 00248 theController.addCampaignSync(campaignName); 00249 CampaignInfo campaign = theBanker.getCampaignDebug(campaignName); 00250 cerr << "\t" << testNum++ << ". Added TestCampaign got the result: " 00251 << campaign << endl; 00252 BOOST_CHECK(campaign.available_.empty()); 00253 } 00254 // Now add a budget to an existing campaign 00255 { 00256 // create a $500 campaign 00257 theController.setBudgetSync(campaignName, USD(500)); 00258 theBanker.sync(); 00259 CampaignInfo campaign = theBanker.getCampaignDebug(campaignName); 00260 cerr << "\t" << testNum++ << ". Set the budget for : " << campaign 00261 << endl; 00262 BOOST_CHECK_EQUAL(campaign.available_, USD(500)); 00263 } 00264 // Now add a strategy 1 to a campaign 00265 { 00266 theController.addStrategySync(campaignName, strategy1); 00267 CampaignInfo campaign = theBanker.getCampaignDebug(campaignName); 00268 cerr << "\t" << testNum++ << ". Added strategy : " << strategy1 00269 << " to campaign " << campaign << endl; 00270 BOOST_CHECK_EQUAL(campaign.available_, USD(500)); 00271 // The strategy isn't there yet as we haven't yet transferred 00272 // any money into it. 00273 } 00274 // Next add a strategy to a campaign that is not known. This should 00275 // not fail, but we don't expect to see it there until we transfer 00276 // some budget to it. 00277 { 00278 theController.addStrategySync(campaign2, strategy1); 00279 } 00280 // Set the budget for a non-existing campaign we expect the campaign 00281 // to be added 00282 { 00283 // create a $600 campaign 00284 theController.setBudgetSync(campaign3, USD(600)); 00285 theBanker.sync(); 00286 CampaignInfo campaign = theBanker.getCampaignDebug(campaign3); 00287 cerr << "\t" << testNum++ 00288 << ". Set the budget for previously non-existing campaign: " 00289 << campaign3 << endl; 00290 BOOST_CHECK_EQUAL(campaign.available_, USD(600)); 00291 } 00292 // Add another strategy to campaign1 00293 { 00294 theController.addStrategySync(campaignName, strategy2); 00295 CampaignInfo campaign = theBanker.getCampaignDebug(campaignName); 00296 cerr << "\t" << testNum++ << ". Added strategy : " << strategy2 00297 << " to campaign " << campaign << endl; 00298 BOOST_CHECK_EQUAL(campaign.available_, USD(500)); 00299 } 00300 { 00301 // Top up strategy 1 to $20 00302 { 00303 std::promise<CampaignInfo> thePromise; 00304 auto onTopupDone = [&] (std::exception_ptr exc) 00305 { 00306 cerr << "called onTopupDone" << endl; 00307 if (exc) 00308 thePromise.set_exception(exc); 00309 else { 00310 cerr << "getting debug campaign" << endl; 00311 theBanker.sync(); 00312 thePromise.set_value(theBanker.getCampaignDebug(campaignName)); 00313 } 00314 cerr << "finished onTopupDone" << endl; 00315 }; 00316 00317 cerr << "performing topup to strategy" << endl; 00318 theController.topupTransfer(campaignName, strategy1, 00319 MicroUSD(20000000), 00320 onTopupDone); 00321 00322 CampaignInfo campaign = thePromise.get_future().get(); 00323 cerr << "\t " << testNum++ << ". topped up strategy : " << strategy1 00324 << " to campaign " << campaign << endl; 00325 BOOST_CHECK_EQUAL(campaign.transferred_, USD(20)); 00326 // Make sure that the campaign now has $480 00327 BOOST_CHECK_EQUAL(campaign.available_, USD(480)); 00328 BOOST_CHECK_GE(campaign.strategies_.size(), 1); 00329 const Strategies &strategies = campaign.strategies_; 00330 // Make sure the strategies are there in-memory 00331 Strategies::const_iterator foundStrat1 = strategies.find(strategy1); 00332 BOOST_CHECK(foundStrat1 != strategies.end()); 00333 00334 // Make sure that the strategy 1 has $20 available 00335 BOOST_CHECK_EQUAL(foundStrat1->second.available_, USD(20)); 00336 //..and 20$ transferred 00337 BOOST_CHECK_EQUAL(foundStrat1->second.transferred_, USD(20)); 00338 } 00339 // topup strategy2 to $20 00340 { 00341 std::promise<CampaignInfo> thePromise; 00342 auto onTopupDone = [&] (std::exception_ptr exc) 00343 { 00344 cerr << "onTopupDone callback with exc " << (bool)exc 00345 << endl; 00346 if (exc) 00347 thePromise.set_exception(exc); 00348 else { 00349 theBanker.sync(); 00350 thePromise.set_value(theBanker.getCampaignDebug(campaignName)); 00351 } 00352 cerr << "onTopupDone callback finished" << endl; 00353 }; 00354 00355 theController.topupTransfer(campaignName, strategy2, 00356 USD(20), onTopupDone); 00357 00358 CampaignInfo campaign = thePromise.get_future().get(); 00359 00360 cerr << "\t " << testNum++ << ". Added strategy : " << strategy2 00361 << " to campaign " << campaign << endl; 00362 BOOST_CHECK_EQUAL(campaign.transferred_, USD(40)); 00363 // Make sure that the campaign now has $480 00364 BOOST_CHECK_EQUAL(campaign.available_, USD(460)); 00365 BOOST_CHECK_EQUAL(campaign.strategies_.size(), 2); 00366 const Strategies &strategies = campaign.strategies_; 00367 // Make sure the strategies are there in-memory 00368 Strategies::const_iterator foundStrat1 = strategies.find(strategy1); 00369 BOOST_CHECK(foundStrat1 != strategies.end()); 00370 Strategies::const_iterator foundStrat2 = strategies.find(strategy2); 00371 BOOST_CHECK(foundStrat2 != strategies.end()); 00372 // Make sure that the strategy 2 has $20 available 00373 BOOST_CHECK_EQUAL(foundStrat2->second.available_, USD(20)); 00374 //..and 20$ transferred 00375 BOOST_CHECK_EQUAL(foundStrat2->second.transferred_, USD(20)); 00376 00377 } 00378 } 00379 cerr << "\t" << testNum++ 00380 << ". Trying to add 100 000 to campaign. Exceeds maximum test" 00381 << endl; 00382 // Now try to add 50000$ to the campaign. It should throw an exception since this is 00383 // the current limit 00384 00385 BOOST_CHECK_THROW(theController.addBudgetSync(campaignName,USD(100000)), 00386 BankerException); 00387 cerr << "finished adding too much" << endl; 00388 00389 { 00390 // Top up strategy 1 to $20 00391 // Now add $30 to the campaign this should be fine and we should 00392 // have $510 available 00393 cerr << "\t" << testNum++ 00394 << ". Add $30 to the budget for campaign: " << campaignName 00395 << endl; 00396 theController.addBudgetSync(campaignName, USD(30)); 00397 theBanker.sync(); 00398 CampaignInfo campaign = theBanker.getCampaignDebug(campaignName); 00399 BOOST_CHECK_EQUAL(campaign.available_, USD(490)); 00400 cerr << "The campaign is " << campaign << endl; 00401 } 00402 // Now we want a test where we set the budget to an absolute value. 00403 // We first try to set the budget to a value that is less than the 00404 // amount transferred. We should get an exception 00405 cerr << "\t" << testNum++ 00406 << ". Testing that we cannot set the campaign budget to less than transferred amount" 00407 << endl; 00408 BOOST_CHECK_THROW(theController.setBudgetSync(campaignName, MicroUSD(15000000)), 00409 BankerException); 00410 { 00411 // Now we set the budget to $300 which should be okay. We expect the 00412 // available amount to now be $280 since $20 has already been transferred 00413 cerr << "\t" << testNum++ << ". Set the budget to $300: " 00414 << campaignName << endl; 00415 theController.setBudgetSync(campaignName, USD(300)); 00416 theBanker.sync(); 00417 CampaignInfo campaign = theBanker.getCampaignDebug(campaignName); 00418 BOOST_CHECK_EQUAL(campaign.available_, USD(260)); 00419 BOOST_CHECK_EQUAL(campaign.transferred_, USD(40)); 00420 const Strategies &memStrategies = campaign.strategies_; 00421 const StrategyInfo &stratinfo = 00422 memStrategies.find(strategy1)->second; 00423 BOOST_CHECK_EQUAL(stratinfo.commitments_.size(), 0); 00424 } 00425 { 00426 // Test - Simple Bid 00427 // Now bid on something for a value of $19 for strategy 1 00428 { 00429 cerr << "\t" << testNum++ << ". Bid on something for $19: " 00430 << campaignName << endl; 00431 00432 00433 BOOST_CHECK(theBanker.authorizeBid(campaignName, strategy1, "bid1", MicroUSD(19000000))); 00434 theBanker.sync(); 00435 CampaignInfo campaign = theBanker.getCampaignDebug(campaignName); 00436 00437 const Strategies &memStrategies = campaign.strategies_; 00438 const StrategyInfo &stratinfo = 00439 memStrategies.find(strategy1)->second; 00440 BOOST_CHECK_EQUAL(stratinfo.available_, MicroUSD(1000000)); 00441 BOOST_CHECK_EQUAL(stratinfo.committed_, MicroUSD(19000000)); 00442 BOOST_CHECK_EQUAL(stratinfo.commitments_.size(), 1); 00443 } 00444 { 00445 // Bid something for a value of $15 for strategy2 00446 cerr << "\t" << testNum++ << ". Bid on something for $15: " 00447 << campaignName << " strategy : " << strategy2 << endl; 00448 theBanker.authorizeBid(campaignName, strategy2, "bid1", MicroUSD(15000000)); 00449 theBanker.sync(); 00450 CampaignInfo campaign = theBanker.getCampaignDebug(campaignName); 00451 00452 const Strategies &memStrategies = campaign.strategies_; 00453 const StrategyInfo &stratinfo = 00454 memStrategies.find(strategy2)->second; 00455 BOOST_CHECK_EQUAL(stratinfo.available_, MicroUSD(5000000)); 00456 BOOST_CHECK_EQUAL(stratinfo.committed_, MicroUSD(15000000)); 00457 BOOST_CHECK_EQUAL(stratinfo.commitments_.size(), 1); 00458 // And win the bid 00459 cerr << "\t" << testNum++ << ". Win the bid for $15: " 00460 << campaignName << " strategy : " << strategy2 << endl; 00461 00462 theBanker.winBid(campaignName, strategy2, "bid1", MicroUSD(15000000)); 00463 theBanker.sync(); 00464 CampaignInfo wincampaign = theBanker.getCampaignDebug(campaignName); 00465 // Now make sure we have the right accounting 00466 const Strategies &winStrategies = wincampaign.strategies_; 00467 const StrategyInfo &winStratInfo = 00468 winStrategies.find(strategy2)->second; 00469 BOOST_CHECK_EQUAL(winStratInfo.available_, MicroUSD(5000000)); 00470 BOOST_CHECK_EQUAL(winStratInfo.committed_, USD(0)); 00471 BOOST_CHECK_EQUAL(winStratInfo.spent_, MicroUSD(15000000)); 00472 BOOST_CHECK_EQUAL(winStratInfo.commitments_.size(), 0); 00473 BOOST_CHECK_EQUAL(wincampaign.spent_, MicroUSD(15000000)); 00474 } 00475 } 00476 { 00477 // Test - Cancel 00478 // cancel a bid we want to be back to the original 00479 cerr << "\t" << testNum++ << ". Cancel previous bid: " 00480 << campaignName << endl; 00481 theBanker.cancelBid(campaignName, strategy1, "bid1"); 00482 theBanker.sync(); 00483 CampaignInfo campaign = theBanker.getCampaignDebug(campaignName); 00484 00485 const Strategies &memStrategies = campaign.strategies_; 00486 const StrategyInfo &stratinfo = 00487 memStrategies.find(strategy1)->second; 00488 BOOST_CHECK_EQUAL(stratinfo.available_, MicroUSD(20000000)); 00489 BOOST_CHECK_EQUAL(stratinfo.committed_, MicroUSD(0)); 00490 BOOST_CHECK_EQUAL(stratinfo.commitments_.size(), 0); 00491 } 00492 { 00493 // Test - win a bid and pay a lower price 00494 // Did on something for a value of $19 00495 cerr << "\t" << testNum++ << ". Win a bid but pay a lower price: " 00496 << campaignName << endl; 00497 theBanker.authorizeBid(campaignName, strategy1, "bid1", MicroUSD(19000000)); 00498 theBanker.winBid(campaignName, strategy1, "bid1", MicroUSD(15000000)); 00499 theBanker.sync(); 00500 CampaignInfo wincampaign = theBanker.getCampaignDebug(campaignName); 00501 00502 const Strategies &memStrategies = wincampaign.strategies_; 00503 const StrategyInfo &stratinfo = 00504 memStrategies.find(strategy1)->second; 00505 BOOST_CHECK_EQUAL(stratinfo.available_, MicroUSD(5000000)); 00506 BOOST_CHECK_EQUAL(stratinfo.committed_, MicroUSD(0)); 00507 BOOST_CHECK_EQUAL(stratinfo.spent_, MicroUSD(15000000)); 00508 BOOST_CHECK_EQUAL(stratinfo.commitments_.size(), 0); 00509 BOOST_CHECK_EQUAL(wincampaign.spent_, MicroUSD(30000000)); 00510 } 00511 Json::Value campaignStatus = theBanker.dumpAllCampaignsJson(); 00512 cerr << "campaign status : " << campaignStatus << endl; 00513 { 00514 cerr << "\t" << testNum++ 00515 << ". submit a bit for a certain amount but pay more than available: " 00516 << campaignName << endl; 00517 // ** 00518 // Test - win a bid but pay more for it than is available. At this point we have $5 00519 // Bid $4.90 00520 BOOST_CHECK(theBanker.authorizeBid(campaignName, strategy1, "bid1", MicroUSD(4900000))); 00521 00522 // We also make sure we cannot submit the same bid twice 00523 BOOST_CHECK_THROW( 00524 theBanker.authorizeBid(campaignName, strategy1, "bid1", MicroUSD(4900000)), 00525 ML::Exception); 00526 00527 // Now win the bid at a higher price 00528 theBanker.winBid(campaignName, strategy1, "bid1", MicroUSD(5100000)); 00529 CampaignInfo winCampaign = theBanker.getCampaignDebug(campaignName); 00530 const Strategies &memStrategies = winCampaign.strategies_; 00531 const StrategyInfo &stratinfo = 00532 memStrategies.find(strategy1)->second; 00533 BOOST_CHECK_EQUAL(stratinfo.available_, MicroUSD(-100000)); 00534 BOOST_CHECK_EQUAL(stratinfo.committed_, MicroUSD(0)); 00535 BOOST_CHECK_EQUAL(stratinfo.commitments_.size(), 0); 00536 // we should have spent $20.10 00537 BOOST_CHECK_EQUAL(stratinfo.spent_, USD(20.10)); 00538 } 00539 { 00540 cerr << "\t" << testNum++ 00541 << ". submit a bit with no funds available: " 00542 << campaignName << endl; 00543 // Test. Submit a bid with no funds available. This is synchronous 00544 // so we don't use a promise 00545 bool result = theBanker.authorizeBid(campaignName, strategy1, "bid1", 00546 MicroUSD(4900000)); 00547 BOOST_CHECK_EQUAL(result, false); 00548 theBanker.sync(); 00549 } 00550 { 00551 // simulate the case where we have a campaign already in the database 00552 // when we add the campaign we expect it to be loaded 00553 theController.addCampaignSync(campaign4); 00554 CampaignInfo campaign = theBanker.getCampaignDebug(campaign4); 00555 cerr << "\t" << testNum++ 00556 << ". Added TestCampaign4 and got the result: " 00557 << campaign << endl; 00558 BOOST_CHECK_EQUAL(campaign.available_, MicroUSD(1000000)); 00559 BOOST_CHECK_EQUAL(campaign.transferred_, MicroUSD(100000)); 00560 } 00561 { 00562 // simulate the case where we have a campaign and its associated strategy 00563 // already in the database. When we add a strategy to the 00564 // campaign we expect them both to be loaded. 00565 theController.addStrategySync(campaign4, strategy1); 00566 CampaignInfo campaign = theBanker.getCampaignDebug(campaign4); 00567 cerr << "\t" << testNum++ << ". Added strategy : " << strategy1 00568 << " to campaign " << campaign4 << endl; 00569 BOOST_CHECK_EQUAL(campaign.available_, MicroUSD(1000000)); 00570 BOOST_CHECK_EQUAL(campaign.transferred_, MicroUSD(100000)); 00571 BOOST_CHECK_EQUAL(campaign.spent_, MicroUSD(10000)); 00572 00573 const Strategies &memStrategies = campaign.strategies_; 00574 const StrategyInfo &stratinfo = 00575 memStrategies.find(strategy1)->second; 00576 BOOST_CHECK_EQUAL(stratinfo.available_, MicroUSD(90000)); 00577 BOOST_CHECK_EQUAL(stratinfo.transferred_, MicroUSD(100000)); 00578 BOOST_CHECK_EQUAL(stratinfo.spent_, MicroUSD(10000)); 00579 BOOST_CHECK_EQUAL(stratinfo.commitments_.size(), 0); 00580 } 00581 cerr << "campaign status at the end : " << theBanker.dumpAllCampaignsJson(); 00582 } 00583 } 00584 00585 #endif