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