diff options
Diffstat (limited to 'test/style/mock_file_source.cpp')
-rw-r--r-- | test/style/mock_file_source.cpp | 129 |
1 files changed, 101 insertions, 28 deletions
diff --git a/test/style/mock_file_source.cpp b/test/style/mock_file_source.cpp index 42067a2a73..0f2d93f71f 100644 --- a/test/style/mock_file_source.cpp +++ b/test/style/mock_file_source.cpp @@ -5,78 +5,151 @@ #include <mbgl/util/io.hpp> #include <mbgl/util/thread.hpp> +#include <algorithm> + +namespace { + +const uint64_t timeout = 1000000; + +} + namespace mbgl { class MockFileSource::Impl { public: - Impl(uv_loop_t*, Type type, const std::string& match) : type_(type), match_(match) {} + Impl(uv_loop_t* loop, Type type, const std::string& match) + : type_(type), match_(match), timer_(loop) { + timer_.start(timeout, timeout, [this] { dispatchPendingRequests(); }); + timer_.unref(); + } - void handleRequest(Request* req) const; + ~Impl() { + timer_.stop(); + } + + void setOnRequestDelayedCallback(std::function<void(void)> callback) { + requestEnqueuedCallback_ = callback; + } + + void handleRequest(Request* req); + void cancelRequest(Request* req); private: - void replyWithFailure(Response* res) const; - void replyWithCorruptedData(Response* res, const std::string& url) const; - void replyWithSuccess(Response* res, const std::string& url) const; + void replyWithSuccess(Request* req) const; + void replyWithSuccessWithDelay(Request* req); + void replyWithFailure(Request* req) const; + void replyWithCorruptedData(Request* req) const; + + void dispatchPendingRequests(); Type type_; std::string match_; -}; + std::vector<Request*> pendingRequests_; + uv::timer timer_; -void MockFileSource::Impl::replyWithFailure(Response* res) const { - res->status = Response::Status::Error; - res->message = "Failed by the test case"; -} + std::function<void(void)> requestEnqueuedCallback_; +}; -void MockFileSource::Impl::replyWithCorruptedData(Response* res, const std::string& url) const { +void MockFileSource::Impl::replyWithSuccess(Request* req) const { + std::shared_ptr<Response> res = std::make_shared<Response>(); res->status = Response::Status::Successful; - res->data = util::read_file(url); - res->data.insert(0, "CORRUPTED"); + res->data = util::read_file(req->resource.url); + + req->notify(res); } -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::replyWithSuccessWithDelay(Request* req) { + if (req->resource.url.find(match_) == std::string::npos) { + replyWithSuccess(req); + return; + } + + pendingRequests_.push_back(req); + requestEnqueuedCallback_(); } -void MockFileSource::Impl::handleRequest(Request* req) const { - const std::string& url = req->resource.url; - std::shared_ptr<Response> response = std::make_shared<Response>(); +void MockFileSource::Impl::replyWithFailure(Request* req) const { + if (req->resource.url.find(match_) == std::string::npos) { + replyWithSuccess(req); + return; + } + + std::shared_ptr<Response> res = std::make_shared<Response>(); + res->status = Response::Status::Error; + res->message = "Failed by the test case"; - if (url.find(match_) == std::string::npos) { - replyWithSuccess(response.get(), url); - req->notify(response); + req->notify(res); +} + +void MockFileSource::Impl::replyWithCorruptedData(Request* req) const { + if (req->resource.url.find(match_) == std::string::npos) { + replyWithSuccess(req); return; } + std::shared_ptr<Response> res = std::make_shared<Response>(); + res->status = Response::Status::Successful; + res->data = util::read_file(req->resource.url); + res->data.insert(0, "CORRUPTED"); + + req->notify(res); +} + +void MockFileSource::Impl::handleRequest(Request* req) { switch (type_) { case Type::Success: - replyWithSuccess(response.get(), url); + replyWithSuccess(req); + break; + case Type::SuccessWithDelay: + replyWithSuccessWithDelay(req); break; case Type::RequestFail: - replyWithFailure(response.get()); + replyWithFailure(req); break; case Type::RequestWithCorruptedData: - replyWithCorruptedData(response.get(), url); + replyWithCorruptedData(req); break; default: EXPECT_TRUE(false) << "Should never be reached."; } +} - req->notify(response); +void MockFileSource::Impl::cancelRequest(Request* req) { + auto it = std::find(pendingRequests_.begin(), pendingRequests_.end(), req); + if (it != pendingRequests_.end()) { + (*it)->destruct(); + pendingRequests_.erase(it); + } else { + EXPECT_TRUE(false) << "Should never be reached."; + } +} + +void MockFileSource::Impl::dispatchPendingRequests() { + for (auto req : pendingRequests_) { + replyWithSuccess(req); + } + + pendingRequests_.clear(); } MockFileSource::MockFileSource(Type type, const std::string& match) : thread_(std::make_unique<util::Thread<Impl>>("FileSource", util::ThreadPriority::Low, type, match)) { } +void MockFileSource::setOnRequestDelayedCallback(std::function<void(void)> callback) { + thread_->invokeSync(&Impl::setOnRequestDelayedCallback, callback); +} + 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); + thread_->invokeSync(&Impl::handleRequest, req); return req; } -void MockFileSource::cancel(Request*) { +void MockFileSource::cancel(Request* req) { + req->cancel(); + thread_->invoke(&Impl::cancelRequest, req); } } |