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

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

Generated on Mon Nov 14 10:59:42 2005 for Mango by  doxygen 1.4.0