[tests] Rewrite {Sprite,Glyph}Store tests in the style of ResourceLoading
This commit is contained in:
67
test/fixtures/stub_style_observer.hpp
vendored
Normal file
67
test/fixtures/stub_style_observer.hpp
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
#ifndef MBGL_TEST_STUB_STYLE_OBSERVER
|
||||
#define MBGL_TEST_STUB_STYLE_OBSERVER
|
||||
|
||||
#include <mbgl/style/style.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
/**
|
||||
* An implementation of Style::Observer that forwards all methods to dynamically-settable lambas.
|
||||
*/
|
||||
class StubStyleObserver : public Style::Observer {
|
||||
public:
|
||||
void onGlyphsLoaded(const std::string& fontStack, const GlyphRange& glyphRange) override {
|
||||
if (glyphsLoaded) glyphsLoaded(fontStack, glyphRange);
|
||||
}
|
||||
|
||||
void onGlyphsError(const std::string& fontStack, const GlyphRange& glyphRange, std::exception_ptr error) override {
|
||||
if (glyphsError) glyphsError(fontStack, glyphRange, error);
|
||||
}
|
||||
|
||||
void onSpriteLoaded() override {
|
||||
if (spriteLoaded) spriteLoaded();
|
||||
}
|
||||
|
||||
void onSpriteError(std::exception_ptr error) override {
|
||||
if (spriteError) spriteError(error);
|
||||
}
|
||||
|
||||
void onSourceLoaded(Source& source) override {
|
||||
if (sourceLoaded) sourceLoaded(source);
|
||||
}
|
||||
|
||||
void onSourceError(Source& source, std::exception_ptr error) override {
|
||||
if (sourceError) sourceError(source, error);
|
||||
}
|
||||
|
||||
void onTileLoaded(Source& source, const TileID& tileID, bool isNewTile) override {
|
||||
if (tileLoaded) tileLoaded(source, tileID, isNewTile);
|
||||
}
|
||||
|
||||
void onTileError(Source& source, const TileID& tileID, std::exception_ptr error) override {
|
||||
if (tileError) tileError(source, tileID, error);
|
||||
}
|
||||
|
||||
void onResourceLoaded() override {
|
||||
if (resourceLoaded) resourceLoaded();
|
||||
};
|
||||
|
||||
void onResourceError(std::exception_ptr error) override {
|
||||
if (resourceError) resourceError(error);
|
||||
};
|
||||
|
||||
std::function<void (const std::string& fontStack, const GlyphRange&)> glyphsLoaded;
|
||||
std::function<void (const std::string& fontStack, const GlyphRange&, std::exception_ptr)> glyphsError;
|
||||
std::function<void ()> spriteLoaded;
|
||||
std::function<void (std::exception_ptr)> spriteError;
|
||||
std::function<void (Source&)> sourceLoaded;
|
||||
std::function<void (Source&, std::exception_ptr)> sourceError;
|
||||
std::function<void (Source&, const TileID&, bool isNewTile)> tileLoaded;
|
||||
std::function<void (Source&, const TileID&, std::exception_ptr)> tileError;
|
||||
std::function<void ()> resourceLoaded;
|
||||
std::function<void (std::exception_ptr)> resourceError;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
#endif
|
||||
@@ -1,17 +1,16 @@
|
||||
#include "../fixtures/util.hpp"
|
||||
#include "../fixtures/fixture_log_observer.hpp"
|
||||
#include "../fixtures/mock_file_source.hpp"
|
||||
#include "../fixtures/stub_style_observer.hpp"
|
||||
|
||||
#include <mbgl/sprite/sprite_store.hpp>
|
||||
|
||||
#include <mbgl/util/async_task.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/util/thread.hpp>
|
||||
|
||||
#include <utility>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
TEST(Sprite, SpriteStore) {
|
||||
TEST(SpriteStore, SpriteStore) {
|
||||
FixtureLog log;
|
||||
|
||||
const auto sprite1 = std::make_shared<SpriteImage>(8, 8, 2, std::string(16 * 16 * 4, '\0'));
|
||||
@@ -77,7 +76,7 @@ TEST(Sprite, SpriteStore) {
|
||||
EXPECT_EQ(Sprites(), store.getDirty());
|
||||
}
|
||||
|
||||
TEST(Sprite, SpriteStoreOtherPixelRatio) {
|
||||
TEST(SpriteStore, OtherPixelRatio) {
|
||||
FixtureLog log;
|
||||
|
||||
const auto sprite1 = std::make_shared<SpriteImage>(8, 8, 1, std::string(8 * 8 * 4, '\0'));
|
||||
@@ -90,7 +89,7 @@ TEST(Sprite, SpriteStoreOtherPixelRatio) {
|
||||
EXPECT_EQ(Sprites({ { "one", sprite1 } }), store.getDirty());
|
||||
}
|
||||
|
||||
TEST(Sprite, SpriteStoreMultiple) {
|
||||
TEST(SpriteStore, Multiple) {
|
||||
const auto sprite1 = std::make_shared<SpriteImage>(8, 8, 2, std::string(16 * 16 * 4, '\0'));
|
||||
const auto sprite2 = std::make_shared<SpriteImage>(8, 8, 2, std::string(16 * 16 * 4, '\0'));
|
||||
|
||||
@@ -107,7 +106,7 @@ TEST(Sprite, SpriteStoreMultiple) {
|
||||
EXPECT_EQ(Sprites(), store.getDirty());
|
||||
}
|
||||
|
||||
TEST(Sprite, SpriteStoreReplace) {
|
||||
TEST(SpriteStore, Replace) {
|
||||
FixtureLog log;
|
||||
|
||||
const auto sprite1 = std::make_shared<SpriteImage>(8, 8, 2, std::string(16 * 16 * 4, '\0'));
|
||||
@@ -124,7 +123,7 @@ TEST(Sprite, SpriteStoreReplace) {
|
||||
EXPECT_EQ(Sprites({ { "sprite", sprite2 } }), store.getDirty());
|
||||
}
|
||||
|
||||
TEST(Sprite, SpriteStoreReplaceWithDifferentDimensions) {
|
||||
TEST(SpriteStore, ReplaceWithDifferentDimensions) {
|
||||
FixtureLog log;
|
||||
|
||||
const auto sprite1 = std::make_shared<SpriteImage>(8, 8, 2, std::string(16 * 16 * 4, '\0'));
|
||||
@@ -148,167 +147,100 @@ TEST(Sprite, SpriteStoreReplaceWithDifferentDimensions) {
|
||||
EXPECT_EQ(Sprites({ { "sprite", sprite1 } }), store.getDirty());
|
||||
}
|
||||
|
||||
using SpriteTestCallback = std::function<void(SpriteStore*, std::exception_ptr)>;
|
||||
|
||||
struct SpriteParams {
|
||||
const std::string baseUrl;
|
||||
const float pixelRatio;
|
||||
};
|
||||
|
||||
class SpriteThread : public SpriteStore::Observer {
|
||||
class SpriteStoreTest {
|
||||
public:
|
||||
SpriteThread(FileSource* fileSource, SpriteTestCallback callback) : callback_(std::move(callback)) {
|
||||
util::ThreadContext::setFileSource(fileSource);
|
||||
}
|
||||
SpriteStoreTest(MockFileSource::Type type, const std::string& resource)
|
||||
: fileSource(type, resource),
|
||||
spriteStore(1.0) {}
|
||||
|
||||
void loadSprite(const SpriteParams& params) {
|
||||
spriteStore_.reset(new SpriteStore(params.pixelRatio));
|
||||
spriteStore_->setObserver(this);
|
||||
spriteStore_->setURL(params.baseUrl);
|
||||
}
|
||||
util::ThreadContext context { "Map", util::ThreadType::Map, util::ThreadPriority::Regular };
|
||||
util::RunLoop loop;
|
||||
MockFileSource fileSource;
|
||||
StubStyleObserver observer;
|
||||
SpriteStore spriteStore;
|
||||
|
||||
void unloadSprite() {
|
||||
spriteStore_->setObserver(nullptr);
|
||||
spriteStore_.reset();
|
||||
}
|
||||
void run(const std::string& url) {
|
||||
// Squelch logging.
|
||||
Log::setObserver(std::make_unique<Log::NullObserver>());
|
||||
|
||||
void onSpriteLoaded() override {
|
||||
callback_(spriteStore_.get(), nullptr);
|
||||
}
|
||||
util::ThreadContext::Set(&context);
|
||||
util::ThreadContext::setFileSource(&fileSource);
|
||||
|
||||
void onSpriteError(std::exception_ptr error) override {
|
||||
callback_(spriteStore_.get(), error);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<SpriteStore> spriteStore_;
|
||||
SpriteTestCallback callback_;
|
||||
};
|
||||
|
||||
class SpriteTest : public testing::Test {
|
||||
protected:
|
||||
void runTest(const SpriteParams& params, FileSource* fileSource, SpriteTestCallback callback) {
|
||||
util::RunLoop loop;
|
||||
|
||||
async_ = std::make_unique<util::AsyncTask>([&] { loop.stop(); });
|
||||
async_->unref();
|
||||
|
||||
const util::ThreadContext context = {"Map", util::ThreadType::Map, util::ThreadPriority::Regular};
|
||||
|
||||
util::Thread<SpriteThread> tester(context, fileSource, callback);
|
||||
tester.invoke(&SpriteThread::loadSprite, params);
|
||||
spriteStore.setObserver(&observer);
|
||||
spriteStore.setURL(url);
|
||||
|
||||
loop.run();
|
||||
|
||||
tester.invoke(&SpriteThread::unloadSprite);
|
||||
}
|
||||
|
||||
void stopTest() {
|
||||
async_->send();
|
||||
void end() {
|
||||
loop.stop();
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<util::AsyncTask> async_;
|
||||
};
|
||||
|
||||
TEST_F(SpriteTest, LoadingSuccess) {
|
||||
SpriteParams params = {
|
||||
"test/fixtures/resources/sprite",
|
||||
1.0,
|
||||
TEST(SpriteStore, LoadingSuccess) {
|
||||
SpriteStoreTest test(MockFileSource::Success, "");
|
||||
|
||||
test.observer.spriteError = [&] (std::exception_ptr) {
|
||||
FAIL();
|
||||
test.end();
|
||||
};
|
||||
|
||||
auto callback = [this, ¶ms](SpriteStore* spriteStore, std::exception_ptr error) {
|
||||
ASSERT_TRUE(util::ThreadContext::currentlyOn(util::ThreadType::Map));
|
||||
|
||||
ASSERT_TRUE(error == nullptr);
|
||||
|
||||
ASSERT_TRUE(!spriteStore->getDirty().empty());
|
||||
|
||||
ASSERT_EQ(spriteStore->pixelRatio, params.pixelRatio);
|
||||
ASSERT_NE(spriteStore->pixelRatio, 1.5);
|
||||
ASSERT_NE(spriteStore->pixelRatio, 2.0);
|
||||
|
||||
ASSERT_TRUE(spriteStore->isLoaded());
|
||||
|
||||
stopTest();
|
||||
test.observer.spriteLoaded = [&] () {
|
||||
ASSERT_TRUE(!test.spriteStore.getDirty().empty());
|
||||
ASSERT_EQ(test.spriteStore.pixelRatio, 1.0);
|
||||
ASSERT_TRUE(test.spriteStore.isLoaded());
|
||||
test.end();
|
||||
};
|
||||
|
||||
MockFileSource fileSource(MockFileSource::Success, "");
|
||||
runTest(params, &fileSource, callback);
|
||||
test.run("test/fixtures/resources/sprite");
|
||||
}
|
||||
|
||||
TEST_F(SpriteTest, LoadingFail) {
|
||||
SpriteParams params = {
|
||||
"test/fixtures/resources/sprite",
|
||||
1.0,
|
||||
};
|
||||
|
||||
auto callback = [this, ¶ms](SpriteStore* spriteStore, std::exception_ptr error) {
|
||||
ASSERT_TRUE(util::ThreadContext::currentlyOn(util::ThreadType::Map));
|
||||
TEST(SpriteStore, LoadingFail) {
|
||||
SpriteStoreTest test(MockFileSource::RequestFail, "sprite.json");
|
||||
|
||||
test.observer.spriteError = [&] (std::exception_ptr error) {
|
||||
ASSERT_TRUE(error != nullptr);
|
||||
|
||||
ASSERT_EQ(spriteStore->pixelRatio, params.pixelRatio);
|
||||
ASSERT_NE(spriteStore->pixelRatio, 1.5);
|
||||
ASSERT_NE(spriteStore->pixelRatio, 2.0);
|
||||
|
||||
ASSERT_FALSE(spriteStore->isLoaded());
|
||||
|
||||
stopTest();
|
||||
ASSERT_FALSE(test.spriteStore.isLoaded());
|
||||
test.end();
|
||||
};
|
||||
|
||||
MockFileSource fileSourceFailSpriteJSON(MockFileSource::RequestFail, "sprite.json");
|
||||
runTest(params, &fileSourceFailSpriteJSON, callback);
|
||||
|
||||
MockFileSource fileSourceFailSpriteImage(MockFileSource::RequestFail, "sprite.png");
|
||||
runTest(params, &fileSourceFailSpriteImage, callback);
|
||||
|
||||
MockFileSource fileSourceCorruptedSpriteJSON(MockFileSource::RequestWithCorruptedData, "sprite.json");
|
||||
runTest(params, &fileSourceCorruptedSpriteJSON, callback);
|
||||
|
||||
MockFileSource fileSourceCorruptedSpriteImage(MockFileSource::RequestWithCorruptedData, "sprite.png");
|
||||
runTest(params, &fileSourceCorruptedSpriteImage, callback);
|
||||
test.run("test/fixtures/resources/sprite");
|
||||
}
|
||||
|
||||
TEST_F(SpriteTest, LoadingCancel) {
|
||||
SpriteParams params = {
|
||||
"test/fixtures/resources/sprite",
|
||||
1.0,
|
||||
TEST(SpriteStore, LoadingCorrupted) {
|
||||
SpriteStoreTest test(MockFileSource::RequestWithCorruptedData, "sprite.json");
|
||||
|
||||
test.observer.spriteError = [&] (std::exception_ptr error) {
|
||||
ASSERT_TRUE(error != nullptr);
|
||||
ASSERT_FALSE(test.spriteStore.isLoaded());
|
||||
test.end();
|
||||
};
|
||||
|
||||
auto callback = [this](SpriteStore*, std::exception_ptr) {
|
||||
test.run("test/fixtures/resources/sprite");
|
||||
}
|
||||
|
||||
TEST(SpriteStore, LoadingCancel) {
|
||||
SpriteStoreTest test(MockFileSource::SuccessWithDelay, "sprite.json");
|
||||
|
||||
test.observer.spriteLoaded = [&] () {
|
||||
FAIL() << "Should never be called";
|
||||
};
|
||||
|
||||
MockFileSource fileSourceDelaySpriteJSON(MockFileSource::SuccessWithDelay, "sprite.json");
|
||||
fileSourceDelaySpriteJSON.setOnRequestDelayedCallback([this]{
|
||||
stopTest();
|
||||
test.fileSource.setOnRequestDelayedCallback([&]{
|
||||
test.end();
|
||||
});
|
||||
runTest(params, &fileSourceDelaySpriteJSON, callback);
|
||||
|
||||
MockFileSource fileSourceDelaySpriteImage(MockFileSource::SuccessWithDelay, "sprite.png");
|
||||
fileSourceDelaySpriteImage.setOnRequestDelayedCallback([this]{
|
||||
stopTest();
|
||||
});
|
||||
runTest(params, &fileSourceDelaySpriteImage, callback);
|
||||
test.run("test/fixtures/resources/sprite");
|
||||
}
|
||||
|
||||
TEST_F(SpriteTest, InvalidURL) {
|
||||
SpriteParams params = {
|
||||
"foo bar",
|
||||
1.0,
|
||||
};
|
||||
|
||||
auto callback = [this](SpriteStore* spriteStore, std::exception_ptr error) {
|
||||
ASSERT_TRUE(util::ThreadContext::currentlyOn(util::ThreadType::Map));
|
||||
TEST(SpriteStore, InvalidURL) {
|
||||
SpriteStoreTest test(MockFileSource::Success, "");
|
||||
|
||||
test.observer.spriteError = [&] (std::exception_ptr error) {
|
||||
ASSERT_TRUE(error != nullptr);
|
||||
|
||||
ASSERT_EQ(spriteStore->isLoaded(), false);
|
||||
|
||||
stopTest();
|
||||
ASSERT_EQ(test.spriteStore.isLoaded(), false);
|
||||
test.end();
|
||||
};
|
||||
|
||||
MockFileSource fileSource(MockFileSource::Success, "");
|
||||
runTest(params, &fileSource, callback);
|
||||
test.run("foo bar");
|
||||
}
|
||||
|
||||
@@ -1,233 +1,145 @@
|
||||
#include "../fixtures/fixture_log_observer.hpp"
|
||||
#include "../fixtures/mock_file_source.hpp"
|
||||
#include "../fixtures/util.hpp"
|
||||
#include "../fixtures/mock_file_source.hpp"
|
||||
#include "../fixtures/stub_style_observer.hpp"
|
||||
|
||||
#include <mbgl/text/font_stack.hpp>
|
||||
#include <mbgl/text/glyph_store.hpp>
|
||||
#include <mbgl/util/async_task.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/util/thread.hpp>
|
||||
#include <utility>
|
||||
#include <mbgl/platform/log.hpp>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
using GlyphStoreTestCallback = std::function<void(GlyphStore*, std::exception_ptr)>;
|
||||
|
||||
struct GlyphStoreParams {
|
||||
const std::string url;
|
||||
const std::string stack;
|
||||
const std::set<GlyphRange> ranges;
|
||||
};
|
||||
|
||||
class GlyphStoreThread : public GlyphStore::Observer {
|
||||
class GlyphStoreTest {
|
||||
public:
|
||||
GlyphStoreThread(FileSource* fileSource, GlyphStoreTestCallback callback) : callback_(std::move(callback)) {
|
||||
util::ThreadContext::setFileSource(fileSource);
|
||||
}
|
||||
GlyphStoreTest(MockFileSource::Type type, const std::string& resource)
|
||||
: fileSource(type, resource) {}
|
||||
|
||||
void loadGlyphStore(const GlyphStoreParams& params) {
|
||||
glyphStore_.reset(new GlyphStore());
|
||||
util::ThreadContext context { "Map", util::ThreadType::Map, util::ThreadPriority::Regular };
|
||||
util::RunLoop loop;
|
||||
MockFileSource fileSource;
|
||||
StubStyleObserver observer;
|
||||
GlyphStore glyphStore;
|
||||
|
||||
glyphStore_->setObserver(this);
|
||||
glyphStore_->setURL(params.url);
|
||||
void run(const std::string& url, const std::string& fontStack, const std::set<GlyphRange>& glyphRanges) {
|
||||
// Squelch logging.
|
||||
Log::setObserver(std::make_unique<Log::NullObserver>());
|
||||
|
||||
ASSERT_FALSE(glyphStore_->hasGlyphRanges(params.stack, params.ranges));
|
||||
}
|
||||
util::ThreadContext::Set(&context);
|
||||
util::ThreadContext::setFileSource(&fileSource);
|
||||
|
||||
void unloadGlyphStore() {
|
||||
glyphStore_->setObserver(nullptr);
|
||||
glyphStore_.reset();
|
||||
}
|
||||
|
||||
void onGlyphsLoaded(const std::string&, const GlyphRange&) override {
|
||||
callback_(glyphStore_.get(), nullptr);
|
||||
}
|
||||
|
||||
void onGlyphsError(const std::string&, const GlyphRange&, std::exception_ptr error) override {
|
||||
callback_(glyphStore_.get(), error);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<GlyphStore> glyphStore_;
|
||||
GlyphStoreTestCallback callback_;
|
||||
};
|
||||
|
||||
class GlyphStoreTest : public testing::Test {
|
||||
protected:
|
||||
void runTest(const GlyphStoreParams& params, FileSource* fileSource, GlyphStoreTestCallback callback) {
|
||||
util::RunLoop loop;
|
||||
|
||||
async_ = std::make_unique<util::AsyncTask>([&]{ loop.stop(); });
|
||||
async_->unref();
|
||||
|
||||
const util::ThreadContext context = {"Map", util::ThreadType::Map, util::ThreadPriority::Regular};
|
||||
|
||||
util::Thread<GlyphStoreThread> tester(context, fileSource, callback);
|
||||
tester.invoke(&GlyphStoreThread::loadGlyphStore, params);
|
||||
glyphStore.setObserver(&observer);
|
||||
glyphStore.setURL(url);
|
||||
glyphStore.hasGlyphRanges(fontStack, glyphRanges);
|
||||
|
||||
loop.run();
|
||||
|
||||
tester.invoke(&GlyphStoreThread::unloadGlyphStore);
|
||||
}
|
||||
|
||||
void stopTest() {
|
||||
testDone = true;
|
||||
async_->send();
|
||||
void end() {
|
||||
loop.stop();
|
||||
}
|
||||
|
||||
bool isDone() const {
|
||||
return testDone;
|
||||
}
|
||||
|
||||
private:
|
||||
bool testDone = false;
|
||||
|
||||
std::unique_ptr<util::AsyncTask> async_;
|
||||
};
|
||||
|
||||
TEST_F(GlyphStoreTest, LoadingSuccess) {
|
||||
GlyphStoreParams params = {
|
||||
"test/fixtures/resources/glyphs.pbf",
|
||||
"Test Stack",
|
||||
{{0, 255}, {256, 511}}
|
||||
TEST(GlyphStore, LoadingSuccess) {
|
||||
GlyphStoreTest test(MockFileSource::Success, "");
|
||||
|
||||
test.observer.glyphsError = [&] (const std::string&, const GlyphRange&, std::exception_ptr) {
|
||||
FAIL();
|
||||
test.end();
|
||||
};
|
||||
|
||||
auto callback = [this, ¶ms](GlyphStore* store, std::exception_ptr error) {
|
||||
ASSERT_TRUE(util::ThreadContext::currentlyOn(util::ThreadType::Map));
|
||||
|
||||
// We need to check if the test is over because checking
|
||||
// if the GlyphStore has glyphs below will cause more requests
|
||||
// to happen and we don't want this endless loop.
|
||||
if (isDone()) {
|
||||
test.observer.glyphsLoaded = [&] (const std::string&, const GlyphRange&) {
|
||||
if (!test.glyphStore.hasGlyphRanges("Test Stack", {{0, 255}, {256, 511}}))
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT_EQ(error, nullptr);
|
||||
|
||||
if (!store->hasGlyphRanges(params.stack, params.ranges)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT_FALSE(store->hasGlyphRanges("Foobar", params.ranges));
|
||||
ASSERT_FALSE(store->hasGlyphRanges("Foobar", {{512, 767}}));
|
||||
ASSERT_FALSE(store->hasGlyphRanges("Test Stack", {{512, 767}}));
|
||||
|
||||
auto fontStack = store->getFontStack(params.stack);
|
||||
auto fontStack = test.glyphStore.getFontStack("Test Stack");
|
||||
ASSERT_FALSE(fontStack->getMetrics().empty());
|
||||
ASSERT_FALSE(fontStack->getSDFs().empty());
|
||||
|
||||
stopTest();
|
||||
test.end();
|
||||
};
|
||||
|
||||
MockFileSource fileSource(MockFileSource::Success, "");
|
||||
runTest(params, &fileSource, callback);
|
||||
}
|
||||
|
||||
TEST_F(GlyphStoreTest, LoadingFail) {
|
||||
GlyphStoreParams params = {
|
||||
test.run(
|
||||
"test/fixtures/resources/glyphs.pbf",
|
||||
"Test Stack",
|
||||
{{0, 255}, {256, 511}}
|
||||
};
|
||||
{{0, 255}, {256, 511}});
|
||||
}
|
||||
|
||||
auto callback = [this, ¶ms](GlyphStore* store, std::exception_ptr error) {
|
||||
ASSERT_TRUE(util::ThreadContext::currentlyOn(util::ThreadType::Map));
|
||||
|
||||
if (isDone()) {
|
||||
return;
|
||||
}
|
||||
TEST(GlyphStore, LoadingFail) {
|
||||
GlyphStoreTest test(MockFileSource::RequestFail, "glyphs.pbf");
|
||||
|
||||
test.observer.glyphsError = [&] (const std::string& fontStack, const GlyphRange& glyphRange, std::exception_ptr error) {
|
||||
ASSERT_TRUE(error != nullptr);
|
||||
ASSERT_EQ(fontStack, "Test Stack");
|
||||
ASSERT_EQ(glyphRange, GlyphRange(0, 255));
|
||||
|
||||
auto fontStack = store->getFontStack(params.stack);
|
||||
ASSERT_TRUE(fontStack->getMetrics().empty());
|
||||
ASSERT_TRUE(fontStack->getSDFs().empty());
|
||||
auto stack = test.glyphStore.getFontStack("Test Stack");
|
||||
ASSERT_TRUE(stack->getMetrics().empty());
|
||||
ASSERT_TRUE(stack->getSDFs().empty());
|
||||
ASSERT_FALSE(test.glyphStore.hasGlyphRanges("Test Stack", {{0, 255}}));
|
||||
|
||||
for (const auto& range : params.ranges) {
|
||||
ASSERT_FALSE(store->hasGlyphRanges(params.stack, {range}));
|
||||
}
|
||||
|
||||
ASSERT_FALSE(store->hasGlyphRanges(params.stack, params.ranges));
|
||||
ASSERT_FALSE(store->hasGlyphRanges("Foobar", params.ranges));
|
||||
ASSERT_FALSE(store->hasGlyphRanges("Foobar", {{512, 767}}));
|
||||
|
||||
stopTest();
|
||||
test.end();
|
||||
};
|
||||
|
||||
MockFileSource fileSource(MockFileSource::RequestFail, "glyphs.pbf");
|
||||
runTest(params, &fileSource, callback);
|
||||
}
|
||||
|
||||
TEST_F(GlyphStoreTest, LoadingCorrupted) {
|
||||
GlyphStoreParams params = {
|
||||
test.run(
|
||||
"test/fixtures/resources/glyphs.pbf",
|
||||
"Test Stack",
|
||||
{{0, 255}, {256, 511}}
|
||||
};
|
||||
{{0, 255}});
|
||||
}
|
||||
|
||||
auto callback = [this, ¶ms](GlyphStore* store, std::exception_ptr error) {
|
||||
ASSERT_TRUE(util::ThreadContext::currentlyOn(util::ThreadType::Map));
|
||||
|
||||
if (isDone()) {
|
||||
return;
|
||||
}
|
||||
TEST(GlyphStore, LoadingCorrupted) {
|
||||
GlyphStoreTest test(MockFileSource::RequestWithCorruptedData, "glyphs.pbf");
|
||||
|
||||
test.observer.glyphsError = [&] (const std::string& fontStack, const GlyphRange& glyphRange, std::exception_ptr error) {
|
||||
ASSERT_TRUE(error != nullptr);
|
||||
ASSERT_EQ(fontStack, "Test Stack");
|
||||
ASSERT_EQ(glyphRange, GlyphRange(0, 255));
|
||||
|
||||
auto fontStack = store->getFontStack(params.stack);
|
||||
ASSERT_TRUE(fontStack->getMetrics().empty());
|
||||
ASSERT_TRUE(fontStack->getSDFs().empty());
|
||||
auto stack = test.glyphStore.getFontStack("Test Stack");
|
||||
ASSERT_TRUE(stack->getMetrics().empty());
|
||||
ASSERT_TRUE(stack->getSDFs().empty());
|
||||
ASSERT_FALSE(test.glyphStore.hasGlyphRanges("Test Stack", {{0, 255}}));
|
||||
|
||||
for (const auto& range : params.ranges) {
|
||||
ASSERT_FALSE(store->hasGlyphRanges(params.stack, {range}));
|
||||
}
|
||||
|
||||
ASSERT_FALSE(store->hasGlyphRanges(params.stack, params.ranges));
|
||||
ASSERT_FALSE(store->hasGlyphRanges("Foobar", params.ranges));
|
||||
ASSERT_FALSE(store->hasGlyphRanges("Foobar", {{512, 767}}));
|
||||
|
||||
stopTest();
|
||||
test.end();
|
||||
};
|
||||
|
||||
MockFileSource fileSource(MockFileSource::RequestWithCorruptedData, "glyphs.pbf");
|
||||
runTest(params, &fileSource, callback);
|
||||
}
|
||||
|
||||
TEST_F(GlyphStoreTest, LoadingCancel) {
|
||||
GlyphStoreParams params = {
|
||||
test.run(
|
||||
"test/fixtures/resources/glyphs.pbf",
|
||||
"Test Stack",
|
||||
{{0, 255}, {256, 511}}
|
||||
};
|
||||
{{0, 255}});
|
||||
}
|
||||
|
||||
auto callback = [this](GlyphStore*, std::exception_ptr) {
|
||||
TEST(GlyphStore, LoadingCancel) {
|
||||
GlyphStoreTest test(MockFileSource::SuccessWithDelay, "glyphs.pbf");
|
||||
|
||||
test.observer.glyphsLoaded = [&] (const std::string&, const GlyphRange&) {
|
||||
FAIL() << "Should never be called";
|
||||
};
|
||||
|
||||
MockFileSource fileSource(MockFileSource::SuccessWithDelay, "glyphs.pbf");
|
||||
fileSource.setOnRequestDelayedCallback([this]{
|
||||
stopTest();
|
||||
test.fileSource.setOnRequestDelayedCallback([&]{
|
||||
test.end();
|
||||
});
|
||||
runTest(params, &fileSource, callback);
|
||||
|
||||
test.run(
|
||||
"test/fixtures/resources/glyphs.pbf",
|
||||
"Test Stack",
|
||||
{{0, 255}});
|
||||
}
|
||||
|
||||
TEST_F(GlyphStoreTest, InvalidURL) {
|
||||
GlyphStoreParams params = {
|
||||
"foo bar",
|
||||
"Test Stack",
|
||||
{{0, 255}, {256, 511}}
|
||||
};
|
||||
TEST(GlyphStore, InvalidURL) {
|
||||
GlyphStoreTest test(MockFileSource::Success, "");
|
||||
|
||||
auto callback = [this, ¶ms](GlyphStore* store, std::exception_ptr error) {
|
||||
test.observer.glyphsError = [&] (const std::string&, const GlyphRange&, std::exception_ptr error) {
|
||||
ASSERT_TRUE(error != nullptr);
|
||||
|
||||
auto fontStack = store->getFontStack(params.stack);
|
||||
ASSERT_TRUE(fontStack->getMetrics().empty());
|
||||
ASSERT_TRUE(fontStack->getSDFs().empty());
|
||||
auto stack = test.glyphStore.getFontStack("Test Stack");
|
||||
ASSERT_TRUE(stack->getMetrics().empty());
|
||||
ASSERT_TRUE(stack->getSDFs().empty());
|
||||
|
||||
stopTest();
|
||||
test.end();
|
||||
};
|
||||
|
||||
MockFileSource fileSource(MockFileSource::Success, "");
|
||||
runTest(params, &fileSource, callback);
|
||||
test.run(
|
||||
"foo bar",
|
||||
"Test Stack",
|
||||
{{0, 255}});
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "../fixtures/util.hpp"
|
||||
#include "../fixtures/mock_file_source.hpp"
|
||||
#include "../fixtures/mock_view.hpp"
|
||||
#include "../fixtures/stub_style_observer.hpp"
|
||||
|
||||
#include <mbgl/map/map_data.hpp>
|
||||
#include <mbgl/map/transform.hpp>
|
||||
@@ -15,72 +16,16 @@
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
class StyleObserver : public Style::Observer {
|
||||
public:
|
||||
void onGlyphsLoaded(const std::string& fontStack, const GlyphRange& glyphRange) override {
|
||||
if (glyphsLoaded) glyphsLoaded(fontStack, glyphRange);
|
||||
}
|
||||
|
||||
void onGlyphsError(const std::string& fontStack, const GlyphRange& glyphRange, std::exception_ptr error) override {
|
||||
if (glyphsError) glyphsError(fontStack, glyphRange, error);
|
||||
}
|
||||
|
||||
void onSpriteLoaded() override {
|
||||
if (spriteLoaded) spriteLoaded();
|
||||
}
|
||||
|
||||
void onSpriteError(std::exception_ptr error) override {
|
||||
if (spriteError) spriteError(error);
|
||||
}
|
||||
|
||||
void onSourceLoaded(Source& source) override {
|
||||
if (sourceLoaded) sourceLoaded(source);
|
||||
}
|
||||
|
||||
void onSourceError(Source& source, std::exception_ptr error) override {
|
||||
if (sourceError) sourceError(source, error);
|
||||
}
|
||||
|
||||
void onTileLoaded(Source& source, const TileID& tileID, bool isNewTile) override {
|
||||
if (tileLoaded) tileLoaded(source, tileID, isNewTile);
|
||||
}
|
||||
|
||||
void onTileError(Source& source, const TileID& tileID, std::exception_ptr error) override {
|
||||
if (tileError) tileError(source, tileID, error);
|
||||
}
|
||||
|
||||
void onResourceLoaded() override {
|
||||
if (resourceLoaded) resourceLoaded();
|
||||
};
|
||||
|
||||
void onResourceError(std::exception_ptr error) override {
|
||||
if (resourceError) resourceError(error);
|
||||
};
|
||||
|
||||
std::function<void (const std::string& fontStack, const GlyphRange&)> glyphsLoaded;
|
||||
std::function<void (const std::string& fontStack, const GlyphRange&, std::exception_ptr)> glyphsError;
|
||||
std::function<void ()> spriteLoaded;
|
||||
std::function<void (std::exception_ptr)> spriteError;
|
||||
std::function<void (Source&)> sourceLoaded;
|
||||
std::function<void (Source&, std::exception_ptr)> sourceError;
|
||||
std::function<void (Source&, const TileID&, bool isNewTile)> tileLoaded;
|
||||
std::function<void (Source&, const TileID&, std::exception_ptr)> tileError;
|
||||
std::function<void ()> resourceLoaded;
|
||||
std::function<void (std::exception_ptr)> resourceError;
|
||||
|
||||
std::function<void ()> fullyLoaded;
|
||||
};
|
||||
|
||||
class ResourceLoadingTest {
|
||||
public:
|
||||
ResourceLoadingTest(MockFileSource::Type type, const std::string& resource)
|
||||
: fileSource(type, resource) {}
|
||||
|
||||
util::ThreadContext context { "Map", util::ThreadType::Map, util::ThreadPriority::Regular };
|
||||
|
||||
MockFileSource fileSource;
|
||||
StyleObserver observer;
|
||||
util::RunLoop loop;
|
||||
MockFileSource fileSource;
|
||||
StubStyleObserver observer;
|
||||
std::function<void ()> onFullyLoaded;
|
||||
|
||||
MapData data { MapMode::Still, GLContextMode::Unique, 1.0 };
|
||||
MockView view;
|
||||
@@ -97,8 +42,8 @@ public:
|
||||
|
||||
observer.resourceLoaded = [&] () {
|
||||
style.update(transform.getState(), texturePool);
|
||||
if (style.isLoaded() && observer.fullyLoaded) {
|
||||
observer.fullyLoaded();
|
||||
if (style.isLoaded() && onFullyLoaded) {
|
||||
onFullyLoaded();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -125,7 +70,7 @@ TEST(ResourceLoading, Success) {
|
||||
FAIL() << util::toString(error);
|
||||
};
|
||||
|
||||
test.observer.fullyLoaded = [&] () {
|
||||
test.onFullyLoaded = [&] () {
|
||||
SUCCEED();
|
||||
test.end();
|
||||
};
|
||||
@@ -306,7 +251,7 @@ TEST(ResourceLoading, GlyphsCorrupt) {
|
||||
TEST(ResourceLoading, UnusedSource) {
|
||||
ResourceLoadingTest test(MockFileSource::Success, "");
|
||||
|
||||
test.observer.fullyLoaded = [&] () {
|
||||
test.onFullyLoaded = [&] () {
|
||||
Source *usedSource = test.style.getSource("usedsource");
|
||||
EXPECT_TRUE(usedSource);
|
||||
EXPECT_TRUE(usedSource->isLoaded());
|
||||
@@ -326,7 +271,7 @@ TEST(ResourceLoading, UnusedSourceActiveViaClassUpdate) {
|
||||
|
||||
test.data.addClass("visible");
|
||||
|
||||
test.observer.fullyLoaded = [&] () {
|
||||
test.onFullyLoaded = [&] () {
|
||||
Source *unusedSource = test.style.getSource("unusedsource");
|
||||
EXPECT_TRUE(unusedSource);
|
||||
EXPECT_TRUE(unusedSource->isLoaded());
|
||||
|
||||
Reference in New Issue
Block a user