/*************************************************************************** * Copyright (C) 2004 by Intra2net AG * * info@intra2net.com * * * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_CONFIG_H #include #endif using namespace std; using namespace libt2n; using namespace CppUnit; // this is an evil hack to get access to real_write, don't ever do this in an app!!! class real_write_connection: public socket_server_connection { public: void real_write(const std::string& data) { socket_write(data); } }; class test_hello : public TestFixture { CPPUNIT_TEST_SUITE(test_hello); CPPUNIT_TEST(HelloOk); CPPUNIT_TEST(BadTag); CPPUNIT_TEST(BadVersion); CPPUNIT_TEST(SeparatorMissing); CPPUNIT_TEST(WrongByteOrder); CPPUNIT_TEST(OtherServerBig); CPPUNIT_TEST(OtherServerSmall); CPPUNIT_TEST_SUITE_END(); public: void setUp() { } void tearDown() { } void send_hello(string hello_string, socket_server* ss, int conn_id) { server_connection *sc=ss->get_connection(conn_id); sc->write(hello_string); } void send_raw_socket(string hello_string, socket_server* ss, int conn_id) { socket_server_connection *ssc=dynamic_cast(ss->get_connection(conn_id)); // this is an evil hack to get access to real_write, don't ever do this in an app!!! real_write_connection *rwc=(real_write_connection*)ssc; rwc->real_write(hello_string); } void HelloOk() { pid_t pid; switch(pid=fork()) { case -1: { CPPUNIT_FAIL("fork error"); break; } case 0: // child { socket_server ss("./socket"); ostringstream hello; hello << "T2Nv" << PROTOCOL_VERSION << ';'; int byteordercheck=1; hello.write((char*)&byteordercheck,sizeof(byteordercheck)); hello << ';'; ss.add_callback(new_connection,bind(&test_hello::send_hello, boost::ref(*this), hello.str(),&ss, _1)); // max 10 sec for (int i=0; i < 10; i++) ss.fill_buffer(1000000); // don't call atexit and stuff _exit(0); } default: // parent { string data; // wait till server is up sleep(1); socket_client_connection sc("./socket"); command_client cc(sc); } } } void BadTag() { pid_t pid; switch(pid=fork()) { case -1: { CPPUNIT_FAIL("fork error"); break; } case 0: // child { socket_server ss("./socket"); ostringstream hello; hello << "XYZ 123"; ss.add_callback(new_connection,bind(&test_hello::send_hello, boost::ref(*this), hello.str(),&ss, _1)); // max 10 sec for (int i=0; i < 10; i++) ss.fill_buffer(1000000); // don't call atexit and stuff _exit(0); } default: // parent { string data; // wait till server is up sleep(1); socket_client_connection sc("./socket"); string errormsg; try { command_client cc(sc); } catch(t2n_version_mismatch &e) { errormsg=e.what(); } catch(...) { throw; } CPPUNIT_ASSERT_EQUAL(string("illegal hello received (T2N)"),errormsg); } } } void BadVersion() { pid_t pid; switch(pid=fork()) { case -1: { CPPUNIT_FAIL("fork error"); break; } case 0: // child { socket_server ss("./socket"); ostringstream hello; // lets hope we don't ever get near such a version number... hello << "T2Nv" << 4982271 << ';'; int byteordercheck=1; hello.write((char*)&byteordercheck,sizeof(byteordercheck)); hello << ';'; ss.add_callback(new_connection,bind(&test_hello::send_hello, boost::ref(*this), hello.str(),&ss, _1)); // max 10 sec for (int i=0; i < 10; i++) ss.fill_buffer(1000000); // don't call atexit and stuff _exit(0); } default: // parent { string data; // wait till server is up sleep(1); socket_client_connection sc("./socket"); string errormsg; try { command_client cc(sc); } catch(t2n_version_mismatch &e) { errormsg=e.what(); } catch(...) { throw; } CPPUNIT_ASSERT_EQUAL(string("not compatible with the server protocol version"),errormsg); } } } void SeparatorMissing() { pid_t pid; switch(pid=fork()) { case -1: { CPPUNIT_FAIL("fork error"); break; } case 0: // child { socket_server ss("./socket"); ostringstream hello; hello << "T2Nv" << PROTOCOL_VERSION; int byteordercheck=1; hello.write((char*)&byteordercheck,sizeof(byteordercheck)); hello << ';'; ss.add_callback(new_connection,bind(&test_hello::send_hello, boost::ref(*this), hello.str(),&ss, _1)); // max 10 sec for (int i=0; i < 10; i++) ss.fill_buffer(1000000); // don't call atexit and stuff _exit(0); } default: // parent { string data; // wait till server is up sleep(1); socket_client_connection sc("./socket"); string errormsg; try { command_client cc(sc); } catch(t2n_version_mismatch &e) { errormsg=e.what(); } catch(...) { throw; } CPPUNIT_ASSERT_EQUAL(string("illegal hello received (1. ;)"),errormsg); } } } void WrongByteOrder() { pid_t pid; switch(pid=fork()) { case -1: { CPPUNIT_FAIL("fork error"); break; } case 0: // child { socket_server ss("./socket"); ostringstream hello; hello << "T2Nv" << PROTOCOL_VERSION << ';'; int byteordercheck=1; int dst; char* si=(char*)&byteordercheck; char* di=(char*)&dst; di[0]=si[3]; di[1]=si[2]; di[2]=si[1]; di[3]=si[0]; hello.write((char*)&dst,sizeof(dst)); hello << ';'; ss.add_callback(new_connection,bind(&test_hello::send_hello, boost::ref(*this), hello.str(),&ss, _1)); // max 10 sec for (int i=0; i < 10; i++) ss.fill_buffer(1000000); // don't call atexit and stuff _exit(0); } default: // parent { string data; // wait till server is up sleep(1); socket_client_connection sc("./socket"); string errormsg; try { command_client cc(sc); } catch(t2n_version_mismatch &e) { errormsg=e.what(); } catch(...) { throw; } CPPUNIT_ASSERT_EQUAL(string("host byte order not matching"),errormsg); } } } void OtherServerBig() { pid_t pid; switch(pid=fork()) { case -1: { CPPUNIT_FAIL("fork error"); break; } case 0: // child { socket_server ss("./socket"); ostringstream hello; // hmm, we got the wrong socket hello << "* OK intradev.net.lan Cyrus IMAP4 v2.2.13 server ready"; ss.add_callback(new_connection,bind(&test_hello::send_raw_socket, boost::ref(*this), hello.str(),&ss, _1)); // max 3 sec for (int i=0; i < 3; i++) ss.fill_buffer(1000000); // don't call atexit and stuff _exit(0); } default: // parent { string data; // wait till server is up sleep(1); socket_client_connection sc("./socket"); string errormsg; try { command_client cc(sc); } catch(t2n_version_mismatch &e) { errormsg=e.what(); } catch(...) { throw; } CPPUNIT_ASSERT_EQUAL(string("illegal hello received (T2N)"),errormsg); } } } void OtherServerSmall() { pid_t pid; switch(pid=fork()) { case -1: { CPPUNIT_FAIL("fork error"); break; } case 0: // child { socket_server ss("./socket"); ostringstream hello; // hmm, we got the wrong socket hello << "READY"; ss.add_callback(new_connection,bind(&test_hello::send_raw_socket, boost::ref(*this), hello.str(),&ss, _1)); // max 3 sec for (int i=0; i < 3; i++) ss.fill_buffer(1000000); // don't call atexit and stuff _exit(0); } default: // parent { string data; // wait till server is up sleep(1); socket_client_connection sc("./socket"); string errormsg; try { command_client cc(sc); } catch(t2n_version_mismatch &e) { errormsg=e.what(); } catch(...) { throw; } CPPUNIT_ASSERT_EQUAL(string("illegal hello received (T2N)"),errormsg); } } } }; CPPUNIT_TEST_SUITE_REGISTRATION(test_hello);