PLearn 0.1
|
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 :