diff options
-rw-r--r-- | include/mbgl/platform/log.hpp | 6 | ||||
-rw-r--r-- | include/mbgl/util/string.hpp | 9 | ||||
-rw-r--r-- | test/fixtures/resources/style.json | 2 | ||||
-rw-r--r-- | test/style/resource_loading.cpp | 219 |
4 files changed, 114 insertions, 122 deletions
diff --git a/include/mbgl/platform/log.hpp b/include/mbgl/platform/log.hpp index a2a9119905..cd072c37da 100644 --- a/include/mbgl/platform/log.hpp +++ b/include/mbgl/platform/log.hpp @@ -21,6 +21,12 @@ public: virtual bool onRecord(EventSeverity severity, Event event, int64_t code, const std::string &msg) = 0; }; + class NullObserver : public Observer { + bool onRecord(EventSeverity, Event, int64_t, const std::string&) override { + return true; + } + }; + static void setObserver(std::unique_ptr<Observer> Observer); static std::unique_ptr<Observer> removeObserver(); diff --git a/include/mbgl/util/string.hpp b/include/mbgl/util/string.hpp index 9e2b2d8819..bc6b3b1eff 100644 --- a/include/mbgl/util/string.hpp +++ b/include/mbgl/util/string.hpp @@ -22,6 +22,15 @@ inline std::string toString(int8_t num) { return boost::lexical_cast<std::string>(int(num)); } +inline std::string toString(std::exception_ptr error) { + try { + std::rethrow_exception(error); + } catch (const std::exception& ex) { + return ex.what(); + } catch (...) { + return "Unknown exception type"; + } +} template<size_t max, typename... Args> inline std::string sprintf(const char *msg, Args... args) { diff --git a/test/fixtures/resources/style.json b/test/fixtures/resources/style.json index f794d54fab..858e2de037 100644 --- a/test/fixtures/resources/style.json +++ b/test/fixtures/resources/style.json @@ -9,7 +9,7 @@ "rastersource": { "url": "test/fixtures/resources/source_raster.json", "type": "raster", - "tileSize": 256 + "tileSize": 512 } }, "sprite": "test/fixtures/resources/sprite", diff --git a/test/style/resource_loading.cpp b/test/style/resource_loading.cpp index ba6a138b5d..8330879844 100644 --- a/test/style/resource_loading.cpp +++ b/test/style/resource_loading.cpp @@ -11,164 +11,141 @@ #include <mbgl/util/run_loop.hpp> #include <mbgl/util/texture_pool.hpp> #include <mbgl/util/thread.hpp> - -#include <regex> +#include <mbgl/util/string.hpp> using namespace mbgl; -namespace { - -class MockMapContext : public Style::Observer { +class StyleObserver : public Style::Observer { public: - MockMapContext(View& view, - FileSource& fileSource, - const std::function<void(std::exception_ptr error)>& callback) - : data_(MapMode::Still, GLContextMode::Unique, view.getPixelRatio()), - transform_(view, ConstrainMode::HeightOnly), - callback_(callback) { - util::ThreadContext::setFileSource(&fileSource); - - transform_.resize({{ 1000, 1000 }}); - transform_.setLatLngZoom({0, 0}, 16); - - const std::string style = util::read_file("test/fixtures/resources/style.json"); - style_ = std::make_unique<Style>(data_); - style_->setJSON(style, ""); - style_->setObserver(this); + void onTileDataChanged() override { + tileDataChanged(); } - ~MockMapContext() { - cleanup(); + void onResourceLoadingFailed(std::exception_ptr error) override { + resourceLoadingFailed(error); } - void cleanup() { - style_.reset(); - } + std::function<void ()> tileDataChanged = [] {}; + std::function<void (std::exception_ptr)> resourceLoadingFailed = [] (auto) {}; +}; - void update() { - const auto now = Clock::now(); +std::string resourceErrorString(MockFileSource::Type type, const std::string& param) { + Log::setObserver(std::make_unique<Log::NullObserver>()); // Squelch logging. - data_.setAnimationTime(now); - transform_.updateTransitions(now); + util::RunLoop loop; - style_->cascade(); - style_->recalculate(16); - style_->update(transform_.getState(), texturePool_); - } + util::ThreadContext context("Map", util::ThreadType::Map, util::ThreadPriority::Regular); + util::ThreadContext::Set(&context); - // Style::Observer implementation. - void onTileDataChanged() override { - update(); + MockFileSource fileSource(type, param); + util::ThreadContext::setFileSource(&fileSource); - if (style_->isLoaded()) { - callback_(nullptr); - } - }; + MapData data(MapMode::Still, GLContextMode::Unique, 1.0); + MockView view; + Transform transform(view, ConstrainMode::HeightOnly); + TexturePool texturePool; + Style style(data); - void onResourceLoadingFailed(std::exception_ptr error) override { - callback_(error); - } + StyleObserver observer; + std::string result; -private: - MapData data_; - Transform transform_; - TexturePool texturePool_; + observer.tileDataChanged = [&] () { + // Prompt tile loading after sources load. + style.update(transform.getState(), texturePool); - std::unique_ptr<Style> style_; + if (style.isLoaded()) { + loop.stop(); + } + }; - std::function<void(std::exception_ptr error)> callback_; -}; + observer.resourceLoadingFailed = [&] (std::exception_ptr error) { + result = util::toString(error); + loop.stop(); + }; -void runTestCase(MockFileSource::Type type, - const std::string& param, - const std::string& message) { - util::RunLoop loop; + transform.resize({{ 512, 512 }}); + transform.setLatLngZoom({0, 0}, 0); - MockView view; - MockFileSource fileSource(type, param); + style.setObserver(&observer); + style.setJSON(util::read_file("test/fixtures/resources/style.json"), ""); + style.cascade(); + style.recalculate(16); - FixtureLogObserver* log = new FixtureLogObserver(); - Log::setObserver(std::unique_ptr<Log::Observer>(log)); + loop.run(); - auto callback = [type, &loop, ¶m](std::exception_ptr error) { - if (type == MockFileSource::Success) { - EXPECT_TRUE(error == nullptr); - } else { - EXPECT_TRUE(error != nullptr); - } + return result; +} - try { - if (error) { - std::rethrow_exception(error); - } - } catch (const util::GlyphRangeLoadingException&) { - EXPECT_EQ(param, "glyphs.pbf"); - } catch (const util::SourceLoadingException&) { - EXPECT_TRUE(param == "source_raster.json" || param == "source_vector.json"); - } catch (const util::SpriteLoadingException&) { - EXPECT_TRUE(param == "sprite.png" || param == "sprite.json"); - } catch (const util::TileLoadingException&) { - EXPECT_TRUE(param == "raster.png" || param == "vector.pbf"); - } catch (const std::exception&) { - EXPECT_TRUE(false) << "Unhandled exception."; - } +TEST(ResourceLoading, Success) { + EXPECT_EQ(resourceErrorString(MockFileSource::Success, ""), ""); +} - loop.stop(); - }; +TEST(ResourceLoading, RasterSourceFail) { + EXPECT_EQ(resourceErrorString(MockFileSource::RequestFail, "source_raster.json"), + "Failed to load [test/fixtures/resources/source_raster.json]: Failed by the test case"); +} - std::unique_ptr<util::Thread<MockMapContext>> context( - std::make_unique<util::Thread<MockMapContext>>( - util::ThreadContext{"Map", util::ThreadType::Map, util::ThreadPriority::Regular}, view, fileSource, callback)); +TEST(ResourceLoading, VectorSourceFail) { + EXPECT_EQ(resourceErrorString(MockFileSource::RequestFail, "source_vector.json"), + "Failed to load [test/fixtures/resources/source_vector.json]: Failed by the test case"); +} - loop.run(); +TEST(ResourceLoading, SpriteJSONFail) { + EXPECT_EQ(resourceErrorString(MockFileSource::RequestFail, "sprite.json"), + "Failed to load [test/fixtures/resources/sprite.json]: Failed by the test case"); +} - // Needed because it will make the Map thread - // join and cease logging after this point. - context->invoke(&MockMapContext::cleanup); - context.reset(); +TEST(ResourceLoading, SpriteImageFail) { + EXPECT_EQ(resourceErrorString(MockFileSource::RequestFail, "sprite.png"), + "Failed to load [test/fixtures/resources/sprite.png]: Failed by the test case"); +} - uint32_t match = 0; - std::vector<FixtureLogObserver::LogMessage> logMessages = log->unchecked(); +TEST(ResourceLoading, RasterTileFail) { + EXPECT_EQ(resourceErrorString(MockFileSource::RequestFail, "raster.png"), + "Failed to load [test/fixtures/resources/raster.png]: Failed by the test case"); +} - for (auto& logMessage : logMessages) { - if (std::regex_match(logMessage.msg, std::regex(message))) { - match++; - } - } +TEST(ResourceLoading, VectorTileFail) { + EXPECT_EQ(resourceErrorString(MockFileSource::RequestFail, "vector.pbf"), + "Failed to load [test/fixtures/resources/vector.pbf]: Failed by the test case"); +} - if (type == MockFileSource::Success) { - EXPECT_EQ(match, 0u); - } else { - EXPECT_GT(match, 0u); - } +TEST(ResourceLoading, GlyphsFail) { + EXPECT_EQ(resourceErrorString(MockFileSource::RequestFail, "glyphs.pbf"), + "Failed to load [test/fixtures/resources/glyphs.pbf]: Failed by the test case"); } -} // namespace +TEST(ResourceLoading, RasterSourceCorrupt) { + EXPECT_EQ(resourceErrorString(MockFileSource::RequestWithCorruptedData, "source_raster.json"), + "Failed to parse [test/fixtures/resources/source_raster.json]: 0 - Invalid value."); +} -class ResourceLoading : public ::testing::TestWithParam<std::pair<std::string, std::string>> { -}; +TEST(ResourceLoading, VectorSourceCorrupt) { + EXPECT_EQ(resourceErrorString(MockFileSource::RequestWithCorruptedData, "source_vector.json"), + "Failed to parse [test/fixtures/resources/source_vector.json]: 0 - Invalid value."); +} -TEST_P(ResourceLoading, Success) { - runTestCase(MockFileSource::Success, GetParam().first, std::string()); +TEST(ResourceLoading, SpriteJSONCorrupt) { + EXPECT_EQ(resourceErrorString(MockFileSource::RequestWithCorruptedData, "sprite.json"), + "Failed to parse JSON: Invalid value. at offset 0"); } -TEST_P(ResourceLoading, RequestFail) { - std::stringstream message; - message << "Failed to load \\[test\\/fixtures\\/resources\\/" << GetParam().first << "\\]\\: Failed by the test case"; +TEST(ResourceLoading, SpriteImageCorrupt) { + EXPECT_EQ(resourceErrorString(MockFileSource::RequestWithCorruptedData, "sprite.png"), + "Could not parse sprite image"); +} - runTestCase(MockFileSource::RequestFail, GetParam().first, message.str()); +TEST(ResourceLoading, RasterTileCorrupt) { + EXPECT_EQ(resourceErrorString(MockFileSource::RequestWithCorruptedData, "raster.png"), + "Failed to parse [0/0/0]: error parsing raster image"); } -TEST_P(ResourceLoading, RequestWithCorruptedData) { - runTestCase(MockFileSource::RequestWithCorruptedData, GetParam().first, GetParam().second); +TEST(ResourceLoading, VectorTileCorrupt) { + EXPECT_EQ(resourceErrorString(MockFileSource::RequestWithCorruptedData, "vector.pbf"), + "Failed to parse [0/0/0]: pbf unknown field type exception"); } -INSTANTIATE_TEST_CASE_P(Style, ResourceLoading, - ::testing::Values( - std::make_pair("source_raster.json", "Failed to parse \\[test\\/fixtures\\/resources\\/source_raster.json\\]: 0 - Invalid value."), - std::make_pair("source_vector.json", "Failed to parse \\[test\\/fixtures\\/resources\\/source_vector.json\\]: 0 - Invalid value."), - std::make_pair("sprite.json", "Failed to parse JSON: Invalid value. at offset 0"), - std::make_pair("sprite.png", "Could not parse sprite image"), - std::make_pair("raster.png", "Failed to parse \\[17\\/6553(4|5|6|7)\\/6553(4|5|6|7)\\]\\: error parsing raster image"), - std::make_pair("vector.pbf", "Failed to parse \\[1(5|6)\\/1638(3|4)\\/1638(3|4)\\]\\: pbf unknown field type exception"), - std::make_pair("glyphs.pbf", "Failed to parse \\[test\\/fixtures\\/resources\\/glyphs.pbf\\]: pbf unknown field type exception"))); +TEST(ResourceLoading, GlyphsCorrupt) { + EXPECT_EQ(resourceErrorString(MockFileSource::RequestWithCorruptedData, "glyphs.pbf"), + "Failed to parse [test/fixtures/resources/glyphs.pbf]: pbf unknown field type exception"); +} |