summaryrefslogtreecommitdiff
path: root/test/storage/http_coalescing.cpp
blob: ab776eebfbcb982d731d92210744106f904c03fa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include "storage.hpp"

#include <uv.h>

#include <mbgl/storage/default_file_source.hpp>

TEST_F(Storage, HTTPCoalescing) {
    SCOPED_TEST(HTTPCoalescing)

    static int counter = 0;
    const static int total = 4;

    using namespace mbgl;

    DefaultFileSource fs(nullptr);

    static const Response *reference = nullptr;

    const auto complete = [&](const Response &res) {
        counter++;

        // Make sure all of the Response objects are the same.
        if (!reference) {
            reference = &res;
        } else {
            EXPECT_EQ(&res, reference);
        }

        EXPECT_EQ(nullptr, res.error);
        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);

        if (counter >= total) {
            HTTPCoalescing.finish();
        }
    };

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

    Request* reqs[total];
    for (int i = 0; i < total; i++) {
        reqs[i] = fs.request(resource, uv_default_loop(), [&complete, &fs, &reqs, i] (const Response &res) {
            fs.cancel(reqs[i]);
            complete(res);
        });
    }

    uv_run(uv_default_loop(), UV_RUN_DEFAULT);
}

TEST_F(Storage, HTTPMultiple) {
    SCOPED_TEST(HTTPMultiple)

    using namespace mbgl;

    DefaultFileSource fs(nullptr);

    const Response *reference = nullptr;

    const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/test?expires=2147483647" };
    Request* req1 = nullptr;
    Request* req2 = nullptr;
    req1 = fs.request(resource, uv_default_loop(), [&] (const Response &res) {
        EXPECT_EQ(nullptr, reference);
        reference = &res;

        // Do not cancel the request right away.
        EXPECT_EQ(nullptr, res.error);
        ASSERT_TRUE(res.data.get());
        EXPECT_EQ("Hello World!", *res.data);
        EXPECT_EQ(2147483647, res.expires);
        EXPECT_EQ(0, res.modified);
        EXPECT_EQ("", res.etag);

        // Start a second request for the same resource after the first one has been completed.
        req2 = fs.request(resource, uv_default_loop(), [&] (const Response &res2) {
            // Make sure we get the same object ID as before.
            EXPECT_EQ(reference, &res2);

            // Now cancel both requests after both have been notified.
            fs.cancel(req1);
            fs.cancel(req2);

            EXPECT_EQ(nullptr, res2.error);
            ASSERT_TRUE(res2.data.get());
            EXPECT_EQ("Hello World!", *res2.data);
            EXPECT_EQ(2147483647, res2.expires);
            EXPECT_EQ(0, res2.modified);
            EXPECT_EQ("", res2.etag);

            HTTPMultiple.finish();
        });
    });

    uv_run(uv_default_loop(), UV_RUN_DEFAULT);
}

// Tests that we get stale responses from previous requests when requesting the same thing again.
TEST_F(Storage, HTTPStale) {
    SCOPED_TEST(HTTPStale)

    using namespace mbgl;

    DefaultFileSource fs(nullptr);

    int updates = 0;
    int stale = 0;

    const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/test" };
    Request* req1 = nullptr;
    Request* req2 = nullptr;
    req1 = fs.request(resource, uv_default_loop(), [&] (const Response &res) {
        // Do not cancel the request right away.
        EXPECT_EQ(nullptr, res.error);
        ASSERT_TRUE(res.data.get());
        EXPECT_EQ("Hello World!", *res.data);
        EXPECT_EQ(false, res.stale);
        EXPECT_EQ(0, res.expires);
        EXPECT_EQ(0, res.modified);
        EXPECT_EQ("", res.etag);

        // Don't start the request twice in case this callback gets fired multiple times.
        if (req2) {
            return;
        }

        updates++;

        // Start a second request for the same resource after the first one has been completed.
        req2 = fs.request(resource, uv_default_loop(), [&] (const Response &res2) {
            EXPECT_EQ(nullptr, res2.error);
            ASSERT_TRUE(res2.data.get());
            EXPECT_EQ("Hello World!", *res2.data);
            EXPECT_EQ(0, res2.expires);
            EXPECT_EQ(0, res2.modified);
            EXPECT_EQ("", res2.etag);

            if (res2.stale) {
                EXPECT_EQ(0, stale);
                stale++;
            } else {
                // Now cancel both requests after both have been notified.
                fs.cancel(req1);
                fs.cancel(req2);
                HTTPStale.finish();
            }
        });
    });

    uv_run(uv_default_loop(), UV_RUN_DEFAULT);

    EXPECT_EQ(1, stale);
    EXPECT_EQ(1, updates);
}