diff options
author | Thiago Marcos P. Santos <thiago@mapbox.com> | 2015-06-02 17:53:42 +0300 |
---|---|---|
committer | Thiago Marcos P. Santos <thiago@mapbox.com> | 2015-06-02 20:43:00 +0300 |
commit | 5c4c6648d1bbc66b38d702cc28e8bac8c5485247 (patch) | |
tree | 09eea6ff101fcd109f42963b81866a2c7c506637 /test/style | |
parent | 68989e671cba847ba65f3d6afd4327b4677be1f3 (diff) | |
download | qtlocation-mapboxgl-5c4c6648d1bbc66b38d702cc28e8bac8c5485247.tar.gz |
Rebase the resource loading tests
Update the ResourceLoader tests to reflect the changes
after we merged ResourceLoader with Style.
Diffstat (limited to 'test/style')
-rw-r--r-- | test/style/mock_file_source.cpp | 82 | ||||
-rw-r--r-- | test/style/mock_file_source.hpp | 40 | ||||
-rw-r--r-- | test/style/mock_view.hpp | 21 | ||||
-rw-r--r-- | test/style/resource_loading.cpp | 184 |
4 files changed, 327 insertions, 0 deletions
diff --git a/test/style/mock_file_source.cpp b/test/style/mock_file_source.cpp new file mode 100644 index 0000000000..42067a2a73 --- /dev/null +++ b/test/style/mock_file_source.cpp @@ -0,0 +1,82 @@ +#include "../fixtures/util.hpp" +#include "mock_file_source.hpp" + +#include <mbgl/storage/request.hpp> +#include <mbgl/util/io.hpp> +#include <mbgl/util/thread.hpp> + +namespace mbgl { + +class MockFileSource::Impl { +public: + Impl(uv_loop_t*, Type type, const std::string& match) : type_(type), match_(match) {} + + void handleRequest(Request* req) const; + +private: + void replyWithFailure(Response* res) const; + void replyWithCorruptedData(Response* res, const std::string& url) const; + void replyWithSuccess(Response* res, const std::string& url) const; + + Type type_; + std::string match_; +}; + +void MockFileSource::Impl::replyWithFailure(Response* res) const { + res->status = Response::Status::Error; + res->message = "Failed by the test case"; +} + +void MockFileSource::Impl::replyWithCorruptedData(Response* res, const std::string& url) const { + res->status = Response::Status::Successful; + res->data = util::read_file(url); + res->data.insert(0, "CORRUPTED"); +} + +void MockFileSource::Impl::replyWithSuccess(Response* res, const std::string& url) const { + res->status = Response::Status::Successful; + res->data = util::read_file(url); +} + +void MockFileSource::Impl::handleRequest(Request* req) const { + const std::string& url = req->resource.url; + std::shared_ptr<Response> response = std::make_shared<Response>(); + + if (url.find(match_) == std::string::npos) { + replyWithSuccess(response.get(), url); + req->notify(response); + return; + } + + switch (type_) { + case Type::Success: + replyWithSuccess(response.get(), url); + break; + case Type::RequestFail: + replyWithFailure(response.get()); + break; + case Type::RequestWithCorruptedData: + replyWithCorruptedData(response.get(), url); + break; + default: + EXPECT_TRUE(false) << "Should never be reached."; + } + + req->notify(response); +} + +MockFileSource::MockFileSource(Type type, const std::string& match) + : thread_(std::make_unique<util::Thread<Impl>>("FileSource", util::ThreadPriority::Low, type, match)) { +} + +Request* MockFileSource::request(const Resource& resource, uv_loop_t* loop, Callback callback) { + Request* req = new Request(resource, loop, std::move(callback)); + thread_->invoke(&Impl::handleRequest, req); + + return req; +} + +void MockFileSource::cancel(Request*) { +} + +} diff --git a/test/style/mock_file_source.hpp b/test/style/mock_file_source.hpp new file mode 100644 index 0000000000..bb9fb55a30 --- /dev/null +++ b/test/style/mock_file_source.hpp @@ -0,0 +1,40 @@ +#ifndef TEST_RESOURCES_MOCK_FILE_SOURCE +#define TEST_RESOURCES_MOCK_FILE_SOURCE + +#include <mbgl/storage/file_source.hpp> + +#include <string> +#include <memory> + +namespace mbgl { + +namespace util { +template <typename T> class Thread; +} + +// This mock FileSource will read data from the disk and will fail +// the request if the URL matches a string. +class MockFileSource : public FileSource { +public: + enum Type { + Success, + RequestFail, + RequestWithCorruptedData + }; + + class Impl; + + MockFileSource(Type type, const std::string& match); + ~MockFileSource() override = default; + + // FileSource implementation. + Request* request(const Resource&, uv_loop_t*, Callback) override; + void cancel(Request*) override; + +private: + const std::unique_ptr<util::Thread<Impl>> thread_; +}; + +} + +#endif diff --git a/test/style/mock_view.hpp b/test/style/mock_view.hpp new file mode 100644 index 0000000000..865cd2da55 --- /dev/null +++ b/test/style/mock_view.hpp @@ -0,0 +1,21 @@ +#ifndef TEST_RESOURCES_MOCK_VIEW +#define TEST_RESOURCES_MOCK_VIEW + +#include <mbgl/map/view.hpp> + +namespace mbgl { + +class MockView : public View { +public: + MockView() = default; + + // View implementation. + void activate() override {}; + void deactivate() override {}; + void notify() override {}; + void invalidate(std::function<void()>) override {}; +}; + +} + +#endif diff --git a/test/style/resource_loading.cpp b/test/style/resource_loading.cpp new file mode 100644 index 0000000000..5f7195d9b6 --- /dev/null +++ b/test/style/resource_loading.cpp @@ -0,0 +1,184 @@ +#include "../fixtures/fixture_log_observer.hpp" +#include "../fixtures/util.hpp" +#include "mock_file_source.hpp" +#include "mock_view.hpp" + +#include <mbgl/map/environment.hpp> +#include <mbgl/map/map_data.hpp> +#include <mbgl/map/transform_state.hpp> +#include <mbgl/style/style.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> + +using namespace mbgl; + +namespace { + +class MockMapContext : public Style::Observer { +public: + MockMapContext(uv_loop_t* loop, + View& view, + FileSource& fileSource, + const std::function<void(std::exception_ptr error)>& callback) + : env_(fileSource), + envScope_(env_, ThreadType::Map, "Map"), + data_(view, MapMode::Still), + asyncUpdate(std::make_unique<uv::async>(loop, [this] { update(); })), + callback_(callback) { + asyncUpdate->unref(); + + data_.transform.resize(1000, 1000, 1.0, 1000, 1000); + data_.transform.setLatLngZoom({0, 0}, 16); + + const std::string style = util::read_file("test/fixtures/resources/style.json"); + style_ = std::make_unique<Style>(style, "", loop, env_), + style_->setObserver(this); + } + + ~MockMapContext() { + style_.reset(); + env_.performCleanup(); + } + + void update() { + const auto now = Clock::now(); + + data_.setAnimationTime(now); + data_.transform.updateTransitions(now); + + transformState_ = data_.transform.currentState(); + style_->update(data_, transformState_, texturePool_); + } + + // Style::Observer implementation. + void onTileDataChanged() override { + if (style_->isLoaded()) { + callback_(nullptr); + } + + asyncUpdate->send(); + }; + + void onResourceLoadingFailed(std::exception_ptr error) override { + callback_(error); + } + +private: + Environment env_; + EnvironmentScope envScope_; + + MapData data_; + TransformState transformState_; + TexturePool texturePool_; + + std::unique_ptr<Style> style_; + + std::unique_ptr<uv::async> asyncUpdate; + + std::function<void(std::exception_ptr error)> callback_; +}; + +void runTestCase(MockFileSource::Type type, + const std::string& param, + const std::string& message) { + util::RunLoop loop(uv_default_loop()); + + MockView view; + MockFileSource fileSource(type, param); + + FixtureLogObserver* log = new FixtureLogObserver(); + Log::setObserver(std::unique_ptr<Log::Observer>(log)); + + auto callback = [type, &loop, ¶m](std::exception_ptr error) { + if (type == MockFileSource::Success) { + EXPECT_TRUE(error == nullptr); + } else { + EXPECT_TRUE(error != nullptr); + } + + try { + if (error) { + std::rethrow_exception(error); + } + } catch (const util::GlyphRangeLoadingException&) { + EXPECT_EQ(param, "glyphs.pbf"); + } catch (const util::SourceLoadingException&) { + EXPECT_EQ(param, "source.json"); + } catch (const util::SpriteLoadingException&) { + EXPECT_TRUE(param == "sprite.png" || param == "sprite.json"); + } catch (const util::TileLoadingException&) { + EXPECT_EQ(param, "vector.pbf"); + } catch (const std::exception&) { + EXPECT_TRUE(false) << "Unhandled exception."; + } + + loop.stop(); + }; + + std::unique_ptr<util::Thread<MockMapContext>> context( + std::make_unique<util::Thread<MockMapContext>>( + "Map", util::ThreadPriority::Regular, view, fileSource, callback)); + + uv_run(loop.get(), UV_RUN_DEFAULT); + + // Needed because it will make the Map thread + // join and cease logging after this point. + context.reset(); + + const FixtureLogObserver::LogMessage logMessage { + EventSeverity::Error, + Event::Style, + int64_t(-1), + message, + }; + + if (type == MockFileSource::Success) { + EXPECT_EQ(log->count(logMessage), 0u); + } else { + EXPECT_GT(log->count(logMessage), 0u); + } + + // Clear the remaining error messages + log->unchecked().size(); +} + +} + +class ResourceLoading : public ::testing::TestWithParam<std::string> { +}; + +TEST_P(ResourceLoading, Success) { + runTestCase(MockFileSource::Success, GetParam(), std::string()); +} + +TEST_P(ResourceLoading, RequestFail) { + std::stringstream message; + message << "Failed to load [test/fixtures/resources/" << GetParam() << "]: Failed by the test case"; + + runTestCase(MockFileSource::RequestFail, GetParam(), message.str()); +} + +TEST_P(ResourceLoading, RequestWithCorruptedData) { + const std::string param(GetParam()); + + std::stringstream message; + message << "Failed to parse "; + + if (param == "vector.pbf") { + message << "[15/16384/16384]: pbf unknown field type exception"; + } else { + message << "[test/fixtures/resources/" << param << "]"; + } + + if (param.find("json") != std::string::npos) { + message << ": 0 - Expect either an object or array at root"; + } + + runTestCase(MockFileSource::RequestWithCorruptedData, GetParam(), message.str()); +} + +INSTANTIATE_TEST_CASE_P(Style, ResourceLoading, + ::testing::Values("source.json", "sprite.json", "sprite.png", "vector.pbf", "glyphs.pbf")); |