summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2015-10-15 21:30:21 +0200
committerKonstantin Käfer <mail@kkaefer.com>2015-10-26 15:54:27 +0100
commit6a7334b882a47ca193209f2012843e42aa3ed4e2 (patch)
treef74bf484c4c53efaa657f524f8c8b01211e15b20 /test
parent096a3edf39d23fbd4baa134938c16fed4f2e199c (diff)
downloadqtlocation-mapboxgl-6a7334b882a47ca193209f2012843e42aa3ed4e2.tar.gz
[core] add support for stale responses
We're now returning stale responses from cache. Those responses will have the `stale` flag set to true. Currently, all requesters in the core code discard stale responses, and cancel the request immediately after they got a non-stale response.
Diffstat (limited to 'test')
-rw-r--r--test/storage/cache_response.cpp30
-rw-r--r--test/storage/cache_revalidate.cpp139
-rw-r--r--test/storage/directory_reading.cpp1
-rw-r--r--test/storage/file_reading.cpp3
-rw-r--r--test/storage/http_cancel.cpp1
-rw-r--r--test/storage/http_coalescing.cpp105
-rw-r--r--test/storage/http_error.cpp2
-rw-r--r--test/storage/http_header_parsing.cpp2
-rw-r--r--test/storage/http_issue_1369.cpp1
-rw-r--r--test/storage/http_load.cpp1
-rw-r--r--test/storage/http_other_loop.cpp1
-rw-r--r--test/storage/http_reading.cpp3
12 files changed, 265 insertions, 24 deletions
diff --git a/test/storage/cache_response.cpp b/test/storage/cache_response.cpp
index 0fba2ba5e7..1294513858 100644
--- a/test/storage/cache_response.cpp
+++ b/test/storage/cache_response.cpp
@@ -14,27 +14,35 @@ TEST_F(Storage, CacheResponse) {
DefaultFileSource fs(&cache);
const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/cache" };
+ Response response;
Request* req = fs.request(resource, uv_default_loop(), [&](const Response &res) {
fs.cancel(req);
EXPECT_EQ(Response::Successful, res.status);
+ EXPECT_EQ(false, res.stale);
EXPECT_EQ("Response 1", res.data);
EXPECT_LT(0, res.expires);
EXPECT_EQ(0, res.modified);
EXPECT_EQ("", res.etag);
EXPECT_EQ("", res.message);
+ response = res;
+ });
+
+ uv_run(uv_default_loop(), UV_RUN_DEFAULT);
- req = fs.request(resource, uv_default_loop(), [&, res](const Response &res2) {
- fs.cancel(req);
- EXPECT_EQ(res.status, res2.status);
- EXPECT_EQ(res.data, res2.data);
- EXPECT_EQ(res.expires, res2.expires);
- EXPECT_EQ(res.modified, res2.modified);
- EXPECT_EQ(res.etag, res2.etag);
- EXPECT_EQ(res.message, res2.message);
-
- CacheResponse.finish();
- });
+ // Now test that we get the same values as in the previous request. If we'd go to the server
+ // again, we'd get different values.
+ req = fs.request(resource, uv_default_loop(), [&](const Response &res) {
+ fs.cancel(req);
+ EXPECT_EQ(response.status, res.status);
+ EXPECT_EQ(response.stale, res.stale);
+ EXPECT_EQ(response.data, res.data);
+ EXPECT_EQ(response.expires, res.expires);
+ EXPECT_EQ(response.modified, res.modified);
+ EXPECT_EQ(response.etag, res.etag);
+ EXPECT_EQ(response.message, res.message);
+
+ CacheResponse.finish();
});
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
diff --git a/test/storage/cache_revalidate.cpp b/test/storage/cache_revalidate.cpp
index 8ebedef01b..90633b83ac 100644
--- a/test/storage/cache_revalidate.cpp
+++ b/test/storage/cache_revalidate.cpp
@@ -5,29 +5,58 @@
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/storage/sqlite_cache.hpp>
-TEST_F(Storage, CacheRevalidate) {
+TEST_F(Storage, CacheRevalidateSame) {
SCOPED_TEST(CacheRevalidateSame)
- SCOPED_TEST(CacheRevalidateModified)
- SCOPED_TEST(CacheRevalidateEtag)
using namespace mbgl;
SQLiteCache cache(":memory:");
DefaultFileSource fs(&cache);
+ const Response *reference = nullptr;
+
const Resource revalidateSame { Resource::Unknown, "http://127.0.0.1:3000/revalidate-same" };
- Request* req = fs.request(revalidateSame, uv_default_loop(), [&](const Response &res) {
- fs.cancel(req);
+ Request* req1 = nullptr;
+ Request* req2 = nullptr;
+ 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(nullptr, reference);
+ reference = &res;
+
EXPECT_EQ(Response::Successful, res.status);
+ EXPECT_EQ(false, res.stale);
EXPECT_EQ("Response", res.data);
EXPECT_EQ(0, res.expires);
EXPECT_EQ(0, res.modified);
EXPECT_EQ("snowfall", res.etag);
EXPECT_EQ("", res.message);
- req = fs.request(revalidateSame, uv_default_loop(), [&, res](const Response &res2) {
- fs.cancel(req);
+ req2 = fs.request(revalidateSame, uv_default_loop(), [&, res](const Response &res2) {
+ // Make sure we get a different object than before, since this request should've been revalidated.
+ EXPECT_TRUE(reference != &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);
EXPECT_EQ("Response", res2.data);
// We use this to indicate that a 304 reply came back.
EXPECT_LT(0, res2.expires);
@@ -40,11 +69,37 @@ TEST_F(Storage, CacheRevalidate) {
});
});
+ uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+}
+
+TEST_F(Storage, CacheRevalidateModified) {
+ SCOPED_TEST(CacheRevalidateModified)
+
+ using namespace mbgl;
+
+ SQLiteCache cache(":memory:");
+ DefaultFileSource fs(&cache);
+
+ const Response *reference = nullptr;
+
const Resource revalidateModified{ Resource::Unknown,
"http://127.0.0.1:3000/revalidate-modified" };
- Request* req2 = fs.request(revalidateModified, uv_default_loop(), [&](const Response &res) {
- fs.cancel(req2);
+ Request* req1 = nullptr;
+ Request* req2 = nullptr;
+ req1 = fs.request(revalidateModified, 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(nullptr, reference);
+ reference = &res;
+
EXPECT_EQ(Response::Successful, res.status);
+ EXPECT_EQ(false, res.stale);
EXPECT_EQ("Response", res.data);
EXPECT_EQ(0, res.expires);
EXPECT_EQ(1420070400, res.modified);
@@ -52,8 +107,24 @@ TEST_F(Storage, CacheRevalidate) {
EXPECT_EQ("", res.message);
req2 = fs.request(revalidateModified, uv_default_loop(), [&, res](const Response &res2) {
+ // Make sure we get a different object than before, since this request should've been revalidated.
+ EXPECT_TRUE(reference != &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);
EXPECT_EQ("Response", res2.data);
// We use this to indicate that a 304 reply came back.
EXPECT_LT(0, res2.expires);
@@ -65,19 +136,61 @@ TEST_F(Storage, CacheRevalidate) {
});
});
+ uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+}
+
+TEST_F(Storage, CacheRevalidateEtag) {
+ SCOPED_TEST(CacheRevalidateEtag)
+
+ using namespace mbgl;
+
+ SQLiteCache cache(":memory:");
+ DefaultFileSource fs(&cache);
+
+ const Response *reference = nullptr;
+
const Resource revalidateEtag { Resource::Unknown, "http://127.0.0.1:3000/revalidate-etag" };
- Request* req3 = fs.request(revalidateEtag, uv_default_loop(), [&](const Response &res) {
- fs.cancel(req3);
+ Request* req1 = nullptr;
+ Request* req2 = nullptr;
+ req1 = fs.request(revalidateEtag, 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(nullptr, reference);
+ reference = &res;
+
EXPECT_EQ(Response::Successful, res.status);
+ EXPECT_EQ(false, res.stale);
EXPECT_EQ("Response 1", res.data);
EXPECT_EQ(0, res.expires);
EXPECT_EQ(0, res.modified);
EXPECT_EQ("response-1", res.etag);
EXPECT_EQ("", res.message);
- req3 = fs.request(revalidateEtag, uv_default_loop(), [&, res](const Response &res2) {
- fs.cancel(req3);
+ req2 = fs.request(revalidateEtag, uv_default_loop(), [&, res](const Response &res2) {
+ // Make sure we get a different object than before, since this request should've been revalidated.
+ EXPECT_TRUE(reference != &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);
EXPECT_EQ("Response 2", res2.data);
EXPECT_EQ(0, res2.expires);
EXPECT_EQ(0, res2.modified);
diff --git a/test/storage/directory_reading.cpp b/test/storage/directory_reading.cpp
index 11298dff8b..f0bc7ea6d2 100644
--- a/test/storage/directory_reading.cpp
+++ b/test/storage/directory_reading.cpp
@@ -19,6 +19,7 @@ TEST_F(Storage, AssetReadDirectory) {
[&](const Response &res) {
fs.cancel(req);
EXPECT_EQ(Response::Error, res.status);
+ EXPECT_EQ(false, res.stale);
EXPECT_EQ(0ul, res.data.size());
EXPECT_EQ(0, res.expires);
EXPECT_EQ(0, res.modified);
diff --git a/test/storage/file_reading.cpp b/test/storage/file_reading.cpp
index dc0620b78b..434af703f2 100644
--- a/test/storage/file_reading.cpp
+++ b/test/storage/file_reading.cpp
@@ -20,6 +20,7 @@ TEST_F(Storage, AssetEmptyFile) {
[&](const Response &res) {
fs.cancel(req);
EXPECT_EQ(Response::Successful, res.status);
+ EXPECT_EQ(false, res.stale);
EXPECT_EQ(0ul, res.data.size());
EXPECT_EQ(0, res.expires);
EXPECT_LT(1420000000, res.modified);
@@ -46,6 +47,7 @@ TEST_F(Storage, AssetNonEmptyFile) {
uv_default_loop(), [&](const Response &res) {
fs.cancel(req);
EXPECT_EQ(Response::Successful, res.status);
+ EXPECT_EQ(false, res.stale);
EXPECT_EQ(16ul, res.data.size());
EXPECT_EQ(0, res.expires);
EXPECT_LT(1420000000, res.modified);
@@ -73,6 +75,7 @@ TEST_F(Storage, AssetNonExistentFile) {
uv_default_loop(), [&](const Response &res) {
fs.cancel(req);
EXPECT_EQ(Response::Error, res.status);
+ EXPECT_EQ(false, res.stale);
EXPECT_EQ(0ul, res.data.size());
EXPECT_EQ(0, res.expires);
EXPECT_EQ(0, res.modified);
diff --git a/test/storage/http_cancel.cpp b/test/storage/http_cancel.cpp
index 2eb599eeaa..5743ccb8f7 100644
--- a/test/storage/http_cancel.cpp
+++ b/test/storage/http_cancel.cpp
@@ -39,6 +39,7 @@ TEST_F(Storage, HTTPCancelMultiple) {
Request* req = fs.request(resource, uv_default_loop(), [&](const Response &res) {
fs.cancel(req);
EXPECT_EQ(Response::Successful, res.status);
+ EXPECT_EQ(false, res.stale);
EXPECT_EQ("Hello World!", res.data);
EXPECT_EQ(0, res.expires);
EXPECT_EQ(0, res.modified);
diff --git a/test/storage/http_coalescing.cpp b/test/storage/http_coalescing.cpp
index 9dfa855501..8558362034 100644
--- a/test/storage/http_coalescing.cpp
+++ b/test/storage/http_coalescing.cpp
@@ -50,3 +50,108 @@ TEST_F(Storage, HTTPCoalescing) {
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(Response::Successful, res.status);
+ EXPECT_EQ("Hello World!", res.data);
+ EXPECT_EQ(2147483647, res.expires);
+ EXPECT_EQ(0, res.modified);
+ EXPECT_EQ("", res.etag);
+ EXPECT_EQ("", res.message);
+
+ // 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(Response::Successful, res2.status);
+ EXPECT_EQ("Hello World!", res2.data);
+ EXPECT_EQ(2147483647, res2.expires);
+ EXPECT_EQ(0, res2.modified);
+ EXPECT_EQ("", res2.etag);
+ EXPECT_EQ("", res2.message);
+
+ 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(Response::Successful, res.status);
+ 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);
+ EXPECT_EQ("", res.message);
+
+ // 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(Response::Successful, res2.status);
+ EXPECT_EQ("Hello World!", res2.data);
+ EXPECT_EQ(0, res2.expires);
+ EXPECT_EQ(0, res2.modified);
+ EXPECT_EQ("", res2.etag);
+ EXPECT_EQ("", res2.message);
+
+ 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);
+}
diff --git a/test/storage/http_error.cpp b/test/storage/http_error.cpp
index aebc75405d..50b46a41b8 100644
--- a/test/storage/http_error.cpp
+++ b/test/storage/http_error.cpp
@@ -37,6 +37,7 @@ TEST_F(Storage, HTTPError) {
EXPECT_LT(1, duration) << "Backoff timer didn't wait 1 second";
EXPECT_GT(1.2, duration) << "Backoff timer fired too late";
EXPECT_EQ(Response::Successful, res.status);
+ EXPECT_EQ(false, res.stale);
EXPECT_EQ("Hello World!", res.data);
EXPECT_EQ(0, res.expires);
EXPECT_EQ(0, res.modified);
@@ -54,6 +55,7 @@ TEST_F(Storage, HTTPError) {
EXPECT_LT(1.5, duration) << "Resource wasn't retried the correct number of times";
EXPECT_GT(1.7, duration) << "Resource wasn't retried the correct number of times";
EXPECT_EQ(Response::Error, res.status);
+ EXPECT_EQ(false, res.stale);
#ifdef MBGL_HTTP_NSURL
EXPECT_TRUE(res.message ==
"The operation couldn’t be completed. (NSURLErrorDomain error -1004.)" ||
diff --git a/test/storage/http_header_parsing.cpp b/test/storage/http_header_parsing.cpp
index 13eab99125..93fdcb6231 100644
--- a/test/storage/http_header_parsing.cpp
+++ b/test/storage/http_header_parsing.cpp
@@ -20,6 +20,7 @@ TEST_F(Storage, HTTPHeaderParsing) {
uv_default_loop(), [&](const Response &res) {
fs.cancel(req1);
EXPECT_EQ(Response::Successful, res.status);
+ EXPECT_EQ(false, res.stale);
EXPECT_EQ("Hello World!", res.data);
EXPECT_EQ(1420797926, res.expires);
EXPECT_EQ(1420794326, res.modified);
@@ -35,6 +36,7 @@ TEST_F(Storage, HTTPHeaderParsing) {
uv_default_loop(), [&](const Response &res) {
fs.cancel(req2);
EXPECT_EQ(Response::Successful, res.status);
+ EXPECT_EQ(false, res.stale);
EXPECT_EQ("Hello World!", res.data);
EXPECT_GT(2, std::abs(res.expires - now - 120)) << "Expiration date isn't about 120 seconds in the future";
EXPECT_EQ(0, res.modified);
diff --git a/test/storage/http_issue_1369.cpp b/test/storage/http_issue_1369.cpp
index 954cb3b3f5..ba4e3d3885 100644
--- a/test/storage/http_issue_1369.cpp
+++ b/test/storage/http_issue_1369.cpp
@@ -33,6 +33,7 @@ TEST_F(Storage, HTTPIssue1369) {
req = fs.request(resource, uv_default_loop(), [&](const Response &res) {
fs.cancel(req);
EXPECT_EQ(Response::Successful, res.status);
+ EXPECT_EQ(false, res.stale);
EXPECT_EQ("Hello World!", res.data);
EXPECT_EQ(0, res.expires);
EXPECT_EQ(0, res.modified);
diff --git a/test/storage/http_load.cpp b/test/storage/http_load.cpp
index fa0468a848..092bf2db5a 100644
--- a/test/storage/http_load.cpp
+++ b/test/storage/http_load.cpp
@@ -25,6 +25,7 @@ TEST_F(Storage, HTTPLoad) {
fs.cancel(reqs[i]);
reqs[i] = nullptr;
EXPECT_EQ(Response::Successful, res.status);
+ EXPECT_EQ(false, res.stale);
EXPECT_EQ(std::string("Request ") + std::to_string(current), res.data);
EXPECT_EQ(0, res.expires);
EXPECT_EQ(0, res.modified);
diff --git a/test/storage/http_other_loop.cpp b/test/storage/http_other_loop.cpp
index 43a655fba4..cd9fad95be 100644
--- a/test/storage/http_other_loop.cpp
+++ b/test/storage/http_other_loop.cpp
@@ -16,6 +16,7 @@ TEST_F(Storage, HTTPOtherLoop) {
[&](const Response &res) {
fs.cancel(req);
EXPECT_EQ(Response::Successful, res.status);
+ EXPECT_EQ(false, res.stale);
EXPECT_EQ("Hello World!", res.data);
EXPECT_EQ(0, res.expires);
EXPECT_EQ(0, res.modified);
diff --git a/test/storage/http_reading.cpp b/test/storage/http_reading.cpp
index 84af943025..c5e89b88e8 100644
--- a/test/storage/http_reading.cpp
+++ b/test/storage/http_reading.cpp
@@ -23,6 +23,7 @@ TEST_F(Storage, HTTPReading) {
fs.cancel(req1);
EXPECT_EQ(uv_thread_self(), mainThread);
EXPECT_EQ(Response::Successful, res.status);
+ EXPECT_EQ(false, res.stale);
EXPECT_EQ("Hello World!", res.data);
EXPECT_EQ(0, res.expires);
EXPECT_EQ(0, res.modified);
@@ -36,6 +37,7 @@ TEST_F(Storage, HTTPReading) {
fs.cancel(req2);
EXPECT_EQ(uv_thread_self(), mainThread);
EXPECT_EQ(Response::NotFound, res.status);
+ EXPECT_EQ(false, res.stale);
EXPECT_EQ("", res.message);
EXPECT_EQ(0, res.expires);
EXPECT_EQ(0, res.modified);
@@ -48,6 +50,7 @@ TEST_F(Storage, HTTPReading) {
fs.cancel(req3);
EXPECT_EQ(uv_thread_self(), mainThread);
EXPECT_EQ(Response::Error, res.status);
+ EXPECT_EQ(false, res.stale);
EXPECT_EQ("HTTP status code 500", res.message);
EXPECT_EQ(0, res.expires);
EXPECT_EQ(0, res.modified);