1 // Copyright (C) 2015 James Turner - zakalawe@mac.com
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Library General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 # include <simgear_config.h>
22 #include <simgear/misc/test_macros.hxx>
28 #include <simgear/package/Catalog.hxx>
29 #include <simgear/package/Root.hxx>
30 #include <simgear/package/Package.hxx>
31 #include <simgear/package/Install.hxx>
33 #include <simgear/misc/test_macros.hxx>
34 #include <simgear/misc/sg_dir.hxx>
35 #include <simgear/timing/timestamp.hxx>
37 #include <simgear/io/test_HTTP.hxx>
38 #include <simgear/io/HTTPClient.hxx>
39 #include <simgear/io/sg_file.hxx>
40 #include <simgear/structure/exception.hxx>
42 using namespace simgear;
44 std::string readFileIntoString(const SGPath& path)
50 if (!f.open(SG_IO_IN)) {
51 throw sg_io_exception("Couldn't open file", path);
55 while ((readLen = f.read(buf, 8192)) > 0) {
56 contents += std::string(buf, readLen);
62 SGPath global_serverFilesRoot;
63 unsigned int global_catalogVersion = 0;
65 class TestPackageChannel : public TestServerChannel
69 virtual void processRequestHeaders()
72 SGPath localPath(global_serverFilesRoot);
75 if (path == "/catalogTest1/catalog.xml") {
76 if (global_catalogVersion > 0) {
78 ss << "/catalogTest1/catalog-v" << global_catalogVersion << ".xml";
83 localPath.append(path);
85 // SG_LOG(SG_IO, SG_INFO, "local path is:" << localPath.str());
87 if (localPath.exists()) {
88 std::string content = readFileIntoString(localPath);
90 d << "HTTP/1.1 " << 200 << " " << reasonForCode(200) << "\r\n";
91 d << "Content-Length:" << content.size() << "\r\n";
92 d << "\r\n"; // final CRLF to terminate the headers
95 std::string ds(d.str());
96 bufferSend(ds.data(), ds.size());
98 sendErrorResponse(404, false, "");
103 TestServer<TestPackageChannel> testServer;
105 void waitForUpdateComplete(HTTP::Client* cl, pkg::Root* root)
107 SGTimeStamp start(SGTimeStamp::now());
108 while (start.elapsedMSec() < 10000) {
112 if (!cl->hasActiveRequests()) {
116 SGTimeStamp::sleepForMSec(15);
119 std::cerr << "timed out" << std::endl;
124 SGPath rootPath = simgear::Dir::current().path();
125 rootPath.append("testRoot");
126 pkg::Root* root = new pkg::Root(rootPath, "8.1.12");
127 pkg::CatalogRef cat = pkg::Catalog::createFromPath(root, SGPath(SRC_DIR "/catalogTest1"));
131 COMPARE(cat->id(), "org.flightgear.test.catalog1");
132 COMPARE(cat->url(), "http://localhost:2000/catalogTest1/catalog.xml");
133 COMPARE(cat->description(), "First test catalog");
135 // check the packages too
136 COMPARE(cat->packages().size(), 3);
138 pkg::PackageRef p1 = cat->packages().front();
139 COMPARE(p1->catalog(), cat.ptr());
141 COMPARE(p1->id(), "alpha");
142 COMPARE(p1->qualifiedId(), "org.flightgear.test.catalog1.alpha");
143 COMPARE(p1->name(), "Alpha package");
144 COMPARE(p1->revision(), 8);
145 COMPARE(p1->fileSizeBytes(), 593);
148 pkg::PackageRef p2 = cat->getPackageById("c172p");
150 COMPARE(p2->qualifiedId(), "org.flightgear.test.catalog1.c172p");
151 COMPARE(p2->description(), "A plane made by Cessna");
155 // test filtering / searching too
156 string_set tags(p2->tags());
157 COMPARE(tags.size(), 4);
158 VERIFY(tags.find("ifr") != tags.end());
159 VERIFY(tags.find("cessna") != tags.end());
160 VERIFY(tags.find("jet") == tags.end());
163 SGPropertyNode_ptr queryA(new SGPropertyNode);
164 queryA->setStringValue("tag", "ifr");
165 VERIFY(p2->matches(queryA.ptr()));
167 SGPropertyNode_ptr queryB(new SGPropertyNode);
168 queryB->setStringValue("name", "ces");
169 VERIFY(p2->matches(queryB.ptr()));
171 SGPropertyNode_ptr queryC(new SGPropertyNode);
172 queryC->setStringValue("name", "foo");
173 VERIFY(!p2->matches(queryC.ptr()));
175 SGPropertyNode_ptr queryD(new SGPropertyNode);
176 queryD->setIntValue("rating-FDM", 3);
177 VERIFY(p2->matches(queryD.ptr()));
179 SGPropertyNode_ptr queryE(new SGPropertyNode);
180 queryE->setIntValue("rating-model", 5);
181 queryE->setStringValue("description", "cessna");
182 VERIFY(p2->matches(queryE.ptr()));
189 void testAddCatalog(HTTP::Client* cl)
192 SGPath rootPath(simgear::Dir::current().path());
193 rootPath.append("pkg_add_catalog");
194 simgear::Dir pd(rootPath);
198 pkg::RootRef root(new pkg::Root(rootPath, "8.1.2"));
199 // specify a test dir
200 root->setHTTPClient(cl);
202 pkg::CatalogRef c = pkg::Catalog::createFromUrl(root.ptr(), "http://localhost:2000/catalogTest1/catalog.xml");
204 waitForUpdateComplete(cl, root);
206 // verify on disk state
208 p.append("org.flightgear.test.catalog1");
209 p.append("catalog.xml");
211 COMPARE(root->allPackages().size(), 3);
212 COMPARE(root->catalogs().size(), 1);
214 pkg::PackageRef p1 = root->getPackageById("alpha");
215 COMPARE(p1->id(), "alpha");
217 pkg::PackageRef p2 = root->getPackageById("org.flightgear.test.catalog1.c172p");
218 COMPARE(p2->id(), "c172p");
219 COMPARE(p2->qualifiedId(), "org.flightgear.test.catalog1.c172p");
223 void testInstallPackage(HTTP::Client* cl)
225 SGPath rootPath(simgear::Dir::current().path());
226 rootPath.append("pkg_install_with_dep");
227 simgear::Dir pd(rootPath);
230 pkg::RootRef root(new pkg::Root(rootPath, "8.1.2"));
231 // specify a test dir
232 root->setHTTPClient(cl);
234 pkg::CatalogRef c = pkg::Catalog::createFromUrl(root.ptr(), "http://localhost:2000/catalogTest1/catalog.xml");
235 waitForUpdateComplete(cl, root);
237 pkg::PackageRef p1 = root->getPackageById("org.flightgear.test.catalog1.c172p");
238 pkg::InstallRef ins = p1->install();
240 VERIFY(ins->isQueued());
242 waitForUpdateComplete(cl, root);
243 VERIFY(p1->isInstalled());
244 VERIFY(p1->existingInstall() == ins);
246 pkg::PackageRef commonDeps = root->getPackageById("common-sounds");
247 VERIFY(commonDeps->existingInstall());
249 // verify on disk state
251 p.append("org.flightgear.test.catalog1");
252 p.append("Aircraft");
255 COMPARE(p, ins->path());
257 p.append("c172p-floats-set.xml");
261 p2.append("org.flightgear.test.catalog1");
262 p2.append("Aircraft");
264 p2.append("sharedfile.txt");
268 void testUninstall(HTTP::Client* cl)
270 SGPath rootPath(simgear::Dir::current().path());
271 rootPath.append("pkg_uninstall");
272 simgear::Dir pd(rootPath);
275 pkg::RootRef root(new pkg::Root(rootPath, "8.1.2"));
276 root->setHTTPClient(cl);
278 pkg::CatalogRef c = pkg::Catalog::createFromUrl(root.ptr(), "http://localhost:2000/catalogTest1/catalog.xml");
279 waitForUpdateComplete(cl, root);
281 pkg::PackageRef p1 = root->getPackageById("org.flightgear.test.catalog1.c172p");
282 pkg::InstallRef ins = p1->install();
284 waitForUpdateComplete(cl, root);
286 VERIFY(p1->isInstalled());
290 VERIFY(!ins->path().exists());
293 void testRemoveCatalog(HTTP::Client* cl)
295 SGPath rootPath(simgear::Dir::current().path());
296 rootPath.append("pkg_catalog_remove");
297 simgear::Dir pd(rootPath);
300 pkg::RootRef root(new pkg::Root(rootPath, "8.1.2"));
301 root->setHTTPClient(cl);
304 pkg::CatalogRef c = pkg::Catalog::createFromUrl(root.ptr(), "http://localhost:2000/catalogTest1/catalog.xml");
305 waitForUpdateComplete(cl, root);
309 pkg::PackageRef p1 = root->getPackageById("org.flightgear.test.catalog1.c172p");
310 pkg::InstallRef ins = p1->install();
312 waitForUpdateComplete(cl, root);
314 VERIFY(p1->isInstalled());
317 root->removeCatalogById("org.flightgear.test.catalog1");
321 p2.append("org.flightgear.test.catalog1");
322 VERIFY(!p2.exists());
324 VERIFY(root->allPackages().empty());
325 VERIFY(root->catalogs().empty());
327 pkg::CatalogRef c = root->getCatalogById("org.flightgear.test.catalog1");
328 COMPARE(c, pkg::CatalogRef());
332 bool contains(const std::vector<T>& vec, const T& item)
334 typename std::vector<T>::const_iterator it = std::find(vec.begin(), vec.end(), item);
335 return (it != vec.end());
338 void testRefreshCatalog(HTTP::Client* cl)
340 SGPath rootPath(simgear::Dir::current().path());
341 rootPath.append("pkg_catalog_refresh_update");
342 simgear::Dir pd(rootPath);
345 pkg::RootRef root(new pkg::Root(rootPath, "8.1.2"));
346 root->setHTTPClient(cl);
349 pkg::CatalogRef c = pkg::Catalog::createFromUrl(root.ptr(), "http://localhost:2000/catalogTest1/catalog.xml");
350 waitForUpdateComplete(cl, root);
354 pkg::PackageRef p1 = root->getPackageById("org.flightgear.test.catalog1.c172p");
355 pkg::InstallRef ins = p1->install();
357 pkg::PackageRef p2 = root->getPackageById("org.flightgear.test.catalog1.alpha");
358 pkg::InstallRef ins2 = p2->install();
360 waitForUpdateComplete(cl, root);
362 VERIFY(p1->isInstalled());
363 VERIFY(p2->isInstalled());
366 VERIFY(root->packagesNeedingUpdate().empty());
368 global_catalogVersion = 2;
370 VERIFY(!cl->hasActiveRequests());
373 // should be a no-op due to catalog age testing
374 VERIFY(!cl->hasActiveRequests());
376 // force it this time
378 VERIFY(cl->hasActiveRequests());
379 waitForUpdateComplete(cl, root);
381 pkg::CatalogRef c = root->getCatalogById("org.flightgear.test.catalog1");
382 COMPARE(c->ageInSeconds(), 0);
384 VERIFY(root->getPackageById("dc3") != pkg::PackageRef());
385 COMPARE(root->packagesNeedingUpdate().size(), 2);
387 pkg::PackageList needingUpdate = root->packagesNeedingUpdate();
388 VERIFY(contains(needingUpdate, root->getPackageById("common-sounds")));
389 VERIFY(contains(needingUpdate, root->getPackageById("org.flightgear.test.catalog1.alpha")));
391 pkg::InstallRef ins = root->getPackageById("alpha")->existingInstall();
392 VERIFY(ins->hasUpdate());
394 for (pkg::PackageList::const_iterator it = needingUpdate.begin();
395 it != needingUpdate.end(); ++it)
397 root->scheduleToUpdate((*it)->existingInstall());
400 waitForUpdateComplete(cl, root);
402 VERIFY(root->packagesNeedingUpdate().empty());
403 COMPARE(root->getPackageById("common-sounds")->revision(), 11);
407 int main(int argc, char* argv[])
409 sglog().setLogLevels( SG_ALL, SG_DEBUG );
412 cl.setMaxConnections(1);
414 global_serverFilesRoot = SGPath(SRC_DIR);
420 testInstallPackage(&cl);
424 testRemoveCatalog(&cl);
426 testRefreshCatalog(&cl);
428 std::cout << "Successfully passed all tests!" << std::endl;