Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/workerd/api/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,17 @@ wd_test(
args = ["--experimental"],
)

wd_test(
src = "cache-test.wd-test",
args = ["--experimental"],
data = [
"cache-instrumentation-test.js",
"cache-mock.js",
"cache-operations.js",
"tests/instrumentation-tail-worker.js",
],
)

wd_test(
src = "kv-test.wd-test",
args = ["--experimental"],
Expand Down
259 changes: 259 additions & 0 deletions src/workerd/api/cache-instrumentation-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
// Copyright (c) 2017-2023 Cloudflare, Inc.
// Licensed under the Apache 2.0 license found in the LICENSE file or at:
// https://opensource.org/licenses/Apache-2.0
import * as assert from 'node:assert';
import {
invocationPromises,
spans,
testTailHandler,
} from 'test:instumentation-tail';

// Use shared instrumentation test tail worker
export default testTailHandler;

export const test = {
async test() {
// Wait for all the tailStream executions to finish
await Promise.allSettled(invocationPromises);

// Recorded streaming tail worker events, in insertion order,
// filtering spans not associated with Cache
let received = Array.from(spans.values());

// spans emitted by cache-operations.js in execution order
let expected = [
{
name: 'cache_match',
'cache.request.url': 'https://example.com/conditional-etag',
'cache.request.method': 'GET',
'cache.request.header.if_none_match': 'abc123',
'cache.response.status_code': 504n,
'cache.response.body.size': 0n,
'cache.response.cache_status': 'MISS',
'cache.response.success': false,
closed: true,
},
{
name: 'cache_match',
'cache.request.url': 'https://example.com/conditional-last-modified',
'cache.request.method': 'GET',
'cache.request.header.if_modified_since':
'Wed, 21 Oct 2020 07:28:00 GMT',
'cache.response.status_code': 504n,
'cache.response.body.size': 0n,
'cache.response.cache_status': 'MISS',
'cache.response.success': false,
closed: true,
},
{
name: 'cache_delete',
'cache.request.url': 'https://example.com/delete-exists',
'cache.response.status_code': 200n,
'cache.response.success': true,
closed: true,
},
{
name: 'cache_delete',
'cache.request.url': 'https://example.com/delete-not-exists',
'cache.response.status_code': 404n,
'cache.response.success': false,
closed: true,
},
{
name: 'cache_delete',
'cache.request.ignore_method': true,
'cache.request.url': 'https://example.com/delete-with-options',
'cache.response.status_code': 404n,
'cache.response.success': false,
closed: true,
},
{
name: 'cache_put',
'cache.request.url': 'https://example.com/put-cache-tag',
'cache.request.method': 'GET',
'cache.request.payload.status_code': 200n,
'cache.request.payload.header.cache_control': 'public, max-age=3600',
'cache.request.payload.header.cache_tag': 'tag1,tag2,tag3',
'cache.request.payload.size': 143n,
'cache.response.success': true,
closed: true,
},
{
name: 'cache_put',
'cache.request.url': 'https://example.com/put-etag',
'cache.request.method': 'GET',
'cache.request.payload.status_code': 200n,
'cache.request.payload.header.cache_control': 'public, max-age=3600',
'cache.request.payload.header.etag': '"abc123"',
'cache.request.payload.size': 130n,
'cache.response.success': true,
closed: true,
},
{
name: 'cache_put',
'cache.request.url': 'https://example.com/put-expires',
'cache.request.method': 'GET',
'cache.request.payload.status_code': 200n,
'cache.request.payload.header.expires': 'Wed, 21 Oct 2025 07:28:00 GMT',
'cache.request.payload.size': 120n,
'cache.response.success': true,
closed: true,
},
{
name: 'cache_put',
'cache.request.url': 'https://example.com/put-last-modified',
'cache.request.method': 'GET',
'cache.request.payload.status_code': 200n,
'cache.request.payload.header.cache_control': 'public, max-age=3600',
'cache.request.payload.header.last_modified':
'Wed, 21 Oct 2020 07:28:00 GMT',
'cache.request.payload.size': 169n,
'cache.response.success': true,
closed: true,
},
{
name: 'cache_put',
'cache.request.url': 'https://example.com/put-set-cookie',
'cache.request.method': 'GET',
'cache.request.payload.status_code': 200n,
'cache.request.payload.header.cache_control': 'public, max-age=3600',
'cache.request.payload.size': 164n,
'cache.response.success': true,
closed: true,
},
{
name: 'cache_put',
'cache.request.url': 'https://example.com/put-set-cookie-private',
'cache.request.method': 'GET',
'cache.request.payload.status_code': 200n,
'cache.request.payload.header.cache_control':
'public, max-age=3600, private=Set-Cookie',
'cache.request.payload.size': 197n,
'cache.response.success': true,
closed: true,
},
{
name: 'cache_put',
'cache.request.url': 'https://example.com/put-must-revalidate',
'cache.request.method': 'GET',
'cache.request.payload.status_code': 200n,
'cache.request.payload.header.cache_control':
'public, max-age=3600, must-revalidate',
'cache.request.payload.size': 142n,
'cache.response.success': true,
closed: true,
},
{
name: 'cache_put',
'cache.request.url': 'https://example.com/put-proxy-revalidate',
'cache.request.method': 'GET',
'cache.request.payload.status_code': 200n,
'cache.request.payload.header.cache_control':
'public, max-age=3600, proxy-revalidate',
'cache.request.payload.size': 144n,
'cache.response.success': true,
closed: true,
},
{
name: 'cache_put',
'cache.request.url': 'https://example.com/put-private',
'cache.request.method': 'GET',
'cache.request.payload.status_code': 200n,
'cache.request.payload.header.cache_control': 'private, max-age=3600',
'cache.request.payload.size': 118n,
'cache.response.success': true,
closed: true,
},
{
name: 'cache_put',
'cache.request.url': 'https://example.com/put-no-cache',
'cache.request.method': 'GET',
'cache.request.payload.status_code': 200n,
'cache.request.payload.header.cache_control': 'no-cache, max-age=3600',
'cache.request.payload.size': 120n,
'cache.response.success': true,
closed: true,
},
{
name: 'cache_match',
'cache.request.url': 'https://example.com/cached-resource',
'cache.request.method': 'GET',
'cache.response.status_code': 200n,
'cache.response.body.size': 14n,
'cache.response.cache_status': 'HIT',
'cache.response.success': true,
closed: true,
},
{
name: 'cache_match',
'cache.request.url': 'https://example.com/not-cached',
'cache.request.method': 'GET',
'cache.response.status_code': 504n,
'cache.response.body.size': 0n,
'cache.response.cache_status': 'MISS',
'cache.response.success': false,
closed: true,
},
{
name: 'cache_match',
'cache.request.ignore_method': false,
'cache.request.url': 'https://example.com/cached-with-options',
'cache.request.method': 'GET',
'cache.response.status_code': 504n,
'cache.response.body.size': 0n,
'cache.response.cache_status': 'MISS',
'cache.response.success': false,
closed: true,
},
{
name: 'cache_put',
'cache.request.url': 'https://example.com/put-resource',
'cache.request.method': 'GET',
'cache.request.payload.status_code': 200n,
'cache.request.payload.header.cache_control': 'public, max-age=3600',
'cache.request.payload.size': 114n,
'cache.response.success': true,
closed: true,
},
{
name: 'cache_put',
'cache.request.url': 'https://example.com/put-no-store',
'cache.request.method': 'GET',
'cache.request.payload.status_code': 200n,
'cache.request.payload.header.cache_control': 'no-store',
'cache.request.payload.size': 106n,
'cache.response.success': true,
closed: true,
},
{
name: 'cache_put',
'cache.request.url': 'https://example.com/put-s-maxage',
'cache.request.method': 'GET',
'cache.request.payload.status_code': 200n,
'cache.request.payload.header.cache_control': 's-maxage=7200, public',
'cache.request.payload.size': 119n,
'cache.response.success': true,
closed: true,
},
];

assert.equal(
received.length,
expected.length,
`Expected ${expected.length} received ${received.length} spans`
);
let errors = [];
for (let i = 0; i < received.length; i++) {
try {
assert.deepStrictEqual(received[i], expected[i]);
} catch (e) {
console.error(`value: ${i} does not match`);
console.log(e);
errors.push(e);
}
}
if (errors.length > 0) {
throw 'cache spans are incorrect';
}
},
};
48 changes: 48 additions & 0 deletions src/workerd/api/cache-mock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) 2017-2023 Cloudflare, Inc.
// Licensed under the Apache 2.0 license found in the LICENSE file or at:
// https://opensource.org/licenses/Apache-2.0

// Mock cache backend - responds to GET (match), PUT (put), and PURGE (delete)
export default {
async fetch(request) {
const url = new URL(request.url);
const headers = new Headers();

// Handle cache.match() operations (GET requests)
if (request.method === 'GET') {
// Check if this is a cache.match() request (has only-if-cached)
const cacheControl = request.headers.get('cache-control');
if (cacheControl?.includes('only-if-cached')) {
// Simulate cache HIT
if (url.pathname.includes('cached-resource')) {
headers.set('CF-Cache-Status', 'HIT');
return new Response('Cached content', { status: 200, headers });
}
// Simulate cache MISS
headers.set('CF-Cache-Status', 'MISS');
return new Response(null, { status: 504, headers });
}
}

// Handle cache.put() operations (PUT requests)
if (request.method === 'PUT') {
// Read the body (which contains the serialized response to cache)
await request.text();

// Simulate successful cache write
return new Response(null, { status: 204 });
}

// Handle cache.delete() operations (PURGE requests)
if (request.method === 'PURGE') {
// Simulate successful deletion
if (url.pathname.includes('delete-exists')) {
return new Response(null, { status: 200 });
}
// Simulate not found
return new Response(null, { status: 404 });
}

return new Response('Not Found', { status: 404 });
},
};
Loading
Loading