From 3f3fc7b7723698e44427e2a14a2f4906832800bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Wed, 28 Sep 2016 11:45:33 +0200 Subject: [test] add .test.cpp suffix to test case files --- test/sprite/sprite_atlas.cpp | 419 ------------------------------------- test/sprite/sprite_atlas.test.cpp | 419 +++++++++++++++++++++++++++++++++++++ test/sprite/sprite_image.cpp | 57 ----- test/sprite/sprite_image.test.cpp | 57 +++++ test/sprite/sprite_parser.cpp | 306 --------------------------- test/sprite/sprite_parser.test.cpp | 306 +++++++++++++++++++++++++++ 6 files changed, 782 insertions(+), 782 deletions(-) delete mode 100644 test/sprite/sprite_atlas.cpp create mode 100644 test/sprite/sprite_atlas.test.cpp delete mode 100644 test/sprite/sprite_image.cpp create mode 100644 test/sprite/sprite_image.test.cpp delete mode 100644 test/sprite/sprite_parser.cpp create mode 100644 test/sprite/sprite_parser.test.cpp (limited to 'test/sprite') diff --git a/test/sprite/sprite_atlas.cpp b/test/sprite/sprite_atlas.cpp deleted file mode 100644 index f84e17cbcf..0000000000 --- a/test/sprite/sprite_atlas.cpp +++ /dev/null @@ -1,419 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace mbgl; - -namespace { - -auto readImage(const std::string& name) { - return decodeImage(util::read_file(name)); -} - -auto imageFromAtlas(const SpriteAtlas& atlas) { - const size_t bytes = atlas.getTextureWidth() * atlas.getTextureHeight() * 4; - auto data = std::make_unique(bytes); - const auto src = reinterpret_cast(atlas.getData()); - std::copy(src, src + bytes, data.get()); - return PremultipliedImage{ atlas.getTextureWidth(), atlas.getTextureHeight(), std::move(data) }; -} - -} // namespace - -TEST(SpriteAtlas, Basic) { - FixtureLog log; - - auto spriteParseResult = parseSprite(util::read_file("test/fixtures/annotations/emerald.png"), - util::read_file("test/fixtures/annotations/emerald.json")); - - SpriteAtlas atlas(63, 112, 1); - atlas.setSprites(spriteParseResult.get()); - - EXPECT_EQ(1.0f, atlas.getPixelRatio()); - EXPECT_EQ(63, atlas.getWidth()); - EXPECT_EQ(112, atlas.getHeight()); - EXPECT_EQ(63, atlas.getTextureWidth()); - EXPECT_EQ(112, atlas.getTextureHeight()); - - // Image hasn't been created yet. - EXPECT_FALSE(atlas.getData()); - - auto metro = *atlas.getImage("metro", SpritePatternMode::Single); - EXPECT_EQ(0, metro.pos.x); - EXPECT_EQ(0, metro.pos.y); - EXPECT_EQ(20, metro.pos.w); - EXPECT_EQ(20, metro.pos.h); - EXPECT_EQ(18, metro.spriteImage->getWidth()); - EXPECT_EQ(18, metro.spriteImage->getHeight()); - EXPECT_EQ(18u, metro.spriteImage->image.width); - EXPECT_EQ(18u, metro.spriteImage->image.height); - EXPECT_EQ(1.0f, metro.spriteImage->pixelRatio); - - EXPECT_TRUE(atlas.getData()); - - auto pos = *atlas.getPosition("metro", SpritePatternMode::Single); - EXPECT_DOUBLE_EQ(18, pos.size[0]); - EXPECT_DOUBLE_EQ(18, pos.size[1]); - EXPECT_DOUBLE_EQ(1.0f / 63, pos.tl[0]); - EXPECT_DOUBLE_EQ(1.0f / 112, pos.tl[1]); - EXPECT_DOUBLE_EQ(19.0f / 63, pos.br[0]); - EXPECT_DOUBLE_EQ(19.0f / 112, pos.br[1]); - - auto missing = atlas.getImage("doesnotexist", SpritePatternMode::Single); - EXPECT_FALSE(missing); - - EXPECT_EQ(1u, log.count({ - EventSeverity::Info, - Event::Sprite, - int64_t(-1), - "Can't find sprite named 'doesnotexist'", - })); - - // Different wrapping mode produces different image. - auto metro2 = *atlas.getImage("metro", SpritePatternMode::Repeating); - EXPECT_EQ(20, metro2.pos.x); - EXPECT_EQ(0, metro2.pos.y); - EXPECT_EQ(20, metro2.pos.w); - EXPECT_EQ(20, metro2.pos.h); - - EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteatlas.png"), imageFromAtlas(atlas)); -} - -TEST(SpriteAtlas, Size) { - auto spriteParseResult = parseSprite(util::read_file("test/fixtures/annotations/emerald.png"), - util::read_file("test/fixtures/annotations/emerald.json")); - - SpriteAtlas atlas(63, 112, 1.4); - atlas.setSprites(spriteParseResult.get()); - - EXPECT_DOUBLE_EQ(1.4f, atlas.getPixelRatio()); - EXPECT_EQ(63, atlas.getWidth()); - EXPECT_EQ(112, atlas.getHeight()); - EXPECT_EQ(89, atlas.getTextureWidth()); - EXPECT_EQ(157, atlas.getTextureHeight()); - - auto metro = *atlas.getImage("metro", SpritePatternMode::Single); - EXPECT_EQ(0, metro.pos.x); - EXPECT_EQ(0, metro.pos.y); - EXPECT_EQ(16, metro.pos.w); - EXPECT_EQ(16, metro.pos.h); - EXPECT_EQ(18, metro.spriteImage->getWidth()); - EXPECT_EQ(18, metro.spriteImage->getHeight()); - EXPECT_EQ(18u, metro.spriteImage->image.width); - EXPECT_EQ(18u, metro.spriteImage->image.height); - EXPECT_EQ(1.0f, metro.spriteImage->pixelRatio); - - EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteatlassize.png"), - imageFromAtlas(atlas)); -} - -TEST(SpriteAtlas, Updates) { - SpriteAtlas atlas(32, 32, 1); - - EXPECT_EQ(1.0f, atlas.getPixelRatio()); - EXPECT_EQ(32, atlas.getWidth()); - EXPECT_EQ(32, atlas.getHeight()); - EXPECT_EQ(32, atlas.getTextureWidth()); - EXPECT_EQ(32, atlas.getTextureHeight()); - - atlas.setSprite("one", std::make_shared(PremultipliedImage(16, 12), 1)); - auto one = *atlas.getImage("one", SpritePatternMode::Single); - EXPECT_EQ(0, one.pos.x); - EXPECT_EQ(0, one.pos.y); - EXPECT_EQ(20, one.pos.w); - EXPECT_EQ(16, one.pos.h); - EXPECT_EQ(16, one.spriteImage->getWidth()); - EXPECT_EQ(12, one.spriteImage->getHeight()); - EXPECT_EQ(16u, one.spriteImage->image.width); - EXPECT_EQ(12u, one.spriteImage->image.height); - EXPECT_EQ(1.0f, one.spriteImage->pixelRatio); - - EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteatlas-empty.png"), - imageFromAtlas(atlas)); - - // Update sprite - PremultipliedImage image2(16, 12); - for (size_t i = 0; i < image2.size(); i++) { - image2.data.get()[i] = 255; - } - auto newSprite = std::make_shared(std::move(image2), 1); - 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"), - imageFromAtlas(atlas)); - - atlas.updateDirty(); - - // Now the atlas texture has changed. - EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteatlas-updated.png"), - imageFromAtlas(atlas)); -} - -TEST(SpriteAtlas, AddRemove) { - FixtureLog log; - - const auto sprite1 = std::make_shared(PremultipliedImage(16, 16), 2); - const auto sprite2 = std::make_shared(PremultipliedImage(16, 16), 2); - const auto sprite3 = std::make_shared(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(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(PremultipliedImage(16, 16), 2); - const auto sprite2 = std::make_shared(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(PremultipliedImage(16, 16), 2); - const auto sprite2 = std::make_shared(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(PremultipliedImage(16, 16), 2); - const auto sprite2 = std::make_shared(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()); - - 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(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(util::read_file(resource.url)); - return response; -} - -Response failedSpriteResponse(const Resource&) { - Response response; - response.error = std::make_unique( - Response::Error::Reason::Other, - "Failed by the test case"); - return response; -} - -Response corruptSpriteResponse(const Resource&) { - Response response; - response.data = std::make_shared("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(); - }; - - test.observer.spriteLoaded = [&] () { - FAIL() << "Should never be called"; - }; - - test.run(); -} diff --git a/test/sprite/sprite_atlas.test.cpp b/test/sprite/sprite_atlas.test.cpp new file mode 100644 index 0000000000..f84e17cbcf --- /dev/null +++ b/test/sprite/sprite_atlas.test.cpp @@ -0,0 +1,419 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace mbgl; + +namespace { + +auto readImage(const std::string& name) { + return decodeImage(util::read_file(name)); +} + +auto imageFromAtlas(const SpriteAtlas& atlas) { + const size_t bytes = atlas.getTextureWidth() * atlas.getTextureHeight() * 4; + auto data = std::make_unique(bytes); + const auto src = reinterpret_cast(atlas.getData()); + std::copy(src, src + bytes, data.get()); + return PremultipliedImage{ atlas.getTextureWidth(), atlas.getTextureHeight(), std::move(data) }; +} + +} // namespace + +TEST(SpriteAtlas, Basic) { + FixtureLog log; + + auto spriteParseResult = parseSprite(util::read_file("test/fixtures/annotations/emerald.png"), + util::read_file("test/fixtures/annotations/emerald.json")); + + SpriteAtlas atlas(63, 112, 1); + atlas.setSprites(spriteParseResult.get()); + + EXPECT_EQ(1.0f, atlas.getPixelRatio()); + EXPECT_EQ(63, atlas.getWidth()); + EXPECT_EQ(112, atlas.getHeight()); + EXPECT_EQ(63, atlas.getTextureWidth()); + EXPECT_EQ(112, atlas.getTextureHeight()); + + // Image hasn't been created yet. + EXPECT_FALSE(atlas.getData()); + + auto metro = *atlas.getImage("metro", SpritePatternMode::Single); + EXPECT_EQ(0, metro.pos.x); + EXPECT_EQ(0, metro.pos.y); + EXPECT_EQ(20, metro.pos.w); + EXPECT_EQ(20, metro.pos.h); + EXPECT_EQ(18, metro.spriteImage->getWidth()); + EXPECT_EQ(18, metro.spriteImage->getHeight()); + EXPECT_EQ(18u, metro.spriteImage->image.width); + EXPECT_EQ(18u, metro.spriteImage->image.height); + EXPECT_EQ(1.0f, metro.spriteImage->pixelRatio); + + EXPECT_TRUE(atlas.getData()); + + auto pos = *atlas.getPosition("metro", SpritePatternMode::Single); + EXPECT_DOUBLE_EQ(18, pos.size[0]); + EXPECT_DOUBLE_EQ(18, pos.size[1]); + EXPECT_DOUBLE_EQ(1.0f / 63, pos.tl[0]); + EXPECT_DOUBLE_EQ(1.0f / 112, pos.tl[1]); + EXPECT_DOUBLE_EQ(19.0f / 63, pos.br[0]); + EXPECT_DOUBLE_EQ(19.0f / 112, pos.br[1]); + + auto missing = atlas.getImage("doesnotexist", SpritePatternMode::Single); + EXPECT_FALSE(missing); + + EXPECT_EQ(1u, log.count({ + EventSeverity::Info, + Event::Sprite, + int64_t(-1), + "Can't find sprite named 'doesnotexist'", + })); + + // Different wrapping mode produces different image. + auto metro2 = *atlas.getImage("metro", SpritePatternMode::Repeating); + EXPECT_EQ(20, metro2.pos.x); + EXPECT_EQ(0, metro2.pos.y); + EXPECT_EQ(20, metro2.pos.w); + EXPECT_EQ(20, metro2.pos.h); + + EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteatlas.png"), imageFromAtlas(atlas)); +} + +TEST(SpriteAtlas, Size) { + auto spriteParseResult = parseSprite(util::read_file("test/fixtures/annotations/emerald.png"), + util::read_file("test/fixtures/annotations/emerald.json")); + + SpriteAtlas atlas(63, 112, 1.4); + atlas.setSprites(spriteParseResult.get()); + + EXPECT_DOUBLE_EQ(1.4f, atlas.getPixelRatio()); + EXPECT_EQ(63, atlas.getWidth()); + EXPECT_EQ(112, atlas.getHeight()); + EXPECT_EQ(89, atlas.getTextureWidth()); + EXPECT_EQ(157, atlas.getTextureHeight()); + + auto metro = *atlas.getImage("metro", SpritePatternMode::Single); + EXPECT_EQ(0, metro.pos.x); + EXPECT_EQ(0, metro.pos.y); + EXPECT_EQ(16, metro.pos.w); + EXPECT_EQ(16, metro.pos.h); + EXPECT_EQ(18, metro.spriteImage->getWidth()); + EXPECT_EQ(18, metro.spriteImage->getHeight()); + EXPECT_EQ(18u, metro.spriteImage->image.width); + EXPECT_EQ(18u, metro.spriteImage->image.height); + EXPECT_EQ(1.0f, metro.spriteImage->pixelRatio); + + EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteatlassize.png"), + imageFromAtlas(atlas)); +} + +TEST(SpriteAtlas, Updates) { + SpriteAtlas atlas(32, 32, 1); + + EXPECT_EQ(1.0f, atlas.getPixelRatio()); + EXPECT_EQ(32, atlas.getWidth()); + EXPECT_EQ(32, atlas.getHeight()); + EXPECT_EQ(32, atlas.getTextureWidth()); + EXPECT_EQ(32, atlas.getTextureHeight()); + + atlas.setSprite("one", std::make_shared(PremultipliedImage(16, 12), 1)); + auto one = *atlas.getImage("one", SpritePatternMode::Single); + EXPECT_EQ(0, one.pos.x); + EXPECT_EQ(0, one.pos.y); + EXPECT_EQ(20, one.pos.w); + EXPECT_EQ(16, one.pos.h); + EXPECT_EQ(16, one.spriteImage->getWidth()); + EXPECT_EQ(12, one.spriteImage->getHeight()); + EXPECT_EQ(16u, one.spriteImage->image.width); + EXPECT_EQ(12u, one.spriteImage->image.height); + EXPECT_EQ(1.0f, one.spriteImage->pixelRatio); + + EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteatlas-empty.png"), + imageFromAtlas(atlas)); + + // Update sprite + PremultipliedImage image2(16, 12); + for (size_t i = 0; i < image2.size(); i++) { + image2.data.get()[i] = 255; + } + auto newSprite = std::make_shared(std::move(image2), 1); + 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"), + imageFromAtlas(atlas)); + + atlas.updateDirty(); + + // Now the atlas texture has changed. + EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteatlas-updated.png"), + imageFromAtlas(atlas)); +} + +TEST(SpriteAtlas, AddRemove) { + FixtureLog log; + + const auto sprite1 = std::make_shared(PremultipliedImage(16, 16), 2); + const auto sprite2 = std::make_shared(PremultipliedImage(16, 16), 2); + const auto sprite3 = std::make_shared(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(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(PremultipliedImage(16, 16), 2); + const auto sprite2 = std::make_shared(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(PremultipliedImage(16, 16), 2); + const auto sprite2 = std::make_shared(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(PremultipliedImage(16, 16), 2); + const auto sprite2 = std::make_shared(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()); + + 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(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(util::read_file(resource.url)); + return response; +} + +Response failedSpriteResponse(const Resource&) { + Response response; + response.error = std::make_unique( + Response::Error::Reason::Other, + "Failed by the test case"); + return response; +} + +Response corruptSpriteResponse(const Resource&) { + Response response; + response.data = std::make_shared("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(); + }; + + test.observer.spriteLoaded = [&] () { + FAIL() << "Should never be called"; + }; + + test.run(); +} diff --git a/test/sprite/sprite_image.cpp b/test/sprite/sprite_image.cpp deleted file mode 100644 index f8982826a3..0000000000 --- a/test/sprite/sprite_image.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include - -#include -#include -#include - -using namespace mbgl; - -TEST(Sprite, SpriteImageZeroWidth) { - PremultipliedImage image(0, 16); - try { - SpriteImage(std::move(image), 2.0); - FAIL() << "Expected exception"; - } catch (util::SpriteImageException& ex) { - EXPECT_STREQ("Sprite image dimensions may not be zero", ex.what()); - } -} - -TEST(Sprite, SpriteImageZeroHeight) { - PremultipliedImage image(16, 0); - try { - SpriteImage(std::move(image), 2.0); - FAIL() << "Expected exception"; - } catch (util::SpriteImageException& ex) { - EXPECT_STREQ("Sprite image dimensions may not be zero", ex.what()); - } -} - -TEST(Sprite, SpriteImageZeroRatio) { - PremultipliedImage image(16, 16); - try { - SpriteImage(std::move(image), 0.0); - FAIL() << "Expected exception"; - } catch (util::SpriteImageException& ex) { - EXPECT_STREQ("Sprite pixelRatio may not be <= 0", ex.what()); - } -} - -TEST(Sprite, SpriteImage) { - PremultipliedImage image(32, 24); - SpriteImage sprite(std::move(image), 2.0); - EXPECT_EQ(16, sprite.getWidth()); - EXPECT_EQ(32u, sprite.image.width); - EXPECT_EQ(12, sprite.getHeight()); - EXPECT_EQ(24u, sprite.image.height); - EXPECT_EQ(2, sprite.pixelRatio); -} - -TEST(Sprite, SpriteImageFractionalRatio) { - PremultipliedImage image(20, 12); - SpriteImage sprite(std::move(image), 1.5); - EXPECT_EQ(float(20.0 / 1.5), sprite.getWidth()); - EXPECT_EQ(20u, sprite.image.width); - EXPECT_EQ(float(12.0 / 1.5), sprite.getHeight()); - EXPECT_EQ(12u, sprite.image.height); - EXPECT_EQ(1.5, sprite.pixelRatio); -} diff --git a/test/sprite/sprite_image.test.cpp b/test/sprite/sprite_image.test.cpp new file mode 100644 index 0000000000..f8982826a3 --- /dev/null +++ b/test/sprite/sprite_image.test.cpp @@ -0,0 +1,57 @@ +#include + +#include +#include +#include + +using namespace mbgl; + +TEST(Sprite, SpriteImageZeroWidth) { + PremultipliedImage image(0, 16); + try { + SpriteImage(std::move(image), 2.0); + FAIL() << "Expected exception"; + } catch (util::SpriteImageException& ex) { + EXPECT_STREQ("Sprite image dimensions may not be zero", ex.what()); + } +} + +TEST(Sprite, SpriteImageZeroHeight) { + PremultipliedImage image(16, 0); + try { + SpriteImage(std::move(image), 2.0); + FAIL() << "Expected exception"; + } catch (util::SpriteImageException& ex) { + EXPECT_STREQ("Sprite image dimensions may not be zero", ex.what()); + } +} + +TEST(Sprite, SpriteImageZeroRatio) { + PremultipliedImage image(16, 16); + try { + SpriteImage(std::move(image), 0.0); + FAIL() << "Expected exception"; + } catch (util::SpriteImageException& ex) { + EXPECT_STREQ("Sprite pixelRatio may not be <= 0", ex.what()); + } +} + +TEST(Sprite, SpriteImage) { + PremultipliedImage image(32, 24); + SpriteImage sprite(std::move(image), 2.0); + EXPECT_EQ(16, sprite.getWidth()); + EXPECT_EQ(32u, sprite.image.width); + EXPECT_EQ(12, sprite.getHeight()); + EXPECT_EQ(24u, sprite.image.height); + EXPECT_EQ(2, sprite.pixelRatio); +} + +TEST(Sprite, SpriteImageFractionalRatio) { + PremultipliedImage image(20, 12); + SpriteImage sprite(std::move(image), 1.5); + EXPECT_EQ(float(20.0 / 1.5), sprite.getWidth()); + EXPECT_EQ(20u, sprite.image.width); + EXPECT_EQ(float(12.0 / 1.5), sprite.getHeight()); + EXPECT_EQ(12u, sprite.image.height); + EXPECT_EQ(1.5, sprite.pixelRatio); +} diff --git a/test/sprite/sprite_parser.cpp b/test/sprite/sprite_parser.cpp deleted file mode 100644 index 8d32d081bf..0000000000 --- a/test/sprite/sprite_parser.cpp +++ /dev/null @@ -1,306 +0,0 @@ -#include -#include - -#include -#include -#include -#include -#include - -#include - -using namespace mbgl; - -namespace { - -auto readImage(const std::string& name) { - return decodeImage(util::read_file(name)); -} - -} // namespace - -TEST(Sprite, SpriteImageCreationInvalid) { - FixtureLog log; - - const PremultipliedImage image_1x = decodeImage(util::read_file("test/fixtures/annotations/emerald.png")); - - ASSERT_EQ(200u, image_1x.width); - ASSERT_EQ(299u, image_1x.height); - - ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 0, 16, 1, false)); // width == 0 - ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 16, 0, 1, false)); // height == 0 - ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, -1, 16, 1, false)); // width < 0 - ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 16, -1, 1, false)); // height < 0 - ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 1, 1, 0, false)); // ratio == 0 - ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 1, 1, -1, false)); // ratio < 0 - ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 1, 1, 23, false)); // ratio too large - ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 2048, 16, 1, false)); // too wide - ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 16, 1025, 1, false)); // too tall - ASSERT_EQ(nullptr, createSpriteImage(image_1x, -1, 0, 16, 16, 1, false)); // srcX < 0 - ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, -1, 16, 16, 1, false)); // srcY < 0 - ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, image_1x.width + 1, 16, 1, false)); // right edge out of bounds - ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 16, image_1x.height + 1, 1, false)); // bottom edge out of bounds - - EXPECT_EQ(13u, log.count({ - EventSeverity::Error, - Event::Sprite, - int64_t(-1), - "Can't create sprite with invalid metrics", - })); -} - -TEST(Sprite, SpriteImageCreation1x) { - const PremultipliedImage image_1x = decodeImage(util::read_file("test/fixtures/annotations/emerald.png")); - - ASSERT_EQ(200u, image_1x.width); - ASSERT_EQ(299u, image_1x.height); - - { // "museum_icon":{"x":177,"y":187,"width":18,"height":18,"pixelRatio":1,"sdf":false} - const auto sprite = createSpriteImage(image_1x, 177, 187, 18, 18, 1, false); - ASSERT_TRUE(sprite.get()); - EXPECT_EQ(18, sprite->getWidth()); - EXPECT_EQ(18, sprite->getHeight()); - EXPECT_EQ(18u, sprite->image.width); - EXPECT_EQ(18u, sprite->image.height); - EXPECT_EQ(1, sprite->pixelRatio); - EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteimagecreation1x-museum.png"), - sprite->image); - } -} - -TEST(Sprite, SpriteImageCreation2x) { - const PremultipliedImage image_2x = decodeImage(util::read_file("test/fixtures/annotations/emerald@2x.png")); - - // "museum_icon":{"x":354,"y":374,"width":36,"height":36,"pixelRatio":2,"sdf":false} - const auto sprite = createSpriteImage(image_2x, 354, 374, 36, 36, 2, false); - ASSERT_TRUE(sprite.get()); - EXPECT_EQ(18, sprite->getWidth()); - EXPECT_EQ(18, sprite->getHeight()); - EXPECT_EQ(36u, sprite->image.width); - EXPECT_EQ(36u, sprite->image.height); - EXPECT_EQ(2, sprite->pixelRatio); - EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteimagecreation2x.png"), - sprite->image); -} - -TEST(Sprite, SpriteImageCreation1_5x) { - const PremultipliedImage image_2x = decodeImage(util::read_file("test/fixtures/annotations/emerald@2x.png")); - - // "museum_icon":{"x":354,"y":374,"width":36,"height":36,"pixelRatio":2,"sdf":false} - const auto sprite = createSpriteImage(image_2x, 354, 374, 36, 36, 1.5, false); - ASSERT_TRUE(sprite.get()); - EXPECT_EQ(24, sprite->getWidth()); - EXPECT_EQ(24, sprite->getHeight()); - EXPECT_EQ(36u, sprite->image.width); - EXPECT_EQ(36u, sprite->image.height); - EXPECT_EQ(1.5, sprite->pixelRatio); - EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteimagecreation1_5x-museum.png"), - sprite->image); - - // "hospital_icon":{"x":314,"y":518,"width":36,"height":36,"pixelRatio":2,"sdf":false} - const auto sprite2 = createSpriteImage(image_2x, 314, 518, 35, 35, 1.5, false); - ASSERT_TRUE(sprite2.get()); - EXPECT_EQ(float(35 / 1.5), sprite2->getWidth()); - EXPECT_EQ(float(35 / 1.5), sprite2->getHeight()); - EXPECT_EQ(35u, sprite2->image.width); - EXPECT_EQ(35u, sprite2->image.height); - EXPECT_EQ(1.5, sprite2->pixelRatio); - EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteimagecreation1_5x-hospital.png"), - sprite2->image); -} - -TEST(Sprite, SpriteParsing) { - const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); - const auto json_1x = util::read_file("test/fixtures/annotations/emerald.json"); - - const auto images = parseSprite(image_1x, json_1x).get(); - - std::set names; - std::transform(images.begin(), images.end(), std::inserter(names, names.begin()), - [](const auto& pair) { return pair.first; }); - - EXPECT_EQ(std::set({ "airfield_icon", - "airport_icon", - "background", - "cemetery_icon", - "college_icon", - "default_1", - "default_2", - "default_3", - "default_4", - "default_5", - "default_6", - "default_marker", - "dlr", - "dlr.london-overground.london-underground.national-rail", - "dlr.london-underground", - "dlr.london-underground.national-rail", - "dlr.national-rail", - "dot", - "embassy_icon", - "fire-station_icon", - "generic-metro", - "generic-rail", - "generic_icon", - "golf_icon", - "government_icon", - "grass_pattern", - "harbor_icon", - "hospital_icon", - "hospital_striped", - "interstate_1", - "interstate_2", - "interstate_3", - "library_icon", - "london-overground", - "london-overground.london-underground", - "london-overground.london-underground.national-rail", - "london-overground.national-rail", - "london-underground", - "london-underground.national-rail", - "marker_icon", - "metro", - "metro.rer", - "monument_icon", - "moscow-metro", - "museum_icon", - "national-rail", - "oneway_motorway", - "oneway_road", - "park_icon", - "police_icon", - "post_icon", - "prison_icon", - "religious-christian_icon", - "religious-jewish_icon", - "religious-muslim_icon", - "rer", - "rer.transilien", - "s-bahn", - "s-bahn.u-bahn", - "sand_noise", - "school_icon", - "school_striped", - "secondary_marker", - "u-bahn", - "us_highway_1", - "us_highway_2", - "us_highway_3", - "us_state_1", - "us_state_2", - "us_state_3", - "washington-metro", - "wiener-linien", - "zoo_icon" }), - names); - - { - auto sprite = images.find("generic-metro")->second; - EXPECT_EQ(18, sprite->getWidth()); - EXPECT_EQ(18, sprite->getHeight()); - EXPECT_EQ(18u, sprite->image.width); - EXPECT_EQ(18u, sprite->image.height); - EXPECT_EQ(1, sprite->pixelRatio); - EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteparsing.png"), sprite->image); - } -} - -TEST(Sprite, SpriteParsingInvalidJSON) { - const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); - const auto json_1x = R"JSON({ "image": " })JSON"; - - const auto error = parseSprite(image_1x, json_1x).get(); - - EXPECT_EQ(util::toString(error), - std::string("Failed to parse JSON: Missing a closing quotation mark in string. at offset 14")); -} - -TEST(Sprite, SpriteParsingEmptyImage) { - FixtureLog log; - - const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); - const auto json_1x = R"JSON({ "image": {} })JSON"; - - const auto images = parseSprite(image_1x, json_1x).get(); - EXPECT_EQ(0u, images.size()); - - EXPECT_EQ(1u, log.count({ - EventSeverity::Error, - Event::Sprite, - int64_t(-1), - "Can't create sprite with invalid metrics", - })); -} - -TEST(Sprite, SpriteParsingSimpleWidthHeight) { - FixtureLog log; - - const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); - const auto json_1x = R"JSON({ "image": { "width": 32, "height": 32 } })JSON"; - - const auto images = parseSprite(image_1x, json_1x).get(); - EXPECT_EQ(1u, images.size()); -} - -TEST(Sprite, SpriteParsingWidthTooBig) { - FixtureLog log; - - const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); - const auto json_1x = R"JSON({ "image": { "width": 65536, "height": 32 } })JSON"; - - const auto images = parseSprite(image_1x, json_1x).get(); - EXPECT_EQ(0u, images.size()); - - EXPECT_EQ(1u, log.count({ - EventSeverity::Warning, - Event::Sprite, - int64_t(-1), - "Value of 'width' must be an integer between 0 and 65535", - })); - EXPECT_EQ(1u, log.count({ - EventSeverity::Error, - Event::Sprite, - int64_t(-1), - "Can't create sprite with invalid metrics", - })); -} - -TEST(Sprite, SpriteParsingNegativeWidth) { - FixtureLog log; - - const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); - const auto json_1x = R"JSON({ "image": { "width": -1, "height": 32 } })JSON"; - - const auto images = parseSprite(image_1x, json_1x).get(); - EXPECT_EQ(0u, images.size()); - - EXPECT_EQ(1u, log.count({ - EventSeverity::Warning, - Event::Sprite, - int64_t(-1), - "Value of 'width' must be an integer between 0 and 65535", - })); - EXPECT_EQ(1u, log.count({ - EventSeverity::Error, - Event::Sprite, - int64_t(-1), - "Can't create sprite with invalid metrics", - })); -} - -TEST(Sprite, SpriteParsingNullRatio) { - FixtureLog log; - - const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); - const auto json_1x = R"JSON({ "image": { "width": 32, "height": 32, "pixelRatio": 0 } })JSON"; - - const auto images = parseSprite(image_1x, json_1x).get(); - EXPECT_EQ(0u, images.size()); - - EXPECT_EQ(1u, log.count({ - EventSeverity::Error, - Event::Sprite, - int64_t(-1), - "Can't create sprite with invalid metrics", - })); -} diff --git a/test/sprite/sprite_parser.test.cpp b/test/sprite/sprite_parser.test.cpp new file mode 100644 index 0000000000..8d32d081bf --- /dev/null +++ b/test/sprite/sprite_parser.test.cpp @@ -0,0 +1,306 @@ +#include +#include + +#include +#include +#include +#include +#include + +#include + +using namespace mbgl; + +namespace { + +auto readImage(const std::string& name) { + return decodeImage(util::read_file(name)); +} + +} // namespace + +TEST(Sprite, SpriteImageCreationInvalid) { + FixtureLog log; + + const PremultipliedImage image_1x = decodeImage(util::read_file("test/fixtures/annotations/emerald.png")); + + ASSERT_EQ(200u, image_1x.width); + ASSERT_EQ(299u, image_1x.height); + + ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 0, 16, 1, false)); // width == 0 + ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 16, 0, 1, false)); // height == 0 + ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, -1, 16, 1, false)); // width < 0 + ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 16, -1, 1, false)); // height < 0 + ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 1, 1, 0, false)); // ratio == 0 + ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 1, 1, -1, false)); // ratio < 0 + ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 1, 1, 23, false)); // ratio too large + ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 2048, 16, 1, false)); // too wide + ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 16, 1025, 1, false)); // too tall + ASSERT_EQ(nullptr, createSpriteImage(image_1x, -1, 0, 16, 16, 1, false)); // srcX < 0 + ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, -1, 16, 16, 1, false)); // srcY < 0 + ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, image_1x.width + 1, 16, 1, false)); // right edge out of bounds + ASSERT_EQ(nullptr, createSpriteImage(image_1x, 0, 0, 16, image_1x.height + 1, 1, false)); // bottom edge out of bounds + + EXPECT_EQ(13u, log.count({ + EventSeverity::Error, + Event::Sprite, + int64_t(-1), + "Can't create sprite with invalid metrics", + })); +} + +TEST(Sprite, SpriteImageCreation1x) { + const PremultipliedImage image_1x = decodeImage(util::read_file("test/fixtures/annotations/emerald.png")); + + ASSERT_EQ(200u, image_1x.width); + ASSERT_EQ(299u, image_1x.height); + + { // "museum_icon":{"x":177,"y":187,"width":18,"height":18,"pixelRatio":1,"sdf":false} + const auto sprite = createSpriteImage(image_1x, 177, 187, 18, 18, 1, false); + ASSERT_TRUE(sprite.get()); + EXPECT_EQ(18, sprite->getWidth()); + EXPECT_EQ(18, sprite->getHeight()); + EXPECT_EQ(18u, sprite->image.width); + EXPECT_EQ(18u, sprite->image.height); + EXPECT_EQ(1, sprite->pixelRatio); + EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteimagecreation1x-museum.png"), + sprite->image); + } +} + +TEST(Sprite, SpriteImageCreation2x) { + const PremultipliedImage image_2x = decodeImage(util::read_file("test/fixtures/annotations/emerald@2x.png")); + + // "museum_icon":{"x":354,"y":374,"width":36,"height":36,"pixelRatio":2,"sdf":false} + const auto sprite = createSpriteImage(image_2x, 354, 374, 36, 36, 2, false); + ASSERT_TRUE(sprite.get()); + EXPECT_EQ(18, sprite->getWidth()); + EXPECT_EQ(18, sprite->getHeight()); + EXPECT_EQ(36u, sprite->image.width); + EXPECT_EQ(36u, sprite->image.height); + EXPECT_EQ(2, sprite->pixelRatio); + EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteimagecreation2x.png"), + sprite->image); +} + +TEST(Sprite, SpriteImageCreation1_5x) { + const PremultipliedImage image_2x = decodeImage(util::read_file("test/fixtures/annotations/emerald@2x.png")); + + // "museum_icon":{"x":354,"y":374,"width":36,"height":36,"pixelRatio":2,"sdf":false} + const auto sprite = createSpriteImage(image_2x, 354, 374, 36, 36, 1.5, false); + ASSERT_TRUE(sprite.get()); + EXPECT_EQ(24, sprite->getWidth()); + EXPECT_EQ(24, sprite->getHeight()); + EXPECT_EQ(36u, sprite->image.width); + EXPECT_EQ(36u, sprite->image.height); + EXPECT_EQ(1.5, sprite->pixelRatio); + EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteimagecreation1_5x-museum.png"), + sprite->image); + + // "hospital_icon":{"x":314,"y":518,"width":36,"height":36,"pixelRatio":2,"sdf":false} + const auto sprite2 = createSpriteImage(image_2x, 314, 518, 35, 35, 1.5, false); + ASSERT_TRUE(sprite2.get()); + EXPECT_EQ(float(35 / 1.5), sprite2->getWidth()); + EXPECT_EQ(float(35 / 1.5), sprite2->getHeight()); + EXPECT_EQ(35u, sprite2->image.width); + EXPECT_EQ(35u, sprite2->image.height); + EXPECT_EQ(1.5, sprite2->pixelRatio); + EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteimagecreation1_5x-hospital.png"), + sprite2->image); +} + +TEST(Sprite, SpriteParsing) { + const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); + const auto json_1x = util::read_file("test/fixtures/annotations/emerald.json"); + + const auto images = parseSprite(image_1x, json_1x).get(); + + std::set names; + std::transform(images.begin(), images.end(), std::inserter(names, names.begin()), + [](const auto& pair) { return pair.first; }); + + EXPECT_EQ(std::set({ "airfield_icon", + "airport_icon", + "background", + "cemetery_icon", + "college_icon", + "default_1", + "default_2", + "default_3", + "default_4", + "default_5", + "default_6", + "default_marker", + "dlr", + "dlr.london-overground.london-underground.national-rail", + "dlr.london-underground", + "dlr.london-underground.national-rail", + "dlr.national-rail", + "dot", + "embassy_icon", + "fire-station_icon", + "generic-metro", + "generic-rail", + "generic_icon", + "golf_icon", + "government_icon", + "grass_pattern", + "harbor_icon", + "hospital_icon", + "hospital_striped", + "interstate_1", + "interstate_2", + "interstate_3", + "library_icon", + "london-overground", + "london-overground.london-underground", + "london-overground.london-underground.national-rail", + "london-overground.national-rail", + "london-underground", + "london-underground.national-rail", + "marker_icon", + "metro", + "metro.rer", + "monument_icon", + "moscow-metro", + "museum_icon", + "national-rail", + "oneway_motorway", + "oneway_road", + "park_icon", + "police_icon", + "post_icon", + "prison_icon", + "religious-christian_icon", + "religious-jewish_icon", + "religious-muslim_icon", + "rer", + "rer.transilien", + "s-bahn", + "s-bahn.u-bahn", + "sand_noise", + "school_icon", + "school_striped", + "secondary_marker", + "u-bahn", + "us_highway_1", + "us_highway_2", + "us_highway_3", + "us_state_1", + "us_state_2", + "us_state_3", + "washington-metro", + "wiener-linien", + "zoo_icon" }), + names); + + { + auto sprite = images.find("generic-metro")->second; + EXPECT_EQ(18, sprite->getWidth()); + EXPECT_EQ(18, sprite->getHeight()); + EXPECT_EQ(18u, sprite->image.width); + EXPECT_EQ(18u, sprite->image.height); + EXPECT_EQ(1, sprite->pixelRatio); + EXPECT_EQ(readImage("test/fixtures/annotations/result-spriteparsing.png"), sprite->image); + } +} + +TEST(Sprite, SpriteParsingInvalidJSON) { + const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); + const auto json_1x = R"JSON({ "image": " })JSON"; + + const auto error = parseSprite(image_1x, json_1x).get(); + + EXPECT_EQ(util::toString(error), + std::string("Failed to parse JSON: Missing a closing quotation mark in string. at offset 14")); +} + +TEST(Sprite, SpriteParsingEmptyImage) { + FixtureLog log; + + const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); + const auto json_1x = R"JSON({ "image": {} })JSON"; + + const auto images = parseSprite(image_1x, json_1x).get(); + EXPECT_EQ(0u, images.size()); + + EXPECT_EQ(1u, log.count({ + EventSeverity::Error, + Event::Sprite, + int64_t(-1), + "Can't create sprite with invalid metrics", + })); +} + +TEST(Sprite, SpriteParsingSimpleWidthHeight) { + FixtureLog log; + + const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); + const auto json_1x = R"JSON({ "image": { "width": 32, "height": 32 } })JSON"; + + const auto images = parseSprite(image_1x, json_1x).get(); + EXPECT_EQ(1u, images.size()); +} + +TEST(Sprite, SpriteParsingWidthTooBig) { + FixtureLog log; + + const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); + const auto json_1x = R"JSON({ "image": { "width": 65536, "height": 32 } })JSON"; + + const auto images = parseSprite(image_1x, json_1x).get(); + EXPECT_EQ(0u, images.size()); + + EXPECT_EQ(1u, log.count({ + EventSeverity::Warning, + Event::Sprite, + int64_t(-1), + "Value of 'width' must be an integer between 0 and 65535", + })); + EXPECT_EQ(1u, log.count({ + EventSeverity::Error, + Event::Sprite, + int64_t(-1), + "Can't create sprite with invalid metrics", + })); +} + +TEST(Sprite, SpriteParsingNegativeWidth) { + FixtureLog log; + + const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); + const auto json_1x = R"JSON({ "image": { "width": -1, "height": 32 } })JSON"; + + const auto images = parseSprite(image_1x, json_1x).get(); + EXPECT_EQ(0u, images.size()); + + EXPECT_EQ(1u, log.count({ + EventSeverity::Warning, + Event::Sprite, + int64_t(-1), + "Value of 'width' must be an integer between 0 and 65535", + })); + EXPECT_EQ(1u, log.count({ + EventSeverity::Error, + Event::Sprite, + int64_t(-1), + "Can't create sprite with invalid metrics", + })); +} + +TEST(Sprite, SpriteParsingNullRatio) { + FixtureLog log; + + const auto image_1x = util::read_file("test/fixtures/annotations/emerald.png"); + const auto json_1x = R"JSON({ "image": { "width": 32, "height": 32, "pixelRatio": 0 } })JSON"; + + const auto images = parseSprite(image_1x, json_1x).get(); + EXPECT_EQ(0u, images.size()); + + EXPECT_EQ(1u, log.count({ + EventSeverity::Error, + Event::Sprite, + int64_t(-1), + "Can't create sprite with invalid metrics", + })); +} -- cgit v1.2.1