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

unittest.d

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

Generated on Sat Apr 9 20:11:29 2005 for Mango by doxygen 1.3.6