changeset 80:98bd4d6355fe

Irccd: fix Irccd.SystemError not thrown
author David Demelier <markand@malikania.fr>
date Thu, 31 Mar 2016 12:16:00 +0200
parents d0deb5835aed
children 969f30acfb0e
files lib/irccd/js-irccd.cpp tests/js-irccd/main.cpp
diffstat 2 files changed, 80 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/lib/irccd/js-irccd.cpp	Wed Mar 30 21:30:53 2016 +0200
+++ b/lib/irccd/js-irccd.cpp	Thu Mar 31 12:16:00 2016 +0200
@@ -36,12 +36,15 @@
 
 void SystemError::raise(duk::ContextPtr ctx) const
 {
+	duk::StackAssert sa(ctx, 1);
+
 	duk::getGlobal<void>(ctx, "Irccd");
 	duk::getProperty<void>(ctx, -1, "SystemError");
+	duk::remove(ctx, -2);
 	duk::push(ctx, m_errno);
 	duk::push(ctx, m_message);
 	duk::create(ctx, 2);
-	duk::remove(ctx, -2);
+	duk::raise(ctx);
 }
 
 duk::Ret constructor(duk::ContextPtr ctx)
@@ -71,15 +74,12 @@
 
 	/* Create the SystemError that inherits from Error */
 	duk::push(ctx, duk::Function{constructor, 2});
+	duk::push(ctx, duk::Object{});
 	duk::getGlobal<void>(ctx, "Error");
-	duk::push(ctx, duk::Function{[] (duk::ContextPtr) -> duk::Ret { return 0; }});
-	duk::getProperty<void>(ctx, -2, "prototype");
+	duk::getProperty<void>(ctx, -1, "prototype");
+	duk::remove(ctx, -2);
+	duk::setPrototype(ctx, -2);
 	duk::putProperty(ctx, -2, "prototype");
-	duk::create(ctx, 0);
-	duk::putProperty(ctx, -3, "prototype");
-	duk::pop(ctx);
-	duk::dup(ctx, -1);
-	duk::putProperty(ctx, -2, "constructor");
 	duk::putProperty(ctx, -2, "SystemError");
 
 	/* Set Irccd as global */
--- a/tests/js-irccd/main.cpp	Wed Mar 30 21:30:53 2016 +0200
+++ b/tests/js-irccd/main.cpp	Thu Mar 31 12:16:00 2016 +0200
@@ -49,6 +49,78 @@
 	}
 }
 
+TEST(SystemError, fromJavascript)
+{
+	duk::Context ctx;
+
+	loadJsIrccd(ctx);
+
+	try {
+		auto ret = duk::pevalString(ctx,
+			"try {"
+			"  throw new Irccd.SystemError(1, 'test');"
+			"} catch (e) {"
+			"  errno = e.errno;"
+			"  name = e.name;"
+			"  message = e.message;"
+			"  v1 = (e instanceof Error);"
+			"  v2 = (e instanceof Irccd.SystemError);"
+			"}"
+		);
+
+		if (ret != 0)
+			throw duk::error(ctx, -1);
+
+		ASSERT_EQ(1, duk::getGlobal<int>(ctx, "errno"));
+		ASSERT_EQ("SystemError", duk::getGlobal<std::string>(ctx, "name"));
+		ASSERT_EQ("test", duk::getGlobal<std::string>(ctx, "message"));
+		ASSERT_TRUE(duk::getGlobal<bool>(ctx, "v1"));
+		ASSERT_TRUE(duk::getGlobal<bool>(ctx, "v2"));
+	} catch (const std::exception &ex) {
+		FAIL() << ex.what();
+	}
+}
+
+TEST(SystemError, fromNative)
+{
+	duk::Context ctx;
+
+	loadJsIrccd(ctx);
+
+	try {
+		duk::push(ctx, duk::Function{[] (duk::ContextPtr ctx) -> duk::Ret {
+			duk::raise(ctx, SystemError{EINVAL, "hey"});
+
+			return 0;
+		}});
+
+		duk::putGlobal(ctx, "f");
+
+		auto ret = duk::pevalString(ctx,
+			"try {"
+			"  f();"
+			"} catch (e) {"
+			"  errno = e.errno;"
+			"  name = e.name;"
+			"  message = e.message;"
+			"  v1 = (e instanceof Error);"
+			"  v2 = (e instanceof Irccd.SystemError);"
+			"}"
+		);
+
+		if (ret != 0)
+			throw duk::error(ctx, -1);
+
+		ASSERT_EQ(EINVAL, duk::getGlobal<int>(ctx, "errno"));
+		ASSERT_EQ("SystemError", duk::getGlobal<std::string>(ctx, "name"));
+		ASSERT_EQ("hey", duk::getGlobal<std::string>(ctx, "message"));
+		ASSERT_TRUE(duk::getGlobal<bool>(ctx, "v1"));
+		ASSERT_TRUE(duk::getGlobal<bool>(ctx, "v2"));
+	} catch (const std::exception &ex) {
+		FAIL() << ex.what();
+	}
+}
+
 int main(int argc, char **argv)
 {
 	testing::InitGoogleTest(&argc, argv);