Skip to content
File

Blob: src/workerd/api/tests/warnings-tail.js

javascript69 lines
1// Copyright (c) 2026 Cloudflare, Inc.
2// Licensed under the Apache 2.0 license found in the LICENSE file or at:
3// https://opensource.org/licenses/Apache-2.0
4import * as assert from 'node:assert';
5 
6// ================================================================================================
7// Expected warnings registry.
8//
9// Add new entries here when introducing logWarning() calls. Each entry is a substring that must
10// appear in at least one warn-level tail event's message. The trigger worker (warnings-test.js)
11// must exercise a code path that produces each warning.
12//
13// NOTE: Some logWarning() calls go through jsg::Lock::logWarning() instead of
14// IoContext::logWarning(). The jsg path does not currently emit to the tracer, so those warnings
15// are not observable via tail workers and cannot be tested here (e.g. .text() on non-text body).
16const EXPECTED_WARNINGS = [
17 // From Body::Body (http.c++) โ€” FormData body with a custom Content-Type header.
18 'FormData body was provided',
19 // From Response constructor (http.c++) โ€” null-body status with zero-length body.
20 'Constructing a Response with a null body status',
21];
22// ================================================================================================
23 
24let allEvents = [];
25 
26export default {
27 tailStream(event) {
28 allEvents.push(event.event);
29 return (event) => {
30 allEvents.push(event.event);
31 };
32 },
33};
34 
35export const test = {
36 async test() {
37 // HACK: Tail events from the trigger worker's fetch invocation are delivered asynchronously
38 // across service boundaries. There is no JS-level synchronization primitive to await their
39 // arrival โ€” a plain `await promise` doesn't drive the I/O loop that delivers them. We must
40 // use scheduler.wait() to yield while the runtime processes pending I/O.
41 const TIMEOUT_MS = 5000;
42 const POLL_MS = 10;
43 const deadline = Date.now() + TIMEOUT_MS;
44 
45 const unseen = () =>
46 EXPECTED_WARNINGS.filter(
47 (substring) =>
48 !allEvents.some(
49 (e) =>
50 e.type === 'log' &&
51 e.level === 'warn' &&
52 e.message?.[0]?.includes(substring)
53 )
54 );
55 
56 while (unseen().length > 0 && Date.now() < deadline) {
57 await scheduler.wait(POLL_MS);
58 }
59 
60 const missing = unseen();
61 assert.strictEqual(
62 missing.length,
63 0,
64 `${missing.length} expected warning(s) were not observed after ${TIMEOUT_MS}ms:\n` +
65 missing.map((s) => ` - "${s}"`).join('\n')
66 );
67 },
68};