1 #include "FileEntry.h"
2 
3 #include <cppunit/extensions/HelperMacros.h>
4 
5 #include "InorderURISelector.h"
6 #include "util.h"
7 
8 namespace aria2 {
9 
10 class FileEntryTest : public CppUnit::TestFixture {
11 
12   CPPUNIT_TEST_SUITE(FileEntryTest);
13   CPPUNIT_TEST(testRemoveURIWhoseHostnameIs);
14   CPPUNIT_TEST(testExtractURIResult);
15   CPPUNIT_TEST(testGetRequest);
16   CPPUNIT_TEST(testGetRequest_withoutUriReuse);
17   CPPUNIT_TEST(testGetRequest_withUniqueProtocol);
18   CPPUNIT_TEST(testGetRequest_withReferer);
19   CPPUNIT_TEST(testReuseUri);
20   CPPUNIT_TEST(testAddUri);
21   CPPUNIT_TEST(testAddUris);
22   CPPUNIT_TEST(testInsertUri);
23   CPPUNIT_TEST(testRemoveUri);
24   CPPUNIT_TEST(testPutBackRequest);
25   CPPUNIT_TEST_SUITE_END();
26 
27 public:
setUp()28   void setUp() {}
29 
30   void testRemoveURIWhoseHostnameIs();
31   void testExtractURIResult();
32   void testGetRequest();
33   void testGetRequest_withoutUriReuse();
34   void testGetRequest_withUniqueProtocol();
35   void testGetRequest_withReferer();
36   void testReuseUri();
37   void testAddUri();
38   void testAddUris();
39   void testInsertUri();
40   void testRemoveUri();
41   void testPutBackRequest();
42 };
43 
44 CPPUNIT_TEST_SUITE_REGISTRATION(FileEntryTest);
45 
46 namespace {
createFileEntry()47 std::shared_ptr<FileEntry> createFileEntry()
48 {
49   auto fileEntry = std::make_shared<FileEntry>();
50   fileEntry->setUris(std::vector<std::string>{"http://localhost/aria2.zip",
51                                               "ftp://localhost/aria2.zip",
52                                               "http://mirror/aria2.zip"});
53   return fileEntry;
54 }
55 } // namespace
56 
testRemoveURIWhoseHostnameIs()57 void FileEntryTest::testRemoveURIWhoseHostnameIs()
58 {
59   auto fileEntry = createFileEntry();
60   fileEntry->removeURIWhoseHostnameIs("localhost");
61   CPPUNIT_ASSERT_EQUAL((size_t)1, fileEntry->getRemainingUris().size());
62   CPPUNIT_ASSERT_EQUAL(std::string("http://mirror/aria2.zip"),
63                        fileEntry->getRemainingUris()[0]);
64 }
65 
testExtractURIResult()66 void FileEntryTest::testExtractURIResult()
67 {
68   FileEntry fileEntry;
69   fileEntry.addURIResult("http://timeout/file", error_code::TIME_OUT);
70   fileEntry.addURIResult("http://finished/file", error_code::FINISHED);
71   fileEntry.addURIResult("http://timeout/file2", error_code::TIME_OUT);
72   fileEntry.addURIResult("http://unknownerror/file", error_code::UNKNOWN_ERROR);
73 
74   std::deque<URIResult> res;
75   fileEntry.extractURIResult(res, error_code::TIME_OUT);
76   CPPUNIT_ASSERT_EQUAL((size_t)2, res.size());
77   CPPUNIT_ASSERT_EQUAL(std::string("http://timeout/file"), res[0].getURI());
78   CPPUNIT_ASSERT_EQUAL(std::string("http://timeout/file2"), res[1].getURI());
79 
80   CPPUNIT_ASSERT_EQUAL((size_t)2, fileEntry.getURIResults().size());
81   CPPUNIT_ASSERT_EQUAL(std::string("http://finished/file"),
82                        fileEntry.getURIResults()[0].getURI());
83   CPPUNIT_ASSERT_EQUAL(std::string("http://unknownerror/file"),
84                        fileEntry.getURIResults()[1].getURI());
85 
86   res.clear();
87 
88   fileEntry.extractURIResult(res, error_code::TIME_OUT);
89   CPPUNIT_ASSERT(res.empty());
90   CPPUNIT_ASSERT_EQUAL((size_t)2, fileEntry.getURIResults().size());
91 }
92 
testGetRequest()93 void FileEntryTest::testGetRequest()
94 {
95   auto fileEntry = createFileEntry();
96   InorderURISelector selector{};
97   std::vector<std::pair<size_t, std::string>> usedHosts;
98   auto req = fileEntry->getRequest(&selector, true, usedHosts);
99   CPPUNIT_ASSERT_EQUAL(std::string("localhost"), req->getHost());
100   CPPUNIT_ASSERT_EQUAL(std::string("http"), req->getProtocol());
101   fileEntry->poolRequest(req);
102 
103   auto req2nd = fileEntry->getRequest(&selector, true, usedHosts);
104   CPPUNIT_ASSERT_EQUAL(std::string("localhost"), req2nd->getHost());
105   CPPUNIT_ASSERT_EQUAL(std::string("http"), req2nd->getProtocol());
106 
107   auto req3rd = fileEntry->getRequest(&selector, true, usedHosts);
108   CPPUNIT_ASSERT_EQUAL(std::string("mirror"), req3rd->getHost());
109   CPPUNIT_ASSERT_EQUAL(std::string("http"), req3rd->getProtocol());
110 
111   auto req4th = fileEntry->getRequest(&selector, true, usedHosts);
112   CPPUNIT_ASSERT(!req4th);
113 
114   fileEntry->setMaxConnectionPerServer(2);
115 
116   auto req5th = fileEntry->getRequest(&selector, true, usedHosts);
117   CPPUNIT_ASSERT_EQUAL(std::string("localhost"), req5th->getHost());
118   CPPUNIT_ASSERT_EQUAL(std::string("ftp"), req5th->getProtocol());
119 
120   auto req6th = fileEntry->getRequest(&selector, true, usedHosts);
121   CPPUNIT_ASSERT_EQUAL(std::string("mirror"), req6th->getHost());
122   CPPUNIT_ASSERT_EQUAL(std::string("http"), req6th->getProtocol());
123 
124   auto req7th = fileEntry->getRequest(&selector, true, usedHosts);
125   CPPUNIT_ASSERT(!req7th);
126 }
127 
testGetRequest_withoutUriReuse()128 void FileEntryTest::testGetRequest_withoutUriReuse()
129 {
130   std::vector<std::pair<size_t, std::string>> usedHosts;
131   auto fileEntry = createFileEntry();
132   fileEntry->setMaxConnectionPerServer(2);
133   InorderURISelector selector{};
134   auto req = fileEntry->getRequest(&selector, false, usedHosts);
135   CPPUNIT_ASSERT_EQUAL(std::string("localhost"), req->getHost());
136   CPPUNIT_ASSERT_EQUAL(std::string("http"), req->getProtocol());
137 
138   auto req2nd = fileEntry->getRequest(&selector, false, usedHosts);
139   CPPUNIT_ASSERT_EQUAL(std::string("localhost"), req2nd->getHost());
140   CPPUNIT_ASSERT_EQUAL(std::string("ftp"), req2nd->getProtocol());
141 
142   auto req3rd = fileEntry->getRequest(&selector, false, usedHosts);
143   CPPUNIT_ASSERT_EQUAL(std::string("mirror"), req3rd->getHost());
144   CPPUNIT_ASSERT_EQUAL(std::string("http"), req3rd->getProtocol());
145 
146   auto req4th = fileEntry->getRequest(&selector, false, usedHosts);
147   CPPUNIT_ASSERT(!req4th);
148 }
149 
testGetRequest_withUniqueProtocol()150 void FileEntryTest::testGetRequest_withUniqueProtocol()
151 {
152   std::vector<std::pair<size_t, std::string>> usedHosts;
153   auto fileEntry = createFileEntry();
154   fileEntry->setUniqueProtocol(true);
155   InorderURISelector selector{};
156   auto req = fileEntry->getRequest(&selector, true, usedHosts);
157   CPPUNIT_ASSERT_EQUAL(std::string("localhost"), req->getHost());
158   CPPUNIT_ASSERT_EQUAL(std::string("http"), req->getProtocol());
159 
160   auto req2nd = fileEntry->getRequest(&selector, true, usedHosts);
161   CPPUNIT_ASSERT_EQUAL(std::string("mirror"), req2nd->getHost());
162   CPPUNIT_ASSERT_EQUAL(std::string("http"), req2nd->getProtocol());
163 
164   auto req3rd = fileEntry->getRequest(&selector, true, usedHosts);
165   CPPUNIT_ASSERT(!req3rd);
166 
167   CPPUNIT_ASSERT_EQUAL((size_t)2, fileEntry->getRemainingUris().size());
168   CPPUNIT_ASSERT_EQUAL(std::string("ftp://localhost/aria2.zip"),
169                        fileEntry->getRemainingUris()[0]);
170   CPPUNIT_ASSERT_EQUAL(std::string("http://mirror/aria2.zip"),
171                        fileEntry->getRemainingUris()[1]);
172 }
173 
testGetRequest_withReferer()174 void FileEntryTest::testGetRequest_withReferer()
175 {
176   auto fileEntry = createFileEntry();
177   InorderURISelector selector{};
178   std::vector<std::pair<size_t, std::string>> usedHosts;
179   auto req =
180       fileEntry->getRequest(&selector, true, usedHosts, "http://referer");
181   CPPUNIT_ASSERT_EQUAL(std::string("http://referer"), req->getReferer());
182   // URI is used as referer if "*" is given.
183   req = fileEntry->getRequest(&selector, true, usedHosts, "*");
184   CPPUNIT_ASSERT_EQUAL(req->getUri(), req->getReferer());
185 }
186 
testReuseUri()187 void FileEntryTest::testReuseUri()
188 {
189   InorderURISelector selector{};
190   auto fileEntry = createFileEntry();
191   fileEntry->setMaxConnectionPerServer(3);
192   size_t numUris = fileEntry->getRemainingUris().size();
193   std::vector<std::pair<size_t, std::string>> usedHosts;
194   for (size_t i = 0; i < numUris; ++i) {
195     fileEntry->getRequest(&selector, false, usedHosts);
196   }
197   CPPUNIT_ASSERT_EQUAL((size_t)0, fileEntry->getRemainingUris().size());
198   fileEntry->addURIResult("http://localhost/aria2.zip",
199                           error_code::UNKNOWN_ERROR);
200   std::vector<std::string> ignore;
201   fileEntry->reuseUri(ignore);
202   CPPUNIT_ASSERT_EQUAL((size_t)2, fileEntry->getRemainingUris().size());
203   auto uris = fileEntry->getRemainingUris();
204   CPPUNIT_ASSERT_EQUAL(std::string("ftp://localhost/aria2.zip"), uris[0]);
205   CPPUNIT_ASSERT_EQUAL(std::string("http://mirror/aria2.zip"), uris[1]);
206   for (size_t i = 0; i < 2; ++i) {
207     fileEntry->getRequest(&selector, false, usedHosts);
208   }
209   CPPUNIT_ASSERT_EQUAL((size_t)0, fileEntry->getRemainingUris().size());
210   ignore.clear();
211   ignore.push_back("mirror");
212   fileEntry->reuseUri(ignore);
213   CPPUNIT_ASSERT_EQUAL((size_t)1, fileEntry->getRemainingUris().size());
214   uris = fileEntry->getRemainingUris();
215   CPPUNIT_ASSERT_EQUAL(std::string("ftp://localhost/aria2.zip"), uris[0]);
216 }
217 
testAddUri()218 void FileEntryTest::testAddUri()
219 {
220   FileEntry file;
221   CPPUNIT_ASSERT(file.addUri("http://good"));
222   CPPUNIT_ASSERT(!file.addUri("bad"));
223   // Test for percent-encode
224   CPPUNIT_ASSERT(file.addUri("http://host:80/file<with%2 %20space/"
225                              "file with space;param%?a=/?"));
226 
227   CPPUNIT_ASSERT_EQUAL(std::string("http://host:80"
228                                    "/file%3Cwith%2%20%20space/"
229                                    "file%20with%20space;param%"
230                                    "?a=/?"),
231                        file.getRemainingUris()[1]);
232 }
233 
testAddUris()234 void FileEntryTest::testAddUris()
235 {
236   FileEntry file;
237   std::string uris[] = {"bad", "http://good"};
238   CPPUNIT_ASSERT_EQUAL((size_t)1, file.addUris(&uris[0], &uris[2]));
239 }
240 
testInsertUri()241 void FileEntryTest::testInsertUri()
242 {
243   FileEntry file;
244   CPPUNIT_ASSERT(file.insertUri("http://example.org/1", 0));
245   CPPUNIT_ASSERT(file.insertUri("http://example.org/2", 0));
246   CPPUNIT_ASSERT(file.insertUri("http://example.org/3", 1));
247   CPPUNIT_ASSERT(file.insertUri("http://example.org/4", 5));
248   auto& uris = file.getRemainingUris();
249   CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/2"), uris[0]);
250   CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/3"), uris[1]);
251   CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/1"), uris[2]);
252   CPPUNIT_ASSERT_EQUAL(std::string("http://example.org/4"), uris[3]);
253   // Test for percent-encode
254   CPPUNIT_ASSERT(file.insertUri("http://host:80/file<with%2 %20space/"
255                                 "file with space;param%?a=/?",
256                                 0));
257 
258   CPPUNIT_ASSERT_EQUAL(std::string("http://host:80"
259                                    "/file%3Cwith%2%20%20space/"
260                                    "file%20with%20space;param%"
261                                    "?a=/?"),
262                        file.getRemainingUris()[0]);
263 }
264 
testRemoveUri()265 void FileEntryTest::testRemoveUri()
266 {
267   std::vector<std::pair<size_t, std::string>> usedHosts;
268   InorderURISelector selector{};
269   FileEntry file;
270   file.addUri("http://example.org/");
271   CPPUNIT_ASSERT(file.removeUri("http://example.org/"));
272   CPPUNIT_ASSERT(file.getRemainingUris().empty());
273   CPPUNIT_ASSERT(!file.removeUri("http://example.org/"));
274 
275   file.addUri("http://example.org/");
276   auto exampleOrgReq = file.getRequest(&selector, true, usedHosts);
277   CPPUNIT_ASSERT(!exampleOrgReq->removalRequested());
278   CPPUNIT_ASSERT_EQUAL((size_t)1, file.getSpentUris().size());
279   CPPUNIT_ASSERT(file.removeUri("http://example.org/"));
280   CPPUNIT_ASSERT(file.getSpentUris().empty());
281   CPPUNIT_ASSERT(exampleOrgReq->removalRequested());
282   file.poolRequest(exampleOrgReq);
283   CPPUNIT_ASSERT_EQUAL((size_t)0, file.countPooledRequest());
284 
285   file.addUri("http://example.org/");
286   exampleOrgReq = file.getRequest(&selector, true, usedHosts);
287   file.poolRequest(exampleOrgReq);
288   CPPUNIT_ASSERT_EQUAL((size_t)1, file.countPooledRequest());
289   CPPUNIT_ASSERT(file.removeUri("http://example.org/"));
290   CPPUNIT_ASSERT_EQUAL((size_t)0, file.countPooledRequest());
291   CPPUNIT_ASSERT(file.getSpentUris().empty());
292 
293   file.addUri("http://example.org/");
294   CPPUNIT_ASSERT(!file.removeUri("http://example.net"));
295 }
296 
testPutBackRequest()297 void FileEntryTest::testPutBackRequest()
298 {
299   auto fileEntry = createFileEntry();
300   InorderURISelector selector{};
301   std::vector<std::pair<size_t, std::string>> usedHosts;
302   auto req1 = fileEntry->getRequest(&selector, false, usedHosts);
303   auto req2 = fileEntry->getRequest(&selector, false, usedHosts);
304   CPPUNIT_ASSERT_EQUAL((size_t)1, fileEntry->getRemainingUris().size());
305   fileEntry->poolRequest(req2);
306   fileEntry->putBackRequest();
307   auto& uris = fileEntry->getRemainingUris();
308   CPPUNIT_ASSERT_EQUAL((size_t)3, uris.size());
309   CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/aria2.zip"), uris[0]);
310   CPPUNIT_ASSERT_EQUAL(std::string("http://mirror/aria2.zip"), uris[1]);
311   CPPUNIT_ASSERT_EQUAL(std::string("ftp://localhost/aria2.zip"), uris[2]);
312 }
313 
314 } // namespace aria2
315