diff options
author | Alexander Shalamov <alexander.shalamov@mapbox.com> | 2019-10-04 15:02:01 +0300 |
---|---|---|
committer | Alexander Shalamov <alexander.shalamov@mapbox.com> | 2020-01-13 10:57:23 +0200 |
commit | 879c44f661c5eb762c93a721b657859a71aabfc7 (patch) | |
tree | 3a542777434e0d685811ce1c66b752dc9ca36e92 /test | |
parent | 86a360534994cb37d3dddc53b71a2858d97419c3 (diff) | |
download | qtlocation-mapboxgl-879c44f661c5eb762c93a721b657859a71aabfc7.tar.gz |
[core] Modularize FileSource codebase (#15768)
* [core] Introduce FileSourceManager and use it for default platform impl
- Add `FileSourceManager` interface that provides access to `FileSource`
instances and means of registering / unregistering `FileSource` factories
- Split `DefaultFileSource` into smaller parts
- Add `DatabaseFileSource` interface and it's default implementation
- Remove inter-dependencies between concrete `FileSource` classes
* [build] Add files to next build system
* [core] Add generic property setters / getters
* [core] Remove setOnlineStatus from OnlineFileSource interface
* [core] Hide threading implementation details from DatabaseFileSource interface
* [core] Make DB file source methods virtual
* [core] Add documentation for DatabaseFileSource and rename one method
* [core] Use simple callback instead of ActorRef
* [core] Remove ActorRef from OnlineFileSource public header
* [core] Add callback to FileSource::forward async API
* [core] Pass OfflineRegionDefinition by value
* [core] Update tests to use modular file sources
* [core] Update unit tests
* [core] Update unit tests after rebase
* [core] Backport low prio fix for cached requests
* [core] Backport pack database
* [core] Return removed factory from unRegisterFileSourceFactory
* [core] Rename shadowed args in onlinefilesource
* [core] Remove simple std::function callback aliases
* [core] Expose online file source property keys in public header file
* [test-runner] Add proxy file source test runner
* [cache] Update mbgl-cache utility to use new file source
* [metrics] Rebaseline binary size metrics
* [offline] Update offline utility
* [core] Update changelog
Diffstat (limited to 'test')
21 files changed, 386 insertions, 348 deletions
diff --git a/test/map/map.test.cpp b/test/map/map.test.cpp index 3eb01a7383..89be4ad73e 100644 --- a/test/map/map.test.cpp +++ b/test/map/map.test.cpp @@ -10,7 +10,8 @@ #include <mbgl/gl/context.hpp> #include <mbgl/map/map_options.hpp> #include <mbgl/math/log2.hpp> -#include <mbgl/storage/default_file_source.hpp> +#include <mbgl/storage/file_source_manager.hpp> +#include <mbgl/storage/main_resource_loader.hpp> #include <mbgl/storage/network_status.hpp> #include <mbgl/storage/online_file_source.hpp> #include <mbgl/storage/resource_options.hpp> @@ -47,13 +48,17 @@ public: MapOptions().withMapMode(mode).withSize(frontend.getSize()).withPixelRatio(pixelRatio)) {} template <typename T = FileSource> - MapTest(const std::string& cachePath, const std::string& assetPath, - float pixelRatio = 1, MapMode mode = MapMode::Static, - typename std::enable_if<std::is_same<T, DefaultFileSource>::value>::type* = nullptr) - : fileSource(std::make_shared<T>(cachePath, assetPath)) - , frontend(pixelRatio) - , map(frontend, observer, fileSource, - MapOptions().withMapMode(mode).withSize(frontend.getSize()).withPixelRatio(pixelRatio)) {} + MapTest(const std::string& cachePath, + const std::string& assetPath, + float pixelRatio = 1, + MapMode mode = MapMode::Static, + typename std::enable_if<std::is_same<T, MainResourceLoader>::value>::type* = nullptr) + : fileSource(std::make_shared<T>(ResourceOptions().withCachePath(cachePath).withAssetPath(assetPath))), + frontend(pixelRatio), + map(frontend, + observer, + fileSource, + MapOptions().withMapMode(mode).withSize(frontend.getSize()).withPixelRatio(pixelRatio)) {} }; TEST(Map, RendererState) { @@ -295,7 +300,7 @@ TEST(Map, CameraToLatLngBoundsUnwrappedCrossDateLine) { } TEST(Map, Offline) { - MapTest<DefaultFileSource> test {":memory:", "."}; + MapTest<MainResourceLoader> test{":memory:", "."}; auto expiredItem = [] (const std::string& path) { Response response; @@ -304,19 +309,21 @@ TEST(Map, Offline) { return response; }; - const std::string prefix = "http://127.0.0.1:3000/"; - test.fileSource->put(Resource::style(prefix + "style.json"), expiredItem("style.json")); - test.fileSource->put(Resource::source(prefix + "streets.json"), expiredItem("streets.json")); - test.fileSource->put(Resource::spriteJSON(prefix + "sprite", 1.0), expiredItem("sprite.json")); - test.fileSource->put(Resource::spriteImage(prefix + "sprite", 1.0), expiredItem("sprite.png")); - test.fileSource->put(Resource::tile(prefix + "{z}-{x}-{y}.vector.pbf", 1.0, 0, 0, 0, Tileset::Scheme::XYZ), expiredItem("0-0-0.vector.pbf")); - test.fileSource->put(Resource::glyphs(prefix + "{fontstack}/{range}.pbf", {{"Helvetica"}}, {0, 255}), expiredItem("glyph.pbf")); NetworkStatus::Set(NetworkStatus::Status::Offline); - - test.map.getStyle().loadURL(prefix + "style.json"); + const std::string prefix = "http://127.0.0.1:3000/"; + auto dbfs = FileSourceManager::get()->getFileSource(FileSourceType::Database, ResourceOptions{}); + dbfs->forward(Resource::style(prefix + "style.json"), expiredItem("style.json")); + dbfs->forward(Resource::source(prefix + "streets.json"), expiredItem("streets.json")); + dbfs->forward(Resource::spriteJSON(prefix + "sprite", 1.0), expiredItem("sprite.json")); + dbfs->forward(Resource::spriteImage(prefix + "sprite", 1.0), expiredItem("sprite.png")); + dbfs->forward(Resource::tile(prefix + "{z}-{x}-{y}.vector.pbf", 1.0, 0, 0, 0, Tileset::Scheme::XYZ), + expiredItem("0-0-0.vector.pbf")); + dbfs->forward(Resource::glyphs(prefix + "{fontstack}/{range}.pbf", {{"Helvetica"}}, {0, 255}), + expiredItem("glyph.pbf"), + [&] { test.map.getStyle().loadURL(prefix + "style.json"); }); #if ANDROID - test::checkImage("test/fixtures/map/offline", test.frontend.render(test.map).image, 0.0045, 0.1); + test::checkImage("test/fixtures/map/offline", test.frontend.render(test.map).image, 0.0046, 0.1); #else test::checkImage("test/fixtures/map/offline", test.frontend.render(test.map).image, 0.0015, 0.1); #endif @@ -672,7 +679,7 @@ TEST(Map, WithoutVAOExtension) { return; } - MapTest<DefaultFileSource> test { ":memory:", "test/fixtures/api/assets" }; + MapTest<MainResourceLoader> test{":memory:", "test/fixtures/api/assets"}; gfx::BackendScope scope { *test.frontend.getBackend() }; static_cast<gl::Context&>(test.frontend.getBackend()->getContext()).disableVAOExtension = true; @@ -836,7 +843,7 @@ TEST(Map, TEST_DISABLED_ON_CI(ContinuousRendering)) { } TEST(Map, NoContentTiles) { - MapTest<DefaultFileSource> test {":memory:", "."}; + MapTest<MainResourceLoader> test{":memory:", "."}; using namespace std::chrono_literals; @@ -844,33 +851,32 @@ TEST(Map, NoContentTiles) { Response response; response.noContent = true; response.expires = util::now() + 1h; - test.fileSource->put(Resource::tile("http://example.com/{z}-{x}-{y}.vector.pbf", 1.0, 0, 0, 0, - Tileset::Scheme::XYZ), - response); - - test.map.getStyle().loadJSON(R"STYLE({ - "version": 8, - "name": "Water", - "sources": { - "mapbox": { - "type": "vector", - "tiles": ["http://example.com/{z}-{x}-{y}.vector.pbf"] - } - }, - "layers": [{ - "id": "background", - "type": "background", - "paint": { - "background-color": "red" - } - }, { - "id": "water", - "type": "fill", - "source": "mapbox", - "source-layer": "water" - }] - })STYLE"); - + auto dbfs = FileSourceManager::get()->getFileSource(FileSourceType::Database, ResourceOptions{}); + dbfs->forward( + Resource::tile("http://example.com/{z}-{x}-{y}.vector.pbf", 1.0, 0, 0, 0, Tileset::Scheme::XYZ), response, [&] { + test.map.getStyle().loadJSON(R"STYLE({ + "version": 8, + "name": "Water", + "sources": { + "mapbox": { + "type": "vector", + "tiles": ["http://example.com/{z}-{x}-{y}.vector.pbf"] + } + }, + "layers": [{ + "id": "background", + "type": "background", + "paint": { + "background-color": "red" + } + }, { + "id": "water", + "type": "fill", + "source": "mapbox", + "source-layer": "water" + }] + })STYLE"); + }); test::checkImage("test/fixtures/map/nocontent", test.frontend.render(test.map).image, 0.0015, 0.1); } diff --git a/test/src/mbgl/test/fake_file_source.hpp b/test/src/mbgl/test/fake_file_source.hpp index 8803e9576b..1faf4b7a18 100644 --- a/test/src/mbgl/test/fake_file_source.hpp +++ b/test/src/mbgl/test/fake_file_source.hpp @@ -2,6 +2,8 @@ #include <mbgl/storage/file_source.hpp> #include <mbgl/storage/online_file_source.hpp> +#include <mbgl/storage/resource.hpp> +#include <mbgl/util/async_request.hpp> #include <algorithm> #include <list> @@ -42,6 +44,8 @@ public: return std::make_unique<FakeFileRequest>(resource, callback, requests); } + bool canRequest(const Resource&) const override { return true; } + bool respond(Resource::Kind kind, const Response& response) { auto it = std::find_if(requests.begin(), requests.end(), [&] (FakeFileRequest* fakeRequest) { return fakeRequest->resource.kind == kind; @@ -60,7 +64,7 @@ public: }; -class FakeOnlineFileSource : public OnlineFileSource, public FakeFileSource { +class FakeOnlineFileSource : public FakeFileSource { public: std::unique_ptr<AsyncRequest> request(const Resource& resource, Callback callback) override { return FakeFileSource::request(resource, callback); @@ -69,7 +73,12 @@ public: bool respond(Resource::Kind kind, const Response& response) { return FakeFileSource::respond(kind, response); } -}; + mapbox::base::Value getProperty(const std::string& property) const override { + return onlineFs.getProperty(property); + } + + OnlineFileSource onlineFs; +}; } // namespace mbgl diff --git a/test/src/mbgl/test/stub_file_source.cpp b/test/src/mbgl/test/stub_file_source.cpp index 0bbff84ff3..8870a45bdc 100644 --- a/test/src/mbgl/test/stub_file_source.cpp +++ b/test/src/mbgl/test/stub_file_source.cpp @@ -1,4 +1,5 @@ #include <mbgl/test/stub_file_source.hpp> +#include <mbgl/util/async_request.hpp> namespace mbgl { diff --git a/test/src/mbgl/test/stub_file_source.hpp b/test/src/mbgl/test/stub_file_source.hpp index 1135fa9a80..46bb33d5e2 100644 --- a/test/src/mbgl/test/stub_file_source.hpp +++ b/test/src/mbgl/test/stub_file_source.hpp @@ -2,6 +2,7 @@ #include <mbgl/storage/file_source.hpp> #include <mbgl/storage/online_file_source.hpp> +#include <mbgl/storage/resource.hpp> #include <mbgl/util/timer.hpp> #include <unordered_map> @@ -19,6 +20,7 @@ public: ~StubFileSource() override; std::unique_ptr<AsyncRequest> request(const Resource&, Callback) override; + bool canRequest(const Resource&) const override { return true; } void remove(AsyncRequest*); using ResponseFunction = std::function<optional<Response> (const Resource&)>; @@ -48,15 +50,4 @@ private: util::Timer timer; }; -class StubOnlineFileSource : public StubFileSource, public OnlineFileSource { -public: - - StubOnlineFileSource(ResponseType t = ResponseType::Asynchronous) : StubFileSource(t) {}; - ~StubOnlineFileSource() override = default; - - std::unique_ptr<AsyncRequest> request(const Resource& r, Callback c) override { return StubFileSource::request(r, c); }; - void remove(AsyncRequest* r) { StubFileSource::remove(r); }; -}; - - } // namespace mbgl diff --git a/test/storage/asset_file_source.test.cpp b/test/storage/asset_file_source.test.cpp index 978a41a306..ac04bc7dc2 100644 --- a/test/storage/asset_file_source.test.cpp +++ b/test/storage/asset_file_source.test.cpp @@ -1,9 +1,10 @@ +#include <mbgl/actor/actor_ref.hpp> #include <mbgl/storage/asset_file_source.hpp> -#include <mbgl/util/platform.hpp> +#include <mbgl/storage/resource.hpp> #include <mbgl/util/chrono.hpp> +#include <mbgl/util/platform.hpp> #include <mbgl/util/run_loop.hpp> #include <mbgl/util/thread.hpp> -#include <mbgl/actor/actor_ref.hpp> #include <gtest/gtest.h> #include <atomic> @@ -70,12 +71,13 @@ TEST(AssetFileSource, Load) { } TEST(AssetFileSource, AcceptsURL) { - EXPECT_TRUE(AssetFileSource::acceptsURL("asset://empty")); - EXPECT_TRUE(AssetFileSource::acceptsURL("asset:///test")); - EXPECT_FALSE(AssetFileSource::acceptsURL("assds://foo")); - EXPECT_FALSE(AssetFileSource::acceptsURL("asset:")); - EXPECT_FALSE(AssetFileSource::acceptsURL("style.json")); - EXPECT_FALSE(AssetFileSource::acceptsURL("")); + AssetFileSource fs("test/fixtures/storage/assets"); + EXPECT_TRUE(fs.canRequest(Resource::style("asset://empty"))); + EXPECT_TRUE(fs.canRequest(Resource::style("asset:///test"))); + EXPECT_FALSE(fs.canRequest(Resource::style("assds://foo"))); + EXPECT_FALSE(fs.canRequest(Resource::style("asset:"))); + EXPECT_FALSE(fs.canRequest(Resource::style("style.json"))); + EXPECT_FALSE(fs.canRequest(Resource::style(""))); } TEST(AssetFileSource, EmptyFile) { diff --git a/test/storage/http_file_source.test.cpp b/test/storage/http_file_source.test.cpp index 42b4174e69..37476c8e7c 100644 --- a/test/storage/http_file_source.test.cpp +++ b/test/storage/http_file_source.test.cpp @@ -1,9 +1,10 @@ -#include <mbgl/test/util.hpp> #include <mbgl/storage/http_file_source.hpp> -#include <mbgl/util/exception.hpp> +#include <mbgl/storage/resource.hpp> +#include <mbgl/test/util.hpp> #include <mbgl/util/chrono.hpp> -#include <mbgl/util/string.hpp> +#include <mbgl/util/exception.hpp> #include <mbgl/util/run_loop.hpp> +#include <mbgl/util/string.hpp> using namespace mbgl; diff --git a/test/storage/local_file_source.test.cpp b/test/storage/local_file_source.test.cpp index e1756f8e7d..45c8c54d91 100644 --- a/test/storage/local_file_source.test.cpp +++ b/test/storage/local_file_source.test.cpp @@ -1,4 +1,5 @@ #include <mbgl/storage/local_file_source.hpp> +#include <mbgl/storage/resource.hpp> #include <mbgl/util/platform.hpp> #include <mbgl/util/run_loop.hpp> @@ -21,12 +22,13 @@ std::string toAbsoluteURL(const std::string& fileName) { using namespace mbgl; TEST(LocalFileSource, AcceptsURL) { - EXPECT_TRUE(LocalFileSource::acceptsURL("file://empty")); - EXPECT_TRUE(LocalFileSource::acceptsURL("file:///test")); - EXPECT_FALSE(LocalFileSource::acceptsURL("flie://foo")); - EXPECT_FALSE(LocalFileSource::acceptsURL("file:")); - EXPECT_FALSE(LocalFileSource::acceptsURL("style.json")); - EXPECT_FALSE(LocalFileSource::acceptsURL("")); + LocalFileSource fs; + EXPECT_TRUE(fs.canRequest(Resource::style("file://empty"))); + EXPECT_TRUE(fs.canRequest(Resource::style("file:///test"))); + EXPECT_FALSE(fs.canRequest(Resource::style("flie://foo"))); + EXPECT_FALSE(fs.canRequest(Resource::style("file:"))); + EXPECT_FALSE(fs.canRequest(Resource::style("style.json"))); + EXPECT_FALSE(fs.canRequest(Resource::style(""))); } TEST(LocalFileSource, EmptyFile) { diff --git a/test/storage/default_file_source.test.cpp b/test/storage/main_resource_loader.test.cpp index 52051ac839..c5f1a9c707 100644 --- a/test/storage/default_file_source.test.cpp +++ b/test/storage/main_resource_loader.test.cpp @@ -1,17 +1,21 @@ #include <mbgl/actor/actor.hpp> -#include <mbgl/storage/default_file_source.hpp> +#include <mbgl/storage/database_file_source.hpp> +#include <mbgl/storage/file_source_manager.hpp> +#include <mbgl/storage/main_resource_loader.hpp> #include <mbgl/storage/network_status.hpp> +#include <mbgl/storage/online_file_source.hpp> +#include <mbgl/storage/resource_options.hpp> #include <mbgl/storage/resource_transform.hpp> #include <mbgl/test/util.hpp> #include <mbgl/util/run_loop.hpp> using namespace mbgl; -TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheResponse)) { +TEST(MainResourceLoader, TEST_REQUIRES_SERVER(CacheResponse)) { util::RunLoop loop; - DefaultFileSource fs(":memory:", "."); + MainResourceLoader fs(ResourceOptions{}); - const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/cache" }; + const Resource resource{Resource::Unknown, "http://127.0.0.1:3000/cache"}; Response response; std::unique_ptr<AsyncRequest> req1; @@ -47,11 +51,11 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheResponse)) { loop.run(); } -TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheRevalidateSame)) { +TEST(MainResourceLoader, TEST_REQUIRES_SERVER(CacheRevalidateSame)) { util::RunLoop loop; - DefaultFileSource fs(":memory:", "."); + MainResourceLoader fs(ResourceOptions{}); - const Resource revalidateSame { Resource::Unknown, "http://127.0.0.1:3000/revalidate-same" }; + const Resource revalidateSame{Resource::Unknown, "http://127.0.0.1:3000/revalidate-same"}; std::unique_ptr<AsyncRequest> req1; std::unique_ptr<AsyncRequest> req2; bool gotResponse = false; @@ -109,12 +113,11 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheRevalidateSame)) { loop.run(); } -TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheRevalidateModified)) { +TEST(MainResourceLoader, TEST_REQUIRES_SERVER(CacheRevalidateModified)) { util::RunLoop loop; - DefaultFileSource fs(":memory:", "."); + MainResourceLoader fs(ResourceOptions{}); - const Resource revalidateModified{ Resource::Unknown, - "http://127.0.0.1:3000/revalidate-modified" }; + const Resource revalidateModified{Resource::Unknown, "http://127.0.0.1:3000/revalidate-modified"}; std::unique_ptr<AsyncRequest> req1; std::unique_ptr<AsyncRequest> req2; bool gotResponse = false; @@ -129,7 +132,7 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheRevalidateModified)) { EXPECT_EQ("Response", *res.data); EXPECT_FALSE(bool(res.expires)); EXPECT_TRUE(res.mustRevalidate); - EXPECT_EQ(Timestamp{ Seconds(1420070400) }, *res.modified); + EXPECT_EQ(Timestamp{Seconds(1420070400)}, *res.modified); EXPECT_FALSE(res.etag); // The first response is stored in the cache, but it has 'must-revalidate' set. This means @@ -149,7 +152,7 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheRevalidateModified)) { EXPECT_EQ("Response", *res2.data); EXPECT_TRUE(bool(res2.expires)); EXPECT_TRUE(res2.mustRevalidate); - EXPECT_EQ(Timestamp{ Seconds(1420070400) }, *res2.modified); + EXPECT_EQ(Timestamp{Seconds(1420070400)}, *res2.modified); EXPECT_FALSE(res2.etag); } else { // The test server sends a Cache-Control header with a max-age of 1 second. This @@ -162,7 +165,7 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheRevalidateModified)) { EXPECT_FALSE(res2.data.get()); EXPECT_TRUE(bool(res2.expires)); EXPECT_TRUE(res2.mustRevalidate); - EXPECT_EQ(Timestamp{ Seconds(1420070400) }, *res2.modified); + EXPECT_EQ(Timestamp{Seconds(1420070400)}, *res2.modified); EXPECT_FALSE(res2.etag); loop.stop(); } @@ -172,11 +175,11 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheRevalidateModified)) { loop.run(); } -TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheRevalidateEtag)) { +TEST(MainResourceLoader, TEST_REQUIRES_SERVER(CacheRevalidateEtag)) { util::RunLoop loop; - DefaultFileSource fs(":memory:", "."); + MainResourceLoader fs(ResourceOptions{}); - const Resource revalidateEtag { Resource::Unknown, "http://127.0.0.1:3000/revalidate-etag" }; + const Resource revalidateEtag{Resource::Unknown, "http://127.0.0.1:3000/revalidate-etag"}; std::unique_ptr<AsyncRequest> req1; std::unique_ptr<AsyncRequest> req2; @@ -222,16 +225,13 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheRevalidateEtag)) { // will notify as expected, the second one will have bound a DefaultFileRequest* in the lambda that // gets invalidated by the first notify's pending.erase, and when it gets notified, the crash // occurs. - -TEST(DefaultFileSource, TEST_REQUIRES_SERVER(HTTPIssue1369)) { +TEST(MainResourceLoader, TEST_REQUIRES_SERVER(HTTPIssue1369)) { util::RunLoop loop; - DefaultFileSource fs(":memory:", "."); + MainResourceLoader fs(ResourceOptions{}); - const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/test" }; + const Resource resource{Resource::Unknown, "http://127.0.0.1:3000/test"}; - auto req = fs.request(resource, [&](Response) { - ADD_FAILURE() << "Callback should not be called"; - }); + auto req = fs.request(resource, [&](Response) { ADD_FAILURE() << "Callback should not be called"; }); req.reset(); req = fs.request(resource, [&](Response res) { req.reset(); @@ -248,87 +248,77 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(HTTPIssue1369)) { loop.run(); } -TEST(DefaultFileSource, OptionalNonExpired) { +TEST(MainResourceLoader, OptionalNonExpired) { util::RunLoop loop; - DefaultFileSource fs(":memory:", "."); + MainResourceLoader fs(ResourceOptions{}); - const Resource optionalResource { Resource::Unknown, "http://127.0.0.1:3000/test", {}, Resource::LoadingMethod::CacheOnly }; + const Resource optionalResource{ + Resource::Unknown, "http://127.0.0.1:3000/test", {}, Resource::LoadingMethod::CacheOnly}; using namespace std::chrono_literals; Response response; response.data = std::make_shared<std::string>("Cached value"); response.expires = util::now() + 1h; - fs.put(optionalResource, response); std::unique_ptr<AsyncRequest> req; - req = fs.request(optionalResource, [&](Response res) { - req.reset(); - EXPECT_EQ(nullptr, res.error); - ASSERT_TRUE(res.data.get()); - EXPECT_EQ("Cached value", *res.data); - ASSERT_TRUE(bool(res.expires)); - EXPECT_EQ(*response.expires, *res.expires); - EXPECT_FALSE(res.mustRevalidate); - EXPECT_FALSE(bool(res.modified)); - EXPECT_FALSE(bool(res.etag)); - loop.stop(); + auto dbfs = FileSourceManager::get()->getFileSource(FileSourceType::Database, ResourceOptions{}); + dbfs->forward(optionalResource, response, [&] { + req = fs.request(optionalResource, [&](Response res) { + req.reset(); + EXPECT_EQ(nullptr, res.error); + ASSERT_TRUE(res.data.get()); + EXPECT_EQ("Cached value", *res.data); + ASSERT_TRUE(bool(res.expires)); + EXPECT_EQ(*response.expires, *res.expires); + EXPECT_FALSE(res.mustRevalidate); + EXPECT_FALSE(bool(res.modified)); + EXPECT_FALSE(bool(res.etag)); + loop.stop(); + }); }); loop.run(); } -TEST(DefaultFileSource, OptionalExpired) { +TEST(MainResourceLoader, OptionalExpired) { util::RunLoop loop; - DefaultFileSource fs(":memory:", "."); + MainResourceLoader fs(ResourceOptions{}); - const Resource optionalResource { Resource::Unknown, "http://127.0.0.1:3000/test", {}, Resource::LoadingMethod::CacheOnly }; + const Resource optionalResource{ + Resource::Unknown, "http://127.0.0.1:3000/test", {}, Resource::LoadingMethod::CacheOnly}; using namespace std::chrono_literals; Response response; response.data = std::make_shared<std::string>("Cached value"); response.expires = util::now() - 1h; - fs.put(optionalResource, response); - + auto dbfs = FileSourceManager::get()->getFileSource(FileSourceType::Database, ResourceOptions{}); std::unique_ptr<AsyncRequest> req; - req = fs.request(optionalResource, [&](Response res) { - req.reset(); - EXPECT_EQ(nullptr, res.error); - ASSERT_TRUE(res.data.get()); - EXPECT_EQ("Cached value", *res.data); - ASSERT_TRUE(bool(res.expires)); - EXPECT_EQ(*response.expires, *res.expires); - EXPECT_FALSE(res.mustRevalidate); - EXPECT_FALSE(bool(res.modified)); - EXPECT_FALSE(bool(res.etag)); - loop.stop(); + dbfs->forward(optionalResource, response, [&] { + req = fs.request(optionalResource, [&](Response res) { + req.reset(); + EXPECT_EQ(nullptr, res.error); + ASSERT_TRUE(res.data.get()); + EXPECT_EQ("Cached value", *res.data); + ASSERT_TRUE(bool(res.expires)); + EXPECT_EQ(*response.expires, *res.expires); + EXPECT_FALSE(res.mustRevalidate); + EXPECT_FALSE(bool(res.modified)); + EXPECT_FALSE(bool(res.etag)); + loop.stop(); + }); }); loop.run(); } -TEST(DefaultFileSource, GetBaseURLAndAccessTokenWhilePaused) { +TEST(MainResourceLoader, OptionalNotFound) { util::RunLoop loop; - DefaultFileSource fs(":memory:", "."); + MainResourceLoader fs(ResourceOptions{}); - fs.pause(); - - auto baseURL = "http://url"; - auto accessToken = "access_token"; - - fs.setAPIBaseURL(baseURL); - fs.setAccessToken(accessToken); - - EXPECT_EQ(fs.getAPIBaseURL(), baseURL); - EXPECT_EQ(fs.getAccessToken(), accessToken); -} - -TEST(DefaultFileSource, OptionalNotFound) { - util::RunLoop loop; - DefaultFileSource fs(":memory:", "."); - - const Resource optionalResource { Resource::Unknown, "http://127.0.0.1:3000/test", {}, Resource::LoadingMethod::CacheOnly }; + const Resource optionalResource{ + Resource::Unknown, "http://127.0.0.1:3000/test", {}, Resource::LoadingMethod::CacheOnly}; using namespace std::chrono_literals; @@ -350,9 +340,9 @@ TEST(DefaultFileSource, OptionalNotFound) { } // Test that a network only request doesn't attempt to load data from the cache. -TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheRefreshEtagNotModified)) { +TEST(MainResourceLoader, TEST_REQUIRES_SERVER(NoCacheRefreshEtagNotModified)) { util::RunLoop loop; - DefaultFileSource fs(":memory:", "."); + MainResourceLoader fs(ResourceOptions{}); Resource resource { Resource::Unknown, "http://127.0.0.1:3000/revalidate-same" }; resource.loadingMethod = Resource::LoadingMethod::NetworkOnly; @@ -364,30 +354,31 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheRefreshEtagNotModified)) { Response response; response.data = std::make_shared<std::string>("Cached value"); response.expires = util::now() + 1h; - fs.put(resource, response); - std::unique_ptr<AsyncRequest> req; - req = fs.request(resource, [&](Response res) { - req.reset(); - EXPECT_EQ(nullptr, res.error); - EXPECT_TRUE(res.notModified); - EXPECT_FALSE(res.data.get()); - ASSERT_TRUE(bool(res.expires)); - EXPECT_LT(util::now(), *res.expires); - EXPECT_TRUE(res.mustRevalidate); - EXPECT_FALSE(bool(res.modified)); - ASSERT_TRUE(bool(res.etag)); - EXPECT_EQ("snowfall", *res.etag); - loop.stop(); + auto dbfs = FileSourceManager::get()->getFileSource(FileSourceType::Database, ResourceOptions{}); + dbfs->forward(resource, response, [&] { + req = fs.request(resource, [&](Response res) { + req.reset(); + EXPECT_EQ(nullptr, res.error); + EXPECT_TRUE(res.notModified); + EXPECT_FALSE(res.data.get()); + ASSERT_TRUE(bool(res.expires)); + EXPECT_LT(util::now(), *res.expires); + EXPECT_TRUE(res.mustRevalidate); + EXPECT_FALSE(bool(res.modified)); + ASSERT_TRUE(bool(res.etag)); + EXPECT_EQ("snowfall", *res.etag); + loop.stop(); + }); }); loop.run(); } // Test that a network only request doesn't attempt to load data from the cache. -TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheRefreshEtagModified)) { +TEST(MainResourceLoader, TEST_REQUIRES_SERVER(NoCacheRefreshEtagModified)) { util::RunLoop loop; - DefaultFileSource fs(":memory:", "."); + MainResourceLoader fs(ResourceOptions{}); Resource resource { Resource::Unknown, "http://127.0.0.1:3000/revalidate-same" }; resource.loadingMethod = Resource::LoadingMethod::NetworkOnly; @@ -399,30 +390,31 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheRefreshEtagModified)) { Response response; response.data = std::make_shared<std::string>("Cached value"); response.expires = util::now() + 1h; - fs.put(resource, response); - std::unique_ptr<AsyncRequest> req; - req = fs.request(resource, [&](Response res) { - req.reset(); - EXPECT_EQ(nullptr, res.error); - EXPECT_FALSE(res.notModified); - ASSERT_TRUE(res.data.get()); - EXPECT_EQ("Response", *res.data); - EXPECT_FALSE(bool(res.expires)); - EXPECT_TRUE(res.mustRevalidate); - EXPECT_FALSE(bool(res.modified)); - ASSERT_TRUE(bool(res.etag)); - EXPECT_EQ("snowfall", *res.etag); - loop.stop(); + auto dbfs = FileSourceManager::get()->getFileSource(FileSourceType::Database, ResourceOptions{}); + dbfs->forward(resource, response, [&] { + req = fs.request(resource, [&](Response res) { + req.reset(); + EXPECT_EQ(nullptr, res.error); + EXPECT_FALSE(res.notModified); + ASSERT_TRUE(res.data.get()); + EXPECT_EQ("Response", *res.data); + EXPECT_FALSE(bool(res.expires)); + EXPECT_TRUE(res.mustRevalidate); + EXPECT_FALSE(bool(res.modified)); + ASSERT_TRUE(bool(res.etag)); + EXPECT_EQ("snowfall", *res.etag); + loop.stop(); + }); }); loop.run(); } // Test that a network only request doesn't attempt to load data from the cache. -TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheFull)) { +TEST(MainResourceLoader, TEST_REQUIRES_SERVER(NoCacheFull)) { util::RunLoop loop; - DefaultFileSource fs(":memory:", "."); + MainResourceLoader fs(ResourceOptions{}); Resource resource { Resource::Unknown, "http://127.0.0.1:3000/revalidate-same" }; resource.loadingMethod = Resource::LoadingMethod::NetworkOnly; @@ -433,21 +425,22 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheFull)) { Response response; response.data = std::make_shared<std::string>("Cached value"); response.expires = util::now() + 1h; - fs.put(resource, response); - std::unique_ptr<AsyncRequest> req; - req = fs.request(resource, [&](Response res) { - req.reset(); - EXPECT_EQ(nullptr, res.error); - EXPECT_FALSE(res.notModified); - ASSERT_TRUE(res.data.get()); - EXPECT_EQ("Response", *res.data); - EXPECT_FALSE(bool(res.expires)); - EXPECT_TRUE(res.mustRevalidate); - EXPECT_FALSE(bool(res.modified)); - ASSERT_TRUE(bool(res.etag)); - EXPECT_EQ("snowfall", *res.etag); - loop.stop(); + auto dbfs = FileSourceManager::get()->getFileSource(FileSourceType::Database, ResourceOptions{}); + dbfs->forward(resource, response, [&] { + req = fs.request(resource, [&](Response res) { + req.reset(); + EXPECT_EQ(nullptr, res.error); + EXPECT_FALSE(res.notModified); + ASSERT_TRUE(res.data.get()); + EXPECT_EQ("Response", *res.data); + EXPECT_FALSE(bool(res.expires)); + EXPECT_TRUE(res.mustRevalidate); + EXPECT_FALSE(bool(res.modified)); + ASSERT_TRUE(bool(res.etag)); + EXPECT_EQ("snowfall", *res.etag); + loop.stop(); + }); }); loop.run(); @@ -455,9 +448,9 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheFull)) { // Test that we can make a request with a Modified field that doesn't first try to load // from cache like a regular request -TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheRefreshModifiedNotModified)) { +TEST(MainResourceLoader, TEST_REQUIRES_SERVER(NoCacheRefreshModifiedNotModified)) { util::RunLoop loop; - DefaultFileSource fs(":memory:", "."); + MainResourceLoader fs(ResourceOptions{}); Resource resource { Resource::Unknown, "http://127.0.0.1:3000/revalidate-modified" }; resource.loadingMethod = Resource::LoadingMethod::NetworkOnly; @@ -469,21 +462,22 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheRefreshModifiedNotModified)) Response response; response.data = std::make_shared<std::string>("Cached value"); response.expires = util::now() + 1h; - fs.put(resource, response); - std::unique_ptr<AsyncRequest> req; - req = fs.request(resource, [&](Response res) { - req.reset(); - EXPECT_EQ(nullptr, res.error); - EXPECT_TRUE(res.notModified); - EXPECT_FALSE(res.data.get()); - ASSERT_TRUE(bool(res.expires)); - EXPECT_LT(util::now(), *res.expires); - EXPECT_TRUE(res.mustRevalidate); - ASSERT_TRUE(bool(res.modified)); - EXPECT_EQ(Timestamp{ Seconds(1420070400) }, *res.modified); - EXPECT_FALSE(bool(res.etag)); - loop.stop(); + auto dbfs = FileSourceManager::get()->getFileSource(FileSourceType::Database, ResourceOptions{}); + dbfs->forward(resource, response, [&] { + req = fs.request(resource, [&](Response res) { + req.reset(); + EXPECT_EQ(nullptr, res.error); + EXPECT_TRUE(res.notModified); + EXPECT_FALSE(res.data.get()); + ASSERT_TRUE(bool(res.expires)); + EXPECT_LT(util::now(), *res.expires); + EXPECT_TRUE(res.mustRevalidate); + ASSERT_TRUE(bool(res.modified)); + EXPECT_EQ(Timestamp{Seconds(1420070400)}, *res.modified); + EXPECT_FALSE(bool(res.etag)); + loop.stop(); + }); }); loop.run(); @@ -491,9 +485,9 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheRefreshModifiedNotModified)) // Test that we can make a request with a Modified field that doesn't first try to load // from cache like a regular request -TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheRefreshModifiedModified)) { +TEST(MainResourceLoader, TEST_REQUIRES_SERVER(NoCacheRefreshModifiedModified)) { util::RunLoop loop; - DefaultFileSource fs(":memory:", "."); + MainResourceLoader fs(ResourceOptions{}); Resource resource { Resource::Unknown, "http://127.0.0.1:3000/revalidate-modified" }; resource.loadingMethod = Resource::LoadingMethod::NetworkOnly; @@ -505,40 +499,49 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(NoCacheRefreshModifiedModified)) { Response response; response.data = std::make_shared<std::string>("Cached value"); response.expires = util::now() + 1h; - fs.put(resource, response); - std::unique_ptr<AsyncRequest> req; - req = fs.request(resource, [&](Response res) { - req.reset(); - EXPECT_EQ(nullptr, res.error); - EXPECT_FALSE(res.notModified); - ASSERT_TRUE(res.data.get()); - EXPECT_EQ("Response", *res.data); - EXPECT_FALSE(bool(res.expires)); - EXPECT_TRUE(res.mustRevalidate); - EXPECT_EQ(Timestamp{ Seconds(1420070400) }, *res.modified); - EXPECT_FALSE(res.etag); - loop.stop(); + auto dbfs = FileSourceManager::get()->getFileSource(FileSourceType::Database, ResourceOptions{}); + dbfs->forward(resource, response, [&] { + req = fs.request(resource, [&](Response res) { + req.reset(); + EXPECT_EQ(nullptr, res.error); + EXPECT_FALSE(res.notModified); + ASSERT_TRUE(res.data.get()); + EXPECT_EQ("Response", *res.data); + EXPECT_FALSE(bool(res.expires)); + EXPECT_TRUE(res.mustRevalidate); + EXPECT_EQ(Timestamp{Seconds(1420070400)}, *res.modified); + EXPECT_FALSE(res.etag); + loop.stop(); + }); }); loop.run(); } -TEST(DefaultFileSource, TEST_REQUIRES_SERVER(SetResourceTransform)) { +TEST(MainResourceLoader, TEST_REQUIRES_SERVER(SetResourceTransform)) { util::RunLoop loop; - DefaultFileSource fs(":memory:", "."); + MainResourceLoader fs(ResourceOptions{}); + + auto onlinefs = std::static_pointer_cast<OnlineFileSource>( + FileSourceManager::get()->getFileSource(FileSourceType::Network, ResourceOptions{})); // Translates the URL "localhost://test to http://127.0.0.1:3000/test - Actor<ResourceTransform> transform(loop, [](Resource::Kind, const std::string& url) -> std::string { - if (url == "localhost://test") { - return "http://127.0.0.1:3000/test"; - } else { - return url; - } - }); + Actor<ResourceTransform::TransformCallback> transform( + loop, [](Resource::Kind, const std::string& url, ResourceTransform::FinishedCallback cb) { + if (url == "localhost://test") { + cb("http://127.0.0.1:3000/test"); + } else { + cb(url); + } + }); - fs.setResourceTransform(transform.self()); - const Resource resource1 { Resource::Unknown, "localhost://test" }; + onlinefs->setResourceTransform( + {[actorRef = transform.self()]( + Resource::Kind kind, const std::string& url, ResourceTransform::FinishedCallback cb) { + actorRef.invoke(&ResourceTransform::TransformCallback::operator(), kind, url, std::move(cb)); + }}); + const Resource resource1{Resource::Unknown, "localhost://test"}; std::unique_ptr<AsyncRequest> req; req = fs.request(resource1, [&](Response res) { @@ -555,8 +558,8 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(SetResourceTransform)) { loop.run(); - fs.setResourceTransform({}); - const Resource resource2 { Resource::Unknown, "http://127.0.0.1:3000/test" }; + onlinefs->setResourceTransform({}); + const Resource resource2{Resource::Unknown, "http://127.0.0.1:3000/test"}; req = fs.request(resource2, [&](Response res) { req.reset(); @@ -573,22 +576,19 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(SetResourceTransform)) { loop.run(); } -TEST(DefaultFileSource, SetResourceCachePath) { +TEST(MainResourceLoader, SetResourceCachePath) { util::RunLoop loop; - DefaultFileSource fs(":memory:", "."); - - Actor<PathChangeCallback> callback(loop, [&]() -> void { - loop.stop(); - }); - - fs.setResourceCachePath("./new_offline.db", callback.self()); + MainResourceLoader fs(ResourceOptions{}); + auto dbfs = std::static_pointer_cast<DatabaseFileSource>( + FileSourceManager::get()->getFileSource(FileSourceType::Database, ResourceOptions{})); + dbfs->setDatabasePath("./new_offline.db", [&loop] { loop.stop(); }); loop.run(); } // Test that a stale cache file that has must-revalidate set will trigger a response. -TEST(DefaultFileSource, TEST_REQUIRES_SERVER(RespondToStaleMustRevalidate)) { +TEST(MainResourceLoader, TEST_REQUIRES_SERVER(RespondToStaleMustRevalidate)) { util::RunLoop loop; - DefaultFileSource fs(":memory:", "."); + MainResourceLoader fs(ResourceOptions{}); Resource resource { Resource::Unknown, "http://127.0.0.1:3000/revalidate-same" }; resource.loadingMethod = Resource::LoadingMethod::CacheOnly; @@ -602,37 +602,38 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(RespondToStaleMustRevalidate)) { response.expires = Timestamp(Seconds(1417392000)); response.mustRevalidate = true; response.etag.emplace("snowfall"); - fs.put(resource, response); - std::unique_ptr<AsyncRequest> req; - req = fs.request(resource, [&](Response res) { - req.reset(); - ASSERT_TRUE(res.error.get()); - EXPECT_EQ(Response::Error::Reason::NotFound, res.error->reason); - EXPECT_EQ("Cached resource is unusable", res.error->message); - EXPECT_FALSE(res.notModified); - ASSERT_TRUE(res.data.get()); - EXPECT_EQ("Cached value", *res.data); - ASSERT_TRUE(res.expires); - EXPECT_EQ(Timestamp{ Seconds(1417392000) }, *res.expires); - EXPECT_TRUE(res.mustRevalidate); - ASSERT_TRUE(res.modified); - EXPECT_EQ(Timestamp{ Seconds(1417392000) }, *res.modified); - ASSERT_TRUE(res.etag); - EXPECT_EQ("snowfall", *res.etag); - - resource.priorEtag = res.etag; - resource.priorModified = res.modified; - resource.priorExpires = res.expires; - resource.priorData = res.data; + auto dbfs = FileSourceManager::get()->getFileSource(FileSourceType::Database, ResourceOptions{}); + dbfs->forward(resource, response, [&] { + req = fs.request(resource, [&](Response res) { + req.reset(); + ASSERT_TRUE(res.error.get()); + EXPECT_EQ(Response::Error::Reason::NotFound, res.error->reason); + EXPECT_EQ("Cached resource is unusable", res.error->message); + EXPECT_FALSE(res.notModified); + ASSERT_TRUE(res.data.get()); + EXPECT_EQ("Cached value", *res.data); + ASSERT_TRUE(res.expires); + EXPECT_EQ(Timestamp{Seconds(1417392000)}, *res.expires); + EXPECT_TRUE(res.mustRevalidate); + ASSERT_TRUE(res.modified); + EXPECT_EQ(Timestamp{Seconds(1417392000)}, *res.modified); + ASSERT_TRUE(res.etag); + EXPECT_EQ("snowfall", *res.etag); + + resource.priorEtag = res.etag; + resource.priorModified = res.modified; + resource.priorExpires = res.expires; + resource.priorData = res.data; - loop.stop(); + loop.stop(); + }); }); loop.run(); // Now run this request again, with the data we gathered from the previous stale/unusable - // request. We're replacing the data so that we can check that the DefaultFileSource doesn't + // request. We're replacing the data so that we can check that the MainResourceLoader doesn't // attempt another database access if we already have the value. resource.loadingMethod = Resource::LoadingMethod::NetworkOnly; resource.priorData = std::make_shared<std::string>("Prior value"); @@ -664,9 +665,9 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(RespondToStaleMustRevalidate)) { } // Test that requests for expired resources have lower priority than requests for new resources -TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CachedResourceLowPriority)) { +TEST(MainResourceLoader, TEST_REQUIRES_SERVER(CachedResourceLowPriority)) { util::RunLoop loop; - DefaultFileSource fs(":memory:", "."); + MainResourceLoader fs(ResourceOptions{}); Response response; std::size_t online_response_counter = 0; @@ -674,16 +675,20 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CachedResourceLowPriority)) { using namespace std::chrono_literals; response.expires = util::now() - 1h; + auto dbfs = FileSourceManager::get()->getFileSource(FileSourceType::Database, ResourceOptions{}); + auto onlineFs = FileSourceManager::get()->getFileSource(FileSourceType::Network, ResourceOptions{}); + // Put existing values into the cache. Resource resource1{Resource::Unknown, "http://127.0.0.1:3000/load/3", {}, Resource::LoadingMethod::All}; response.data = std::make_shared<std::string>("Cached Request 3"); - fs.put(resource1, response); + dbfs->forward(resource1, response); Resource resource2{Resource::Unknown, "http://127.0.0.1:3000/load/4", {}, Resource::LoadingMethod::All}; response.data = std::make_shared<std::string>("Cached Request 4"); - fs.put(resource2, response); + dbfs->forward(resource2, response); - fs.setMaximumConcurrentRequests(1); + onlineFs->setProperty("max-concurrent-requests", 1u); + fs.pause(); NetworkStatus::Set(NetworkStatus::Status::Offline); // Ensure that the online requests for new resources are processed first. @@ -695,14 +700,6 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CachedResourceLowPriority)) { EXPECT_EQ("Request 1", *res.data); }); - Resource nonCached2{Resource::Unknown, "http://127.0.0.1:3000/load/2", {}, Resource::LoadingMethod::All}; - std::unique_ptr<AsyncRequest> req2 = fs.request(nonCached2, [&](Response res) { - online_response_counter++; - req2.reset(); - EXPECT_EQ(online_response_counter, 2); // make sure this is responded second - EXPECT_EQ("Request 2", *res.data); - }); - bool req3CachedResponseReceived = false; std::unique_ptr<AsyncRequest> req3 = fs.request(resource1, [&](Response res) { // Offline callback is received first @@ -732,6 +729,15 @@ TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CachedResourceLowPriority)) { } }); + Resource nonCached2{Resource::Unknown, "http://127.0.0.1:3000/load/2", {}, Resource::LoadingMethod::All}; + std::unique_ptr<AsyncRequest> req2 = fs.request(nonCached2, [&](Response res) { + online_response_counter++; + req2.reset(); + EXPECT_EQ(online_response_counter, 2); // make sure this is responded second + EXPECT_EQ("Request 2", *res.data); + }); + + fs.resume(); NetworkStatus::Set(NetworkStatus::Status::Online); loop.run(); diff --git a/test/storage/offline_download.test.cpp b/test/storage/offline_download.test.cpp index c1a9bb73f4..a15c96d391 100644 --- a/test/storage/offline_download.test.cpp +++ b/test/storage/offline_download.test.cpp @@ -6,7 +6,6 @@ #include <mbgl/test/sqlite3_test_fs.hpp> #include <mbgl/gfx/headless_frontend.hpp> -#include <mbgl/storage/default_file_source.hpp> #include <mbgl/storage/offline.hpp> #include <mbgl/storage/offline_database.hpp> #include <mbgl/storage/offline_download.hpp> @@ -64,7 +63,7 @@ public: } util::RunLoop loop; - StubOnlineFileSource fileSource; + StubFileSource fileSource; OfflineDatabase db; std::size_t size = 0; @@ -386,7 +385,7 @@ TEST(OfflineDownload, DoesNotFloodTheFileSourceWithRequests) { fileSource.respond(Resource::Kind::Style, test.response("style.json")); test.loop.runOnce(); - EXPECT_EQ(fileSource.getMaximumConcurrentRequests(), fileSource.requests.size()); + EXPECT_EQ(*fileSource.getProperty("max-concurrent-requests").getUint(), fileSource.requests.size()); } TEST(OfflineDownload, GetStatusNoResources) { @@ -822,7 +821,6 @@ TEST(OfflineDownload, AllOfflineRequestsHaveLowPriorityAndOfflineUsage) { test.loop.run(); } - #ifndef __QT__ // Qt doesn't expose the ability to register virtual file system handlers. TEST(OfflineDownload, DiskFull) { FixtureLog log; diff --git a/test/storage/online_file_source.test.cpp b/test/storage/online_file_source.test.cpp index 3e697a99ea..88dbf519f8 100644 --- a/test/storage/online_file_source.test.cpp +++ b/test/storage/online_file_source.test.cpp @@ -1,11 +1,12 @@ -#include <mbgl/test/util.hpp> -#include <mbgl/storage/online_file_source.hpp> #include <mbgl/storage/network_status.hpp> +#include <mbgl/storage/online_file_source.hpp> +#include <mbgl/storage/resource.hpp> +#include <mbgl/test/util.hpp> #include <mbgl/util/chrono.hpp> +#include <mbgl/util/constants.hpp> #include <mbgl/util/run_loop.hpp> -#include <mbgl/util/timer.hpp> #include <mbgl/util/string.hpp> -#include <mbgl/util/constants.hpp> +#include <mbgl/util/timer.hpp> #include <gtest/gtest.h> @@ -52,9 +53,9 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(TemporaryError)) { OnlineFileSource fs; const auto start = Clock::now(); + int counter = 0; auto req = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/temporary-error" }, [&](Response res) { - static int counter = 0; switch (counter++) { case 0: { const auto duration = std::chrono::duration<const double>(Clock::now() - start).count(); @@ -92,10 +93,10 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(ConnectionError)) { OnlineFileSource fs; const auto start = Clock::now(); + int counter = 0; + int wait = 0; std::unique_ptr<AsyncRequest> req = fs.request({ Resource::Unknown, "http://127.0.0.1:3001/" }, [&](Response res) { - static int counter = 0; - static int wait = 0; const auto duration = std::chrono::duration<const double>(Clock::now() - start).count(); EXPECT_LT(wait - 0.01, duration) << "Backoff timer didn't wait 1 second"; EXPECT_GT(wait + 0.3, duration) << "Backoff timer fired too late"; @@ -157,10 +158,6 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(RetryDelayOnExpiredTile)) { EXPECT_EQ(nullptr, res.error); EXPECT_GT(util::now(), *res.expires); EXPECT_FALSE(res.mustRevalidate); - }); - - util::Timer timer; - timer.start(Milliseconds(500), Duration::zero(), [&] () { loop.stop(); }); @@ -306,12 +303,13 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(NetworkStatusChange)) { TEST(OnlineFileSource, TEST_REQUIRES_SERVER(NetworkStatusChangePreempt)) { util::RunLoop loop; OnlineFileSource fs; + fs.pause(); const auto start = Clock::now(); + int counter = 0; const Resource resource{ Resource::Unknown, "http://127.0.0.1:3001/test" }; std::unique_ptr<AsyncRequest> req = fs.request(resource, [&](Response res) { - static int counter = 0; const auto duration = std::chrono::duration<const double>(Clock::now() - start).count(); if (counter == 0) { EXPECT_GT(0.2, duration) << "Response came in too late"; @@ -341,6 +339,7 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(NetworkStatusChangePreempt)) { mbgl::NetworkStatus::Reachable(); }); + fs.resume(); loop.run(); } @@ -416,14 +415,30 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(RateLimitDefault)) { loop.run(); } +TEST(OnlineFileSource, GetBaseURLAndAccessTokenWhilePaused) { + util::RunLoop loop; + OnlineFileSource fs; + + fs.pause(); + + auto baseURL = "http://url"; + auto accessToken = "access_token"; + + fs.setProperty(API_BASE_URL_KEY, baseURL); + fs.setProperty(ACCESS_TOKEN_KEY, accessToken); + + EXPECT_EQ(*fs.getProperty(API_BASE_URL_KEY).getString(), baseURL); + EXPECT_EQ(*fs.getProperty(ACCESS_TOKEN_KEY).getString(), accessToken); +} + TEST(OnlineFileSource, ChangeAPIBaseURL){ util::RunLoop loop; OnlineFileSource fs; - EXPECT_EQ(mbgl::util::API_BASE_URL, fs.getAPIBaseURL()); + EXPECT_EQ(mbgl::util::API_BASE_URL, *fs.getProperty(API_BASE_URL_KEY).getString()); const std::string customURL = "test.domain"; - fs.setAPIBaseURL(customURL); - EXPECT_EQ(customURL, fs.getAPIBaseURL()); + fs.setProperty(API_BASE_URL_KEY, customURL); + EXPECT_EQ(customURL, *fs.getProperty(API_BASE_URL_KEY).getString()); } @@ -433,34 +448,38 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(LowHighPriorityRequests)) { std::size_t response_counter = 0; const std::size_t NUM_REQUESTS = 3; - fs.setMaximumConcurrentRequests(1); - NetworkStatus::Set(NetworkStatus::Status::Offline); - - // requesting a low priority resource - Resource low_prio{ Resource::Unknown, "http://127.0.0.1:3000/load/1" }; - low_prio.setPriority(Resource::Priority::Low); - std::unique_ptr<AsyncRequest> req_0 = fs.request(low_prio, [&](Response) { + fs.setProperty("max-concurrent-requests", 1u); + // After DefaultFileSource was split, OnlineFileSource lives on a separate + // thread. Pause OnlineFileSource, so that messages are queued for processing. + fs.pause(); + + // First regular request. + Resource regular1{Resource::Unknown, "http://127.0.0.1:3000/load/1"}; + std::unique_ptr<AsyncRequest> req_0 = fs.request(regular1, [&](Response) { response_counter++; req_0.reset(); - EXPECT_EQ(response_counter, NUM_REQUESTS); // make sure this is responded last - loop.stop(); }); - // requesting two "regular" resources - Resource regular1{ Resource::Unknown, "http://127.0.0.1:3000/load/2" }; - std::unique_ptr<AsyncRequest> req_1 = fs.request(regular1, [&](Response) { + // Low priority request that will be queued and should be requested last. + Resource low_prio{Resource::Unknown, "http://127.0.0.1:3000/load/2"}; + low_prio.setPriority(Resource::Priority::Low); + std::unique_ptr<AsyncRequest> req_1 = fs.request(low_prio, [&](Response) { response_counter++; req_1.reset(); + EXPECT_EQ(response_counter, NUM_REQUESTS); // make sure this is responded last + loop.stop(); }); + + // Second regular priority request that should de-preoritize low priority request. Resource regular2{ Resource::Unknown, "http://127.0.0.1:3000/load/3" }; std::unique_ptr<AsyncRequest> req_2 = fs.request(regular2, [&](Response) { response_counter++; req_2.reset(); }); + fs.resume(); NetworkStatus::Set(NetworkStatus::Status::Online); - loop.run(); } @@ -472,10 +491,9 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(LowHighPriorityRequestsMany)) { int correct_low = 0; int correct_regular = 0; - - fs.setMaximumConcurrentRequests(1); - NetworkStatus::Set(NetworkStatus::Status::Offline); + fs.setProperty("max-concurrent-requests", 1u); + fs.pause(); std::vector<std::unique_ptr<AsyncRequest>> collector; @@ -515,8 +533,8 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(LowHighPriorityRequestsMany)) { } } + fs.resume(); NetworkStatus::Set(NetworkStatus::Status::Online); - loop.run(); } @@ -524,11 +542,12 @@ TEST(OnlineFileSource, TEST_REQUIRES_SERVER(MaximumConcurrentRequests)) { util::RunLoop loop; OnlineFileSource fs; - ASSERT_EQ(fs.getMaximumConcurrentRequests(), 20u); + ASSERT_EQ(*fs.getProperty("max-concurrent-requests").getUint(), 20u); - fs.setMaximumConcurrentRequests(10); - ASSERT_EQ(fs.getMaximumConcurrentRequests(), 10u); + fs.setProperty("max-concurrent-requests", 10u); + ASSERT_EQ(*fs.getProperty("max-concurrent-requests").getUint(), 10u); } + TEST(OnlineFileSource, TEST_REQUIRES_SERVER(RequestSameUrlMultipleTimes)) { util::RunLoop loop; OnlineFileSource fs; diff --git a/test/storage/sync_file_source.test.cpp b/test/storage/sync_file_source.test.cpp index 4bd964199d..3cd6cd9f6e 100644 --- a/test/storage/sync_file_source.test.cpp +++ b/test/storage/sync_file_source.test.cpp @@ -1,11 +1,12 @@ -#include <mbgl/util/run_loop.hpp> -#include <mbgl/util/io.hpp> -#include <mbgl/storage/file_source.hpp> #include <mbgl/gfx/headless_frontend.hpp> #include <mbgl/map/map.hpp> #include <mbgl/map/map_impl.hpp> +#include <mbgl/storage/file_source.hpp> +#include <mbgl/storage/resource.hpp> #include <mbgl/style/style.hpp> #include <mbgl/test/map_adapter.hpp> +#include <mbgl/util/io.hpp> +#include <mbgl/util/run_loop.hpp> #include <unordered_map> #include <gtest/gtest.h> @@ -14,7 +15,7 @@ using namespace mbgl; class SyncFileSource : public FileSource { public: - std::unique_ptr<AsyncRequest> request(const Resource& resource, FileSource::Callback callback) { + std::unique_ptr<AsyncRequest> request(const Resource& resource, FileSource::Callback callback) override { Response response; auto it = assets.find(resource.url); if (it == assets.end()) { @@ -27,6 +28,8 @@ public: return nullptr; } + bool canRequest(const Resource&) const override { return true; } + void add(std::string const& key, std::string const& data) { assets.emplace(key, std::make_shared<std::string>(data)); }; diff --git a/test/style/source.test.cpp b/test/style/source.test.cpp index 5eb837d92b..0286aaaec3 100644 --- a/test/style/source.test.cpp +++ b/test/style/source.test.cpp @@ -58,7 +58,7 @@ public: StubRenderSourceObserver renderSourceObserver; Transform transform; TransformState transformState; - Style style { *fileSource, 1 }; + Style style{fileSource, 1}; AnnotationManager annotationManager { style }; ImageManager imageManager; GlyphManager glyphManager; diff --git a/test/style/style.test.cpp b/test/style/style.test.cpp index b9e19d5a85..c866431ac1 100644 --- a/test/style/style.test.cpp +++ b/test/style/style.test.cpp @@ -18,7 +18,7 @@ using namespace mbgl::style; TEST(Style, Properties) { util::RunLoop loop; - StubFileSource fileSource; + auto fileSource = std::make_shared<StubFileSource>(); Style::Impl style { fileSource, 1.0 }; style.loadJSON(R"STYLE({"name": "Test"})STYLE"); @@ -60,7 +60,7 @@ TEST(Style, Properties) { TEST(Style, DuplicateSource) { util::RunLoop loop; - StubFileSource fileSource; + auto fileSource = std::make_shared<StubFileSource>(); Style::Impl style { fileSource, 1.0 }; style.loadJSON(util::read_file("test/fixtures/resources/style-unused-sources.json")); @@ -81,7 +81,7 @@ TEST(Style, RemoveSourceInUse) { auto log = new FixtureLogObserver(); Log::setObserver(std::unique_ptr<Log::Observer>(log)); - StubFileSource fileSource; + auto fileSource = std::make_shared<StubFileSource>(); Style::Impl style { fileSource, 1.0 }; style.loadJSON(util::read_file("test/fixtures/resources/style-unused-sources.json")); @@ -106,7 +106,7 @@ TEST(Style, RemoveSourceInUse) { TEST(Style, SourceImplsOrder) { util::RunLoop loop; - StubFileSource fileSource; + auto fileSource = std::make_shared<StubFileSource>(); Style::Impl style{fileSource, 1.0}; style.addSource(std::make_unique<VectorSource>("c", "mapbox://mapbox.mapbox-terrain-v2")); diff --git a/test/style/style_layer.test.cpp b/test/style/style_layer.test.cpp index 1d60197c2d..77e936ff3b 100644 --- a/test/style/style_layer.test.cpp +++ b/test/style/style_layer.test.cpp @@ -283,7 +283,7 @@ TEST(Layer, DuplicateLayer) { util::RunLoop loop; // Setup style - StubFileSource fileSource; + auto fileSource = std::make_shared<StubFileSource>(); Style::Impl style { fileSource, 1.0 }; style.loadJSON(util::read_file("test/fixtures/resources/style-unused-sources.json")); @@ -304,7 +304,7 @@ TEST(Layer, IncompatibleLayer) { util::RunLoop loop; // Setup style - StubFileSource fileSource; + auto fileSource = std::make_shared<StubFileSource>(); Style::Impl style{fileSource, 1.0}; style.loadJSON(util::read_file("test/fixtures/resources/style-unused-sources.json")); diff --git a/test/test-files.json b/test/test-files.json index b997503877..8691583765 100644 --- a/test/test-files.json +++ b/test/test-files.json @@ -36,10 +36,10 @@ "test/src/mbgl/test/test.cpp", "test/src/mbgl/test/util.cpp", "test/storage/asset_file_source.test.cpp", - "test/storage/default_file_source.test.cpp", "test/storage/headers.test.cpp", "test/storage/http_file_source.test.cpp", "test/storage/local_file_source.test.cpp", + "test/storage/main_resource_loader.test.cpp", "test/storage/offline.test.cpp", "test/storage/offline_database.test.cpp", "test/storage/offline_download.test.cpp", diff --git a/test/tile/custom_geometry_tile.test.cpp b/test/tile/custom_geometry_tile.test.cpp index fb905ac076..f3d11ab898 100644 --- a/test/tile/custom_geometry_tile.test.cpp +++ b/test/tile/custom_geometry_tile.test.cpp @@ -25,7 +25,7 @@ public: std::shared_ptr<FileSource> fileSource = std::make_shared<FakeFileSource>(); TransformState transformState; util::RunLoop loop; - style::Style style { *fileSource, 1 }; + style::Style style{fileSource, 1}; AnnotationManager annotationManager { style }; ImageManager imageManager; GlyphManager glyphManager; diff --git a/test/tile/geojson_tile.test.cpp b/test/tile/geojson_tile.test.cpp index d4bf1e0752..25fd268dc8 100644 --- a/test/tile/geojson_tile.test.cpp +++ b/test/tile/geojson_tile.test.cpp @@ -25,7 +25,7 @@ public: std::shared_ptr<FileSource> fileSource = std::make_shared<FakeFileSource>(); TransformState transformState; util::RunLoop loop; - style::Style style { *fileSource, 1 }; + style::Style style{fileSource, 1}; AnnotationManager annotationManager { style }; ImageManager imageManager; GlyphManager glyphManager; diff --git a/test/tile/raster_dem_tile.test.cpp b/test/tile/raster_dem_tile.test.cpp index 42e7594720..f5f7610096 100644 --- a/test/tile/raster_dem_tile.test.cpp +++ b/test/tile/raster_dem_tile.test.cpp @@ -19,7 +19,7 @@ public: std::shared_ptr<FileSource> fileSource = std::make_shared<FakeFileSource>(); TransformState transformState; util::RunLoop loop; - style::Style style { *fileSource, 1 }; + style::Style style{fileSource, 1}; AnnotationManager annotationManager { style }; ImageManager imageManager; GlyphManager glyphManager; diff --git a/test/tile/raster_tile.test.cpp b/test/tile/raster_tile.test.cpp index f19bd26260..a5a2875f2e 100644 --- a/test/tile/raster_tile.test.cpp +++ b/test/tile/raster_tile.test.cpp @@ -19,7 +19,7 @@ public: std::shared_ptr<FileSource> fileSource = std::make_shared<FakeFileSource>(); TransformState transformState; util::RunLoop loop; - style::Style style { *fileSource, 1 }; + style::Style style{fileSource, 1}; AnnotationManager annotationManager { style }; ImageManager imageManager; GlyphManager glyphManager; diff --git a/test/tile/tile_cache.test.cpp b/test/tile/tile_cache.test.cpp index 7a89ece756..43b409ae87 100644 --- a/test/tile/tile_cache.test.cpp +++ b/test/tile/tile_cache.test.cpp @@ -28,7 +28,7 @@ public: std::shared_ptr<FileSource> fileSource = std::make_shared<FakeFileSource>(); TransformState transformState; util::RunLoop loop; - style::Style style{*fileSource, 1}; + style::Style style{fileSource, 1}; AnnotationManager annotationManager{style}; ImageManager imageManager; GlyphManager glyphManager; diff --git a/test/tile/vector_tile.test.cpp b/test/tile/vector_tile.test.cpp index 940c0272db..d282c874ef 100644 --- a/test/tile/vector_tile.test.cpp +++ b/test/tile/vector_tile.test.cpp @@ -25,7 +25,7 @@ public: std::shared_ptr<FileSource> fileSource = std::make_shared<FakeFileSource>(); TransformState transformState; util::RunLoop loop; - style::Style style { *fileSource, 1 }; + style::Style style{fileSource, 1}; AnnotationManager annotationManager { style }; ImageManager imageManager; GlyphManager glyphManager; |