2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
22 * (c) Copyright 2007-2009 by Intra2net AG
32 #include <cppunit/extensions/TestFactoryRegistry.h>
33 #include <cppunit/ui/text/TestRunner.h>
34 #include <cppunit/extensions/HelperMacros.h>
36 #include <async_io.hpp>
37 #include <async_pipe.hpp>
38 #include <async_process.hpp>
39 #include <async_timer.hpp>
40 #include <async_callout.hpp>
41 #include <async_socket.hpp>
42 #include <asyncio_system_tools.hpp>
43 #include <asyncio_containerfunc.hpp>
44 #include <boost/signal.hpp>
45 #include <boost/bind.hpp>
46 #include <boost/random.hpp>
50 #define DOUT(msg) std::cout << msg << std::endl
52 #define DOUT(msg) do {} while (0)
57 using namespace AsyncIo;
60 using namespace CppUnit;
70 Counter() : value(0) { DOUT("Counter construct");}
72 void reset() { value=0;}
76 DOUT(" advance called");
85 }; // eo struct Counter
88 class TestTimer : public TimerBase
98 void setDelta(long msec)
100 setDeltaWhenTime(0,msec);
102 } // eo setDelta(long)
109 virtual void execute()
114 }; // eo class TestTimer
120 std::vector<std::string> m_received_vector;
121 std::string m_received_string;
123 unsigned long m_count_lines;
124 unsigned long m_data_size;
127 void resetReceivedData()
129 m_received_vector.clear();
130 m_received_string.clear();
136 void receiveData(const std::string& data)
138 m_received_vector.push_back(data);
139 m_received_string.append(data);
141 m_data_size += data.size();
142 } // eo receiveData(const std::string&)
144 }; // eo struct ReceivedData
148 class TestPipe : public SimplePipe, public ReceivedData
154 signal_received_string.connect( boost::bind(&TestPipe::receiveData, this, _1) );
161 }; // eo class TestPipe
164 class TestIO : public SimpleIO2, public ReceivedData
169 signal_received_string.connect( boost::bind(&TestIO::receiveData, this, _1) );
175 class TestProcess : public ProcessImplementation, public ReceivedData
179 const std::string& path,
180 const std::vector<std::string>& args= std::vector<std::string>() )
181 : ProcessImplementation(path,args)
183 m_signal_read.connect( boost::bind(&TestProcess::slotReceivedData, this) );
184 } // eo Testprocess(const std::string&, const std::vector<std::string>&)
187 const std::string& path,
188 const std::string& arg1 )
189 : ProcessImplementation(
191 TransientPushBackFiller< std::string,std::vector >()(arg1)
194 m_signal_read.connect( boost::bind(&TestProcess::slotReceivedData, this) );
195 } // eo Testprocess(const std::string&, const std::vector<std::string>&)
198 const std::string& path,
199 const std::string& arg1, const std::string& arg2 )
200 : ProcessImplementation(
202 TransientPushBackFiller< std::string, std::vector >()(arg1)(arg2)
205 m_signal_read.connect( boost::bind(&TestProcess::slotReceivedData, this) );
206 } // eo Testprocess(const std::string&, const std::vector<std::string>&)
210 pid_t pid() { return m_pid; }
212 bool kill( Signal signal) { return ProcessImplementation::kill(signal); }
216 void slotReceivedData()
218 receiveData(m_input_buffer);
219 m_input_buffer.clear();
220 } // eo slotReceivedData()
222 }; // eo class TestProcess
226 class TestUnixIOSocket
227 : public UnixIOSocket
228 , public ReceivedData
235 m_signal_read.connect( boost::bind(&TestUnixIOSocket::slotReceivedData, this) );
236 } // eo TestUnixIOSocket()
240 int fd, const std::string& path,
241 unsigned int peer_pid, unsigned int peer_uid, unsigned int peer_gid
243 : UnixIOSocket(fd, path, peer_pid, peer_uid, peer_gid)
245 m_signal_read.connect( boost::bind(&TestUnixIOSocket::slotReceivedData, this) );
246 } // eo TestUnixIOSocket()
249 void sendData(const std::string& data)
252 } // eo sendData(const std::string&)
256 void slotReceivedData()
258 receiveData(m_input_buffer);
259 m_input_buffer.clear();
260 } // eo slotReceivedData()
262 }; // eo class TestUnixIOSocket
264 typedef boost::shared_ptr< TestUnixIOSocket > TestUnixIOSocketPtr;
267 class UnixIOSocketHolder
268 : public std::vector< UnixIOSocketPtr >
272 void operator()(UnixIOSocketPtr ptr)
277 void storeBase (IOImplementationPtr ptr)
279 push_back(boost::dynamic_pointer_cast< UnixIOSocket >(ptr) );
282 void store (UnixIOSocketPtr ptr)
287 TestUnixIOSocketPtr get(int idx)
289 return boost::dynamic_pointer_cast<
293 }; // eo class UnixIOSocketHolder
296 /// global random generator (from boost lib).
297 boost::mt19937 g_random_gen;
301 * generates a string with random characters from a given ASCII subset.
302 * @param len the desired length of the output string
303 * @return a random string of length @a len
305 std::string makeRandomAsciiString(std::string::size_type len)
307 static std::string chars("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz=+-*/%(){}<>.,:;\\");
310 boost::uniform_int<> discreter(0, chars.size()-1);
311 boost::variate_generator<boost::mt19937&, boost::uniform_int<> > idxgen(g_random_gen, discreter);
313 for(; len-->0;) s+= chars.at( idxgen() );
316 } // eo makeRandomAsciiString
319 } // eo namespace <anonymous>
323 class TestSimpleioBasics : public TestFixture
325 CPPUNIT_TEST_SUITE(TestSimpleioBasics);
327 CPPUNIT_TEST(EmptyBackendStepCall);
328 CPPUNIT_TEST(NonEmptyBackendStepCall);
329 CPPUNIT_TEST(SingleTimerShot);
330 CPPUNIT_TEST(SimpleTimerShot);
331 CPPUNIT_TEST(SimpleTimerShot2);
333 CPPUNIT_TEST(EmptyWantTest);
334 CPPUNIT_TEST(SimplePipeTest);
335 CPPUNIT_TEST(SimplePipePump);
337 CPPUNIT_TEST(SimpleProcessTestBinTrue);
338 CPPUNIT_TEST(SimpleProcessTestBinFalse);
339 CPPUNIT_TEST(SimpleProcessTestEcho);
340 CPPUNIT_TEST(SimpleProcessTestStderr);
341 CPPUNIT_TEST(SignaledProcessTermination);
344 CPPUNIT_TEST(CallOut1);
345 CPPUNIT_TEST(CallOut2);
346 CPPUNIT_TEST(RemoveCallOut1);
348 CPPUNIT_TEST(FrozenCall_Thaw);
349 CPPUNIT_TEST(FrozenCall_Decay);
352 CPPUNIT_TEST(UnixSockets_ClientServer);
355 //CPPUNIT_TEST(Dummy);
356 CPPUNIT_TEST_SUITE_END();
361 std::set<std::string> used_check_files;
364 template<class Callable>
365 bool backendLoopUntil( Callable condition, int maxLoops=100 )
367 for (int i=std::max(maxLoops,1); i-->0 && ! condition();)
369 backend->doOneStep(10);
372 } // eo backendLoopUntil
375 bool backendStep(int msTimeout= 10, int count=1)
378 for(;count-->0 && res;)
380 res= backend->doOneStep(msTimeout);
386 std::string getCheckFilepath(std::string tag)
389 result= "__unittest__" + tag + ".dat";
390 used_check_files.insert(result);
392 } // eo get_check_file_path
395 void removeCheckFiles()
397 for(std::set<std::string>::iterator it= used_check_files.begin();
398 it != used_check_files.end();
401 std::string filepath(*it);
402 if (Utils::FileStat(filepath))
404 Utils::unlink(filepath);
407 used_check_files.clear();
408 } // eo removeCheckFiles
416 backend = Backend::getBackend();
417 installChildHandler();
418 used_check_files.clear();
424 restoreChildHandler();
439 void EmptyBackendStepCall()
441 CPPUNIT_ASSERT( backend );
443 // a backend call without active objects should return false:
444 bool result = backend->doOneStep(0);
446 CPPUNIT_ASSERT_EQUAL( false, result );
447 } // eo EmptyBackendStepCall
451 void NonEmptyBackendStepCall()
453 CPPUNIT_ASSERT(backend);
458 // with an active object, a step should return true:
459 bool result = backend->doOneStep(0);
460 CPPUNIT_ASSERT_EQUAL( true, result );
461 // the timer should not be executed:
462 CPPUNIT_ASSERT_EQUAL( 0u, timer.m_counter );
464 // now it should return false:
465 bool result = backend->doOneStep(0);
466 CPPUNIT_ASSERT_EQUAL( false, result );
467 } // eo NonEmptyBackendStepCall
472 * check for timer to execute immediatly.
474 void SingleTimerShot()
476 CPPUNIT_ASSERT(backend);
479 timer.setDelta(0); // shot now!
481 bool result = backend->doOneStep(10);
483 CPPUNIT_ASSERT_EQUAL( true, result );
484 // the timer should be executed once:
485 CPPUNIT_ASSERT_EQUAL( 1u, timer.m_counter );
487 result = backend->doOneStep(0);
489 CPPUNIT_ASSERT_EQUAL( false, result );
490 // the timer should not be executed again:
491 CPPUNIT_ASSERT_EQUAL( 1u, timer.m_counter );
493 } // eo SingleTimerShot()
498 * tests a simple timer class to be executed with a timeout.
500 void SimpleTimerShot()
503 CPPUNIT_ASSERT(backend);
507 timer1.addAction( boost::bind(&Counter::advance,&counter1) );
508 CPPUNIT_ASSERT_EQUAL(false, timer1.active());
510 timer1.startTimerMS( 100 );
511 CPPUNIT_ASSERT_EQUAL(true, timer1.active());
513 res=backend->doOneStep( 1000 );
514 CPPUNIT_ASSERT_EQUAL( true, res );
516 CPPUNIT_ASSERT_EQUAL( 1, counter1.value );
517 } // eo SimpleTimerShot
522 * tests 3 timers; after the first was active, disable another and check if the remaining one fires.
524 void SimpleTimerShot2()
527 CPPUNIT_ASSERT(backend);
529 SimpleTimer timer1, timer2, timer3;
530 Counter counter1, counter2, counter3;
531 timer1.addAction( boost::bind(&Counter::advance,&counter1) );
532 timer2.addAction( boost::bind(&Counter::advance,&counter2) );
533 timer3.addAction( boost::bind(&Counter::advance,&counter3) );
534 CPPUNIT_ASSERT_EQUAL(false, timer1.active());
535 CPPUNIT_ASSERT_EQUAL(false, timer2.active());
536 CPPUNIT_ASSERT_EQUAL(false, timer3.active());
538 timer1.startTimerMS( 100 );
539 timer2.startTimerMS( 500 );
540 timer3.startTimerMS( 400 );
541 CPPUNIT_ASSERT_EQUAL(true, timer1.active());
542 CPPUNIT_ASSERT_EQUAL(true, timer2.active());
543 CPPUNIT_ASSERT_EQUAL(true, timer3.active());
545 res=backend->doOneStep( 1000 );
546 CPPUNIT_ASSERT_EQUAL( true, res );
548 CPPUNIT_ASSERT_EQUAL(false, timer1.active());
549 CPPUNIT_ASSERT_EQUAL(true, timer2.active());
550 CPPUNIT_ASSERT_EQUAL(true, timer3.active());
552 CPPUNIT_ASSERT_EQUAL( 1, counter1.value );
553 CPPUNIT_ASSERT_EQUAL( 0, counter2.value );
554 CPPUNIT_ASSERT_EQUAL( 0, counter3.value );
556 // now stop the next timer:
558 CPPUNIT_ASSERT_EQUAL(false, timer3.active());
560 res=backend->doOneStep( 1000 );
561 CPPUNIT_ASSERT_EQUAL( true, res );
563 CPPUNIT_ASSERT_EQUAL( 1, counter1.value );
564 CPPUNIT_ASSERT_EQUAL( 1, counter2.value );
565 CPPUNIT_ASSERT_EQUAL( 0, counter3.value );
566 } // eo SimpleTimerShot2
579 CPPUNIT_ASSERT_EQUAL(false, io.wantRead() );
580 CPPUNIT_ASSERT_EQUAL(false, io.wantWrite() );
581 } // eo EmptyWantTest
585 * a simple pipe (and io) test.
587 * This test basically tests the io framework.
588 * It opens two connected pipes and sends a test string in each direction.
589 * It tests the following functionalities of the base classes:
590 * - set write marks in backend step (enabling direct send of data)
592 * - construct and interpret poll() data structures
594 * - signal chains for received data
599 void SimplePipeTest()
601 static const std::string test_string("a test string");
602 static const std::string test_string2("only another short test string");
604 CPPUNIT_ASSERT(backend);
606 TestPipe pipe1, pipe2;
608 bool res= pipe1.makePipe(pipe2);
610 CPPUNIT_ASSERT_EQUAL(true, res);
611 CPPUNIT_ASSERT_EQUAL(true, pipe1.opened());
612 CPPUNIT_ASSERT_EQUAL(true, pipe2.opened());
614 res= backend->doOneStep(0);
615 CPPUNIT_ASSERT_EQUAL(true, res);
617 pipe1.sendString(test_string);
619 res= backend->doOneStep(0);
620 CPPUNIT_ASSERT_EQUAL(true, res);
622 CPPUNIT_ASSERT_EQUAL( test_string, pipe2.m_received_string );
624 pipe2.sendString(test_string2);
626 res= backend->doOneStep(0);
627 CPPUNIT_ASSERT_EQUAL(true, res);
629 CPPUNIT_ASSERT_EQUAL( test_string2, pipe1.m_received_string );
632 CPPUNIT_ASSERT_EQUAL(false, pipe1.opened());
634 res= backend->doOneStep(0);
635 CPPUNIT_ASSERT_EQUAL(true, res);
637 CPPUNIT_ASSERT_EQUAL(true, pipe2.eof());
638 } // eo SimplePipeTest
643 * sends a larger data chunk through a pipe.
644 * This tests if sending and receiving data in (smaller internal) chunks works.
646 void SimplePipePump()
648 CPPUNIT_ASSERT(backend);
650 TestPipe pipe1, pipe2;
652 bool res= pipe1.makePipe(pipe2);
654 CPPUNIT_ASSERT_EQUAL(true, res);
655 CPPUNIT_ASSERT_EQUAL(true, pipe1.opened());
656 CPPUNIT_ASSERT_EQUAL(true, pipe2.opened());
658 res= backend->doOneStep(0);
659 CPPUNIT_ASSERT_EQUAL(true, res);
661 std::string test_string= makeRandomAsciiString(256*1024);
663 pipe1.sendString(test_string);
665 res= backend->doOneStep(0);
666 CPPUNIT_ASSERT_EQUAL(true, res);
668 // do some backend cycles to empty the pipe:
669 for (int i=64; i-->0 && res && !pipe1.empty(); )
671 res= backend->doOneStep(100);
675 CPPUNIT_ASSERT_EQUAL(false, pipe1.opened());
677 // now read the remaining data until we recognize EOF:
678 for (int i=64; i-->0 && res && !pipe2.eof();)
680 res= backend->doOneStep(100);
683 CPPUNIT_ASSERT_EQUAL( test_string.size(), pipe2.m_received_string.size() );
684 CPPUNIT_ASSERT_EQUAL( test_string, pipe2.m_received_string );
686 CPPUNIT_ASSERT_EQUAL(true, pipe2.eof());
687 } // eo SimplePipePump
692 * fork a subprocess (/bin/true) and test exit code.
694 void SimpleProcessTestBinTrue()
697 CPPUNIT_ASSERT(backend);
699 TestProcess proc("/bin/true");
701 res= proc.startProcess();
702 CPPUNIT_ASSERT_EQUAL(true, res);
704 res= backend->doOneStep(200);
705 CPPUNIT_ASSERT_EQUAL(true, res);
707 for(int i=20; i-->0 && proc.processState() != ProcessState::stopped;)
709 backend->doOneStep(15);
712 CPPUNIT_ASSERT_EQUAL( ProcessState(ProcessState::stopped), proc.processState() );
713 CPPUNIT_ASSERT_EQUAL( true, proc.eof() );
714 CPPUNIT_ASSERT_EQUAL( 0, proc.exitCode() );
715 } // eo SimpleProcessTestBinTrue
719 * fork a subprocess (/bin/false) and test exit code.
721 void SimpleProcessTestBinFalse()
724 CPPUNIT_ASSERT(backend);
726 TestProcess proc("/bin/false");
728 res= proc.startProcess();
729 CPPUNIT_ASSERT_EQUAL(true, res);
731 res= backend->doOneStep(200);
732 CPPUNIT_ASSERT_EQUAL(true, res);
733 for(int i=20; i-->0 && proc.processState() != ProcessState::stopped;)
735 backend->doOneStep(15);
738 CPPUNIT_ASSERT_EQUAL( ProcessState(ProcessState::stopped), proc.processState() );
739 CPPUNIT_ASSERT_EQUAL( true, proc.eof() );
740 CPPUNIT_ASSERT_EQUAL( 1, proc.exitCode() );
741 DOUT("leave SimpleProcessTestBinFalse");
742 } // eo SimpleProcessTestBinFalse
746 * fork an echo subprocess and read back the output.
748 void SimpleProcessTestEcho()
750 DOUT("enter SimpleProcessTestEcho");
752 CPPUNIT_ASSERT(backend);
756 TransientPushBackFiller<std::string, std::vector >()("Eine")("Zeichenkette")
759 res= proc.startProcess();
760 CPPUNIT_ASSERT_EQUAL(true, res);
762 res= backend->doOneStep(200);
763 CPPUNIT_ASSERT_EQUAL(true, res);
764 for(int i=20; i-->0 && (proc.processState()!= ProcessState::stopped || !proc.eof());)
766 backend->doOneStep(10);
769 CPPUNIT_ASSERT_EQUAL( ProcessState(ProcessState::stopped), proc.processState() );
770 CPPUNIT_ASSERT_EQUAL( true, proc.eof() );
771 CPPUNIT_ASSERT_EQUAL( 0, proc.exitCode() );
772 CPPUNIT_ASSERT_EQUAL( std::string("Eine Zeichenkette\n"), proc.m_received_string);
773 } // eo SimpleProcessTestEcho
778 * fork a bash subprocess, echo something on stderr and read back the output.
780 void SimpleProcessTestStderr()
783 CPPUNIT_ASSERT(backend);
789 TransientPushBackFiller<std::string, std::vector >()
791 ("echo Eine Zeichenkette >&2")
794 // start with a seperate io object for stderr.
795 DOUT("## start process");
796 res= proc.startProcess( &my_stderr );
797 CPPUNIT_ASSERT_EQUAL(true, res);
798 CPPUNIT_ASSERT_EQUAL(true, my_stderr.opened());
800 DOUT("## do a backend step");
801 res= backend->doOneStep(200);
802 CPPUNIT_ASSERT_EQUAL(true, res);
803 // wait until process stopped and both io's signal EOF (or until the loop ends ;-) )
804 DOUT("## enter loop");
805 for(int i=17; i-->0 && (proc.processState()!= ProcessState::stopped || !proc.eof() || !my_stderr.eof());)
807 DOUT("## round i=" << i);
808 backend->doOneStep(10);
810 DOUT("## loop left");
812 CPPUNIT_ASSERT_EQUAL( ProcessState(ProcessState::stopped), proc.processState() );
813 CPPUNIT_ASSERT_EQUAL( true, proc.eof() );
814 CPPUNIT_ASSERT_EQUAL( true, my_stderr.eof() );
815 CPPUNIT_ASSERT_EQUAL( 0, proc.exitCode() );
816 CPPUNIT_ASSERT_EQUAL( std::string("Eine Zeichenkette\n"), my_stderr.m_received_string);
817 DOUT("leave Test SimpleProcessTestStderr");
818 } // eo SimpleProcessTestStderr
823 * checks termination of process by signal and if the signal is returned.
825 void SignaledProcessTermination()
828 CPPUNIT_ASSERT(backend);
830 TestProcess proc("/bin/sleep","2");
831 res= proc.startProcess();
832 CPPUNIT_ASSERT_EQUAL(true, res);
834 res= backend->doOneStep(10);
835 CPPUNIT_ASSERT_EQUAL(true, res);
836 CPPUNIT_ASSERT_EQUAL( ProcessState(ProcessState::running), proc.processState() );
838 res= backend->doOneStep(50);
840 // now send the process an USR1 (which terminates the process)
841 res=proc.kill( Signal::USR1 );
842 CPPUNIT_ASSERT_EQUAL(true, res);
844 // give the backend a chance to process the termination event:
845 for(int i=30; i-->0 && proc.processState()!=ProcessState::stopped;) backend->doOneStep(10);
847 CPPUNIT_ASSERT_EQUAL( ProcessState(ProcessState::stopped), proc.processState() );
848 CPPUNIT_ASSERT_EQUAL( true, proc.eof() );
849 CPPUNIT_ASSERT_EQUAL( Signal::USR1 , proc.exitCode()>>8 );
850 } // eo SignaledProcessTermination
858 callOut( boost::bind(&Counter::advance, &count), 1 );
859 backend->doOneStep( 10 );
861 CPPUNIT_ASSERT_EQUAL( 0, count.value );
862 backend->doOneStep( 1100 );
864 CPPUNIT_ASSERT_EQUAL( 1, count.value );
873 callOut( boost::bind(&Counter::advance, &count), 0.5 );
874 backend->doOneStep( 10 );
876 CPPUNIT_ASSERT_EQUAL( 0, count.value );
877 backend->doOneStep( 800 );
879 CPPUNIT_ASSERT_EQUAL( 1, count.value );
884 void RemoveCallOut1()
888 CallOutId id= callOut( boost::bind(&Counter::advance, &count), 1 );
889 backend->doOneStep( 10 );
891 CPPUNIT_ASSERT_EQUAL( 0, count.value );
892 bool res1 = removeCallOut(id);
893 bool res2 = removeCallOut(id);
895 CPPUNIT_ASSERT_EQUAL( true, res1 );
896 CPPUNIT_ASSERT_EQUAL( false, res2 );
898 backend->doOneStep( 1100 );
900 CPPUNIT_ASSERT_EQUAL( 0, count.value );
901 } // eo RemoveCallOut1()
905 void FrozenCall_Thaw()
909 CallOutId id= frozenCall( boost::bind(&Counter::advance, &count), 1 );
910 backend->doOneStep( 10 );
912 CPPUNIT_ASSERT_EQUAL( 0, count.value );
915 backend->doOneStep( 1100 );
917 CPPUNIT_ASSERT_EQUAL( 1, count.value );
918 } // eo FrozenCall_Thaw()
922 void FrozenCall_Decay()
926 CallOutId id= frozenCall( boost::bind(&Counter::advance, &count), 1 );
927 backend->doOneStep( 10 );
929 CPPUNIT_ASSERT_EQUAL( 0, count.value );
930 CPPUNIT_ASSERT_EQUAL( true, id.active() );
931 backend->doOneStep( 1100 );
933 CPPUNIT_ASSERT_EQUAL( 0, count.value );
934 CPPUNIT_ASSERT_EQUAL( false, id.active() );
935 } // eo FrozenCall_Decay()
939 void UnixSockets_ClientServer()
941 std::string path= getCheckFilepath("UDS_CS");
943 UnixIOSocketHolder server_holder;
944 UnixServerSocket< TestUnixIOSocket > server_port;
945 UnixIOSocketPtr server;
946 TestUnixIOSocket client0;
947 TestUnixIOSocket client1;
949 bool res1 = server_port.open(path, 0600);
950 CPPUNIT_ASSERT_EQUAL( true, res1 );
953 AsyncIo::Utils::FileStat stat(path,false);
954 CPPUNIT_ASSERT( stat.is_socket() );
955 CPPUNIT_ASSERT_EQUAL( 0600u, (stat.mode() & 0777));
958 server_port.setNewConnectionCallback(
959 boost::bind( &UnixIOSocketHolder::store, &server_holder, _1)
962 // open a first client
963 bool res2= client0.open(path);
964 CPPUNIT_ASSERT_EQUAL( true, res2 );
966 CPPUNIT_ASSERT_EQUAL(0u, server_holder.size() );
968 CPPUNIT_ASSERT_EQUAL(1u, server_holder.size() );
969 CPPUNIT_ASSERT( server_holder.get(0).get() );
971 client0.sendData("a simple test string.");
974 CPPUNIT_ASSERT_EQUAL(
975 std::string("a simple test string."),
976 server_holder.get(0)->m_received_string
978 server_holder.get(0)->sendData("reply 1");
980 CPPUNIT_ASSERT_EQUAL( std::string("reply 1"), client0.m_received_string );
982 // open a second client
983 res2= client1.open(path);
984 CPPUNIT_ASSERT_EQUAL( true, res2 );
986 CPPUNIT_ASSERT_EQUAL(2u, server_holder.size() );
987 CPPUNIT_ASSERT( server_holder.get(1).get() );
989 server_holder.get(1)->sendData("::reply 2");
991 CPPUNIT_ASSERT_EQUAL( std::string("::reply 2"), client1.m_received_string );
993 client1.sendData("another simple test string. 124");
996 CPPUNIT_ASSERT_EQUAL(
997 std::string("another simple test string. 124"),
998 server_holder.get(1)->m_received_string
1001 // close first client
1003 CPPUNIT_ASSERT_EQUAL( false, server_holder.get(0)->eof() );
1005 CPPUNIT_ASSERT_EQUAL( true, server_holder.get(0)->eof() );
1006 server_holder.get(0)->close();
1008 // close second connection from server side
1009 CPPUNIT_ASSERT_EQUAL( false, client1.eof() );
1010 server_holder.get(1)->close();
1012 CPPUNIT_ASSERT_EQUAL( true, client1.eof() );
1014 } // eo UnixSockets_ClientServer()
1019 using namespace std;
1020 cout << endl << "Random strings:" << endl;
1021 for (int i=10; i-->0;)
1023 cout << " " << makeRandomAsciiString(70)<< endl;
1028 }; // eo class TestSimpleioBasics
1031 CPPUNIT_TEST_SUITE_REGISTRATION(TestSimpleioBasics);