ladybird/Tests/LibHTTP/TestMemoryCache.cpp

120 lines
4.9 KiB
C++
Raw Normal View History

/*
* Copyright (c) 2026-present, the Ladybird developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibCore/ImmutableBytes.h>
#include <LibHTTP/Cache/MemoryCache.h>
#include <LibHTTP/Cache/Utilities.h>
#include <LibHTTP/HeaderList.h>
#include <LibTest/TestCase.h>
#include <LibURL/Parser.h>
static URL::URL parse_url(StringView url)
{
return URL::Parser::basic_parse(url).release_value();
}
static NonnullRefPtr<HTTP::HeaderList> create_cacheable_request_headers()
{
return HTTP::HeaderList::create({
{ "Accept"sv, "*/*"sv },
});
}
static NonnullRefPtr<HTTP::HeaderList> create_cacheable_response_headers()
{
return HTTP::HeaderList::create({
{ "Cache-Control"sv, "max-age=60"sv },
});
}
static NonnullRefPtr<HTTP::HeaderList> create_vary_user_agent_response_headers()
{
return HTTP::HeaderList::create({
{ "Cache-Control"sv, "max-age=60"sv },
{ "Vary"sv, "User-Agent"sv },
});
}
static Core::ImmutableBytes immutable_bytes(StringView bytes)
{
return MUST(Core::ImmutableBytes::copy(bytes.bytes()));
}
TEST_CASE(javascript_bytecode_cache_round_trips_with_memory_cache_entry)
{
auto cache = HTTP::MemoryCache::create();
auto url = parse_url("https://example.com/script.js"sv);
auto request_headers = create_cacheable_request_headers();
auto response_headers = create_cacheable_response_headers();
auto bytecode = immutable_bytes("cached bytecode"sv);
cache->create_entry(url, "GET"sv, *request_headers, UnixDateTime::now(), 200, "OK"sv, *response_headers, bytecode, 0);
cache->finalize_entry(url, "GET"sv, *request_headers, 200, *response_headers, immutable_bytes("console.log('hello');"sv));
auto entry = cache->open_entry(url, "GET"sv, *request_headers, HTTP::CacheMode::Default);
VERIFY(entry.has_value());
VERIFY(entry->javascript_bytecode_cache.has_value());
EXPECT_EQ(entry->javascript_bytecode_cache->bytes(), bytecode.bytes());
EXPECT_EQ(entry->javascript_bytecode_cache_vary_key, Optional<u64> { 0 });
}
TEST_CASE(javascript_bytecode_cache_update_matches_memory_cache_vary_headers)
{
auto cache = HTTP::MemoryCache::create();
auto url = parse_url("https://example.com/script.js"sv);
auto script_request_headers = create_cacheable_request_headers();
auto cache_request_headers = HTTP::HeaderList::create({
{ "Accept"sv, "*/*"sv },
{ "User-Agent"sv, "Ladybird"sv },
});
auto response_headers = create_vary_user_agent_response_headers();
auto bytecode = immutable_bytes("generated bytecode"sv);
auto vary_key = HTTP::create_vary_key(*cache_request_headers, *response_headers);
cache->create_entry(url, "GET"sv, *cache_request_headers, UnixDateTime::now(), 200, "OK"sv, *response_headers);
cache->finalize_entry(url, "GET"sv, *cache_request_headers, 200, *response_headers, immutable_bytes("console.log('hello');"sv));
cache->update_javascript_bytecode_cache(url, "GET"sv, *script_request_headers, vary_key, bytecode);
auto entry = cache->open_entry(url, "GET"sv, *cache_request_headers, HTTP::CacheMode::Default);
VERIFY(entry.has_value());
EXPECT(!entry->javascript_bytecode_cache.has_value());
EXPECT(!entry->javascript_bytecode_cache_vary_key.has_value());
cache->update_javascript_bytecode_cache(url, "GET"sv, *cache_request_headers, vary_key, bytecode);
entry = cache->open_entry(url, "GET"sv, *cache_request_headers, HTTP::CacheMode::Default);
VERIFY(entry.has_value());
VERIFY(entry->javascript_bytecode_cache.has_value());
EXPECT_EQ(entry->javascript_bytecode_cache->bytes(), bytecode.bytes());
EXPECT_EQ(entry->javascript_bytecode_cache_vary_key, Optional<u64> { vary_key });
}
TEST_CASE(javascript_bytecode_cache_can_be_added_after_memory_cache_entry_is_complete)
{
auto cache = HTTP::MemoryCache::create();
auto url = parse_url("https://example.com/script.js"sv);
auto request_headers = create_cacheable_request_headers();
auto response_headers = create_cacheable_response_headers();
auto bytecode = immutable_bytes("generated bytecode"sv);
cache->create_entry(url, "GET"sv, *request_headers, UnixDateTime::now(), 200, "OK"sv, *response_headers);
cache->finalize_entry(url, "GET"sv, *request_headers, 200, *response_headers, immutable_bytes("console.log('hello');"sv));
auto entry = cache->open_entry(url, "GET"sv, *request_headers, HTTP::CacheMode::Default);
VERIFY(entry.has_value());
EXPECT(!entry->javascript_bytecode_cache.has_value());
EXPECT(!entry->javascript_bytecode_cache_vary_key.has_value());
cache->update_javascript_bytecode_cache(url, "GET"sv, *request_headers, 0, bytecode);
entry = cache->open_entry(url, "GET"sv, *request_headers, HTTP::CacheMode::Default);
VERIFY(entry.has_value());
VERIFY(entry->javascript_bytecode_cache.has_value());
EXPECT_EQ(entry->javascript_bytecode_cache->bytes(), bytecode.bytes());
EXPECT_EQ(entry->javascript_bytecode_cache_vary_key, Optional<u64> { 0 });
}