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

Generated on Sun Nov 7 19:06:54 2004 for Mango by doxygen 1.3.6