/////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) // // See accompanying file COPYING.TXT file for licensing details. // /////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include #include #include #include #include #include #include "client.h" #include #include #include "test.h" int g_fail; #define TESTNT(x) do { if(x) break; std::cerr << "FAIL: " #x " in line: " << __LINE__ << std::endl; g_fail = 1; return; } while(0) booster::thread_specific_ptr g_thread_id; booster::mutex g_id_lock; int g_thread_id_counter=1000; struct thread_submitter { thread_submitter(cppcms::service &srv) : srv_(&srv) {} void operator()() const { runner r(*srv_); booster::thread t(r); t.detach(); } cppcms::service *srv_; }; void set_thread_id(int v) { g_thread_id.reset(new int(v)); } int get_thread_id() { if(g_thread_id.get()==0) { booster::unique_lock guard(g_id_lock); int new_id = ++g_thread_id_counter; set_thread_id(new_id); } return *g_thread_id; } class counter { typedef booster::unique_lock guard; counter() : current(0), max(0), total(0) { } public: static counter *instance(std::string const &name) { static const int max = 20; static int curr; static counter all[max]; for(int i=0;i > weak_pools; class tester : public cppcms::application { public: tester(cppcms::service &srv) : cppcms::application(srv) {} void main(std::string name) { if(name=="/stats") counter::instance(request().get("id"))->print(response().out()); else if(name=="/unmount") { std::string id = request().get("id"); bool exists_before = weak_pools[id].lock(); service().applications_pool().unmount(weak_pools[id]); bool exists_after = weak_pools[id].lock(); response().out()<<"unmount=" << id << "\n" "before="< app_; }; struct marker { marker(std::string const &name) : name_(name) {} booster::shared_ptr const &operator | (booster::shared_ptr const &in) { weak_pools[name_] = in; return in; } std::string name_; }; struct pools { booster::weak_ptr sync,async; bool async_requested; pools() : async_requested(false) {} }; class sender : public cppcms::application { public: struct src_prop { bool src_async; bool src_created; bool src_to_app; }; sender(cppcms::service &srv,pools *p) : cppcms::application(srv), pools_(p) { } void main(std::string url) { if(url!="/sender") { src_prop *p = context().get_specific(); TESTNT(p); response().out() << "async=" << is_asynchronous() << "\n" "src_async=" << p->src_async <<"\n" "src_created="<< p->src_created <<"\n" "src_to_app=" << p->src_to_app <<"\n" "path=" << url<<"\n" ; return; } src_prop *p=new src_prop(); context().reset_specific(p); bool to_app = request().get("to_app")=="1"; p->src_to_app = to_app; p->src_async = is_asynchronous(); p->src_created = false; booster::shared_ptr tgt; if(request().get("to")=="sync") tgt = pools_->sync.lock(); else tgt = pools_->async.lock(); booster::shared_ptr ctx = release_context(); TESTNT(tgt); if(!to_app) { ctx->submit_to_pool(tgt,"/pool"); return; } booster::intrusive_ptr app; app =tgt->asynchronous_application_by_io_service(service().get_io_service()); if(!app) { app = tgt->asynchronous_application_by_io_service(service().get_io_service(),service()); p->src_created=true; } TESTNT(app); ctx->submit_to_asynchronous_application(app,"/app"); } private: pools *pools_; }; int main(int argc,char **argv) { try { { using cppcms::mount_point; cppcms::service srv(argc,argv); set_thread_id(1); srv.applications_pool().mount( marker("/sync") | cppcms::create_pool(counter::instance("/sync")), mount_point("/sync","",0), cppcms::app::synchronous); srv.applications_pool().mount( cppcms::create_pool(counter::instance("/sync/work")), mount_point("/sync","/work",0), cppcms::app::synchronous); srv.applications_pool().mount( marker("/sync/prepopulated") | cppcms::create_pool(counter::instance("/sync/prepopulated")), mount_point("/sync","/prepopulated",0), cppcms::app::synchronous | cppcms::app::prepopulated); srv.applications_pool().mount( marker("/sync/tss") | cppcms::create_pool(counter::instance("/sync/tss")), mount_point("/sync","/tss",0), cppcms::app::synchronous | cppcms::app::thread_specific); srv.applications_pool().mount( cppcms::applications_factory(counter::instance("/sync/legacy")), mount_point("/sync","/legacy",0)); srv.applications_pool().mount( marker("/async") | cppcms::create_pool(counter::instance("/async")), mount_point("/async","",0), cppcms::app::asynchronous); srv.applications_pool().mount( marker("/async/prepopulated") | cppcms::create_pool(counter::instance("/async/prepopulated")), mount_point("/async","/prepopulated",0), cppcms::app::asynchronous | cppcms::app::prepopulated); booster::intrusive_ptr app = new unit_test(srv,counter::instance("/async/legacy")); srv.applications_pool().mount( app, mount_point("/async","/legacy",0)); counter::instance("/async/temporary"); srv.applications_pool().mount(cppcms::create_pool(),mount_point("/test"),cppcms::app::asynchronous); pools p; { booster::shared_ptr tmp; srv.applications_pool().mount( (tmp=cppcms::create_pool(&p)), mount_point("/async","/sender",0), cppcms::app::asynchronous); p.async = tmp; } { booster::shared_ptr tmp; srv.applications_pool().mount( (tmp=cppcms::create_pool(&p)), mount_point("/sync","/sender",0), cppcms::app::synchronous); p.sync = tmp; } srv.after_fork(thread_submitter(srv)); srv.run(); weak_pools.clear(); } std::cout << "Test all deleted" << std::endl; TEST(counter::instance("/sync")->current == 0); TEST(counter::instance("/sync/prepopulated")->current == 0); TEST(counter::instance("/sync/tss")->current == 0); TEST(counter::instance("/sync/legacy")->current == 0); TEST(counter::instance("/async")->current == 0); TEST(counter::instance("/async/prepopulated")->current == 0); TEST(counter::instance("/async/legacy")->current == 0); std::cout << "Done" << std::endl; } catch(std::exception const &e) { std::cerr << e.what() << std::endl; return EXIT_FAILURE; } if(run_ok && !g_fail) { std::cout << "Full Test: Ok" << std::endl; return EXIT_SUCCESS; } else { std::cout << "FAILED" << std::endl; return EXIT_FAILURE; } }