Skip to content

Commit e376767

Browse files
committed
Add a test to validate exception parsing for alarms
1 parent fa18dec commit e376767

1 file changed

Lines changed: 111 additions & 0 deletions

File tree

src/workerd/jsg/exception-test.c++

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// Copyright (c) 2017-2022 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
4+
5+
#include "exception.h"
6+
7+
#include <kj/test.h>
8+
9+
namespace workerd::jsg {
10+
namespace {
11+
12+
// ---------------------------------------------------------------------------
13+
// isExceptionJsgError
14+
// ---------------------------------------------------------------------------
15+
16+
KJ_TEST("isExceptionJsgError: plain jsg.Error") {
17+
KJ_EXPECT(isExceptionJsgError("jsg.Error: something went wrong"_kj));
18+
}
19+
20+
KJ_TEST("isExceptionJsgError: broken.outputGateBroken; jsg.Error (STOR-5119)") {
21+
KJ_EXPECT(isExceptionJsgError("broken.outputGateBroken; jsg.Error: Abort reason"_kj));
22+
}
23+
24+
KJ_TEST("isExceptionJsgError: broken.inputGateBroken; jsg.Error") {
25+
KJ_EXPECT(isExceptionJsgError("broken.inputGateBroken; jsg.Error: DO reset after cleanup"_kj));
26+
}
27+
28+
KJ_TEST("isExceptionJsgError: broken.exceededCpu; jsg.Error") {
29+
KJ_EXPECT(isExceptionJsgError("broken.exceededCpu; jsg.Error: CPU limit exceeded"_kj));
30+
}
31+
32+
KJ_TEST("isExceptionJsgError: overload queue message (plain jsg.Error, output gate also broken)") {
33+
KJ_EXPECT(isExceptionJsgError(
34+
"jsg.Error: Durable Object is overloaded. Requests queued for too long."_kj));
35+
}
36+
37+
KJ_TEST("isExceptionJsgError: remote. prefix is stripped") {
38+
KJ_EXPECT(isExceptionJsgError("remote.broken.outputGateBroken; jsg.Error: Abort reason"_kj));
39+
}
40+
41+
KJ_TEST("isExceptionJsgError: multiple remote. prefixes are stripped") {
42+
KJ_EXPECT(
43+
isExceptionJsgError("remote.remote.broken.outputGateBroken; jsg.Error: Abort reason"_kj));
44+
}
45+
46+
KJ_TEST("isExceptionJsgError: jsg.TypeError is not matched") {
47+
KJ_EXPECT(!isExceptionJsgError("jsg.TypeError: bad type"_kj));
48+
}
49+
50+
KJ_TEST("isExceptionJsgError: jsg.RangeError is not matched") {
51+
KJ_EXPECT(!isExceptionJsgError("jsg.RangeError: out of range"_kj));
52+
}
53+
54+
KJ_TEST("isExceptionJsgError: jsg.DOMException is not matched") {
55+
KJ_EXPECT(!isExceptionJsgError("jsg.DOMException(OperationError): op failed"_kj));
56+
}
57+
58+
KJ_TEST("isExceptionJsgError: jsg-internal errors are not matched") {
59+
KJ_EXPECT(!isExceptionJsgError("jsg-internal.Error: internal detail"_kj));
60+
}
61+
62+
KJ_TEST("isExceptionJsgError: broken + jsg-internal is not matched") {
63+
KJ_EXPECT(!isExceptionJsgError("broken.outputGateBroken; jsg-internal.Error: storage reset"_kj));
64+
}
65+
66+
KJ_TEST("isExceptionJsgError: plain internal C++ exception is not matched") {
67+
KJ_EXPECT(!isExceptionJsgError("OVERLOADED: storage broke"_kj));
68+
}
69+
70+
KJ_TEST("isExceptionJsgError: worker_do_not_log tag is not matched") {
71+
// broken.dropped; worker_do_not_log; jsg.Error comes from the alarm timeout path, but the
72+
// worker_do_not_log tag sits between the broken prefix and jsg.Error, so after stripping
73+
// broken.dropped; the remainder is "worker_do_not_log; jsg.Error: ..." which does not start
74+
// with "jsg.", and tunneledErrorType correctly returns isJsgError=false for it.
75+
KJ_EXPECT(!isExceptionJsgError(
76+
"broken.dropped; worker_do_not_log; jsg.Error: Alarm exceeded its allowed execution time"_kj));
77+
}
78+
79+
// ---------------------------------------------------------------------------
80+
// isExceptionFromInputGateBroken
81+
// ---------------------------------------------------------------------------
82+
83+
KJ_TEST("isExceptionFromInputGateBroken: basic match") {
84+
KJ_EXPECT(isExceptionFromInputGateBroken(
85+
"broken.inputGateBroken; jsg.Error: DO reset after cleanup"_kj));
86+
}
87+
88+
KJ_TEST("isExceptionFromInputGateBroken: KJ rpc remote exception prefix is stripped") {
89+
// stripRemoteExceptionPrefix() strips "remote exception: " (KJ RPC tunneling format).
90+
// Note: the "remote." prefix from annotateBroken() is NOT stripped by this function.
91+
KJ_EXPECT(isExceptionFromInputGateBroken(
92+
"remote exception: broken.inputGateBroken; jsg.Error: DO reset after cleanup"_kj));
93+
}
94+
95+
KJ_TEST("isExceptionFromInputGateBroken: annotateBroken remote. prefix is not stripped") {
96+
// annotateBroken() prepends "remote." which this function does not strip (unlike
97+
// isExceptionJsgError which uses tunneledErrorType() and handles both formats).
98+
KJ_EXPECT(!isExceptionFromInputGateBroken(
99+
"remote.broken.inputGateBroken; jsg.Error: DO reset after cleanup"_kj));
100+
}
101+
102+
KJ_TEST("isExceptionFromInputGateBroken: outputGateBroken is not matched") {
103+
KJ_EXPECT(!isExceptionFromInputGateBroken("broken.outputGateBroken; jsg.Error: Abort reason"_kj));
104+
}
105+
106+
KJ_TEST("isExceptionFromInputGateBroken: plain jsg.Error is not matched") {
107+
KJ_EXPECT(!isExceptionFromInputGateBroken("jsg.Error: something"_kj));
108+
}
109+
110+
} // namespace
111+
} // namespace workerd::jsg

0 commit comments

Comments
 (0)