diff options
author | Thiago Marcos P. Santos <thiago@mapbox.com> | 2015-05-22 13:11:23 +0300 |
---|---|---|
committer | Thiago Marcos P. Santos <thiago@mapbox.com> | 2015-05-28 09:43:56 +0300 |
commit | 379d7830d9a2cb602e41476a1c0809cca84f532c (patch) | |
tree | 7de2bbfe33b7b7faad55347445341434096d5a9e /test | |
parent | f8cc50683ad52cff702fb3b324502c5e792917a0 (diff) | |
download | qtlocation-mapboxgl-379d7830d9a2cb602e41476a1c0809cca84f532c.tar.gz |
Add tests for handling corrupted data
The MockFileSource will insert garbage on the reply and report as
a request done successfully. The network stack cannot detect this
kind of errors but the consumer should report it like we do for
network problems.
Diffstat (limited to 'test')
-rw-r--r-- | test/resources/mock_file_source.cpp | 57 | ||||
-rw-r--r-- | test/resources/mock_file_source.hpp | 10 | ||||
-rw-r--r-- | test/resources/resource_loader.cpp | 63 |
3 files changed, 98 insertions, 32 deletions
diff --git a/test/resources/mock_file_source.cpp b/test/resources/mock_file_source.cpp index 0a9d448d45..42067a2a73 100644 --- a/test/resources/mock_file_source.cpp +++ b/test/resources/mock_file_source.cpp @@ -1,3 +1,4 @@ +#include "../fixtures/util.hpp" #include "mock_file_source.hpp" #include <mbgl/storage/request.hpp> @@ -8,30 +9,64 @@ namespace mbgl { class MockFileSource::Impl { public: - Impl(uv_loop_t*, const std::string& matchFail) : matchFail_(matchFail) {} + Impl(uv_loop_t*, Type type, const std::string& match) : type_(type), match_(match) {} void handleRequest(Request* req) const; private: - std::string matchFail_; + 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::handleRequest(Request* req) const { - const Resource& resource = req->resource; +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 (matchFail_.empty() || resource.url.find(matchFail_) == std::string::npos) { - response->status = Response::Status::Successful; - response->data = util::read_file(resource.url.c_str()); - } else { - response->message = "Failed by the test case"; + + 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(const std::string& matchFail) - : thread_(std::make_unique<util::Thread<Impl>>("FileSource", util::ThreadPriority::Low, matchFail)) { +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) { diff --git a/test/resources/mock_file_source.hpp b/test/resources/mock_file_source.hpp index 55ecd95c13..bb9fb55a30 100644 --- a/test/resources/mock_file_source.hpp +++ b/test/resources/mock_file_source.hpp @@ -13,12 +13,18 @@ template <typename T> class Thread; } // This mock FileSource will read data from the disk and will fail -// the request if the URL matches the 'matchFail' string. +// the request if the URL matches a string. class MockFileSource : public FileSource { public: + enum Type { + Success, + RequestFail, + RequestWithCorruptedData + }; + class Impl; - MockFileSource(const std::string& matchFail); + MockFileSource(Type type, const std::string& match); ~MockFileSource() override = default; // FileSource implementation. diff --git a/test/resources/resource_loader.cpp b/test/resources/resource_loader.cpp index 83807156ed..7d57f47ee6 100644 --- a/test/resources/resource_loader.cpp +++ b/test/resources/resource_loader.cpp @@ -107,18 +107,13 @@ private: std::function<void(std::exception_ptr error)> callback_; }; -} - -class ResourceLoaderTest : public ::testing::TestWithParam<std::string> { -}; - -TEST_P(ResourceLoaderTest, RequestFailure) { +void runTestCase(MockFileSource::Type type, + const std::string& param, + const std::string& message) { util::RunLoop loop(uv_default_loop()); - const std::string param(GetParam()); - MockView view; - MockFileSource fileSource(param); + MockFileSource fileSource(type, param); FixtureLogObserver* log = new FixtureLogObserver(); Log::setObserver(std::unique_ptr<Log::Observer>(log)); @@ -127,9 +122,6 @@ TEST_P(ResourceLoaderTest, RequestFailure) { try { if (error) { std::rethrow_exception(error); - } else { - // Control test, should succeed. - EXPECT_TRUE(param.empty()); } } catch (const util::GlyphRangeLoadingException&) { EXPECT_EQ(param, "glyphs.pbf"); @@ -156,24 +148,57 @@ TEST_P(ResourceLoaderTest, RequestFailure) { // join and cease logging after this point. context.reset(); - std::stringstream message; - message << "Failed to load [test/fixtures/resources/" << param << "]: Failed by the test case"; - const FixtureLogObserver::LogMessage logMessage { EventSeverity::Error, Event::ResourceLoader, int64_t(-1), - message.str(), + message, }; - if (param.empty()) { + if (type == MockFileSource::Success) { EXPECT_EQ(log->count(logMessage), 0u); } else { EXPECT_GT(log->count(logMessage), 0u); } - EXPECT_EQ(log->unchecked().size(), 0u); + // Clear the remaining error messages + log->unchecked().size(); +} + +} + +class ResourceLoaderTest : public ::testing::TestWithParam<std::string> { +}; + +TEST_P(ResourceLoaderTest, Success) { + runTestCase(MockFileSource::Success, GetParam(), std::string()); +} + +TEST_P(ResourceLoaderTest, 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(ResourceLoaderTest, 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(ResourceLoader, ResourceLoaderTest, - ::testing::Values("", "source.json", "sprite.json", "sprite.png", "vector.pbf", "glyphs.pbf")); + ::testing::Values("source.json", "sprite.json", "sprite.png", "vector.pbf", "glyphs.pbf")); |