void MockFileSource::Impl::dispatchPendingRequests() {
    for (auto& pair : pendingRequests_) {
        replyWithSuccess(pair.second.first, pair.second.second);
    }

    pendingRequests_.clear();
}
void MockFileSource::Impl::dispatchPendingRequests() {
    for (auto req : pendingRequests_) {
        replyWithSuccess(req);
    }

    pendingRequests_.clear();
}
void MockFileSource::Impl::replyWithSuccessWithDelay(FileRequest* req, Resource resource, Callback callback) {
    if (resource.url.find(match_) == std::string::npos) {
        replyWithSuccess(resource, callback);
        return;
    }

    pendingRequests_.emplace(req, std::make_pair(resource, callback));
    requestEnqueuedCallback_();
}
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::replyWithFailure(Resource resource, Callback callback) const {
    if (resource.url.find(match_) == std::string::npos) {
        replyWithSuccess(resource, callback);
        return;
    }

    Response res;
    res.error = std::make_unique<Response::Error>(Response::Error::Reason::Other, "Failed by the test case");
    callback(res);
}
void MockFileSource::Impl::replyWithCorruptedData(Resource resource, Callback callback) const {
    if (resource.url.find(match_) == std::string::npos) {
        replyWithSuccess(resource, callback);
        return;
    }

    Response res;
    auto data = std::make_shared<std::string>(std::move(util::read_file(resource.url)));
    data->insert(0, "CORRUPTED");
    res.data = std::move(data);
    callback(res);
}
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";

    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(FileRequest* req, Resource resource, Callback callback) {
    switch (type_) {
    case Type::Success:
        replyWithSuccess(resource, callback);
        break;
    case Type::SuccessWithDelay:
        replyWithSuccessWithDelay(req, resource, callback);
        break;
    case Type::RequestFail:
        replyWithFailure(resource, callback);
        break;
    case Type::RequestWithCorruptedData:
        replyWithCorruptedData(resource, callback);
        break;
    default:
        EXPECT_TRUE(false) << "Should never be reached.";
    }
}