diff options
Diffstat (limited to 'test/sprite/sprite_atlas.cpp')
-rw-r--r-- | test/sprite/sprite_atlas.cpp | 292 |
1 files changed, 274 insertions, 18 deletions
diff --git a/test/sprite/sprite_atlas.cpp b/test/sprite/sprite_atlas.cpp index 10bfbfa67f..f84e17cbcf 100644 --- a/test/sprite/sprite_atlas.cpp +++ b/test/sprite/sprite_atlas.cpp @@ -1,11 +1,17 @@ #include <mbgl/test/util.hpp> #include <mbgl/test/fixture_log_observer.hpp> +#include <mbgl/test/stub_file_source.hpp> +#include <mbgl/test/stub_style_observer.hpp> #include <mbgl/sprite/sprite_atlas.hpp> -#include <mbgl/sprite/sprite_store.hpp> +#include <mbgl/sprite/sprite_atlas.hpp> #include <mbgl/sprite/sprite_parser.hpp> #include <mbgl/util/io.hpp> #include <mbgl/util/image.hpp> +#include <mbgl/util/run_loop.hpp> +#include <mbgl/util/string.hpp> + +#include <utility> using namespace mbgl; @@ -25,16 +31,14 @@ auto imageFromAtlas(const SpriteAtlas& atlas) { } // namespace -TEST(Sprite, SpriteAtlas) { +TEST(SpriteAtlas, Basic) { FixtureLog log; auto spriteParseResult = parseSprite(util::read_file("test/fixtures/annotations/emerald.png"), util::read_file("test/fixtures/annotations/emerald.json")); - SpriteStore store(1); - store.setSprites(spriteParseResult.get<Sprites>()); - - SpriteAtlas atlas(63, 112, 1, store); + SpriteAtlas atlas(63, 112, 1); + atlas.setSprites(spriteParseResult.get<Sprites>()); EXPECT_EQ(1.0f, atlas.getPixelRatio()); EXPECT_EQ(63, atlas.getWidth()); @@ -86,14 +90,12 @@ TEST(Sprite, SpriteAtlas) { EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteatlas.png"), imageFromAtlas(atlas)); } -TEST(Sprite, SpriteAtlasSize) { +TEST(SpriteAtlas, Size) { auto spriteParseResult = parseSprite(util::read_file("test/fixtures/annotations/emerald.png"), util::read_file("test/fixtures/annotations/emerald.json")); - SpriteStore store(1); - store.setSprites(spriteParseResult.get<Sprites>()); - - SpriteAtlas atlas(63, 112, 1.4, store); + SpriteAtlas atlas(63, 112, 1.4); + atlas.setSprites(spriteParseResult.get<Sprites>()); EXPECT_DOUBLE_EQ(1.4f, atlas.getPixelRatio()); EXPECT_EQ(63, atlas.getWidth()); @@ -116,10 +118,8 @@ TEST(Sprite, SpriteAtlasSize) { imageFromAtlas(atlas)); } -TEST(Sprite, SpriteAtlasUpdates) { - SpriteStore store(1); - - SpriteAtlas atlas(32, 32, 1, store); +TEST(SpriteAtlas, Updates) { + SpriteAtlas atlas(32, 32, 1); EXPECT_EQ(1.0f, atlas.getPixelRatio()); EXPECT_EQ(32, atlas.getWidth()); @@ -127,7 +127,7 @@ TEST(Sprite, SpriteAtlasUpdates) { EXPECT_EQ(32, atlas.getTextureWidth()); EXPECT_EQ(32, atlas.getTextureHeight()); - store.setSprite("one", std::make_shared<SpriteImage>(PremultipliedImage(16, 12), 1)); + atlas.setSprite("one", std::make_shared<SpriteImage>(PremultipliedImage(16, 12), 1)); auto one = *atlas.getImage("one", SpritePatternMode::Single); EXPECT_EQ(0, one.pos.x); EXPECT_EQ(0, one.pos.y); @@ -148,8 +148,8 @@ TEST(Sprite, SpriteAtlasUpdates) { image2.data.get()[i] = 255; } auto newSprite = std::make_shared<SpriteImage>(std::move(image2), 1); - store.setSprite("one", newSprite); - ASSERT_EQ(newSprite, store.getSprite("one")); + atlas.setSprite("one", newSprite); + ASSERT_EQ(newSprite, atlas.getSprite("one")); // Atlas texture hasn't changed yet. EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteatlas-empty.png"), @@ -161,3 +161,259 @@ TEST(Sprite, SpriteAtlasUpdates) { EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteatlas-updated.png"), imageFromAtlas(atlas)); } + +TEST(SpriteAtlas, AddRemove) { + FixtureLog log; + + const auto sprite1 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2); + const auto sprite2 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2); + const auto sprite3 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2); + + SpriteAtlas atlas(32, 32, 1); + + // Adding single + atlas.setSprite("one", sprite1); + + // Adding multiple + atlas.setSprite("two", sprite2); + atlas.setSprite("three", sprite3); + + // Removing + atlas.removeSprite("one"); + atlas.removeSprite("two"); + + // Accessing + EXPECT_EQ(sprite3, atlas.getSprite("three")); + + EXPECT_TRUE(log.empty()); + + EXPECT_EQ(nullptr, atlas.getSprite("two")); + EXPECT_EQ(nullptr, atlas.getSprite("four")); + + EXPECT_EQ(1u, log.count({ + EventSeverity::Info, + Event::Sprite, + int64_t(-1), + "Can't find sprite named 'two'", + })); + EXPECT_EQ(1u, log.count({ + EventSeverity::Info, + Event::Sprite, + int64_t(-1), + "Can't find sprite named 'four'", + })); + + // Overwriting + atlas.setSprite("three", sprite1); +} + +TEST(SpriteAtlas, OtherPixelRatio) { + FixtureLog log; + + const auto sprite1 = std::make_shared<SpriteImage>(PremultipliedImage(8, 8), 1); + + SpriteAtlas atlas(32, 32, 1); + + // Adding mismatched sprite image + atlas.setSprite("one", sprite1); +} + +TEST(SpriteAtlas, Multiple) { + const auto sprite1 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2); + const auto sprite2 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2); + + SpriteAtlas atlas(32, 32, 1); + + atlas.setSprites({ + { "one", sprite1 }, { "two", sprite2 }, + }); +} + +TEST(SpriteAtlas, Replace) { + FixtureLog log; + + const auto sprite1 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2); + const auto sprite2 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2); + + SpriteAtlas atlas(32, 32, 1); + + atlas.setSprite("sprite", sprite1); + EXPECT_EQ(sprite1, atlas.getSprite("sprite")); + atlas.setSprite("sprite", sprite2); + EXPECT_EQ(sprite2, atlas.getSprite("sprite")); +} + +TEST(SpriteAtlas, ReplaceWithDifferentDimensions) { + FixtureLog log; + + PremultipliedImage image(16, 16); + PremultipliedImage image2(18, 18); + const auto sprite1 = std::make_shared<SpriteImage>(PremultipliedImage(16, 16), 2); + const auto sprite2 = std::make_shared<SpriteImage>(PremultipliedImage(18, 18), 2); + + SpriteAtlas atlas(32, 32, 1); + + atlas.setSprite("sprite", sprite1); + atlas.setSprite("sprite", sprite2); + + EXPECT_EQ(1u, log.count({ + EventSeverity::Warning, + Event::Sprite, + int64_t(-1), + "Can't change sprite dimensions for 'sprite'", + })); + + EXPECT_EQ(sprite1, atlas.getSprite("sprite")); +} + +class SpriteAtlasTest { +public: + SpriteAtlasTest() = default; + + util::RunLoop loop; + StubFileSource fileSource; + StubStyleObserver observer; + SpriteAtlas spriteAtlas { 32, 32, 1 }; + + void run() { + // Squelch logging. + Log::setObserver(std::make_unique<Log::NullObserver>()); + + spriteAtlas.setObserver(&observer); + spriteAtlas.load("test/fixtures/resources/sprite", fileSource); + + loop.run(); + } + + void end() { + loop.stop(); + } +}; + +Response successfulSpriteImageResponse(const Resource& resource) { + EXPECT_EQ("test/fixtures/resources/sprite.png", resource.url); + Response response; + response.data = std::make_shared<std::string>(util::read_file(resource.url)); + return response; +} + +Response successfulSpriteJSONResponse(const Resource& resource) { + EXPECT_EQ("test/fixtures/resources/sprite.json", resource.url); + Response response; + response.data = std::make_shared<std::string>(util::read_file(resource.url)); + return response; +} + +Response failedSpriteResponse(const Resource&) { + Response response; + response.error = std::make_unique<Response::Error>( + Response::Error::Reason::Other, + "Failed by the test case"); + return response; +} + +Response corruptSpriteResponse(const Resource&) { + Response response; + response.data = std::make_shared<std::string>("CORRUPT"); + return response; +} + +TEST(SpriteAtlas, LoadingSuccess) { + SpriteAtlasTest test; + + test.fileSource.spriteImageResponse = successfulSpriteImageResponse; + test.fileSource.spriteJSONResponse = successfulSpriteJSONResponse; + + test.observer.spriteError = [&] (std::exception_ptr error) { + FAIL() << util::toString(error); + test.end(); + }; + + test.observer.spriteLoaded = [&] () { + EXPECT_EQ(1.0, test.spriteAtlas.getPixelRatio()); + EXPECT_TRUE(test.spriteAtlas.isLoaded()); + test.end(); + }; + + test.run(); +} + +TEST(SpriteAtlas, JSONLoadingFail) { + SpriteAtlasTest test; + + test.fileSource.spriteImageResponse = successfulSpriteImageResponse; + test.fileSource.spriteJSONResponse = failedSpriteResponse; + + test.observer.spriteError = [&] (std::exception_ptr error) { + EXPECT_TRUE(error != nullptr); + EXPECT_EQ("Failed by the test case", util::toString(error)); + EXPECT_FALSE(test.spriteAtlas.isLoaded()); + test.end(); + }; + + test.run(); +} + +TEST(SpriteAtlas, ImageLoadingFail) { + SpriteAtlasTest test; + + test.fileSource.spriteImageResponse = failedSpriteResponse; + test.fileSource.spriteJSONResponse = successfulSpriteJSONResponse; + + test.observer.spriteError = [&] (std::exception_ptr error) { + EXPECT_TRUE(error != nullptr); + EXPECT_EQ("Failed by the test case", util::toString(error)); + EXPECT_FALSE(test.spriteAtlas.isLoaded()); + test.end(); + }; + + test.run(); +} + +TEST(SpriteAtlas, JSONLoadingCorrupted) { + SpriteAtlasTest test; + + test.fileSource.spriteImageResponse = successfulSpriteImageResponse; + test.fileSource.spriteJSONResponse = corruptSpriteResponse; + + test.observer.spriteError = [&] (std::exception_ptr error) { + EXPECT_TRUE(error != nullptr); + EXPECT_EQ("Failed to parse JSON: Invalid value. at offset 0", util::toString(error)); + EXPECT_FALSE(test.spriteAtlas.isLoaded()); + test.end(); + }; + + test.run(); +} + +TEST(SpriteAtlas, ImageLoadingCorrupted) { + SpriteAtlasTest test; + + test.fileSource.spriteImageResponse = corruptSpriteResponse; + test.fileSource.spriteJSONResponse = successfulSpriteJSONResponse; + + test.observer.spriteError = [&] (std::exception_ptr error) { + EXPECT_TRUE(error != nullptr); + // Not asserting on platform-specific error text. + EXPECT_FALSE(test.spriteAtlas.isLoaded()); + test.end(); + }; + + test.run(); +} + +TEST(SpriteAtlas, LoadingCancel) { + SpriteAtlasTest test; + + test.fileSource.spriteImageResponse = + test.fileSource.spriteJSONResponse = [&] (const Resource&) { + test.end(); + return optional<Response>(); + }; + + test.observer.spriteLoaded = [&] () { + FAIL() << "Should never be called"; + }; + + test.run(); +} |