[core] Use better types for modified / expires / etag
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
#define MBGL_STORAGE_RESPONSE
|
||||
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/util/optional.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
@@ -25,9 +26,9 @@ public:
|
||||
// The actual data of the response. This is guaranteed to never be empty.
|
||||
std::shared_ptr<const std::string> data;
|
||||
|
||||
Seconds modified = Seconds::zero();
|
||||
Seconds expires = Seconds::zero();
|
||||
std::string etag;
|
||||
optional<SystemTimePoint> modified;
|
||||
optional<SystemTimePoint> expires;
|
||||
optional<std::string> etag;
|
||||
};
|
||||
|
||||
class Response::Error {
|
||||
|
||||
@@ -124,10 +124,10 @@ HTTPAndroidRequest::HTTPAndroidRequest(HTTPAndroidContext* context_, const std::
|
||||
std::string etagStr;
|
||||
std::string modifiedStr;
|
||||
if (existingResponse) {
|
||||
if (!existingResponse->etag.empty()) {
|
||||
etagStr = existingResponse->etag;
|
||||
} else if (existingResponse->modified != Seconds::zero()) {
|
||||
modifiedStr = util::rfc1123(existingResponse->modified.count());
|
||||
if (existingResponse->etag) {
|
||||
etagStr = *existingResponse->etag;
|
||||
} else if (existingResponse->modified) {
|
||||
modifiedStr = util::rfc1123(SystemClock::to_time_t(*existingResponse->modified));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,11 +195,11 @@ void HTTPAndroidRequest::onResponse(int code, std::string message, std::string e
|
||||
// the message param is unused, this generates a warning at build time
|
||||
// this was breaking builds for `make android -j4`
|
||||
(void)message;
|
||||
response->modified = Seconds(parse_date(modified.c_str()));
|
||||
response->modified = SystemClock::from_time_t(parse_date(modified.c_str()));
|
||||
response->etag = etag;
|
||||
response->expires = parseCacheControl(cacheControl.c_str());
|
||||
if (!expires.empty()) {
|
||||
response->expires = Seconds(parse_date(expires.c_str()));
|
||||
response->expires = SystemClock::from_time_t(parse_date(expires.c_str()));
|
||||
}
|
||||
response->data = std::make_shared<std::string>(body);
|
||||
|
||||
@@ -211,15 +211,15 @@ void HTTPAndroidRequest::onResponse(int code, std::string message, std::string e
|
||||
if (existingResponse) {
|
||||
response->data = existingResponse->data;
|
||||
|
||||
if (response->expires == Seconds::zero()) {
|
||||
if (!response->expires) {
|
||||
response->expires = existingResponse->expires;
|
||||
}
|
||||
|
||||
if (response->modified == Seconds::zero()) {
|
||||
if (!response->modified) {
|
||||
response->modified = existingResponse->modified;
|
||||
}
|
||||
|
||||
if (response->etag.empty()) {
|
||||
if (!response->etag) {
|
||||
response->etag = existingResponse->etag;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,12 +113,12 @@ HTTPNSURLRequest::HTTPNSURLRequest(HTTPNSURLContext* context_,
|
||||
|
||||
NSMutableURLRequest* req = [NSMutableURLRequest requestWithURL:url];
|
||||
if (existingResponse) {
|
||||
if (!existingResponse->etag.empty()) {
|
||||
[req addValue:@(existingResponse->etag.c_str())
|
||||
forHTTPHeaderField:@"If-None-Match"];
|
||||
} else if (existingResponse->modified != Seconds::zero()) {
|
||||
const std::string time = util::rfc1123(existingResponse->modified.count());
|
||||
[req addValue:@(time.c_str()) forHTTPHeaderField:@"If-Modified-Since"];
|
||||
if (existingResponse->etag) {
|
||||
[req addValue:@((*existingResponse->etag).c_str())
|
||||
forHTTPHeaderField:@"If-None-Match"];
|
||||
} else if (existingResponse->modified) {
|
||||
[req addValue:@(util::rfc1123(SystemClock::to_time_t(*existingResponse->modified)).c_str())
|
||||
forHTTPHeaderField:@"If-Modified-Since"];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,17 +217,17 @@ void HTTPNSURLRequest::handleResult(NSData *data, NSURLResponse *res, NSError *e
|
||||
|
||||
NSString *expires = [headers objectForKey:@"Expires"];
|
||||
if (expires) {
|
||||
response->expires = Seconds(parse_date([expires UTF8String]));
|
||||
response->expires = SystemClock::from_time_t(parse_date([expires UTF8String]));
|
||||
}
|
||||
|
||||
NSString *last_modified = [headers objectForKey:@"Last-Modified"];
|
||||
if (last_modified) {
|
||||
response->modified = Seconds(parse_date([last_modified UTF8String]));
|
||||
response->modified = SystemClock::from_time_t(parse_date([last_modified UTF8String]));
|
||||
}
|
||||
|
||||
NSString *etag = [headers objectForKey:@"ETag"];
|
||||
if (etag) {
|
||||
response->etag = [etag UTF8String];
|
||||
response->etag = std::string([etag UTF8String]);
|
||||
}
|
||||
|
||||
if (responseCode == 200) {
|
||||
@@ -238,15 +238,15 @@ void HTTPNSURLRequest::handleResult(NSData *data, NSURLResponse *res, NSError *e
|
||||
if (existingResponse) {
|
||||
response->data = existingResponse->data;
|
||||
|
||||
if (response->expires == Seconds::zero()) {
|
||||
if (!response->expires) {
|
||||
response->expires = existingResponse->expires;
|
||||
}
|
||||
|
||||
if (response->modified == Seconds::zero()) {
|
||||
if (!response->modified) {
|
||||
response->modified = existingResponse->modified;
|
||||
}
|
||||
|
||||
if (response->etag.empty()) {
|
||||
if (!response->etag) {
|
||||
response->etag = existingResponse->etag;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,12 +363,12 @@ HTTPCURLRequest::HTTPCURLRequest(HTTPCURLContext* context_, const std::string& u
|
||||
// If there's already a response, set the correct etags/modified headers to make sure we are
|
||||
// getting a 304 response if possible. This avoids redownloading unchanged data.
|
||||
if (existingResponse) {
|
||||
if (!existingResponse->etag.empty()) {
|
||||
const std::string header = std::string("If-None-Match: ") + existingResponse->etag;
|
||||
if (existingResponse->etag) {
|
||||
const std::string header = std::string("If-None-Match: ") + *existingResponse->etag;
|
||||
headers = curl_slist_append(headers, header.c_str());
|
||||
} else if (existingResponse->modified != Seconds::zero()) {
|
||||
} else if (existingResponse->modified) {
|
||||
const std::string time =
|
||||
std::string("If-Modified-Since: ") + util::rfc1123(existingResponse->modified.count());
|
||||
std::string("If-Modified-Since: ") + util::rfc1123(SystemClock::to_time_t(*existingResponse->modified));
|
||||
headers = curl_slist_append(headers, time.c_str());
|
||||
}
|
||||
}
|
||||
@@ -466,15 +466,15 @@ size_t HTTPCURLRequest::headerCallback(char *const buffer, const size_t size, co
|
||||
// Always overwrite the modification date; We might already have a value here from the
|
||||
// Date header, but this one is more accurate.
|
||||
const std::string value { buffer + begin, length - begin - 2 }; // remove \r\n
|
||||
baton->response->modified = Seconds(curl_getdate(value.c_str(), nullptr));
|
||||
baton->response->modified = SystemClock::from_time_t(curl_getdate(value.c_str(), nullptr));
|
||||
} else if ((begin = headerMatches("etag: ", buffer, length)) != std::string::npos) {
|
||||
baton->response->etag = { buffer + begin, length - begin - 2 }; // remove \r\n
|
||||
baton->response->etag = std::string(buffer + begin, length - begin - 2); // remove \r\n
|
||||
} else if ((begin = headerMatches("cache-control: ", buffer, length)) != std::string::npos) {
|
||||
const std::string value { buffer + begin, length - begin - 2 }; // remove \r\n
|
||||
baton->response->expires = parseCacheControl(value.c_str());
|
||||
} else if ((begin = headerMatches("expires: ", buffer, length)) != std::string::npos) {
|
||||
const std::string value { buffer + begin, length - begin - 2 }; // remove \r\n
|
||||
baton->response->expires = Seconds(curl_getdate(value.c_str(), nullptr));
|
||||
baton->response->expires = SystemClock::from_time_t(curl_getdate(value.c_str(), nullptr));
|
||||
}
|
||||
|
||||
return length;
|
||||
@@ -534,15 +534,15 @@ void HTTPCURLRequest::handleResult(CURLcode code) {
|
||||
if (existingResponse) {
|
||||
response->data = existingResponse->data;
|
||||
|
||||
if (response->expires == Seconds::zero()) {
|
||||
if (!response->expires) {
|
||||
response->expires = existingResponse->expires;
|
||||
}
|
||||
|
||||
if (response->modified == Seconds::zero()) {
|
||||
if (!response->modified) {
|
||||
response->modified = existingResponse->modified;
|
||||
}
|
||||
|
||||
if (response->etag.empty()) {
|
||||
if (!response->etag) {
|
||||
response->etag = existingResponse->etag;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,14 +192,13 @@ void OnlineFileRequestImpl::scheduleCacheRequest(OnlineFileSource::Impl& impl) {
|
||||
callback(*response);
|
||||
}
|
||||
|
||||
// Force an immediate request if the cached response is stale. Note that this is not
|
||||
// quite the same as what `expirationTimeout` would calculate, because in `expirationTimeout`
|
||||
// Seconds::zero() is treated as "no expiration", but here we want it to force a revalidation.
|
||||
scheduleRealRequest(impl, response && response->expires <= toSeconds(SystemClock::now()));
|
||||
// Force immediate revalidation if the cached response didn't indicate an expiration. If
|
||||
// it did indicate an expiration, revalidation will happen in the normal scheduling flow.
|
||||
scheduleRealRequest(impl, response && !response->expires);
|
||||
});
|
||||
}
|
||||
|
||||
static Seconds errorRetryTimeout(const Response& response, uint32_t failedRequests) {
|
||||
static Duration errorRetryTimeout(const Response& response, uint32_t failedRequests) {
|
||||
if (response.error && response.error->reason == Response::Error::Reason::Server) {
|
||||
// Retry after one second three times, then start exponential backoff.
|
||||
return Seconds(failedRequests <= 3 ? 1 : 1 << std::min(failedRequests - 3, 31u));
|
||||
@@ -209,16 +208,15 @@ static Seconds errorRetryTimeout(const Response& response, uint32_t failedReques
|
||||
return Seconds(1 << std::min(failedRequests - 1, 31u));
|
||||
} else {
|
||||
// No error, or not an error that triggers retries.
|
||||
return Seconds::max();
|
||||
return Duration::max();
|
||||
}
|
||||
}
|
||||
|
||||
static Seconds expirationTimeout(const Response& response) {
|
||||
// Seconds::zero() is a special value meaning "no expiration".
|
||||
if (response.expires > Seconds::zero()) {
|
||||
return std::max(Seconds::zero(), response.expires - toSeconds(SystemClock::now()));
|
||||
static Duration expirationTimeout(const Response& response) {
|
||||
if (response.expires) {
|
||||
return std::max(SystemDuration::zero(), *response.expires - SystemClock::now());
|
||||
} else {
|
||||
return Seconds::max();
|
||||
return Duration::max();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,7 +226,7 @@ void OnlineFileRequestImpl::scheduleRealRequest(OnlineFileSource::Impl& impl, bo
|
||||
return;
|
||||
}
|
||||
|
||||
Seconds timeout = Seconds::zero();
|
||||
Duration timeout = Duration::zero();
|
||||
|
||||
// If there was a prior response and we're not being asked for a forced refresh, calculate a timeout
|
||||
// that depends on how many consecutive errors we've encountered, and on the expiration time.
|
||||
@@ -236,7 +234,7 @@ void OnlineFileRequestImpl::scheduleRealRequest(OnlineFileSource::Impl& impl, bo
|
||||
timeout = std::min(errorRetryTimeout(*response, failedRequests),
|
||||
expirationTimeout(*response));
|
||||
|
||||
if (timeout == Seconds::max()) {
|
||||
if (timeout == Duration::max()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <chrono>
|
||||
#include <experimental/optional>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
@@ -24,6 +26,9 @@ const static bool sqliteVersionCheck = []() {
|
||||
namespace mapbox {
|
||||
namespace sqlite {
|
||||
|
||||
template <typename T>
|
||||
using optional = std::experimental::optional<T>;
|
||||
|
||||
Database::Database(const std::string &filename, int flags) {
|
||||
const int err = sqlite3_open_v2(filename.c_str(), &db, flags, nullptr);
|
||||
if (err != SQLITE_OK) {
|
||||
@@ -105,6 +110,11 @@ void Statement::check(int err) {
|
||||
}
|
||||
}
|
||||
|
||||
template <> void Statement::bind(int offset, std::nullptr_t) {
|
||||
assert(stmt);
|
||||
check(sqlite3_bind_null(stmt, offset));
|
||||
}
|
||||
|
||||
template <> void Statement::bind(int offset, int value) {
|
||||
assert(stmt);
|
||||
check(sqlite3_bind_int(stmt, offset, value));
|
||||
@@ -130,12 +140,33 @@ template <> void Statement::bind(int offset, const char *value) {
|
||||
check(sqlite3_bind_text(stmt, offset, value, -1, SQLITE_STATIC));
|
||||
}
|
||||
|
||||
void Statement::bind(int offset, const std::string &value, bool retain) {
|
||||
void Statement::bind(int offset, const std::string& value, bool retain) {
|
||||
assert(stmt);
|
||||
check(sqlite3_bind_blob(stmt, offset, value.data(), int(value.size()),
|
||||
retain ? SQLITE_TRANSIENT : SQLITE_STATIC));
|
||||
}
|
||||
|
||||
template <> void Statement::bind(int offset, std::chrono::system_clock::time_point value) {
|
||||
assert(stmt);
|
||||
check(sqlite3_bind_int64(stmt, offset, std::chrono::system_clock::to_time_t(value)));
|
||||
}
|
||||
|
||||
template <> void Statement::bind(int offset, optional<std::string> value) {
|
||||
if (!value) {
|
||||
bind(offset, nullptr);
|
||||
} else {
|
||||
bind(offset, *value);
|
||||
}
|
||||
}
|
||||
|
||||
template <> void Statement::bind(int offset, optional<std::chrono::system_clock::time_point> value) {
|
||||
if (!value) {
|
||||
bind(offset, nullptr);
|
||||
} else {
|
||||
bind(offset, *value);
|
||||
}
|
||||
}
|
||||
|
||||
bool Statement::run() {
|
||||
assert(stmt);
|
||||
const int err = sqlite3_step(stmt);
|
||||
@@ -173,6 +204,29 @@ template <> std::string Statement::get(int offset) {
|
||||
};
|
||||
}
|
||||
|
||||
template <> std::chrono::system_clock::time_point Statement::get(int offset) {
|
||||
assert(stmt);
|
||||
return std::chrono::system_clock::from_time_t(sqlite3_column_int64(stmt, offset));
|
||||
}
|
||||
|
||||
template <> optional<std::string> Statement::get(int offset) {
|
||||
assert(stmt);
|
||||
if (sqlite3_column_type(stmt, offset) == SQLITE_NULL) {
|
||||
return optional<std::string>();
|
||||
} else {
|
||||
return get<std::string>(offset);
|
||||
}
|
||||
}
|
||||
|
||||
template <> optional<std::chrono::system_clock::time_point> Statement::get(int offset) {
|
||||
assert(stmt);
|
||||
if (sqlite3_column_type(stmt, offset) == SQLITE_NULL) {
|
||||
return optional<std::chrono::system_clock::time_point>();
|
||||
} else {
|
||||
return get<std::chrono::system_clock::time_point>(offset);
|
||||
}
|
||||
}
|
||||
|
||||
void Statement::reset() {
|
||||
assert(stmt);
|
||||
sqlite3_reset(stmt);
|
||||
|
||||
@@ -332,9 +332,9 @@ void SQLiteCache::Impl::get(const Resource &resource, Callback callback) {
|
||||
// Status codes > 1 indicate an error
|
||||
response->error = std::make_unique<Response::Error>(Response::Error::Reason(status));
|
||||
}
|
||||
response->modified = Seconds(getStmt->get<int64_t>(1));
|
||||
response->etag = getStmt->get<std::string>(2);
|
||||
response->expires = Seconds(getStmt->get<int64_t>(3));
|
||||
response->modified = getStmt->get<optional<SystemTimePoint>>(1);
|
||||
response->etag = getStmt->get<optional<std::string>>(2);
|
||||
response->expires = getStmt->get<optional<SystemTimePoint>>(3);
|
||||
response->data = std::make_shared<std::string>(getStmt->get<std::string>(4));
|
||||
if (getStmt->get<int>(5)) { // == compressed
|
||||
response->data = std::make_shared<std::string>(util::decompress(*response->data));
|
||||
@@ -357,7 +357,7 @@ void SQLiteCache::Impl::get(const Resource &resource, Callback callback) {
|
||||
accessedStmt->reset();
|
||||
}
|
||||
|
||||
accessedStmt->bind(1, int64_t(toSeconds(SystemClock::now()).count()));
|
||||
accessedStmt->bind(1, SystemClock::now());
|
||||
accessedStmt->bind(2, canonicalURL.c_str());
|
||||
accessedStmt->run();
|
||||
}
|
||||
@@ -419,10 +419,10 @@ void SQLiteCache::Impl::put(const Resource& resource, const Response& response)
|
||||
putStmt->bind(2 /* status */, 1 /* success */);
|
||||
}
|
||||
putStmt->bind(3 /* kind */, int(resource.kind));
|
||||
putStmt->bind(4 /* modified */, int64_t(response.modified.count()));
|
||||
putStmt->bind(5 /* etag */, response.etag.c_str());
|
||||
putStmt->bind(6 /* expires */, int64_t(response.expires.count()));
|
||||
putStmt->bind(7 /* accessed */, int64_t(toSeconds(SystemClock::now()).count()));
|
||||
putStmt->bind(4 /* modified */, response.modified);
|
||||
putStmt->bind(5 /* etag */, response.etag);
|
||||
putStmt->bind(6 /* expires */, response.expires);
|
||||
putStmt->bind(7 /* accessed */, SystemClock::now());
|
||||
|
||||
std::string data;
|
||||
if (resource.kind != Resource::SpriteImage && response.data) {
|
||||
@@ -452,7 +452,7 @@ void SQLiteCache::Impl::put(const Resource& resource, const Response& response)
|
||||
}
|
||||
}
|
||||
|
||||
void SQLiteCache::Impl::refresh(const Resource& resource, Seconds expires) {
|
||||
void SQLiteCache::Impl::refresh(const Resource& resource, optional<SystemTimePoint> expires) {
|
||||
try {
|
||||
initializeDatabase();
|
||||
|
||||
@@ -466,8 +466,8 @@ void SQLiteCache::Impl::refresh(const Resource& resource, Seconds expires) {
|
||||
}
|
||||
|
||||
const auto canonicalURL = util::mapbox::canonicalURL(resource.url);
|
||||
refreshStmt->bind(1, int64_t(toSeconds(SystemClock::now()).count()));
|
||||
refreshStmt->bind(2, int64_t(expires.count()));
|
||||
refreshStmt->bind(1, SystemClock::now());
|
||||
refreshStmt->bind(2, expires);
|
||||
refreshStmt->bind(3, canonicalURL.c_str());
|
||||
refreshStmt->run();
|
||||
} catch (mapbox::sqlite::Exception& ex) {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <mbgl/storage/sqlite_cache.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/util/optional.hpp>
|
||||
|
||||
namespace mapbox {
|
||||
namespace sqlite {
|
||||
@@ -23,7 +24,7 @@ public:
|
||||
|
||||
void get(const Resource&, Callback);
|
||||
void put(const Resource&, const Response&);
|
||||
void refresh(const Resource&, Seconds expires);
|
||||
void refresh(const Resource&, optional<SystemTimePoint> expires);
|
||||
|
||||
private:
|
||||
void initializeDatabase();
|
||||
|
||||
@@ -44,7 +44,6 @@ v8::Handle<v8::Object> NodeRequest::Create(const mbgl::Resource& resource, mbgl:
|
||||
|
||||
NAN_METHOD(NodeRequest::Respond) {
|
||||
using Error = mbgl::Response::Error;
|
||||
using Milliseconds = mbgl::Milliseconds;
|
||||
|
||||
mbgl::Response response;
|
||||
|
||||
@@ -80,14 +79,14 @@ NAN_METHOD(NodeRequest::Respond) {
|
||||
if (Nan::Has(res, Nan::New("modified").ToLocalChecked()).FromJust()) {
|
||||
const double modified = Nan::Get(res, Nan::New("modified").ToLocalChecked()).ToLocalChecked()->ToNumber()->Value();
|
||||
if (!std::isnan(modified)) {
|
||||
response.modified = mbgl::asSeconds(Milliseconds(Milliseconds::rep(modified)));
|
||||
response.modified = mbgl::SystemClock::from_time_t(modified / 1000);
|
||||
}
|
||||
}
|
||||
|
||||
if (Nan::Has(res, Nan::New("expires").ToLocalChecked()).FromJust()) {
|
||||
const double expires = Nan::Get(res, Nan::New("expires").ToLocalChecked()).ToLocalChecked()->ToNumber()->Value();
|
||||
if (!std::isnan(expires)) {
|
||||
response.expires = mbgl::asSeconds(Milliseconds(Milliseconds::rep(expires)));
|
||||
response.expires = mbgl::SystemClock::from_time_t(expires / 1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ std::unique_ptr<FileRequest> AnnotationTileMonitor::monitorTile(const GeometryTi
|
||||
}
|
||||
|
||||
void AnnotationTileMonitor::update(std::unique_ptr<GeometryTile> tile) {
|
||||
callback(nullptr, std::move(tile), Seconds::zero(), Seconds::zero());
|
||||
callback(nullptr, std::move(tile), {}, {});
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -55,8 +55,8 @@ public:
|
||||
|
||||
using Callback = std::function<void (std::exception_ptr,
|
||||
std::unique_ptr<GeometryTile>,
|
||||
Seconds modified,
|
||||
Seconds expires)>;
|
||||
optional<SystemTimePoint> modified,
|
||||
optional<SystemTimePoint> expires)>;
|
||||
/*
|
||||
* Monitor the tile held by this object for changes. When the tile is loaded for the first time,
|
||||
* or updates, the callback is executed. If an error occurs, the first parameter will be set.
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/util/optional.hpp>
|
||||
#include <mbgl/map/tile_id.hpp>
|
||||
#include <mbgl/renderer/bucket.hpp>
|
||||
#include <mbgl/text/placement_config.hpp>
|
||||
@@ -91,8 +92,8 @@ public:
|
||||
void dumpDebugLogs() const;
|
||||
|
||||
const TileID id;
|
||||
Seconds modified = Seconds::zero();
|
||||
Seconds expires = Seconds::zero();
|
||||
optional<SystemTimePoint> modified;
|
||||
optional<SystemTimePoint> expires;
|
||||
|
||||
// Contains the tile ID string for painting debug information.
|
||||
std::unique_ptr<DebugBucket> debugBucket;
|
||||
|
||||
@@ -29,8 +29,8 @@ VectorTileData::VectorTileData(const TileID& id_,
|
||||
state = State::loading;
|
||||
tileRequest = monitor->monitorTile([callback, this](std::exception_ptr err,
|
||||
std::unique_ptr<GeometryTile> tile,
|
||||
Seconds modified_,
|
||||
Seconds expires_) {
|
||||
optional<SystemTimePoint> modified_,
|
||||
optional<SystemTimePoint> expires_) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
DebugBucket::DebugBucket(const TileID id, const TileData::State state_, Seconds modified_, Seconds expires_, MapDebugOptions debugMode_)
|
||||
DebugBucket::DebugBucket(const TileID id, const TileData::State state_, optional<SystemTimePoint> modified_, optional<SystemTimePoint> expires_, MapDebugOptions debugMode_)
|
||||
: state(state_),
|
||||
modified(modified_),
|
||||
expires(expires_),
|
||||
@@ -22,11 +22,11 @@ DebugBucket::DebugBucket(const TileID id, const TileData::State state_, Seconds
|
||||
baseline += 200;
|
||||
}
|
||||
|
||||
if (debugMode & MapDebugOptions::Timestamps && modified > Seconds::zero() && expires > Seconds::zero()) {
|
||||
const std::string modifiedText = "modified: " + util::iso8601(modified.count());
|
||||
if (debugMode & MapDebugOptions::Timestamps && modified && expires) {
|
||||
const std::string modifiedText = "modified: " + util::iso8601(SystemClock::to_time_t(*modified));
|
||||
fontBuffer.addText(modifiedText.c_str(), 50, baseline, 5);
|
||||
|
||||
const std::string expiresText = "expires: " + util::iso8601(expires.count());
|
||||
const std::string expiresText = "expires: " + util::iso8601(SystemClock::to_time_t(*expires));
|
||||
fontBuffer.addText(expiresText.c_str(), 50, baseline + 200, 5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,14 +13,17 @@ class PlainShader;
|
||||
|
||||
class DebugBucket : private util::noncopyable {
|
||||
public:
|
||||
DebugBucket(TileID id, TileData::State, Seconds modified, Seconds expires, MapDebugOptions);
|
||||
DebugBucket(TileID id, TileData::State,
|
||||
optional<SystemTimePoint> modified,
|
||||
optional<SystemTimePoint> expires,
|
||||
MapDebugOptions);
|
||||
|
||||
void drawLines(PlainShader& shader);
|
||||
void drawPoints(PlainShader& shader);
|
||||
|
||||
const TileData::State state;
|
||||
const Seconds modified;
|
||||
const Seconds expires;
|
||||
const optional<SystemTimePoint> modified;
|
||||
const optional<SystemTimePoint> expires;
|
||||
const MapDebugOptions debugMode;
|
||||
|
||||
private:
|
||||
|
||||
@@ -25,8 +25,8 @@ void Painter::renderDebugText(TileData& tileData, const mat4 &matrix) {
|
||||
config.depthTest = GL_FALSE;
|
||||
|
||||
if (!tileData.debugBucket || tileData.debugBucket->state != tileData.getState()
|
||||
|| tileData.debugBucket->modified != tileData.modified
|
||||
|| tileData.debugBucket->expires != tileData.expires
|
||||
|| !(tileData.debugBucket->modified == tileData.modified)
|
||||
|| !(tileData.debugBucket->expires == tileData.expires)
|
||||
|| tileData.debugBucket->debugMode != data.getDebug()) {
|
||||
tileData.debugBucket = std::make_unique<DebugBucket>(tileData.id, tileData.getState(), tileData.modified, tileData.expires, data.getDebug());
|
||||
}
|
||||
|
||||
@@ -5,15 +5,19 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
Seconds HTTPRequestBase::parseCacheControl(const char *value) {
|
||||
if (value) {
|
||||
const auto cacheControl = http::CacheControl::parse(value);
|
||||
if (cacheControl.maxAge) {
|
||||
return toSeconds(SystemClock::now()) + Seconds(*cacheControl.maxAge);
|
||||
}
|
||||
optional<SystemTimePoint> HTTPRequestBase::parseCacheControl(const char *value) {
|
||||
if (!value) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return Seconds::zero();
|
||||
const auto cacheControl = http::CacheControl::parse(value);
|
||||
if (!cacheControl.maxAge) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// Round trip through time_t to truncate fractional seconds.
|
||||
return SystemClock::from_time_t(SystemClock::to_time_t(
|
||||
SystemClock::now() + std::chrono::seconds(*cacheControl.maxAge)));
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/util/optional.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
@@ -27,7 +28,7 @@ public:
|
||||
virtual void cancel() { cancelled = true; };
|
||||
|
||||
protected:
|
||||
static Seconds parseCacheControl(const char *value);
|
||||
static optional<SystemTimePoint> parseCacheControl(const char *value);
|
||||
|
||||
std::string url;
|
||||
Callback notify;
|
||||
|
||||
@@ -120,7 +120,7 @@ void GeoJSONTileMonitor::setGeoJSONVT(mapbox::geojsonvt::GeoJSONVT* vt) {
|
||||
void GeoJSONTileMonitor::update() {
|
||||
if (geojsonvt) {
|
||||
auto tile = convertTile(geojsonvt->getTile(tileID.z, tileID.x, tileID.y));
|
||||
callback(nullptr, std::move(tile), Seconds::zero(), Seconds::zero());
|
||||
callback(nullptr, std::move(tile), {}, {});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ TEST_F(Storage, CacheResponse) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Response 1", *res.data);
|
||||
EXPECT_LT(Seconds::zero(), res.expires);
|
||||
EXPECT_EQ(Seconds::zero(), res.modified);
|
||||
EXPECT_EQ("", res.etag);
|
||||
EXPECT_TRUE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
response = res;
|
||||
|
||||
// Now test that we get the same values as in the previous request. If we'd go to the server
|
||||
@@ -78,9 +78,9 @@ TEST_F(Storage, CacheNotFound) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("existing data", *res.data);
|
||||
EXPECT_EQ(Seconds::zero(), res.expires);
|
||||
EXPECT_EQ(Seconds::zero(), res.modified);
|
||||
EXPECT_EQ("", res.etag);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
} else if (counter == 1) {
|
||||
EXPECT_NE(nullptr, res.error);
|
||||
EXPECT_EQ(Response::Error::Reason::NotFound, res.error->reason);
|
||||
@@ -135,9 +135,9 @@ TEST_F(Storage, DontCacheConnectionErrors) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("existing data", *res.data);
|
||||
EXPECT_EQ(Seconds::zero(), res.expires);
|
||||
EXPECT_EQ(Seconds::zero(), res.modified);
|
||||
EXPECT_EQ("", res.etag);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
} else if (counter == 1) {
|
||||
EXPECT_NE(nullptr, res.error);
|
||||
EXPECT_EQ(Response::Error::Reason::Connection, res.error->reason);
|
||||
@@ -190,9 +190,9 @@ TEST_F(Storage, DontCacheServerErrors) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("existing data", *res.data);
|
||||
EXPECT_EQ(Seconds::zero(), res.expires);
|
||||
EXPECT_EQ(Seconds::zero(), res.modified);
|
||||
EXPECT_EQ("", res.etag);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
} else if (counter == 1) {
|
||||
EXPECT_NE(nullptr, res.error);
|
||||
EXPECT_EQ(Response::Error::Reason::Server, res.error->reason);
|
||||
|
||||
@@ -26,9 +26,9 @@ TEST_F(Storage, CacheRevalidateSame) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Response", *res.data);
|
||||
EXPECT_EQ(Seconds::zero(), res.expires);
|
||||
EXPECT_EQ(Seconds::zero(), res.modified);
|
||||
EXPECT_EQ("snowfall", res.etag);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_EQ("snowfall", *res.etag);
|
||||
|
||||
// Second request returns the cached response, then immediately revalidates.
|
||||
req2 = fs.request(revalidateSame, [&, res](Response res2) {
|
||||
@@ -42,10 +42,10 @@ TEST_F(Storage, CacheRevalidateSame) {
|
||||
EXPECT_TRUE(res2.notModified);
|
||||
ASSERT_TRUE(res2.data.get());
|
||||
EXPECT_EQ("Response", *res2.data);
|
||||
EXPECT_LT(Seconds::zero(), res2.expires);
|
||||
EXPECT_EQ(Seconds::zero(), res2.modified);
|
||||
EXPECT_TRUE(bool(res2.expires));
|
||||
EXPECT_FALSE(bool(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("snowfall", *res2.etag);
|
||||
|
||||
loop.stop();
|
||||
CacheRevalidateSame.finish();
|
||||
@@ -78,9 +78,9 @@ TEST_F(Storage, CacheRevalidateModified) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Response", *res.data);
|
||||
EXPECT_EQ(Seconds::zero(), res.expires);
|
||||
EXPECT_EQ(1420070400, res.modified.count());
|
||||
EXPECT_EQ("", res.etag);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_EQ(SystemClock::from_time_t(1420070400), *res.modified);
|
||||
EXPECT_FALSE(res.etag);
|
||||
|
||||
// Second request returns the cached response, then immediately revalidates.
|
||||
req2 = fs.request(revalidateModified, [&, res](Response res2) {
|
||||
@@ -94,9 +94,9 @@ TEST_F(Storage, CacheRevalidateModified) {
|
||||
EXPECT_TRUE(res2.notModified);
|
||||
ASSERT_TRUE(res2.data.get());
|
||||
EXPECT_EQ("Response", *res2.data);
|
||||
EXPECT_LT(Seconds::zero(), res2.expires);
|
||||
EXPECT_EQ(1420070400, res2.modified.count());
|
||||
EXPECT_EQ("", res2.etag);
|
||||
EXPECT_TRUE(bool(res2.expires));
|
||||
EXPECT_EQ(SystemClock::from_time_t(1420070400), *res2.modified);
|
||||
EXPECT_FALSE(res2.etag);
|
||||
|
||||
loop.stop();
|
||||
CacheRevalidateModified.finish();
|
||||
@@ -128,9 +128,9 @@ TEST_F(Storage, CacheRevalidateEtag) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Response 1", *res.data);
|
||||
EXPECT_EQ(Seconds::zero(), res.expires);
|
||||
EXPECT_EQ(Seconds::zero(), res.modified);
|
||||
EXPECT_EQ("response-1", res.etag);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_EQ("response-1", *res.etag);
|
||||
|
||||
// Second request returns the cached response, then immediately revalidates.
|
||||
req2 = fs.request(revalidateEtag, [&, res](Response res2) {
|
||||
@@ -144,9 +144,9 @@ TEST_F(Storage, CacheRevalidateEtag) {
|
||||
ASSERT_TRUE(res2.data.get());
|
||||
EXPECT_NE(res.data, res2.data);
|
||||
EXPECT_EQ("Response 2", *res2.data);
|
||||
EXPECT_EQ(Seconds::zero(), res2.expires);
|
||||
EXPECT_EQ(Seconds::zero(), res2.modified);
|
||||
EXPECT_EQ("response-2", res2.etag);
|
||||
EXPECT_FALSE(bool(res2.expires));
|
||||
EXPECT_FALSE(bool(res2.modified));
|
||||
EXPECT_EQ("response-2", *res2.etag);
|
||||
|
||||
loop.stop();
|
||||
CacheRevalidateEtag.finish();
|
||||
|
||||
@@ -39,8 +39,8 @@ void insertTile(mbgl::SQLiteCache* cache, unsigned id, uint64_t size) {
|
||||
auto url = std::string("http://tile") + mbgl::util::toString(id);
|
||||
|
||||
Response response;
|
||||
response.modified = toSeconds(SystemClock::now());
|
||||
response.expires = toSeconds(SystemClock::now()) + Seconds(5000);
|
||||
response.modified = SystemClock::now();
|
||||
response.expires = SystemClock::now() + Seconds(5000);
|
||||
response.etag = url;
|
||||
|
||||
auto data = std::make_shared<std::string>(size, 0);
|
||||
@@ -62,8 +62,8 @@ void refreshTile(mbgl::SQLiteCache* cache, unsigned id) {
|
||||
auto url = std::string("http://tile") + mbgl::util::toString(id);
|
||||
|
||||
Response response;
|
||||
response.modified = toSeconds(SystemClock::now());
|
||||
response.expires = toSeconds(SystemClock::now()) + Seconds(5000);
|
||||
response.modified = SystemClock::now();
|
||||
response.expires = SystemClock::now() + Seconds(5000);
|
||||
response.notModified = true;
|
||||
|
||||
Resource resource{ Resource::Kind::Tile, url };
|
||||
|
||||
@@ -27,7 +27,7 @@ void checkRendering(Map& map,
|
||||
Response expiredItem(const std::string& path) {
|
||||
Response response;
|
||||
response.data = std::make_shared<std::string>(util::read_file("test/fixtures/"s + path));
|
||||
response.expires = 0s;
|
||||
response.expires = SystemClock::from_time_t(0);
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
@@ -257,7 +257,7 @@ TEST_F(Storage, DatabaseLockedRefresh) {
|
||||
// Then, try to refresh it.
|
||||
Log::setObserver(std::make_unique<FixtureLogObserver>());
|
||||
|
||||
cache.refresh({ Resource::Unknown, "mapbox://test" }, Seconds::zero());
|
||||
cache.refresh({ Resource::Unknown, "mapbox://test" }, {});
|
||||
cache.get({ Resource::Unknown, "mapbox://test" }, [] (std::unique_ptr<Response> res) {
|
||||
EXPECT_EQ(nullptr, res.get());
|
||||
});
|
||||
|
||||
@@ -43,9 +43,9 @@ TEST_F(Storage, HTTPCancelMultiple) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
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);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
HTTPCancelMultiple.finish();
|
||||
});
|
||||
|
||||
@@ -28,9 +28,9 @@ TEST_F(Storage, HTTPTemporaryError) {
|
||||
EXPECT_EQ("HTTP status code 500", res.error->message);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("", *res.data);
|
||||
EXPECT_EQ(Seconds::zero(), res.expires);
|
||||
EXPECT_EQ(Seconds::zero(), res.modified);
|
||||
EXPECT_EQ("", res.etag);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
} break;
|
||||
case 1: {
|
||||
req1.reset();
|
||||
@@ -40,9 +40,9 @@ TEST_F(Storage, HTTPTemporaryError) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
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);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
HTTPTemporaryError.finish();
|
||||
} break;
|
||||
@@ -82,9 +82,9 @@ TEST_F(Storage, HTTPConnectionError) {
|
||||
FAIL();
|
||||
#endif
|
||||
ASSERT_FALSE(res.data.get());
|
||||
EXPECT_EQ(Seconds::zero(), res.expires);
|
||||
EXPECT_EQ(Seconds::zero(), res.modified);
|
||||
EXPECT_EQ("", res.etag);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
|
||||
if (counter == 2) {
|
||||
req2.reset();
|
||||
|
||||
@@ -21,9 +21,9 @@ TEST_F(Storage, HTTPExpiresParsing) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
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);
|
||||
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();
|
||||
});
|
||||
@@ -47,9 +47,9 @@ TEST_F(Storage, HTTPCacheControlParsing) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Hello World!", *res.data);
|
||||
EXPECT_GT(2, std::abs(res.expires.count() - now.count() - 120)) << "Expiration date isn't about 120 seconds in the future";
|
||||
EXPECT_EQ(Seconds::zero(), res.modified);
|
||||
EXPECT_EQ("", res.etag);
|
||||
EXPECT_GT(2, std::abs(toSeconds(*res.expires).count() - now.count() - 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();
|
||||
});
|
||||
|
||||
@@ -36,9 +36,9 @@ TEST_F(Storage, HTTPIssue1369) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
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);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
HTTPIssue1369.finish();
|
||||
});
|
||||
|
||||
@@ -27,9 +27,9 @@ TEST_F(Storage, HTTPLoad) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ(std::string("Request ") + std::to_string(current), *res.data);
|
||||
EXPECT_EQ(Seconds::zero(), res.expires);
|
||||
EXPECT_EQ(Seconds::zero(), res.modified);
|
||||
EXPECT_EQ("", res.etag);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
|
||||
if (number <= max) {
|
||||
req(i);
|
||||
|
||||
@@ -19,9 +19,9 @@ TEST_F(Storage, HTTPOtherLoop) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
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);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
HTTPOtherLoop.finish();
|
||||
});
|
||||
|
||||
@@ -23,9 +23,9 @@ TEST_F(Storage, HTTPTest) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
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);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
HTTPTest.finish();
|
||||
});
|
||||
@@ -50,9 +50,9 @@ TEST_F(Storage, HTTP404) {
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Cannot GET /doesnotexist\n", *res.data);
|
||||
EXPECT_EQ("HTTP status code 404", res.error->message);
|
||||
EXPECT_EQ(Seconds::zero(), res.expires);
|
||||
EXPECT_EQ(Seconds::zero(), res.modified);
|
||||
EXPECT_EQ("", res.etag);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
HTTP404.finish();
|
||||
});
|
||||
@@ -77,9 +77,9 @@ TEST_F(Storage, HTTP500) {
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Server Error!", *res.data);
|
||||
EXPECT_EQ("HTTP status code 500", res.error->message);
|
||||
EXPECT_EQ(Seconds::zero(), res.expires);
|
||||
EXPECT_EQ(Seconds::zero(), res.modified);
|
||||
EXPECT_EQ("", res.etag);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
HTTP500.finish();
|
||||
});
|
||||
|
||||
@@ -28,9 +28,9 @@ TEST_F(Storage, HTTPNetworkStatusChange) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
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);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
loop.stop();
|
||||
HTTPNetworkStatusChange.finish();
|
||||
});
|
||||
@@ -87,9 +87,9 @@ TEST_F(Storage, HTTPNetworkStatusChangePreempt) {
|
||||
FAIL();
|
||||
#endif
|
||||
ASSERT_FALSE(res.data.get());
|
||||
EXPECT_EQ(Seconds::zero(), res.expires);
|
||||
EXPECT_EQ(Seconds::zero(), res.modified);
|
||||
EXPECT_EQ("", res.etag);
|
||||
EXPECT_FALSE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
|
||||
if (counter++ == 1) {
|
||||
req.reset();
|
||||
|
||||
@@ -21,9 +21,9 @@ TEST_F(Storage, HTTPTimeout) {
|
||||
EXPECT_EQ(nullptr, res.error);
|
||||
ASSERT_TRUE(res.data.get());
|
||||
EXPECT_EQ("Hello World!", *res.data);
|
||||
EXPECT_LT(Seconds::zero(), res.expires);
|
||||
EXPECT_EQ(Seconds::zero(), res.modified);
|
||||
EXPECT_EQ("", res.etag);
|
||||
EXPECT_TRUE(bool(res.expires));
|
||||
EXPECT_FALSE(bool(res.modified));
|
||||
EXPECT_FALSE(bool(res.etag));
|
||||
if (counter == 4) {
|
||||
req.reset();
|
||||
loop.stop();
|
||||
|
||||
Reference in New Issue
Block a user