[tests] Moved lazy source loading tests to ResourceLoading
This commit is contained in:
@@ -18,18 +18,27 @@ using namespace mbgl;
|
||||
class StyleObserver : public Style::Observer {
|
||||
public:
|
||||
void onTileDataChanged() override {
|
||||
tileDataChanged();
|
||||
if (tileDataChanged) tileDataChanged();
|
||||
}
|
||||
|
||||
void onResourceLoadingFailed(std::exception_ptr error) override {
|
||||
resourceLoadingFailed(error);
|
||||
if (resourceLoadingFailed) resourceLoadingFailed(error);
|
||||
}
|
||||
|
||||
std::function<void ()> tileDataChanged = [] {};
|
||||
std::function<void (std::exception_ptr)> resourceLoadingFailed = [] (auto) {};
|
||||
std::function<void ()> tileDataChanged = nullptr;
|
||||
std::function<void (std::exception_ptr)> resourceLoadingFailed = nullptr;
|
||||
};
|
||||
|
||||
std::string resourceErrorString(MockFileSource::Type type, const std::string& param) {
|
||||
struct StyleTestData {
|
||||
MockFileSource::Type type;
|
||||
std::string style;
|
||||
std::string resource;
|
||||
std::string expectedError;
|
||||
std::string styleClass;
|
||||
std::function<void (const Style&)> callback = nullptr;
|
||||
};
|
||||
|
||||
void runTest(StyleTestData& testData) {
|
||||
Log::setObserver(std::make_unique<Log::NullObserver>()); // Squelch logging.
|
||||
|
||||
util::RunLoop loop;
|
||||
@@ -37,7 +46,7 @@ std::string resourceErrorString(MockFileSource::Type type, const std::string& pa
|
||||
util::ThreadContext context("Map", util::ThreadType::Map, util::ThreadPriority::Regular);
|
||||
util::ThreadContext::Set(&context);
|
||||
|
||||
MockFileSource fileSource(type, param);
|
||||
MockFileSource fileSource(testData.type, testData.resource);
|
||||
util::ThreadContext::setFileSource(&fileSource);
|
||||
|
||||
MapData data(MapMode::Still, GLContextMode::Unique, 1.0);
|
||||
@@ -47,7 +56,6 @@ std::string resourceErrorString(MockFileSource::Type type, const std::string& pa
|
||||
Style style(data);
|
||||
|
||||
StyleObserver observer;
|
||||
std::string result;
|
||||
|
||||
observer.tileDataChanged = [&] () {
|
||||
// Prompt tile loading after sources load.
|
||||
@@ -55,97 +63,188 @@ std::string resourceErrorString(MockFileSource::Type type, const std::string& pa
|
||||
|
||||
if (style.isLoaded()) {
|
||||
loop.stop();
|
||||
if (testData.callback) testData.callback(style);
|
||||
}
|
||||
};
|
||||
|
||||
observer.resourceLoadingFailed = [&] (std::exception_ptr error) {
|
||||
result = util::toString(error);
|
||||
loop.stop();
|
||||
testData.expectedError = util::toString(error);
|
||||
};
|
||||
|
||||
transform.resize({{ 512, 512 }});
|
||||
transform.setLatLngZoom({0, 0}, 0);
|
||||
|
||||
style.setObserver(&observer);
|
||||
style.setJSON(util::read_file("test/fixtures/resources/style.json"), "");
|
||||
style.setJSON(util::read_file(testData.style), "");
|
||||
|
||||
if (!testData.styleClass.empty()) data.addClass(testData.styleClass);
|
||||
|
||||
style.cascade();
|
||||
style.recalculate(16);
|
||||
|
||||
loop.run();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
TEST(ResourceLoading, Success) {
|
||||
EXPECT_EQ(resourceErrorString(MockFileSource::Success, ""), "");
|
||||
StyleTestData testData;
|
||||
testData.type = MockFileSource::Success;
|
||||
testData.style = "test/fixtures/resources/style.json";
|
||||
runTest(testData);
|
||||
EXPECT_EQ(testData.expectedError, "");
|
||||
}
|
||||
|
||||
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");
|
||||
StyleTestData testData;
|
||||
testData.type = MockFileSource::RequestFail;
|
||||
testData.style = "test/fixtures/resources/style.json";
|
||||
testData.resource = "source_raster.json";
|
||||
runTest(testData);
|
||||
EXPECT_EQ(testData.expectedError, "Failed to load [test/fixtures/resources/source_raster.json]: Failed by the test case");
|
||||
}
|
||||
|
||||
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");
|
||||
StyleTestData testData;
|
||||
testData.type = MockFileSource::RequestFail;
|
||||
testData.style = "test/fixtures/resources/style.json";
|
||||
testData.resource = "source_vector.json";
|
||||
runTest(testData);
|
||||
EXPECT_EQ(testData.expectedError, "Failed to load [test/fixtures/resources/source_vector.json]: Failed by the test case");
|
||||
}
|
||||
|
||||
TEST(ResourceLoading, SpriteJSONFail) {
|
||||
EXPECT_EQ(resourceErrorString(MockFileSource::RequestFail, "sprite.json"),
|
||||
"Failed to load [test/fixtures/resources/sprite.json]: Failed by the test case");
|
||||
StyleTestData testData;
|
||||
testData.type = MockFileSource::RequestFail;
|
||||
testData.style = "test/fixtures/resources/style.json";
|
||||
testData.resource = "sprite.json";
|
||||
runTest(testData);
|
||||
EXPECT_EQ(testData.expectedError, "Failed to load [test/fixtures/resources/sprite.json]: Failed by the test case");
|
||||
}
|
||||
|
||||
TEST(ResourceLoading, SpriteImageFail) {
|
||||
EXPECT_EQ(resourceErrorString(MockFileSource::RequestFail, "sprite.png"),
|
||||
"Failed to load [test/fixtures/resources/sprite.png]: Failed by the test case");
|
||||
StyleTestData testData;
|
||||
testData.type = MockFileSource::RequestFail;
|
||||
testData.style = "test/fixtures/resources/style.json";
|
||||
testData.resource = "sprite.png";
|
||||
runTest(testData);
|
||||
EXPECT_EQ(testData.expectedError, "Failed to load [test/fixtures/resources/sprite.png]: Failed by the test case");
|
||||
}
|
||||
|
||||
TEST(ResourceLoading, RasterTileFail) {
|
||||
EXPECT_EQ(resourceErrorString(MockFileSource::RequestFail, "raster.png"),
|
||||
"Failed to load [test/fixtures/resources/raster.png]: Failed by the test case");
|
||||
StyleTestData testData;
|
||||
testData.type = MockFileSource::RequestFail;
|
||||
testData.style = "test/fixtures/resources/style.json";
|
||||
testData.resource = "raster.png";
|
||||
runTest(testData);
|
||||
EXPECT_EQ(testData.expectedError, "Failed to load [test/fixtures/resources/raster.png]: Failed by the test case");
|
||||
}
|
||||
|
||||
TEST(ResourceLoading, VectorTileFail) {
|
||||
EXPECT_EQ(resourceErrorString(MockFileSource::RequestFail, "vector.pbf"),
|
||||
"Failed to load [test/fixtures/resources/vector.pbf]: Failed by the test case");
|
||||
StyleTestData testData;
|
||||
testData.type = MockFileSource::RequestFail;
|
||||
testData.style = "test/fixtures/resources/style.json";
|
||||
testData.resource = "vector.pbf";
|
||||
runTest(testData);
|
||||
EXPECT_EQ(testData.expectedError, "Failed to load [test/fixtures/resources/vector.pbf]: Failed by the test case");
|
||||
}
|
||||
|
||||
TEST(ResourceLoading, GlyphsFail) {
|
||||
EXPECT_EQ(resourceErrorString(MockFileSource::RequestFail, "glyphs.pbf"),
|
||||
"Failed to load [test/fixtures/resources/glyphs.pbf]: Failed by the test case");
|
||||
StyleTestData testData;
|
||||
testData.type = MockFileSource::RequestFail;
|
||||
testData.style = "test/fixtures/resources/style.json";
|
||||
testData.resource = "glyphs.pbf";
|
||||
runTest(testData);
|
||||
EXPECT_EQ(testData.expectedError, "Failed to load [test/fixtures/resources/glyphs.pbf]: Failed by the test case");
|
||||
}
|
||||
|
||||
TEST(ResourceLoading, RasterSourceCorrupt) {
|
||||
EXPECT_EQ(resourceErrorString(MockFileSource::RequestWithCorruptedData, "source_raster.json"),
|
||||
"Failed to parse [test/fixtures/resources/source_raster.json]: 0 - Invalid value.");
|
||||
StyleTestData testData;
|
||||
testData.type = MockFileSource::RequestWithCorruptedData;
|
||||
testData.style = "test/fixtures/resources/style.json";
|
||||
testData.resource = "source_raster.json";
|
||||
runTest(testData);
|
||||
EXPECT_EQ(testData.expectedError, "Failed to parse [test/fixtures/resources/source_raster.json]: 0 - Invalid value.");
|
||||
}
|
||||
|
||||
TEST(ResourceLoading, VectorSourceCorrupt) {
|
||||
EXPECT_EQ(resourceErrorString(MockFileSource::RequestWithCorruptedData, "source_vector.json"),
|
||||
"Failed to parse [test/fixtures/resources/source_vector.json]: 0 - Invalid value.");
|
||||
StyleTestData testData;
|
||||
testData.type = MockFileSource::RequestWithCorruptedData;
|
||||
testData.style = "test/fixtures/resources/style.json";
|
||||
testData.resource = "source_vector.json";
|
||||
runTest(testData);
|
||||
EXPECT_EQ(testData.expectedError, "Failed to parse [test/fixtures/resources/source_vector.json]: 0 - Invalid value.");
|
||||
}
|
||||
|
||||
TEST(ResourceLoading, SpriteJSONCorrupt) {
|
||||
EXPECT_EQ(resourceErrorString(MockFileSource::RequestWithCorruptedData, "sprite.json"),
|
||||
"Failed to parse JSON: Invalid value. at offset 0");
|
||||
StyleTestData testData;
|
||||
testData.type = MockFileSource::RequestWithCorruptedData;
|
||||
testData.style = "test/fixtures/resources/style.json";
|
||||
testData.resource = "sprite.json";
|
||||
runTest(testData);
|
||||
EXPECT_EQ(testData.expectedError, "Failed to parse JSON: Invalid value. at offset 0");
|
||||
}
|
||||
|
||||
TEST(ResourceLoading, SpriteImageCorrupt) {
|
||||
EXPECT_EQ(resourceErrorString(MockFileSource::RequestWithCorruptedData, "sprite.png"),
|
||||
"Could not parse sprite image");
|
||||
StyleTestData testData;
|
||||
testData.type = MockFileSource::RequestWithCorruptedData;
|
||||
testData.style = "test/fixtures/resources/style.json";
|
||||
testData.resource = "sprite.png";
|
||||
runTest(testData);
|
||||
EXPECT_EQ(testData.expectedError, "Could not parse sprite image");
|
||||
}
|
||||
|
||||
TEST(ResourceLoading, RasterTileCorrupt) {
|
||||
EXPECT_EQ(resourceErrorString(MockFileSource::RequestWithCorruptedData, "raster.png"),
|
||||
"Failed to parse [0/0/0]: error parsing raster image");
|
||||
StyleTestData testData;
|
||||
testData.type = MockFileSource::RequestWithCorruptedData;
|
||||
testData.style = "test/fixtures/resources/style.json";
|
||||
testData.resource = "raster.png";
|
||||
runTest(testData);
|
||||
EXPECT_EQ(testData.expectedError, "Failed to parse [0/0/0]: error parsing raster image");
|
||||
}
|
||||
|
||||
TEST(ResourceLoading, VectorTileCorrupt) {
|
||||
EXPECT_EQ(resourceErrorString(MockFileSource::RequestWithCorruptedData, "vector.pbf"),
|
||||
"Failed to parse [0/0/0]: pbf unknown field type exception");
|
||||
StyleTestData testData;
|
||||
testData.type = MockFileSource::RequestWithCorruptedData;
|
||||
testData.style = "test/fixtures/resources/style.json";
|
||||
testData.resource = "vector.pbf";
|
||||
runTest(testData);
|
||||
EXPECT_EQ(testData.expectedError, "Failed to parse [0/0/0]: 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");
|
||||
StyleTestData testData;
|
||||
testData.type = MockFileSource::RequestWithCorruptedData;
|
||||
testData.style = "test/fixtures/resources/style.json";
|
||||
testData.resource = "glyphs.pbf";
|
||||
runTest(testData);
|
||||
EXPECT_EQ(testData.expectedError, "Failed to parse [test/fixtures/resources/glyphs.pbf]: pbf unknown field type exception");
|
||||
}
|
||||
|
||||
TEST(ResourceLoading, UnusedSource) {
|
||||
StyleTestData testData;
|
||||
testData.type = MockFileSource::Success;
|
||||
testData.style = "test/fixtures/resources/style-unused-sources.json";
|
||||
testData.callback = [] (const Style& style) {
|
||||
Source *usedSource = style.getSource("usedsource");
|
||||
EXPECT_TRUE(usedSource);
|
||||
EXPECT_TRUE(usedSource->isLoaded());
|
||||
|
||||
Source *unusedSource = style.getSource("unusedsource");
|
||||
EXPECT_TRUE(unusedSource);
|
||||
EXPECT_FALSE(unusedSource->isLoaded());
|
||||
};
|
||||
runTest(testData);
|
||||
}
|
||||
|
||||
TEST(ResourceLoading, UnusedSourceActiveViaClassUpdate) {
|
||||
StyleTestData testData;
|
||||
testData.type = MockFileSource::Success;
|
||||
testData.style = "test/fixtures/resources/style-unused-sources.json";
|
||||
testData.styleClass = "visible";
|
||||
testData.callback = [] (const Style& style) {
|
||||
Source *unusedSource = style.getSource("unusedsource");
|
||||
EXPECT_TRUE(unusedSource);
|
||||
EXPECT_TRUE(unusedSource->isLoaded());
|
||||
};
|
||||
runTest(testData);
|
||||
}
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
#include "../fixtures/util.hpp"
|
||||
#include "../fixtures/mock_file_source.hpp"
|
||||
#include "../fixtures/mock_view.hpp"
|
||||
|
||||
#include <mbgl/style/style.hpp>
|
||||
#include <mbgl/map/view.hpp>
|
||||
#include <mbgl/storage/file_source.hpp>
|
||||
#include <mbgl/map/map_data.hpp>
|
||||
#include <mbgl/map/transform.hpp>
|
||||
#include <mbgl/util/exception.hpp>
|
||||
#include <mbgl/util/io.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/util/texture_pool.hpp>
|
||||
#include <mbgl/util/thread.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class MockStyleObserver: public Style::Observer {
|
||||
public:
|
||||
using MockStyleObserverCallback = std::function<void(std::exception_ptr, Style*)>;
|
||||
|
||||
MockStyleObserver(View& view_,
|
||||
FileSource& fileSource_,
|
||||
const MockStyleObserverCallback& callback_)
|
||||
: data(MapMode::Still, GLContextMode::Unique, view_.getPixelRatio()),
|
||||
style(std::make_unique<Style>(data)),
|
||||
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-unused-sources.json");
|
||||
style->setJSON(style_, "");
|
||||
style->setObserver(this);
|
||||
}
|
||||
|
||||
~MockStyleObserver() {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
style.reset();
|
||||
}
|
||||
|
||||
void update() {
|
||||
const auto now = Clock::now();
|
||||
|
||||
data.setAnimationTime(now);
|
||||
transform.updateTransitions(now);
|
||||
|
||||
style->cascade();
|
||||
style->recalculate(16);
|
||||
style->update(transform.getState(), texturePool);
|
||||
}
|
||||
|
||||
// Style::Observer implementation.
|
||||
void onTileDataChanged() override {
|
||||
update();
|
||||
|
||||
if (style->isLoaded()) {
|
||||
callback(nullptr, style.get());
|
||||
}
|
||||
}
|
||||
|
||||
void onResourceLoadingFailed(std::exception_ptr error) override {
|
||||
callback(error, style.get());
|
||||
}
|
||||
|
||||
void addClass(const std::string& class_) {
|
||||
data.addClass(class_);
|
||||
}
|
||||
|
||||
private:
|
||||
MapData data;
|
||||
std::unique_ptr<Style> style;
|
||||
Transform transform;
|
||||
TexturePool texturePool;
|
||||
|
||||
MockStyleObserverCallback callback;
|
||||
};
|
||||
|
||||
TEST(Style, UnusedSource) {
|
||||
util::RunLoop loop;
|
||||
|
||||
MockView view;
|
||||
MockFileSource fileSource(MockFileSource::Success, "");
|
||||
|
||||
auto callback = [&loop](std::exception_ptr error, Style* style) {
|
||||
EXPECT_TRUE(error == nullptr);
|
||||
loop.stop();
|
||||
|
||||
Source *usedSource = style->getSource("usedsource");
|
||||
EXPECT_TRUE(usedSource);
|
||||
EXPECT_TRUE(usedSource->isLoaded());
|
||||
|
||||
Source *unusedSource = style->getSource("unusedsource");
|
||||
EXPECT_TRUE(unusedSource);
|
||||
EXPECT_FALSE(unusedSource->isLoaded());
|
||||
};
|
||||
|
||||
std::unique_ptr<util::Thread<MockStyleObserver>> observer(
|
||||
std::make_unique<util::Thread<MockStyleObserver>>(
|
||||
util::ThreadContext{"Map", util::ThreadType::Map, util::ThreadPriority::Regular}, view, fileSource, callback));
|
||||
|
||||
loop.run();
|
||||
|
||||
// Needed because it will make the Map thread
|
||||
// join and cease logging after this point.
|
||||
observer->invoke(&MockStyleObserver::cleanup);
|
||||
observer.reset();
|
||||
}
|
||||
|
||||
TEST(Style, UnusedSourceActiveViaClassUpdate) {
|
||||
util::RunLoop loop;
|
||||
|
||||
MockView view;
|
||||
MockFileSource fileSource(MockFileSource::Success, "");
|
||||
|
||||
auto callback = [&loop](std::exception_ptr error, Style* style) {
|
||||
loop.stop();
|
||||
|
||||
EXPECT_TRUE(error == nullptr);
|
||||
|
||||
Source *unusedSource = style->getSource("unusedsource");
|
||||
EXPECT_TRUE(unusedSource);
|
||||
EXPECT_TRUE(unusedSource->isLoaded());
|
||||
};
|
||||
|
||||
std::unique_ptr<util::Thread<MockStyleObserver>> observer(
|
||||
std::make_unique<util::Thread<MockStyleObserver>>(
|
||||
util::ThreadContext{"Map", util::ThreadType::Map, util::ThreadPriority::Regular}, view, fileSource, callback));
|
||||
|
||||
observer->invoke(&MockStyleObserver::addClass, "visible");
|
||||
observer->invoke(&MockStyleObserver::update);
|
||||
|
||||
loop.run();
|
||||
|
||||
// Needed because it will make the Map thread
|
||||
// join and cease logging after this point.
|
||||
observer->invoke(&MockStyleObserver::cleanup);
|
||||
observer.reset();
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -90,7 +90,6 @@
|
||||
'style/pending_resources.cpp',
|
||||
'style/resource_loading.cpp',
|
||||
'style/style_layer.cpp',
|
||||
'style/unused_sources.cpp',
|
||||
|
||||
'sprite/sprite_atlas.cpp',
|
||||
'sprite/sprite_image.cpp',
|
||||
|
||||
Reference in New Issue
Block a user