diff options
author | Molly Lloyd <mollymerp@users.noreply.github.com> | 2018-01-23 10:49:23 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-01-23 10:49:23 -0800 |
commit | f3294200c6c866e5ab031ad8346c59a76aa37249 (patch) | |
tree | 6d9aedb552552607641a15c415a60be99a0877d5 /test | |
parent | 2d15aed43c9faa875a8f625c3afc286f1175e0ce (diff) | |
download | qtlocation-mapboxgl-f3294200c6c866e5ab031ad8346c59a76aa37249.tar.gz |
[core] add raster-dem source type and hillshade layer type (#10642)
Diffstat (limited to 'test')
-rw-r--r-- | test/geometry/dem_data.test.cpp | 140 | ||||
-rw-r--r-- | test/style/source.test.cpp | 194 | ||||
-rw-r--r-- | test/tile/raster_dem_tile.test.cpp | 93 |
3 files changed, 427 insertions, 0 deletions
diff --git a/test/geometry/dem_data.test.cpp b/test/geometry/dem_data.test.cpp new file mode 100644 index 0000000000..30091973b2 --- /dev/null +++ b/test/geometry/dem_data.test.cpp @@ -0,0 +1,140 @@ +#include <mbgl/test/util.hpp> + +#include <mbgl/util/image.hpp> +#include <mbgl/geometry/dem_data.hpp> + +using namespace mbgl; + +auto fakeImage = [](Size s) { + PremultipliedImage img = PremultipliedImage(s); + + for (size_t i = 0; i < img.bytes(); i ++) { + img.data[i] = (i+1) % 4 == 0 ? 1 : std::rand() % 255; + } + return img; +}; + +TEST(DEMData, Constructor) { + PremultipliedImage image = fakeImage({16, 16}); + DEMData pyramid(image); + + EXPECT_EQ(pyramid.dim, 16); + EXPECT_EQ(pyramid.border, 8); + EXPECT_EQ(pyramid.stride, 32); + EXPECT_EQ(pyramid.getImage()->bytes(), size_t(32*32*4)); + EXPECT_EQ(pyramid.dim, 16); + EXPECT_EQ(pyramid.border, 8); +}; + +TEST(DEMData, RoundTrip) { + PremultipliedImage image = fakeImage({16, 16}); + DEMData pyramid(image); + + pyramid.set(4, 6, 255); + EXPECT_EQ(pyramid.get(4, 6), 255); +} + +TEST(DEMData, InitialBackfill) { + + PremultipliedImage image1 = fakeImage({4, 4}); + DEMData dem1(image1); + + bool nonempty = true; + // checking that a 1 px border around the fake image has been populated + // with a non-empty pixel value + for (int x = -1; x < 5; x++){ + for (int y = -1; y < 5; y ++) { + if (dem1.get(x, y) == -65536) { + nonempty = false; + break; + } + } + } + EXPECT_TRUE(nonempty); + + bool verticalBorderMatch = true; + int vertx[] = {-1, 4}; + for (int x : vertx) { + for (int y = 0; y < 4; y++) { + if (dem1.get(x, y) != dem1.get(x < 0 ? x + 1 : x - 1, y)) { + verticalBorderMatch = false; + break; + } + } + } + // vertical border of DEM data is initially equal to next column of data + EXPECT_TRUE(verticalBorderMatch); + + // horizontal borders empty + bool horizontalBorderMatch = true; + int horiz[] = {-1, 4}; + for (int y : horiz) { + for (int x = 0; x < 4; x++) { + if (dem1.get(x, y) != dem1.get(x, y < 0 ? y + 1 : y - 1)) { + horizontalBorderMatch = false; + break; + } + } + } + //horizontal border of DEM data is initially equal to next row of data + + EXPECT_TRUE(horizontalBorderMatch); + // -1, 1 corner initially equal to closest corner data + EXPECT_TRUE(dem1.get(-1, 4) == dem1.get(0, 3)); + // 1, 1 corner initially equal to closest corner data + EXPECT_TRUE(dem1.get(4, 4) == dem1.get(3, 3)); + // -1, -1 corner initially equal to closest corner data + EXPECT_TRUE(dem1.get(-1, -1) == dem1.get(0, 0)); + // -1, 1 corner initially equal to closest corner data + EXPECT_TRUE(dem1.get(4, -1) == dem1.get(3, 0)); +}; + +TEST(DEMData, BackfillNeighbor) { + PremultipliedImage image1 = fakeImage({4, 4}); + DEMData dem0(image1); + + PremultipliedImage image2 = fakeImage({4, 4}); + DEMData dem1(image2); + + dem0.backfillBorder(dem1, -1, 0); + for (int y = 0; y < 4; y++) { + // dx = -1, dy = 0, so the left edge of dem1 should equal the right edge of dem0 + // backfills Left neighbor + EXPECT_TRUE(dem0.get(-1, y) == dem1.get(3, y)); + + } + + dem0.backfillBorder(dem1, 0, -1); + // backfills TopCenter neighbor + for (int x = 0; x < 4; x++) { + EXPECT_TRUE(dem0.get(x, -1) == dem1.get(x, 3)); + } + + dem0.backfillBorder(dem1, 1, 0); + // backfills Right neighbor + for (int y = 0; y < 4; y++) { + EXPECT_TRUE(dem0.get(4, y) == dem1.get(0, y)); + } + + dem0.backfillBorder(dem1, 0, 1); + // backfills BottomCenter neighbor + for (int x = 0; x < 4; x++) { + EXPECT_TRUE(dem0.get(x, 4) == dem1.get(x, 0)); + } + + dem0.backfillBorder(dem1, -1, 1); + // backfulls TopRight neighbor + EXPECT_TRUE(dem0.get(-1, 4) == dem1.get(3, 0)); + + dem0.backfillBorder(dem1, 1, 1); + // backfulls BottomRight neighbor + EXPECT_TRUE(dem0.get(4, 4) == dem1.get(0, 0)); + + dem0.backfillBorder(dem1, -1, -1); + // backfulls TopLeft neighbor + EXPECT_TRUE(dem0.get(-1, -1) == dem1.get(3, 3)); + + dem0.backfillBorder(dem1, 1, -1); + // backfulls BottomLeft neighbor + EXPECT_TRUE(dem0.get(4, -1) == dem1.get(0, 3)); +}; diff --git a/test/style/source.test.cpp b/test/style/source.test.cpp index eb419e8080..6cb01146f6 100644 --- a/test/style/source.test.cpp +++ b/test/style/source.test.cpp @@ -6,14 +6,17 @@ #include <mbgl/style/style.hpp> #include <mbgl/style/source_impl.hpp> #include <mbgl/style/sources/raster_source.hpp> +#include <mbgl/style/sources/raster_dem_source.hpp> #include <mbgl/style/sources/vector_source.hpp> #include <mbgl/style/sources/geojson_source.hpp> #include <mbgl/style/sources/image_source.hpp> #include <mbgl/style/sources/custom_geometry_source.hpp> +#include <mbgl/style/layers/hillshade_layer.cpp> #include <mbgl/style/layers/raster_layer.cpp> #include <mbgl/style/layers/line_layer.hpp> #include <mbgl/renderer/sources/render_raster_source.hpp> +#include <mbgl/renderer/sources/render_raster_dem_source.hpp> #include <mbgl/renderer/sources/render_vector_source.hpp> #include <mbgl/renderer/sources/render_geojson_source.hpp> #include <mbgl/renderer/tile_parameters.hpp> @@ -173,6 +176,44 @@ TEST(Source, RasterTileEmpty) { test.run(); } +TEST(Source, RasterDEMTileEmpty) { + SourceTest test; + + test.fileSource.tileResponse = [&] (const Resource&) { + Response response; + response.noContent = true; + return response; + }; + + HillshadeLayer layer("id", "source"); + std::vector<Immutable<Layer::Impl>> layers {{ layer.baseImpl }}; + + Tileset tileset; + tileset.tiles = { "tiles" }; + + RasterDEMSource source("source", tileset, 512); + source.loadDescription(test.fileSource); + + test.renderSourceObserver.tileChanged = [&] (RenderSource& source_, const OverscaledTileID&) { + EXPECT_EQ("source", source_.baseImpl->id); + test.end(); + }; + + test.renderSourceObserver.tileError = [&] (RenderSource&, const OverscaledTileID&, std::exception_ptr) { + FAIL() << "Should never be called"; + }; + + auto renderSource = RenderSource::create(source.baseImpl); + renderSource->setObserver(&test.renderSourceObserver); + renderSource->update(source.baseImpl, + layers, + true, + true, + test.tileParameters); + + test.run(); +} + TEST(Source, VectorTileEmpty) { SourceTest test; @@ -251,6 +292,44 @@ TEST(Source, RasterTileFail) { test.run(); } +TEST(Source, RasterDEMTileFail) { + SourceTest test; + + test.fileSource.tileResponse = [&] (const Resource&) { + Response response; + response.error = std::make_unique<Response::Error>( + Response::Error::Reason::Other, + "Failed by the test case"); + return response; + }; + + HillshadeLayer layer("id", "source"); + std::vector<Immutable<Layer::Impl>> layers {{ layer.baseImpl }}; + + Tileset tileset; + tileset.tiles = { "tiles" }; + + RasterDEMSource source("source", tileset, 512); + source.loadDescription(test.fileSource); + + test.renderSourceObserver.tileError = [&] (RenderSource& source_, const OverscaledTileID& tileID, std::exception_ptr error) { + EXPECT_EQ(SourceType::RasterDEM, source_.baseImpl->type); + EXPECT_EQ(OverscaledTileID(0, 0, 0), tileID); + EXPECT_EQ("Failed by the test case", util::toString(error)); + test.end(); + }; + + auto renderSource = RenderSource::create(source.baseImpl); + renderSource->setObserver(&test.renderSourceObserver); + renderSource->update(source.baseImpl, + layers, + true, + true, + test.tileParameters); + + test.run(); +} + TEST(Source, VectorTileFail) { SourceTest test; @@ -328,6 +407,43 @@ TEST(Source, RasterTileCorrupt) { test.run(); } +TEST(Source, RasterDEMTileCorrupt) { + SourceTest test; + + test.fileSource.tileResponse = [&] (const Resource&) { + Response response; + response.data = std::make_unique<std::string>("CORRUPTED"); + return response; + }; + + HillshadeLayer layer("id", "source"); + std::vector<Immutable<Layer::Impl>> layers {{ layer.baseImpl }}; + + Tileset tileset; + tileset.tiles = { "tiles" }; + + RasterDEMSource source("source", tileset, 512); + source.loadDescription(test.fileSource); + + test.renderSourceObserver.tileError = [&] (RenderSource& source_, const OverscaledTileID& tileID, std::exception_ptr error) { + EXPECT_EQ(source_.baseImpl->type, SourceType::RasterDEM); + EXPECT_EQ(OverscaledTileID(0, 0, 0), tileID); + EXPECT_TRUE(bool(error)); + // Not asserting on platform-specific error text. + test.end(); + }; + + auto renderSource = RenderSource::create(source.baseImpl); + renderSource->setObserver(&test.renderSourceObserver); + renderSource->update(source.baseImpl, + layers, + true, + true, + test.tileParameters); + + test.run(); +} + TEST(Source, VectorTileCorrupt) { SourceTest test; @@ -402,6 +518,42 @@ TEST(Source, RasterTileCancel) { test.run(); } +TEST(Source, RasterDEMTileCancel) { + SourceTest test; + + test.fileSource.tileResponse = [&] (const Resource&) { + test.end(); + return optional<Response>(); + }; + + HillshadeLayer layer("id", "source"); + std::vector<Immutable<Layer::Impl>> layers {{ layer.baseImpl }}; + + Tileset tileset; + tileset.tiles = { "tiles" }; + + RasterDEMSource source("source", tileset, 512); + source.loadDescription(test.fileSource); + + test.renderSourceObserver.tileChanged = [&] (RenderSource&, const OverscaledTileID&) { + FAIL() << "Should never be called"; + }; + + test.renderSourceObserver.tileError = [&] (RenderSource&, const OverscaledTileID&, std::exception_ptr) { + FAIL() << "Should never be called"; + }; + + auto renderSource = RenderSource::create(source.baseImpl); + renderSource->setObserver(&test.renderSourceObserver); + renderSource->update(source.baseImpl, + layers, + true, + true, + test.tileParameters); + + test.run(); +} + TEST(Source, VectorTileCancel) { SourceTest test; @@ -484,6 +636,48 @@ TEST(Source, RasterTileAttribution) { test.run(); } +TEST(Source, RasterDEMTileAttribution) { + SourceTest test; + + HillshadeLayer layer("id", "source"); + std::vector<Immutable<Layer::Impl>> layers {{ layer.baseImpl }}; + + std::string mapbox = ("<a href='https://www.mapbox.com/about/maps/' target='_blank'>© Mapbox</a> "); + + test.fileSource.tileResponse = [&] (const Resource&) { + Response response; + response.noContent = true; + return response; + }; + + test.fileSource.sourceResponse = [&] (const Resource& resource) { + EXPECT_EQ("url", resource.url); + Response response; + response.data = std::make_unique<std::string>(R"TILEJSON({ "tilejson": "2.1.0", "attribution": ")TILEJSON" + + mapbox + + R"TILEJSON(", "tiles": [ "tiles" ] })TILEJSON"); + return response; + }; + + test.styleObserver.sourceChanged = [&] (Source& source) { + EXPECT_EQ(mapbox, source.getAttribution()); + test.end(); + }; + + RasterDEMSource source("source", "url", 512); + source.setObserver(&test.styleObserver); + source.loadDescription(test.fileSource); + + auto renderSource = RenderSource::create(source.baseImpl); + renderSource->update(source.baseImpl, + layers, + true, + true, + test.tileParameters); + + test.run(); +} + TEST(Source, GeoJSonSourceUrlUpdate) { SourceTest test; diff --git a/test/tile/raster_dem_tile.test.cpp b/test/tile/raster_dem_tile.test.cpp new file mode 100644 index 0000000000..c6f9b80b42 --- /dev/null +++ b/test/tile/raster_dem_tile.test.cpp @@ -0,0 +1,93 @@ +#include <mbgl/test/util.hpp> +#include <mbgl/test/fake_file_source.hpp> +#include <mbgl/tile/raster_dem_tile.hpp> +#include <mbgl/tile/tile_loader_impl.hpp> + +#include <mbgl/style/style.hpp> +#include <mbgl/util/default_thread_pool.hpp> +#include <mbgl/util/run_loop.hpp> +#include <mbgl/map/transform.hpp> +#include <mbgl/annotation/annotation_manager.hpp> +#include <mbgl/renderer/tile_parameters.hpp> +#include <mbgl/renderer/buckets/hillshade_bucket.hpp> +#include <mbgl/renderer/image_manager.hpp> +#include <mbgl/text/glyph_manager.hpp> + +using namespace mbgl; + +class RasterDEMTileTest { +public: + FakeFileSource fileSource; + TransformState transformState; + util::RunLoop loop; + ThreadPool threadPool { 1 }; + style::Style style { loop, fileSource, 1 }; + AnnotationManager annotationManager { style }; + ImageManager imageManager; + GlyphManager glyphManager { fileSource }; + Tileset tileset { { "https://example.com" }, { 0, 22 }, "none" }; + + TileParameters tileParameters { + 1.0, + MapDebugOptions(), + transformState, + threadPool, + fileSource, + MapMode::Continuous, + annotationManager, + imageManager, + glyphManager, + 0 + }; +}; + +TEST(RasterDEMTile, setError) { + RasterDEMTileTest test; + RasterDEMTile tile(OverscaledTileID(0, 0, 0), test.tileParameters, test.tileset); + tile.setError(std::make_exception_ptr(std::runtime_error("test"))); + EXPECT_FALSE(tile.isRenderable()); + EXPECT_TRUE(tile.isLoaded()); + EXPECT_TRUE(tile.isComplete()); +} + +TEST(RasterDEMTile, onError) { + RasterDEMTileTest test; + RasterDEMTile tile(OverscaledTileID(0, 0, 0), test.tileParameters, test.tileset); + tile.onError(std::make_exception_ptr(std::runtime_error("test")), 0); + EXPECT_FALSE(tile.isRenderable()); + EXPECT_TRUE(tile.isLoaded()); + EXPECT_TRUE(tile.isComplete()); +} + +TEST(RasterDEMTile, onParsed) { + RasterDEMTileTest test; + RasterDEMTile tile(OverscaledTileID(0, 0, 0), test.tileParameters, test.tileset); + tile.onParsed(std::make_unique<HillshadeBucket>(PremultipliedImage({16, 16})), 0); + EXPECT_TRUE(tile.isRenderable()); + EXPECT_TRUE(tile.isLoaded()); + EXPECT_TRUE(tile.isComplete()); + + // Make sure that once we've had a renderable tile and then receive erroneous data, we retain + // the previously rendered data and keep the tile renderable. + tile.setError(std::make_exception_ptr(std::runtime_error("Connection offline"))); + EXPECT_TRUE(tile.isRenderable()); + EXPECT_TRUE(tile.isLoaded()); + EXPECT_TRUE(tile.isComplete()); + + // Then simulate a parsing failure and make sure that we keep it renderable in this situation + // as well. + tile.onError(std::make_exception_ptr(std::runtime_error("Parse error")), 0); + ASSERT_TRUE(tile.isRenderable()); + EXPECT_TRUE(tile.isLoaded()); + EXPECT_TRUE(tile.isComplete()); +} + +TEST(RasterDEMTile, onParsedEmpty) { + RasterDEMTileTest test; + RasterDEMTile tile(OverscaledTileID(0, 0, 0), test.tileParameters, test.tileset); + tile.onParsed(nullptr, 0); + EXPECT_FALSE(tile.isRenderable()); + EXPECT_TRUE(tile.isLoaded()); + EXPECT_TRUE(tile.isComplete()); +} + |