#include #include #include #include #include using namespace Balau; const char htmlTemplateStr[] = "\n" "\n" " \n" " \n" " {{title}}\n" " \n" " \n" "\n" " \n" "

{{title}}

\n" "

{{msg}}

\n" " \n" "\n" ; class TestHtmlTemplateTask : public Task { virtual void Do() { m_template.setTemplate(htmlTemplateStr); } virtual const char * getName() const { return "TestHtmlTemplateTask"; } SimpleMustache & m_template; public: TestHtmlTemplateTask(SimpleMustache & htmlTemplate) : m_template(htmlTemplate) { } }; class TestHtmlTemplate : public AtStartAsTask { public: TestHtmlTemplate() : AtStartAsTask(10), htmlTemplate(m_template) { } virtual Task * createStartTask() { return new TestHtmlTemplateTask(m_template); } const SimpleMustache & htmlTemplate; public: SimpleMustache m_template; }; static TestHtmlTemplate testHtmlTemplate; static Regex stopURL("/stop$"); class StopAction : public HttpServer::Action { public: StopAction(Events::Async & event, bool & stop) : Action(stopURL), m_event(event), m_stop(stop) { } private: virtual bool Do(HttpServer * server, Http::Request & req, HttpServer::Action::ActionMatch & match, IO out) throw (GeneralException); Events::Async & m_event; bool & m_stop; }; bool StopAction::Do(HttpServer * server, Http::Request & req, HttpServer::Action::ActionMatch & match, IO out) throw (GeneralException) { m_stop = true; m_event.trigger(); SimpleMustache::Context ctx; HttpServer::Response response(server, req, out); ctx["title"] = "Stop"; ctx["msg"] = "Server stopping"; testHtmlTemplate.htmlTemplate.render(response.get(), &ctx); response.Flush(); return true; } class TestAction : public HttpServer::Action { public: TestAction() : Action(Regexes::any) { } private: virtual bool Do(HttpServer * server, Http::Request & req, HttpServer::Action::ActionMatch & match, IO out) throw (GeneralException); }; bool TestAction::Do(HttpServer * server, Http::Request & req, HttpServer::Action::ActionMatch & match, IO out) throw (GeneralException) { SimpleMustache::Context ctx; HttpServer::Response response(server, req, out); ctx["title"] = "Test"; ctx["msg"] = "This is a test document."; testHtmlTemplate.htmlTemplate.render(response.get(), &ctx); response.Flush(); return true; } static Regex testFailureURL("^/failure.html$"); class TestFailure : public HttpServer::Action { public: TestFailure() : Action(testFailureURL) { } private: virtual bool Do(HttpServer * server, Http::Request & req, HttpServer::Action::ActionMatch & match, IO out) throw (GeneralException); }; bool TestFailure::Do(HttpServer * server, Http::Request & req, HttpServer::Action::ActionMatch & match, IO out) throw (GeneralException) { throw GeneralException("Test..."); } class Stopper : public Task { virtual const char * getName() const { return "ServerStopper"; } virtual void Do(); }; void Stopper::Do() { IO s(new Socket()); bool c = s->connect("localhost", 8080); TAssert(c); s->writeString("GET /stop HTTP/1.0\r\n\r\n"); } static const int NTHREADS = 4; void MainTask::Do() { Printer::enable(M_DEBUG); Printer::log(M_STATUS, "Test::Http running."); TaskMan::TaskManThread * tms[NTHREADS]; for (int i = 0; i < NTHREADS; i++) tms[i] = TaskMan::createThreadedTaskMan(); Events::Async event; bool stop = false; waitFor(&event); HttpServer * s = new HttpServer(); s->registerAction(new TestAction()); s->registerAction(new TestFailure()); s->registerAction(new StopAction(event, stop)); s->setPort(8080); s->setLocal("localhost"); s->start(); while (!s->started()) sleep(0.1); Events::TaskEvent stopperEvent; Task * stopper = TaskMan::registerTask(new Stopper, &stopperEvent); waitFor(&stopperEvent); bool gotEvent = false, gotStopperEvent = false; int count = 0; while (!gotEvent || !gotStopperEvent) { count++; yield(); if (event.gotSignal()) { TAssert(!gotEvent); gotEvent = true; event.reset(); } if (stopperEvent.gotSignal()) { TAssert(!gotStopperEvent); gotStopperEvent = true; stopperEvent.ack(); } } TAssert(count <= 2); TAssert(stop); Printer::log(M_STATUS, "Test::Http is stopping."); s->stop(); for (int i = 0; i < NTHREADS; i++) TaskMan::stopThreadedTaskMan(tms[i]); Printer::log(M_STATUS, "Test::Http passed."); }