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-2010 by Intra2net AG
32 #include <async_io.hpp>
33 #include <async_pipe.hpp>
34 #include <async_process.hpp>
35 #include <async_timer.hpp>
36 #include <async_callout.hpp>
37 #include <async_socket.hpp>
38 #include <asyncio_system_tools.hpp>
39 #include <asyncio_containerfunc.hpp>
41 #include <boost/signal.hpp>
42 #include <boost/bind.hpp>
43 #include <boost/random.hpp>
45 #define BOOST_TEST_MAIN
46 #define BOOST_TEST_DYN_LINK
47 #include <boost/test/unit_test.hpp>
50 #define DOUT(msg) std::cout << msg << std::endl
52 #define DOUT(msg) do {} while (0)
57 using namespace AsyncIo;
67 Counter() : value(0) { DOUT("Counter construct");}
69 void reset() { value=0;}
73 DOUT(" advance called");
82 }; // eo struct Counter
85 class TestTimer : public TimerBase
95 void setDelta(long msec)
97 setDeltaWhenTime(0,msec);
99 } // eo setDelta(long)
106 virtual void execute()
111 }; // eo class TestTimer
117 std::vector<std::string> m_received_vector;
118 std::string m_received_string;
120 unsigned long m_count_lines;
121 unsigned long m_data_size;
124 void resetReceivedData()
126 m_received_vector.clear();
127 m_received_string.clear();
133 void receiveData(const std::string& data)
135 m_received_vector.push_back(data);
136 m_received_string.append(data);
138 m_data_size += data.size();
139 } // eo receiveData(const std::string&)
141 }; // eo struct ReceivedData
145 class TestPipe : public SimplePipe, public ReceivedData
151 signal_received_string.connect( boost::bind(&TestPipe::receiveData, this, _1) );
158 }; // eo class TestPipe
161 class TestIO : public SimpleIO2, public ReceivedData
166 signal_received_string.connect( boost::bind(&TestIO::receiveData, this, _1) );
172 class TestProcess : public ProcessImplementation, public ReceivedData
176 const std::string& path,
177 const std::vector<std::string>& args= std::vector<std::string>() )
178 : ProcessImplementation(path,args)
180 m_signal_read.connect( boost::bind(&TestProcess::slotReceivedData, this) );
181 } // eo Testprocess(const std::string&, const std::vector<std::string>&)
184 const std::string& path,
185 const std::string& arg1 )
186 : ProcessImplementation(
188 TransientPushBackFiller< std::string,std::vector >()(arg1)
191 m_signal_read.connect( boost::bind(&TestProcess::slotReceivedData, this) );
192 } // eo Testprocess(const std::string&, const std::vector<std::string>&)
195 const std::string& path,
196 const std::string& arg1, const std::string& arg2 )
197 : ProcessImplementation(
199 TransientPushBackFiller< std::string, std::vector >()(arg1)(arg2)
202 m_signal_read.connect( boost::bind(&TestProcess::slotReceivedData, this) );
203 } // eo Testprocess(const std::string&, const std::vector<std::string>&)
207 void slotReceivedData()
209 receiveData(m_input_buffer);
210 m_input_buffer.clear();
211 } // eo slotReceivedData()
213 }; // eo class TestProcess
217 class TestUnixIOSocket
218 : public UnixIOSocket
219 , public ReceivedData
226 m_signal_read.connect( boost::bind(&TestUnixIOSocket::slotReceivedData, this) );
227 } // eo TestUnixIOSocket()
231 int fd, const std::string& path
233 : UnixIOSocket(fd, path)
235 m_signal_read.connect( boost::bind(&TestUnixIOSocket::slotReceivedData, this) );
236 } // eo TestUnixIOSocket()
239 void sendData(const std::string& data)
242 } // eo sendData(const std::string&)
246 void slotReceivedData()
248 receiveData(m_input_buffer);
249 m_input_buffer.clear();
250 } // eo slotReceivedData()
252 }; // eo class TestUnixIOSocket
254 typedef boost::shared_ptr< TestUnixIOSocket > TestUnixIOSocketPtr;
257 class UnixIOSocketHolder
258 : public std::vector< UnixIOSocketPtr >
262 void operator()(UnixIOSocketPtr ptr)
267 void storeBase (IOImplementationPtr ptr)
269 push_back(boost::dynamic_pointer_cast< UnixIOSocket >(ptr) );
272 void store (UnixIOSocketPtr ptr)
277 TestUnixIOSocketPtr get(int idx)
279 return boost::dynamic_pointer_cast<
283 }; // eo class UnixIOSocketHolder
286 /// global random generator (from boost lib).
287 boost::mt19937 g_random_gen;
291 * generates a string with random characters from a given ASCII subset.
292 * @param len the desired length of the output string
293 * @return a random string of length @a len
295 std::string makeRandomAsciiString(std::string::size_type len)
297 static std::string chars("ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz=+-*/%(){}<>.,:;\\");
300 boost::uniform_int<> discreter(0, chars.size()-1);
301 boost::variate_generator<boost::mt19937&, boost::uniform_int<> > idxgen(g_random_gen, discreter);
303 for(; len-->0;) s+= chars.at( idxgen() );
306 } // eo makeRandomAsciiString
309 } // eo namespace <anonymous>
312 class SimpleioBasicsFixture
316 std::set<std::string> used_check_files;
318 template<class Callable>
319 bool backendLoopUntil( Callable condition, int maxLoops=100 )
321 for (int i=std::max(maxLoops,1); i-->0 && ! condition();)
323 backend->doOneStep(10);
326 } // eo backendLoopUntil
329 bool backendStep(int msTimeout= 10, int count=1)
332 for(;count-->0 && res;)
334 res= backend->doOneStep(msTimeout);
340 std::string getCheckFilepath(std::string tag)
343 result= "__unittest__" + tag + ".dat";
344 used_check_files.insert(result);
346 } // eo get_check_file_path
349 void removeCheckFiles()
351 for(std::set<std::string>::iterator it= used_check_files.begin();
352 it != used_check_files.end();
355 std::string filepath(*it);
356 if (Utils::FileStat(filepath))
358 Utils::unlink(filepath);
361 used_check_files.clear();
362 } // eo removeCheckFiles
365 SimpleioBasicsFixture()
367 backend = Backend::getBackend();
368 installChildHandler();
369 used_check_files.clear();
372 ~SimpleioBasicsFixture()
374 restoreChildHandler();
379 BOOST_FIXTURE_TEST_SUITE(TestSimpleioBasics, SimpleioBasicsFixture)
381 BOOST_AUTO_TEST_CASE(EmptyBackendStepCall)
383 BOOST_REQUIRE( backend );
385 // a backend call without active objects should return false:
386 bool result = backend->doOneStep(0);
388 BOOST_CHECK_EQUAL( false, result );
389 } // eo EmptyBackendStepCall
393 BOOST_AUTO_TEST_CASE(NonEmptyBackendStepCall)
395 BOOST_REQUIRE(backend);
400 // with an active object, a step should return true:
401 bool result = backend->doOneStep(0);
402 BOOST_CHECK_EQUAL( true, result );
403 // the timer should not be executed:
404 BOOST_CHECK_EQUAL( 0u, timer.m_counter );
406 // now it should return false:
407 bool result = backend->doOneStep(0);
408 BOOST_CHECK_EQUAL( false, result );
409 } // eo NonEmptyBackendStepCall
414 * check for timer to execute immediatly.
416 BOOST_AUTO_TEST_CASE(SingleTimerShot)
418 BOOST_REQUIRE(backend);
421 timer.setDelta(0); // shot now!
423 bool result = backend->doOneStep(10);
425 BOOST_CHECK_EQUAL( true, result );
426 // the timer should be executed once:
427 BOOST_CHECK_EQUAL( 1u, timer.m_counter );
429 result = backend->doOneStep(0);
431 BOOST_CHECK_EQUAL( false, result );
432 // the timer should not be executed again:
433 BOOST_CHECK_EQUAL( 1u, timer.m_counter );
435 } // eo SingleTimerShot()
440 * tests a simple timer class to be executed with a timeout.
442 BOOST_AUTO_TEST_CASE(SimpleTimerShot)
445 BOOST_REQUIRE(backend);
449 timer1.addAction( boost::bind(&Counter::advance,&counter1) );
450 BOOST_CHECK_EQUAL(false, timer1.active());
452 timer1.startTimerMS( 100 );
453 BOOST_CHECK_EQUAL(true, timer1.active());
455 res=backend->doOneStep( 1000 );
456 BOOST_CHECK_EQUAL( true, res );
458 BOOST_CHECK_EQUAL( 1, counter1.value );
459 } // eo SimpleTimerShot
464 * tests 3 timers; after the first was active, disable another and check if the remaining one fires.
466 BOOST_AUTO_TEST_CASE(SimpleTimerShot2)
469 BOOST_REQUIRE(backend);
471 SimpleTimer timer1, timer2, timer3;
472 Counter counter1, counter2, counter3;
473 timer1.addAction( boost::bind(&Counter::advance,&counter1) );
474 timer2.addAction( boost::bind(&Counter::advance,&counter2) );
475 timer3.addAction( boost::bind(&Counter::advance,&counter3) );
476 BOOST_CHECK_EQUAL(false, timer1.active());
477 BOOST_CHECK_EQUAL(false, timer2.active());
478 BOOST_CHECK_EQUAL(false, timer3.active());
480 timer1.startTimerMS( 100 );
481 timer2.startTimerMS( 500 );
482 timer3.startTimerMS( 400 );
483 BOOST_CHECK_EQUAL(true, timer1.active());
484 BOOST_CHECK_EQUAL(true, timer2.active());
485 BOOST_CHECK_EQUAL(true, timer3.active());
487 res=backend->doOneStep( 1000 );
488 BOOST_CHECK_EQUAL( true, res );
490 BOOST_CHECK_EQUAL(false, timer1.active());
491 BOOST_CHECK_EQUAL(true, timer2.active());
492 BOOST_CHECK_EQUAL(true, timer3.active());
494 BOOST_CHECK_EQUAL( 1, counter1.value );
495 BOOST_CHECK_EQUAL( 0, counter2.value );
496 BOOST_CHECK_EQUAL( 0, counter3.value );
498 // now stop the next timer:
500 BOOST_CHECK_EQUAL(false, timer3.active());
502 res=backend->doOneStep( 1000 );
503 BOOST_CHECK_EQUAL( true, res );
505 BOOST_CHECK_EQUAL( 1, counter1.value );
506 BOOST_CHECK_EQUAL( 1, counter2.value );
507 BOOST_CHECK_EQUAL( 0, counter3.value );
508 } // eo SimpleTimerShot2
517 BOOST_AUTO_TEST_CASE(EmptyWantTest)
521 BOOST_CHECK_EQUAL(false, io.wantRead() );
522 BOOST_CHECK_EQUAL(false, io.wantWrite() );
523 } // eo EmptyWantTest
527 * a simple pipe (and io) test.
529 * This test basically tests the io framework.
530 * It opens two connected pipes and sends a test string in each direction.
531 * It tests the following functionalities of the base classes:
532 * - set write marks in backend step (enabling direct send of data)
534 * - construct and interpret poll() data structures
536 * - signal chains for received data
541 BOOST_AUTO_TEST_CASE(SimplePipeTest)
543 static const std::string test_string("a test string");
544 static const std::string test_string2("only another short test string");
546 BOOST_REQUIRE(backend);
548 TestPipe pipe1, pipe2;
550 bool res= pipe1.makePipe(pipe2);
552 BOOST_CHECK_EQUAL(true, res);
553 BOOST_CHECK_EQUAL(true, pipe1.opened());
554 BOOST_CHECK_EQUAL(true, pipe2.opened());
556 res= backend->doOneStep(0);
557 BOOST_CHECK_EQUAL(true, res);
559 pipe1.sendString(test_string);
561 res= backend->doOneStep(0);
562 BOOST_CHECK_EQUAL(true, res);
564 BOOST_CHECK_EQUAL( test_string, pipe2.m_received_string );
566 pipe2.sendString(test_string2);
568 res= backend->doOneStep(0);
569 BOOST_CHECK_EQUAL(true, res);
571 BOOST_CHECK_EQUAL( test_string2, pipe1.m_received_string );
574 BOOST_CHECK_EQUAL(false, pipe1.opened());
576 res= backend->doOneStep(0);
577 BOOST_CHECK_EQUAL(true, res);
579 BOOST_CHECK_EQUAL(true, pipe2.eof());
580 } // eo SimplePipeTest
585 * sends a larger data chunk through a pipe.
586 * This tests if sending and receiving data in (smaller internal) chunks works.
588 BOOST_AUTO_TEST_CASE(SimplePipePump)
590 BOOST_REQUIRE(backend);
592 TestPipe pipe1, pipe2;
594 bool res= pipe1.makePipe(pipe2);
596 BOOST_CHECK_EQUAL(true, res);
597 BOOST_CHECK_EQUAL(true, pipe1.opened());
598 BOOST_CHECK_EQUAL(true, pipe2.opened());
600 res= backend->doOneStep(0);
601 BOOST_CHECK_EQUAL(true, res);
603 std::string test_string= makeRandomAsciiString(256*1024);
605 pipe1.sendString(test_string);
607 res= backend->doOneStep(0);
608 BOOST_CHECK_EQUAL(true, res);
610 // do some backend cycles to empty the pipe:
611 for (int i=64; i-->0 && res && !pipe1.empty(); )
613 res= backend->doOneStep(100);
617 BOOST_CHECK_EQUAL(false, pipe1.opened());
619 // now read the remaining data until we recognize EOF:
620 for (int i=64; i-->0 && res && !pipe2.eof();)
622 res= backend->doOneStep(100);
625 BOOST_CHECK_EQUAL( test_string.size(), pipe2.m_received_string.size() );
626 BOOST_CHECK_EQUAL( test_string, pipe2.m_received_string );
628 BOOST_CHECK_EQUAL(true, pipe2.eof());
629 } // eo SimplePipePump
634 * fork a subprocess (/bin/true) and test exit code.
636 BOOST_AUTO_TEST_CASE(SimpleProcessTestBinTrue)
639 BOOST_REQUIRE(backend);
641 TestProcess proc("/bin/true");
643 res= proc.startProcess();
644 BOOST_CHECK_EQUAL(true, res);
646 res= backend->doOneStep(200);
647 BOOST_CHECK_EQUAL(true, res);
649 for(int i=20; i-->0 && proc.processState() != ProcessState::stopped;)
651 backend->doOneStep(15);
654 BOOST_CHECK_EQUAL( ProcessState(ProcessState::stopped), proc.processState() );
655 BOOST_CHECK_EQUAL( true, proc.eof() );
656 BOOST_CHECK_EQUAL( 0, proc.exitCode() );
657 } // eo SimpleProcessTestBinTrue
661 * fork a subprocess (/bin/false) and test exit code.
663 BOOST_AUTO_TEST_CASE(SimpleProcessTestBinFalse)
666 BOOST_REQUIRE(backend);
668 TestProcess proc("/bin/false");
670 res= proc.startProcess();
671 BOOST_CHECK_EQUAL(true, res);
673 res= backend->doOneStep(200);
674 BOOST_CHECK_EQUAL(true, res);
675 for(int i=20; i-->0 && proc.processState() != ProcessState::stopped;)
677 backend->doOneStep(15);
680 BOOST_CHECK_EQUAL( ProcessState(ProcessState::stopped), proc.processState() );
681 BOOST_CHECK_EQUAL( true, proc.eof() );
682 BOOST_CHECK_EQUAL( 1, proc.exitCode() );
683 DOUT("leave SimpleProcessTestBinFalse");
684 } // eo SimpleProcessTestBinFalse
688 * fork an echo subprocess and read back the output.
690 BOOST_AUTO_TEST_CASE(SimpleProcessTestEcho)
692 DOUT("enter SimpleProcessTestEcho");
694 BOOST_REQUIRE(backend);
698 TransientPushBackFiller<std::string, std::vector >()("Eine")("Zeichenkette")
701 res= proc.startProcess();
702 BOOST_CHECK_EQUAL(true, res);
704 res= backend->doOneStep(200);
705 BOOST_CHECK_EQUAL(true, res);
706 for(int i=20; i-->0 && (proc.processState()!= ProcessState::stopped || !proc.eof());)
708 backend->doOneStep(10);
711 BOOST_CHECK_EQUAL( ProcessState(ProcessState::stopped), proc.processState() );
712 BOOST_CHECK_EQUAL( true, proc.eof() );
713 BOOST_CHECK_EQUAL( 0, proc.exitCode() );
714 BOOST_CHECK_EQUAL( std::string("Eine Zeichenkette\n"), proc.m_received_string);
715 } // eo SimpleProcessTestEcho
720 * fork a bash subprocess, echo something on stderr and read back the output.
722 BOOST_AUTO_TEST_CASE(SimpleProcessTestStderr)
725 BOOST_REQUIRE(backend);
731 TransientPushBackFiller<std::string, std::vector >()
733 ("echo Eine Zeichenkette >&2")
736 // start with a seperate io object for stderr.
737 DOUT("## start process");
738 res= proc.startProcess( &my_stderr );
739 BOOST_CHECK_EQUAL(true, res);
740 BOOST_CHECK_EQUAL(true, my_stderr.opened());
742 DOUT("## do a backend step");
743 res= backend->doOneStep(200);
744 BOOST_CHECK_EQUAL(true, res);
745 // wait until process stopped and both io's signal EOF (or until the loop ends ;-) )
746 DOUT("## enter loop");
747 for(int i=17; i-->0 && (proc.processState()!= ProcessState::stopped || !proc.eof() || !my_stderr.eof());)
749 DOUT("## round i=" << i);
750 backend->doOneStep(10);
752 DOUT("## loop left");
754 BOOST_CHECK_EQUAL( ProcessState(ProcessState::stopped), proc.processState() );
755 BOOST_CHECK_EQUAL( true, proc.eof() );
756 BOOST_CHECK_EQUAL( true, my_stderr.eof() );
757 BOOST_CHECK_EQUAL( 0, proc.exitCode() );
758 BOOST_CHECK_EQUAL( std::string("Eine Zeichenkette\n"), my_stderr.m_received_string);
759 DOUT("leave Test SimpleProcessTestStderr");
760 } // eo SimpleProcessTestStderr
765 * checks termination of process by signal and if the signal is returned.
767 BOOST_AUTO_TEST_CASE(SignaledProcessTermination)
770 BOOST_REQUIRE(backend);
772 TestProcess proc("/bin/sleep","2");
773 res= proc.startProcess();
774 BOOST_CHECK_EQUAL(true, res);
776 res= backend->doOneStep(10);
777 BOOST_CHECK_EQUAL(true, res);
778 BOOST_CHECK_EQUAL( ProcessState(ProcessState::running), proc.processState() );
780 res= backend->doOneStep(50);
782 // now send the process an USR1 (which terminates the process)
783 res=proc.kill( Signal::USR1 );
784 BOOST_CHECK_EQUAL(true, res);
786 // give the backend a chance to process the termination event:
787 for(int i=30; i-->0 && proc.processState()!=ProcessState::stopped;) backend->doOneStep(10);
789 BOOST_CHECK_EQUAL( ProcessState(ProcessState::stopped), proc.processState() );
790 BOOST_CHECK_EQUAL( true, proc.eof() );
791 BOOST_CHECK_EQUAL( Signal::USR1 , proc.exitCode()>>8 );
792 } // eo SignaledProcessTermination
796 BOOST_AUTO_TEST_CASE(CallOut1)
800 callOut( boost::bind(&Counter::advance, &count), 1 );
801 backend->doOneStep( 10 );
803 BOOST_CHECK_EQUAL( 0, count.value );
804 backend->doOneStep( 1100 );
806 BOOST_CHECK_EQUAL( 1, count.value );
811 BOOST_AUTO_TEST_CASE(CallOut2)
815 callOut( boost::bind(&Counter::advance, &count), 0.5 );
816 backend->doOneStep( 10 );
818 BOOST_CHECK_EQUAL( 0, count.value );
819 backend->doOneStep( 800 );
821 BOOST_CHECK_EQUAL( 1, count.value );
826 BOOST_AUTO_TEST_CASE(RemoveCallOut1)
830 CallOutId id= callOut( boost::bind(&Counter::advance, &count), 1 );
831 backend->doOneStep( 10 );
833 BOOST_CHECK_EQUAL( 0, count.value );
834 bool res1 = removeCallOut(id);
835 bool res2 = removeCallOut(id);
837 BOOST_CHECK_EQUAL( true, res1 );
838 BOOST_CHECK_EQUAL( false, res2 );
840 backend->doOneStep( 1100 );
842 BOOST_CHECK_EQUAL( 0, count.value );
843 } // eo RemoveCallOut1()
847 BOOST_AUTO_TEST_CASE(FrozenCall_Thaw)
851 CallOutId id= frozenCall( boost::bind(&Counter::advance, &count), 1 );
852 backend->doOneStep( 10 );
854 BOOST_CHECK_EQUAL( 0, count.value );
857 backend->doOneStep( 1100 );
859 BOOST_CHECK_EQUAL( 1, count.value );
860 } // eo FrozenCall_Thaw()
864 BOOST_AUTO_TEST_CASE(FrozenCall_Decay)
868 CallOutId id= frozenCall( boost::bind(&Counter::advance, &count), 1 );
869 backend->doOneStep( 10 );
871 BOOST_CHECK_EQUAL( 0, count.value );
872 BOOST_CHECK_EQUAL( true, id.active() );
873 backend->doOneStep( 1100 );
875 BOOST_CHECK_EQUAL( 0, count.value );
876 BOOST_CHECK_EQUAL( false, id.active() );
877 } // eo FrozenCall_Decay()
881 BOOST_AUTO_TEST_CASE(UnixSockets_ClientServer)
883 std::string path= getCheckFilepath("UDS_CS");
885 UnixIOSocketHolder server_holder;
886 UnixServerSocket< TestUnixIOSocket > server_port;
887 UnixIOSocketPtr server;
888 TestUnixIOSocket client0;
889 TestUnixIOSocket client1;
891 bool res1 = server_port.open(path, 0600);
892 BOOST_CHECK_EQUAL( true, res1 );
895 AsyncIo::Utils::FileStat stat(path,false);
896 BOOST_REQUIRE( stat.is_socket() );
897 BOOST_CHECK_EQUAL( 0600u, (stat.mode() & 0777));
900 server_port.setNewConnectionCallback(
901 boost::bind( &UnixIOSocketHolder::store, &server_holder, _1)
904 // open a first client
905 bool res2= client0.open(path);
906 BOOST_CHECK_EQUAL( true, res2 );
908 BOOST_CHECK_EQUAL(0u, server_holder.size() );
910 BOOST_CHECK_EQUAL(1u, server_holder.size() );
911 BOOST_REQUIRE( server_holder.get(0).get() );
913 client0.sendData("a simple test string.");
917 std::string("a simple test string."),
918 server_holder.get(0)->m_received_string
920 server_holder.get(0)->sendData("reply 1");
922 BOOST_CHECK_EQUAL( std::string("reply 1"), client0.m_received_string );
924 // open a second client
925 res2= client1.open(path);
926 BOOST_CHECK_EQUAL( true, res2 );
928 BOOST_CHECK_EQUAL(2u, server_holder.size() );
929 BOOST_REQUIRE( server_holder.get(1).get() );
931 server_holder.get(1)->sendData("::reply 2");
933 BOOST_CHECK_EQUAL( std::string("::reply 2"), client1.m_received_string );
935 client1.sendData("another simple test string. 124");
939 std::string("another simple test string. 124"),
940 server_holder.get(1)->m_received_string
943 // close first client
945 BOOST_CHECK_EQUAL( false, server_holder.get(0)->eof() );
947 BOOST_CHECK_EQUAL( true, server_holder.get(0)->eof() );
948 server_holder.get(0)->close();
950 // close second connection from server side
951 BOOST_CHECK_EQUAL( false, client1.eof() );
952 server_holder.get(1)->close();
954 BOOST_CHECK_EQUAL( true, client1.eof() );
956 } // eo UnixSockets_ClientServer()
960 BOOST_AUTO_TEST_CASE(Dummy)
963 cout << endl << "Random strings:" << endl;
964 for (int i=10; i-->0;)
966 cout << " " << makeRandomAsciiString(70)<< endl;
971 BOOST_AUTO_TEST_SUITE_END()