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

unittest.d

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

Generated on Fri May 27 18:11:57 2005 for Mango by  doxygen 1.4.0