Commit 98113bf5 authored by Kenton Varda's avatar Kenton Varda

Fix no-exceptions build.

parent 9017031f
...@@ -382,7 +382,7 @@ Orphan<DynamicList> JsonCodec::decodeArray(List<JsonValue>::Reader input, ListSc ...@@ -382,7 +382,7 @@ Orphan<DynamicList> JsonCodec::decodeArray(List<JsonValue>::Reader input, ListSc
} }
void JsonCodec::decodeObject(JsonValue::Reader input, StructSchema type, Orphanage orphanage, DynamicStruct::Builder output) const { void JsonCodec::decodeObject(JsonValue::Reader input, StructSchema type, Orphanage orphanage, DynamicStruct::Builder output) const {
KJ_REQUIRE(input.isObject(), "Expected object value"); KJ_REQUIRE(input.isObject(), "Expected object value") { return; }
for (auto field: input.getObject()) { for (auto field: input.getObject()) {
KJ_IF_MAYBE(fieldSchema, type.findFieldByName(field.getName())) { KJ_IF_MAYBE(fieldSchema, type.findFieldByName(field.getName())) {
decodeField(*fieldSchema, field.getValue(), orphanage, output); decodeField(*fieldSchema, field.getValue(), orphanage, output);
...@@ -495,14 +495,16 @@ Orphan<DynamicValue> JsonCodec::decode( ...@@ -495,14 +495,16 @@ Orphan<DynamicValue> JsonCodec::decode(
case JsonValue::ARRAY: case JsonValue::ARRAY:
return decodeArray(input.getArray(), type.asList(), orphanage); return decodeArray(input.getArray(), type.asList(), orphanage);
default: default:
KJ_FAIL_REQUIRE("Expected list value"); KJ_FAIL_REQUIRE("Expected list value") { break; }
return orphanage.newOrphan(type.asList(), 0);
} }
case schema::Type::ENUM: case schema::Type::ENUM:
switch (input.which()) { switch (input.which()) {
case JsonValue::STRING: case JsonValue::STRING:
return DynamicEnum(type.asEnum().getEnumerantByName(input.getString())); return DynamicEnum(type.asEnum().getEnumerantByName(input.getString()));
default: default:
KJ_FAIL_REQUIRE("Expected enum value"); KJ_FAIL_REQUIRE("Expected enum value") { break; }
return DynamicEnum(type.asEnum(), 0);
} }
case schema::Type::STRUCT: { case schema::Type::STRUCT: {
auto structType = type.asStruct(); auto structType = type.asStruct();
......
...@@ -362,14 +362,20 @@ KJ_TEST("revoke membrane") { ...@@ -362,14 +362,20 @@ KJ_TEST("revoke membrane") {
paf.fulfiller->reject(KJ_EXCEPTION(DISCONNECTED, "foobar")); paf.fulfiller->reject(KJ_EXCEPTION(DISCONNECTED, "foobar"));
// TRICKY: We need to use .ignoreResult().wait() below because when compiling with
// -fno-exceptions, void waits throw recoverable exceptions while non-void waits necessarily
// throw fatal exceptions... but testing for fatal exceptions when exceptions are disabled
// involves fork()ing the process to run the code so if it has side effects on file descriptors
// then we'll get in a bad state...
KJ_ASSERT(callPromise.poll(env.io.waitScope)); KJ_ASSERT(callPromise.poll(env.io.waitScope));
KJ_EXPECT_THROW_MESSAGE("foobar", callPromise.wait(env.io.waitScope)); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("foobar", callPromise.ignoreResult().wait(env.io.waitScope));
KJ_EXPECT_THROW_MESSAGE("foobar", KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("foobar",
env.membraned.makeThingRequest().send().wait(env.io.waitScope)); env.membraned.makeThingRequest().send().ignoreResult().wait(env.io.waitScope));
KJ_EXPECT_THROW_MESSAGE("foobar", KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("foobar",
thing.passThroughRequest().send().wait(env.io.waitScope)); thing.passThroughRequest().send().ignoreResult().wait(env.io.waitScope));
} }
} // namespace } // namespace
......
...@@ -910,7 +910,7 @@ KJ_TEST("Userland pipe with limit") { ...@@ -910,7 +910,7 @@ KJ_TEST("Userland pipe with limit") {
KJ_EXPECT(!promise.poll(ws)); KJ_EXPECT(!promise.poll(ws));
auto promise2 = pipe.out->write("barbaz", 6); auto promise2 = pipe.out->write("barbaz", 6);
KJ_EXPECT(promise.wait(ws) == "bar"); KJ_EXPECT(promise.wait(ws) == "bar");
KJ_EXPECT_THROW_MESSAGE("read end of pipe was aborted", promise2.wait(ws)); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("read end of pipe was aborted", promise2.wait(ws));
} }
// Further writes throw and reads return EOF. // Further writes throw and reads return EOF.
...@@ -939,7 +939,7 @@ KJ_TEST("Userland pipe pumpTo with limit") { ...@@ -939,7 +939,7 @@ KJ_TEST("Userland pipe pumpTo with limit") {
auto promise2 = pipe.out->write("barbaz", 6); auto promise2 = pipe.out->write("barbaz", 6);
promise.wait(ws); promise.wait(ws);
pumpPromise.wait(ws); pumpPromise.wait(ws);
KJ_EXPECT_THROW_MESSAGE("read end of pipe was aborted", promise2.wait(ws)); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("read end of pipe was aborted", promise2.wait(ws));
} }
// Further writes throw. // Further writes throw.
......
...@@ -597,7 +597,7 @@ TEST(Async, Canceler) { ...@@ -597,7 +597,7 @@ TEST(Async, Canceler) {
canceler.cancel("foobar"); canceler.cancel("foobar");
KJ_EXPECT_THROW_MESSAGE("foobar", never.wait(waitScope)); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("foobar", never.wait(waitScope));
now.wait(waitScope); now.wait(waitScope);
KJ_EXPECT_THROW_MESSAGE("foobar", neverI.wait(waitScope)); KJ_EXPECT_THROW_MESSAGE("foobar", neverI.wait(waitScope));
KJ_EXPECT(nowI.wait(waitScope) == 123u); KJ_EXPECT(nowI.wait(waitScope) == 123u);
......
...@@ -1730,7 +1730,7 @@ KJ_TEST("WebSocket pump disconnect on send") { ...@@ -1730,7 +1730,7 @@ KJ_TEST("WebSocket pump disconnect on send") {
pipe2.ends[1] = nullptr; pipe2.ends[1] = nullptr;
// Pump throws disconnected. // Pump throws disconnected.
KJ_EXPECT_THROW(DISCONNECTED, pumpTask.wait(waitScope)); KJ_EXPECT_THROW_RECOVERABLE(DISCONNECTED, pumpTask.wait(waitScope));
// client1 managed to send its whole message into the pump, though. // client1 managed to send its whole message into the pump, though.
sendTask.wait(waitScope); sendTask.wait(waitScope);
...@@ -2659,7 +2659,9 @@ public: ...@@ -2659,7 +2659,9 @@ public:
HttpMethod method, kj::StringPtr url, const HttpHeaders& headers, HttpMethod method, kj::StringPtr url, const HttpHeaders& headers,
kj::AsyncInputStream& requestBody, Response& response) override { kj::AsyncInputStream& requestBody, Response& response) override {
if (!headers.isWebSocket()) { if (!headers.isWebSocket()) {
KJ_ASSERT(url != "/throw"); if (url == "/throw") {
return KJ_EXCEPTION(FAILED, "client requested failure");
}
auto body = kj::str(headers.get(HttpHeaderId::HOST).orDefault("null"), ":", url); auto body = kj::str(headers.get(HttpHeaderId::HOST).orDefault("null"), ":", url);
auto stream = response.send(200, "OK", HttpHeaders(headerTable), body.size()); auto stream = response.send(200, "OK", HttpHeaders(headerTable), body.size());
......
...@@ -410,7 +410,7 @@ KJ_TEST("DiskDirectory") { ...@@ -410,7 +410,7 @@ KJ_TEST("DiskDirectory") {
KJ_EXPECT(dir->tryOpenFile(Path({"foo", "bar"}), WriteMode::MODIFY) == nullptr); KJ_EXPECT(dir->tryOpenFile(Path({"foo", "bar"}), WriteMode::MODIFY) == nullptr);
KJ_EXPECT(dir->tryOpenFile(Path({"bar", "baz"}), WriteMode::MODIFY) == nullptr); KJ_EXPECT(dir->tryOpenFile(Path({"bar", "baz"}), WriteMode::MODIFY) == nullptr);
KJ_EXPECT_THROW_MESSAGE("parent is not a directory", KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("parent is not a directory",
dir->tryOpenFile(Path({"bar", "baz"}), WriteMode::CREATE)); dir->tryOpenFile(Path({"bar", "baz"}), WriteMode::CREATE));
{ {
...@@ -537,9 +537,9 @@ KJ_TEST("DiskDirectory symlinks") { ...@@ -537,9 +537,9 @@ KJ_TEST("DiskDirectory symlinks") {
KJ_EXPECT(dir->tryOpenFile(Path("foo")) == nullptr); KJ_EXPECT(dir->tryOpenFile(Path("foo")) == nullptr);
KJ_EXPECT(dir->tryOpenFile(Path("foo"), WriteMode::CREATE) == nullptr); KJ_EXPECT(dir->tryOpenFile(Path("foo"), WriteMode::CREATE) == nullptr);
KJ_EXPECT(dir->tryOpenFile(Path("foo"), WriteMode::MODIFY) == nullptr); KJ_EXPECT(dir->tryOpenFile(Path("foo"), WriteMode::MODIFY) == nullptr);
KJ_EXPECT_THROW_MESSAGE("parent is not a directory", KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("parent is not a directory",
dir->tryOpenFile(Path("foo"), WriteMode::CREATE | WriteMode::MODIFY)); dir->tryOpenFile(Path("foo"), WriteMode::CREATE | WriteMode::MODIFY));
KJ_EXPECT_THROW_MESSAGE("parent is not a directory", KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("parent is not a directory",
dir->tryOpenFile(Path("foo"), dir->tryOpenFile(Path("foo"),
WriteMode::CREATE | WriteMode::MODIFY | WriteMode::CREATE_PARENT)); WriteMode::CREATE | WriteMode::MODIFY | WriteMode::CREATE_PARENT));
......
...@@ -133,18 +133,23 @@ KJ_TEST("Path exceptions") { ...@@ -133,18 +133,23 @@ KJ_TEST("Path exceptions") {
KJ_EXPECT_THROW_MESSAGE("invalid path component", Path("..")); KJ_EXPECT_THROW_MESSAGE("invalid path component", Path(".."));
KJ_EXPECT_THROW_MESSAGE("NUL character", Path(StringPtr("foo\0bar", 7))); KJ_EXPECT_THROW_MESSAGE("NUL character", Path(StringPtr("foo\0bar", 7)));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path::parse("..")); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting", Path::parse(".."));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path::parse("../foo")); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting", Path::parse("../foo"));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path::parse("foo/../..")); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting", Path::parse("foo/../.."));
KJ_EXPECT_THROW_MESSAGE("expected a relative path", Path::parse("/foo")); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("expected a relative path", Path::parse("/foo"));
KJ_EXPECT_THROW_MESSAGE("NUL character", Path::parse(kj::StringPtr("foo\0bar", 7))); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("NUL character", Path::parse(kj::StringPtr("foo\0bar", 7)));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).eval("../../..")); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).eval("../baz/../../..")); Path({"foo", "bar"}).eval("../../.."));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).eval("baz/../../../..")); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).eval("/..")); Path({"foo", "bar"}).eval("../baz/../../.."));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).eval("/baz/../..")); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
Path({"foo", "bar"}).eval("baz/../../../.."));
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
Path({"foo", "bar"}).eval("/.."));
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
Path({"foo", "bar"}).eval("/baz/../.."));
KJ_EXPECT_THROW_MESSAGE("root path has no basename", Path(nullptr).basename()); KJ_EXPECT_THROW_MESSAGE("root path has no basename", Path(nullptr).basename());
KJ_EXPECT_THROW_MESSAGE("root path has no parent", Path(nullptr).parent()); KJ_EXPECT_THROW_MESSAGE("root path has no parent", Path(nullptr).parent());
...@@ -210,28 +215,35 @@ KJ_TEST("Win32 Path") { ...@@ -210,28 +215,35 @@ KJ_TEST("Win32 Path") {
} }
KJ_TEST("Win32 Path exceptions") { KJ_TEST("Win32 Path exceptions") {
KJ_EXPECT_THROW_MESSAGE("colons are prohibited", Path({"c:", "foo", "bar"}).toWin32String()); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("colons are prohibited",
KJ_EXPECT_THROW_MESSAGE("colons are prohibited", Path({"c:", "foo:bar"}).toWin32String(true)); Path({"c:", "foo", "bar"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"con"}).toWin32String()); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("colons are prohibited",
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"CON", "bar"}).toWin32String()); Path({"c:", "foo:bar"}).toWin32String(true));
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"foo", "cOn"}).toWin32String()); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"con"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"prn"}).toWin32String()); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"CON", "bar"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"aux"}).toWin32String()); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"foo", "cOn"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"NUL"}).toWin32String()); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"prn"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"nul.txt"}).toWin32String()); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"aux"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"com3"}).toWin32String()); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"NUL"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"lpt9"}).toWin32String()); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"nul.txt"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("DOS reserved name", Path({"com1.hello"}).toWin32String()); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"com3"}).toWin32String());
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"lpt9"}).toWin32String());
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("DOS reserved name", Path({"com1.hello"}).toWin32String());
KJ_EXPECT_THROW_MESSAGE("drive letter or netbios", Path({"?", "foo"}).toWin32String(true)); KJ_EXPECT_THROW_MESSAGE("drive letter or netbios", Path({"?", "foo"}).toWin32String(true));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).evalWin32("../../..")); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).evalWin32("../baz/../../..")); Path({"foo", "bar"}).evalWin32("../../.."));
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).evalWin32("baz/../../../..")); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
KJ_EXPECT_THROW_MESSAGE("break out of starting", Path({"foo", "bar"}).evalWin32("c:\\..\\..")); Path({"foo", "bar"}).evalWin32("../baz/../../.."));
KJ_EXPECT_THROW_MESSAGE("break out of starting", KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
Path({"foo", "bar"}).evalWin32("baz/../../../.."));
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
Path({"foo", "bar"}).evalWin32("c:\\..\\.."));
KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("break out of starting",
Path({"c:", "foo", "bar"}).evalWin32("/baz/../../..")); Path({"c:", "foo", "bar"}).evalWin32("/baz/../../.."));
KJ_EXPECT_THROW_MESSAGE("must specify drive letter", Path({"foo"}).evalWin32("\\baz\\qux")); KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("must specify drive letter",
Path({"foo"}).evalWin32("\\baz\\qux"));
} }
KJ_TEST("WriteMode operators") { KJ_TEST("WriteMode operators") {
...@@ -482,7 +494,7 @@ KJ_TEST("InMemoryDirectory") { ...@@ -482,7 +494,7 @@ KJ_TEST("InMemoryDirectory") {
KJ_EXPECT(dir->tryOpenFile(Path({"foo", "bar"}), WriteMode::MODIFY) == nullptr); KJ_EXPECT(dir->tryOpenFile(Path({"foo", "bar"}), WriteMode::MODIFY) == nullptr);
KJ_EXPECT(dir->tryOpenFile(Path({"bar", "baz"}), WriteMode::MODIFY) == nullptr); KJ_EXPECT(dir->tryOpenFile(Path({"bar", "baz"}), WriteMode::MODIFY) == nullptr);
KJ_EXPECT_THROW_MESSAGE("parent is not a directory", KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("parent is not a directory",
dir->tryOpenFile(Path({"bar", "baz"}), WriteMode::CREATE)); dir->tryOpenFile(Path({"bar", "baz"}), WriteMode::CREATE));
clock.expectUnchanged(*dir); clock.expectUnchanged(*dir);
...@@ -628,9 +640,9 @@ KJ_TEST("InMemoryDirectory symlinks") { ...@@ -628,9 +640,9 @@ KJ_TEST("InMemoryDirectory symlinks") {
KJ_EXPECT(dir->tryOpenFile(Path("foo")) == nullptr); KJ_EXPECT(dir->tryOpenFile(Path("foo")) == nullptr);
KJ_EXPECT(dir->tryOpenFile(Path("foo"), WriteMode::CREATE) == nullptr); KJ_EXPECT(dir->tryOpenFile(Path("foo"), WriteMode::CREATE) == nullptr);
KJ_EXPECT(dir->tryOpenFile(Path("foo"), WriteMode::MODIFY) == nullptr); KJ_EXPECT(dir->tryOpenFile(Path("foo"), WriteMode::MODIFY) == nullptr);
KJ_EXPECT_THROW_MESSAGE("parent is not a directory", KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("parent is not a directory",
dir->tryOpenFile(Path("foo"), WriteMode::CREATE | WriteMode::MODIFY)); dir->tryOpenFile(Path("foo"), WriteMode::CREATE | WriteMode::MODIFY));
KJ_EXPECT_THROW_MESSAGE("parent is not a directory", KJ_EXPECT_THROW_RECOVERABLE_MESSAGE("parent is not a directory",
dir->tryOpenFile(Path("foo"), dir->tryOpenFile(Path("foo"),
WriteMode::CREATE | WriteMode::MODIFY | WriteMode::CREATE_PARENT)); WriteMode::CREATE | WriteMode::MODIFY | WriteMode::CREATE_PARENT));
......
...@@ -251,11 +251,12 @@ String PathPtr::toWin32StringImpl(bool absolute, bool forApi) const { ...@@ -251,11 +251,12 @@ String PathPtr::toWin32StringImpl(bool absolute, bool forApi) const {
for (size_t i = 0; i < p.size(); i++) { for (size_t i = 0; i < p.size(); i++) {
*ptr++ = '|'; *ptr++ = '|';
} }
continue; goto skip;
} }
memcpy(ptr, p.begin(), p.size()); memcpy(ptr, p.begin(), p.size());
ptr += p.size(); ptr += p.size();
skip:;
} }
KJ_ASSERT(ptr == result.end()); KJ_ASSERT(ptr == result.end());
...@@ -274,6 +275,7 @@ String PathPtr::toWin32StringImpl(bool absolute, bool forApi) const { ...@@ -274,6 +275,7 @@ String PathPtr::toWin32StringImpl(bool absolute, bool forApi) const {
result) { result) {
// Recover by using a different character which we know Win32 syscalls will reject. // Recover by using a different character which we know Win32 syscalls will reject.
result[i] = '|'; result[i] = '|';
break;
} }
} }
} }
......
...@@ -98,7 +98,7 @@ private: ...@@ -98,7 +98,7 @@ private:
#if KJ_NO_EXCEPTIONS #if KJ_NO_EXCEPTIONS
#define KJ_EXPECT_THROW(type, code) \ #define KJ_EXPECT_THROW(type, code) \
do { \ do { \
KJ_EXPECT(::kj::_::expectFatalThrow(type, nullptr, [&]() { code; })); \ KJ_EXPECT(::kj::_::expectFatalThrow(::kj::Exception::Type::type, nullptr, [&]() { code; })); \
} while (false) } while (false)
#define KJ_EXPECT_THROW_MESSAGE(message, code) \ #define KJ_EXPECT_THROW_MESSAGE(message, code) \
do { \ do { \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment