Back to index

nordugrid-arc-nox  1.1.0~rc6
FileCacheTest.cpp
Go to the documentation of this file.
00001 // -*- indent-tabs-mode: nil -*-
00002 
00003 #include <cppunit/extensions/HelperMacros.h>
00004 
00005 #include "../FileCache.h"
00006 
00007 #include <cerrno>
00008 #include <list>
00009 
00010 #include <unistd.h>
00011 #include <utime.h>
00012 #include <sys/stat.h>
00013 #include <sys/types.h>
00014 #include <sys/utsname.h>
00015 
00016 class FileCacheTest
00017   : public CppUnit::TestFixture {
00018 
00019   CPPUNIT_TEST_SUITE(FileCacheTest);
00020   CPPUNIT_TEST(testStart);
00021   CPPUNIT_TEST(testRemoteCache);
00022   CPPUNIT_TEST(testStop);
00023   CPPUNIT_TEST(testStopAndDelete);
00024   CPPUNIT_TEST(testLinkFile);
00025   CPPUNIT_TEST(testLinkFileLinkCache);
00026   CPPUNIT_TEST(testCopyFile);
00027   CPPUNIT_TEST(testFile);
00028   CPPUNIT_TEST(testRelease);
00029   CPPUNIT_TEST(testCheckDN);
00030   CPPUNIT_TEST(testTwoCaches);
00031   CPPUNIT_TEST(testCreationDate);
00032   CPPUNIT_TEST(testValidityDate);
00033   CPPUNIT_TEST(testConstructor);
00034   CPPUNIT_TEST(testBadConstructor);
00035   CPPUNIT_TEST(testInternal);
00036   CPPUNIT_TEST_SUITE_END();
00037 
00038 public:
00039   void setUp();
00040   void tearDown();
00041 
00042   void testStart();
00043   void testRemoteCache();
00044   void testStop();
00045   void testStopAndDelete();
00046   void testLinkFile();
00047   void testLinkFileLinkCache();
00048   void testCopyFile();
00049   void testFile();
00050   void testRelease();
00051   void testCheckDN();
00052   void testTwoCaches();
00053   void testCreationDate();
00054   void testValidityDate();
00055   void testConstructor();
00056   void testBadConstructor();
00057   void testInternal();
00058 
00059 private:
00060   std::string _cache_dir;
00061   std::string _cache_data_dir;
00062   std::string _cache_job_dir;
00063   std::string _session_dir;
00064   std::string _url;
00065   std::string _jobid;
00066   uid_t _uid;
00067   gid_t _gid;
00068   Arc::FileCache *_fc1;
00070   std::list<std::string> _files;
00072   bool _createFile(std::string filename, std::string text = "a");
00074   std::string _readFile(std::string filename);
00076   std::string _intToString(int i);
00077 };
00078 
00079 
00080 
00081 void FileCacheTest::setUp() {
00082 
00083   _cache_dir = "/tmp/" + _intToString(getpid());
00084   _cache_data_dir = _cache_dir + "/data";
00085   _cache_job_dir = _cache_dir + "/joblinks";
00086   _session_dir = "/tmp/" + _intToString(getpid()) + "_session";
00087 
00088   // remove directories that may have been created
00089   rmdir(std::string(_cache_data_dir + "/69").c_str());
00090   rmdir(std::string(_cache_data_dir).c_str());
00091   rmdir(std::string(_session_dir + "/" + _jobid).c_str());
00092   rmdir(std::string(_session_dir).c_str());
00093   rmdir(std::string(_cache_job_dir + "/" + _jobid).c_str());
00094   rmdir(std::string(_cache_job_dir).c_str());
00095   rmdir(std::string(_cache_dir).c_str());
00096 
00097   _url = "rls://rls1.ndgf.org/file1";
00098   _uid = getuid();
00099   _gid = getgid();
00100   _jobid = "1";
00101   _fc1 = new Arc::FileCache(_cache_dir, _jobid, _uid, _gid);
00102 }
00103 
00104 void FileCacheTest::tearDown() {
00105   // delete all possible files that might have been created
00106   for (std::list<std::string>::iterator i = _files.begin(); i != _files.end(); ++i)
00107     remove((char*)(*i).c_str());
00108   _files.clear();
00109 
00110   // remove directories that have been created
00111   rmdir(std::string(_cache_data_dir + "/69").c_str());
00112   rmdir(std::string(_cache_data_dir).c_str());
00113   rmdir(std::string(_session_dir + "/" + _jobid).c_str());
00114   rmdir(std::string(_session_dir).c_str());
00115   rmdir(std::string(_cache_job_dir + "/" + _jobid).c_str());
00116   rmdir(std::string(_cache_job_dir).c_str());
00117   rmdir(std::string(_cache_dir).c_str());
00118 
00119   delete _fc1;
00120 }
00121 
00122 void FileCacheTest::testStart() {
00123 
00124   // test that the cache Starts ok
00125   bool available = false;
00126   bool is_locked = false;
00127   CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked));
00128   _files.push_back(_fc1->File(_url) + ".meta");
00129   _files.push_back(_fc1->File(_url) + ".lock");
00130 
00131   // test cache is ok
00132   CPPUNIT_ASSERT(*_fc1);
00133   CPPUNIT_ASSERT(!available);
00134   CPPUNIT_ASSERT(!is_locked);
00135 
00136   // test cache file is locked
00137   std::string lock_file(_fc1->File(_url) + ".lock");
00138   struct stat fileStat;
00139   CPPUNIT_ASSERT_EQUAL_MESSAGE("Could not stat lock file " + lock_file, 0, stat(lock_file.c_str(), &fileStat));
00140 
00141   // test meta file exists and contains correct url
00142   std::string meta_file(_fc1->File(_url) + ".meta");
00143   CPPUNIT_ASSERT_EQUAL_MESSAGE("Could not stat meta file " + meta_file, 0, stat(meta_file.c_str(), &fileStat));
00144   std::string meta_url = _readFile(meta_file);
00145   CPPUNIT_ASSERT(meta_url != "");
00146   CPPUNIT_ASSERT_EQUAL(std::string(_url) + '\n', meta_url);
00147 
00148   // test calling Start() again is ok
00149   // waits for timeout so takes long time
00150   //CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked));
00151   //CPPUNIT_ASSERT(*_fc1);
00152   //CPPUNIT_ASSERT(!available);
00153 
00154   // look at modification time - should not be more than 1 second old
00155   CPPUNIT_ASSERT_EQUAL_MESSAGE("Could not stat lock file " + lock_file, 0, stat(lock_file.c_str(), &fileStat));
00156   time_t mod_time = fileStat.st_mtime;
00157   time_t now = time(NULL);
00158   CPPUNIT_ASSERT((now - mod_time) <= 1);
00159 
00160   // check it has the right pid inside
00161   std::string lock_pid = _readFile(lock_file);
00162   CPPUNIT_ASSERT(lock_pid != "");
00163 
00164   // construct hostname
00165   struct utsname buf;
00166   CPPUNIT_ASSERT_EQUAL(uname(&buf), 0);
00167   std::string host(buf.nodename);
00168 
00169   CPPUNIT_ASSERT_EQUAL(_intToString(getpid()) + "@" + host, lock_pid);
00170 
00171   // set old modification time
00172   struct utimbuf times;
00173   time_t t = 1;
00174   times.actime = t;
00175   times.modtime = t;
00176   CPPUNIT_ASSERT_EQUAL(0, utime(lock_file.c_str(), &times));
00177   CPPUNIT_ASSERT_EQUAL_MESSAGE("Could not stat lock file " + lock_file, 0, stat(lock_file.c_str(), &fileStat));
00178   CPPUNIT_ASSERT_EQUAL(t, fileStat.st_mtime);
00179 
00180   // call Start again - should succeed and make new lock file
00181   CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked));
00182   CPPUNIT_ASSERT(*_fc1);
00183   CPPUNIT_ASSERT(!available);
00184   CPPUNIT_ASSERT(!is_locked);
00185 
00186   // look at modification time - should not be more than 1 second old
00187   CPPUNIT_ASSERT_EQUAL_MESSAGE("Could not stat lock file " + lock_file, 0, stat(lock_file.c_str(), &fileStat));
00188   mod_time = fileStat.st_mtime;
00189   now = time(NULL);
00190   CPPUNIT_ASSERT((now - mod_time) <= 1);
00191 
00192   // create a cache file
00193   _createFile(_fc1->File(_url));
00194 
00195   // Stop cache
00196   CPPUNIT_ASSERT(_fc1->Stop(_url));
00197   // check lock is released
00198   CPPUNIT_ASSERT(stat(lock_file.c_str(), &fileStat) != 0);
00199   // check meta file is still there
00200   CPPUNIT_ASSERT_EQUAL_MESSAGE("Could not stat meta file " + meta_file, 0, stat(meta_file.c_str(), &fileStat));
00201 
00202   // call Start again and check available is true
00203   CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked));
00204   CPPUNIT_ASSERT(*_fc1);
00205   CPPUNIT_ASSERT(available);
00206   CPPUNIT_ASSERT(_fc1->Stop(_url));
00207 
00208   // lock the file with a pid which is still running on this host and check is_locked
00209   _createFile(_fc1->File(_url) + ".lock", "1@" + host);
00210   CPPUNIT_ASSERT(!_fc1->Start(_url, available, is_locked));
00211   CPPUNIT_ASSERT(!available);
00212   CPPUNIT_ASSERT(is_locked);
00213 
00214   // lock with process on different host
00215   is_locked = false;
00216   _createFile(_fc1->File(_url) + ".lock", "1@mybadhost.org");
00217   CPPUNIT_ASSERT(!_fc1->Start(_url, available, is_locked));
00218   CPPUNIT_ASSERT(!available);
00219   CPPUNIT_ASSERT(is_locked);
00220 
00221   // delete lock file and try again with a non-existent pid
00222   CPPUNIT_ASSERT_EQUAL(0, remove(std::string(_fc1->File(_url) + ".lock").c_str()));
00223   _createFile(_fc1->File(_url) + ".lock", "99999@" + host);
00224   CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked));
00225   CPPUNIT_ASSERT(!available);
00226   CPPUNIT_ASSERT(!is_locked);
00227 
00228   // Stop cache
00229   CPPUNIT_ASSERT(_fc1->Stop(_url));
00230 
00231   // put different url in meta file
00232   _createFile(_fc1->File(_url) + ".meta", "http://badfile 1234567890");
00233   CPPUNIT_ASSERT(!_fc1->Start(_url, available, is_locked));
00234   _createFile(_fc1->File(_url) + ".meta", "rls://rls1.ndgf.org/file1.bad");
00235   CPPUNIT_ASSERT(!_fc1->Start(_url, available, is_locked));
00236   CPPUNIT_ASSERT_EQUAL(0, remove(std::string(_fc1->File(_url)+".meta").c_str()));
00237 
00238 }
00239 
00240 void FileCacheTest::testRemoteCache() {
00241   
00242   // test with remote cache
00243   std::vector<std::string> caches;
00244   std::vector<std::string> remote_caches;
00245   std::vector<std::string> draining_caches;
00246   
00247   caches.push_back(_cache_dir);
00248   std::string remote_cache_dir = "/tmp/"+_intToString(getpid())+"_remotecache";
00249   remote_caches.push_back(remote_cache_dir);
00250   delete _fc1;
00251   _fc1 = new Arc::FileCache(caches, remote_caches, draining_caches, _jobid, _uid, _gid);
00252 
00253   // file is not available
00254   bool available, is_locked;
00255   CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked));
00256   CPPUNIT_ASSERT(!available);
00257   CPPUNIT_ASSERT(!is_locked);
00258   CPPUNIT_ASSERT(_fc1->Stop(_url));
00259   
00260   // create a cache file
00261   CPPUNIT_ASSERT(_createFile(_fc1->File(_url)));
00262   
00263   // should be available
00264   CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked));
00265   CPPUNIT_ASSERT(available);
00266   CPPUNIT_ASSERT(!is_locked);
00267   
00268   // delete file and create in remote cache
00269   CPPUNIT_ASSERT(_fc1->StopAndDelete(_url));
00270   CPPUNIT_ASSERT(_createFile(remote_cache_dir+"/data/69/59dbaef4f0a0d9aa84368e01a35a78abf267ac"));
00271   _files.push_back(remote_cache_dir+"/data/69/59dbaef4f0a0d9aa84368e01a35a78abf267ac");
00272   _files.push_back(remote_cache_dir+"/data/69");
00273   _files.push_back(remote_cache_dir+"/data");
00274   
00275   // check not available if not using remote caches
00276   CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked, false));
00277   CPPUNIT_ASSERT(!available);
00278   CPPUNIT_ASSERT(!is_locked);
00279   CPPUNIT_ASSERT(_fc1->Stop(_url));
00280   
00281   // check available when remote caches are enabled
00282   CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked, true));
00283   CPPUNIT_ASSERT(available);
00284   CPPUNIT_ASSERT(!is_locked);
00285   struct stat fileStat; 
00286   CPPUNIT_ASSERT_EQUAL_MESSAGE("Could not stat remote lock file", 0, stat(std::string(remote_cache_dir+"/data/69/59dbaef4f0a0d9aa84368e01a35a78abf267ac.lock").c_str(), &fileStat) );
00287 
00288   // check a symlink was created
00289   CPPUNIT_ASSERT_EQUAL_MESSAGE( "Could not stat soft link "+_fc1->File(_url), 0, lstat( _fc1->File(_url).c_str(), &fileStat) );
00290   // check our soft link links to yet another link
00291   CPPUNIT_ASSERT(S_ISLNK(fileStat.st_mode));
00292   // check the target is correct
00293   CPPUNIT_ASSERT_EQUAL_MESSAGE( "Could not stat target of soft link "+_fc1->File(_url), 0, stat( _fc1->File(_url).c_str(), &fileStat) );
00294 
00295   // call link and check it was created in the remote cache
00296   std::string soft_link = _session_dir+"/"+_jobid+"/file1";
00297   std::string local_hard_link = _cache_job_dir+"/"+_jobid+"/file1";
00298   CPPUNIT_ASSERT(_fc1->Link(soft_link, _url));
00299   _files.push_back(soft_link);
00300   _files.push_back(local_hard_link);
00301   _files.push_back(remote_cache_dir+"/joblinks/1/file1");
00302   _files.push_back(remote_cache_dir+"/joblinks/1");
00303   _files.push_back(remote_cache_dir+"/joblinks");
00304   _files.push_back(remote_cache_dir);
00305 
00306   CPPUNIT_ASSERT_EQUAL_MESSAGE( "Could not stat remote hard link ", 0, stat((remote_cache_dir+"/joblinks/1/file1").c_str(), &fileStat) );
00307   CPPUNIT_ASSERT_EQUAL_MESSAGE( "Hard link is a soft link", true, (lstat((remote_cache_dir+"/joblinks/1/file1").c_str(), &fileStat) == 0 && !S_ISLNK(fileStat.st_mode)));  
00308   CPPUNIT_ASSERT(stat( local_hard_link.c_str(), &fileStat) != 0 );
00309 
00310   // stop cache to release locks and remove symlink
00311   CPPUNIT_ASSERT(_fc1->Stop(_url));
00312   CPPUNIT_ASSERT(stat( _fc1->File(_url).c_str(), &fileStat) != 0 );
00313   CPPUNIT_ASSERT(stat(std::string(remote_cache_dir+"/data/69/59dbaef4f0a0d9aa84368e01a35a78abf267ac.lock").c_str(), &fileStat) != 0 );
00314   CPPUNIT_ASSERT(stat((_fc1->File(_url)+".lock").c_str(), &fileStat) != 0 );
00315   
00316   // release
00317   CPPUNIT_ASSERT(_fc1->Release());
00318   CPPUNIT_ASSERT(stat(std::string(remote_cache_dir+"/joblinks/1/file1").c_str(), &fileStat) != 0 );
00319   CPPUNIT_ASSERT(stat(std::string(remote_cache_dir+"/joblinks/1").c_str(), &fileStat) != 0 );
00320   
00321   // test with a replicate policy
00322   delete _fc1;
00323   remote_cache_dir = "/tmp/"+_intToString(getpid())+"_remotecache replicate";
00324   remote_caches.clear();
00325   remote_caches.push_back(remote_cache_dir);
00326   _fc1 = new Arc::FileCache(caches, remote_caches, draining_caches, _jobid, _uid, _gid);
00327   CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked));
00328   CPPUNIT_ASSERT(available);
00329   CPPUNIT_ASSERT(!is_locked);
00330   CPPUNIT_ASSERT_EQUAL_MESSAGE( "Could not stat file "+_fc1->File(_url), 0, stat( _fc1->File(_url).c_str(), &fileStat) );
00331   // check it is a copy and not a symlink
00332   CPPUNIT_ASSERT(!S_ISLNK(fileStat.st_mode));
00333   CPPUNIT_ASSERT(_fc1->Stop(_url));
00334 }
00335 
00336 void FileCacheTest::testStop() {
00337 
00338   // Start cache
00339   bool available = false;
00340   bool is_locked = false;
00341   CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked));
00342   _files.push_back(_fc1->File(_url) + ".meta");
00343   _files.push_back(_fc1->File(_url) + ".lock");
00344 
00345   // test cache is ok
00346   CPPUNIT_ASSERT(*_fc1);
00347   CPPUNIT_ASSERT(!available);
00348   CPPUNIT_ASSERT(!is_locked);
00349 
00350   // Stop cache with non-existent cache file - this is ok
00351   CPPUNIT_ASSERT(_fc1->Stop(_url));
00352   // check lock is released
00353   std::string lock_file(_fc1->File(_url) + ".lock");
00354   struct stat fileStat;
00355   CPPUNIT_ASSERT(stat(lock_file.c_str(), &fileStat) != 0);
00356 
00357   // Start again to create a new lock
00358   CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked));
00359 
00360   // test cache is ok
00361   CPPUNIT_ASSERT(*_fc1);
00362   CPPUNIT_ASSERT(!available);
00363 
00364   // create the cache file
00365   _createFile(_fc1->File(_url));
00366   // Stop cache
00367   CPPUNIT_ASSERT(_fc1->Stop(_url));
00368 
00369   // check lock is released
00370   CPPUNIT_ASSERT(stat(lock_file.c_str(), &fileStat) != 0);
00371 
00372   // check cache file is still there
00373   CPPUNIT_ASSERT_EQUAL_MESSAGE("Could not stat cache file " + _fc1->File(_url), 0, stat(_fc1->File(_url).c_str(), &fileStat));
00374 
00375   // check meta file is still there with correct url
00376   std::string meta_file(_fc1->File(_url) + ".meta");
00377   CPPUNIT_ASSERT_EQUAL_MESSAGE("Could not stat meta file " + meta_file, 0, stat(meta_file.c_str(), &fileStat));
00378   std::string meta_url = _readFile(meta_file);
00379   CPPUNIT_ASSERT(meta_url != "");
00380   CPPUNIT_ASSERT_EQUAL(std::string(_url) + '\n', meta_url);
00381 
00382   // call with non-existent lock file
00383   CPPUNIT_ASSERT(!_fc1->Stop(_url));
00384 
00385   // put different pid in lock file - Stop() should return false
00386   _createFile(_fc1->File(_url) + ".lock", _intToString(getpid() + 1));
00387   CPPUNIT_ASSERT(!_fc1->Stop(_url));
00388 
00389   // check that lock and cache file are still there
00390   CPPUNIT_ASSERT(stat(_fc1->File(_url).c_str(), &fileStat) == 0);
00391   CPPUNIT_ASSERT(stat((_fc1->File(_url) + ".lock").c_str(), &fileStat) == 0);
00392 
00393   // check meta file is still there
00394   CPPUNIT_ASSERT_EQUAL_MESSAGE("Could not stat meta file " + meta_file, 0, stat(meta_file.c_str(), &fileStat));
00395 }
00396 
00397 void FileCacheTest::testStopAndDelete() {
00398 
00399   // Start cache
00400   bool available = false;
00401   bool is_locked = false;
00402   CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked));
00403   _files.push_back(_fc1->File(_url) + ".meta");
00404   _files.push_back(_fc1->File(_url) + ".lock");
00405 
00406   // test cache is ok
00407   CPPUNIT_ASSERT(*_fc1);
00408   CPPUNIT_ASSERT(!available);
00409   CPPUNIT_ASSERT(!is_locked);
00410 
00411   // Stop and delete cache file with non-existent cache file
00412   CPPUNIT_ASSERT(_fc1->StopAndDelete(_url));
00413   // check lock is released
00414   std::string lock_file(_fc1->File(_url) + ".lock");
00415   struct stat fileStat;
00416   CPPUNIT_ASSERT(stat(lock_file.c_str(), &fileStat) != 0);
00417 
00418   // check meta file is deleted
00419   std::string meta_file(_fc1->File(_url) + ".meta");
00420   CPPUNIT_ASSERT(stat(meta_file.c_str(), &fileStat) != 0);
00421 
00422   // Start again to create a new lock
00423   CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked));
00424 
00425   // test cache is ok
00426   CPPUNIT_ASSERT(*_fc1);
00427   CPPUNIT_ASSERT(!available);
00428 
00429   // create the cache file
00430   CPPUNIT_ASSERT(_createFile(_fc1->File(_url)));
00431   // check cache file is there
00432   CPPUNIT_ASSERT_EQUAL_MESSAGE("Could not stat cache file " + _fc1->File(_url), 0, stat(_fc1->File(_url).c_str(), &fileStat));
00433 
00434   // Stop cache and delete file
00435   CPPUNIT_ASSERT(_fc1->StopAndDelete(_url));
00436 
00437   // check lock is released
00438   CPPUNIT_ASSERT(stat(lock_file.c_str(), &fileStat) != 0);
00439 
00440   // check cache file has gone
00441   CPPUNIT_ASSERT(stat(_fc1->File(_url).c_str(), &fileStat) != 0);
00442 
00443   // check meta file is deleted
00444   CPPUNIT_ASSERT(stat(meta_file.c_str(), &fileStat) != 0);
00445 
00446   // create the cache file
00447   CPPUNIT_ASSERT(_createFile(_fc1->File(_url)));
00448 
00449   // call with non-existent lock file
00450   CPPUNIT_ASSERT(!_fc1->StopAndDelete(_url));
00451 
00452   // check the cache file is still there
00453   CPPUNIT_ASSERT(stat(_fc1->File(_url).c_str(), &fileStat) == 0);
00454 
00455   // put different pid in lock file - StopAndDelete() should return false
00456   _createFile(_fc1->File(_url) + ".lock", _intToString(getpid() + 1));
00457   CPPUNIT_ASSERT(!_fc1->StopAndDelete(_url));
00458 
00459   // check that lock and cache files are still there
00460   CPPUNIT_ASSERT(stat(_fc1->File(_url).c_str(), &fileStat) == 0);
00461   CPPUNIT_ASSERT(stat((_fc1->File(_url) + ".lock").c_str(), &fileStat) == 0);
00462 
00463 }
00464 
00465 void FileCacheTest::testLinkFile() {
00466 
00467   std::string soft_link = _session_dir + "/" + _jobid + "/file1";
00468   std::string hard_link = _cache_job_dir + "/" + _jobid + "/file1";
00469   // link non-existent file
00470   CPPUNIT_ASSERT(!_fc1->Link(soft_link, _url));
00471 
00472   // Start cache
00473   bool available = false;
00474   bool is_locked = false;
00475   CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked));
00476   _files.push_back(_fc1->File(_url) + ".meta");
00477   _files.push_back(_fc1->File(_url) + ".lock");
00478 
00479   // test cache is ok
00480   CPPUNIT_ASSERT(*_fc1);
00481   CPPUNIT_ASSERT(!available);
00482   CPPUNIT_ASSERT(!is_locked);
00483 
00484   // create cache file
00485   CPPUNIT_ASSERT(_createFile(_fc1->File(_url)));
00486 
00487   // check cache file is there
00488   struct stat fileStat;
00489   CPPUNIT_ASSERT_EQUAL_MESSAGE("Could not stat cache file " + _fc1->File(_url), 0, stat(_fc1->File(_url).c_str(), &fileStat));
00490 
00491   // create link
00492   CPPUNIT_ASSERT(_fc1->Link(soft_link, _url));
00493   _files.push_back(hard_link);
00494   _files.push_back(soft_link);
00495 
00496   // check hard- and soft-links exist
00497   CPPUNIT_ASSERT(stat((_cache_job_dir + "/1").c_str(), &fileStat) == 0);
00498   CPPUNIT_ASSERT((fileStat.st_mode & S_IRWXU) == S_IRWXU);
00499   CPPUNIT_ASSERT_EQUAL_MESSAGE("Could not stat hard link " + hard_link, 0, stat(hard_link.c_str(), &fileStat));
00500   CPPUNIT_ASSERT_EQUAL_MESSAGE("Could not stat soft link " + soft_link, 0, stat(soft_link.c_str(), &fileStat));
00501 
00502   // create bad soft-link
00503   if (_uid != 0 && stat("/lost+found/sessiondir", &fileStat) != 0 && errno == EACCES)
00504     CPPUNIT_ASSERT(!_fc1->Link("/lost_found/sessiondir/file1", _url));
00505 
00506   // Stop cache to release lock
00507   CPPUNIT_ASSERT(_fc1->Stop(_url));
00508 }
00509 
00510 void FileCacheTest::testLinkFileLinkCache() {
00511 
00512   // new cache with link path set
00513   std::string cache_link_dir = "/tmp/" + _intToString(getpid()) + "_link";
00514   _fc1 = new Arc::FileCache(_cache_dir + " " + cache_link_dir, _jobid, _uid, _gid);
00515   CPPUNIT_ASSERT(symlink(_cache_dir.c_str(), cache_link_dir.c_str()) == 0);
00516   _files.push_back(cache_link_dir);
00517   _files.push_back(_fc1->File(_url) + ".lock");
00518 
00519   // Start cache
00520   bool available = false;
00521   bool is_locked = false;
00522   CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked));
00523   // test cache is ok
00524   CPPUNIT_ASSERT(*_fc1);
00525   CPPUNIT_ASSERT(!available);
00526   CPPUNIT_ASSERT(!is_locked);
00527 
00528   // create cache file
00529   CPPUNIT_ASSERT(_createFile(_fc1->File(_url)));
00530 
00531   // check cache file is there
00532   struct stat fileStat;
00533   CPPUNIT_ASSERT_EQUAL_MESSAGE("Could not stat cache file " + _fc1->File(_url), 0, stat(_fc1->File(_url).c_str(), &fileStat));
00534 
00535   // create link
00536   std::string soft_link = _session_dir + "/" + _jobid + "/file1";
00537   std::string hard_link = _cache_job_dir + "/" + _jobid + "/file1";
00538   CPPUNIT_ASSERT(_fc1->Link(soft_link, _url));
00539   _files.push_back(soft_link);
00540   _files.push_back(hard_link);
00541 
00542   // check soft link is ok and points to the right place
00543   CPPUNIT_ASSERT_EQUAL_MESSAGE("Could not stat soft link " + soft_link, 0, lstat(soft_link.c_str(), &fileStat));
00544   // check our soft link links to yet another link
00545   CPPUNIT_ASSERT(S_ISLNK(fileStat.st_mode));
00546   // check the target is correct
00547   CPPUNIT_ASSERT_EQUAL_MESSAGE("Could not stat target of soft link " + soft_link, 0, stat(soft_link.c_str(), &fileStat));
00548 
00549   // Stop cache to release lock
00550   CPPUNIT_ASSERT(_fc1->Stop(_url));
00551 }
00552 
00553 void FileCacheTest::testCopyFile() {
00554 
00555   std::string dest_file = _session_dir + "/" + _jobid + "/file1";
00556 
00557   // copy non-existent file
00558   CPPUNIT_ASSERT(!_fc1->Copy(dest_file, _url));
00559 
00560   // Start cache
00561   bool available = false;
00562   bool is_locked = false;
00563   CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked));
00564   _files.push_back(_fc1->File(_url) + ".meta");
00565   _files.push_back(_fc1->File(_url) + ".lock");
00566 
00567   // test cache is ok
00568   CPPUNIT_ASSERT(*_fc1);
00569   CPPUNIT_ASSERT(!available);
00570   CPPUNIT_ASSERT(!is_locked);
00571 
00572   // create cache file
00573   CPPUNIT_ASSERT(_createFile(_fc1->File(_url)));
00574 
00575   // check cache file is there
00576   struct stat fileStat;
00577   CPPUNIT_ASSERT_EQUAL_MESSAGE("Could not stat cache file " + _fc1->File(_url), 0, stat(_fc1->File(_url).c_str(), &fileStat));
00578 
00579   // do copy
00580   CPPUNIT_ASSERT(_fc1->Copy(dest_file, _url));
00581   _files.push_back(dest_file);
00582 
00583   // check copy exists
00584   CPPUNIT_ASSERT_EQUAL_MESSAGE("Could not stat destination file " + dest_file, 0, stat(dest_file.c_str(), &fileStat));
00585 
00586   // create bad copy
00587   if (_uid != 0 && stat("/lost+found/sessiondir", &fileStat) != 0 && errno == EACCES)
00588     CPPUNIT_ASSERT(!_fc1->Copy("/lost_found/sessiondir/file1", _url));
00589 
00590   // Stop cache to release lock
00591   CPPUNIT_ASSERT(_fc1->Stop(_url));
00592 }
00593 
00594 void FileCacheTest::testFile() {
00595   // test hash returned
00596   std::string hash = "/69/59dbaef4f0a0d9aa84368e01a35a78abf267ac";
00597   CPPUNIT_ASSERT_EQUAL(std::string(_cache_data_dir + hash), _fc1->File(_url));
00598 
00599   // set up two caches
00600   std::vector<std::string> caches;
00601   caches.push_back(_cache_dir);
00602   std::string cache_dir2 = _cache_dir + "2";
00603   caches.push_back(cache_dir2);
00604 
00605   _files.push_back(cache_dir2 + "/joblinks");
00606   _files.push_back(cache_dir2 + "/data");
00607   _files.push_back(cache_dir2);
00608 
00609   Arc::FileCache *fc2 = new Arc::FileCache(caches, "1", _uid, _gid);
00610   // _url can go to either cache, so check it at least is mapped to one
00611   bool found = false;
00612   if (fc2->File(_url) == std::string(_cache_data_dir + hash))
00613     found = true;
00614   if (fc2->File(_url) == std::string(cache_dir2 + "/data" + hash))
00615     found = true;
00616   
00617   CPPUNIT_ASSERT(found);
00618   delete fc2;
00619 }
00620 
00621 void FileCacheTest::testRelease() {
00622 
00623   // create cache and link
00624   std::string soft_link = _session_dir + "/" + _jobid + "/file1";
00625   std::string hard_link = _cache_job_dir + "/" + _jobid + "/file1";
00626   bool available = false;
00627   bool is_locked = false;
00628   CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked));
00629   _files.push_back(_fc1->File(_url) + ".meta");
00630   _files.push_back(_fc1->File(_url) + ".lock");
00631 
00632   // test cache is ok
00633   CPPUNIT_ASSERT(*_fc1);
00634   CPPUNIT_ASSERT(!available);
00635   CPPUNIT_ASSERT(!is_locked);
00636 
00637   // create cache file
00638   CPPUNIT_ASSERT(_createFile(_fc1->File(_url)));
00639 
00640   // create link
00641   CPPUNIT_ASSERT(_fc1->Link(soft_link, _url));
00642   _files.push_back(hard_link);
00643   _files.push_back(soft_link);
00644 
00645   // Stop cache to release lock
00646   CPPUNIT_ASSERT(_fc1->Stop(_url));
00647 
00648   // release
00649   CPPUNIT_ASSERT(_fc1->Release());
00650 
00651   // check files and dir are gone
00652   struct stat fileStat;
00653   CPPUNIT_ASSERT(stat(hard_link.c_str(), &fileStat) != 0);
00654   CPPUNIT_ASSERT(stat(std::string(_cache_job_dir + "/" + _jobid).c_str(), &fileStat) != 0);
00655 
00656   // copy file
00657   CPPUNIT_ASSERT_EQUAL(0, remove(soft_link.c_str()));
00658   CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked));
00659   CPPUNIT_ASSERT(_fc1->Copy(soft_link, _url));
00660 
00661   // check job dir is not created
00662   CPPUNIT_ASSERT(stat(std::string(_cache_job_dir + "/" + _jobid).c_str(), &fileStat) != 0);
00663 
00664   // release should not give an error, even though job dir does not exist
00665   CPPUNIT_ASSERT(_fc1->Release());
00666 }
00667 
00668 void FileCacheTest::testCheckDN() {
00669 
00670   CPPUNIT_ASSERT(!_fc1->AddDN(_url, "", Arc::Time()));
00671   CPPUNIT_ASSERT(!_fc1->CheckDN(_url, ""));
00672 
00673   // create meta file
00674   std::string meta_file = _fc1->File(_url) + ".meta";
00675   CPPUNIT_ASSERT(_createFile(meta_file, _url + '\n'));
00676   _files.push_back(meta_file);
00677 
00678   std::string dn1 = "/O=Grid/O=NorduGrid/OU=test.org/CN=Mr Tester";
00679   CPPUNIT_ASSERT(!_fc1->CheckDN(_url, dn1));
00680 
00681   // add DN
00682   Arc::Time now = Arc::Time();
00683   Arc::Time futuretime = Arc::Time(time(NULL) + 1000);
00684   CPPUNIT_ASSERT(_fc1->AddDN(_url, dn1, futuretime));
00685   CPPUNIT_ASSERT(_fc1->CheckDN(_url, dn1));
00686   CPPUNIT_ASSERT_EQUAL(_url + "\n" + dn1 + " " + futuretime.str(Arc::MDSTime) + '\n', _readFile(meta_file));
00687 
00688   // expired DN
00689   Arc::Time pasttime = Arc::Time(time(NULL) - 10);
00690   CPPUNIT_ASSERT(_createFile(meta_file, _url + "\n" + dn1 + " " + pasttime.str(Arc::MDSTime) + '\n'));
00691   CPPUNIT_ASSERT(!_fc1->CheckDN(_url, dn1));
00692 
00693   // add again
00694   futuretime = Arc::Time(time(NULL) + 86400);
00695   CPPUNIT_ASSERT(_fc1->AddDN(_url, dn1, futuretime));
00696   CPPUNIT_ASSERT(_fc1->CheckDN(_url, dn1));
00697   CPPUNIT_ASSERT_EQUAL(_url + "\n" + dn1 + " " + futuretime.str(Arc::MDSTime) + '\n', _readFile(meta_file));
00698 
00699   // add another DN
00700   std::string dn2 = "/O=Grid/O=NorduGrid/OU=test.org/CN=Mrs Tester";
00701   CPPUNIT_ASSERT(!_fc1->CheckDN(_url, dn2));
00702 
00703   CPPUNIT_ASSERT(_fc1->AddDN(_url, dn2, futuretime));
00704   CPPUNIT_ASSERT(_fc1->CheckDN(_url, dn1));
00705   CPPUNIT_ASSERT(_fc1->CheckDN(_url, dn2));
00706   CPPUNIT_ASSERT_EQUAL(_url + "\n" + dn2 + " " + futuretime.str(Arc::MDSTime) + "\n" + dn1 + " " + futuretime.str(Arc::MDSTime) + '\n', _readFile(meta_file));
00707 
00708   // create expired DN and check it gets removed
00709   pasttime = Arc::Time(time(NULL) - 86401);
00710   CPPUNIT_ASSERT(_createFile(meta_file, _url + '\n' + dn2 + " " + pasttime.str(Arc::MDSTime) + "\n" + dn1 + " " + pasttime.str(Arc::MDSTime) + '\n'));
00711   CPPUNIT_ASSERT(_fc1->AddDN(_url, dn1, futuretime));
00712   CPPUNIT_ASSERT(_fc1->CheckDN(_url, dn1));
00713   CPPUNIT_ASSERT_EQUAL(_url + "\n" + dn1 + " " + futuretime.str(Arc::MDSTime) + '\n', _readFile(meta_file));
00714 
00715   // add with no specified expiry time
00716   CPPUNIT_ASSERT(_fc1->AddDN(_url, dn2, Arc::Time(0)));
00717   CPPUNIT_ASSERT_EQUAL(_url + "\n" + dn2 + " " + futuretime.str(Arc::MDSTime) + "\n" + dn1 + " " + futuretime.str(Arc::MDSTime) + '\n', _readFile(meta_file));
00718 }
00719 
00720 void FileCacheTest::testTwoCaches() {
00721 
00722   // set up two caches
00723   std::vector<std::string> caches;
00724   caches.push_back(_cache_dir);
00725   std::string cache_dir2 = _cache_dir + "2";
00726   caches.push_back(cache_dir2);
00727 
00728   std::string url2 = "rls://rls1.ndgf.org/file2";
00729 
00730   Arc::FileCache *fc2 = new Arc::FileCache(caches, "1", _uid, _gid);
00731   // create cache
00732   bool available = false;
00733   bool is_locked = false;
00734   CPPUNIT_ASSERT(fc2->Start(_url, available, is_locked));
00735   std::string cache_file1 = fc2->File(_url);
00736   _files.push_back(fc2->File(_url) + ".meta");
00737   _files.push_back(fc2->File(_url) + ".lock");
00738 
00739   // test cache is ok
00740   CPPUNIT_ASSERT(*fc2);
00741   CPPUNIT_ASSERT(!available);
00742   CPPUNIT_ASSERT(!is_locked);
00743 
00744   bool available2 = false;
00745   bool is_locked2 = false;
00746   CPPUNIT_ASSERT(fc2->Start(url2, available2, is_locked2));
00747   std::string cache_file2 = fc2->File(url2);
00748   _files.push_back(fc2->File(url2) + ".meta");
00749   _files.push_back(fc2->File(url2) + ".lock");
00750 
00751   // test cache is ok
00752   CPPUNIT_ASSERT(!available2);
00753   CPPUNIT_ASSERT(!is_locked2);
00754 
00755   // create cache files
00756   CPPUNIT_ASSERT(_createFile(cache_file1));
00757   CPPUNIT_ASSERT(_createFile(cache_file2));
00758 
00759   // create links
00760   std::string soft_link = _session_dir + "/" + _jobid + "/file1";
00761   std::string soft_link2 = _session_dir + "/" + _jobid + "/file2";
00762   
00763   // we expect the hard links to be made to here
00764   std::string hard_link_cache1 = _cache_job_dir + "/" + _jobid + "/file1";
00765   std::string hard_link_cache2 = cache_dir2 + "/joblinks/" + _jobid + "/file1";
00766   std::string hard_link2_cache1 = _cache_job_dir + "/" + _jobid + "/file2";
00767   std::string hard_link2_cache2 = cache_dir2 + "/joblinks/" + _jobid + "/file2";
00768 
00769   CPPUNIT_ASSERT(fc2->Link(soft_link, _url));
00770   CPPUNIT_ASSERT(fc2->Link(soft_link2, url2));
00771   _files.push_back(hard_link_cache1);
00772   _files.push_back(hard_link_cache2);
00773   _files.push_back(hard_link2_cache1);
00774   _files.push_back(hard_link2_cache2);
00775   _files.push_back(soft_link);
00776   _files.push_back(soft_link2);
00777   _files.push_back(cache_dir2 + "/data/11");
00778   _files.push_back(cache_dir2 + "/data/69");
00779   _files.push_back(cache_dir2 + "/data");
00780   _files.push_back(cache_dir2 + "/joblinks/1");
00781   _files.push_back(cache_dir2 + "/joblinks");
00782   _files.push_back(cache_dir2);
00783 
00784   // check hard links are made in one of the caches
00785   struct stat fileStat;
00786   CPPUNIT_ASSERT(stat(hard_link_cache1.c_str(), &fileStat) == 0 || stat(hard_link_cache2.c_str(), &fileStat) == 0);
00787   CPPUNIT_ASSERT(stat(hard_link2_cache1.c_str(), &fileStat) == 0 || stat(hard_link2_cache2.c_str(), &fileStat) == 0);
00788 
00789 
00790   // Stop caches to release locks
00791   CPPUNIT_ASSERT(fc2->Stop(_url));
00792   CPPUNIT_ASSERT(fc2->Stop(url2));
00793 
00794   // release with correct IDs
00795   CPPUNIT_ASSERT(fc2->Release());
00796 
00797   // check links and job dir are gone
00798   CPPUNIT_ASSERT(stat(hard_link_cache1.c_str(), &fileStat) != 0 && stat(hard_link_cache2.c_str(), &fileStat) != 0);
00799   CPPUNIT_ASSERT(stat(hard_link2_cache1.c_str(), &fileStat) != 0 && stat(hard_link2_cache2.c_str(), &fileStat) != 0);
00800 
00801   CPPUNIT_ASSERT(stat(std::string(_cache_job_dir + "/" + _jobid).c_str(), &fileStat) != 0);
00802   CPPUNIT_ASSERT(stat(std::string(cache_dir2 + "/joblinks/" + _jobid).c_str(), &fileStat) != 0);
00803 
00804   // copy file
00805   CPPUNIT_ASSERT_EQUAL(0, remove(soft_link.c_str()));
00806   CPPUNIT_ASSERT(fc2->Start(_url, available, is_locked));
00807   CPPUNIT_ASSERT(fc2->Copy(soft_link, _url));
00808 
00809   // check job dir is not created
00810   CPPUNIT_ASSERT(stat(std::string(_cache_job_dir + "/" + _jobid).c_str(), &fileStat) != 0);
00811   CPPUNIT_ASSERT(stat(std::string(cache_dir2 + "/joblinks/" + _jobid).c_str(), &fileStat) != 0);
00812 
00813   // release should not give an error, even though job dir does not exist
00814   CPPUNIT_ASSERT(fc2->Release());
00815 }
00816 
00817 void FileCacheTest::testCreationDate() {
00818 
00819   // call with non-existent file
00820   CPPUNIT_ASSERT(!_fc1->CheckCreated(_url));
00821   CPPUNIT_ASSERT_EQUAL(0, (int)(_fc1->GetCreated(_url).GetTime()));
00822 
00823   // Start cache and add file
00824   bool available = false;
00825   bool is_locked = false;
00826   CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked));
00827   _files.push_back(_fc1->File(_url) + ".meta");
00828   _files.push_back(_fc1->File(_url) + ".lock");
00829 
00830   // test cache is ok
00831   CPPUNIT_ASSERT(*_fc1);
00832   CPPUNIT_ASSERT(!available);
00833   CPPUNIT_ASSERT(!is_locked);
00834 
00835   // create cache file
00836   CPPUNIT_ASSERT(_createFile(_fc1->File(_url)));
00837 
00838   // test creation date is available
00839   CPPUNIT_ASSERT(_fc1->CheckCreated(_url));
00840 
00841   // get creation date from file system
00842   struct stat fileStat;
00843   CPPUNIT_ASSERT_EQUAL_MESSAGE("Could not stat cache file " + _fc1->File(_url), 0, stat(_fc1->File(_url).c_str(), &fileStat));
00844 
00845   // test this is equal to created()
00846   CPPUNIT_ASSERT_EQUAL(fileStat.st_ctime, _fc1->GetCreated(_url).GetTime());
00847 
00848   // sleep 1 second and check dates still match
00849   sleep(1);
00850   CPPUNIT_ASSERT(fileStat.st_ctime == _fc1->GetCreated(_url).GetTime());
00851 
00852   // Stop cache to release lock
00853   CPPUNIT_ASSERT(_fc1->Stop(_url));
00854 
00855 }
00856 
00857 void FileCacheTest::testValidityDate() {
00858 
00859   // call with non-existent file
00860   CPPUNIT_ASSERT(!_fc1->CheckValid(_url));
00861   CPPUNIT_ASSERT_EQUAL(0, (int)(_fc1->GetValid(_url).GetTime()));
00862   CPPUNIT_ASSERT(!_fc1->SetValid(_url, Arc::Time(time(NULL))));
00863 
00864   // Start cache and add file
00865   bool available = false;
00866   bool is_locked = false;
00867   CPPUNIT_ASSERT(_fc1->Start(_url, available, is_locked));
00868   _files.push_back(_fc1->File(_url) + ".meta");
00869   _files.push_back(_fc1->File(_url) + ".lock");
00870 
00871   // test cache is ok
00872   CPPUNIT_ASSERT(*_fc1);
00873   CPPUNIT_ASSERT(!available);
00874   CPPUNIT_ASSERT(!is_locked);
00875 
00876   // create cache file
00877   CPPUNIT_ASSERT(_createFile(_fc1->File(_url)));
00878 
00879   // test validity date is not available
00880   CPPUNIT_ASSERT(!_fc1->CheckValid(_url));
00881 
00882   // look inside the meta file to check
00883   std::string meta_file = _fc1->File(_url) + ".meta";
00884   CPPUNIT_ASSERT_EQUAL(_url + '\n', _readFile(meta_file));
00885 
00886   // set validity time to now
00887   Arc::Time now;
00888   CPPUNIT_ASSERT(_fc1->SetValid(_url, now));
00889   CPPUNIT_ASSERT(_fc1->CheckValid(_url));
00890   CPPUNIT_ASSERT_EQUAL(now, _fc1->GetValid(_url));
00891   CPPUNIT_ASSERT_EQUAL(_url + " " + now.str(Arc::MDSTime), _readFile(meta_file));
00892 
00893   // put bad format inside metafile
00894   CPPUNIT_ASSERT(_createFile(_fc1->File(_url) + ".meta", _url + " abcd"));
00895   CPPUNIT_ASSERT_EQUAL(0, (int)(_fc1->GetValid(_url).GetTime()));
00896   CPPUNIT_ASSERT(_createFile(_fc1->File(_url) + ".meta", _url + "abc 1234567890"));
00897   CPPUNIT_ASSERT_EQUAL(0, (int)(_fc1->GetValid(_url).GetTime()));
00898   CPPUNIT_ASSERT(_createFile(_fc1->File(_url) + ".meta", _url + "abc1234567890"));
00899   CPPUNIT_ASSERT_EQUAL(0, (int)(_fc1->GetValid(_url).GetTime()));
00900   // cannot be more than MAX_INT
00901   CPPUNIT_ASSERT(_createFile(_fc1->File(_url) + ".meta", _url + " 1234567890123"));
00902   CPPUNIT_ASSERT_EQUAL(0, (int)(_fc1->GetValid(_url).GetTime()));
00903 
00904   // set new time
00905   Arc::Time newtime(time(NULL) + 10);
00906   CPPUNIT_ASSERT(_fc1->SetValid(_url, newtime));
00907   CPPUNIT_ASSERT_EQUAL(newtime, _fc1->GetValid(_url));
00908   CPPUNIT_ASSERT_EQUAL(_url + " " + newtime.str(Arc::MDSTime), _readFile(meta_file));
00909 
00910   // Stop cache to release lock
00911   CPPUNIT_ASSERT(_fc1->Stop(_url));
00912 
00913 }
00914 
00915 void FileCacheTest::testConstructor() {
00916   // permissions testing of dirs created by the constructor
00917   struct stat fileStat;
00918   CPPUNIT_ASSERT(stat(_cache_data_dir.c_str(), &fileStat) == 0);
00919   CPPUNIT_ASSERT((fileStat.st_mode & (S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH)) == (S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH));
00920   CPPUNIT_ASSERT(stat(_cache_job_dir.c_str(), &fileStat) == 0);
00921   CPPUNIT_ASSERT((fileStat.st_mode & (S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH)) == (S_IRWXU | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH));
00922   // create constructor with same parameters
00923   Arc::FileCache *fc2 = new Arc::FileCache(_cache_dir, _jobid, _uid, _gid);
00924   CPPUNIT_ASSERT(*_fc1 == *fc2);
00925   delete fc2;
00926   // test copy constructor
00927   Arc::FileCache *fc3 = new Arc::FileCache(*_fc1);
00928   CPPUNIT_ASSERT(*_fc1 == *fc3);
00929   delete fc3;
00930   // test invalid cache constructor, and that cache is not available
00931   Arc::FileCache *fc5 = new Arc::FileCache();
00932   CPPUNIT_ASSERT(!(*_fc1 == *fc5));
00933   CPPUNIT_ASSERT(!(*fc5));
00934   delete fc5;
00935 
00936   // create with 2 cache dirs
00937   std::vector<std::string> caches;
00938   std::string cache_dir2 = _cache_dir + "2";
00939   std::string cache_dir3 = _cache_dir + "3";
00940 
00941   _files.push_back(cache_dir2 + "/joblinks");
00942   _files.push_back(cache_dir2 + "/data");
00943   _files.push_back(cache_dir2);
00944   _files.push_back(cache_dir3 + "/joblinks");
00945   _files.push_back(cache_dir3 + "/data");
00946   _files.push_back(cache_dir3);
00947 
00948   caches.push_back(_cache_dir);
00949   caches.push_back(cache_dir2);
00950 
00951   Arc::FileCache *fc6 = new Arc::FileCache(caches, _jobid, _uid, _gid);
00952   CPPUNIT_ASSERT(*fc6);
00953   CPPUNIT_ASSERT(!(*_fc1 == *fc6));
00954 
00955   // create with two different caches and compare
00956   caches.empty();
00957   caches.push_back(_cache_dir);
00958   caches.push_back(cache_dir3);
00959   Arc::FileCache *fc7 = new Arc::FileCache(caches, _jobid, _uid, _gid);
00960   CPPUNIT_ASSERT(*fc7);
00961   CPPUNIT_ASSERT(!(*fc6 == *fc7));
00962 
00963   delete fc6;
00964   delete fc7;
00965 }
00966 
00967 void FileCacheTest::testBadConstructor() {
00968   // permission denied
00969   delete _fc1;
00970   struct stat fileStat;
00971   if (_uid != 0 && stat("/lost+found/cache", &fileStat) != 0 && errno == EACCES) {
00972     _fc1 = new Arc::FileCache("/lost+found/cache", _jobid, _uid, _gid);
00973     CPPUNIT_ASSERT(!(*_fc1));
00974     delete _fc1;
00975   }
00976   // no cache dir
00977   _fc1 = new Arc::FileCache("", _jobid, _uid, _gid);
00978   CPPUNIT_ASSERT(!(*_fc1));
00979   delete _fc1;
00980   // two caches, one of which is bad
00981   std::vector<std::string> caches;
00982   caches.push_back(_cache_dir);
00983   caches.push_back("");
00984   _fc1 = new Arc::FileCache(caches, _jobid, _uid, _gid);
00985   CPPUNIT_ASSERT(!(*_fc1));
00986   // call some methods
00987   bool available = false;
00988   bool is_locked = false;
00989   CPPUNIT_ASSERT(!(_fc1->Start(_url, available, is_locked)));
00990   CPPUNIT_ASSERT_EQUAL(std::string(""), _fc1->File(_url));
00991   CPPUNIT_ASSERT(!(_fc1->Stop(_url)));
00992   CPPUNIT_ASSERT(!(_fc1->StopAndDelete(_url)));
00993   CPPUNIT_ASSERT(!(_fc1->CheckCreated(_url)));
00994 }
00995 
00996 void FileCacheTest::testInternal() {
00997 
00998   // read a non-existent file
00999   std::string pid(_intToString(getpid()));
01000   std::string testfile("test.file." + pid);
01001   CPPUNIT_ASSERT(_readFile(testfile) == "");
01002 
01003   // create a file
01004   CPPUNIT_ASSERT(_createFile(testfile, pid));
01005 
01006   // check it exists
01007   struct stat fileStat;
01008   CPPUNIT_ASSERT_EQUAL(0, stat(testfile.c_str(), &fileStat));
01009 
01010   // check the contents
01011   CPPUNIT_ASSERT_EQUAL(pid, _readFile(testfile));
01012 
01013   // delete
01014   CPPUNIT_ASSERT_EQUAL(0, remove((char*)testfile.c_str()));
01015 
01016   // check it has gone
01017   CPPUNIT_ASSERT(stat(testfile.c_str(), &fileStat) != 0);
01018 }
01019 
01020 bool FileCacheTest::_createFile(std::string filename, std::string text) {
01021 
01022   FILE *pFile;
01023   pFile = fopen((char*)filename.c_str(), "w");
01024   if (pFile == NULL) {
01025     // try to create necessary dirs
01026     std::string::size_type slashpos = filename.find("/", 1);
01027     do {
01028       std::string dirname = filename.substr(0, slashpos);
01029       // list dir to see if it exists
01030       struct stat statbuf;
01031       if (stat(dirname.c_str(), &statbuf) == 0) {
01032         slashpos = filename.find("/", slashpos + 1);
01033         continue;
01034       }
01035       if (mkdir(dirname.c_str(), S_IRWXU) != 0)
01036         if (errno != EEXIST)
01037           return false;
01038       slashpos = filename.find("/", slashpos + 1);
01039     } while (slashpos != std::string::npos);
01040     pFile = fopen((char*)filename.c_str(), "w");
01041     if (pFile == NULL)
01042       return false;
01043   }
01044   fputs((char*)text.c_str(), pFile);
01045   fclose(pFile);
01046   _files.push_back(filename);
01047   return true;
01048 }
01049 
01050 std::string FileCacheTest::_readFile(std::string filename) {
01051 
01052   FILE *pFile;
01053   char mystring[1024];
01054   pFile = fopen((char*)filename.c_str(), "r");
01055   if (pFile == NULL)
01056     return "";
01057   std::string data;
01058   while (fgets(mystring, sizeof(mystring), pFile))
01059     data += std::string(mystring);
01060   fclose(pFile);
01061 
01062   return data;
01063 }
01064 
01065 std::string FileCacheTest::_intToString(int i) {
01066   std::stringstream out;
01067   out << i;
01068   return out.str();
01069 }
01070 
01071 CPPUNIT_TEST_SUITE_REGISTRATION(FileCacheTest);