PLearn 0.1
PPathTest.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // PPathTest.cc
00004 //
00005 // Copyright (C) 2005 Olivier Delalleau 
00006 // Copyright (C) 2005 Christian Dorion
00007 // 
00008 // Redistribution and use in source and binary forms, with or without
00009 // modification, are permitted provided that the following conditions are met:
00010 // 
00011 //  1. Redistributions of source code must retain the above copyright
00012 //     notice, this list of conditions and the following disclaimer.
00013 // 
00014 //  2. Redistributions in binary form must reproduce the above copyright
00015 //     notice, this list of conditions and the following disclaimer in the
00016 //     documentation and/or other materials provided with the distribution.
00017 // 
00018 //  3. The name of the authors may not be used to endorse or promote
00019 //     products derived from this software without specific prior written
00020 //     permission.
00021 // 
00022 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
00023 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00024 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
00025 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00027 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00028 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00029 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00030 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00031 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00032 // 
00033 // This file is part of the PLearn library. For more information on the PLearn
00034 // library, go to the PLearn Web site at www.plearn.org
00035 
00036 /* *******************************************************      
00037    * $Id: .pyskeleton_header 544 2003-09-01 00:05:31Z plearner $ 
00038    ******************************************************* */
00039 
00040 // Authors: Olivier Delalleau, Christian Dorion
00041 
00045 #include "PPathTest.h"
00046 #include <plearn/io/PPath.h>
00047 #include <plearn/io/pl_log.h>
00048 #include <plearn/base/stringutils.h>
00049 
00050 namespace PLearn {
00051 using namespace std;
00052 
00053 PLEARN_IMPLEMENT_OBJECT(
00054     PPathTest,
00055     "Test PPath-related stuff.",
00056     ""
00057 );
00058 
00060 // PPathTest //
00062 PPathTest::PPathTest() 
00063     /* ### Initialize all fields to their default value */
00064 {
00065     // ...
00066 
00067     // ### You may (or not) want to call build_() to finish building the object
00068     // ### (doing so assumes the parent classes' build_() have been called too
00069     // ### in the parent classes' constructors, something that you must ensure)
00070 }
00071 
00073 // build //
00075 void PPathTest::build()
00076 {
00077     inherited::build();
00078     build_();
00079 }
00080 
00082 // makeDeepCopyFromShallowCopy //
00084 void PPathTest::makeDeepCopyFromShallowCopy(CopiesMap& copies)
00085 {
00086     inherited::makeDeepCopyFromShallowCopy(copies);
00087 
00088     // ### Call deepCopyField on all "pointer-like" fields 
00089     // ### that you wish to be deepCopied rather than 
00090     // ### shallow-copied.
00091     // ### ex:
00092     // deepCopyField(trainvec, copies);
00093 
00094     // ### Remove this line when you have fully implemented this method.
00095     PLERROR("PPathTest::makeDeepCopyFromShallowCopy not fully (correctly) implemented yet!");
00096 }
00097 
00099 // declareOptions //
00101 void PPathTest::declareOptions(OptionList& ol)
00102 {
00103     // ### Declare all of this object's options here
00104     // ### For the "flags" of each option, you should typically specify  
00105     // ### one of OptionBase::buildoption, OptionBase::learntoption or 
00106     // ### OptionBase::tuningoption. Another possible flag to be combined with
00107     // ### is OptionBase::nosave
00108 
00109     // ### ex:
00110     // declareOption(ol, "myoption", &PPathTest::myoption, OptionBase::buildoption,
00111     //               "Help text describing this option");
00112     // ...
00113 
00114     // Now call the parent class' declareOptions
00115     inherited::declareOptions(ol);
00116 }
00117 
00119 // build_ //
00121 void PPathTest::build_()
00122 {
00123     // ### This method should do the real building of the object,
00124     // ### according to set 'options', in *any* situation. 
00125     // ### Typical situations include:
00126     // ###  - Initial building of an object from a few user-specified options
00127     // ###  - Building of a "reloaded" object: i.e. from the complete set of all serialised options.
00128     // ###  - Updating or "re-building" of an object after a few "tuning" options have been modified.
00129     // ### You should assume that the parent class' build_() has already been called.
00130 }
00131 
00132 #define WIDTH 60    
00133 #define PRINT_TEST(str, __test) \
00134 MAND_LOG\
00135  << left(str, WIDTH) << flush;\
00136   try {\
00137     MAND_LOG << (__test) << endl << endl;\
00138   }\
00139   catch(const PLearnError& e)\
00140   {\
00141     perr << "FATAL ERROR: " << e.message() << endl << endl;\
00142   }\
00143   catch (...)\
00144   {\
00145     perr << "FATAL ERROR: uncaught unknown exception" << endl << endl;\
00146   }
00147 
00148 #define ASSERT(str, __test) \
00149 MAND_LOG\
00150  << left(str, WIDTH) << flush;\
00151   try {\
00152     bool   __result = (__test);\
00153     string __success;\
00154     if ( __result ) __success = "True";\
00155     else            __success = "False";\
00156     MAND_LOG << __success << endl << endl;\
00157   }\
00158   catch(const PLearnError& e)\
00159   {\
00160     perr << "FATAL ERROR: " << e.message() << endl << endl;\
00161   }\
00162   catch (...)\
00163   {\
00164     perr << "FATAL ERROR: uncaught unknown exception" << endl << endl;\
00165   }
00166 
00167 
00175 
00176 void split_behavior( const string& test,
00177                             const string& dos,
00178                             const string& posix  )
00179 {
00180     int wd = WIDTH / 2;
00181     string str = left("  DOS: " + dos, wd) + "POSIX: " + posix;
00182   
00183     MAND_LOG << test << endl
00184              << left(str, WIDTH)            << flush;
00185 }
00186 
00187 string boolstr(bool b)
00188 {
00189     if ( b ) return "True";
00190     return "False";
00191 }
00192 
00193 void backslashes()
00194 {
00195     split_behavior( "PPath('./foo//bar\\toto')", 
00196                     "== 'foo/bar/toto'",
00197                     "Rejected" );
00198 
00199     bool success = false;
00200 
00201 #ifdef WIN32
00202     success = PPath("./foo//bar\\toto") == "foo/bar/toto";
00203 #else
00204     try {
00205         PPath p("./foo//bar\\toto");
00206     }
00207     catch(const PLearnError& e)
00208     {
00209         success = true;
00210     }
00211 #endif
00212     MAND_LOG << boolstr( success ) << endl << endl;
00213 } 
00214 
00215 
00216 
00217 void absolute_path()
00218 {
00219     string absolute_str;
00220     string drive;
00221     string display_str = "HOME:dorionc";
00222 #ifdef WIN32
00223     absolute_str = "r:/dorionc"; 
00224     drive        = "r:"; 
00225 #else
00226     absolute_str = "/home/dorionc";
00227     drive        = "";
00228 #endif
00229 
00230     PPath absolute( absolute_str );
00231 
00232     split_behavior( "isAbsPath()",                  
00233                     "r:/dorionc",
00234                     "/home/dorionc" );
00235   
00236     MAND_LOG << boolstr( absolute.isAbsPath() ) << endl << endl;
00237 
00238     split_behavior( "absolute('" + display_str + "') == ...",                  
00239                     "r:/dorionc", "/home/dorionc" );
00240   
00241     MAND_LOG << boolstr( absolute == absolute_str ) << endl << endl;
00242 
00243     split_behavior( "absolute('" + display_str + "').drive() == ...",           
00244                     "r:", "" );
00245   
00246     MAND_LOG << boolstr( absolute.drive() == drive ) << endl << endl;
00247 }
00248 
00249 // Should all be true
00250 void someAsserts()
00251 {
00252     MAND_LOG << plhead("Asserts") << endl;
00253 
00255     MAND_LOG << plhead("The special dirnames . and ..") << endl;  
00256 
00257     ASSERT( "PPath('./foo/bar') == 'foo/bar'",
00258             PPath("./foo/bar") == "foo/bar" );
00259     
00260     ASSERT( "PPath('foo/./bar') == 'foo/bar'",
00261             PPath("foo/./bar") == "foo/bar" );
00262 
00263     ASSERT( "PPath('foo/../bar') == 'bar'",
00264             PPath("foo/../bar") == "bar" );
00265 
00266     ASSERT( "PPath('./foo/bar/../bar/../../foo/./bar') == 'foo/bar'",
00267             PPath("./foo/bar/../bar/../../foo/./bar") == "foo/bar" );
00268 
00269     PRINT_TEST("PPath('././foo/bar') / PPath('../bar/../../foo/./bar') == 'foo/bar'", "")
00270         ASSERT( "", PPath("././foo/bar") / PPath("../bar/../../foo/./bar") == "foo/bar" );
00271 
00273     MAND_LOG << plhead("Operators") << endl;
00274     
00275     ASSERT( "PPath('') == ''", PPath("") == "" );
00276 
00277     ASSERT( "PPath('') != 'foo'", PPath("") != "foo" );
00278 
00279     ASSERT( "PPath('foo/bar') / '' == 'foo/bar/'",
00280             PPath("foo/bar") / "" == "foo/bar/" );  
00281   
00282     ASSERT( "PPath('foo/bar') / 'file.cc' == 'foo/bar/file.cc'",
00283             PPath("foo/bar") / "file.cc" == "foo/bar/file.cc" );  
00284 
00285     ASSERT( "PPath('foo/bar/') / 'file.cc' == 'foo/bar/file.cc'",
00286             PPath("foo/bar/") / "file.cc" == "foo/bar/file.cc" );  
00287 
00289     MAND_LOG << plhead("Methods up and dirname") << endl;  
00290 
00291     PRINT_TEST( "PPath('PL_ROOT:').up()", PPath("PL_ROOT:").up() );   // PLERROR
00292     PRINT_TEST( "PPath('').up()",  PPath("").up() );    // PLERROR
00293   
00294     ASSERT( "PPath('PL_ROOT:foo').up() == 'PL_ROOT:'",
00295             PPath("PL_ROOT:foo").up() == "PL_ROOT:" );  
00296 
00297     ASSERT( "PPath('foo/bar').up() == 'foo'",
00298             PPath("foo/bar").up() == "foo" );  
00299 
00300     ASSERT( "PPath('foo/bar/').up() == 'foo'",
00301             PPath("foo/bar/").up() == "foo" );
00302 
00303     ASSERT( "PPath('foo.cc').dirname() == '.'",
00304             PPath("foo.cc").dirname() == "." );
00305     
00306     ASSERT( "PPath('foo/bar').dirname() == 'foo'",
00307             PPath("foo/bar").dirname() == "foo" );
00308     
00309     ASSERT( "PPath('foo/bar/').dirname() == 'foo/bar'",
00310             PPath("foo/bar/").dirname() == "foo/bar" );
00311   
00312     ASSERT( "PPath('foo/bar/hi.cc').dirname() == 'foo/bar'",
00313             PPath("foo/bar/hi.cc").dirname() == "foo/bar" );
00314 
00316     MAND_LOG << plhead("Methods extension and no_extension") << endl;  
00317 
00318     ASSERT( "PPath('foo/bar/hi.cc').extension() == 'cc'",
00319             PPath("foo/bar/hi.cc").extension() == "cc" );
00320 
00321     ASSERT( "PPath('foo/bar.dir/hi.cc').extension() == 'cc'",
00322             PPath("foo/bar.dir/hi.cc").extension() == "cc" );
00323 
00324     ASSERT( "PPath('foo/bar/hi.').extension() == ''",
00325             PPath("foo/bar/hi.").extension() == "" );
00326 
00327     ASSERT( "PPath('foo/bar/hi').extension() == ''",
00328             PPath("foo/bar/hi").extension() == "" );
00329 
00330     ASSERT( "PPath('foo/bar.dir/hi').extension() == ''",
00331             PPath("foo/bar.dir/hi").extension() == "" );
00332 
00333     ASSERT( "PPath('foo/bar/hi.cc').no_extension() == 'foo/bar/hi'",
00334             PPath("foo/bar/hi.cc").no_extension() == "foo/bar/hi" );
00335 
00336     ASSERT( "PPath('foo/bar.d/hi.cc').no_extension() == 'foo/bar.d/hi'",
00337             PPath("foo/bar.d/hi.cc").no_extension() == "foo/bar.d/hi" );
00338 
00339     ASSERT( "PPath('foo/bar.d/hi').no_extension() == 'foo/bar.d/hi'",
00340             PPath("foo/bar.d/hi").no_extension() == "foo/bar.d/hi" );
00341 
00342     ASSERT( "PPath('foo/bar.d/hi.').no_extension() == 'foo/bar.d/hi.'",
00343             PPath("foo/bar.d/hi.").no_extension() == "foo/bar.d/hi." );
00344 
00346     MAND_LOG << plhead("Methods addProtocol() and removeProtocol()") << endl;  
00347 
00348     // TODO There is currently a problem with the 'file' protocol with DOS
00349     // paths: we cannot use file:C:\foo (could be worth checking out why
00350     // exactly), nor can we use file:foo (it is forbidden to use the file
00351     // protocol with a relative path). Thus the 'file' protocol is pretty
00352     // useless, and the following tests have been hacked to systematically
00353     // yield success, as otherwise they would fail.
00354     string portability_hack_string;
00355 
00356     // TODO Actually, this does not look like a correct canonical output!
00357 #ifdef WIN32
00358     portability_hack_string ="file:/foo/bar";
00359 #else
00360     portability_hack_string = PPath("/foo/bar").addProtocol().canonical();
00361 #endif
00362 
00363     PRINT_TEST( "PPath('/foo/bar').addProtocol()",
00364                 portability_hack_string);
00365 
00366     PRINT_TEST( "PPath('foo/bar').addProtocol()",
00367                 PPath("foo/bar").addProtocol().canonical() );  // PLERROR
00368 
00369 #ifdef WIN32
00370     portability_hack_string ="PL_ROOT:foo/bar";
00371 #else
00372     portability_hack_string = PPath("file:/foo/bar").removeProtocol().canonical();
00373 #endif
00374     PRINT_TEST( "PPath('file:/foo/bar').removeProtocol()",
00375                 portability_hack_string);
00376 
00377     PRINT_TEST( "PPath('PL_ROOT:foo/bar').removeProtocol()",
00378                 PPath("PL_ROOT:foo/bar").removeProtocol().canonical() );
00379 
00381     MAND_LOG << plhead("PPath comparisons") << endl;  
00382 
00383     ASSERT( "PPath('foo') == 'foo/'",
00384             PPath("foo") == "foo/" );
00385 
00386     ASSERT( "!(PPath('foo') != 'foo/')",
00387             !(PPath("foo") != "foo/") );
00388 
00389     ASSERT( "PPath('') == ''",
00390             PPath("") == "" );
00391 
00392     ASSERT( "!(PPath('') != '')",
00393             !(PPath("") != "") );
00394     
00395     // TODO See note above about the protocols problems with DOS paths.
00396     bool portability_hack_bool;
00397 #ifdef WIN32
00398     portability_hack_bool = true;
00399 #else
00400     portability_hack_bool = PPath("/foo/bar") == "file:/foo/bar";
00401 #endif
00402 
00403     ASSERT( "PPath('/foo/bar') == 'file:/foo/bar'",
00404             portability_hack_bool );
00405 
00406 #ifdef WIN32
00407     portability_hack_bool = true;
00408 #else
00409     portability_hack_bool = !(PPath("/foo/bar") != "file:/foo/bar");
00410 #endif
00411 
00412     ASSERT( "!(PPath('/foo/bar') != 'file:/foo/bar')",
00413             portability_hack_bool );
00414 
00415     ASSERT( "PPath('ftp:/foo/bar') == 'ftp:/foo/bar/'",
00416             PPath("ftp:/foo/bar") == "ftp:/foo/bar/" );
00417 
00418     ASSERT( "!(PPath('ftp:/foo/bar') != 'ftp:/foo/bar/')",
00419             !(PPath("ftp:/foo/bar") != "ftp:/foo/bar/") );
00420 
00421     ASSERT( "PPath('PL_ROOT:foo') != 'ftp:/foo'",
00422             PPath("PL_ROOT:foo") != "ftp:/foo" );
00423 
00424 #ifdef WIN32
00425     portability_hack_bool = true;
00426 #else
00427     portability_hack_bool = PPath("file:/foo") != "htpp:/foo";
00428 #endif
00429 
00430     ASSERT( "PPath('file:/foo') != 'http:/foo'",
00431             portability_hack_bool );
00432 
00433 }
00434 
00435 void canonical()
00436 {
00437     MAND_LOG << plhead("Canonical paths") << endl;
00438 
00439     // Single dots.
00440 
00441     PRINT_TEST("./foo", PPath("./foo").canonical())
00442         PRINT_TEST("./", PPath("./").canonical())
00443         PRINT_TEST(".", PPath(".").canonical())
00444         PRINT_TEST("PL_ROOT:.", PPath("PL_ROOT:.").canonical())
00445         PRINT_TEST("PL_ROOT:./", PPath("PL_ROOT:./").canonical())
00446         PRINT_TEST("PL_ROOT:./foo", PPath("PL_ROOT:./foo").canonical())
00447         PRINT_TEST("foo/.", PPath("foo/.").canonical())
00448         PRINT_TEST("foo/./", PPath("foo/./").canonical())
00449         PRINT_TEST("foo/./bar", PPath("foo/./bar").canonical())
00450         PRINT_TEST("foo/.bar", PPath("foo/.bar").canonical())
00451         PRINT_TEST("foo./bar", PPath("foo./bar").canonical())
00452 
00453         // Double dots.
00454 
00455         PRINT_TEST("PL_ROOT:..", PPath("PL_ROOT:..").canonical())
00456         PRINT_TEST("PL_ROOT:../foo", PPath("PL_ROOT:../foo").canonical())
00457         PRINT_TEST("../foo", PPath("../foo").canonical())
00458         PRINT_TEST("foo/..", PPath("foo/..").canonical())
00459         PRINT_TEST("foo/../", PPath("foo/../").canonical())
00460         PRINT_TEST("PL_ROOT:foo/..", PPath("PL_ROOT:foo/..").canonical())
00461         PRINT_TEST("PL_ROOT:foo/../", PPath("PL_ROOT:foo/../").canonical())
00462         PRINT_TEST("foo/../bar", PPath("foo/../bar").canonical())
00463         PRINT_TEST("PL_ROOT:foo/../bar", PPath("PL_ROOT:foo/../bar").canonical())
00464         PRINT_TEST("PL_ROOT:..foo", PPath("PL_ROOT:..foo").canonical())
00465         PRINT_TEST("foo../", PPath("foo../").canonical())
00466         PRINT_TEST("../../../foo", PPath("../../../foo").canonical())
00467         PRINT_TEST("foo/../../..", PPath("foo/../../..").canonical())
00468 
00469         // Mixing them all.
00470 
00471         PRINT_TEST(".././../foo/./bar/../foobar", PPath(".././../foo/./bar/../foobar").canonical())
00472         PRINT_TEST("foo/bar/foobar/.././../../foobi/../foobo/../..", PPath("foo/bar/foobar/.././../../foobi/../foobo/../..").canonical())
00473         PRINT_TEST("foo/bar/foobar/.././../../foobi/../foobo/", PPath("foo/bar/foobar/.././../../foobi/../foobo/").canonical())
00474         PRINT_TEST("PL_ROOT:foo/bar/foobar/.././../../foobi/../",
00475              PPath("PL_ROOT:foo/bar/foobar/.././../../foobi/../").canonical())
00476 
00477         // Some metaprotocols tests.
00478 
00479         PPath plearn_dir = PPath("PLEARNDIR:").absolute();
00480         PRINT_TEST("PLEARNDIR:", plearn_dir.canonical())
00481         PRINT_TEST("PLEARNDIR:/.", (plearn_dir / ".").canonical())
00482         PRINT_TEST("PLEARNDIR:/", (plearn_dir / "").canonical())
00483         PRINT_TEST("PLEARNDIR:/foo", (plearn_dir / "foo").canonical())
00484         PRINT_TEST("PLEARNDIR:/foo/", (plearn_dir / "foo/").canonical())
00485         PRINT_TEST("PLEARNDIR:/foo/../", (plearn_dir / "foo/../").canonical())
00486 
00487         }
00492 
00496 
00499 
00500 void unitTest(const string& p)
00501 {
00502     MAND_LOG << plhead(p) << endl;
00503   
00504     PPath path(p);
00505   
00506     PRINT_TEST(  "path",                   path                   );
00507     PRINT_TEST(  "path.isAbsPath()",       path.isAbsPath()       );
00508     PRINT_TEST(  "path.absolute()",        path.absolute()        );
00509     PRINT_TEST(  "path.canonical()",       path.canonical()       );
00510                                    
00511     PRINT_TEST(  "path.protocol()",        path.protocol()        );
00512     PRINT_TEST(  "path.isFilePath()",      path.isFilePath()      );
00513     PRINT_TEST(  "path.isHttpPath()",      path.isHttpPath()      );
00514     PRINT_TEST(  "path.isFtpPath()",       path.isFtpPath()       );
00515     PRINT_TEST(  "path.addProtocol()",     path.addProtocol()     );  
00516     PRINT_TEST(  "path.removeProtocol()",  path.removeProtocol()  );
00517                                    
00518     PRINT_TEST(  "path.up()",              path.up()              );
00519     PRINT_TEST(  "path / 'toto' ",         path / "toto"          );
00520                                    
00521     PRINT_TEST(  "path.drive()",           path.drive()           );
00522     PRINT_TEST(  "path.extension()",       path.extension()       );  
00523   
00524     MAND_LOG << plsep << endl << endl;
00525 }
00526 
00527 
00529 // perform //
00531 void PPathTest::perform()
00532 {
00533     // ### The test code should go here.
00534     PL_Log::instance().verbosity(VLEVEL_NORMAL);
00535     PL_Log::instance().outmode( PStream::raw_ascii );
00536     // Add root metaprotocol binding for cross-platform tests.
00537 #ifdef WIN32
00538     string pl_root = "C:\\";
00539 #else
00540     string pl_root = "/";
00541 #endif
00542     PPath::addMetaprotocolBinding("PL_ROOT", pl_root);
00543     // Display canonical paths in errors for cross-platform compatibility.
00544     PPath::setCanonicalInErrors(true);
00545 
00546     someAsserts();
00547     canonical();    // Display some canonical paths.
00548 
00549     MAND_LOG << plhead("Platform-dependent tests.") << endl;
00550 
00551     backslashes();
00552     absolute_path();
00553   
00554 // Note that platform-dependent tests must not PRINT anything that is
00555 // platform-dependent...
00561 
00562     PPath::setCanonicalInErrors(false);
00563 }
00564 
00565 } // end of namespace PLearn
00566 
00567 
00568 /*
00569   Local Variables:
00570   mode:c++
00571   c-basic-offset:4
00572   c-file-style:"stroustrup"
00573   c-file-offsets:((innamespace . 0)(inline-open . 0))
00574   indent-tabs-mode:nil
00575   fill-column:79
00576   End:
00577 */
00578 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines