MultiDiskAdaptorTest.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. #include "MultiDiskAdaptor.h"
  2. #include <string>
  3. #include <cerrno>
  4. #include <cstring>
  5. #include <cppunit/extensions/HelperMacros.h>
  6. #include "FileEntry.h"
  7. #include "Exception.h"
  8. #include "a2io.h"
  9. #include "array_fun.h"
  10. #include "TestUtil.h"
  11. #include "DiskWriter.h"
  12. namespace aria2 {
  13. class MultiDiskAdaptorTest:public CppUnit::TestFixture {
  14. CPPUNIT_TEST_SUITE(MultiDiskAdaptorTest);
  15. CPPUNIT_TEST(testWriteData);
  16. CPPUNIT_TEST(testReadData);
  17. CPPUNIT_TEST(testCutTrailingGarbage);
  18. CPPUNIT_TEST(testSize);
  19. CPPUNIT_TEST(testUtime);
  20. CPPUNIT_TEST(testResetDiskWriterEntries);
  21. CPPUNIT_TEST_SUITE_END();
  22. private:
  23. SharedHandle<MultiDiskAdaptor> adaptor;
  24. public:
  25. void setUp() {
  26. adaptor.reset(new MultiDiskAdaptor());
  27. adaptor->setPieceLength(2);
  28. adaptor->setStoreDir(".");
  29. adaptor->setTopDir(".");
  30. }
  31. void testWriteData();
  32. void testReadData();
  33. void testCutTrailingGarbage();
  34. void testSize();
  35. void testUtime();
  36. void testResetDiskWriterEntries();
  37. };
  38. CPPUNIT_TEST_SUITE_REGISTRATION( MultiDiskAdaptorTest );
  39. std::deque<SharedHandle<FileEntry> > createEntries() {
  40. SharedHandle<FileEntry> array[] = {
  41. SharedHandle<FileEntry>(new FileEntry("file1.txt", 0, 0)),
  42. SharedHandle<FileEntry>(new FileEntry("file2.txt", 15, 0)),
  43. SharedHandle<FileEntry>(new FileEntry("file3.txt", 7, 15)),
  44. SharedHandle<FileEntry>(new FileEntry("file4.txt", 0, 22)),
  45. SharedHandle<FileEntry>(new FileEntry("file5.txt", 2, 22)),
  46. SharedHandle<FileEntry>(new FileEntry("file6.txt", 0, 24)),
  47. };
  48. std::deque<SharedHandle<FileEntry> > entries(&array[0],
  49. &array[arrayLength(array)]);
  50. for(std::deque<SharedHandle<FileEntry> >::const_iterator i = entries.begin();
  51. i != entries.end(); ++i) {
  52. File((*i)->getPath()).remove();
  53. }
  54. return entries;
  55. }
  56. void MultiDiskAdaptorTest::testResetDiskWriterEntries()
  57. {
  58. {
  59. std::deque<SharedHandle<FileEntry> > fileEntries = createEntries();
  60. adaptor->setFileEntries(fileEntries);
  61. // In openFile(), resetDiskWriterEntries() are called.
  62. adaptor->openFile();
  63. std::deque<SharedHandle<DiskWriterEntry> > entries =
  64. adaptor->getDiskWriterEntries();
  65. CPPUNIT_ASSERT(!entries[0]->getDiskWriter().isNull());
  66. CPPUNIT_ASSERT(!entries[1]->getDiskWriter().isNull());
  67. CPPUNIT_ASSERT(!entries[2]->getDiskWriter().isNull());
  68. CPPUNIT_ASSERT(!entries[3]->getDiskWriter().isNull());
  69. CPPUNIT_ASSERT(!entries[4]->getDiskWriter().isNull());
  70. CPPUNIT_ASSERT(!entries[5]->getDiskWriter().isNull());
  71. }
  72. {
  73. std::deque<SharedHandle<FileEntry> > fileEntries = createEntries();
  74. fileEntries[0]->setRequested(false);
  75. adaptor->setFileEntries(fileEntries);
  76. // In openFile(), resetDiskWriterEntries() are called.
  77. adaptor->openFile();
  78. std::deque<SharedHandle<DiskWriterEntry> > entries =
  79. adaptor->getDiskWriterEntries();
  80. // Because entries[1] spans entries[0]
  81. CPPUNIT_ASSERT(!entries[0]->getDiskWriter().isNull());
  82. CPPUNIT_ASSERT(!entries[1]->getDiskWriter().isNull());
  83. CPPUNIT_ASSERT(!entries[2]->getDiskWriter().isNull());
  84. CPPUNIT_ASSERT(!entries[3]->getDiskWriter().isNull());
  85. CPPUNIT_ASSERT(!entries[4]->getDiskWriter().isNull());
  86. CPPUNIT_ASSERT(!entries[5]->getDiskWriter().isNull());
  87. }
  88. {
  89. std::deque<SharedHandle<FileEntry> > fileEntries = createEntries();
  90. fileEntries[0]->setRequested(false);
  91. fileEntries[1]->setRequested(false);
  92. adaptor->setFileEntries(fileEntries);
  93. // In openFile(), resetDiskWriterEntries() are called.
  94. adaptor->openFile();
  95. std::deque<SharedHandle<DiskWriterEntry> > entries =
  96. adaptor->getDiskWriterEntries();
  97. CPPUNIT_ASSERT(entries[0]->getDiskWriter().isNull());
  98. // Because entries[2] spans entries[1]
  99. CPPUNIT_ASSERT(!entries[1]->getDiskWriter().isNull());
  100. CPPUNIT_ASSERT(!entries[2]->getDiskWriter().isNull());
  101. CPPUNIT_ASSERT(!entries[3]->getDiskWriter().isNull());
  102. CPPUNIT_ASSERT(!entries[4]->getDiskWriter().isNull());
  103. CPPUNIT_ASSERT(!entries[5]->getDiskWriter().isNull());
  104. }
  105. {
  106. std::deque<SharedHandle<FileEntry> > fileEntries = createEntries();
  107. fileEntries[3]->setRequested(false);
  108. adaptor->setFileEntries(fileEntries);
  109. // In openFile(), resetDiskWriterEntries() are called.
  110. adaptor->openFile();
  111. std::deque<SharedHandle<DiskWriterEntry> > entries =
  112. adaptor->getDiskWriterEntries();
  113. CPPUNIT_ASSERT(!entries[0]->getDiskWriter().isNull());
  114. CPPUNIT_ASSERT(!entries[1]->getDiskWriter().isNull());
  115. CPPUNIT_ASSERT(!entries[2]->getDiskWriter().isNull());
  116. // Because entries[4] spans entries[3]
  117. CPPUNIT_ASSERT(!entries[3]->getDiskWriter().isNull());
  118. CPPUNIT_ASSERT(!entries[4]->getDiskWriter().isNull());
  119. CPPUNIT_ASSERT(!entries[5]->getDiskWriter().isNull());
  120. }
  121. {
  122. std::deque<SharedHandle<FileEntry> > fileEntries = createEntries();
  123. fileEntries[4]->setRequested(false);
  124. adaptor->setFileEntries(fileEntries);
  125. // In openFile(), resetDiskWriterEntries() are called.
  126. adaptor->openFile();
  127. std::deque<SharedHandle<DiskWriterEntry> > entries =
  128. adaptor->getDiskWriterEntries();
  129. CPPUNIT_ASSERT(!entries[0]->getDiskWriter().isNull());
  130. CPPUNIT_ASSERT(!entries[1]->getDiskWriter().isNull());
  131. CPPUNIT_ASSERT(!entries[2]->getDiskWriter().isNull());
  132. CPPUNIT_ASSERT(!entries[3]->getDiskWriter().isNull());
  133. // Because entries[3] spans entries[4]
  134. CPPUNIT_ASSERT(!entries[4]->getDiskWriter().isNull());
  135. CPPUNIT_ASSERT(!entries[5]->getDiskWriter().isNull());
  136. }
  137. {
  138. std::deque<SharedHandle<FileEntry> > fileEntries = createEntries();
  139. fileEntries[3]->setRequested(false);
  140. fileEntries[4]->setRequested(false);
  141. adaptor->setFileEntries(fileEntries);
  142. // In openFile(), resetDiskWriterEntries() are called.
  143. adaptor->openFile();
  144. std::deque<SharedHandle<DiskWriterEntry> > entries =
  145. adaptor->getDiskWriterEntries();
  146. CPPUNIT_ASSERT(!entries[0]->getDiskWriter().isNull());
  147. CPPUNIT_ASSERT(!entries[1]->getDiskWriter().isNull());
  148. CPPUNIT_ASSERT(!entries[2]->getDiskWriter().isNull());
  149. CPPUNIT_ASSERT(entries[3]->getDiskWriter().isNull());
  150. CPPUNIT_ASSERT(entries[4]->getDiskWriter().isNull());
  151. CPPUNIT_ASSERT(!entries[5]->getDiskWriter().isNull());
  152. }
  153. {
  154. std::deque<SharedHandle<FileEntry> > fileEntries = createEntries();
  155. fileEntries[5]->setRequested(false);
  156. adaptor->setFileEntries(fileEntries);
  157. // In openFile(), resetDiskWriterEntries() are called.
  158. adaptor->openFile();
  159. std::deque<SharedHandle<DiskWriterEntry> > entries =
  160. adaptor->getDiskWriterEntries();
  161. CPPUNIT_ASSERT(!entries[0]->getDiskWriter().isNull());
  162. CPPUNIT_ASSERT(!entries[1]->getDiskWriter().isNull());
  163. CPPUNIT_ASSERT(!entries[2]->getDiskWriter().isNull());
  164. CPPUNIT_ASSERT(!entries[3]->getDiskWriter().isNull());
  165. CPPUNIT_ASSERT(!entries[4]->getDiskWriter().isNull());
  166. CPPUNIT_ASSERT(entries[5]->getDiskWriter().isNull());
  167. }
  168. }
  169. void readFile(const std::string& filename, char* buf, int bufLength) {
  170. FILE* f = fopen(filename.c_str(), "r");
  171. if(f == NULL) {
  172. CPPUNIT_FAIL(strerror(errno));
  173. }
  174. int retval = fread(buf, bufLength, 1, f);
  175. fclose(f);
  176. if(retval != 1) {
  177. CPPUNIT_FAIL("return value is not 1");
  178. }
  179. }
  180. void MultiDiskAdaptorTest::testWriteData() {
  181. try {
  182. adaptor->setFileEntries(createEntries());
  183. adaptor->openFile();
  184. std::string msg = "12345";
  185. adaptor->writeData((const unsigned char*)msg.c_str(), msg.size(), 0);
  186. adaptor->closeFile();
  187. CPPUNIT_ASSERT(File("file1.txt").isFile());
  188. char buf[128];
  189. readFile("file2.txt", buf, 5);
  190. buf[5] = '\0';
  191. CPPUNIT_ASSERT_EQUAL(msg, std::string(buf));
  192. adaptor->openFile();
  193. std::string msg2 = "67890ABCDEF";
  194. adaptor->writeData((const unsigned char*)msg2.c_str(), msg2.size(), 5);
  195. adaptor->closeFile();
  196. readFile("file2.txt", buf, 15);
  197. buf[15] = '\0';
  198. CPPUNIT_ASSERT_EQUAL(std::string("1234567890ABCDE"), std::string(buf));
  199. readFile("file3.txt", buf, 1);
  200. buf[1] = '\0';
  201. CPPUNIT_ASSERT_EQUAL(std::string("F"), std::string(buf));
  202. adaptor->openFile();
  203. std::string msg3 = "12345123456712";
  204. adaptor->writeData((const unsigned char*)msg3.c_str(), msg3.size(), 10);
  205. adaptor->closeFile();
  206. readFile("file2.txt", buf, 15);
  207. buf[15] = '\0';
  208. CPPUNIT_ASSERT_EQUAL(std::string("123456789012345"), std::string(buf));
  209. readFile("file3.txt", buf, 7);
  210. buf[7] = '\0';
  211. CPPUNIT_ASSERT_EQUAL(std::string("1234567"), std::string(buf));
  212. CPPUNIT_ASSERT(File("file4.txt").isFile());
  213. readFile("file5.txt", buf, 2);
  214. buf[2] = '\0';
  215. CPPUNIT_ASSERT_EQUAL(std::string("12"), std::string(buf));
  216. CPPUNIT_ASSERT(File("file6.txt").isFile());
  217. } catch(Exception& e) {
  218. CPPUNIT_FAIL(e.stackTrace());
  219. }
  220. }
  221. void MultiDiskAdaptorTest::testReadData() {
  222. SharedHandle<FileEntry> entry1(new FileEntry("file1r.txt", 15, 0));
  223. SharedHandle<FileEntry> entry2(new FileEntry("file2r.txt", 7, 15));
  224. SharedHandle<FileEntry> entry3(new FileEntry("file3r.txt", 3, 22));
  225. std::deque<SharedHandle<FileEntry> > entries;
  226. entries.push_back(entry1);
  227. entries.push_back(entry2);
  228. entries.push_back(entry3);
  229. adaptor->setFileEntries(entries);
  230. adaptor->openFile();
  231. unsigned char buf[128];
  232. adaptor->readData(buf, 15, 0);
  233. buf[15] = '\0';
  234. CPPUNIT_ASSERT_EQUAL(std::string("1234567890ABCDE"), std::string((char*)buf));
  235. adaptor->readData(buf, 10, 6);
  236. buf[10] = '\0';
  237. CPPUNIT_ASSERT_EQUAL(std::string("7890ABCDEF"), std::string((char*)buf));
  238. adaptor->readData(buf, 4, 20);
  239. buf[4] = '\0';
  240. CPPUNIT_ASSERT_EQUAL(std::string("KLMN"), std::string((char*)buf));
  241. adaptor->readData(buf, 25, 0);
  242. buf[25] = '\0';
  243. CPPUNIT_ASSERT_EQUAL(std::string("1234567890ABCDEFGHIJKLMNO"), std::string((char*)buf));
  244. }
  245. void MultiDiskAdaptorTest::testCutTrailingGarbage()
  246. {
  247. std::string dir = "/tmp";
  248. std::string topDir = ".";
  249. std::string topDirPath = dir+"/"+topDir;
  250. std::string prefix = "aria2_MultiDiskAdaptorTest_testCutTrailingGarbage_";
  251. SharedHandle<FileEntry> entries[] = {
  252. SharedHandle<FileEntry>(new FileEntry(prefix+"1", 256, 0)),
  253. SharedHandle<FileEntry>(new FileEntry(prefix+"2", 512, 256))
  254. };
  255. for(size_t i = 0; i < arrayLength(entries); ++i) {
  256. createFile(topDirPath+"/"+entries[i]->getPath(),
  257. entries[i]->getLength()+100);
  258. }
  259. std::deque<SharedHandle<FileEntry> > fileEntries
  260. (&entries[0], &entries[arrayLength(entries)]);
  261. MultiDiskAdaptor adaptor;
  262. adaptor.setStoreDir(dir);
  263. adaptor.setTopDir(topDir);
  264. adaptor.setFileEntries(fileEntries);
  265. adaptor.setMaxOpenFiles(1);
  266. adaptor.setPieceLength(1);
  267. adaptor.openFile();
  268. adaptor.cutTrailingGarbage();
  269. CPPUNIT_ASSERT_EQUAL((uint64_t)256,
  270. File(topDirPath+"/"+entries[0]->getPath()).size());
  271. CPPUNIT_ASSERT_EQUAL((uint64_t)512,
  272. File(topDirPath+"/"+entries[1]->getPath()).size());
  273. }
  274. void MultiDiskAdaptorTest::testSize()
  275. {
  276. std::string dir = "/tmp";
  277. std::string topDir = ".";
  278. std::string topDirPath = dir+"/"+topDir;
  279. std::string prefix = "aria2_MultiDiskAdaptorTest_testSize_";
  280. SharedHandle<FileEntry> entries[] = {
  281. SharedHandle<FileEntry>(new FileEntry(prefix+"1", 1, 0)),
  282. SharedHandle<FileEntry>(new FileEntry(prefix+"2", 1, 1))
  283. };
  284. for(size_t i = 0; i < arrayLength(entries); ++i) {
  285. createFile(topDirPath+"/"+entries[i]->getPath(), entries[i]->getLength());
  286. }
  287. std::deque<SharedHandle<FileEntry> > fileEntries
  288. (&entries[0], &entries[arrayLength(entries)]);
  289. MultiDiskAdaptor adaptor;
  290. adaptor.setStoreDir(dir);
  291. adaptor.setTopDir(topDir);
  292. adaptor.setFileEntries(fileEntries);
  293. adaptor.setMaxOpenFiles(1);
  294. adaptor.setPieceLength(1);
  295. adaptor.openFile();
  296. CPPUNIT_ASSERT_EQUAL((uint64_t)2, adaptor.size());
  297. }
  298. void MultiDiskAdaptorTest::testUtime()
  299. {
  300. std::string storeDir = "/tmp";
  301. std::string topDir = "aria2_MultiDiskAdaptorTest_testUtime";
  302. std::string prefix = storeDir+"/"+topDir;
  303. SharedHandle<FileEntry> entries[] = {
  304. SharedHandle<FileEntry>(new FileEntry("requested", 0, 0)),
  305. SharedHandle<FileEntry>(new FileEntry("notFound", 0, 0)),
  306. SharedHandle<FileEntry>(new FileEntry("notRequested", 0, 0)),
  307. SharedHandle<FileEntry>(new FileEntry("anotherRequested", 0, 0)),
  308. };
  309. createFile(prefix+"/"+entries[0]->getPath(), entries[0]->getLength());
  310. File(prefix+"/"+entries[1]->getPath()).remove();
  311. createFile(prefix+"/"+entries[2]->getPath(), entries[2]->getLength());
  312. createFile(prefix+"/"+entries[3]->getPath(), entries[3]->getLength());
  313. entries[2]->setRequested(false);
  314. std::deque<SharedHandle<FileEntry> > fileEntries
  315. (&entries[0], &entries[arrayLength(entries)]);
  316. MultiDiskAdaptor adaptor;
  317. adaptor.setStoreDir(storeDir);
  318. adaptor.setTopDir(topDir);
  319. adaptor.setFileEntries(fileEntries);
  320. CPPUNIT_ASSERT_EQUAL((size_t)2, adaptor.utime(Time(1000), Time(2000)));
  321. CPPUNIT_ASSERT_EQUAL((time_t)2000,
  322. File(prefix+"/"+entries[0]->getPath())
  323. .getModifiedTime().getTime());
  324. CPPUNIT_ASSERT_EQUAL((time_t)2000,
  325. File(prefix+"/"+entries[3]->getPath())
  326. .getModifiedTime().getTime());
  327. CPPUNIT_ASSERT((time_t)2000 != File(prefix+"/"+entries[2]->getPath())
  328. .getModifiedTime().getTime());
  329. }
  330. } // namespace aria2