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

unittest.d

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

Generated on Tue Jan 25 21:18:24 2005 for Mango by doxygen 1.3.6