RTBKit  0.9
Open-source framework to create real-time ad bidding systems.
core/banker/testing/redis_banker_race_test.cc
00001 /* redis_banker_race_test.cc
00002    Jeremy Barnes, 2 November 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 #include <boost/test/unit_test.hpp>
00011 #include "jml/arch/format.h"
00012 #include "jml/arch/exception_handler.h"
00013 #include "jml/utils/guard.h"
00014 #include "rtbkit/plugins/bidding_agent/bidding_agent.h"
00015 #include "rtbkit/core/banker/redis_banker.h"
00016 #include "rtbkit/common/auction.h"
00017 #include "rtbkit/core/router/router.h"
00018 #include "jml/utils/environment.h"
00019 #include "jml/arch/timers.h"
00020 #include "dataflow/work_scheduler.h"
00021 #include <future>
00022 #include "soa/service/testing/redis_temporary_server.h"
00023 #include <boost/thread/thread.hpp>
00024 
00025 
00026 using namespace std;
00027 using namespace ML;
00028 using namespace Datacratic;
00029 using namespace RTBKIT;
00030 using namespace Redis;
00031 
00032 
00033 BOOST_AUTO_TEST_CASE( test_topup_transfer_race )
00034 {
00035     auto s = std::make_shared<ServiceProxies>();
00036     RedisTemporaryServer redis;
00037 
00038     // Create a campaign with a budget
00039     {
00040         RedisBudgetController controller("bankerTest", redis);
00041         controller.addCampaignSync("testCampaign");
00042         controller.addStrategySync("testCampaign", "testStrategy");
00043         controller.setBudgetSync("testCampaign", MicroUSD(1000000));
00044     }
00045 
00046     // Do 1,000 topup transfers of one micro
00047 
00048     int nTopupThreads = 2;
00049     int nAddBudgetThreads = 2;
00050     int nBidThreads = 1; // for the moment, we don't support multiple2;
00051     int numTransfersPerThread = 10000;
00052     int numAddBudgetsPerThread = 1000;
00053 
00054     auto runTopupThread = [&] ()
00055         {
00056             RedisBudgetController controller("bankerTest", redis);
00057 
00058             for (unsigned i = 0;  i < numTransfersPerThread;  ++i) {
00059                 controller.topupTransferSync("testCampaign",
00060                                                        "testStrategy",
00061                                                        MicroUSD(1));
00062             }
00063         };
00064 
00065     auto runAddBudgetThread = [&] ()
00066         {
00067             RedisBudgetController controller("bankerTest", redis);
00068 
00069             for (unsigned i = 0;  i < numAddBudgetsPerThread;  ++i) {
00070                 controller.addBudgetSync("testCampaign", MicroUSD(1));
00071             }
00072         };
00073 
00074     uint64_t numBidsCommitted = 0;
00075     volatile bool finished = false;
00076 
00077     auto runBidThread = [&] (int threadNum)
00078         {
00079             RedisBanker banker("bankerTest", "b", s, redis);
00080 
00081             string item = "thread" + to_string(threadNum);
00082 
00083             while (!finished) {
00084                 // Authorize 10
00085                 if (!banker.authorizeBid("testCampaign", "testStrategy", item,
00086                                          MicroUSD(1))) {
00087                     banker.sync();
00088                     continue;
00089                 }
00090 
00091                 // Commit 1
00092                 banker.commitBid("testCampaign", "testStrategy", item,
00093                                  MicroUSD(1));
00094 
00095                 ML::atomic_inc(numBidsCommitted);
00096             }
00097 
00098             banker.sync();
00099         };
00100 
00101     boost::thread_group topupThreads;
00102     for (unsigned i = 0;  i < nTopupThreads;  ++i)
00103         topupThreads.create_thread(runTopupThread);
00104 
00105     for (unsigned i = 0;  i < nAddBudgetThreads;  ++i)
00106         topupThreads.create_thread(runAddBudgetThread);
00107 
00108     boost::thread_group bidThreads;
00109     for (unsigned i = 0;  i < nBidThreads;  ++i)
00110         bidThreads.create_thread(std::bind(runBidThread, i));
00111     
00112 
00113     topupThreads.join_all();
00114 
00115     finished = true;
00116 
00117     bidThreads.join_all();
00118     
00119     RedisBanker banker("bankerTest", "b", s, redis);
00120     banker.sync();
00121     Json::Value status = banker.getCampaignStatusJson("testCampaign", "");
00122 
00123     cerr << status << endl;
00124 
00125     uint32_t amountAdded       = nAddBudgetThreads * numAddBudgetsPerThread;
00126     uint32_t amountTransferred = nTopupThreads * numTransfersPerThread;
00127 
00128     cerr << "numBidsCommitted = "  << numBidsCommitted << endl;
00129     cerr << "amountTransferred = " << amountTransferred << endl;
00130     cerr << "amountAdded =       " << amountAdded << endl;
00131 
00132 
00133 
00134     BOOST_CHECK_EQUAL(status["available"]["micro-USD"].asInt(), 1000000 - amountTransferred + amountAdded);
00135     BOOST_CHECK_EQUAL(status["strategies"][0]["available"]["micro-USD"].asInt(),
00136                       amountTransferred - numBidsCommitted);
00137     BOOST_CHECK_EQUAL(status["strategies"][0]["transferred"]["micro-USD"].asInt(),
00138                       amountTransferred);
00139     BOOST_CHECK_EQUAL(status["strategies"][0]["spent"]["micro-USD"].asInt(),
00140                       numBidsCommitted);
00141     BOOST_CHECK_EQUAL(status["spent"]["micro-USD"].asInt(), numBidsCommitted);
00142 
00143     //BOOST_CHECK_EQUAL(status["available"].
00144 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator