libmoost
|
00001 /* vim:set ts=3 sw=3 sts=3 et: */ 00028 #include <boost/test/unit_test.hpp> 00029 #include <boost/test/test_tools.hpp> 00030 00031 #include <vector> 00032 #include <istream> 00033 #include <ostream> 00034 #include <fstream> 00035 00036 #include <boost/filesystem/path.hpp> 00037 #include <boost/filesystem/operations.hpp> 00038 00039 #include "../../include/moost/thread/xtime_util.hpp" 00040 #include "../../include/moost/io/async_writer.hpp" 00041 00042 #ifdef _WIN32 00043 #define gmtime_r( _clock, _result ) \ 00044 ( *(_result) = *gmtime( (_clock) ), \ 00045 (_result) ) 00046 #endif 00047 00048 using namespace boost::filesystem; 00049 using namespace moost::thread; 00050 using namespace moost::io; 00051 00052 BOOST_AUTO_TEST_SUITE( async_writer_test ) 00053 00054 struct Item 00055 { 00056 int x; 00057 00058 void read(std::istream & in) 00059 { 00060 in.read(reinterpret_cast<char *>(&x), sizeof(x)); 00061 } 00062 00063 void write(std::ostream & out) 00064 { 00065 out.write(reinterpret_cast<const char *>(&x), sizeof(x)); 00066 } 00067 }; 00068 00069 struct Fixture 00070 { 00071 struct TempDirectory 00072 { 00073 path Path; 00074 TempDirectory(const std::string & path_name) : Path(path_name) { create_directory(Path); } 00075 ~TempDirectory() { remove_all(Path); } 00076 }; 00077 TempDirectory temp_dir; 00078 async_writer<Item> aw_simple; 00079 async_writer<Item> aw_roll; 00080 Item item; 00081 00082 Fixture() 00083 : temp_dir("async_writer_test"), 00084 aw_simple((temp_dir.Path / "simple").string()), 00085 aw_roll((temp_dir.Path / "roll").string(), count_rollover(3)) 00086 { 00087 item.x = 22; 00088 } 00089 ~Fixture() 00090 { 00091 } 00092 00093 void sleep(int seconds) 00094 { 00095 boost::thread::sleep(xtime_util::add_sec(xtime_util::now(), seconds)); 00096 } 00097 }; 00098 00099 // what happens when we do nothing? 00100 BOOST_FIXTURE_TEST_CASE( test_nothing, Fixture ) 00101 { 00102 aw_simple.stop(); 00103 aw_roll.stop(); 00104 00105 directory_iterator end_it; // default construction yields past-the-end 00106 00107 for (directory_iterator it( temp_dir.Path ); it != end_it; ++it ) 00108 { 00109 BOOST_CHECK(false); 00110 } 00111 } 00112 00113 // what happens when we write something 00114 BOOST_FIXTURE_TEST_CASE( test_something, Fixture ) 00115 { 00116 aw_simple.enqueue(item); 00117 aw_simple.stop(); 00118 00119 directory_iterator it( temp_dir.Path ); 00120 BOOST_REQUIRE(it != directory_iterator()); 00121 00122 std::ifstream in(it->string().c_str(), std::ios::binary); 00123 Item item2; 00124 item2.read(in); 00125 BOOST_CHECK_EQUAL(item2.x, item.x); 00126 BOOST_CHECK(++it == directory_iterator()); 00127 } 00128 00129 // what happens when we stop and then start? 00130 BOOST_FIXTURE_TEST_CASE( test_stopstart, Fixture ) 00131 { 00132 aw_simple.enqueue(item); 00133 aw_simple.stop(); 00134 00135 aw_simple.start(); 00136 aw_simple.enqueue(item); 00137 aw_simple.stop(); 00138 00139 directory_iterator it( temp_dir.Path ); 00140 BOOST_REQUIRE(it != directory_iterator()); 00141 00142 std::ifstream in(it->string().c_str(), std::ios::binary); 00143 00144 Item item2; 00145 item2.read(in); 00146 BOOST_CHECK_EQUAL(item2.x, item.x); 00147 00148 BOOST_REQUIRE(++it != directory_iterator()); 00149 00150 in.close(); 00151 in.clear(); 00152 in.open(it->string().c_str(), std::ios::binary); 00153 item2.x = 0; 00154 item2.read(in); 00155 BOOST_CHECK_EQUAL(item2.x, item.x); 00156 BOOST_REQUIRE(++it == directory_iterator()); 00157 } 00158 00159 // can we force a rollover 00160 BOOST_FIXTURE_TEST_CASE( test_rollover, Fixture ) 00161 { 00162 for (int i = 0; i != 4; ++i) 00163 aw_roll.enqueue(item); 00164 00165 aw_roll.stop(); 00166 00167 // we should have two files, one should have 1000, the other 1 00168 int first_file_count = 0; 00169 int second_file_count = 0; 00170 00171 directory_iterator it( temp_dir.Path ); 00172 BOOST_REQUIRE(it != directory_iterator()); 00173 00174 std::ifstream in(it->string().c_str(), std::ios::binary); 00175 Item item2; 00176 for ( ;in.is_open(); ) 00177 { 00178 item2.read(in); 00179 if (in.eof()) 00180 break; 00181 ++first_file_count; 00182 } 00183 in.close(); in.clear(); 00184 00185 BOOST_REQUIRE(++it != directory_iterator()); 00186 in.open(it->string().c_str(), std::ios::binary); 00187 for ( ;in.is_open(); ) 00188 { 00189 item2.read(in); 00190 if (in.eof()) 00191 break; 00192 ++second_file_count; 00193 } 00194 00195 BOOST_CHECK(++it == directory_iterator()); 00196 BOOST_CHECK((first_file_count == 3 && second_file_count == 1) || (first_file_count == 1 && second_file_count == 3)); 00197 } 00198 00199 // how about timeofday rollover 00200 BOOST_FIXTURE_TEST_CASE( test_timeofday_rollover, Fixture ) 00201 { 00202 struct tm time_info; 00203 time_t now; 00204 time(&now); 00205 gmtime_r(&now, &time_info); 00206 async_writer<Item, timeofday_rollover> aw_timeofday_roll((temp_dir.Path / "roll").string(), 00207 timeofday_rollover(time_info.tm_hour, time_info.tm_min, time_info.tm_sec + 2)); 00208 aw_timeofday_roll.enqueue(item); 00209 sleep(3); 00210 aw_timeofday_roll.enqueue(item); 00211 aw_timeofday_roll.stop(); 00212 00213 directory_iterator it( temp_dir.Path ); 00214 BOOST_REQUIRE(it != directory_iterator()); 00215 00216 std::ifstream in(it->string().c_str(), std::ios::binary); 00217 00218 Item item2; 00219 item2.read(in); 00220 BOOST_CHECK_EQUAL(item2.x, item.x); 00221 00222 BOOST_REQUIRE(++it != directory_iterator()); 00223 00224 in.close(); 00225 in.clear(); 00226 in.open(it->string().c_str(), std::ios::binary); 00227 item2.x = 0; 00228 item2.read(in); 00229 BOOST_CHECK_EQUAL(item2.x, item.x); 00230 BOOST_REQUIRE(++it == directory_iterator()); 00231 } 00232 00233 BOOST_AUTO_TEST_SUITE_END()