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
242 : UnixIOSocket(fd, path)
244 m_signal_read.connect( boost::bind(&TestUnixIOSocket::slotReceivedData, this) );
245 } // eo TestUnixIOSocket()
248 void sendData(const std::string& data)
251 } // eo sendData(const std::string&)
255 void slotReceivedData()
257 receiveData(m_input_buffer);
258 m_input_buffer.clear();
259 } // eo slotReceivedData()
261 }; // eo class TestUnixIOSocket
263 typedef boost::shared_ptr< TestUnixIOSocket > TestUnixIOSocketPtr;
266 class UnixIOSocketHolder
267 : public std::vector< UnixIOSocketPtr >
271 void operator()(UnixIOSocketPtr ptr)
276 void storeBase (IOImplementationPtr ptr)
278 push_back(boost::dynamic_pointer_cast< UnixIOSocket >(ptr) );
281 void store (UnixIOSocketPtr ptr)
286 TestUnixIOSocketPtr get(int idx)
288 return boost::dynamic_pointer_cast<
292 }; // eo class UnixIOSocketHolder
295 /// global random generator (from boost lib).
296 boost::mt19937 g_random_gen;
300 * generates a string with random characters from a given ASCII subset.
301 * @param len the desired length of the output string
302 * @return a random string of length @a len
304 std::string makeRandomAsciiString(std::string::size_type len)
306 static std::string chars("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz=+-*/%(){}<>.,:;\\");
309 boost::uniform_int<> discreter(0, chars.size()-1);
310 boost::variate_generator<boost::mt19937&, boost::uniform_int<> > idxgen(g_random_gen, discreter);
312 for(; len-->0;) s+= chars.at( idxgen() );
315 } // eo makeRandomAsciiString
318 } // eo namespace <anonymous>
322 class TestSimpleioBasics : public TestFixture
324 CPPUNIT_TEST_SUITE(TestSimpleioBasics);
326 CPPUNIT_TEST(EmptyBackendStepCall);
327 CPPUNIT_TEST(NonEmptyBackendStepCall);
328 CPPUNIT_TEST(SingleTimerShot);
329 CPPUNIT_TEST(SimpleTimerShot);
330 CPPUNIT_TEST(SimpleTimerShot2);
332 CPPUNIT_TEST(EmptyWantTest);
333 CPPUNIT_TEST(SimplePipeTest);
334 CPPUNIT_TEST(SimplePipePump);
336 CPPUNIT_TEST(SimpleProcessTestBinTrue);
337 CPPUNIT_TEST(SimpleProcessTestBinFalse);
338 CPPUNIT_TEST(SimpleProcessTestEcho);
339 CPPUNIT_TEST(SimpleProcessTestStderr);
340 CPPUNIT_TEST(SignaledProcessTermination);
343 CPPUNIT_TEST(CallOut1);
344 CPPUNIT_TEST(CallOut2);
345 CPPUNIT_TEST(RemoveCallOut1);
347 CPPUNIT_TEST(FrozenCall_Thaw);
348 CPPUNIT_TEST(FrozenCall_Decay);
351 CPPUNIT_TEST(UnixSockets_ClientServer);
354 //CPPUNIT_TEST(Dummy);
355 CPPUNIT_TEST_SUITE_END();
360 std::set<std::string> used_check_files;
363 template<class Callable>
364 bool backendLoopUntil( Callable condition, int maxLoops=100 )
366 for (int i=std::max(maxLoops,1); i-->0 && ! condition();)
368 backend->doOneStep(10);
371 } // eo backendLoopUntil
374 bool backendStep(int msTimeout= 10, int count=1)
377 for(;count-->0 && res;)
379 res= backend->doOneStep(msTimeout);
385 std::string getCheckFilepath(std::string tag)
388 result= "__unittest__" + tag + ".dat";
389 used_check_files.insert(result);
391 } // eo get_check_file_path
394 void removeCheckFiles()
396 for(std::set<std::string>::iterator it= used_check_files.begin();
397 it != used_check_files.end();
400 std::string filepath(*it);
401 if (Utils::FileStat(filepath))
403 Utils::unlink(filepath);
406 used_check_files.clear();
407 } // eo removeCheckFiles
415 backend = Backend::getBackend();
416 installChildHandler();
417 used_check_files.clear();
423 restoreChildHandler();
438 void EmptyBackendStepCall()
440 CPPUNIT_ASSERT( backend );
442 // a backend call without active objects should return false:
443 bool result = backend->doOneStep(0);
445 CPPUNIT_ASSERT_EQUAL( false, result );
446 } // eo EmptyBackendStepCall
450 void NonEmptyBackendStepCall()
452 CPPUNIT_ASSERT(backend);
457 // with an active object, a step should return true:
458 bool result = backend->doOneStep(0);
459 CPPUNIT_ASSERT_EQUAL( true, result );
460 // the timer should not be executed:
461 CPPUNIT_ASSERT_EQUAL( 0u, timer.m_counter );
463 // now it should return false:
464 bool result = backend->doOneStep(0);
465 CPPUNIT_ASSERT_EQUAL( false, result );
466 } // eo NonEmptyBackendStepCall
471 * check for timer to execute immediatly.
473 void SingleTimerShot()
475 CPPUNIT_ASSERT(backend);
478 timer.setDelta(0); // shot now!
480 bool result = backend->doOneStep(10);
482 CPPUNIT_ASSERT_EQUAL( true, result );
483 // the timer should be executed once:
484 CPPUNIT_ASSERT_EQUAL( 1u, timer.m_counter );
486 result = backend->doOneStep(0);
488 CPPUNIT_ASSERT_EQUAL( false, result );
489 // the timer should not be executed again:
490 CPPUNIT_ASSERT_EQUAL( 1u, timer.m_counter );
492 } // eo SingleTimerShot()
497 * tests a simple timer class to be executed with a timeout.
499 void SimpleTimerShot()
502 CPPUNIT_ASSERT(backend);
506 timer1.addAction( boost::bind(&Counter::advance,&counter1) );
507 CPPUNIT_ASSERT_EQUAL(false, timer1.active());
509 timer1.startTimerMS( 100 );
510 CPPUNIT_ASSERT_EQUAL(true, timer1.active());
512 res=backend->doOneStep( 1000 );
513 CPPUNIT_ASSERT_EQUAL( true, res );
515 CPPUNIT_ASSERT_EQUAL( 1, counter1.value );
516 } // eo SimpleTimerShot
521 * tests 3 timers; after the first was active, disable another and check if the remaining one fires.
523 void SimpleTimerShot2()
526 CPPUNIT_ASSERT(backend);
528 SimpleTimer timer1, timer2, timer3;
529 Counter counter1, counter2, counter3;
530 timer1.addAction( boost::bind(&Counter::advance,&counter1) );
531 timer2.addAction( boost::bind(&Counter::advance,&counter2) );
532 timer3.addAction( boost::bind(&Counter::advance,&counter3) );
533 CPPUNIT_ASSERT_EQUAL(false, timer1.active());
534 CPPUNIT_ASSERT_EQUAL(false, timer2.active());
535 CPPUNIT_ASSERT_EQUAL(false, timer3.active());
537 timer1.startTimerMS( 100 );
538 timer2.startTimerMS( 500 );
539 timer3.startTimerMS( 400 );
540 CPPUNIT_ASSERT_EQUAL(true, timer1.active());
541 CPPUNIT_ASSERT_EQUAL(true, timer2.active());
542 CPPUNIT_ASSERT_EQUAL(true, timer3.active());
544 res=backend->doOneStep( 1000 );
545 CPPUNIT_ASSERT_EQUAL( true, res );
547 CPPUNIT_ASSERT_EQUAL(false, timer1.active());
548 CPPUNIT_ASSERT_EQUAL(true, timer2.active());
549 CPPUNIT_ASSERT_EQUAL(true, timer3.active());
551 CPPUNIT_ASSERT_EQUAL( 1, counter1.value );
552 CPPUNIT_ASSERT_EQUAL( 0, counter2.value );
553 CPPUNIT_ASSERT_EQUAL( 0, counter3.value );
555 // now stop the next timer:
557 CPPUNIT_ASSERT_EQUAL(false, timer3.active());
559 res=backend->doOneStep( 1000 );
560 CPPUNIT_ASSERT_EQUAL( true, res );
562 CPPUNIT_ASSERT_EQUAL( 1, counter1.value );
563 CPPUNIT_ASSERT_EQUAL( 1, counter2.value );
564 CPPUNIT_ASSERT_EQUAL( 0, counter3.value );
565 } // eo SimpleTimerShot2
578 CPPUNIT_ASSERT_EQUAL(false, io.wantRead() );
579 CPPUNIT_ASSERT_EQUAL(false, io.wantWrite() );
580 } // eo EmptyWantTest
584 * a simple pipe (and io) test.
586 * This test basically tests the io framework.
587 * It opens two connected pipes and sends a test string in each direction.
588 * It tests the following functionalities of the base classes:
589 * - set write marks in backend step (enabling direct send of data)
591 * - construct and interpret poll() data structures
593 * - signal chains for received data
598 void SimplePipeTest()
600 static const std::string test_string("a test string");
601 static const std::string test_string2("only another short test string");
603 CPPUNIT_ASSERT(backend);
605 TestPipe pipe1, pipe2;
607 bool res= pipe1.makePipe(pipe2);
609 CPPUNIT_ASSERT_EQUAL(true, res);
610 CPPUNIT_ASSERT_EQUAL(true, pipe1.opened());
611 CPPUNIT_ASSERT_EQUAL(true, pipe2.opened());
613 res= backend->doOneStep(0);
614 CPPUNIT_ASSERT_EQUAL(true, res);
616 pipe1.sendString(test_string);
618 res= backend->doOneStep(0);
619 CPPUNIT_ASSERT_EQUAL(true, res);
621 CPPUNIT_ASSERT_EQUAL( test_string, pipe2.m_received_string );
623 pipe2.sendString(test_string2);
625 res= backend->doOneStep(0);
626 CPPUNIT_ASSERT_EQUAL(true, res);
628 CPPUNIT_ASSERT_EQUAL( test_string2, pipe1.m_received_string );
631 CPPUNIT_ASSERT_EQUAL(false, pipe1.opened());
633 res= backend->doOneStep(0);
634 CPPUNIT_ASSERT_EQUAL(true, res);
636 CPPUNIT_ASSERT_EQUAL(true, pipe2.eof());
637 } // eo SimplePipeTest
642 * sends a larger data chunk through a pipe.
643 * This tests if sending and receiving data in (smaller internal) chunks works.
645 void SimplePipePump()
647 CPPUNIT_ASSERT(backend);
649 TestPipe pipe1, pipe2;
651 bool res= pipe1.makePipe(pipe2);
653 CPPUNIT_ASSERT_EQUAL(true, res);
654 CPPUNIT_ASSERT_EQUAL(true, pipe1.opened());
655 CPPUNIT_ASSERT_EQUAL(true, pipe2.opened());
657 res= backend->doOneStep(0);
658 CPPUNIT_ASSERT_EQUAL(true, res);
660 std::string test_string= makeRandomAsciiString(256*1024);
662 pipe1.sendString(test_string);
664 res= backend->doOneStep(0);
665 CPPUNIT_ASSERT_EQUAL(true, res);
667 // do some backend cycles to empty the pipe:
668 for (int i=64; i-->0 && res && !pipe1.empty(); )
670 res= backend->doOneStep(100);
674 CPPUNIT_ASSERT_EQUAL(false, pipe1.opened());
676 // now read the remaining data until we recognize EOF:
677 for (int i=64; i-->0 && res && !pipe2.eof();)
679 res= backend->doOneStep(100);
682 CPPUNIT_ASSERT_EQUAL( test_string.size(), pipe2.m_received_string.size() );
683 CPPUNIT_ASSERT_EQUAL( test_string, pipe2.m_received_string );
685 CPPUNIT_ASSERT_EQUAL(true, pipe2.eof());
686 } // eo SimplePipePump
691 * fork a subprocess (/bin/true) and test exit code.
693 void SimpleProcessTestBinTrue()
696 CPPUNIT_ASSERT(backend);
698 TestProcess proc("/bin/true");
700 res= proc.startProcess();
701 CPPUNIT_ASSERT_EQUAL(true, res);
703 res= backend->doOneStep(200);
704 CPPUNIT_ASSERT_EQUAL(true, res);
706 for(int i=20; i-->0 && proc.processState() != ProcessState::stopped;)
708 backend->doOneStep(15);
711 CPPUNIT_ASSERT_EQUAL( ProcessState(ProcessState::stopped), proc.processState() );
712 CPPUNIT_ASSERT_EQUAL( true, proc.eof() );
713 CPPUNIT_ASSERT_EQUAL( 0, proc.exitCode() );
714 } // eo SimpleProcessTestBinTrue
718 * fork a subprocess (/bin/false) and test exit code.
720 void SimpleProcessTestBinFalse()
723 CPPUNIT_ASSERT(backend);
725 TestProcess proc("/bin/false");
727 res= proc.startProcess();
728 CPPUNIT_ASSERT_EQUAL(true, res);
730 res= backend->doOneStep(200);
731 CPPUNIT_ASSERT_EQUAL(true, res);
732 for(int i=20; i-->0 && proc.processState() != ProcessState::stopped;)
734 backend->doOneStep(15);
737 CPPUNIT_ASSERT_EQUAL( ProcessState(ProcessState::stopped), proc.processState() );
738 CPPUNIT_ASSERT_EQUAL( true, proc.eof() );
739 CPPUNIT_ASSERT_EQUAL( 1, proc.exitCode() );
740 DOUT("leave SimpleProcessTestBinFalse");
741 } // eo SimpleProcessTestBinFalse
745 * fork an echo subprocess and read back the output.
747 void SimpleProcessTestEcho()
749 DOUT("enter SimpleProcessTestEcho");
751 CPPUNIT_ASSERT(backend);
755 TransientPushBackFiller<std::string, std::vector >()("Eine")("Zeichenkette")
758 res= proc.startProcess();
759 CPPUNIT_ASSERT_EQUAL(true, res);
761 res= backend->doOneStep(200);
762 CPPUNIT_ASSERT_EQUAL(true, res);
763 for(int i=20; i-->0 && (proc.processState()!= ProcessState::stopped || !proc.eof());)
765 backend->doOneStep(10);
768 CPPUNIT_ASSERT_EQUAL( ProcessState(ProcessState::stopped), proc.processState() );
769 CPPUNIT_ASSERT_EQUAL( true, proc.eof() );
770 CPPUNIT_ASSERT_EQUAL( 0, proc.exitCode() );
771 CPPUNIT_ASSERT_EQUAL( std::string("Eine Zeichenkette\n"), proc.m_received_string);
772 } // eo SimpleProcessTestEcho
777 * fork a bash subprocess, echo something on stderr and read back the output.
779 void SimpleProcessTestStderr()
782 CPPUNIT_ASSERT(backend);
788 TransientPushBackFiller<std::string, std::vector >()
790 ("echo Eine Zeichenkette >&2")
793 // start with a seperate io object for stderr.
794 DOUT("## start process");
795 res= proc.startProcess( &my_stderr );
796 CPPUNIT_ASSERT_EQUAL(true, res);
797 CPPUNIT_ASSERT_EQUAL(true, my_stderr.opened());
799 DOUT("## do a backend step");
800 res= backend->doOneStep(200);
801 CPPUNIT_ASSERT_EQUAL(true, res);
802 // wait until process stopped and both io's signal EOF (or until the loop ends ;-) )
803 DOUT("## enter loop");
804 for(int i=17; i-->0 && (proc.processState()!= ProcessState::stopped || !proc.eof() || !my_stderr.eof());)
806 DOUT("## round i=" << i);
807 backend->doOneStep(10);
809 DOUT("## loop left");
811 CPPUNIT_ASSERT_EQUAL( ProcessState(ProcessState::stopped), proc.processState() );
812 CPPUNIT_ASSERT_EQUAL( true, proc.eof() );
813 CPPUNIT_ASSERT_EQUAL( true, my_stderr.eof() );
814 CPPUNIT_ASSERT_EQUAL( 0, proc.exitCode() );
815 CPPUNIT_ASSERT_EQUAL( std::string("Eine Zeichenkette\n"), my_stderr.m_received_string);
816 DOUT("leave Test SimpleProcessTestStderr");
817 } // eo SimpleProcessTestStderr
822 * checks termination of process by signal and if the signal is returned.
824 void SignaledProcessTermination()
827 CPPUNIT_ASSERT(backend);
829 TestProcess proc("/bin/sleep","2");
830 res= proc.startProcess();
831 CPPUNIT_ASSERT_EQUAL(true, res);
833 res= backend->doOneStep(10);
834 CPPUNIT_ASSERT_EQUAL(true, res);
835 CPPUNIT_ASSERT_EQUAL( ProcessState(ProcessState::running), proc.processState() );
837 res= backend->doOneStep(50);
839 // now send the process an USR1 (which terminates the process)
840 res=proc.kill( Signal::USR1 );
841 CPPUNIT_ASSERT_EQUAL(true, res);
843 // give the backend a chance to process the termination event:
844 for(int i=30; i-->0 && proc.processState()!=ProcessState::stopped;) backend->doOneStep(10);
846 CPPUNIT_ASSERT_EQUAL( ProcessState(ProcessState::stopped), proc.processState() );
847 CPPUNIT_ASSERT_EQUAL( true, proc.eof() );
848 CPPUNIT_ASSERT_EQUAL( Signal::USR1 , proc.exitCode()>>8 );
849 } // eo SignaledProcessTermination
857 callOut( boost::bind(&Counter::advance, &count), 1 );
858 backend->doOneStep( 10 );
860 CPPUNIT_ASSERT_EQUAL( 0, count.value );
861 backend->doOneStep( 1100 );
863 CPPUNIT_ASSERT_EQUAL( 1, count.value );
872 callOut( boost::bind(&Counter::advance, &count), 0.5 );
873 backend->doOneStep( 10 );
875 CPPUNIT_ASSERT_EQUAL( 0, count.value );
876 backend->doOneStep( 800 );
878 CPPUNIT_ASSERT_EQUAL( 1, count.value );
883 void RemoveCallOut1()
887 CallOutId id= callOut( boost::bind(&Counter::advance, &count), 1 );
888 backend->doOneStep( 10 );
890 CPPUNIT_ASSERT_EQUAL( 0, count.value );
891 bool res1 = removeCallOut(id);
892 bool res2 = removeCallOut(id);
894 CPPUNIT_ASSERT_EQUAL( true, res1 );
895 CPPUNIT_ASSERT_EQUAL( false, res2 );
897 backend->doOneStep( 1100 );
899 CPPUNIT_ASSERT_EQUAL( 0, count.value );
900 } // eo RemoveCallOut1()
904 void FrozenCall_Thaw()
908 CallOutId id= frozenCall( boost::bind(&Counter::advance, &count), 1 );
909 backend->doOneStep( 10 );
911 CPPUNIT_ASSERT_EQUAL( 0, count.value );
914 backend->doOneStep( 1100 );
916 CPPUNIT_ASSERT_EQUAL( 1, count.value );
917 } // eo FrozenCall_Thaw()
921 void FrozenCall_Decay()
925 CallOutId id= frozenCall( boost::bind(&Counter::advance, &count), 1 );
926 backend->doOneStep( 10 );
928 CPPUNIT_ASSERT_EQUAL( 0, count.value );
929 CPPUNIT_ASSERT_EQUAL( true, id.active() );
930 backend->doOneStep( 1100 );
932 CPPUNIT_ASSERT_EQUAL( 0, count.value );
933 CPPUNIT_ASSERT_EQUAL( false, id.active() );
934 } // eo FrozenCall_Decay()
938 void UnixSockets_ClientServer()
940 std::string path= getCheckFilepath("UDS_CS");
942 UnixIOSocketHolder server_holder;
943 UnixServerSocket< TestUnixIOSocket > server_port;
944 UnixIOSocketPtr server;
945 TestUnixIOSocket client0;
946 TestUnixIOSocket client1;
948 bool res1 = server_port.open(path, 0600);
949 CPPUNIT_ASSERT_EQUAL( true, res1 );
952 AsyncIo::Utils::FileStat stat(path,false);
953 CPPUNIT_ASSERT( stat.is_socket() );
954 CPPUNIT_ASSERT_EQUAL( 0600u, (stat.mode() & 0777));
957 server_port.setNewConnectionCallback(
958 boost::bind( &UnixIOSocketHolder::store, &server_holder, _1)
961 // open a first client
962 bool res2= client0.open(path);
963 CPPUNIT_ASSERT_EQUAL( true, res2 );
965 CPPUNIT_ASSERT_EQUAL(0u, server_holder.size() );
967 CPPUNIT_ASSERT_EQUAL(1u, server_holder.size() );
968 CPPUNIT_ASSERT( server_holder.get(0).get() );
970 client0.sendData("a simple test string.");
973 CPPUNIT_ASSERT_EQUAL(
974 std::string("a simple test string."),
975 server_holder.get(0)->m_received_string
977 server_holder.get(0)->sendData("reply 1");
979 CPPUNIT_ASSERT_EQUAL( std::string("reply 1"), client0.m_received_string );
981 // open a second client
982 res2= client1.open(path);
983 CPPUNIT_ASSERT_EQUAL( true, res2 );
985 CPPUNIT_ASSERT_EQUAL(2u, server_holder.size() );
986 CPPUNIT_ASSERT( server_holder.get(1).get() );
988 server_holder.get(1)->sendData("::reply 2");
990 CPPUNIT_ASSERT_EQUAL( std::string("::reply 2"), client1.m_received_string );
992 client1.sendData("another simple test string. 124");
995 CPPUNIT_ASSERT_EQUAL(
996 std::string("another simple test string. 124"),
997 server_holder.get(1)->m_received_string
1000 // close first client
1002 CPPUNIT_ASSERT_EQUAL( false, server_holder.get(0)->eof() );
1004 CPPUNIT_ASSERT_EQUAL( true, server_holder.get(0)->eof() );
1005 server_holder.get(0)->close();
1007 // close second connection from server side
1008 CPPUNIT_ASSERT_EQUAL( false, client1.eof() );
1009 server_holder.get(1)->close();
1011 CPPUNIT_ASSERT_EQUAL( true, client1.eof() );
1013 } // eo UnixSockets_ClientServer()
1018 using namespace std;
1019 cout << endl << "Random strings:" << endl;
1020 for (int i=10; i-->0;)
1022 cout << " " << makeRandomAsciiString(70)<< endl;
1027 }; // eo class TestSimpleioBasics
1030 CPPUNIT_TEST_SUITE_REGISTRATION(TestSimpleioBasics);