4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at
9 // http://senf.berlios.de/license.html
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on,
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
15 // Software distributed under the License is distributed on an "AS IS" basis,
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17 // for the specific language governing rights and limitations under the License.
19 // The Original Code is Fraunhofer FOKUS code.
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V.
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
26 // Stefan Bund <g0dil@berlios.de>
29 \brief FdEvent unit tests */
31 //#include "FdEvent.test.hh"
32 //#include "FdEvent.test.ih"
35 #include <sys/types.h>
40 #include <sys/socket.h>
48 #include <boost/bind.hpp>
50 #include <senf/Utils/auto_unit_test.hh>
51 #include <boost/test/test_tools.hpp>
54 //-/////////////////////////////////////////////////////////////////////////////////////////////////
58 char const * SOCK_PATH = "/tmp/sched_test.sock";
60 void error(char const * fn, char const * proc="")
62 std::cerr << "\n" << proc << fn << ": " << strerror(errno) << std::endl;
65 void fail(char const * fn)
73 int sock = socket(PF_UNIX,SOCK_STREAM,0);
74 if (sock<0) fail("socket");
75 struct sockaddr_un sun;
76 memset(&sun,0,sizeof(sun));
77 sun.sun_family = AF_UNIX;
78 strcpy(sun.sun_path,SOCK_PATH);
79 if (bind(sock,(struct sockaddr*)&sun,sizeof(sun))<0) fail("bind");
80 if (listen(sock,1)<0) fail("listen");
81 int conn = accept(sock,0,0);
82 if (conn < 0) fail("accept");
84 //-/////////////////////////////////////////////////////////////////////////////////////////
86 if (write(conn,"READ",4)<0) fail("write");
88 int size = read(conn,buffer,1024);
89 if (size<0) fail("read");
92 if (strcmp(buffer,"WRITE")==0) {
93 if (write(conn,"OK",2)<0) fail("write");
95 if (write(conn,"FAIL",4)<0) fail("write");
97 if (write(conn,"FAIL",4)<0) fail("write");
99 //-/////////////////////////////////////////////////////////////////////////////////////////
110 signal(SIGCHLD, SIG_IGN);
118 signal(SIGCHLD, SIG_DFL);
120 sleep(1); // Wait for the server socket to be opened
124 bool stop_server(int pid)
126 sleep(1); // Wait for the server to terminate
127 if (kill(pid,SIGTERM)<0) {
132 if (waitpid(pid,&status,0)<0) {
137 if (WIFSIGNALED(status)) {
138 std::cerr << "\nserver terminated with signal " << WTERMSIG(status) << std::endl;
141 if (WEXITSTATUS(status)!=0) {
142 std::cerr << "\nserver terminated with exit status " << WEXITSTATUS(status) << std::endl;
153 void callback(int fd, int ev)
157 switch (event & senf::scheduler::FdEvent::EV_ALL) {
158 case senf::scheduler::FdEvent::EV_READ:
159 size = recv(fd,buffer,1024,0);
161 case senf::scheduler::FdEvent::EV_PRIO:
162 size = recv(fd,buffer,1024,MSG_OOB);
164 case senf::scheduler::FdEvent::EV_WRITE:
165 size = write(fd,buffer,size);
172 SENF_AUTO_UNIT_TEST(fdDispatcher)
174 senf::scheduler::detail::FdManager::instance().timeout(1000);
176 int pid (start_server());
177 BOOST_REQUIRE( pid );
179 int sock = socket(PF_UNIX,SOCK_STREAM,0);
182 BOOST_FAIL("socket");
184 struct sockaddr_un sun;
185 memset(&sun,0,sizeof(sun));
186 sun.sun_family = AF_UNIX;
187 strcpy(sun.sun_path,SOCK_PATH);
189 if (connect(sock,(struct sockaddr*)&sun,sizeof(sun))<0) {
191 BOOST_FAIL("connect");
195 senf::scheduler::FdEvent sockread ("testHandler", boost::bind(&callback, sock, _1),
196 sock, senf::scheduler::FdEvent::EV_READ);
197 senf::scheduler::FdEvent sockwrite ("testHandler", boost::bind(&callback, sock, _1),
198 sock, senf::scheduler::FdEvent::EV_WRITE, false);
200 SENF_CHECK_NO_THROW( senf::scheduler::detail::FdManager::instance().processOnce() );
201 SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
202 BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_READ );
203 BOOST_CHECK_EQUAL( size, 4 );
205 BOOST_CHECK_EQUAL( buffer, "READ" );
207 strcpy(buffer,"WRITE");
209 SENF_CHECK_NO_THROW( sockwrite.enable() );
212 SENF_CHECK_NO_THROW( senf::scheduler::detail::FdManager::instance().processOnce() );
213 SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
214 BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_WRITE );
216 SENF_CHECK_NO_THROW( sockwrite.disable() );
219 SENF_CHECK_NO_THROW( senf::scheduler::detail::FdManager::instance().processOnce() );
220 SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
221 BOOST_CHECK_EQUAL( event, senf::scheduler::FdEvent::EV_HUP | senf::scheduler::FdEvent::EV_READ );
222 BOOST_CHECK_EQUAL( size, 2 );
224 BOOST_CHECK_EQUAL( buffer, "OK" );
226 BOOST_CHECK_EQUAL( calls, 3 );
227 SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
228 BOOST_CHECK_EQUAL( calls, 3 );
230 // Ensure, removing an already closed file-descriptor doesn't wreak havoc
234 SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
235 BOOST_CHECK_EQUAL( calls, 3 );
237 BOOST_CHECK (stop_server(pid));
242 bool is_close(senf::ClockService::clock_type a, senf::ClockService::clock_type b)
244 return (a<b ? b-a : a-b) < senf::ClockService::milliseconds(50);
248 void handler(int events)
254 SENF_AUTO_UNIT_TEST(fileDispatcher)
256 char const * enabled (getenv("SENF_TIMING_CRITICAL_TESTS"));
257 BOOST_WARN_MESSAGE(enabled, "Set SENF_TIMING_CRITICAL_TESTS to not skip timing critical tests");
259 senf::scheduler::detail::FileDispatcher::instance().timeout(500);
261 int fd (open("test.empty.file", O_RDWR|O_CREAT|O_TRUNC, 0600));
263 senf::ClockService::clock_type t (senf::ClockService::now());
265 senf::scheduler::FdEvent fde ("testHandler", &handler,
266 fd, senf::scheduler::FdEvent::EV_READ);
267 SENF_CHECK_NO_THROW( senf::scheduler::detail::FdManager::instance().processOnce() );
268 SENF_CHECK_NO_THROW( senf::scheduler::detail::FileDispatcher::instance().prepareRun() );
269 SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
271 BOOST_CHECK( called );
273 BOOST_CHECK_PREDICATE( is_close, (t)(senf::ClockService::now()) );
275 catch (std::exception const & ex) {
276 std::cerr << "Exception:\n" << ex.what() << "\n";
282 t = senf::ClockService::now();
283 SENF_CHECK_NO_THROW( senf::scheduler::detail::FdManager::instance().processOnce() );
284 SENF_CHECK_NO_THROW( senf::scheduler::detail::FileDispatcher::instance().prepareRun() );
285 SENF_CHECK_NO_THROW( senf::scheduler::detail::FIFORunner::instance().run() );
287 BOOST_CHECK( ! called );
289 BOOST_CHECK_PREDICATE(
290 is_close, (t+senf::ClockService::milliseconds(500))(senf::ClockService::now()) );
292 unlink("test.empty.file");
293 senf::scheduler::detail::FileDispatcher::instance().timeout(-1);
296 //-/////////////////////////////////////////////////////////////////////////////////////////////////
303 // comment-column: 40
304 // c-file-style: "senf"
305 // indent-tabs-mode: nil
306 // ispell-local-dictionary: "american"
307 // compile-command: "scons -u test"