libeventベースのアプリケーションをテストする
libevent(Fast portable non-blocking network programming with Libevent)で回ってるようなアプリのテストって悩ましいよね。
event_dispatchをしてしまうと、Testのコードに戻れないし!
そんな悩める少年少女に送る云々
つまるところは、event_base_loop(or event_loop?)を回せばいいのさジョニー
typedef std::shared_ptr<struct event_base> pevenv_t; event_base * ptr = event_base_new(); BOOST_CHECK(ptr != NULL); pevenv_t pevenv(ptr, event_base_free); ... BOOST_CHECK(event_base_loop(pevenv.get(), EVLOOP_ONCE) == 0);
ものは試し、inotify(inotify を使ってファイルシステムのアクティビティーを監視する)と合わせて簡単なテストを書いてみようそうしよう
#include <event.h> #include <iostream> #include <memory> #include <boost/test/minimal.hpp> #include <sys/inotify.h> #include <sys/ioctl.h> void on_notify(int fd, short event, void * arg) { int len, vpos = 0; ioctl(fd, FIONREAD, &len); std::shared_ptr<char> buf((char *)malloc(len), free); read(fd, buf.get(), len); while(vpos < len) { inotify_event * piev((inotify_event *)(buf.get() + vpos)); std::cout << "Event:"; if(piev->mask == IN_CREATE) std::cout<< "CREATE" << std::endl; else if(piev->mask == IN_MODIFY) std::cout<< "MODIFY" << std::endl; else std::cout<< "???" << std::endl; std::cout << "Name:" << std::string(piev->name, piev->len) << std::endl; vpos += (sizeof(inotify_event) + piev->len); } } int test_main(int, char **) { typedef std::shared_ptr<struct event_base> pevenv_t; event_base * ptr = event_base_new(); BOOST_REQUIRE(ptr != NULL); pevenv_t pevenv(ptr, event_base_free); int fd; std::shared_ptr<struct event> pev(new event, event_del); { fd = inotify_init(); if(inotify_add_watch(fd, "./", IN_CREATE|IN_MODIFY) == -1) { close(fd); return 1; } event_set(pev.get(), fd, EV_READ | EV_PERSIST, on_notify, NULL); event_base_set(pevenv.get(), pev.get()); event_add(pev.get(), NULL); } BOOST_REQUIRE(system("echo >> temp.txt") != -1); BOOST_REQUIRE(event_base_loop(pevenv.get(), EVLOOP_ONCE) == 0); std::cout << "Main!" << std::endl; return 0; }
% g++ test.cpp -std=c++0x -I/usr/local/include/boost-1_39 -levent % ./a.out Event:CREATE Name:temp.txt Event:MODIFY Name:temp.txt Main! **** no errors detected %