diff options
Diffstat (limited to 'test/map/map.test.cpp')
-rw-r--r-- | test/map/map.test.cpp | 153 |
1 files changed, 132 insertions, 21 deletions
diff --git a/test/map/map.test.cpp b/test/map/map.test.cpp index 5311aeb17f..8eedeb3c01 100644 --- a/test/map/map.test.cpp +++ b/test/map/map.test.cpp @@ -4,15 +4,16 @@ #include <mbgl/test/fixture_log_observer.hpp> #include <mbgl/map/map.hpp> -#include <mbgl/platform/default/headless_backend.hpp> -#include <mbgl/platform/default/offscreen_view.hpp> -#include <mbgl/platform/default/thread_pool.hpp> +#include <mbgl/gl/headless_backend.hpp> +#include <mbgl/gl/offscreen_view.hpp> +#include <mbgl/util/default_thread_pool.hpp> #include <mbgl/sprite/sprite_image.hpp> #include <mbgl/storage/network_status.hpp> #include <mbgl/storage/default_file_source.hpp> #include <mbgl/util/image.hpp> #include <mbgl/util/io.hpp> #include <mbgl/util/run_loop.hpp> +#include <mbgl/util/async_task.hpp> #include <mbgl/style/layers/background_layer.hpp> #include <mbgl/util/color.hpp> @@ -22,7 +23,7 @@ using namespace std::literals::string_literals; struct MapTest { util::RunLoop runLoop; - HeadlessBackend backend; + HeadlessBackend backend { test::sharedDisplay() }; OffscreenView view { backend.getContext() }; StubFileSource fileSource; ThreadPool threadPool { 4 }; @@ -30,7 +31,7 @@ struct MapTest { TEST(Map, LatLngBehavior) { MapTest test; - Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still); + Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still); map.setStyleJSON(util::read_file("test/fixtures/api/empty.json")); @@ -64,7 +65,7 @@ TEST(Map, Offline) { fileSource.put(Resource::glyphs(prefix + "{fontstack}/{range}.pbf", {{"Helvetica"}}, {0, 255}), expiredItem("glyph.pbf")); NetworkStatus::Set(NetworkStatus::Status::Offline); - Map map(test.backend, test.view.getSize(), 1, fileSource, test.threadPool, MapMode::Still); + Map map(test.backend, test.view.size, 1, fileSource, test.threadPool, MapMode::Still); map.setStyleURL(prefix + "style.json"); test::checkImage("test/fixtures/map/offline", @@ -88,7 +89,7 @@ TEST(Map, SetStyleInvalidJSON) { }); { - Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, + Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still); map.setStyleJSON("invalid"); } @@ -120,7 +121,7 @@ TEST(Map, SetStyleInvalidURL) { } }); - Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still); + Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still); map.setStyleURL("mapbox://bar"); test.runLoop.run(); @@ -129,7 +130,7 @@ TEST(Map, SetStyleInvalidURL) { TEST(Map, DoubleStyleLoad) { MapTest test; - Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still); + Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still); map.setStyleJSON(""); map.setStyleJSON(""); } @@ -140,7 +141,7 @@ TEST(Map, StyleFresh) { MapTest test; FakeFileSource fileSource; - Map map(test.backend, test.view.getSize(), 1, fileSource, test.threadPool, MapMode::Still); + Map map(test.backend, test.view.size, 1, fileSource, test.threadPool, MapMode::Still); map.setStyleURL("mapbox://styles/test"); EXPECT_EQ(1u, fileSource.requests.size()); @@ -160,7 +161,7 @@ TEST(Map, StyleExpired) { MapTest test; FakeFileSource fileSource; - Map map(test.backend, test.view.getSize(), 1, fileSource, test.threadPool, MapMode::Still); + Map map(test.backend, test.view.size, 1, fileSource, test.threadPool, MapMode::Still); map.setStyleURL("mapbox://styles/test"); EXPECT_EQ(1u, fileSource.requests.size()); @@ -187,7 +188,7 @@ TEST(Map, StyleExpiredWithAnnotations) { MapTest test; FakeFileSource fileSource; - Map map(test.backend, test.view.getSize(), 1, fileSource, test.threadPool, MapMode::Still); + Map map(test.backend, test.view.size, 1, fileSource, test.threadPool, MapMode::Still); map.setStyleURL("mapbox://styles/test"); EXPECT_EQ(1u, fileSource.requests.size()); @@ -211,7 +212,7 @@ TEST(Map, StyleEarlyMutation) { MapTest test; FakeFileSource fileSource; - Map map(test.backend, test.view.getSize(), 1, fileSource, test.threadPool, MapMode::Still); + Map map(test.backend, test.view.size, 1, fileSource, test.threadPool, MapMode::Still); map.setStyleURL("mapbox://styles/test"); map.addLayer(std::make_unique<style::BackgroundLayer>("bg")); @@ -225,7 +226,7 @@ TEST(Map, StyleEarlyMutation) { TEST(Map, StyleLoadedSignal) { MapTest test; - Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still); + Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still); // The map should emit a signal on style loaded bool emitted = false; @@ -246,7 +247,7 @@ TEST(Map, StyleLoadedSignal) { TEST(Map, AddLayer) { MapTest test; - Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still); + Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still); map.setStyleJSON(util::read_file("test/fixtures/api/empty.json")); auto layer = std::make_unique<BackgroundLayer>("background"); @@ -259,7 +260,7 @@ TEST(Map, AddLayer) { TEST(Map, RemoveLayer) { MapTest test; - Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still); + Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still); map.setStyleJSON(util::read_file("test/fixtures/api/empty.json")); auto layer = std::make_unique<BackgroundLayer>("background"); @@ -284,7 +285,7 @@ TEST(Map, DisabledSources) { return {}; }; - Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still); + Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still); map.setZoom(1); // This stylesheet has two raster layers, one that starts at zoom 1, the other at zoom 0. @@ -334,7 +335,7 @@ TEST(Map, DisabledSources) { TEST(Map, Classes) { MapTest test; - Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still); + Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still); map.setStyleJSON(util::read_file("test/fixtures/api/empty.json")); EXPECT_FALSE(map.getTransitionOptions().duration); @@ -368,7 +369,7 @@ TEST(Map, Classes) { TEST(Map, AddImage) { MapTest test; - Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still); + Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still); auto decoded1 = decodeImage(util::read_file("test/fixtures/sprites/default_marker.png")); auto decoded2 = decodeImage(util::read_file("test/fixtures/sprites/default_marker.png")); auto image1 = std::make_unique<SpriteImage>(std::move(decoded1), 1.0); @@ -385,7 +386,7 @@ TEST(Map, AddImage) { TEST(Map, RemoveImage) { MapTest test; - Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still); + Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still); auto decoded = decodeImage(util::read_file("test/fixtures/sprites/default_marker.png")); auto image = std::make_unique<SpriteImage>(std::move(decoded), 1.0); @@ -398,7 +399,7 @@ TEST(Map, RemoveImage) { TEST(Map, GetImage) { MapTest test; - Map map(test.backend, test.view.getSize(), 1, test.fileSource, test.threadPool, MapMode::Still); + Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still); auto decoded = decodeImage(util::read_file("test/fixtures/sprites/default_marker.png")); auto image = std::make_unique<SpriteImage>(std::move(decoded), 1.0); @@ -406,3 +407,113 @@ TEST(Map, GetImage) { map.addImage("test-icon", std::move(image)); test::checkImage("test/fixtures/map/get_icon", map.getImage("test-icon")->image); } + +TEST(Map, DontLoadUnneededTiles) { + MapTest test; + + Map map(test.backend, test.view.size, 1, test.fileSource, test.threadPool, MapMode::Still); + map.setStyleJSON(R"STYLE({ + "sources": { + "a": { "type": "vector", "tiles": [ "a/{z}/{x}/{y}" ] } + }, + "layers": [{ + "id": "a", + "type": "fill", + "source": "a", + "source-layer": "a", + "minzoom": 0.3, + "maxzoom": 1.6 + }] +})STYLE"); + + using Tiles = std::unordered_set<std::string>; + Tiles tiles; + + test.fileSource.tileResponse = [&](const Resource& rsc) { + tiles.emplace(rsc.url); + Response res; + res.noContent = true; + return res; + }; + + std::unordered_map<double, Tiles> referenceTiles = { + // Since the layer's minzoom is 0.3, we shouldn't load tiles before z0.3 + { 0.3, { "a/0/0/0" } }, + { 1.0, { "a/1/1/0", "a/1/0/1", "a/1/0/0", "a/1/1/1" } }, + // Since the layer's maxzoom is 1.6, we should never load z2 or z3 tiles. + }; + + // Loop through zoom levels from 0 to 3 and check that the correct tiles are loaded at every + // step. The source is marked with maxzoom 1.0, which means that it won't be visible anymore + // after z1.0, so we should under no circumstances attempt to load z2 tiles. + for (unsigned zoom = 0; zoom <= 30; zoom++) { // times 10 + // Note: using z += 0.1 in the loop doesn't produce accurate floating point numbers. + const double z = double(zoom) / 10; + tiles.clear(); + map.setZoom(z); + test::render(map, test.view); + EXPECT_EQ(referenceTiles[z], tiles) << "zoom level " << z; + } +} + + +class MockBackend : public HeadlessBackend { +public: + MockBackend(std::shared_ptr<HeadlessDisplay> display_) + : HeadlessBackend(display_) { + } + + std::function<void()> callback; + void invalidate() override { + if (callback) { + callback(); + } + } +}; + +TEST(Map, TEST_DISABLED_ON_CI(ContinuousRendering)) { + util::RunLoop runLoop; + MockBackend backend { test::sharedDisplay() }; + OffscreenView view { backend.getContext() }; + ThreadPool threadPool { 4 }; + +#ifdef MBGL_ASSET_ZIP + // Regenerate with `cd test/fixtures/api/ && zip -r assets.zip assets/` + DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets.zip"); +#else + DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets"); +#endif + + Map map(backend, view.size, 1, fileSource, threadPool, MapMode::Continuous); + + using namespace std::chrono_literals; + + util::Timer emergencyShutoff; + emergencyShutoff.start(10s, 0s, [&] { + util::RunLoop::Get()->stop(); + FAIL() << "Did not stop rendering"; + }); + + util::Timer timer; + util::AsyncTask render{[&] { + if (map.isFullyLoaded()) { + // Abort the test after 1 second after the map loading fully. Note that a "fully loaded + // map" doesn't mean that we won't render anymore: we could still render fade in/fade + // out or other animations. + // If we are continuing to render indefinitely, the emergency shutoff above will trigger + // and the test will fail since the regular time will be constantly reset. + timer.start(1s, 0s, [&] { + util::RunLoop::Get()->stop(); + }); + } + + map.render(view); + }}; + + backend.callback = [&] { + render.send(); + }; + + map.setStyleJSON(util::read_file("test/fixtures/api/water.json")); + util::RunLoop::Get()->run(); +} |