[tests] Rationalize storage tests
Properly divide Storage tests into DefaultFileSource, OnlineFileSource, and HTTPFileSource tests.
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
#include <mbgl/test.hpp>
|
||||
#include <mbgl/test/util.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
int runTests(int argc, char *argv[]) {
|
||||
auto server = std::make_unique<test::Server>("test/storage/server.js");
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#include "storage.hpp"
|
||||
|
||||
#include <mbgl/storage/asset_file_source.hpp>
|
||||
#include <mbgl/platform/platform.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/util/thread.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace {
|
||||
|
||||
std::string getFileSourceRoot() {
|
||||
@@ -17,45 +17,11 @@ std::string getFileSourceRoot() {
|
||||
#endif
|
||||
}
|
||||
|
||||
class TestWorker {
|
||||
public:
|
||||
TestWorker(mbgl::AssetFileSource* fs_) : fs(fs_) {}
|
||||
|
||||
void run(std::function<void()> endCallback) {
|
||||
const std::string asset("asset://nonempty");
|
||||
|
||||
requestCallback = [this, asset, endCallback](mbgl::Response res) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("content is here\n", *res.data);
|
||||
|
||||
if (!--numRequests) {
|
||||
endCallback();
|
||||
request.reset();
|
||||
} else {
|
||||
request = fs->request({ mbgl::Resource::Unknown, asset }, requestCallback);
|
||||
}
|
||||
};
|
||||
|
||||
request = fs->request({ mbgl::Resource::Unknown, asset }, requestCallback);
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned numRequests = 1000;
|
||||
|
||||
mbgl::AssetFileSource* fs;
|
||||
std::unique_ptr<mbgl::AsyncRequest> request;
|
||||
|
||||
std::function<void(mbgl::Response)> requestCallback;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_F(Storage, AssetStress) {
|
||||
SCOPED_TEST(AssetStress)
|
||||
|
||||
using namespace mbgl;
|
||||
using namespace mbgl;
|
||||
|
||||
TEST(AssetFileSource, Stress) {
|
||||
util::RunLoop loop;
|
||||
|
||||
AssetFileSource fs(getFileSourceRoot());
|
||||
@@ -73,6 +39,38 @@ TEST_F(Storage, AssetStress) {
|
||||
}
|
||||
};
|
||||
|
||||
class TestWorker {
|
||||
public:
|
||||
TestWorker(mbgl::AssetFileSource* fs_) : fs(fs_) {}
|
||||
|
||||
void run(std::function<void()> endCallback) {
|
||||
const std::string asset("asset://nonempty");
|
||||
|
||||
requestCallback = [this, asset, endCallback](mbgl::Response res) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("content is here\n", *res.data);
|
||||
|
||||
if (!--numRequests) {
|
||||
endCallback();
|
||||
request.reset();
|
||||
} else {
|
||||
request = fs->request({ mbgl::Resource::Unknown, asset }, requestCallback);
|
||||
}
|
||||
};
|
||||
|
||||
request = fs->request({ mbgl::Resource::Unknown, asset }, requestCallback);
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned numRequests = 1000;
|
||||
|
||||
mbgl::AssetFileSource* fs;
|
||||
std::unique_ptr<mbgl::AsyncRequest> request;
|
||||
|
||||
std::function<void(mbgl::Response)> requestCallback;
|
||||
};
|
||||
|
||||
std::vector<std::unique_ptr<util::Thread<TestWorker>>> threads;
|
||||
std::vector<std::unique_ptr<mbgl::AsyncRequest>> requests;
|
||||
util::ThreadContext context = { "Test", util::ThreadType::Map, util::ThreadPriority::Regular };
|
||||
@@ -88,15 +86,9 @@ TEST_F(Storage, AssetStress) {
|
||||
}
|
||||
|
||||
loop.run();
|
||||
|
||||
AssetStress.finish();
|
||||
}
|
||||
|
||||
TEST_F(Storage, AssetEmptyFile) {
|
||||
SCOPED_TEST(EmptyFile)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
TEST(AssetFileSource, EmptyFile) {
|
||||
util::RunLoop loop;
|
||||
|
||||
AssetFileSource fs(getFileSourceRoot());
|
||||
@@ -107,17 +99,12 @@ TEST_F(Storage, AssetEmptyFile) {
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("", *res.data);
|
||||
loop.stop();
|
||||
EmptyFile.finish();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST_F(Storage, AssetNonEmptyFile) {
|
||||
SCOPED_TEST(NonEmptyFile)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
TEST(AssetFileSource, NonEmptyFile) {
|
||||
util::RunLoop loop;
|
||||
|
||||
AssetFileSource fs(getFileSourceRoot());
|
||||
@@ -128,17 +115,12 @@ TEST_F(Storage, AssetNonEmptyFile) {
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("content is here\n", *res.data);
|
||||
loop.stop();
|
||||
NonEmptyFile.finish();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST_F(Storage, AssetNonExistentFile) {
|
||||
SCOPED_TEST(NonExistentFile)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
TEST(AssetFileSource, NonExistentFile) {
|
||||
util::RunLoop loop;
|
||||
|
||||
AssetFileSource fs(getFileSourceRoot());
|
||||
@@ -150,17 +132,12 @@ TEST_F(Storage, AssetNonExistentFile) {
|
||||
ASSERT_FALSE(res.data.get());
|
||||
// Do not assert on platform-specific error message.
|
||||
loop.stop();
|
||||
NonExistentFile.finish();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST_F(Storage, AssetReadDirectory) {
|
||||
SCOPED_TEST(ReadDirectory)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
TEST(AssetFileSource, ReadDirectory) {
|
||||
util::RunLoop loop;
|
||||
|
||||
AssetFileSource fs(getFileSourceRoot());
|
||||
@@ -172,17 +149,12 @@ TEST_F(Storage, AssetReadDirectory) {
|
||||
ASSERT_FALSE(res.data.get());
|
||||
// Do not assert on platform-specific error message.
|
||||
loop.stop();
|
||||
ReadDirectory.finish();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST_F(Storage, AssetURLEncoding) {
|
||||
SCOPED_TEST(NonEmptyFile)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
TEST(AssetFileSource, URLEncoding) {
|
||||
util::RunLoop loop;
|
||||
|
||||
AssetFileSource fs(getFileSourceRoot());
|
||||
@@ -193,7 +165,6 @@ TEST_F(Storage, AssetURLEncoding) {
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("content is here\n", *res.data);
|
||||
loop.stop();
|
||||
NonEmptyFile.finish();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
#include "storage.hpp"
|
||||
|
||||
#include <mbgl/test/util.hpp>
|
||||
#include <mbgl/storage/default_file_source.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
|
||||
class DefaultFileSourceTest : public Storage {};
|
||||
|
||||
TEST_F(DefaultFileSourceTest, TEST_REQUIRES_SERVER(CacheResponse)) {
|
||||
SCOPED_TEST(CacheResponse);
|
||||
|
||||
using namespace mbgl;
|
||||
using namespace mbgl;
|
||||
|
||||
TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheResponse)) {
|
||||
util::RunLoop loop;
|
||||
DefaultFileSource fs(":memory:", ".");
|
||||
|
||||
@@ -41,18 +36,13 @@ TEST_F(DefaultFileSourceTest, TEST_REQUIRES_SERVER(CacheResponse)) {
|
||||
EXPECT_EQ(response.etag, res2.etag);
|
||||
|
||||
loop.stop();
|
||||
CacheResponse.finish();
|
||||
});
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST_F(DefaultFileSourceTest, TEST_REQUIRES_SERVER(CacheRevalidateSame)) {
|
||||
SCOPED_TEST(CacheRevalidateSame)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheRevalidateSame)) {
|
||||
util::RunLoop loop;
|
||||
DefaultFileSource fs(":memory:", ".");
|
||||
|
||||
@@ -89,7 +79,6 @@ TEST_F(DefaultFileSourceTest, TEST_REQUIRES_SERVER(CacheRevalidateSame)) {
|
||||
EXPECT_EQ("snowfall", *res2.etag);
|
||||
|
||||
loop.stop();
|
||||
CacheRevalidateSame.finish();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -97,11 +86,7 @@ TEST_F(DefaultFileSourceTest, TEST_REQUIRES_SERVER(CacheRevalidateSame)) {
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST_F(DefaultFileSourceTest, TEST_REQUIRES_SERVER(CacheRevalidateModified)) {
|
||||
SCOPED_TEST(CacheRevalidateModified)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheRevalidateModified)) {
|
||||
util::RunLoop loop;
|
||||
DefaultFileSource fs(":memory:", ".");
|
||||
|
||||
@@ -138,7 +123,6 @@ TEST_F(DefaultFileSourceTest, TEST_REQUIRES_SERVER(CacheRevalidateModified)) {
|
||||
EXPECT_FALSE(res2.etag);
|
||||
|
||||
loop.stop();
|
||||
CacheRevalidateModified.finish();
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -146,11 +130,7 @@ TEST_F(DefaultFileSourceTest, TEST_REQUIRES_SERVER(CacheRevalidateModified)) {
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST_F(DefaultFileSourceTest, TEST_REQUIRES_SERVER(CacheRevalidateEtag)) {
|
||||
SCOPED_TEST(CacheRevalidateEtag)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
TEST(DefaultFileSource, TEST_REQUIRES_SERVER(CacheRevalidateEtag)) {
|
||||
util::RunLoop loop;
|
||||
DefaultFileSource fs(":memory:", ".");
|
||||
|
||||
@@ -187,10 +167,44 @@ TEST_F(DefaultFileSourceTest, TEST_REQUIRES_SERVER(CacheRevalidateEtag)) {
|
||||
EXPECT_EQ("response-2", *res2.etag);
|
||||
|
||||
loop.stop();
|
||||
CacheRevalidateEtag.finish();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
// Test for https://github.com/mapbox/mapbox-gl-native/issue/1369
|
||||
//
|
||||
// A request for http://example.com is made. This triggers a cache get. While the cache get is
|
||||
// pending, the request is canceled. This removes it from pending. Then, still while the cache get
|
||||
// is pending, a second request is made for the same resource. This adds an entry back to pending
|
||||
// and queues another cache request, even though the first one is still pending. Now both cache
|
||||
// requests resolve to misses, resulting in two HTTP requests for the same resource. The first one
|
||||
// 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(DefaultFileSource, TEST_REQUIRES_SERVER(HTTPIssue1369)) {
|
||||
util::RunLoop loop;
|
||||
DefaultFileSource fs(":memory:", ".");
|
||||
|
||||
const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/test" };
|
||||
|
||||
auto req = fs.request(resource, [&](Response) {
|
||||
ADD_FAILURE() << "Callback should not be called";
|
||||
});
|
||||
req.reset();
|
||||
req = fs.request(resource, [&](Response res) {
|
||||
req.reset();
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Hello World!", *res.data);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#include "storage.hpp"
|
||||
#include <mbgl/test/util.hpp>
|
||||
|
||||
#include <mbgl/util/http_header.hpp>
|
||||
|
||||
TEST_F(Storage, HTTPHeaderParsing) {
|
||||
TEST(HTTPHeader, Parsing) {
|
||||
using namespace mbgl;
|
||||
|
||||
http::CacheControl cc;
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
#include "storage.hpp"
|
||||
|
||||
#include <mbgl/storage/online_file_source.hpp>
|
||||
#include <mbgl/storage/network_status.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTPCancel)) {
|
||||
SCOPED_TEST(HTTPCancel)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
auto req =
|
||||
fs.request({ Resource::Unknown, "http://127.0.0.1:3000/test" },
|
||||
[&](Response) { ADD_FAILURE() << "Callback should not be called"; });
|
||||
|
||||
req.reset();
|
||||
HTTPCancel.finish();
|
||||
|
||||
loop.runOnce();
|
||||
}
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTPCancelMultiple)) {
|
||||
SCOPED_TEST(HTTPCancelMultiple)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/test" };
|
||||
|
||||
std::unique_ptr<AsyncRequest> req2 = fs.request(resource, [&](Response) {
|
||||
ADD_FAILURE() << "Callback should not be called";
|
||||
});
|
||||
std::unique_ptr<AsyncRequest> req = fs.request(resource, [&](Response res) {
|
||||
req.reset();
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Hello World!", *res.data);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
HTTPCancelMultiple.finish();
|
||||
});
|
||||
req2.reset();
|
||||
|
||||
loop.run();
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
#include "storage.hpp"
|
||||
|
||||
#include <mbgl/storage/online_file_source.hpp>
|
||||
#include <mbgl/storage/network_status.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTPTemporaryError)) {
|
||||
SCOPED_TEST(HTTPTemporaryError)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
const auto start = Clock::now();
|
||||
|
||||
std::unique_ptr<AsyncRequest> req1 = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/temporary-error" }, [&](Response res) {
|
||||
static int counter = 0;
|
||||
switch (counter++) {
|
||||
case 0: {
|
||||
const auto duration = std::chrono::duration<const double>(Clock::now() - start).count();
|
||||
EXPECT_GT(0.2, duration) << "Initial error request took too long";
|
||||
ASSERT_NE(nullptr, res.error);
|
||||
EXPECT_EQ(Response::Error::Reason::Server, res.error->reason);
|
||||
EXPECT_EQ("HTTP status code 500", res.error->message);
|
||||
ASSERT_FALSE(bool(res.data));
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
} break;
|
||||
case 1: {
|
||||
req1.reset();
|
||||
const auto duration = std::chrono::duration<const double>(Clock::now() - start).count();
|
||||
EXPECT_LT(0.99, duration) << "Backoff timer didn't wait 1 second";
|
||||
EXPECT_GT(1.2, duration) << "Backoff timer fired too late";
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Hello World!", *res.data);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
HTTPTemporaryError.finish();
|
||||
} break;
|
||||
}
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTPConnectionError)) {
|
||||
SCOPED_TEST(HTTPConnectionError)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
const auto start = Clock::now();
|
||||
|
||||
std::unique_ptr<AsyncRequest> req2 = fs.request({ Resource::Unknown, "http://127.0.0.1:3001/" }, [&](Response res) {
|
||||
static int counter = 0;
|
||||
static int wait = 0;
|
||||
const auto duration = std::chrono::duration<const double>(Clock::now() - start).count();
|
||||
EXPECT_LT(wait - 0.01, duration) << "Backoff timer didn't wait 1 second";
|
||||
EXPECT_GT(wait + 0.2, duration) << "Backoff timer fired too late";
|
||||
ASSERT_NE(nullptr, res.error);
|
||||
EXPECT_EQ(Response::Error::Reason::Connection, res.error->reason);
|
||||
ASSERT_FALSE(res.data.get());
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
|
||||
if (counter == 2) {
|
||||
req2.reset();
|
||||
loop.stop();
|
||||
HTTPConnectionError.finish();
|
||||
}
|
||||
wait += (1 << counter);
|
||||
counter++;
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
#include "storage.hpp"
|
||||
|
||||
#include <mbgl/storage/default_file_source.hpp>
|
||||
#include <mbgl/storage/online_file_source.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/util/timer.hpp>
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTPRetryDelayOnExpiredTile)) {
|
||||
SCOPED_TEST(HTTPRetryDelayOnExpiredTile)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
int counter = 0;
|
||||
|
||||
const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/test?expires=10000" };
|
||||
std::unique_ptr<AsyncRequest> req = fs.request(resource, [&](Response res) {
|
||||
counter++;
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
EXPECT_GT(SystemClock::now(), res.expires);
|
||||
});
|
||||
|
||||
util::Timer timer;
|
||||
timer.start(Milliseconds(500), Duration::zero(), [&] () {
|
||||
loop.stop();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
|
||||
EXPECT_EQ(1, counter);
|
||||
|
||||
HTTPRetryDelayOnExpiredTile.finish();
|
||||
}
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTPRetryOnClockSkew)) {
|
||||
SCOPED_TEST(HTTPRetryOnClockSkew)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
DefaultFileSource fs(":memory:", ".");
|
||||
|
||||
int counter = 0;
|
||||
|
||||
const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/clockskew" };
|
||||
std::unique_ptr<AsyncRequest> req1 = fs.request(resource, [&](Response res) {
|
||||
switch (counter++) {
|
||||
case 0: {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
EXPECT_GT(SystemClock::now(), res.expires);
|
||||
} break;
|
||||
case 1: {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
|
||||
auto now = SystemClock::now();
|
||||
EXPECT_LT(now + Seconds(40), res.expires) << "Expiration not interpolated to 60s";
|
||||
EXPECT_GT(now + Seconds(80), res.expires) << "Expiration not interpolated to 60s";
|
||||
|
||||
loop.stop();
|
||||
} break;
|
||||
}
|
||||
});
|
||||
|
||||
loop.run();
|
||||
|
||||
HTTPRetryOnClockSkew.finish();
|
||||
}
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTPRespectPriorExpires)) {
|
||||
SCOPED_TEST(HTTPRespectPriorExpires)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
DefaultFileSource fs(":memory:", ".");
|
||||
|
||||
// Very long expiration time, should never arrive.
|
||||
Resource resource1{ Resource::Unknown, "http://127.0.0.1:3000/test" };
|
||||
resource1.priorExpires = SystemClock::now() + Seconds(100000);
|
||||
|
||||
std::unique_ptr<AsyncRequest> req1 = fs.request(resource1, [&](Response) {
|
||||
FAIL() << "Should never be called";
|
||||
});
|
||||
|
||||
// No expiration time, should be requested immediately.
|
||||
Resource resource2{ Resource::Unknown, "http://127.0.0.1:3000/test" };
|
||||
|
||||
std::unique_ptr<AsyncRequest> req2 = fs.request(resource2, [&](Response) {
|
||||
HTTPRespectPriorExpires.finish();
|
||||
loop.stop();
|
||||
});
|
||||
|
||||
// Very long expiration time, should never arrive.
|
||||
Resource resource3{ Resource::Unknown, "http://127.0.0.1:3000/test" };
|
||||
resource3.priorExpires = SystemClock::now() + Seconds(100000);
|
||||
|
||||
std::unique_ptr<AsyncRequest> req3 = fs.request(resource3, [&](Response) {
|
||||
FAIL() << "Should never be called";
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
195
test/storage/http_file_source.cpp
Normal file
195
test/storage/http_file_source.cpp
Normal file
@@ -0,0 +1,195 @@
|
||||
#include <mbgl/test/util.hpp>
|
||||
#include <mbgl/storage/http_file_source.hpp>
|
||||
#include <mbgl/util/exception.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
TEST(HTTPFileSource, TEST_REQUIRES_SERVER(Cancel)) {
|
||||
util::RunLoop loop;
|
||||
HTTPFileSource fs;
|
||||
|
||||
fs.request({ Resource::Unknown, "http://127.0.0.1:3000/test" }, [&](Response) {
|
||||
ADD_FAILURE() << "Callback should not be called";
|
||||
});
|
||||
|
||||
loop.runOnce();
|
||||
}
|
||||
|
||||
TEST(HTTPFileSource, TEST_REQUIRES_SERVER(HTTP200)) {
|
||||
util::RunLoop loop;
|
||||
HTTPFileSource fs;
|
||||
|
||||
auto req = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/test" }, [&](Response res) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Hello World!", *res.data);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST(HTTPFileSource, TEST_REQUIRES_SERVER(HTTP404)) {
|
||||
util::RunLoop loop;
|
||||
HTTPFileSource fs;
|
||||
|
||||
auto req = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/doesnotexist" }, [&](Response res) {
|
||||
ASSERT_NE(nullptr, res.error);
|
||||
EXPECT_EQ(Response::Error::Reason::NotFound, res.error->reason);
|
||||
EXPECT_EQ("HTTP status code 404", res.error->message);
|
||||
EXPECT_FALSE(bool(res.data));
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST(HTTPFileSource, TEST_REQUIRES_SERVER(HTTPTile404)) {
|
||||
util::RunLoop loop;
|
||||
HTTPFileSource fs;
|
||||
|
||||
auto req = fs.request({ Resource::Tile, "http://127.0.0.1:3000/doesnotexist" }, [&](Response res) {
|
||||
EXPECT_TRUE(res.noContent);
|
||||
EXPECT_FALSE(bool(res.error));
|
||||
EXPECT_FALSE(bool(res.data));
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST(HTTPFileSource, TEST_REQUIRES_SERVER(HTTP200EmptyData)) {
|
||||
util::RunLoop loop;
|
||||
HTTPFileSource fs;
|
||||
|
||||
auto req = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/empty-data" }, [&](Response res) {
|
||||
EXPECT_FALSE(res.noContent);
|
||||
EXPECT_FALSE(bool(res.error));
|
||||
EXPECT_EQ(*res.data, std::string());
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST(HTTPFileSource, TEST_REQUIRES_SERVER(HTTP204)) {
|
||||
util::RunLoop loop;
|
||||
HTTPFileSource fs;
|
||||
|
||||
auto req = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/no-content" }, [&](Response res) {
|
||||
EXPECT_TRUE(res.noContent);
|
||||
EXPECT_FALSE(bool(res.error));
|
||||
EXPECT_FALSE(bool(res.data));
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST(HTTPFileSource, TEST_REQUIRES_SERVER(HTTP500)) {
|
||||
util::RunLoop loop;
|
||||
HTTPFileSource fs;
|
||||
|
||||
auto req = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/permanent-error" }, [&](Response res) {
|
||||
ASSERT_NE(nullptr, res.error);
|
||||
EXPECT_EQ(Response::Error::Reason::Server, res.error->reason);
|
||||
EXPECT_EQ("HTTP status code 500", res.error->message);
|
||||
EXPECT_FALSE(bool(res.data));
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST(HTTPFileSource, TEST_REQUIRES_SERVER(ExpiresParsing)) {
|
||||
util::RunLoop loop;
|
||||
HTTPFileSource fs;
|
||||
|
||||
auto req = fs.request({ Resource::Unknown,
|
||||
"http://127.0.0.1:3000/test?modified=1420794326&expires=1420797926&etag=foo" }, [&](Response res) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Hello World!", *res.data);
|
||||
EXPECT_EQ(SystemClock::from_time_t(1420797926), res.expires);
|
||||
EXPECT_EQ(SystemClock::from_time_t(1420794326), res.modified);
|
||||
EXPECT_EQ("foo", *res.etag);
|
||||
loop.stop();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST(HTTPFileSource, TEST_REQUIRES_SERVER(CacheControlParsing)) {
|
||||
util::RunLoop loop;
|
||||
HTTPFileSource fs;
|
||||
|
||||
auto req = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/test?cachecontrol=max-age=120" }, [&](Response res) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Hello World!", *res.data);
|
||||
EXPECT_GT(Seconds(2), util::abs(*res.expires - SystemClock::now() - Seconds(120))) << "Expiration date isn't about 120 seconds in the future";
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST(HTTPFileSource, TEST_REQUIRES_SERVER(Load)) {
|
||||
util::RunLoop loop;
|
||||
HTTPFileSource fs;
|
||||
|
||||
const int concurrency = 50;
|
||||
const int max = 10000;
|
||||
int number = 1;
|
||||
|
||||
std::unique_ptr<AsyncRequest> 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);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ(std::string("Request ") + std::to_string(current), *res.data);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
|
||||
if (number <= max) {
|
||||
req(i);
|
||||
} else if (current == max) {
|
||||
loop.stop();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
for (int i = 0; i < concurrency; i++) {
|
||||
req(i);
|
||||
}
|
||||
|
||||
loop.run();
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
#include "storage.hpp"
|
||||
|
||||
#include <mbgl/storage/online_file_source.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTPExpiresParsing)) {
|
||||
SCOPED_TEST(HTTPExpiresTest)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
std::unique_ptr<AsyncRequest> 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);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Hello World!", *res.data);
|
||||
EXPECT_EQ(SystemClock::from_time_t(1420797926), res.expires);
|
||||
EXPECT_EQ(SystemClock::from_time_t(1420794326), res.modified);
|
||||
EXPECT_EQ("foo", *res.etag);
|
||||
loop.stop();
|
||||
HTTPExpiresTest.finish();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTPCacheControlParsing)) {
|
||||
SCOPED_TEST(HTTPCacheControlTest)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
std::unique_ptr<AsyncRequest> req2 = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/test?cachecontrol=max-age=120" },
|
||||
[&](Response res) {
|
||||
req2.reset();
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Hello World!", *res.data);
|
||||
EXPECT_GT(Seconds(2), util::abs(*res.expires - SystemClock::now() - Seconds(120))) << "Expiration date isn't about 120 seconds in the future";
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
HTTPCacheControlTest.finish();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
#include "storage.hpp"
|
||||
|
||||
#include <mbgl/storage/default_file_source.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
|
||||
// Test for https://github.com/mapbox/mapbox-gl-native/issue/1369
|
||||
//
|
||||
// A request for http://example.com is made. This triggers a cache get. While the cache get is
|
||||
// pending, the request is canceled. This removes it from pending. Then, still while the cache get
|
||||
// is pending, a second request is made for the same resource. This adds an entry back to pending
|
||||
// and queues another cache request, even though the first one is still pending. Now both cache
|
||||
// requests resolve to misses, resulting in two HTTP requests for the same resource. The first one
|
||||
// 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, TEST_REQUIRES_SERVER(HTTPIssue1369)) {
|
||||
SCOPED_TEST(HTTPIssue1369)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
DefaultFileSource fs(":memory:", ".");
|
||||
|
||||
const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/test" };
|
||||
|
||||
auto req = fs.request(resource, [&](Response) {
|
||||
ADD_FAILURE() << "Callback should not be called";
|
||||
});
|
||||
req.reset();
|
||||
req = fs.request(resource, [&](Response res) {
|
||||
req.reset();
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Hello World!", *res.data);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
HTTPIssue1369.finish();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
#include "storage.hpp"
|
||||
|
||||
#include <mbgl/storage/online_file_source.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTPLoad)) {
|
||||
SCOPED_TEST(HTTPLoad)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
const int concurrency = 50;
|
||||
const int max = 10000;
|
||||
int number = 1;
|
||||
|
||||
std::unique_ptr<AsyncRequest> 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);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ(std::string("Request ") + std::to_string(current), *res.data);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
|
||||
if (number <= max) {
|
||||
req(i);
|
||||
} else if (current == max) {
|
||||
loop.stop();
|
||||
HTTPLoad.finish();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
for (int i = 0; i < concurrency; i++) {
|
||||
req(i);
|
||||
}
|
||||
|
||||
loop.run();
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
#include "storage.hpp"
|
||||
|
||||
#include <mbgl/storage/online_file_source.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTPOtherLoop)) {
|
||||
SCOPED_TEST(HTTPOtherLoop)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
// This file source launches a separate thread to do the processing.
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
std::unique_ptr<AsyncRequest> req = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/test" },
|
||||
[&](Response res) {
|
||||
req.reset();
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Hello World!", *res.data);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
HTTPOtherLoop.finish();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
#include "storage.hpp"
|
||||
|
||||
#include <mbgl/storage/online_file_source.hpp>
|
||||
#include <mbgl/util/exception.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/util/thread_context.hpp>
|
||||
|
||||
#include <future>
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTPTest)) {
|
||||
SCOPED_TEST(HTTPTest)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
std::unique_ptr<AsyncRequest> req1 = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/test" },
|
||||
[&](Response res) {
|
||||
req1.reset();
|
||||
EXPECT_TRUE(util::ThreadContext::currentlyOn(util::ThreadType::Main));
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Hello World!", *res.data);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
HTTPTest.finish();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTP404)) {
|
||||
SCOPED_TEST(HTTP404)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
std::unique_ptr<AsyncRequest> req2 = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/doesnotexist" },
|
||||
[&](Response res) {
|
||||
req2.reset();
|
||||
EXPECT_TRUE(util::ThreadContext::currentlyOn(util::ThreadType::Main));
|
||||
ASSERT_NE(nullptr, res.error);
|
||||
EXPECT_EQ(Response::Error::Reason::NotFound, res.error->reason);
|
||||
EXPECT_EQ("HTTP status code 404", res.error->message);
|
||||
EXPECT_FALSE(bool(res.data));
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
HTTP404.finish();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTPTile404)) {
|
||||
SCOPED_TEST(HTTPTile404)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
std::unique_ptr<AsyncRequest> req2 = fs.request({ Resource::Tile, "http://127.0.0.1:3000/doesnotexist" },
|
||||
[&](Response res) {
|
||||
req2.reset();
|
||||
EXPECT_TRUE(util::ThreadContext::currentlyOn(util::ThreadType::Main));
|
||||
EXPECT_TRUE(res.noContent);
|
||||
EXPECT_FALSE(bool(res.error));
|
||||
EXPECT_FALSE(bool(res.data));
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
HTTPTile404.finish();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTP200EmptyData)) {
|
||||
SCOPED_TEST(HTTP200EmptyData)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
std::unique_ptr<AsyncRequest> req = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/empty-data" },
|
||||
[&](Response res) {
|
||||
req.reset();
|
||||
EXPECT_TRUE(util::ThreadContext::currentlyOn(util::ThreadType::Main));
|
||||
EXPECT_FALSE(res.noContent);
|
||||
EXPECT_FALSE(bool(res.error));
|
||||
EXPECT_EQ(*res.data, std::string());
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
HTTP200EmptyData.finish();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTP204)) {
|
||||
SCOPED_TEST(HTTP204)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
std::unique_ptr<AsyncRequest> req2 = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/no-content" },
|
||||
[&](Response res) {
|
||||
req2.reset();
|
||||
EXPECT_TRUE(util::ThreadContext::currentlyOn(util::ThreadType::Main));
|
||||
EXPECT_TRUE(res.noContent);
|
||||
EXPECT_FALSE(bool(res.error));
|
||||
EXPECT_FALSE(bool(res.data));
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
HTTP204.finish();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTP500)) {
|
||||
SCOPED_TEST(HTTP500)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
std::unique_ptr<AsyncRequest> req3 = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/permanent-error" },
|
||||
[&](Response res) {
|
||||
req3.reset();
|
||||
EXPECT_TRUE(util::ThreadContext::currentlyOn(util::ThreadType::Main));
|
||||
ASSERT_NE(nullptr, res.error);
|
||||
EXPECT_EQ(Response::Error::Reason::Server, res.error->reason);
|
||||
EXPECT_EQ("HTTP status code 500", res.error->message);
|
||||
EXPECT_FALSE(bool(res.data));
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
HTTP500.finish();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTPNoCallback)) {
|
||||
SCOPED_TEST(HTTPNoCallback)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
try {
|
||||
fs.request({ Resource::Unknown, "http://127.0.0.1:3000/test" },
|
||||
nullptr);
|
||||
} catch (const util::MisuseException& ex) {
|
||||
EXPECT_EQ(std::string(ex.what()), "FileSource callback can't be empty");
|
||||
} catch (const std::exception&) {
|
||||
EXPECT_TRUE(false) << "Unhandled exception.";
|
||||
}
|
||||
|
||||
HTTPNoCallback.finish();
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
#include "storage.hpp"
|
||||
|
||||
#include <mbgl/storage/online_file_source.hpp>
|
||||
#include <mbgl/storage/network_status.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/util/timer.hpp>
|
||||
|
||||
// Test for https://github.com/mapbox/mapbox-gl-native/issues/2123
|
||||
//
|
||||
// A request is made. While the request is in progress, the network status changes. This should
|
||||
// trigger an immediate retry of all requests that are not in progress. This test makes sure that
|
||||
// we don't accidentally double-trigger the request.
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTPNetworkStatusChange)) {
|
||||
SCOPED_TEST(HTTPNetworkStatusChange)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/delayed" };
|
||||
|
||||
// This request takes 200 milliseconds to answer.
|
||||
std::unique_ptr<AsyncRequest> req = fs.request(resource, [&](Response res) {
|
||||
req.reset();
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Response", *res.data);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
HTTPNetworkStatusChange.finish();
|
||||
});
|
||||
|
||||
// After 50 milliseconds, we're going to trigger a NetworkStatus change.
|
||||
util::Timer reachableTimer;
|
||||
reachableTimer.start(Milliseconds(50), Duration::zero(), [] () {
|
||||
mbgl::NetworkStatus::Reachable();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
// Tests that a change in network status preempts requests that failed due to connection or
|
||||
// reachability issues.
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTPNetworkStatusChangePreempt)) {
|
||||
SCOPED_TEST(HTTPNetworkStatusChangePreempt)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
const auto start = Clock::now();
|
||||
|
||||
const Resource resource{ Resource::Unknown, "http://127.0.0.1:3001/test" };
|
||||
std::unique_ptr<AsyncRequest> req = fs.request(resource, [&](Response res) {
|
||||
static int counter = 0;
|
||||
const auto duration = std::chrono::duration<const double>(Clock::now() - start).count();
|
||||
if (counter == 0) {
|
||||
EXPECT_GT(0.2, duration) << "Response came in too late";
|
||||
} else if (counter == 1) {
|
||||
EXPECT_LT(0.39, duration) << "Preempted retry triggered too early";
|
||||
EXPECT_GT(0.6, duration) << "Preempted retry triggered too late";
|
||||
} else if (counter > 1) {
|
||||
FAIL() << "Retried too often";
|
||||
}
|
||||
ASSERT_NE(nullptr, res.error);
|
||||
EXPECT_EQ(Response::Error::Reason::Connection, res.error->reason);
|
||||
ASSERT_FALSE(res.data.get());
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
|
||||
if (counter++ == 1) {
|
||||
req.reset();
|
||||
loop.stop();
|
||||
HTTPNetworkStatusChangePreempt.finish();
|
||||
}
|
||||
});
|
||||
|
||||
// After 400 milliseconds, we're going to trigger a NetworkStatus change.
|
||||
util::Timer reachableTimer;
|
||||
reachableTimer.start(Milliseconds(400), Duration::zero(), [] () {
|
||||
mbgl::NetworkStatus::Reachable();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTPNetworkStatusOnlineOffline)) {
|
||||
SCOPED_TEST(HTTPNetworkStatusOnlineOffline)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/test" };
|
||||
|
||||
EXPECT_EQ(NetworkStatus::Get(), NetworkStatus::Status::Online) << "Default status should be Online";
|
||||
NetworkStatus::Set(NetworkStatus::Status::Offline);
|
||||
|
||||
util::Timer onlineTimer;
|
||||
onlineTimer.start(Milliseconds(100), Duration::zero(), [&] () {
|
||||
NetworkStatus::Set(NetworkStatus::Status::Online);
|
||||
});
|
||||
|
||||
std::unique_ptr<AsyncRequest> req = fs.request(resource, [&](Response res) {
|
||||
req.reset();
|
||||
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
|
||||
EXPECT_EQ(NetworkStatus::Get(), NetworkStatus::Status::Online) << "Triggered before set back to Online";
|
||||
|
||||
loop.stop();
|
||||
HTTPNetworkStatusOnlineOffline.finish();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
#include "storage.hpp"
|
||||
|
||||
#include <mbgl/storage/online_file_source.hpp>
|
||||
#include <mbgl/storage/network_status.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
|
||||
TEST_F(Storage, TEST_REQUIRES_SERVER(HTTPTimeout)) {
|
||||
SCOPED_TEST(HTTPTimeout)
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
int counter = 0;
|
||||
|
||||
const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/test?cachecontrol=max-age=1" };
|
||||
std::unique_ptr<AsyncRequest> req = fs.request(resource, [&](Response res) {
|
||||
counter++;
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Hello World!", *res.data);
|
||||
EXPECT_TRUE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
if (counter == 4) {
|
||||
req.reset();
|
||||
loop.stop();
|
||||
HTTPTimeout.finish();
|
||||
}
|
||||
});
|
||||
|
||||
loop.run();
|
||||
|
||||
EXPECT_EQ(4, counter);
|
||||
}
|
||||
361
test/storage/online_file_source.cpp
Normal file
361
test/storage/online_file_source.cpp
Normal file
@@ -0,0 +1,361 @@
|
||||
#include <mbgl/test/util.hpp>
|
||||
#include <mbgl/storage/online_file_source.hpp>
|
||||
#include <mbgl/storage/network_status.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/util/timer.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
TEST(OnlineFileSource, Cancel) {
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
fs.request({ Resource::Unknown, "http://127.0.0.1:3000/test" }, [&](Response) {
|
||||
ADD_FAILURE() << "Callback should not be called";
|
||||
});
|
||||
|
||||
loop.runOnce();
|
||||
}
|
||||
|
||||
TEST(OnlineFileSource, TEST_REQUIRES_SERVER(CancelMultiple)) {
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/test" };
|
||||
|
||||
std::unique_ptr<AsyncRequest> req2 = fs.request(resource, [&](Response) {
|
||||
ADD_FAILURE() << "Callback should not be called";
|
||||
});
|
||||
std::unique_ptr<AsyncRequest> req = fs.request(resource, [&](Response res) {
|
||||
req.reset();
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Hello World!", *res.data);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
});
|
||||
req2.reset();
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST(OnlineFileSource, TEST_REQUIRES_SERVER(TemporaryError)) {
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
const auto start = Clock::now();
|
||||
|
||||
auto req = fs.request({ Resource::Unknown, "http://127.0.0.1:3000/temporary-error" }, [&](Response res) {
|
||||
static int counter = 0;
|
||||
switch (counter++) {
|
||||
case 0: {
|
||||
const auto duration = std::chrono::duration<const double>(Clock::now() - start).count();
|
||||
EXPECT_GT(0.2, duration) << "Initial error request took too long";
|
||||
ASSERT_NE(nullptr, res.error);
|
||||
EXPECT_EQ(Response::Error::Reason::Server, res.error->reason);
|
||||
EXPECT_EQ("HTTP status code 500", res.error->message);
|
||||
ASSERT_FALSE(bool(res.data));
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
} break;
|
||||
case 1: {
|
||||
const auto duration = std::chrono::duration<const double>(Clock::now() - start).count();
|
||||
EXPECT_LT(0.99, duration) << "Backoff timer didn't wait 1 second";
|
||||
EXPECT_GT(1.2, duration) << "Backoff timer fired too late";
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Hello World!", *res.data);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
} break;
|
||||
}
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST(OnlineFileSource, TEST_REQUIRES_SERVER(ConnectionError)) {
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
const auto start = Clock::now();
|
||||
|
||||
std::unique_ptr<AsyncRequest> req = fs.request({ Resource::Unknown, "http://127.0.0.1:3001/" }, [&](Response res) {
|
||||
static int counter = 0;
|
||||
static int wait = 0;
|
||||
const auto duration = std::chrono::duration<const double>(Clock::now() - start).count();
|
||||
EXPECT_LT(wait - 0.01, duration) << "Backoff timer didn't wait 1 second";
|
||||
EXPECT_GT(wait + 0.2, duration) << "Backoff timer fired too late";
|
||||
ASSERT_NE(nullptr, res.error);
|
||||
EXPECT_EQ(Response::Error::Reason::Connection, res.error->reason);
|
||||
ASSERT_FALSE(res.data.get());
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
|
||||
if (counter == 2) {
|
||||
req.reset();
|
||||
loop.stop();
|
||||
}
|
||||
wait += (1 << counter);
|
||||
counter++;
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST(OnlineFileSource, TEST_REQUIRES_SERVER(Timeout)) {
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
int counter = 0;
|
||||
|
||||
const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/test?cachecontrol=max-age=1" };
|
||||
std::unique_ptr<AsyncRequest> req = fs.request(resource, [&](Response res) {
|
||||
counter++;
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Hello World!", *res.data);
|
||||
EXPECT_TRUE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
if (counter == 4) {
|
||||
req.reset();
|
||||
loop.stop();
|
||||
}
|
||||
});
|
||||
|
||||
loop.run();
|
||||
|
||||
EXPECT_EQ(4, counter);
|
||||
}
|
||||
|
||||
TEST(OnlineFileSource, TEST_REQUIRES_SERVER(RetryDelayOnExpiredTile)) {
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
int counter = 0;
|
||||
|
||||
const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/test?expires=10000" };
|
||||
std::unique_ptr<AsyncRequest> req = fs.request(resource, [&](Response res) {
|
||||
counter++;
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
EXPECT_GT(SystemClock::now(), res.expires);
|
||||
});
|
||||
|
||||
util::Timer timer;
|
||||
timer.start(Milliseconds(500), Duration::zero(), [&] () {
|
||||
loop.stop();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
|
||||
EXPECT_EQ(1, counter);
|
||||
}
|
||||
|
||||
TEST(OnlineFileSource, TEST_REQUIRES_SERVER(RetryOnClockSkew)) {
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
int counter = 0;
|
||||
|
||||
const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/clockskew" };
|
||||
std::unique_ptr<AsyncRequest> req1 = fs.request(resource, [&](Response res) {
|
||||
switch (counter++) {
|
||||
case 0: {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
EXPECT_GT(SystemClock::now(), res.expires);
|
||||
} break;
|
||||
case 1: {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
|
||||
auto now = SystemClock::now();
|
||||
EXPECT_LT(now + Seconds(40), res.expires) << "Expiration not interpolated to 60s";
|
||||
EXPECT_GT(now + Seconds(80), res.expires) << "Expiration not interpolated to 60s";
|
||||
|
||||
loop.stop();
|
||||
} break;
|
||||
}
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST(OnlineFileSource, TEST_REQUIRES_SERVER(RespectPriorExpires)) {
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
// Very long expiration time, should never arrive.
|
||||
Resource resource1{ Resource::Unknown, "http://127.0.0.1:3000/test" };
|
||||
resource1.priorExpires = SystemClock::now() + Seconds(100000);
|
||||
|
||||
std::unique_ptr<AsyncRequest> req1 = fs.request(resource1, [&](Response) {
|
||||
FAIL() << "Should never be called";
|
||||
});
|
||||
|
||||
// No expiration time, should be requested immediately.
|
||||
Resource resource2{ Resource::Unknown, "http://127.0.0.1:3000/test" };
|
||||
|
||||
std::unique_ptr<AsyncRequest> req2 = fs.request(resource2, [&](Response) {
|
||||
loop.stop();
|
||||
});
|
||||
|
||||
// Very long expiration time, should never arrive.
|
||||
Resource resource3{ Resource::Unknown, "http://127.0.0.1:3000/test" };
|
||||
resource3.priorExpires = SystemClock::now() + Seconds(100000);
|
||||
|
||||
std::unique_ptr<AsyncRequest> req3 = fs.request(resource3, [&](Response) {
|
||||
FAIL() << "Should never be called";
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST(OnlineFileSource, TEST_REQUIRES_SERVER(Load)) {
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
const int concurrency = 50;
|
||||
const int max = 10000;
|
||||
int number = 1;
|
||||
|
||||
std::unique_ptr<AsyncRequest> 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);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ(std::string("Request ") + std::to_string(current), *res.data);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
|
||||
if (number <= max) {
|
||||
req(i);
|
||||
} else if (current == max) {
|
||||
loop.stop();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
for (int i = 0; i < concurrency; i++) {
|
||||
req(i);
|
||||
}
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
// Test for https://github.com/mapbox/mapbox-gl-native/issues/2123
|
||||
//
|
||||
// A request is made. While the request is in progress, the network status changes. This should
|
||||
// trigger an immediate retry of all requests that are not in progress. This test makes sure that
|
||||
// we don't accidentally double-trigger the request.
|
||||
|
||||
TEST(OnlineFileSource, TEST_REQUIRES_SERVER(NetworkStatusChange)) {
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/delayed" };
|
||||
|
||||
// This request takes 200 milliseconds to answer.
|
||||
std::unique_ptr<AsyncRequest> req = fs.request(resource, [&](Response res) {
|
||||
req.reset();
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Response", *res.data);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
});
|
||||
|
||||
// After 50 milliseconds, we're going to trigger a NetworkStatus change.
|
||||
util::Timer reachableTimer;
|
||||
reachableTimer.start(Milliseconds(50), Duration::zero(), [] () {
|
||||
mbgl::NetworkStatus::Reachable();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
// Tests that a change in network status preempts requests that failed due to connection or
|
||||
// reachability issues.
|
||||
TEST(OnlineFileSource, TEST_REQUIRES_SERVER(NetworkStatusChangePreempt)) {
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
const auto start = Clock::now();
|
||||
|
||||
const Resource resource{ Resource::Unknown, "http://127.0.0.1:3001/test" };
|
||||
std::unique_ptr<AsyncRequest> req = fs.request(resource, [&](Response res) {
|
||||
static int counter = 0;
|
||||
const auto duration = std::chrono::duration<const double>(Clock::now() - start).count();
|
||||
if (counter == 0) {
|
||||
EXPECT_GT(0.2, duration) << "Response came in too late";
|
||||
} else if (counter == 1) {
|
||||
EXPECT_LT(0.39, duration) << "Preempted retry triggered too early";
|
||||
EXPECT_GT(0.6, duration) << "Preempted retry triggered too late";
|
||||
} else if (counter > 1) {
|
||||
FAIL() << "Retried too often";
|
||||
}
|
||||
ASSERT_NE(nullptr, res.error);
|
||||
EXPECT_EQ(Response::Error::Reason::Connection, res.error->reason);
|
||||
ASSERT_FALSE(res.data.get());
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
|
||||
if (counter++ == 1) {
|
||||
req.reset();
|
||||
loop.stop();
|
||||
}
|
||||
});
|
||||
|
||||
// After 400 milliseconds, we're going to trigger a NetworkStatus change.
|
||||
util::Timer reachableTimer;
|
||||
reachableTimer.start(Milliseconds(400), Duration::zero(), [] () {
|
||||
mbgl::NetworkStatus::Reachable();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
|
||||
TEST(OnlineFileSource, TEST_REQUIRES_SERVER(NetworkStatusOnlineOffline)) {
|
||||
util::RunLoop loop;
|
||||
OnlineFileSource fs;
|
||||
|
||||
const Resource resource { Resource::Unknown, "http://127.0.0.1:3000/test" };
|
||||
|
||||
EXPECT_EQ(NetworkStatus::Get(), NetworkStatus::Status::Online) << "Default status should be Online";
|
||||
NetworkStatus::Set(NetworkStatus::Status::Offline);
|
||||
|
||||
util::Timer onlineTimer;
|
||||
onlineTimer.start(Milliseconds(100), Duration::zero(), [&] () {
|
||||
NetworkStatus::Set(NetworkStatus::Status::Online);
|
||||
});
|
||||
|
||||
std::unique_ptr<AsyncRequest> req = fs.request(resource, [&](Response res) {
|
||||
req.reset();
|
||||
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
|
||||
EXPECT_EQ(NetworkStatus::Get(), NetworkStatus::Status::Online) << "Triggered before set back to Online";
|
||||
|
||||
loop.stop();
|
||||
});
|
||||
|
||||
loop.run();
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#include "storage.hpp"
|
||||
|
||||
std::unique_ptr<mbgl::test::Server> Storage::server;
|
||||
|
||||
void Storage::SetUpTestCase() {
|
||||
#if TEST_HAS_SERVER
|
||||
server = std::make_unique<mbgl::test::Server>("test/storage/server.js");
|
||||
#endif
|
||||
}
|
||||
|
||||
void Storage::TearDownTestCase() {
|
||||
server.reset();
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
#ifndef MBGL_TEST_STORAGE_STORAGE
|
||||
#define MBGL_TEST_STORAGE_STORAGE
|
||||
|
||||
#include <mbgl/test/util.hpp>
|
||||
#include <mbgl/storage/response.hpp>
|
||||
#include <memory>
|
||||
|
||||
class Storage : public testing::Test {
|
||||
public:
|
||||
static void SetUpTestCase();
|
||||
static void TearDownTestCase();
|
||||
|
||||
protected:
|
||||
static std::unique_ptr<mbgl::test::Server> server;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -45,24 +45,14 @@
|
||||
'map/tile.cpp',
|
||||
'map/transform.cpp',
|
||||
|
||||
'storage/storage.hpp',
|
||||
'storage/storage.cpp',
|
||||
'storage/default_file_source.cpp',
|
||||
'storage/offline.cpp',
|
||||
'storage/offline_database.cpp',
|
||||
'storage/offline_download.cpp',
|
||||
'storage/asset_file_source.cpp',
|
||||
'storage/default_file_source.cpp',
|
||||
'storage/http_file_source.cpp',
|
||||
'storage/online_file_source.cpp',
|
||||
'storage/headers.cpp',
|
||||
'storage/http_cancel.cpp',
|
||||
'storage/http_error.cpp',
|
||||
'storage/http_expires.cpp',
|
||||
'storage/http_header_parsing.cpp',
|
||||
'storage/http_issue_1369.cpp',
|
||||
'storage/http_load.cpp',
|
||||
'storage/http_other_loop.cpp',
|
||||
'storage/http_retry_network_status.cpp',
|
||||
'storage/http_reading.cpp',
|
||||
'storage/http_timeout.cpp',
|
||||
'storage/resource.cpp',
|
||||
|
||||
'style/glyph_store.cpp',
|
||||
|
||||
Reference in New Issue
Block a user