Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

unittest.d

Go to the documentation of this file.
00001 /******************************************************************************
00002 
00003         @mainpage The Mango Tree
00004 
00005         Mango is a collection of D packages with an orientation toward
00006         server-side programming. These packages may be used together 
00007         or in isolation and, in many cases, can be just as applicable 
00008         to client-side development. Mango is targeted for Win32 and 
00009         linux platforms.
00010 
00011         There are currently seven packages under the Mango Tree:
00012 
00013         @li mango.io: a high-performance buffered IO package. Primary 
00014             functionality includes memory Buffers, external Conduits 
00015             (files, sockets, etc), file-system manipulation, several 
00016             flavors of Readers and Writers (formatted data), TextFormat 
00017             (printf) and TextLayout support, class serialization, 
00018             tokenization, and a whole lot more. Socket support is via 
00019             the gracious provision of Christopher Miller's socket module. 
00020             See FilePath, FileProxy, FileConduit, FileSystem, SocketConduit, 
00021             ServerSocket, MulticastSocket, SocketListener, Token, Stdio, 
00022             Reader, Writer, IPickle and PickleRegistry.
00023 
00024         @li mango.http.client: An HTTP client for conversing with a remote
00025             HTTP server. Supports headers, query parameters, cookies, 
00026             timeout etc. Tokenizer classes in mango.io are handy for 
00027             parsing returned content. See HttpClient.
00028 
00029         @li mango.http.server: an HTTP server framework is provided for 
00030             implementing a variety of high performance servers based 
00031             on the HTTP protocol. This is not a fully-fledged v1.1 
00032             implementation. That is, it doesn't currently support 
00033             'fields' or 'keep alive'. However, it happily processes 
00034             each request without allocating memory, making it unusually 
00035             efficient. This is an example of how D array-slicing can 
00036             seriously improve runtime efficiency. An open-source HTTPS 
00037             library should be fairly easy to bolt in.
00038 
00039         @li mango.servlet: A servlet-style engine that sits upon 
00040             mango.server. Includes most of the things that Java servlet 
00041             programmers would expect, and attempts to improve in certain 
00042             key areas such as the IO system. See Servlet and ServletProvider.
00043 
00044         @li mango.cache: Some simple caching mechanisms. Includes MRU 
00045             caching via a queue, and level-two caching (to disk) via 
00046             class-serialization. Now based upon a derivative of Doug Lea's
00047             concurrent hashmap. The mango.cluster package derives from
00048             mango.cache, so it's really easy to switch between a local
00049             cache implementation and a clustered version. See ICache, 
00050             IMutableCache, PlainCache, QueuedCache and VirtualCache.
00051 
00052         @li mango.log: A clone of the wildly popular Log4J package, for 
00053             logging and tracing of runtime behaviour. See
00054             <A HREF="http://logging.apache.org/log4j/docs/documentation.html">this page</A>
00055             for an introduction to Log4J. Mango.log has a dependency upon 
00056             mango.io for file access (PropertyConfigurator, FileAppender) 
00057             and for one of the console appenders (StdioAppender). Other 
00058             than that it is completely standalone, and it would be simple 
00059             to replace/augment those appenders with alternatives. Mango.log
00060             can generate remote log messages, and has an HTML Admin Console
00061             which dynamically adjusts the log settings of an executing program.
00062             See Logger, BasicConfigurator and PropertyConfigurator.
00063 
00064         @li mango.cluster: A clustering package for servers and other
00065             network aware applications. Currently supports clustered
00066             caching and queuing, where the former is limited to a fixed 
00067             MRU number of entries per node, and the latter is limited to an
00068             upper memory waterline. While the underlying QOS (quality of 
00069             service) substrate is setup to be plugable, the QOS
00070             currently provided is stream/multicast based. Note that this
00071             package is not a substitute for a persistence layer; instead
00072             it is a tool for enabling horizontal scaling within a system 
00073             that has been designed explicitly from the outset to scale.
00074             On the other hand, it can significantly enhance the throughput 
00075             of any persistence layer by offloading a large percentage of
00076             read operations. See CacheInvalidatee, CacheInvalidator, 
00077             NetworkCombo, NetworkAlert, NetworkCache and NetworkQueue.
00078 
00079         Package dependencies are as follows (from left to right):
00080 
00081         @code
00082         mango.io           => phobos   (limited)
00083         mango.log          => mango.io (limited)
00084         mango.cache        => mango.io 
00085         mango.http.server  => mango.io
00086         mango.http.client  => mango.io, mango.server
00087         mango.cluster      => mango.io, mango.cache, mango.log
00088         mango.servlet      => mango.io, mango.http.server, mango.cache, mango.log
00089         @endcode
00090 
00091         You might take a look at the unittest.d source to get a general 
00092         feel for functionality, and browse the various pdf files 
00093         <A HREF="http://svn.dsource.org/svn/projects/mango/trunk/doc/">here</A>       
00094         along with the class-hierarchy or alphabetical-list linked at the 
00095         top of this page. There's also a set of examples         
00096         <A HREF="http://svn.dsource.org/svn/projects/mango/trunk/example/">over here</A>. 
00097         Those will probably be sufficient to get an idea where the Mango Tree 
00098         might come in handy within your projects. 
00099 
00100         Discussion forums are hosted 
00101         <A HREF="http://www.dsource.org/forums/viewforum.php?f=5">here</A>, 
00102         and the general introduction starts 
00103         <A HREF="http://www.dsource.org/forums/viewtopic.php?t=148">here</A>. 
00104 
00105 *******************************************************************************/
00106 
00107 
00108 
00109 
00110 /******************************************************************************
00111 
00112         @file unittest.d
00113 
00114         Test jig for the mango.io package.
00115 
00116 
00117         This shows a number of different ways to manipulate buffers, 
00118         readers, writers, and how to perform IO on files and sockets.
00119 
00120         The basic premise behind this IO package is as follows:
00121 
00122         1) the central concept is that of a buffer. The buffer acts
00123            as a queue (line) where items are removed from the front
00124            and new items are added to the back. Buffers are modeled 
00125            by mango.io.model.IBuffer, and a concrete implementation 
00126            is provided via mango.io.Buffer.
00127 
00128         2) buffers can be written to directly, but a Reader and/or
00129            Writer are typically used to read & write formatted data.
00130            These readers & writers are bound to a specific buffer;
00131            often the same buffer. It's also perfectly legitimate to 
00132            bind multiple writers to the same buffer; they will all
00133            behave serially as one would expect. The same applies to
00134            multiple readers on the same buffer. Readers and writers
00135            support two styles of IO: put/get, and the C++ style << 
00136            and >> operators. All such operations can be chained.
00137 
00138         3) Any class can be made compatable with the reader/writer
00139            framework by implementing the IReadable and/or IWritable 
00140            interfaces. Each of these specify just a single method.
00141 
00142         4) Buffers may also be tokenized. This is handy when one is
00143            dealing with text input, and/or the content suits a more
00144            fluid format than most typical readers & writers support.
00145            Tokens are mapped directly onto buffer content, so there
00146            is only minor overhead in using them. Tokens can be read
00147            and written by reader/writers also, using a more relaxed
00148            set of rules than those applied to integral IO.
00149 
00150         5) buffers are sometimes memory-only, in which case there
00151            is nothing left to do when a reader (or tokenizer) hits
00152            end of buffer conditions. Other buffers are themselves 
00153            bound to a Conduit. When this is the case, a reader will 
00154            eventually cause the buffer to reload via its associated 
00155            conduit. Previous buffer content will thus be lost. The
00156            same concept is applied to writers, whereby they flush 
00157            the content of a full buffer to a bound conduit before 
00158            continuing. 
00159 
00160         6) conduits provide virtualized access to external content,
00161            and represent things like files or Internet connections.
00162            They are just a different kind of stream. Conduits are
00163            modelled by mango.io.model.IConduit, and implemented via
00164            classes FileConduit and SocketConduit. Additional kinds
00165            of conduit are easy to construct: one either subclasses
00166            mango.io.Conduit, or implements mango.io.model.IConduit. 
00167            The conduit reads and writes a buffer in large segments;
00168            typically the entire buffer.
00169 
00170         7) additional file-system support is provided through two
00171            classes: FileSystem supports operations such as getting 
00172            and setting the current directory, and FileProxy exposes
00173            facilities to manipulate both files and directories.
00174 
00175         8) console IO is implemented via Stdio, using FileConduit
00176            and appropriate readers and writers. Console IO can be
00177            redirected in the traditional (shell) manner.
00178 
00179         9) the package is intended to be portable between linux and
00180            Win32 platforms. 
00181         
00182 
00183         Kris Bell, March 26th 2004
00184 
00185 *******************************************************************************/
00186 
00187 
00188         // test these modules
00189 import  mango.io.Uri,
00190         mango.io.Stdio,
00191         mango.io.Token,
00192         mango.io.Reader,
00193         mango.io.Writer,
00194         mango.io.Buffer,
00195         mango.io.Socket,
00196         mango.io.Conduit,
00197         mango.io.FilePath,
00198         mango.io.FileStyle,
00199         mango.io.FileProxy,
00200         mango.io.Tokenizer,
00201         mango.io.TextReader,
00202         mango.io.TextWriter,
00203         mango.io.FileBucket,
00204         mango.io.FileConduit,
00205         mango.io.TextLayout,
00206         mango.io.TextFormat,
00207         mango.io.ColumnWriter,
00208         mango.io.DisplayWriter,
00209         mango.io.PickleReader,
00210         mango.io.PickleWriter,
00211         mango.io.SocketConduit,
00212         mango.io.SocketListener,
00213         mango.io.ArrayAllocator,
00214         mango.io.PickleRegistry,
00215         mango.io.DatagramSocket,
00216         mango.io.MulticastSocket;
00217 
00218         // need this for logging
00219 import  mango.log.Logger,
00220         mango.log.Layout,
00221         mango.log.Manager,
00222         mango.log.DateLayout,
00223         mango.log.Configurator,
00224         mango.log.FileAppender,
00225         mango.log.StdioAppender,
00226         mango.log.ConsoleAppender,
00227         mango.log.RollingFileAppender;
00228 
00229         // need these for reading & writing classes
00230 import  mango.io.model.IReader,
00231         mango.io.model.IWriter,
00232         mango.io.model.IPickle;
00233 
00234         // add a bunch of stuff for testing the http server
00235 import  mango.http.server.HttpParams,
00236         mango.http.server.HttpCookies,
00237         mango.http.server.HttpHeaders,
00238         mango.http.server.HttpServer,
00239         mango.http.server.HttpRequest,
00240         mango.http.server.HttpResponse,       
00241         mango.http.server.HttpProvider;
00242 
00243 import  mango.http.server.model.IProvider,
00244         mango.http.server.model.IProviderBridge;
00245 
00246 import  mango.http.client.HttpClient;
00247 
00248 import  mango.servlet.Servlet,
00249         mango.servlet.ServletConfig,
00250         mango.servlet.ServletContext,
00251         mango.servlet.ServletProvider;
00252 
00253 import  mango.cache.PlainCache,
00254         mango.cache.HashMap,
00255         mango.cache.Payload,
00256         mango.cache.QueuedCache,
00257         mango.cache.VirtualCache;
00258 
00259 import  mango.cluster.Message,
00260         mango.cluster.NetworkQueue,
00261         mango.cluster.NetworkCache,
00262         mango.cluster.CacheInvalidator,
00263         mango.cluster.CacheInvalidatee;
00264       
00265 import  mango.cluster.qos.socket.Cluster,
00266         mango.cluster.qos.socket.ClusterServer,
00267         mango.cluster.qos.socket.ProtocolReader,
00268         mango.cluster.qos.socket.ProtocolWriter;
00269 
00270 /*******************************************************************************
00271 
00272         global scope variables
00273 
00274 *******************************************************************************/
00275 
00276 private Logger logger;
00277         
00278 /*******************************************************************************
00279 
00280         Simple test of in-memory buffer. Bind both a Reader and a Writer 
00281         onto the same buffer.
00282    
00283 *******************************************************************************/
00284 
00285 static void testBuffer()
00286 {
00287         // create a small heap buffer
00288         Buffer buf = new Buffer (256);
00289 
00290         // map same buffer into both reader and writer
00291         Writer w = new Writer (buf);
00292         Reader r = new Reader (buf);
00293 
00294         int i = 10;
00295         int j = 20;
00296         double d = 3.14159;
00297         char[] c = "testing";
00298        
00299         // write integral types out
00300         w << c << i << j << d;
00301 
00302         // read them back again
00303         r >> c >> i >> j >> d;
00304 
00305         assert(i==10);
00306         assert(j==20);
00307         assert(d==3.14159);
00308         assert(c=="testing");
00309 
00310         // reset
00311         buf.clear();
00312 
00313         // same thing again, but using put() syntax instead (and swap i & j)
00314         w.put(c).put(i).put(j).put(d);
00315         r.get(c).get(j).get(i).get(d);
00316 
00317         assert(i==20);
00318         assert(j==10);
00319         assert(d==3.14159);
00320         assert(c=="testing");
00321 }
00322 
00323 
00324 /*******************************************************************************
00325 
00326         Append to a buffer directly without using a Writer. This can be
00327         useful for appending a set of strings (or other array type) to
00328         a contiguous space in a similar fashion to std.outbuffer.
00329 
00330 *******************************************************************************/
00331 
00332 static void testAppend()
00333 {
00334         char[] foo = "to write some D code";
00335 
00336         // create a small heap buffer
00337         Buffer buf = new Buffer (256);
00338 
00339         // append some text directly to it
00340         buf.append("now is the time for all good men ").append(foo);
00341 
00342         // output the combined string
00343         Stdout.put (buf.toString).cr();
00344 }
00345 
00346 
00347 /*******************************************************************************
00348 
00349         write delimited text tokens to a buffer, then read them back out 
00350         to the console
00351 
00352 *******************************************************************************/
00353 
00354 static void testToken1()
00355 {
00356         // create a small buffer on top of a static array
00357         static ubyte[128] storage;
00358         Buffer buf = new Buffer (storage);
00359 
00360         // write tokens with a comma between each
00361         IWriter w = new TextWriter (buf, ",");
00362         
00363         // bind a comma-tokenizer to a token instance
00364         BoundToken token = new BoundToken (Tokenizers.comma);
00365 
00366         // write some stuff to the buffer
00367         w.put("now is the time for all good men").put(3.14159);
00368         
00369         // read it back, and display as text
00370         while (token.next (buf))
00371                Stdout.put (token).cr();
00372 }
00373 
00374 /*******************************************************************************
00375 
00376         Use tokens directly with reader/writer also
00377 
00378 *******************************************************************************/
00379 
00380 static void testToken2()
00381 {
00382         // create a small buffer on the heap
00383         Buffer buf = new Buffer (256);
00384 
00385         // write items with a comma between each
00386         IWriter w = new TextWriter (buf, ",");
00387 
00388         // write some stuff to the buffer
00389         w << "now is the time for all good men" << 3.14159;
00390 
00391         // bind a couple of tokens to a comma tokenizer
00392         ReaderToken text = new ReaderToken (Tokenizers.comma);
00393         ReaderToken number = new ReaderToken (Tokenizers.comma);
00394         
00395         // create any old reader since we only use it for handling tokens
00396         IReader r = new Reader (buf);
00397 
00398         // populate both tokens via reader 
00399         r >> text >> number;
00400 
00401         // print them to the console
00402         Stdout << text << ':' << number;
00403         Stdout.cr();
00404 }
00405 
00406 /*******************************************************************************
00407 
00408         use TextReader to convert text into integral types. This is akin 
00409         to what scanf does.
00410 
00411 *******************************************************************************/
00412 
00413 static void testToken3()
00414 {
00415         // create a small buffer
00416         Buffer buf = new Buffer (256);
00417 
00418         // write tokens with a comma between each
00419         TextWriter tw = new TextWriter (buf, ",");
00420 
00421         // write some stuff to the buffer
00422         tw << 101 << 3.14159;
00423 
00424         // map a comma-tokenizing reader onto our buffer 
00425         TextReader tr = new TextReader (buf, Tokenizers.comma);
00426 
00427         real pi;
00428         int  integer;
00429         
00430         // convert both tokens via reader 
00431         tr >> integer >> pi;
00432 
00433         // print them to the console
00434         Stdout << integer << ',' << pi;
00435         Stdout.cr();
00436 }
00437 
00438 
00439 /*******************************************************************************
00440 
00441         Read line tokens via a TextReader
00442 
00443 *******************************************************************************/
00444 
00445 version (ArrayReaderSupport)
00446 {
00447 static void testToken4()
00448 {
00449         // open a file for reading
00450         FileConduit fc = new FileConduit ("test.txt");
00451 
00452         // create a buffer for transferring content
00453         IBuffer buffer = fc.createBuffer ();
00454 
00455         // map a line-tokenizing reader onto our buffer 
00456         TextReader tr = new TextReader (buffer, Tokenizers.line);
00457 
00458         char[] ca;
00459 
00460         // convert both tokens via reader 
00461         tr.get (ca);
00462 
00463         // print them to the console
00464         Stdout.put (ca).cr();
00465 }
00466 }
00467 
00468 
00469 /*******************************************************************************
00470 
00471         Use printf via a wrapper class
00472 
00473 *******************************************************************************/
00474 
00475 static void testFormat()
00476 {       
00477         // create a Pattern instance
00478         TextFormat tf = new TextFormat (256);
00479 
00480         // write text to Stdout
00481         Stdout.put (tf.format ("there are %d arguments to every %.*s", 3, "contradiction")).cr();
00482 }
00483 
00484 
00485 /*******************************************************************************
00486 
00487         Layout text strings in an indexed fashion
00488 
00489 *******************************************************************************/
00490 
00491 static void testLayout()
00492 {       
00493         // create a Layout instance
00494         TextLayout!(char) tl = new TextLayout!(char)(256);
00495 
00496         // write text to Stdout
00497         Stdout.put (tl.format ("%2 %1", "one", "two")).cr();
00498 }
00499 
00500 
00501 /*******************************************************************************
00502 
00503         Use interfaces to make any class reader and/or writer compatible 
00504 
00505 *******************************************************************************/
00506 
00507 static void testClassIO()
00508 {
00509         // define a readable/writable class (via interfaces)
00510         class Foo : IReadable, IWritable
00511         {
00512                 private int x = 11;
00513                 private int y = 112;
00514 
00515                 void write(IWriter writer)
00516                 {
00517                         // use opShl() format here ...
00518                         writer << x << y;
00519                 }
00520 
00521                 void read(IReader reader)
00522                 {
00523                         // use get() format this time ...
00524                         reader.get(x).get(y);
00525                 }
00526         }
00527 
00528         // create a small heap buffer
00529         Buffer buf = new Buffer (256);
00530 
00531         // map reader/writer onto same buffer
00532         Writer w = new Writer(buf);
00533         Reader r = new Reader(buf);
00534 
00535         // construct a Foo
00536         Foo foo = new Foo();
00537 
00538         // write it
00539         w << foo;
00540         
00541         // read it back
00542         r >> foo;
00543 }
00544 
00545 
00546 /*******************************************************************************
00547 
00548         Use interfaces to make any class serializable. This will be used
00549         by mango.server to move class-instances around the network. Each 
00550         class is effectively a factory for itself.
00551 
00552         Note that this is not the same as Java; you can't ship code with
00553         the data ... one might perhaps use dll's or something to do that.
00554 
00555 *******************************************************************************/
00556 
00557 static void testClassSerialization()
00558 {
00559         // define a serializable class (via interfaces)
00560         class Bar : IPickle, IPickleFactory
00561         {
00562                 private int x = 11;
00563                 private int y = 112;
00564         
00565                 void write (IWriter writer)
00566                 {
00567                         writer.put(x).put(y);
00568                 }
00569 
00570                 void read (IReader reader)
00571                 {
00572                         reader.get(x).get(y);
00573                         assert (x == 11 && y == 112);
00574                 }
00575 
00576                 Object create (IReader reader)
00577                 {
00578                         Bar bar = new Bar ();
00579                         bar.read (reader);
00580                         return bar;
00581                 }
00582 
00583                 char[] getGuid ()
00584                 {
00585                         return "unittest.Bar";
00586                 }
00587         }
00588 
00589         static Object create (IReader reader)
00590         {
00591                 Bar bar = new Bar();
00592                 bar.read (reader);
00593                 return bar;
00594         }
00595 
00596         // setup for serialization
00597         Buffer buf = new Buffer (256);
00598         PickleWriter w = new PickleWriter (buf);
00599         PickleReader r = new PickleReader (buf);
00600 
00601         r.setAllocator (new BufferAllocator(r));
00602 
00603         // construct a Bar
00604         Bar bar = new Bar ();
00605 
00606         // tell registry about this object
00607         //PickleRegistry.enroll (&create, "unittest.Bar");
00608         PickleRegistry.enroll (bar);
00609 
00610         // serialize it
00611         w.freeze (bar);
00612         
00613         // create a new instance and populate. This just shows the basic
00614         // concept, not a fully operational implementation
00615         Object o = r.thaw ();
00616 }
00617 
00618 
00619 /*******************************************************************************
00620 
00621         open a file, and stream directly to console
00622 
00623 *******************************************************************************/
00624 
00625 static void testFile4()
00626 {
00627         // open a file for reading
00628         FileConduit fc = new FileConduit ("test.txt");
00629 
00630         // stream directly to console
00631         Stdio.stdout.copy (fc);
00632 }
00633 
00634 
00635 /*******************************************************************************
00636 
00637        Create a file for random access. Write some stuff to it, rewind to
00638        file start and read back.
00639 
00640 *******************************************************************************/
00641 
00642 static void testRandomAccess()
00643 {
00644         // open a file for reading
00645         auto FileConduit fc = new FileConduit ("random.bin", FileStyle.ReadWriteCreate);
00646 
00647         // construct (binary) reader & writer upon this conduit
00648         Reader r = new Reader(fc);
00649         Writer w = new Writer(fc);
00650 
00651         int x=10, y=20;
00652 
00653         // write some data
00654         w.put(x).put(y);
00655 
00656         // flush output since IO is buffered
00657         w.flush();
00658 
00659         // rewind to file start
00660         fc.seek (0);
00661 
00662         // read data back again, but swap destinations
00663         r.get(y).get(x);
00664 
00665         assert (y==10);
00666         assert (x==20);
00667 }
00668 
00669 
00670 /*******************************************************************************
00671 
00672        Create a file for random access. Write some stuff to it, rewind to
00673        file start and read back.
00674 
00675 *******************************************************************************/
00676 
00677 static void testConduitFilters()
00678 {
00679         class MyFilter1 : ConduitSource
00680         {
00681                 int reader (void[] dst)
00682                 {
00683                         printf ("filtering input ...\n");
00684                         return next.reader (dst);
00685                 }
00686         }
00687 
00688         class MyFilter2 : ConduitSink
00689         {
00690                 int writer (void[] src)
00691                 {
00692                         printf ("filtering output ...\n");
00693                         return next.writer (src);
00694                 }
00695         }
00696 
00697         // open a file for reading
00698         auto FileConduit fc = new FileConduit ("random.bin", FileStyle.ReadWriteCreate);
00699         fc.attach (new MyFilter2);
00700         fc.attach (new MyFilter1);
00701         fc.attach (new MyFilter1);
00702 
00703         // construct (binary) reader & writer upon this conduit
00704         Reader r = new Reader(fc);
00705         Writer w = new Writer(fc);
00706 
00707         int x=1;
00708 
00709         // write some data
00710         w.put(x).flush();
00711 
00712         // rewind to file start
00713         fc.seek (0);
00714 
00715         // read data back again
00716         r.get(x);
00717 }
00718 
00719 
00720 /*******************************************************************************
00721 
00722         open a file, and explicitly buffer it to another conduit. This is
00723         effectively what Conduit.copyTo() does.
00724 
00725 *******************************************************************************/
00726 
00727 static void testFile5()
00728 {
00729         // open a file for reading
00730         FileConduit fc = new FileConduit ("test.txt");
00731 
00732         // create a buffer for transferring content
00733         IBuffer buffer = fc.createBuffer ();
00734 
00735         // stream the data from file to stdout. This is probably as fast as 
00736         // one can practically make operations of this type. 
00737         while (fc.read (buffer) != fc.Eof)
00738                Stdio.stdout.write (buffer);
00739 
00740         // ensure the writer actually wrote everything
00741         Stdio.stdout.flush (buffer);
00742 }
00743 
00744 
00745 /*******************************************************************************
00746 
00747         Open a file and read it line-by-line using a line tokenizer. This 
00748         uses CompositeToken to hide some of the details. 
00749 
00750 *******************************************************************************/
00751 
00752 static void testFile1()
00753 {
00754         // open a file for reading
00755         FileConduit fc = new FileConduit ("test.txt");
00756 
00757         // create a Token and bind it to both the file and a line-tokenizer
00758         CompositeToken line = new CompositeToken (Tokenizers.line, fc);
00759 
00760         // read file a line at a time. Method next() returns false when no more 
00761         // delimiters are found. Note there may be an unterminated line at eof
00762         while (line.get)
00763                Stdout.put(line).cr();
00764 }
00765 
00766 
00767 /*******************************************************************************
00768 
00769         Unwound version of above: we now explicitly pass a buffer instance 
00770         to the tokenizer, although the token itself is still bound.
00771 
00772 *******************************************************************************/
00773 
00774 static void testFile2()
00775 {
00776         // open a file for reading
00777         FileConduit fc = new FileConduit ("test.txt");
00778 
00779         // create a buffer for reading the file
00780         IBuffer buffer = fc.createBuffer();
00781 
00782         // bind a line-tokenizer to our input token
00783         BoundToken line = new BoundToken (Tokenizers.line);
00784 
00785         // read file a line at a time. Method next() returns false when no more 
00786         // delimiters are found. Note there may be an unterminated line at eof
00787         while (line.next(buffer) || line.getLength())
00788                Stdout.put(line).cr();
00789 }
00790 
00791 
00792 /*******************************************************************************
00793 
00794         Further unwinding of above: we invoke the tokenizer directly, 
00795         explicitly passing both the buffer and the token
00796 
00797 *******************************************************************************/
00798 
00799 static void testFile3()
00800 {
00801         // open a file for reading
00802         FileConduit fc = new FileConduit ("test.txt");
00803 
00804         // create a buffer for reading the file
00805         IBuffer buffer = fc.createBuffer();
00806 
00807         // create a token for receiving the line
00808         Token token = new Token ();
00809 
00810         // read file a line at a time. Method next() returns false when no more 
00811         // delimiters are found. Note there may be an unterminated line at eof
00812         while (Tokenizers.line.next(buffer, token) || token.getLength())
00813                Stdout.put(token).cr();
00814 }
00815 
00816 
00817 /*******************************************************************************
00818 
00819         Recursively scan files and directories, adding filtered files to
00820         an output structure as we go. Thanks to Chris S for this.
00821         
00822 *******************************************************************************/
00823 
00824 void testScanFiles()
00825 {       
00826         /***********************************************************************
00827 
00828         ***********************************************************************/
00829 
00830         struct Dependencies 
00831         {
00832                 FileProxy[]     mods;
00833                 FilePath[]      pkgs;
00834         }
00835 
00836         /***********************************************************************
00837 
00838         ***********************************************************************/
00839 
00840         void scanFiles (inout Dependencies deps, FilePath base) 
00841         {
00842                 /***************************************************************
00843 
00844                         delegate for filtering sub-directories and 
00845                         D source files
00846 
00847                 ***************************************************************/
00848 
00849                 bit filter (FilePath fp) 
00850                 {
00851                         char[]  sbuf = fp.getExtension();
00852 
00853                         if (fp.getName[0] != '.')                       
00854                             if (sbuf.length == 0 || sbuf == "d")
00855                                 return true;
00856 
00857                         return false;
00858                 }
00859 
00860                 /***************************************************************
00861 
00862                 ***************************************************************/
00863 
00864                 FileProxy  proxy = new FileProxy (base);
00865                 FilePath[] paths = proxy.toList  (&filter);
00866 
00867                 // add packages only if there's something in them
00868                 if (paths.length)
00869                     deps.pkgs ~= base;
00870 
00871                 foreach (FilePath x; paths) 
00872                         {
00873                         // combine base path with listed file
00874                         FilePath spliced = new FilePath (x.splice (base));
00875 
00876                         // recurse if this is a directory ...
00877                         proxy = new FileProxy (spliced);
00878                         if (proxy.isDirectory) 
00879                             scanFiles (deps, spliced);
00880                         else 
00881                            deps.mods ~= proxy;
00882                         }
00883         }
00884 
00885 
00886         /***********************************************************************
00887 
00888         ***********************************************************************/
00889 
00890         Dependencies deps;
00891         scanFiles (deps, new FilePath(r"\dmd\src\mango"));
00892 
00893         Stdout.put ("-----------------").cr();
00894         foreach (FileProxy mod; deps.mods)
00895                  Stdout.put (mod.getPath()).cr();
00896 
00897         Stdout.put ("-----------------").cr();
00898         foreach (FilePath pkg; deps.pkgs)
00899                  Stdout.put (pkg).cr();
00900 }
00901 
00902 
00903 /*******************************************************************************
00904 
00905         Open an internet connection, and copy home page to console (via
00906         Chris Miller's socket.d). We could use a line-by-line approach in
00907         the same manner as above since both Files & Sockets are conduits. 
00908         All conduits are interchangable with others.
00909 
00910 *******************************************************************************/
00911 
00912 static void testSocket()
00913 {
00914         // create a socket and connect it to Walter's site
00915         SocketConduit sc = new SocketConduit();
00916         sc.connect (new InternetAddress("www.digitalmars.com", 80));
00917 
00918         // construct a (flushing) writer and bind it to the socket
00919         IWriter w = new DisplayWriter (new FlushBuffer(1024, sc));
00920 
00921         // send HTTP request
00922         w << "GET /d/intro.html HTTP/1.1\r\n"
00923              "Host: www.digitalmars.com\r\n"
00924              "\r\n";
00925 
00926         // set read-timeout to 0.5 seconds (avoids stalling)
00927         sc.setTimeout (System.Interval.Millisec * 500);
00928 
00929         // stream home-page directly to console conduit
00930         Stdio.stdout.copy (sc);
00931 }
00932 
00933 
00934 /*******************************************************************************
00935 
00936         Use a ColumnWriter to write formatted data onto the console. Note
00937         that we map the ColumnWriter directly into the Stdout buffer.
00938 
00939 *******************************************************************************/
00940 
00941 static void testColumn()
00942 {
00943         static int[] columns = [0, 4, 14, 24];
00944 
00945         // map a ColumnWriter directly onto Stdout
00946         ColumnWriter cw = new ColumnWriter (Stdout.getBuffer(), new ColumnList(columns));
00947 
00948         // set 2 digits of precision
00949         cw.setPrecision (2);
00950 
00951         // put() style
00952         cw.put(1);
00953         cw.put(20.34);
00954         cw.put("test");
00955         cw.cr();
00956         cw.put("next");
00957 }
00958 
00959 /*******************************************************************************
00960 
00961         Get a line of input from the console, and extract an integer. Input
00962         from the console always waits until CR is pressed (at the OS level).
00963 
00964 *******************************************************************************/
00965 
00966 static void testStdin()
00967 {
00968         int x;
00969         
00970         // display a prompt
00971         Stdout << "Enter a number: ";
00972 
00973         // wait for <cr>, then convert input to integer.
00974         Stdin >> x;
00975 }
00976 
00977 
00978 import std.regexp;
00979         
00980 /*******************************************************************************
00981 
00982         Use RegExp to scan words via a buffer. 
00983 
00984 *******************************************************************************/
00985 
00986 static void wordRegex (IBuffer buffer)
00987 {
00988         // create a new regex tokenizer for words
00989         RegexTokenizer rt = new RegexTokenizer (new RegExp(r"\w+", null));
00990 
00991         // create a token to hold tokenized output, and bind it to the buffer
00992         CompositeToken word = new CompositeToken (rt, buffer);
00993 
00994         // read buffer a word at a time. Method next() returns false when no 
00995         // more tokens are found
00996         while (word.next)
00997                Stdout.put(word).cr();
00998 }
00999 
01000 
01001 
01002 /*******************************************************************************
01003 
01004         Use RegExp to scan file content via a buffer. Buffered scanning  
01005         avoids loading the entire file into memory at one time.
01006 
01007 *******************************************************************************/
01008 
01009 static void testFileRegex()
01010 {
01011         // open a file for reading
01012         FileConduit fc = new FileConduit ("test.txt");
01013         
01014         // extract words from file
01015         wordRegex (fc.createBuffer);
01016 }
01017 
01018 
01019 /*******************************************************************************
01020 
01021         open an internet connection and scan home-page for words. 
01022 
01023 *******************************************************************************/
01024 
01025 static void testSocketRegex()
01026 {
01027         // create a socket and connect it to Walter's site
01028         SocketConduit sc = new SocketConduit();
01029         sc.connect (new InternetAddress("www.digitalmars.com", 80));
01030 
01031         // construct a (flushing) writer and bind it to the socket
01032         IWriter w = new DisplayWriter (new FlushBuffer(256, sc));
01033 
01034         // send HTTP request
01035         w << "GET /d/intro.html HTTP/1.1\r\n"
01036              "Host: www.digitalmars.com\r\n"
01037              "\r\n";
01038 
01039         // set read-timeout to 0.5 seconds (avoids stalling)
01040         sc.setTimeout (System.Interval.Millisec * 500);
01041 
01042         // scan words out of home page
01043         wordRegex (sc.createBuffer);
01044 }
01045 
01046 
01047 /*******************************************************************************
01048 
01049         Read lines from a file, and scan each line for words. This shows
01050         how to map the content of one buffer into another without copying
01051         any data. Unlikely to be a common activity.
01052         
01053 *******************************************************************************/
01054 
01055 static void testLineRegex()
01056 {
01057         // open a file for reading
01058         FileConduit fc = new FileConduit ("test.txt");
01059         
01060         // create a token for lines, and map it onto the file buffer.
01061         CompositeToken line = new CompositeToken (Tokenizers.line, fc);
01062 
01063         // create a seperate buffer for scanning within each line. We will 
01064         // set the content for this buffer as we read each line. Note that
01065         // if we used the file buffer directly, then we'd continue reading
01066         // words right past the end of the line. This is because the file
01067         // buffer would just reload itself instead of halting at the line
01068         // termimator.
01069         Buffer rescan = new Buffer;
01070 
01071         // scan all lines in the file, including the final one
01072         while (line.get)
01073               {
01074               // map our rescan buffer onto the line content 
01075               rescan.setValidContent (line.toString);
01076 
01077               // scan just this line for words
01078               wordRegex (rescan);
01079               }
01080         
01081 }
01082 
01083 /*******************************************************************************
01084 
01085         Display the size of a file 
01086         
01087 *******************************************************************************/
01088 
01089 static void testFileSize()
01090 {
01091         FileProxy fp = new FileProxy ("test.txt");
01092 
01093         Stdout.put (fp.getPath)
01094               .put(" is ")
01095               .put(fp.getSize)
01096               .put(" bytes long")
01097               .cr();
01098 }                
01099 
01100 
01101 /*******************************************************************************
01102 
01103         list a set of files
01104         
01105 *******************************************************************************/
01106 
01107 static void testFileList()
01108 {
01109         FileProxy proxy = new FileProxy (r".");
01110 
01111         foreach (FilePath path; proxy.toList())
01112                  Stdout.put(path).cr();
01113 }                
01114 
01115 /*******************************************************************************
01116 
01117         list a set of files
01118         
01119 *******************************************************************************/
01120 
01121 static void testFilePath()
01122 {
01123         FilePath path = new FilePath (r"c:\1\2\3\4\abc.foo.bar");
01124 
01125         Stdout << path << Writer.newline;
01126 
01127         Uri uri = path.toUri();
01128         Stdout << uri.getScheme() << Writer.newline
01129                << uri.getHost() << Writer.newline
01130                << uri.getPath() << Writer.newline
01131                << uri.getPort() << Writer.newline
01132                << uri << Writer.newline;
01133 
01134         uri = new Uri (uri.toString());
01135         Stdout << uri.getScheme() << Writer.newline
01136                << uri.getHost() << Writer.newline
01137                << uri.getPath() << Writer.newline
01138                << uri.getPort() << Writer.newline
01139                << uri << Writer.newline;
01140 
01141         path = new FilePath (uri);
01142 
01143         Stdout << path << Writer.newline;
01144 }                
01145 
01146 
01147 /*******************************************************************************
01148 
01149         Construct a memory-mapped buffer upon a 200MB file. Note that we 
01150         should close both the conduit and buffer when finished. 
01151 
01152         Note also that Win32 takes a while to close the initial file if
01153         it has just been created or resized. Subsequently opening the
01154         file as ReadWriteExising performs admirably. I imagine it's to
01155         do with spooling a gazillion dirty pages to the drive?
01156 
01157 *******************************************************************************/
01158 
01159 void testMappedFile()
01160 {
01161         FileConduit conduit = new FileConduit ("test.bin", FileStyle.ReadWriteCreate);
01162         conduit.seek (200_000_000);
01163         conduit.truncate ();
01164 
01165         MappedBuffer buffer = conduit.createMappedBuffer;
01166         buffer.setPosition (100_000_000);
01167         buffer.append ("test");
01168         buffer.close ();
01169 
01170         conduit.close ();
01171 }
01172 
01173 
01174 /*******************************************************************************
01175 
01176         Use Composite IO to read and write a data-set. See CompositeReader
01177         and CompositeWriter for more on this.
01178          
01179 *******************************************************************************/
01180 
01181 static void testCompositeIO()
01182 {
01183         // define a serializable class (via interfaces)
01184         class Wumpus : IReadable, IWritable
01185         {
01186                 private int     x = 11,
01187                                 y = 112,
01188                                 z = 1024;
01189 
01190                 void write(IWriter writer)
01191                 {
01192                         writer.put(x).put(y).put(z);
01193                 }
01194 
01195                 void read(IReader reader)
01196                 {
01197                         reader.get(x).get(y).get(z);
01198                 }
01199 
01200         }
01201 
01202         // construct a Wumpus
01203         Wumpus wumpus = new Wumpus();
01204 
01205         // open a file for IO
01206         FileConduit fc = new FileConduit ("random.bin", FileStyle.ReadWriteCreate);
01207 
01208         // construct composite reader & writer upon the file, with binary IO
01209         IWriter w = new Writer(fc);
01210         IReader r = new Reader(fc);
01211 
01212         // write the Wumpus (and flush it)
01213         w.put(wumpus).flush();
01214 
01215         // rewind to file start
01216         fc.seek (0);
01217 
01218         // read Wumpus back again
01219         r.get (wumpus);
01220 
01221         fc.close();
01222 }
01223 
01224 
01225 
01226 /*******************************************************************************
01227 
01228         One can perform direct IO on a conduit, simply by mapping a Buffer
01229         onto a local array. No additional buffering takes place but readers, 
01230         writers, and tokenizers can't tell the difference: they may all be 
01231         used without issue.
01232 
01233         This example uses the same direct-buffer for both reading & writing.
01234         However, seperate buffers may be used as appropriate.
01235 
01236 *******************************************************************************/
01237 
01238 static void testDirectIO()
01239 {
01240         // open a file for IO
01241         auto FileConduit fc = new FileConduit ("random.bin", FileStyle.ReadWriteCreate);
01242 
01243         // direct IO area (on the stack)
01244         ubyte[1024] content;
01245 
01246         // map a buffer onto local content. State all of it is valid content.
01247         // There are other IBuffer methods, such as setValidContent(), which
01248         // stipulate how much data is really in the buffer.
01249         IBuffer direct = new Buffer(content, content.length);
01250 
01251         // map our buffer onto the file
01252         direct.setConduit(fc);
01253 
01254         // mess with the content[] ...
01255         // ...
01256         // ...
01257         // ...
01258 
01259         // write directly from the local buffer (might use fc.flush() instead)  
01260         fc.write (direct);
01261 
01262         // rewind to file start
01263         fc.seek (0);
01264 
01265         // make space for reading 
01266         direct.clear();
01267 
01268         // read it all back in again
01269         int count = fc.read (direct);
01270         delete fc;
01271 
01272 }
01273 
01274 
01275 /*******************************************************************************
01276 
01277 *******************************************************************************/
01278 
01279 static void testUri()
01280 {
01281         MutableUri uri;
01282         
01283         uri = new MutableUri ("ftp1://Me:My@a:21");
01284         Stdout << uri << Writer.newline;
01285 
01286         uri.parse ("http://a:8080/b/c/d;p?q=bar of soap#fragmented");
01287         Stdout << uri << Writer.newline;
01288 
01289         Stdin.wait();
01290 
01291         for (int i=10_000_000; i > 0; --i)
01292              uri.parse ("http://a:8080/b/c/d;p?q=bar of soap#fragmented");
01293 }
01294 
01295 
01296 /******************************************************************************
01297 ************************ SocketServer testing *********************************
01298 *******************************************************************************/
01299 
01300 
01301 
01302 /*******************************************************************************
01303         
01304         Test the http server by sending it a few thousand requests.  Note
01305         that we don't use a reader or a writer here, though we could just
01306         as easily have done so.
01307 
01308         Also note that (Gentoo) linux has a hard time scavenging sockets
01309         fast enough to complete more than around 6000 iterations. Without
01310         the appropriate guru incantations to make ulimit work as desired,
01311         we just limit the iterations to a more agreeable level. Testing 
01312         under Win32 seems to be fine at the 100,000 iteration mark.
01313 
01314 *******************************************************************************/
01315 
01316 void testClient ()
01317 {
01318         Buffer buf = new Buffer(1024);
01319         InternetAddress addr = new InternetAddress("127.0.0.1", 80);
01320 
01321         for (int i=5000; --i >= 0;)
01322             {
01323             // connect to the server
01324             SocketConduit socket = new SocketConduit ();
01325             socket.connect (addr);
01326 
01327             // when we close this socket, recycle it immediately!
01328             socket.setLingerPeriod (0);
01329 
01330             // reset buffer for another go around
01331             buf.clear ();
01332                 
01333             // would need this if we were using Reader/Writer IO
01334             // buf.setConduit(socket);
01335 
01336             // send a request. This will be serviced by our IProvider
01337             //buf.append ("GET / HTTP/1.1\n\n");
01338 
01339             buf.append("POST /RPC2 HTTP/1.1\n"
01340             "Content-Length: 157\n"
01341             "Content-Type: text/xml\n"
01342             "Cache-Control: no-cache\n"
01343             "Pragma: no-cache\n"
01344             "User-Agent: Java/1.4.2_05\n"
01345             "Host: localhost:8181\n"
01346             "Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2\n"
01347             "Connection: keep-alive\n\n"
01348             "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><methodCall>"
01349             "<methodName>nnCore.getNode</methodName><params><param>"
01350             "<value>1@1</value></param></params></methodCall>");
01351             socket.write (buf);
01352 
01353             // wait for something to be returned (you can set a timeout)
01354             socket.read (buf);
01355 
01356             // dump response to the console
01357             //Stdio.stdout.write (buf);
01358 
01359             // attempt a graceful shutdown
01360             socket.shutdown ();
01361 
01362             // close and destroy socket (the latter will do both)
01363             socket.close ();
01364             delete socket;
01365             }
01366 }
01367 
01368 
01369 /*******************************************************************************
01370 
01371         Create an http server with the given IProvider
01372 
01373 *******************************************************************************/
01374 
01375 void testServer (IProvider provider)
01376 {       
01377         // bind to port 80 on a local address
01378         InternetAddress addr = new InternetAddress (80);
01379 
01380         // create a (1 thread) server using the IProvider to service requests
01381         HttpServer server = new HttpServer (provider, addr, 1);
01382 
01383         // start listening for requests (but this thread does not listen)
01384         server.start ();
01385         
01386         // pause for some console input
01387         Stdout << "hit return to start the client test ...";
01388         Stdin.wait ();
01389 
01390         // send a few thousand requests
01391         testClient ();
01392 }
01393 
01394 
01395 /*******************************************************************************
01396 
01397         Declare a class for handling http requests. This one just simply
01398         returns a status page
01399 
01400 *******************************************************************************/
01401 
01402 void testHttpServer ()
01403 {       
01404         class Provider : HttpProvider
01405         {
01406                 void service (HttpRequest request, HttpResponse response)
01407                 {
01408                         response.sendError (HttpResponses.OK);
01409                 }
01410         }
01411 
01412         // create a new http-provider, and attach it to a server
01413         testServer (new Provider());
01414 }
01415 
01416 
01417 /*******************************************************************************
01418 
01419         Test the servlet wrapper. Point your Browser at http://127.0.0.1
01420         and optionally add a path, query params, etc ...
01421 
01422 *******************************************************************************/
01423 
01424 void testServletEngine ()
01425 {       
01426         /***********************************************************************
01427 
01428                 Return a file. Deliberately supports GET requests only. 
01429 
01430         ***********************************************************************/
01431 
01432         class FileServlet : MethodServlet
01433         {
01434                 void doGet (IServletRequest request, IServletResponse response)
01435                 {   
01436                         response.copyFile (request.getContext(), request.getPathInfo());
01437                 }
01438         }
01439 
01440 
01441         /***********************************************************************
01442 
01443                 A whole bunch of diagnostic stuff, plus cookie return and
01444                 rudimentary form processing.
01445 
01446         ***********************************************************************/
01447 
01448         class MyServlet : Servlet
01449         {
01450                 void service (IServletRequest request, IServletResponse response)
01451                 {   
01452                         Uri uri = request.getUri();
01453 
01454                         // log everything to the console
01455                         Stdout.put ("------------------------")
01456                               .cr  ()
01457                               .put ("Uri: ")
01458                               .put (uri)
01459                               .cr  ()
01460                               .put ("------------------------")
01461                               .cr  ()
01462                               .put ("Headers:")
01463                               .cr  ()
01464                               .put (request.getHeaders())
01465                               .put ("------------------------")
01466                               .cr  ()
01467                               .put ("Cookies:")
01468                               .cr  ()
01469                               .put (request.getCookies())
01470                               .put ("------------------------")
01471                               .cr  ()
01472                               .put ("Parameters:")
01473                               .cr  ()
01474                               .put (request.getParameters())
01475                               .put ("------------------------")
01476                               .cr  ();
01477 
01478                         // display the Servlet environment
01479                         Stdout.put("encoding: ")
01480                               .put(request.getCharacterEncoding())
01481                               .cr ()
01482                               .put("content length: ").put(request.getContentLength())
01483                               .cr ()
01484                               .put("content type: ").put(request.getContentType())
01485                               .cr ()                   
01486                               .put("protocol: ").put(request.getProtocol())
01487                               .cr ()                   
01488                               .put("scheme: ").put(uri.getScheme())
01489                               .cr ()                   
01490                               .put("method: ").put(request.getMethod())
01491                               .cr ()                   
01492                               .put("host name: ").put(request.getServerName())
01493                               .cr ()                   
01494                               .put("host port: ").put(request.getServerPort())
01495                               .cr ()                   
01496                               //.put("remote address: ").put(request.getRemoteAddress()).cr()                   
01497                               //.put("remote host: ").put(request.getRemoteHost()).cr()                   
01498                               .put("path info: ").put(request.getPathInfo())
01499                               .cr ()                   
01500                               .put("query: ").put(uri.getQuery())
01501                               .cr ()                   
01502                               .put("path: ").put(uri.getPath())
01503                               .cr ()                   
01504                               .put("context path: ").put(request.getContextPath())
01505                               .cr ()                   
01506                               .cr ()
01507                               .cr ();  
01508 
01509                         int i = request.getContentLength();
01510 
01511                         if (i > 0)
01512                            {
01513                            byte[] content = new byte[i];
01514 
01515                            request.getReader.getPostData (content);
01516                            printf ("Content:\n>>%.*s<<\n\n\n", content);
01517                            }
01518 
01519                         // send a cookie to the user-agent ...
01520                         response.getCookies().add (new Cookie ("fu", "'bar of soap'"));
01521 
01522                         // send a form to the user-agent ...
01523                         IWriter writer = response.getWriter();
01524                         writer.put ("<HTML><HEAD><TITLE>Form</TITLE></HEAD>")
01525                               .put ("<BODY><FORM method=POST action=\"/context/test\">")
01526                               .put ("Enter a POST parameter: ")
01527                               .put ("<INPUT type=text name=\"name\"><P>")
01528                               .put ("<INPUT type=hidden name=\"hidden\" value=\"test\"><P>")
01529                               .put ("<INPUT type=submit>")
01530                               .put ("<?FORM></BODY></HTML>")
01531                               .cr  ();
01532 
01533                 }
01534         }
01535           
01536 
01537         // construct a servlet-provider
01538         ServletProvider sp = new ServletProvider();
01539 
01540         // map all html requests to our file servlet
01541         IRegisteredServlet files = sp.addServlet (new FileServlet(), "files");
01542         sp.addMapping ("*.html", files);
01543         sp.addMapping ("*.htm", files);
01544         
01545         // map all other request to our test servlet
01546         IRegisteredServlet test = sp.addServlet (new MyServlet(), "test");
01547         sp.addMapping ("/", test);
01548 
01549         // fire up a server
01550         testServer (sp);
01551 }
01552 
01553 
01554 /*******************************************************************************
01555 
01556         Shows a variety of ways in which to access data returned from
01557         a client-side socket connection.
01558 
01559 *******************************************************************************/
01560 
01561 void testHttpClient ()
01562 {  
01563         /***********************************************************************
01564 
01565                 Bulk copy from input to Stdout
01566 
01567         ***********************************************************************/
01568 
01569         void readBulk (IConduit conduit)
01570         {
01571                 // stream directly to console
01572                 Stdio.stdout.copy (conduit);
01573         }
01574 
01575         /***********************************************************************
01576 
01577                 Unwound version of the above, where we explicitly move
01578                 data between endpoints using a buffer
01579 
01580         ***********************************************************************/
01581 
01582         void readBulkExplicit (IConduit conduit)
01583         {
01584                 // create a buffer for transferring content
01585                 IBuffer buffer = conduit.createBuffer ();
01586 
01587                 // stream the data from file to stdout. This is probably as fast as 
01588                 // one can practically make operations of this type. 
01589                 while (conduit.read (buffer) != conduit.Eof)
01590                        Stdio.stdout.write (buffer);
01591 
01592                 // ensure the writer actually wrote everything
01593                 assert (Stdio.stdout.flush (buffer));
01594         }
01595 
01596         /***********************************************************************
01597 
01598                 Read input a line at a time from the input. You can access
01599                 the line content via method Token.toString()
01600 
01601         ***********************************************************************/
01602 
01603         void readLines (IConduit conduit)
01604         {
01605                 // create a Token and bind it to both the conduit and a line-tokenizer
01606                 CompositeToken line = new CompositeToken (Tokenizers.line, conduit);
01607 
01608                 // read data a line at a time. Method next() returns false when no more 
01609                 // delimiters are found. Note there may be an unterminated line at eof
01610                 while (line.get)
01611                        Stdout.put(line).cr();
01612         }
01613 
01614         /***********************************************************************
01615 
01616                 Read input a char at a time. This will read in big chunks
01617                 of data from the input, but spit them out one character at
01618                 a time. While this is a lot faster then reading one char
01619                 at a time from the OS (the typical approach), this style
01620                 of reading is not recommended. Instead, try the 'chunked'
01621                 approach (below).
01622 
01623         ***********************************************************************/
01624 
01625         void readChars (IConduit conduit)
01626         {
01627                 // create a reader on the conduit
01628                 Reader reader = new Reader (conduit);
01629 
01630                 // read a single character at a time, until we run out of them.
01631                 // An exception will eventually be thrown because we're using
01632                 // the 'formatted' data approach
01633                 try {
01634                     while (true)
01635                           {
01636                           char c;
01637                           reader.get (c);
01638                           Stdout.put (c);
01639                           }
01640                     } catch (IOException x){}
01641         }
01642 
01643         /***********************************************************************
01644 
01645                 Read big chunks of data, and process them as such. Each read
01646                 operation will eat as much as there is from the input, up to
01647                 the size limit of the buffer.
01648 
01649         ***********************************************************************/
01650 
01651         void readChunks (IConduit conduit)
01652         {
01653                 IBuffer buffer = new Buffer(1024);        
01654         
01655                 while (conduit.read (buffer) != conduit.Eof)
01656                       {
01657                       Stdout.put (buffer.toString);
01658                       buffer.clear ();
01659                       }
01660         }
01661 
01662         /***********************************************************************
01663         
01664                 unwound version of the above, where we setup buffer space
01665                 on the stack (instead of the heap). We need to explicitly
01666                 ask the buffer how much data is actually available. One
01667                 could use the return value from read() as the number of
01668                 bytes available instead (in this particular case), or 
01669                 use buffer.toString() as in the above case
01670 
01671         ***********************************************************************/
01672 
01673         void readChunksExplicit (IConduit conduit)
01674         {
01675                 char[1024] content;
01676 
01677                 IBuffer buffer = new Buffer (content);        
01678 
01679                 while (conduit.read (buffer) != conduit.Eof)
01680                       {
01681                       Stdout.put (content[0..buffer.readable()]);
01682                       buffer.clear ();
01683                       }
01684         }
01685 
01686 
01687         /***********************************************************************
01688 
01689                 Open a web-site connection, and process the returned page
01690 
01691         ***********************************************************************/
01692 
01693         // create a socket and connect it to Walter's site
01694         SocketConduit sc = new SocketConduit();
01695         sc.connect (new InternetAddress("www.digitalmars.com", 80));
01696 
01697         // construct a (flushing) writer and bind it to the socket
01698         IWriter w = new DisplayWriter (new FlushBuffer (256, sc));
01699         
01700         // send HTTP request
01701         w.put ("GET /d/intro.html HTTP/1.1")
01702          .cr  ()
01703          .put ("Host: www.digitalmars.com")
01704          .cr  ()
01705          .cr  ();
01706 
01707         // set read-timeout to 1 second (avoids stalling for ever!)
01708         sc.setTimeout (System.Interval.Second);
01709         
01710         //readBulk (sc);
01711         //readBulkExplicit(sc);
01712         //readLines(sc);
01713         //readChars(sc);
01714         //readChunks(sc);
01715         readChunksExplicit(sc);
01716 }
01717      
01718 
01719 /*******************************************************************************
01720 
01721         Extract client-side headers from an HTTP reply
01722         
01723 *******************************************************************************/
01724 
01725 void testHttpClient2 ()
01726 {  
01727         // create a socket and connect it to Walter's site
01728         SocketConduit sc = new SocketConduit;
01729         sc.connect (new InternetAddress("www.digitalmars.com", 80));
01730 
01731         // construct a (flushing) writer and bind it to the socket
01732         IWriter w = new DisplayWriter (new FlushBuffer (256, sc));
01733         
01734         // send HTTP request
01735         w.put ("GET /d/intro.html HTTP/1.1")
01736          .cr  ()
01737          .put ("Host: www.digitalmars.com")
01738          .cr  ()
01739          .cr  ();
01740 
01741         // set read-timeout to 1 second (avoids stalling for ever!)
01742         sc.setTimeout (System.Interval.Second);
01743 
01744         // create an input buffer
01745         IBuffer buffer = sc.createBuffer;
01746         
01747         // extract all headers 
01748         HttpHeaders headers = new HttpHeaders;
01749         headers.parse (buffer);
01750 
01751         // display parsed headers -- these should match HttpHeader.HttpHeaders
01752         foreach (HeaderElement header; headers)
01753                  Stdout.put (header.name.value)
01754                        .put (header.value)
01755                        .cr  ();
01756 
01757         // display remaining content
01758         while (sc.read (buffer) != sc.Eof)
01759               {
01760               Stdout.put (buffer.toString);
01761               buffer.clear ();
01762               }
01763 }
01764 
01765 /*******************************************************************************
01766 
01767         Poke an HTTP server, using HttpClient.
01768 
01769 *******************************************************************************/
01770 
01771 void testHttpClient3()
01772 {
01773         // callback for client reader
01774         void sink (char[] content)
01775         {
01776                 Stdout.put (content);
01777         }
01778 
01779         // create client for a GET request
01780         auto HttpClient client = new HttpClient (HttpClient.Get, "http://www.digitalmars.com/d/intro.html");
01781 
01782         // setup a Host header
01783         client.getRequestHeaders.add (HttpHeader.Host, client.getUri.getHost);
01784 
01785         // make request
01786         client.open ();
01787 
01788         // check return status for validity
01789         if (client.isResponseOK)
01790            {
01791            // extract content length (be aware of -1 return, for no header)
01792            int length = client.getResponseHeaders.getInt (HttpHeader.ContentLength);
01793            if (length < 0)
01794                length = int.max;
01795         
01796            // display all returned headers
01797            Stdout.put (client.getResponseHeaders);
01798         
01799            // display remaining content
01800 //           client.read (&sink, length);
01801            client.read (delegate (char[] c){Stdout.put(c);}, length);
01802            }
01803         else
01804            Stderr.put (client.getResponse);
01805 }
01806 
01807 
01808 
01809 
01810 /******************************************************************************
01811 **************************** Cache testing ************************************
01812 *******************************************************************************/
01813 
01814 
01815 
01816 /*******************************************************************************
01817 
01818 
01819 *******************************************************************************/
01820 
01821 void testPlainCache()
01822 {
01823         PlainCache cache = new PlainCache (2);
01824 
01825         cache.put ("a", new Payload);
01826         cache.put ("b", new Payload);
01827         cache.put ("c", new Payload);
01828         cache.put ("c", new Payload);
01829 
01830         cache.extract ("b");
01831         assert (cache.get("a"));
01832         assert (cache.get("c"));
01833         assert (cache.get("b") is null);
01834 }
01835 
01836 /*******************************************************************************
01837 
01838         QueuedCache maintains a linked list of items, in addition to a
01839         hashmap. Any reference to an item places it at the list head, 
01840         resulting in the LRU items always being left at the tail. When
01841         the list becomes full, tail items are dropped and their places
01842         reused.
01843 
01844         This is great for keeping commonly accessed items around, while
01845         limiting the amount of memory used.
01846 
01847         Typically, the queue size would be set in the hundreds (perhaps
01848         thousands) but we just use 2 for testing purposes. 
01849 
01850 *******************************************************************************/
01851 
01852 void testQueuedCache()
01853 {
01854         QueuedCache cache = new QueuedCache (2);
01855 
01856         cache.put ("a", new Payload);
01857         cache.put ("b", new Payload);
01858         cache.put ("c", new Payload);
01859         cache.put ("c", new Payload);
01860 
01861         assert (cache.get("a") is null);
01862         assert (cache.get("c"));
01863 }
01864 
01865 /*******************************************************************************
01866 
01867         Stuff some data into a FileBucket, and pull it out again.
01868 
01869 *******************************************************************************/
01870 
01871 void testFileBucket()
01872 {
01873         char[] text = "this is a test";
01874 
01875         FileBucket bucket = new FileBucket (new FilePath("bucket.bin"), FileBucket.HalfK, 0);
01876 
01877         // insert some data, and retrieve it again
01878         bucket.put ("a", text);
01879         char[] b = cast(char[]) bucket.get ("a");
01880 
01881         assert (b == text);
01882         bucket.close();
01883 }
01884 
01885 
01886 /*******************************************************************************
01887 
01888         Use a combination of QueuedCache and FileBucket to spill LRU
01889         cache entries onto the hard-drive, and then recover them intact.
01890 
01891         This demonstrates what one can do with the IPickle notion.
01892 
01893 *******************************************************************************/
01894 
01895 void testVirtualCache()
01896 {
01897         FileBucket bucket = new FileBucket (new FilePath("bucket.bin"), FileBucket.HalfK);
01898         VirtualCache cache = new VirtualCache (bucket, 2);
01899         PickleRegistry.enroll (new Payload);
01900         
01901         cache.put ("a", new Payload);
01902         cache.put ("b", new Payload);
01903         cache.put ("c", new Payload);
01904 
01905         assert (cache.get("a"));
01906         assert (cache.get("c"));
01907         assert (cache.get("b"));
01908         bucket.close();
01909 }
01910 
01911 /*******************************************************************************
01912 
01913 
01914 *******************************************************************************/
01915 
01916 void testProtocol()
01917 {
01918         class Protocol : Payload
01919         {
01920                 char[]  x;
01921                 int     y = 10;
01922                 bool    z = true;
01923         
01924                 this ()
01925                 {
01926                         x = "fred";
01927                 }
01928 
01929                 static this()
01930                 {
01931                         PickleRegistry.enroll (new Protocol);
01932                 }
01933 
01934                 void write (IWriter w)
01935                 {
01936                         super.write (w);
01937                         w.put (x)
01938                          .put (y)
01939                          .put (z);
01940                 }
01941 
01942                 void read (IReader r)
01943                 {
01944                         super.read (r);
01945                         r.get (x)
01946                          .get (y)
01947                          .get (z);
01948 
01949                         assert (x == "fred");
01950                         assert (y == 10);
01951                         assert (z == true);
01952                 }
01953 
01954                 Payload create ()
01955                 {
01956                         return new Protocol;
01957                 }
01958 
01959                 char[] getGuid ()
01960                 {
01961                         return this.classinfo.name;
01962                 }
01963         }
01964 
01965         Protocol p = new Protocol;
01966 
01967         Buffer b = new Buffer (1024);
01968         ProtocolWriter w = new ProtocolWriter (b);
01969         ProtocolReader r = new ProtocolReader (b);
01970 
01971         w.put (w.Command.Exception, "mychannel", p);
01972 
01973         ubyte   cmd;
01974         char[]  channel,
01975                 element;
01976 
01977         p = cast(Protocol) r.getPayload (channel, element, cmd);
01978 }
01979 
01980 
01981 /*******************************************************************************
01982 
01983 
01984 *******************************************************************************/
01985 
01986 void testHashMap()
01987 {
01988         class AAPut
01989         {
01990                 Object[char[]] aa;
01991 
01992                 synchronized void put (char[] k, Object v)
01993                 {
01994                         aa[k] = v;
01995                 }
01996 
01997                 synchronized Object get (char[] k)
01998                 {
01999                         if (k in aa)
02000                             return aa[k];
02001                         return null;
02002                 }
02003 
02004                 synchronized void del (char[] k)
02005                 {
02006                         delete aa[k];
02007                 }
02008         }
02009 
02010 
02011         static const char[] key = "dkfsdflksdjf s;dklf kdfjf;lskdfjs d;flskdfjs dfl";
02012 
02013         AAPut aa = new AAPut;
02014         HashMap map = new HashMap (1024);
02015 
02016         map.put (key, Client.EmptyMessage);
02017         aa.put (key, Client.EmptyMessage);
02018 
02019         map.put ("asdfasdfasdfasdfasdfasdfasdfasdfasdfasdf", Client.EmptyMessage);
02020         aa.put ("asdfasdfasdfasdfasdfasdfasdfasdfasdfasdf", Client.EmptyMessage);
02021 
02022         map.put ("asdfasdfasdfasdfasdfasdfasdfasdfasdfasdf 34534 5345", Client.EmptyMessage);
02023         aa.put ("asdfasdfasdfasdfasdfasdfasdfasdfasdfasdf 3453453535", Client.EmptyMessage);
02024 
02025         logger.info ("A");
02026         for (int i=5_000_000; --i;)
02027             {
02028             map.put (key, Client.EmptyMessage);
02029             map.remove (key);
02030             //map.get (key);
02031             }
02032 
02033         logger.info ("B");
02034         for (int i=5_000_000; --i;)
02035             {
02036             aa.put (key, Client.EmptyMessage);
02037             aa.del (key);
02038             //aa.get (key);
02039             }
02040 /*
02041 
02042         map.put ("x", Client.EmptyMessage);
02043         map.put ("y", Client.EmptyMessage);
02044         assert (map.get ("a"));
02045         assert (! map.get ("b"));
02046         assert (map.remove ("a"));
02047         assert (! map.get ("a"));
02048 */
02049 }
02050 
02051 
02052 /*******************************************************************************
02053 
02054 
02055 *******************************************************************************/
02056 
02057 void testRollingFileLog()
02058 {
02059         Logger l = Logger.getLogger ("test");
02060         l.addAppender (new RollingFileAppender (r"e:\test.log", 3, 1024, new DateLayout));
02061 
02062         for (int i=100; --i;)
02063              l.error ("weqwer er wer werqwer wer wer wer wr wqrwe qrw rwe rwqerw");
02064 }
02065 
02066 
02067 
02068 
02069 /******************************************************************************
02070 **************************** Cluster testing **********************************
02071 *******************************************************************************/
02072 
02073 
02074 
02075 /*******************************************************************************
02076 
02077         Join a socket to a multicast group, and send the group a packet.
02078 
02079 *******************************************************************************/
02080 
02081 void testMulticast()
02082 {
02083         class MyListener : SocketListener
02084         {
02085                 this (ISocketReader reader, IBuffer buffer)
02086                 {
02087                         super (reader, buffer);
02088                 }
02089 
02090                 void notify (IBuffer buffer)
02091                 {
02092                         printf ("listener received %d bytes\n", buffer.readable());
02093                 }
02094 
02095                 void exception (char[] msg)
02096                 {       
02097                         printf ("listener error: %.*s\n", msg);
02098                 }
02099         }
02100 
02101         //auto MulticastSocket ms = new MulticastSocket ();
02102         MulticastSocket ms = new MulticastSocket ();
02103         InternetAddress ia = new InternetAddress ("226.1.1.1", 4444);
02104 
02105         ms.join (ia);
02106         MyListener s = new MyListener (ms, new Buffer (2000));
02107         s.start ();
02108         
02109         Stdin.wait ();
02110         //s.pause ();
02111         //s.resume ();
02112 
02113         byte[1000] xx;
02114         Buffer b = new Buffer (xx, xx.length);
02115 
02116         ms.write (b, ia);
02117         Stdin.wait ();
02118         //s.cancel ();
02119 }
02120 
02121 /*******************************************************************************
02122 
02123 *******************************************************************************/
02124 
02125 void testClusterCache()
02126 {
02127         //ClusterServer cs = new ClusterServer (new InternetAddress(4567), 1);
02128         //cs.start ();
02129 
02130         //auto FileConduit config = new FileConduit ("cluster.properties");
02131         //Cluster cluster = new Cluster (logger, config);
02132         Cluster cluster = new Cluster (logger, 4567);
02133 
02134         //NetworkCache cc = new NetworkCombo (cluster, "myChannel", new PlainCache);
02135         NetworkCache cc = new NetworkCache (cluster, "myChannel");
02136 
02137         InvalidatorPayload p = new InvalidatorPayload;
02138 
02139             cc.put ("key", p);
02140 //            cc.invalidate ("key");
02141         for (int i=100_000; i; --i)
02142             {
02143 //            p.setText ("fubar");
02144 //            cc.put ("key", p);
02145 //            cc.invalidate ("key");
02146             IPayload p = cc.get ("key");
02147 //            if ((i & 0x3f) == 0)
02148 //                 System.sleep (System.Interval.Second);
02149 /*
02150             p = cast(InvalidatorPayload) cc.get ("key");
02151             assert (p);
02152             assert (p.getText == "fubar");
02153 
02154             cc.invalidate ("key");
02155             p = cast(InvalidatorPayload) cc.get ("key");
02156 */
02157             }
02158         //assert (p is null);
02159 
02160 //        cc.invalidate ("key");
02161 
02162         //Stdin.wait ();
02163 }
02164 
02165 
02166 /*******************************************************************************
02167 
02168 *******************************************************************************/
02169 
02170 void testClusterQueue()
02171 {       
02172         class Listen : IEventListener
02173         {
02174                 void notify (IEvent event, IPayload payload)
02175                 {
02176                         printf ("recieved queue entry from channel '%.*s'\n", event.getChannel.getName);       
02177                 }
02178         }
02179 
02180         //ClusterServer cs = new ClusterServer (new InternetAddress(4567), 1);
02181         //cs.start ();
02182 
02183         Cluster cluster = new Cluster (logger, 4567);
02184         NetworkQueue queue = new NetworkQueue (cluster, "queue.channel");
02185 
02186         queue.createConsumer (new Listen);
02187         queue.put (new InvalidatorPayload);
02188         queue.put (new InvalidatorPayload);
02189         
02190         Stdin.wait ();
02191 }
02192 
02193 
02194 /*******************************************************************************
02195 
02196 *******************************************************************************/
02197 
02198 void testInvalidatee()
02199 {
02200         ICluster c = new Cluster (logger);
02201 
02202         CacheInvalidatee dst = new CacheInvalidatee (c, "abc", new PlainCache);
02203         CacheInvalidator src = new CacheInvalidator (c, "abc");
02204 
02205         src.invalidate ("key1");
02206 
02207         Stdin.wait ();
02208 }
02209 
02210 
02211 /*******************************************************************************
02212 
02213 
02214 *******************************************************************************/
02215 
02216 void testClusterServer()
02217 {
02218         ClusterServer cs = new ClusterServer (new InternetAddress(81), 1);
02219         SocketConduit sc = new SocketConduit ();
02220         cs.start();
02221 
02222         sc.connect (new InternetAddress ("127.0.0.1", 81));
02223         Stdin.wait ();
02224 }
02225 
02226 
02227 /*******************************************************************************
02228 
02229 
02230 *******************************************************************************/
02231 
02232 
02233 void testClusterMessage()
02234 {
02235         class MessageListener : IEventListener
02236         {
02237                 void notify (IEvent event, IPayload payload)
02238                 {
02239                         IMessage message = cast(IMessage) payload;
02240 
02241                         printf ("Replying to message\n");
02242                         event.reply (message.getReply, new InvalidatorPayload);
02243                 }
02244         }
02245 
02246         class ReplyListener : IEventListener
02247         {
02248                 void notify (IEvent event, IPayload payload)
02249                 {
02250                         printf ("Received reply\n");
02251                 }
02252         }
02253 
02254         //ClusterServer cs = new ClusterServer (new InternetAddress(4567), 1);
02255         //cs.start ();
02256 
02257         // open the cluster
02258         Cluster cluster = new Cluster (logger, 4567);
02259 
02260         // open up a message channel
02261         NetworkMessage msg = new NetworkMessage (cluster, "message.channel", new ReplyListener);
02262 
02263         // toss a message out to the cluster
02264         msg.put (new NullMessage);
02265 
02266         // setup a listener to receive message (could do this earlier)
02267         msg.createConsumer (new MessageListener);
02268         
02269         // wait for traffic to pass by
02270         Stdin.wait ();
02271 }
02272 
02273 
02274 /*******************************************************************************
02275 
02276 
02277 *******************************************************************************/
02278 
02279 void testCacheLoader()
02280 {
02281         class CacheLoader : ICacheLoader
02282         {
02283                 bool test (IPayload p)
02284                 {
02285                         return false;
02286                 }            
02287                 
02288                 IPayload load (char[] key, long time)
02289                 {
02290                         printf ("loading local cache instance\n");
02291                         return new NullMessage;
02292                 }    
02293         }
02294 
02295         IMutableCache mc = new PlainCache;
02296         ICache c = mc.bind (new CacheLoader);
02297 
02298         c.get ("abcde");
02299 }
02300 
02301 
02302 /*******************************************************************************
02303 
02304 
02305 *******************************************************************************/
02306 
02307 void testRemoteCacheLoader()
02308 {
02309         class RemoteCacheLoader : Payload, IRemoteCacheLoader
02310         {
02311                 bool test (IPayload p)
02312                 {
02313                         return false;
02314                 }            
02315                 
02316                 IPayload load (char[] key, long time)
02317                 {
02318                         printf ("loading remote cache instance\n");
02319                         return new NullMessage;
02320                 }    
02321 
02322                 /**********************************************************************
02323                 
02324                         Recover the timestamp from the provided reader
02325 
02326                 **********************************************************************/
02327 
02328                 void read (IReader reader)
02329                 {
02330                         super.read (reader);
02331                 }
02332 
02333                 /**********************************************************************
02334 
02335                         Emit our timestamp to the provided writer
02336 
02337                 **********************************************************************/
02338 
02339                 void write (IWriter writer)
02340                 {
02341                         super.write (writer);
02342                 }
02343 
02344                 /***********************************************************************
02345 
02346                         Create a new instance of a payload, and populate it via
02347                         read() using the specified reader
02348 
02349                 ***********************************************************************/
02350 
02351                 Object create (IReader reader)
02352                 {
02353                         Payload r = new RemoteCacheLoader;
02354                         r.read (reader);
02355                         return r;
02356                 }
02357 
02358                 /**********************************************************************
02359 
02360                         Return the guid for this payload. This should be unique
02361                         per payload class, if said class is used in conjunction
02362                         with the clustering facilities. Inspected by the Pickle
02363                         utilitiy classes.
02364 
02365                 **********************************************************************/
02366 
02367                 char[] getGuid ()
02368                 {
02369                         return this.classinfo.name;
02370                 }
02371 
02372 
02373                 uint pause (uint wait)
02374                 {
02375                         return 100_000;
02376                 }
02377         }
02378 
02379         Cluster cluster = new Cluster (logger, 4567);
02380         NetworkCache nc = new NetworkCache (cluster, "my.channel");
02381         IRemoteCacheLoader cl = new RemoteCacheLoader;
02382         ICache c = nc.bind (cl);
02383 
02384         c.get ("abcde");
02385 }
02386 
02387 
02388 /*******************************************************************************
02389 
02390 
02391 *******************************************************************************/
02392 
02393 void testDisplay ()
02394 {
02395         class Encoder : IStringEncoder
02396         {
02397                 void char8 (void* src, uint count)
02398                 {
02399                         printf ("%.*s", count, src);
02400                 }
02401 
02402                 void char16 (void* src, uint count)
02403                 {
02404                         assert (0);
02405                 }
02406 
02407                 void char32 (void* src, uint count)
02408                 {
02409                         assert (0);
02410                 }
02411         }
02412 
02413         IWriter w = new DisplayWriter (Stdio.stdout.createBuffer());
02414         w.setStringEncoder (new Encoder);
02415 
02416         ubyte b = 129;
02417         uint ui = uint.max;
02418         int i = -3;
02419         
02420         w.put (1);
02421         w.put (' ');
02422         w.put (1.12);
02423 
02424         w.put(b).put(' ')
02425          .put(ui).put(' ')
02426          .put(i).put(' ')
02427          .put("hello")
02428          .cr()
02429          .flush();
02430 }
02431 
02432 
02433 /*******************************************************************************
02434 
02435 
02436 *******************************************************************************/
02437 
02438 void testTextWriter ()
02439 {
02440         class Encoder1 : IStringEncoder
02441         {
02442                 void char8 (void* src, uint count)
02443                 {
02444                         printf ("%.*s", count, src);
02445                 }
02446 
02447                 void char16 (void* src, uint count)
02448                 {
02449                         assert (0);
02450                 }
02451 
02452                 void char32 (void* src, uint count)
02453                 {
02454                         assert (0);
02455                 }
02456         }
02457 
02458         IWriter w = new TextWriter (Stdout.getBuffer(), ", ");
02459         w.setStringEncoder (new Encoder1);
02460 
02461         ubyte b = 129;
02462         uint ui = uint.max;
02463         int i = -3;
02464 
02465         w.put(b)
02466          .put(ui)
02467          .put(i)
02468          .put("hello")
02469          .cr();
02470         w.put("test");
02471         w.flush();
02472 }
02473 
02474 
02475 /*******************************************************************************
02476 
02477 
02478 *******************************************************************************/
02479 
02480 int main(char[][] args)
02481 {   
02482         BasicConfigurator.configure ();
02483         //PropertyConfigurator.configure ("log.properties");
02484         logger = Logger.getLogger ("mango.unittest");
02485         //logger.setLevel (logger.Level.Error);
02486         //logger.addAppender (new FileAppender ("log.txt", new DateLayout));
02487         //logger.addAppender (new StdioAppender (new SimpleTimerLayout));
02488 
02489         try {
02490             //testDisplay();
02491             //testTextWriter();
02492             //testHashMap();
02493             //testRemoteCacheLoader();
02494             //testCacheLoader();
02495             //testProtocol();
02496             //testClusterMessage();
02497             //testRollingFileLog();
02498             //testClusterCache();
02499             //testClusterQueue();
02500             //testClusterServer();
02501             //testInvalidatee();
02502             //testMulticast();
02503 
02504             //testAppend();
02505             //testFile4();
02506             testClassSerialization();
02507             //testFormat();
02508             //testLayout();
02509             //testFileSize();
02510             //testFilePath();
02511             //testFileList();
02512             //testScanFiles();
02513             //testFile1();
02514             //testFile5();
02515             //testToken1();
02516             //testToken2();
02517             //testColumn();
02518             //testSocket();
02519             //testStdin();
02520             //testBuffer();
02521             //testToken3();
02522             //testFileRegex();
02523             //testLineRegex();
02524             //testSocketRegex();
02525             //testRandomAccess();
02526             //testCompositeIO();
02527             //testDirectIO();
02528             //testHttpServer();
02529             //testServletEngine();
02530             //testUri();
02531             //testHttpClient();
02532             //testHttpClient2();
02533             //testHttpClient3();
02534             //testQueuedCache();
02535             //testFileBucket();
02536             //testScanFiles();
02537             //testVirtualCache();
02538             //testQueuedCache();
02539             //testPlainCache();
02540             //testMappedFile();
02541             logger.info ("Done");
02542             } catch (Object x)
02543                     {
02544                     logger.fatal (x.toString);
02545                     }
02546 
02547         return 0;
02548 }
02549 

Generated on Sun Oct 24 22:31:17 2004 for Mango by doxygen 1.3.6