req1 = fs.request(revalidateSame, uv_default_loop(), [&](const Response &res) {
        // This callback can get triggered multiple times. We only care about the first invocation.
        // It will get triggered again when refreshing the req2 (see below).
        static bool first = true;
        if (!first) {
            return;
        }
        first = false;

        EXPECT_EQ(Response::Successful, res.status);
        EXPECT_EQ(false, res.stale);
        ASSERT_TRUE(res.data.get());
        EXPECT_EQ("Response", *res.data);
        EXPECT_EQ(0, res.expires);
        EXPECT_EQ(0, res.modified);
        EXPECT_EQ("snowfall", res.etag);
        EXPECT_EQ("", res.message);

        req2 = fs.request(revalidateSame, uv_default_loop(), [&, res](const Response &res2) {
            if (res2.stale) {
                // Discard stale responses, if any.
                return;
            }

            ASSERT_TRUE(req1);
            fs.cancel(req1);
            req1 = nullptr;

            ASSERT_TRUE(req2);
            fs.cancel(req2);
            req2 = nullptr;

            EXPECT_EQ(Response::Successful, res2.status);
            EXPECT_EQ(false, res.stale);
            ASSERT_TRUE(res2.data.get());
            EXPECT_EQ(res.data, res2.data);
            EXPECT_EQ("Response", *res2.data);
            // We use this to indicate that a 304 reply came back.
            EXPECT_LT(0, res2.expires);
            EXPECT_EQ(0, res2.modified);
            // We're not sending the ETag in the 304 reply, but it should still be there.
            EXPECT_EQ("snowfall", res2.etag);
            EXPECT_EQ("", res2.message);

            CacheRevalidateSame.finish();
        });
    });
TEST_F(Storage, HTTPExpiresParsing) {
    SCOPED_TEST(HTTPExpiresTest)

    using namespace mbgl;

    DefaultFileSource fs(nullptr);
    util::RunLoop loop(uv_default_loop());

    std::unique_ptr<FileRequest> req1 = fs.request({ Resource::Unknown,
                 "http://127.0.0.1:3000/test?modified=1420794326&expires=1420797926&etag=foo" },
               [&](Response res) {
        req1.reset();
        EXPECT_EQ(nullptr, res.error);
        EXPECT_EQ(false, res.stale);
        ASSERT_TRUE(res.data.get());
        EXPECT_EQ("Hello World!", *res.data);
        EXPECT_EQ(1420797926, res.expires.count());
        EXPECT_EQ(1420794326, res.modified.count());
        EXPECT_EQ("foo", res.etag);
        loop.stop();
        HTTPExpiresTest.finish();
    });

    uv_run(uv_default_loop(), UV_RUN_DEFAULT);
}

TEST_F(Storage, HTTPCacheControlParsing) {
    SCOPED_TEST(HTTPCacheControlTest)

    using namespace mbgl;
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/util/chrono.hpp>
#include <mbgl/util/run_loop.hpp>

TEST_F(Storage, HTTPOtherLoop) {
    SCOPED_TEST(HTTPOtherLoop)

    using namespace mbgl;

    // This file source launches a separate thread to do the processing.
    util::RunLoop loop;
    DefaultFileSource fs(nullptr);

    std::unique_ptr<FileRequest> req = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/test" },
               [&](Response res) {
        req.reset();
        EXPECT_EQ(nullptr, res.error);
        EXPECT_EQ(false, res.stale);
        ASSERT_TRUE(res.data.get());
        EXPECT_EQ("Hello World!", *res.data);
        EXPECT_EQ(Seconds::zero(), res.expires);
        EXPECT_EQ(Seconds::zero(), res.modified);
        EXPECT_EQ("", res.etag);
        loop.stop();
        HTTPOtherLoop.finish();
    });

    loop.run();
}
    SCOPED_TEST(HTTPNetworkStatusChange)

    using namespace mbgl;

    util::RunLoop loop;
    DefaultFileSource fs(nullptr);

    const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/delayed" };

    // This request takes 200 milliseconds to answer.
    std::unique_ptr<FileRequest> req = fs.request(resource, [&](Response res) {
         req.reset();
         EXPECT_EQ(nullptr, res.error);
         EXPECT_EQ(false, res.stale);
         ASSERT_TRUE(res.data.get());
         EXPECT_EQ("Response", *res.data);
         EXPECT_EQ(Seconds::zero(), res.expires);
         EXPECT_EQ(Seconds::zero(), res.modified);
         EXPECT_EQ("", res.etag);
         loop.stop();
         HTTPNetworkStatusChange.finish();
    });

    // After 50 milliseconds, we're going to trigger a NetworkStatus change.
    util::Timer reachableTimer;
    reachableTimer.start(std::chrono::milliseconds(50), Duration::zero(), [] () {
        mbgl::NetworkStatus::Reachable();
    });

    // This timer will keep the loop alive to make sure we would be getting a response in caes the
    // network status change triggered another change (which it shouldn't).
    util::Timer delayTimer;
    const Resource revalidateSame { Resource::Unknown, "http://127.0.0.1:3000/revalidate-same" };
    fs.request(revalidateSame, uv_default_loop(), env, [&](const Response &res) {
        EXPECT_EQ(Response::Successful, res.status);
        EXPECT_EQ("Response", res.data);
        EXPECT_EQ(0, res.expires);
        EXPECT_EQ(0, res.modified);
        EXPECT_EQ("snowfall", res.etag);
        EXPECT_EQ("", res.message);

        fs.request(revalidateSame, uv_default_loop(), env, [&, res](const Response &res2) {
            EXPECT_EQ(Response::Successful, res2.status);
            EXPECT_EQ("Response", res2.data);
            // We use this to indicate that a 304 reply came back.
            EXPECT_LT(0, res2.expires);
            EXPECT_EQ(0, res2.modified);
            // We're not sending the ETag in the 304 reply, but it should still be there.
            EXPECT_EQ("snowfall", res2.etag);
            EXPECT_EQ("", res2.message);

            CacheRevalidateSame.finish();
        });
    });

    const Resource revalidateModified{ Resource::Unknown,
                                       "http://127.0.0.1:3000/revalidate-modified" };
    fs.request(revalidateModified, uv_default_loop(), env, [&](const Response &res) {
        EXPECT_EQ(Response::Successful, res.status);
        EXPECT_EQ("Response", res.data);
        EXPECT_EQ(0, res.expires);
        EXPECT_EQ(1420070400, res.modified);
        EXPECT_EQ("", res.etag);
Esempio n. 6
0
    int number = 1;

    std::unique_ptr<FileRequest> reqs[concurrency];

    std::function<void(int)> req = [&](int i) {
        const auto current = number++;
        reqs[i] = fs.request({ Resource::Unknown,
                     std::string("http://127.0.0.1:3000/load/") + std::to_string(current) },
                   [&, i, current](Response res) {
            reqs[i].reset();
            EXPECT_EQ(nullptr, res.error);
            EXPECT_EQ(false, res.stale);
            ASSERT_TRUE(res.data.get());
            EXPECT_EQ(std::string("Request ") +  std::to_string(current), *res.data);
            EXPECT_EQ(0, res.expires);
            EXPECT_EQ(0, res.modified);
            EXPECT_EQ("", res.etag);

            if (number <= max) {
                req(i);
            } else if (current == max) {
                loop.stop();
                HTTPLoad.finish();
            }
        });
    };


    for (int i = 0; i < concurrency; i++) {
        req(i);
    }
Esempio n. 7
0
#include <uv.h>

#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/storage/network_status.hpp>

#include <cmath>

TEST_F(Storage, HTTPCancel) {
    SCOPED_TEST(HTTPCancel)

    using namespace mbgl;

    DefaultFileSource fs(nullptr);

    auto req =
        fs.request({ Resource::Unknown, "http://127.0.0.1:3000/test" }, uv_default_loop(),
                   [&](const Response &) { ADD_FAILURE() << "Callback should not be called"; });

    fs.cancel(req);
    HTTPCancel.finish();

    uv_run(uv_default_loop(), UV_RUN_DEFAULT);
}

TEST_F(Storage, HTTPCancelMultiple) {
    SCOPED_TEST(HTTPCancelMultiple)

    using namespace mbgl;

    DefaultFileSource fs(nullptr);

    const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/test" };
#include "storage.hpp"

#include <uv.h>

#include <mbgl/storage/default_file_source.hpp>

TEST_F(Storage, HTTPOtherLoop) {
    SCOPED_TEST(HTTPOtherLoop)

    using namespace mbgl;

    // This file source launches a separate thread to do the processing.
    DefaultFileSource fs(nullptr);

    Request* req = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/test" }, uv_default_loop(),
               [&](const Response &res) {
        fs.cancel(req);
        EXPECT_EQ(Response::Successful, res.status);
        EXPECT_EQ(false, res.stale);
        ASSERT_TRUE(res.data.get());
        EXPECT_EQ("Hello World!", *res.data);
        EXPECT_EQ(0, res.expires);
        EXPECT_EQ(0, res.modified);
        EXPECT_EQ("", res.etag);
        EXPECT_EQ("", res.message);
        HTTPOtherLoop.finish();
    });

    uv_run(uv_default_loop(), UV_RUN_DEFAULT);
}
TEST_F(Storage, HTTPNetworkStatusChange) {
    SCOPED_TEST(HTTPNetworkStatusChange)

    using namespace mbgl;

    DefaultFileSource fs(nullptr);

    const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/delayed" };

    // This request takes 200 milliseconds to answer.
    Request* req = fs.request(resource, uv_default_loop(), [&](const Response& res) {
         fs.cancel(req);
         EXPECT_EQ(nullptr, res.error);
         EXPECT_EQ(false, res.stale);
         ASSERT_TRUE(res.data.get());
         EXPECT_EQ("Response", *res.data);
         EXPECT_EQ(0, res.expires);
         EXPECT_EQ(0, res.modified);
         EXPECT_EQ("", res.etag);
         HTTPNetworkStatusChange.finish();
    });

    // After 50 milliseconds, we're going to trigger a NetworkStatus change.
    uv::timer reachableTimer(uv_default_loop());
    reachableTimer.start(50, 0, [] () {
        mbgl::NetworkStatus::Reachable();
    });

    // This timer will keep the loop alive to make sure we would be getting a response in caes the
    // network status change triggered another change (which it shouldn't).
    uv::timer delayTimer(uv_default_loop());
// will notify as expected, the second one will have bound a DefaultFileRequest* in the lambda that
// gets invalidated by the first notify's pending.erase, and when it gets notified, the crash
// occurs.

TEST_F(Storage, HTTPIssue1369) {
    SCOPED_TEST(HTTPIssue1369)

    using namespace mbgl;

    SQLiteCache cache;
    DefaultFileSource fs(&cache);

    const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/test" };

    auto req = fs.request(resource, uv_default_loop(), [&](const Response&) {
        ADD_FAILURE() << "Callback should not be called";
    });
    fs.cancel(req);
    fs.request(resource, uv_default_loop(), [&](const Response &res) {
        EXPECT_EQ(Response::Successful, res.status);
        EXPECT_EQ("Hello World!", res.data);
        EXPECT_EQ(0, res.expires);
        EXPECT_EQ(0, res.modified);
        EXPECT_EQ("", res.etag);
        EXPECT_EQ("", res.message);
        HTTPIssue1369.finish();
    });

    uv_run(uv_default_loop(), UV_RUN_DEFAULT);
}