X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Scheduler%2FScheduler.test.cc;h=e270b060374a306ad02ca70b9b7761556fc24661;hb=04b5fd6be72efd504de15a215a268f8b82f4d132;hp=2bc2a323af32a6c74300a46d85ec28bc6095814f;hpb=44c966bc9d744d0926cffd5184fdb77a62564c16;p=senf.git diff --git a/Scheduler/Scheduler.test.cc b/Scheduler/Scheduler.test.cc index 2bc2a32..e270b06 100644 --- a/Scheduler/Scheduler.test.cc +++ b/Scheduler/Scheduler.test.cc @@ -2,9 +2,9 @@ // $Id$ // // Copyright (C) 2006 -// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) -// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) -// Stefan Bund +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY +// Stefan Bund // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -36,6 +36,7 @@ #include #include #include +#include #include "Scheduler.hh" @@ -141,28 +142,28 @@ namespace { int size; int event; - void callback(int fd, Scheduler::EventId ev) + void callback(int fd, int ev) { event = ev; - switch (event & Scheduler::EV_ALL) { - case Scheduler::EV_READ: + switch (event & senf::scheduler::FdEvent::EV_ALL) { + case senf::scheduler::FdEvent::EV_READ: size = recv(fd,buffer,1024,0); break; - case Scheduler::EV_PRIO: + case senf::scheduler::FdEvent::EV_PRIO: size = recv(fd,buffer,1024,MSG_OOB); - Scheduler::instance().terminate(); break; - case Scheduler::EV_WRITE: + case senf::scheduler::FdEvent::EV_WRITE: size = write(fd,buffer,size); - Scheduler::instance().terminate(); break; } - Scheduler::instance().terminate(); + senf::scheduler::terminate(); } + bool timeoutCalled = false; void timeout() { - Scheduler::instance().terminate(); + timeoutCalled = true; + senf::scheduler::terminate(); } struct HandleWrapper @@ -177,7 +178,7 @@ namespace { return handle.fd_; } - void handleCallback(HandleWrapper const & handle, Scheduler::EventId event) + void handleCallback(HandleWrapper const & handle, int event) { if (handle.tag_ != "TheTag") return; @@ -191,12 +192,12 @@ namespace { ClockService::clock_type sigtime (0); - void sigusr() + void sigusr(siginfo_t const &) { sigtime = ClockService::now(); - Scheduler::instance().terminate(); + senf::scheduler::terminate(); } - + void delay(unsigned long milliseconds) { struct timespec ts; @@ -204,9 +205,16 @@ namespace { ts.tv_nsec = (milliseconds % 1000) * 1000000; while (nanosleep(&ts,&ts) < 0 && errno == EINTR) ; } + + void blockingHandler() + { + delay(2200); + senf::scheduler::terminate(); + } + } -BOOST_AUTO_UNIT_TEST(scheduler) +BOOST_AUTO_UNIT_TEST(testScheduler) { int pid = start_server(); BOOST_REQUIRE (pid); @@ -228,58 +236,76 @@ BOOST_AUTO_UNIT_TEST(scheduler) /////////////////////////////////////////////////////////////////////////// - BOOST_CHECK_NO_THROW( Scheduler::instance() ); - - BOOST_CHECK_NO_THROW( Scheduler::instance().add(sock,boost::bind(&callback, sock, _1), - Scheduler::EV_READ) ); - event = Scheduler::EV_NONE; - BOOST_CHECK_NO_THROW( Scheduler::instance().process() ); - BOOST_CHECK_EQUAL( event, Scheduler::EV_READ ); - BOOST_REQUIRE_EQUAL( size, 4 ); - buffer[size]=0; - BOOST_CHECK_EQUAL( buffer, "READ" ); - - BOOST_CHECK_NO_THROW( Scheduler::instance().timeout( - ClockService::now()+ClockService::milliseconds(200),&timeout) ); - BOOST_CHECK_NO_THROW( Scheduler::instance().timeout( - ClockService::now()+ClockService::milliseconds(400),&timeout) ); - ClockService::clock_type t (ClockService::now()); - BOOST_CHECK_NO_THROW( Scheduler::instance().process() ); - BOOST_CHECK_PREDICATE( is_close, (ClockService::now()) (t+ClockService::milliseconds(200)) ); - BOOST_CHECK_NO_THROW( Scheduler::instance().process() ); - BOOST_CHECK_PREDICATE( is_close, (ClockService::now()) (t+ClockService::milliseconds(400)) ); - - HandleWrapper handle(sock,"TheTag"); - BOOST_CHECK_NO_THROW( Scheduler::instance().add(handle, - boost::bind(&handleCallback,handle,_1), - Scheduler::EV_WRITE) ); - strcpy(buffer,"WRITE"); - size=5; - event = Scheduler::EV_NONE; - BOOST_CHECK_NO_THROW( Scheduler::instance().process() ); - BOOST_CHECK_EQUAL( event, Scheduler::EV_WRITE ); - - BOOST_CHECK_NO_THROW( Scheduler::instance().remove(handle,Scheduler::EV_WRITE) ); - event = Scheduler::EV_NONE; - sleep(1); - BOOST_CHECK_NO_THROW( Scheduler::instance().process() ); - BOOST_CHECK_EQUAL( event, Scheduler::EventId(Scheduler::EV_READ|Scheduler::EV_HUP) ); - BOOST_REQUIRE_EQUAL( size, 2 ); - buffer[size]=0; - BOOST_CHECK_EQUAL( buffer, "OK" ); - BOOST_CHECK_NO_THROW( Scheduler::instance().remove(handle) ); - - unsigned tid (Scheduler::instance().timeout( - ClockService::now()+ClockService::milliseconds(400),&timeout)); - BOOST_CHECK_NO_THROW( Scheduler::instance().registerSignal(SIGUSR1, &sigusr) ); - t = ClockService::now(); - ::kill(::getpid(), SIGUSR1); - delay(100); - BOOST_CHECK_NO_THROW( Scheduler::instance().process() ); - BOOST_CHECK_PREDICATE( is_close, (ClockService::now()) (t+ClockService::milliseconds(200)) ); - BOOST_CHECK_PREDICATE( is_close, (sigtime) (t+ClockService::milliseconds(200)) ); - Scheduler::instance().cancelTimeout(tid); - BOOST_CHECK_NO_THROW( Scheduler::instance().unregisterSignal(SIGUSR1) ); + { + senf::scheduler::FdEvent fde1 ("testFdEvent", boost::bind(&callback, sock, _1), + sock, senf::scheduler::FdEvent::EV_READ); + event = senf::scheduler::FdEvent::EV_NONE; + BOOST_CHECK_NO_THROW( senf::scheduler::process() ); + BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_READ ); + BOOST_REQUIRE_EQUAL( size, 4 ); + buffer[size]=0; + BOOST_CHECK_EQUAL( buffer, "READ" ); + + HandleWrapper handle(sock,"TheTag"); + senf::scheduler::FdEvent fde2 ("testFdEvent", boost::bind(&handleCallback,handle,_1), + handle, senf::scheduler::FdEvent::EV_WRITE); + strcpy(buffer,"WRITE"); + size=5; + event = senf::scheduler::FdEvent::EV_NONE; + BOOST_CHECK_NO_THROW( senf::scheduler::process() ); + BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_WRITE ); + + SENF_CHECK_NO_THROW( fde2.disable() ); + event = senf::scheduler::FdEvent::EV_NONE; + sleep(1); + BOOST_CHECK_NO_THROW( senf::scheduler::process() ); + BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_READ|senf::scheduler::FdEvent::EV_HUP ); + BOOST_REQUIRE_EQUAL( size, 2 ); + buffer[size]=0; + BOOST_CHECK_EQUAL( buffer, "OK" ); + } + + { + senf::scheduler::TimerEvent timer1 ("testTimer1", &timeout, + ClockService::now()+ClockService::milliseconds(200)); + senf::scheduler::TimerEvent timer2 ("testTimer2", &timeout, + ClockService::now()+ClockService::milliseconds(400)); + + event = senf::scheduler::FdEvent::EV_NONE; + ClockService::clock_type t (ClockService::now()); + BOOST_CHECK_NO_THROW( senf::scheduler::process() ); + BOOST_CHECK_PREDICATE( is_close, (ClockService::now()-t) (ClockService::milliseconds(200)) ); + BOOST_CHECK( timeoutCalled ); + BOOST_CHECK( ! timer1.enabled() ); + BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_NONE ); + BOOST_CHECK_PREDICATE( is_close, (ClockService::now()) (senf::scheduler::eventTime()) ); + timeoutCalled = false; + BOOST_CHECK_NO_THROW( senf::scheduler::process() ); + BOOST_CHECK_PREDICATE( is_close, (ClockService::now()-t) (ClockService::milliseconds(400)) ); + BOOST_CHECK( timeoutCalled ); + BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_NONE ); + BOOST_CHECK( ! timer2.enabled() ); + + BOOST_WARN_MESSAGE( false, "A 'Scheduler task hanging' error is expected to be signaled here." ); + BOOST_CHECK_NO_THROW( timer1.action(&blockingHandler) ); + BOOST_CHECK_NO_THROW( timer1.timeout(ClockService::now()) ); + BOOST_CHECK_NO_THROW( senf::scheduler::process() ); + BOOST_CHECK_EQUAL( senf::scheduler::hangCount(), 1u ); + } + + { + senf::scheduler::TimerEvent timer ("testWatchdog", &timeout, + ClockService::now()+ClockService::milliseconds(400)); + senf::scheduler::SignalEvent sig (SIGUSR1, &sigusr); + + ClockService::clock_type t = ClockService::now(); + ::kill(::getpid(), SIGUSR1); + delay(100); + BOOST_CHECK_NO_THROW( senf::scheduler::process() ); + BOOST_CHECK_PREDICATE( is_close, (ClockService::now()) (t+ClockService::milliseconds(200)) ); + BOOST_CHECK_PREDICATE( is_close, (sigtime) (t+ClockService::milliseconds(200)) ); + BOOST_CHECK_NO_THROW( senf::scheduler::process() ); + } ///////////////////////////////////////////////////////////////////////////