mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-28 12:05:06 +00:00
445 lines
21 KiB
C++
445 lines
21 KiB
C++
#include "prx/libc/include/general/VabiMacros.hpp"
|
|
#include "prx/libSceHttpCache/libSceHttpCache.hpp"
|
|
#include "prx/libSceRtc/libSceRtc.hpp"
|
|
#include "prx/libSceUserService/libSceUserService.hpp"
|
|
#include <array>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <cstdlib>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
namespace {
|
|
|
|
using Header = HttpCacheHeader;
|
|
using Request = HttpCacheRequest;
|
|
using ResponseHeader = HttpCacheResponseHeader;
|
|
using Response = HttpCacheResponse;
|
|
using QuotaEntry = HttpCacheQuotaEntry;
|
|
using Quota = HttpCacheQuota;
|
|
|
|
}
|
|
|
|
namespace {
|
|
|
|
constexpr int NotFound = static_cast<int>(0x817a0011);
|
|
constexpr int InvalidValue = static_cast<int>(0x817a0012);
|
|
constexpr int InvalidUser = static_cast<int>(0x817a0013);
|
|
constexpr int TooManyCaches = static_cast<int>(0x817a0002);
|
|
constexpr int UserServiceAlreadyInitialized = static_cast<int>(0x80960003);
|
|
constexpr std::int32_t InitialUser = 0x10000000;
|
|
|
|
void Require(bool value) { if (!value) std::abort(); }
|
|
|
|
void TestWithoutCache() {
|
|
Require(sceHttpCacheTerm(1) == NotFound);
|
|
Require(sceHttpCacheCreateRequest(1, -1) == NotFound);
|
|
Require(sceHttpCacheClearAll(1, -1) == NotFound);
|
|
Require(sceHttpCacheCompleteRequest(0x01000001) == NotFound);
|
|
Require(sceHttpCacheDeleteRequest(0x01000001) == NotFound);
|
|
Require(sceHttpCacheSetCacheSharing(1) == 0);
|
|
Require(sceHttpCacheSystemSendStatistics() == 0);
|
|
Require(sceHttpCacheSystemTerm() == 0);
|
|
Require(sceHttpCacheDebugSetUrl() == 0);
|
|
Require(sceHttpCacheRegisterCacheInfoUrl(nullptr) == InvalidValue);
|
|
}
|
|
|
|
void TestRequests() {
|
|
const int cache = sceHttpCacheInit(0);
|
|
const int second = sceHttpCacheInit(0x10000);
|
|
Require(cache == 1 && second == 2);
|
|
Require(sceUserServiceInitialize(nullptr) == UserServiceAlreadyInitialized);
|
|
Require(sceHttpCacheCreateRequest(9, -1) == NotFound);
|
|
Require(sceHttpCacheCreateRequest(cache, 5) == InvalidUser);
|
|
Require(sceHttpCacheCreateRequest(cache, 0x10000001) == InvalidUser);
|
|
const int request = sceHttpCacheCreateRequest(cache, -1);
|
|
Require(request == 0x01000001);
|
|
Require(sceHttpCacheCreateRequest(cache, 255) == 0x01000002);
|
|
Require(sceHttpCacheCreateRequest(cache, InitialUser) == 0x01000003);
|
|
Require(sceHttpCacheCreateRequest(cache, 0xfe) == 0x01000004);
|
|
Require(sceHttpCacheCreateRequest(second, -1) == 0x02000001);
|
|
Require(sceHttpCacheCompleteRequest(request) == 0);
|
|
Require(sceHttpCacheCompleteRequest(0x01000099) == NotFound);
|
|
Require(sceHttpCacheCompleteRequest(0x09000001) == NotFound);
|
|
std::array<std::uint8_t, 4> buffer{1, 2, 3, 4};
|
|
Require(sceHttpCacheReadData(request, 4, nullptr) == InvalidValue);
|
|
Require(sceHttpCacheReadData(request, 0, nullptr) == 0);
|
|
Require(sceHttpCacheReadData(request, buffer.size(), buffer.data()) == 0);
|
|
Require(buffer[0] == 1 && buffer[3] == 4);
|
|
Require(sceHttpCacheReadData(0x01000099, buffer.size(), buffer.data()) == NotFound);
|
|
Require(sceHttpCacheSetData(request, nullptr, 4) == InvalidValue);
|
|
Require(sceHttpCacheSetData(0x01000099, buffer.data(), buffer.size()) == NotFound);
|
|
Require(sceHttpCacheSetData(request, buffer.data(), buffer.size()) == 0);
|
|
Request query{};
|
|
Response response{};
|
|
Request next{};
|
|
ResponseHeader header{};
|
|
std::int32_t result = 0;
|
|
Require(sceHttpCacheRetrieve(request, nullptr, &response, &next, &result) == InvalidValue);
|
|
Require(sceHttpCacheRetrieve(request, &query, &response, &next, nullptr) == InvalidValue);
|
|
Require(sceHttpCacheRetrieve(0x01000099, &query, &response, &next, &result) == NotFound);
|
|
const Header nullName[]{{nullptr, "a"}};
|
|
query.url = "http://a/";
|
|
query.headerCount = 1;
|
|
Require(sceHttpCacheRetrieve(request, &query, &response, &next, &result) == InvalidValue);
|
|
query.headers = nullName;
|
|
Require(sceHttpCacheRetrieve(request, &query, &response, &next, &result) == InvalidValue);
|
|
query.headerCount = 0;
|
|
result = 7;
|
|
Require(sceHttpCacheRetrieve(request, &query, &response, &next, &result) == 0 && result == 0);
|
|
Require(sceHttpCacheRevalidate(request, nullptr, &response, &result) == InvalidValue);
|
|
Require(sceHttpCacheRevalidate(request, &header, &response, nullptr) == InvalidValue);
|
|
Require(sceHttpCacheRevalidate(0x01000099, &header, &response, &result) == NotFound);
|
|
result = 7;
|
|
Require(sceHttpCacheRevalidate(request, &header, &response, &result) == 0 && result == 0);
|
|
Require(sceHttpCacheSetResponseHeader(request, nullptr) == InvalidValue);
|
|
Require(sceHttpCacheSetResponseHeader(0x01000099, &header) == NotFound);
|
|
Require(sceHttpCacheSetResponseHeader(request, &header) == 0);
|
|
header.headerCount = 1;
|
|
Require(sceHttpCacheSetResponseHeader(request, &header) == InvalidValue);
|
|
Require(sceHttpCacheRevalidate(request, &header, &response, &result) == InvalidValue);
|
|
header.headerCount = 0;
|
|
Require(sceHttpCacheDeleteRequest(0x01000099) == 0);
|
|
Require(sceHttpCacheDeleteRequest(0x09000001) == NotFound);
|
|
Require(sceHttpCacheDeleteRequest(request) == 0);
|
|
Require(sceHttpCacheCompleteRequest(request) == NotFound);
|
|
Require(sceHttpCacheReadData(request, 0, nullptr) == NotFound);
|
|
Require(sceHttpCacheCreateRequest(cache, -1) == 0x01000005);
|
|
Require(sceHttpCacheClearAll(cache, -1) == 0);
|
|
Require(sceHttpCacheTerm(second) == 0);
|
|
Require(sceHttpCacheCompleteRequest(0x02000001) == NotFound);
|
|
Require(sceHttpCacheTerm(cache) == 0);
|
|
Require(sceHttpCacheTerm(cache) == NotFound);
|
|
Require(sceUserServiceInitialize(nullptr) == 0);
|
|
Require(sceUserServiceTerminate() == 0);
|
|
}
|
|
|
|
void TestCacheArguments() {
|
|
const int cache = sceHttpCacheInit(0);
|
|
Require(cache == 3);
|
|
Require(sceHttpCacheCreateRequest(cache, -1) == 0x03000001);
|
|
Require(sceHttpCacheSetQuota(9, nullptr) == NotFound);
|
|
Require(sceHttpCacheSetQuota(cache, nullptr) == InvalidValue);
|
|
Quota quota{1, nullptr};
|
|
Require(sceHttpCacheSetQuota(cache, "a) == InvalidValue);
|
|
QuotaEntry entries[]{{"", 1}};
|
|
quota.entries = entries;
|
|
Require(sceHttpCacheSetQuota(cache, "a) == InvalidValue);
|
|
entries[0].name = "a";
|
|
const std::int32_t users[]{InitialUser};
|
|
Require(sceHttpCacheClearAllUserTags(9, users, 1) == NotFound);
|
|
Require(sceHttpCacheClearAllUserTags(cache, nullptr, 1) == InvalidValue);
|
|
Require(sceHttpCacheClearAllUserTags(cache, users, 21) == InvalidValue);
|
|
Require(sceHttpCacheTerm(cache) == 0);
|
|
}
|
|
|
|
void TestCacheLimit() {
|
|
std::vector<int> caches;
|
|
for (int i = 0; i < 127; ++i) {
|
|
const int cache = sceHttpCacheInit(0);
|
|
Require(cache >= 1 && cache <= 127);
|
|
caches.push_back(cache);
|
|
}
|
|
Require(caches.front() == 4 && caches[123] == 127 && caches[124] == 1 && caches.back() == 3);
|
|
Require(sceHttpCacheInit(0) == TooManyCaches);
|
|
Require(sceHttpCacheTerm(caches[10]) == 0);
|
|
Require(sceHttpCacheInit(0) == caches[10]);
|
|
for (const int cache : caches) Require(sceHttpCacheTerm(cache) == 0);
|
|
}
|
|
|
|
constexpr std::uint64_t TicksPerSecond = 1000000;
|
|
|
|
void Advance(std::uint64_t seconds) {
|
|
RtcTick tick{};
|
|
Require(sceRtcGetCurrentTick(&tick) == 0);
|
|
tick.tick += seconds * TicksPerSecond;
|
|
Require(sceRtcSetCurrentTick(&tick) == 0);
|
|
}
|
|
|
|
std::string_view Value(const Response& response, std::string_view name) {
|
|
for (std::size_t i = 0; i < response.headerCount; ++i) {
|
|
if (name == response.headers[i].name) return response.headers[i].value;
|
|
}
|
|
return {};
|
|
}
|
|
|
|
std::string_view Value(const Request& request, std::string_view name) {
|
|
for (std::size_t i = 0; i < request.headerCount; ++i) {
|
|
if (name == request.headers[i].name) return request.headers[i].value;
|
|
}
|
|
return {};
|
|
}
|
|
|
|
std::string ReadAll(int request) {
|
|
std::string body;
|
|
char buffer[4];
|
|
for (;;) {
|
|
const int read = sceHttpCacheReadData(request, sizeof(buffer), buffer);
|
|
Require(read >= 0 && read <= static_cast<int>(sizeof(buffer)));
|
|
if (read == 0) return body;
|
|
body.append(buffer, static_cast<std::size_t>(read));
|
|
}
|
|
}
|
|
|
|
struct Exchange {
|
|
int cache;
|
|
std::int32_t user = InitialUser;
|
|
std::uint32_t method = 0;
|
|
std::vector<Header> requestHeaders;
|
|
Request next{};
|
|
Response response{};
|
|
std::int32_t result = -1;
|
|
int request = 0;
|
|
|
|
int Retrieve(const char* url) {
|
|
request = sceHttpCacheCreateRequest(cache, user);
|
|
Require(request > 0);
|
|
Request query{method, 0, url, requestHeaders.size(), requestHeaders.data()};
|
|
next = Request{};
|
|
response = Response{};
|
|
result = -1;
|
|
return sceHttpCacheRetrieve(request, &query, &response, &next, &result);
|
|
}
|
|
|
|
void Store(std::uint32_t status, std::vector<Header> headers, std::string_view body) {
|
|
ResponseHeader header{status, 0, headers.size(), headers.data()};
|
|
Require(sceHttpCacheSetResponseHeader(request, &header) == 0);
|
|
Require(sceHttpCacheSetData(request, body.data(), body.size()) == 0);
|
|
Require(sceHttpCacheReadData(request, 0, nullptr) == 0);
|
|
Require(sceHttpCacheCompleteRequest(request) == 0);
|
|
}
|
|
|
|
int Revalidate(std::uint32_t status, std::vector<Header> headers) {
|
|
ResponseHeader header{status, 0, headers.size(), headers.data()};
|
|
response = Response{};
|
|
result = -1;
|
|
return sceHttpCacheRevalidate(request, &header, &response, &result);
|
|
}
|
|
|
|
void Done() {
|
|
Require(sceHttpCacheDeleteRequest(request) == 0);
|
|
}
|
|
};
|
|
|
|
void Cached(Exchange& exchange, const char* url, std::vector<Header> headers, std::string_view body) {
|
|
Require(exchange.Retrieve(url) == 0 && exchange.result == 0);
|
|
exchange.Store(200, std::move(headers), body);
|
|
exchange.Done();
|
|
}
|
|
|
|
void RequireMiss(Exchange& exchange, const char* url) {
|
|
Require(exchange.Retrieve(url) == 0 && exchange.result == 0);
|
|
exchange.Done();
|
|
}
|
|
|
|
void TestStoreAndHit() {
|
|
Exchange exchange{sceHttpCacheInit(0)};
|
|
exchange.requestHeaders = {{"User-Agent", "agent"}};
|
|
Require(exchange.Retrieve("http://store/a") == 0 && exchange.result == 0);
|
|
exchange.Store(200, {{"Cache-Control", "max-age=3600"}, {"ETag", "\"v1\""}}, "hello world");
|
|
Require(sceHttpCacheSetData(exchange.request, "!", 1) == 0);
|
|
exchange.Done();
|
|
Require(exchange.Retrieve("http://store/a") == 0 && exchange.result == 1);
|
|
Require(exchange.response.statusCode == 200 && exchange.response.headerCount == 2 && exchange.response.contentLength == 11);
|
|
Require(Value(exchange.response, "Cache-Control") == "max-age=3600" && Value(exchange.response, "ETag") == "\"v1\"");
|
|
Require(ReadAll(exchange.request) == "hello world");
|
|
Request again{0, 0, "http://store/a", 0, nullptr};
|
|
std::int32_t result = -1;
|
|
Require(sceHttpCacheRetrieve(exchange.request, &again, nullptr, &exchange.next, &result) == InvalidValue && result == 1);
|
|
exchange.Done();
|
|
exchange.requestHeaders = {{"User-Agent", "other"}};
|
|
RequireMiss(exchange, "http://store/a");
|
|
exchange.requestHeaders = {{"user-agent", "agent"}, {"If-None-Match", "\"v1\""}};
|
|
RequireMiss(exchange, "http://store/a");
|
|
exchange.requestHeaders = {{"User-Agent", "agent"}};
|
|
exchange.method = 1;
|
|
RequireMiss(exchange, "http://store/a");
|
|
exchange.method = 0;
|
|
exchange.user = -1;
|
|
RequireMiss(exchange, "http://store/a");
|
|
Cached(exchange, "http://store/system", {{"Cache-Control", "max-age=3600"}}, "x");
|
|
RequireMiss(exchange, "http://store/system");
|
|
exchange.user = InitialUser;
|
|
Require(exchange.Retrieve("http://store/a") == 0 && exchange.result == 1);
|
|
exchange.Done();
|
|
Require(exchange.Retrieve("http://store/a") == 0 && exchange.result == 1);
|
|
exchange.Store(200, {{"Content-Type", "text/plain"}}, "uncacheable");
|
|
exchange.Done();
|
|
RequireMiss(exchange, "http://store/a");
|
|
Cached(exchange, "http://store/b", {{"Cache-Control", "no-store, max-age=60"}}, "x");
|
|
RequireMiss(exchange, "http://store/b");
|
|
Require(exchange.Retrieve("http://store/b") == 0 && exchange.result == 0);
|
|
exchange.Store(404, {{"Cache-Control", "max-age=60"}}, "x");
|
|
exchange.Done();
|
|
RequireMiss(exchange, "http://store/b");
|
|
Require(exchange.Retrieve("http://store/c") == 0 && exchange.result == 0);
|
|
ResponseHeader pending{200, 0, 1, nullptr};
|
|
Header maxAge[]{{"Cache-Control", "max-age=60"}};
|
|
pending.headers = maxAge;
|
|
Require(sceHttpCacheSetResponseHeader(exchange.request, &pending) == 0);
|
|
Require(sceHttpCacheSetData(exchange.request, "lost", 4) == 0);
|
|
exchange.Done();
|
|
RequireMiss(exchange, "http://store/c");
|
|
Cached(exchange, "http://store/d", {{"Expires", "x"}}, "expires");
|
|
Require(exchange.Retrieve("http://store/d") == 0 && exchange.result == 0);
|
|
exchange.Done();
|
|
Cached(exchange, "http://store/e", {{"Cache-Control", "max-age=60"}, {"Vary", "Accept-Language"}}, "en");
|
|
exchange.requestHeaders = {{"User-Agent", "agent"}, {"Accept-Language", "fr"}};
|
|
RequireMiss(exchange, "http://store/e");
|
|
exchange.requestHeaders = {{"User-Agent", "agent"}};
|
|
Require(exchange.Retrieve("http://store/e") == 0 && exchange.result == 1);
|
|
exchange.Done();
|
|
Require(sceHttpCacheClearAll(exchange.cache, -1) == 0);
|
|
Require(sceHttpCacheClearAll(exchange.cache, 5) == 0);
|
|
Require(exchange.Retrieve("http://store/e") == 0 && exchange.result == 1);
|
|
exchange.Done();
|
|
Require(sceHttpCacheTerm(exchange.cache) == 0);
|
|
exchange.cache = sceHttpCacheInit(0);
|
|
Require(exchange.Retrieve("http://store/e") == 0 && exchange.result == 1);
|
|
exchange.Done();
|
|
Require(sceHttpCacheClearAll(exchange.cache, InitialUser) == 0);
|
|
RequireMiss(exchange, "http://store/e");
|
|
Require(sceHttpCacheTerm(exchange.cache) == 0);
|
|
}
|
|
|
|
void TestLifetimeOrder() {
|
|
Exchange exchange{sceHttpCacheInit(0)};
|
|
Cached(exchange, "http://order/expires-later", {{"Date", "Sat, 01 Jan 2000 00:00:00 GMT"}, {"Expires", "Sat, 01 Jan 2000 01:00:00 GMT"}}, "x");
|
|
RequireMiss(exchange, "http://order/expires-later");
|
|
Cached(exchange, "http://order/expires-earlier", {{"Date", "Sat, 01 Jan 2000 01:00:00 GMT"}, {"Expires", "Sat, 01 Jan 2000 00:00:00 GMT"}}, "expired");
|
|
Require(exchange.Retrieve("http://order/expires-earlier") == 0 && exchange.result == 1);
|
|
Require(ReadAll(exchange.request) == "expired" && Value(exchange.response, "Warning").empty());
|
|
exchange.Done();
|
|
Cached(exchange, "http://order/modified-earlier", {{"Date", "Mon, 10 Jan 2000 00:00:00 GMT"}, {"Last-Modified", "Sat, 01 Jan 2000 00:00:00 GMT"}}, "x");
|
|
Require(exchange.Retrieve("http://order/modified-earlier") == 0 && exchange.result == 2);
|
|
Require(Value(exchange.next, "If-Modified-Since") == "Sat, 01 Jan 2000 00:00:00 GMT");
|
|
exchange.Done();
|
|
Cached(exchange, "http://order/modified-later", {{"Date", "Sat, 01 Jan 2000 00:00:00 GMT"}, {"Last-Modified", "Sun, 02 Jan 2000 00:00:00 GMT"}}, "modified");
|
|
Advance(400 * 24 * 3600);
|
|
Require(exchange.Retrieve("http://order/modified-later") == 0 && exchange.result == 1);
|
|
Require(ReadAll(exchange.request) == "modified" && !Value(exchange.response, "Warning").empty());
|
|
exchange.Done();
|
|
Require(sceHttpCacheTerm(exchange.cache) == 0);
|
|
}
|
|
|
|
void TestRevalidation() {
|
|
Exchange exchange{sceHttpCacheInit(0)};
|
|
Cached(exchange, "http://stale/a", {{"Cache-Control", "max-age=60"}, {"ETag", "e1"}, {"Last-Modified", "lm"}}, "old body");
|
|
Advance(120);
|
|
exchange.requestHeaders = {{"Accept", "*/*"}};
|
|
Require(exchange.Retrieve("http://stale/a") == 0 && exchange.result == 2);
|
|
Require(std::string_view(exchange.next.url) == "http://stale/a" && exchange.next.method == 0 && exchange.next.headerCount == 3);
|
|
Require(Value(exchange.next, "Accept") == "*/*" && Value(exchange.next, "If-Modified-Since") == "lm" && Value(exchange.next, "If-None-Match") == "e1");
|
|
Require(exchange.response.headers == nullptr);
|
|
Require(sceHttpCacheReadData(exchange.request, 0, nullptr) == 0);
|
|
Request query{0, 0, "http://stale/a", 0, nullptr};
|
|
std::int32_t result = -1;
|
|
Require(sceHttpCacheRetrieve(exchange.request, &query, nullptr, nullptr, &result) == InvalidValue && result == 2);
|
|
Require(exchange.Revalidate(304, {{"Cache-Control", "max-age=600"}, {"ETag", "e2"}, {"X-New", "1"}}) == 0 && exchange.result == 1);
|
|
Require(exchange.response.statusCode == 200 && exchange.response.contentLength == 8);
|
|
Require(Value(exchange.response, "Cache-Control") == "max-age=600" && Value(exchange.response, "ETag") == "e1" && Value(exchange.response, "X-New").empty());
|
|
Require(ReadAll(exchange.request) == "old body");
|
|
exchange.Done();
|
|
Advance(120);
|
|
Require(exchange.Retrieve("http://stale/a") == 0 && exchange.result == 1);
|
|
Require(ReadAll(exchange.request) == "old body");
|
|
exchange.Done();
|
|
exchange.requestHeaders = {{"Cache-Control", "no-cache"}};
|
|
Require(exchange.Retrieve("http://stale/a") == 0 && exchange.result == 2);
|
|
Require(exchange.Revalidate(200, {{"Cache-Control", "max-age=600"}, {"ETag", "e3"}}) == 0 && exchange.result == 0);
|
|
Require(exchange.response.headers == nullptr);
|
|
Require(sceHttpCacheSetData(exchange.request, "new body", 8) == 0);
|
|
Require(sceHttpCacheCompleteRequest(exchange.request) == 0);
|
|
exchange.Done();
|
|
exchange.requestHeaders = {{"Pragma", "no-cache"}};
|
|
Require(exchange.Retrieve("http://stale/a") == 0 && exchange.result == 2 && Value(exchange.next, "If-None-Match") == "e3");
|
|
exchange.Done();
|
|
exchange.requestHeaders = {};
|
|
Require(exchange.Retrieve("http://stale/a") == 0 && exchange.result == 1);
|
|
Require(ReadAll(exchange.request) == "new body");
|
|
exchange.Done();
|
|
Require(exchange.Retrieve("http://stale/a") == 0 && exchange.result == 1);
|
|
Require(exchange.Revalidate(304, {{"Cache-Control", "max-age=60"}}) == 0 && exchange.result == 0);
|
|
exchange.Done();
|
|
exchange.requestHeaders = {{"Cache-Control", "no-cache"}};
|
|
Require(exchange.Retrieve("http://stale/a") == 0 && exchange.result == 2);
|
|
Require(exchange.Revalidate(304, {{"ETag", "e3"}}) == 0 && exchange.result == 0);
|
|
exchange.Done();
|
|
exchange.requestHeaders = {};
|
|
RequireMiss(exchange, "http://stale/a");
|
|
Cached(exchange, "http://stale/b", {{"Cache-Control", "max-age=60"}, {"ETag", "b"}}, "b");
|
|
exchange.requestHeaders = {{"Cache-Control", "no-cache"}};
|
|
Require(exchange.Retrieve("http://stale/b") == 0 && exchange.result == 2);
|
|
Require(exchange.Revalidate(404, {{"Cache-Control", "max-age=60"}}) == 0 && exchange.result == 0);
|
|
exchange.Done();
|
|
exchange.requestHeaders = {};
|
|
RequireMiss(exchange, "http://stale/b");
|
|
Cached(exchange, "http://stale/c", {{"Cache-Control", "max-age=60"}}, "c");
|
|
Advance(120);
|
|
RequireMiss(exchange, "http://stale/c");
|
|
exchange.requestHeaders = {{"Cache-Control", "max-stale"}};
|
|
RequireMiss(exchange, "http://stale/c");
|
|
exchange.requestHeaders = {};
|
|
Cached(exchange, "http://stale/d", {{"Cache-Control", "max-age=60"}}, "d");
|
|
Advance(120);
|
|
exchange.requestHeaders = {{"Cache-Control", "max-stale"}};
|
|
Require(exchange.Retrieve("http://stale/d") == 0 && exchange.result == 1);
|
|
Require(Value(exchange.response, "Warning") == "110 - \"Response is Stale\"" && ReadAll(exchange.request) == "d");
|
|
exchange.Done();
|
|
exchange.requestHeaders = {{"Cache-Control", "max-stale=30"}};
|
|
RequireMiss(exchange, "http://stale/d");
|
|
exchange.requestHeaders = {};
|
|
Cached(exchange, "http://stale/e", {{"Cache-Control", "max-age=60, stale-while-revalidate=600"}, {"ETag", "e"}}, "swr");
|
|
Advance(120);
|
|
Require(exchange.Retrieve("http://stale/e") == 0 && exchange.result == 2);
|
|
Require(exchange.response.statusCode == 200 && Value(exchange.response, "Warning") == "110 - \"Response is Stale\"");
|
|
Require(Value(exchange.response, "Age").substr(0, 2) == "12" && ReadAll(exchange.request) == "swr");
|
|
exchange.Done();
|
|
Cached(exchange, "http://stale/f", {{"Cache-Control", "max-age=60, stale-if-error=600"}, {"ETag", "f"}}, "sie");
|
|
Advance(120);
|
|
Require(exchange.Retrieve("http://stale/f") == 0 && exchange.result == 2 && exchange.response.headers == nullptr);
|
|
Require(exchange.Revalidate(503, {}) == 0 && exchange.result == 1);
|
|
Require(exchange.response.statusCode == 200 && Value(exchange.response, "Warning") == "110 - \"Response is Stale\"" && ReadAll(exchange.request) == "sie");
|
|
exchange.Done();
|
|
Require(sceHttpCacheTerm(exchange.cache) == 0);
|
|
}
|
|
|
|
void TestPublicResponses() {
|
|
Exchange exchange{sceHttpCacheInit(0)};
|
|
Require(exchange.Retrieve("http://public/a") == 0 && exchange.result == 0);
|
|
std::vector<Header> headers{{"Cache-Control", "public, max-age=60"}};
|
|
ResponseHeader header{200, 0, headers.size(), headers.data()};
|
|
Require(sceHttpCacheSetCacheSharing(0) == 0);
|
|
Require(sceHttpCacheSetResponseHeader(exchange.request, &header) == 0);
|
|
Require(sceHttpCacheCompleteRequest(exchange.request) == 0);
|
|
exchange.Done();
|
|
Require(exchange.Retrieve("http://public/a") == 0 && exchange.result == 1);
|
|
exchange.Done();
|
|
Require(sceHttpCacheSetCacheSharing(1) == 0);
|
|
exchange.user = 0xfe;
|
|
Cached(exchange, "http://public/b", headers, "shared");
|
|
Require(exchange.Retrieve("http://public/b") == 0 && exchange.result == 1 && ReadAll(exchange.request) == "shared");
|
|
exchange.Done();
|
|
exchange.user = InitialUser;
|
|
Require(exchange.Retrieve("http://public/a") == 0);
|
|
exchange.Done();
|
|
Require(sceHttpCacheClearAll(exchange.cache, 0xfe) == 0);
|
|
RequireMiss(exchange, "http://public/b");
|
|
Require(sceHttpCacheTerm(exchange.cache) == 0);
|
|
}
|
|
|
|
}
|
|
|
|
int main() {
|
|
TestWithoutCache();
|
|
TestRequests();
|
|
TestCacheArguments();
|
|
TestCacheLimit();
|
|
TestStoreAndHit();
|
|
TestLifetimeOrder();
|
|
TestRevalidation();
|
|
TestPublicResponses();
|
|
return 0;
|
|
}
|