changeset 612:18ec7f4fc3de

Js: new style, closes #685
author David Demelier <markand@malikania.fr>
date Mon, 21 Aug 2017 11:08:49 +0200
parents beef249c796c
children 1c9d99ac4b68
files CMakeLists.txt cmake/CodeDefineModule.cmake modules/js/duktape.hpp modules/js/test/main.cpp
diffstat 4 files changed, 252 insertions(+), 374 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Sat Jul 01 07:35:13 2017 +0200
+++ b/CMakeLists.txt	Mon Aug 21 11:08:49 2017 +0200
@@ -33,6 +33,7 @@
 
 # Doxygen target.
 find_package(Doxygen)
+find_package(Boost REQUIRED COMPONENTS unit_test_framework)
 
 if (DOXYGEN_FOUND)
     configure_file(
--- a/cmake/CodeDefineModule.cmake	Sat Jul 01 07:35:13 2017 +0200
+++ b/cmake/CodeDefineModule.cmake	Mon Aug 21 11:08:49 2017 +0200
@@ -63,14 +63,24 @@
                 RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR}
                 RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_BINARY_DIR}
         )
-        target_compile_definitions(test-${MOD_NAME} PRIVATE ${MOD_FLAGS})
+        target_compile_definitions(
+            test-${MOD_NAME}
+            PRIVATE
+                BOOST_TEST_DYN_LINK
+                ${MOD_FLAGS}
+        )
         target_include_directories(
             test-${MOD_NAME}
             PRIVATE
                 ${CMAKE_CURRENT_SOURCE_DIR}
                 ${MOD_INCLUDES}
         )
-        target_link_libraries(test-${MOD_NAME} gtest ${MOD_LIBRARIES})
+        target_link_libraries(
+            test-${MOD_NAME}
+            Boost::unit_test_framework
+            gtest
+            ${MOD_LIBRARIES}
+        )
 
         # Register the test.
         add_test(
--- a/modules/js/duktape.hpp	Sat Jul 01 07:35:13 2017 +0200
+++ b/modules/js/duktape.hpp	Mon Aug 21 11:08:49 2017 +0200
@@ -36,7 +36,6 @@
 #include <duktape.h>
 
 /**
- * \class StackAssert
  * \brief Stack sanity checker.
  *
  * Instanciate this class where you need to manipulate the Duktape stack outside
@@ -47,12 +46,12 @@
  *
  * To use it, just declare an lvalue at the beginning of your function.
  */
-class StackAssert {
+class dukx_stack_guard {
 #if !defined(NDEBUG)
 private:
-    duk_context *m_context;
-    unsigned m_expected;
-    unsigned m_begin;
+    duk_context* context_;
+    unsigned expected_;
+    unsigned begin_;
 #endif
 
 public:
@@ -64,11 +63,11 @@
      * \param ctx the context
      * \param expected the size expected relative to the already existing values
      */
-    inline StackAssert(duk_context *ctx, unsigned expected = 0) noexcept
+    inline dukx_stack_guard(duk_context* ctx, unsigned expected = 0) noexcept
 #if !defined(NDEBUG)
-        : m_context(ctx)
-        , m_expected(expected)
-        , m_begin(static_cast<unsigned>(duk_get_top(ctx)))
+        : context_(ctx)
+        , expected_(expected)
+        , begin_(static_cast<unsigned>(duk_get_top(ctx)))
 #endif
     {
 #if defined(NDEBUG)
@@ -82,16 +81,16 @@
      *
      * No-op if NDEBUG is set.
      */
-    inline ~StackAssert() noexcept
+    inline ~dukx_stack_guard() noexcept
     {
 #if !defined(NDEBUG)
-        if (static_cast<unsigned>(duk_get_top(m_context)) - m_begin != m_expected) {
-            std::fprintf(stderr, "Corrupt stack detection in StackAssert:\n");
-            std::fprintf(stderr, "  Size at start:            %u\n", m_begin);
-            std::fprintf(stderr, "  Size at end:              %d\n", duk_get_top(m_context));
-            std::fprintf(stderr, "  Expected (user):          %u\n", m_expected);
-            std::fprintf(stderr, "  Expected (adjusted):      %u\n", m_expected + m_begin);
-            std::fprintf(stderr, "  Number of stale values:   %u\n", duk_get_top(m_context) - m_begin - m_expected);
+        if (static_cast<unsigned>(duk_get_top(context_)) - begin_ != expected_) {
+            std::fprintf(stderr, "Corrupt stack detection in dukx_stack_guard:\n");
+            std::fprintf(stderr, "  Size at start:            %u\n", begin_);
+            std::fprintf(stderr, "  Size at end:              %d\n", duk_get_top(context_));
+            std::fprintf(stderr, "  Expected (user):          %u\n", expected_);
+            std::fprintf(stderr, "  Expected (adjusted):      %u\n", expected_ + begin_);
+            std::fprintf(stderr, "  Number of stale values:   %u\n", duk_get_top(context_) - begin_ - expected_);
             std::abort();
         }
 #endif
@@ -99,18 +98,81 @@
 };
 
 /**
- * \class Exception
- * \brief Error description.
+ * \brief dukx_error description.
  *
- * This class fills the fields got in an Error object.
+ * This class fills the fields got in an dukx_error object.
  */
-class Exception : public std::exception {
+class dukx_exception : public std::exception {
+private:
+    std::string name_;
+    std::string message_;
+    std::string stack_;
+    std::string filename_;
+    int linenumber_{0};
+
 public:
-    std::string name;       //!< name of error
-    std::string message;    //!< error message
-    std::string stack;      //!< stack if available
-    std::string fileName;   //!< filename if applicable
-    int lineNumber{0};      //!< line number if applicable
+    inline dukx_exception(std::string name,
+                          std::string message,
+                          std::string stack = "",
+                          std::string filename = "",
+                          int linenumber = 0) noexcept
+        : name_(std::move(name))
+        , message_(std::move(message))
+        , stack_(std::move(stack))
+        , filename_(std::move(filename))
+        , linenumber_(linenumber)
+    {
+    }
+
+    /**
+     * Get exception name (e.g. URIdukx_error).
+     *
+     * \return the exception name
+     */
+    inline const std::string& name() const noexcept
+    {
+        return name_;
+    }
+
+    /**
+     * Get error message.
+     *
+     * \return the error message
+     */
+    inline const std::string& message() const noexcept
+    {
+        return message_;
+    }
+
+    /**
+     * Get stack if available.
+     *
+     * \return the stack
+     */
+    inline const std::string& stack() const noexcept
+    {
+        return stack_;
+    }
+
+    /**
+     * Get filename if available.
+     *
+     * \return the filename
+     */
+    inline const std::string& filename() const noexcept
+    {
+        return filename_;
+    }
+
+    /**
+     * Get the line number if available.
+     *
+     * \return the line number
+     */
+    inline int linenumber() const noexcept
+    {
+        return linenumber_;
+    }
 
     /**
      * Get the error message. This effectively returns message field.
@@ -119,7 +181,7 @@
      */
     const char *what() const noexcept override
     {
-        return message.c_str();
+        return message_.c_str();
     }
 };
 
@@ -128,38 +190,35 @@
  *
  * This class is implicitly convertible to duk_context for convenience.
  */
-class UniqueContext {
+class dukx_unique_context {
 private:
-    using Deleter = void (*)(duk_context *);
-    using Handle = std::unique_ptr<duk_context, Deleter>;
+    std::unique_ptr<duk_context, void (*)(duk_context*)> handle_;
 
-    Handle m_handle;
-
-    UniqueContext(const UniqueContext &) = delete;
-    UniqueContext &operator=(const UniqueContext &) = delete;
+    dukx_unique_context(const dukx_unique_context&) = delete;
+    dukx_unique_context& operator=(const dukx_unique_context&) = delete;
 
 public:
     /**
      * Create default context.
      */
-    inline UniqueContext()
-        : m_handle(duk_create_heap_default(), duk_destroy_heap)
+    inline dukx_unique_context()
+        : handle_(duk_create_heap_default(), duk_destroy_heap)
     {
     }
 
     /**
      * Default move constructor.
      */
-    UniqueContext(UniqueContext &&) noexcept = default;
+    dukx_unique_context(dukx_unique_context&&) noexcept = default;
 
     /**
      * Convert the context to the native Duktape/C type.
      *
      * \return the duk_context
      */
-    inline operator duk_context *() noexcept
+    inline operator duk_context*() noexcept
     {
-        return m_handle.get();
+        return handle_.get();
     }
 
     /**
@@ -167,9 +226,9 @@
      *
      * \return the duk_context
      */
-    inline operator duk_context *() const noexcept
+    inline operator duk_context*() const noexcept
     {
-        return m_handle.get();
+        return handle_.get();
     }
 
     /**
@@ -177,18 +236,17 @@
      *
      * \return this
      */
-    UniqueContext &operator=(UniqueContext &&) noexcept = delete;
+    dukx_unique_context& operator=(dukx_unique_context&&) noexcept = delete;
 };
 
 /**
- * \class Error
  * \brief Base ECMAScript error class.
  * \warning Override the function create for your own exceptions
  */
-class Error {
+class dukx_error {
 private:
-    int m_type{DUK_ERR_ERROR};
-    std::string m_message;
+    int type_{DUK_ERR_ERROR};
+    std::string message_;
 
 protected:
     /**
@@ -198,9 +256,9 @@
      * \param type of error (e.g. DUK_ERR_ERROR)
      * \param message the message
      */
-    inline Error(int type, std::string message) noexcept
-        : m_type(type)
-        , m_message(std::move(message))
+    inline dukx_error(int type, std::string message) noexcept
+        : type_(type)
+        , message_(std::move(message))
     {
     }
 
@@ -210,8 +268,8 @@
      *
      * \param message the message
      */
-    inline Error(std::string message) noexcept
-        : m_message(std::move(message))
+    inline dukx_error(std::string message) noexcept
+        : message_(std::move(message))
     {
     }
 
@@ -221,110 +279,104 @@
      * \note the default implementation search for the global variables
      * \param ctx the context
      */
-    virtual void raise(duk_context *ctx) const
+    virtual void raise(duk_context* ctx) const
     {
-        duk_error(ctx, m_type, "%s", m_message.c_str());
+        duk_error(ctx, type_, "%s", message_.c_str());
     }
 };
 
 /**
- * \class EvalError
  * \brief Error in eval() function.
  */
-class EvalError : public Error {
+class dukx_eval_error : public dukx_error {
 public:
     /**
-     * Construct an EvalError.
+     * Construct an EvalError
      *
      * \param message the message
      */
-    inline EvalError(std::string message) noexcept
-        : Error(DUK_ERR_EVAL_ERROR, std::move(message))
+    inline dukx_eval_error(std::string message) noexcept
+        : dukx_error(DUK_ERR_EVAL_ERROR, std::move(message))
     {
     }
 };
 
 /**
- * \class RangeError
  * \brief Value is out of range.
  */
-class RangeError : public Error {
+class dukx_range_error : public dukx_error {
 public:
     /**
      * Construct an RangeError.
      *
      * \param message the message
      */
-    inline RangeError(std::string message) noexcept
-        : Error(DUK_ERR_RANGE_ERROR, std::move(message))
+    inline dukx_range_error(std::string message) noexcept
+        : dukx_error(DUK_ERR_RANGE_ERROR, std::move(message))
     {
     }
 };
 
 /**
- * \class ReferenceError
  * \brief Trying to use a variable that does not exist.
  */
-class ReferenceError : public Error {
+class dukx_reference_error : public dukx_error {
 public:
     /**
      * Construct an ReferenceError.
      *
      * \param message the message
      */
-    inline ReferenceError(std::string message) noexcept
-        : Error(DUK_ERR_REFERENCE_ERROR, std::move(message))
+    inline dukx_reference_error(std::string message) noexcept
+        : dukx_error(DUK_ERR_REFERENCE_ERROR, std::move(message))
     {
     }
 };
 
 /**
- * \class SyntaxError
  * \brief Syntax error in the script.
  */
-class SyntaxError : public Error {
+class dukx_syntax_error : public dukx_error {
 public:
     /**
      * Construct an SyntaxError.
      *
      * \param message the message
      */
-    inline SyntaxError(std::string message) noexcept
-        : Error(DUK_ERR_SYNTAX_ERROR, std::move(message))
+    inline dukx_syntax_error(std::string message) noexcept
+        : dukx_error(DUK_ERR_SYNTAX_ERROR, std::move(message))
     {
     }
 };
 
 /**
- * \class TypeError
  * \brief Invalid type given.
  */
-class TypeError : public Error {
+class dukx_type_error : public dukx_error {
 public:
     /**
      * Construct an TypeError.
      *
      * \param message the message
      */
-    inline TypeError(std::string message) noexcept
-        : Error(DUK_ERR_TYPE_ERROR, std::move(message))
+    inline dukx_type_error(std::string message) noexcept
+        : dukx_error(DUK_ERR_TYPE_ERROR, std::move(message))
     {
     }
 };
 
 /**
- * \class URIError
  * \brief URI manipulation failure.
  */
-class URIError : public Error {
+class dukx_uri_error : public dukx_error {
 public:
     /**
      * Construct an URIError.
      *
      * \param message the message
      */
-    inline URIError(std::string message) noexcept
-        : Error(DUK_ERR_URI_ERROR, std::move(message))
+    inline dukx_uri_error(std::string message) noexcept
+        : dukx_error(DUK_ERR_URI_ERROR, std::move(message))
     {
     }
 };
@@ -338,28 +390,29 @@
  * \param pop if true, also remove the exception from the stack
  * \return the information
  */
-inline Exception dukx_exception(duk_context *ctx, int index, bool pop = true)
+inline dukx_exception dukx_get_exception(duk_context* ctx, int index, bool pop = true)
 {
-    Exception ex;
+    std::string name, message, stack, filename;
+    int linenumber;
 
     index = duk_normalize_index(ctx, index);
 
     duk_get_prop_string(ctx, index, "name");
-    ex.name = duk_to_string(ctx, -1);
+    name = duk_to_string(ctx, -1);
     duk_get_prop_string(ctx, index, "message");
-    ex.message = duk_to_string(ctx, -1);
+    message = duk_to_string(ctx, -1);
     duk_get_prop_string(ctx, index, "fileName");
-    ex.fileName = duk_to_string(ctx, -1);
+    filename = duk_to_string(ctx, -1);
     duk_get_prop_string(ctx, index, "lineNumber");
-    ex.lineNumber = duk_to_int(ctx, -1);
+    linenumber = duk_to_int(ctx, -1);
     duk_get_prop_string(ctx, index, "stack");
-    ex.stack = duk_to_string(ctx, -1);
+    stack = duk_to_string(ctx, -1);
     duk_pop_n(ctx, 5);
 
     if (pop)
         duk_remove(ctx, index);
 
-    return ex;
+    return dukx_exception(name, message, stack, filename, linenumber);
 }
 
 /**
@@ -367,11 +420,13 @@
  *
  * \param ctx the context
  * \param ex the exception
+ * \return 0 for convenience
  */
 template <typename Exception>
-void dukx_throw(duk_context *ctx, const Exception &ex)
+int dukx_throw(duk_context* ctx, const Exception& ex)
 {
     ex.raise(ctx);
+    return 0;
 }
 
 /**
@@ -381,10 +436,10 @@
  * \param index the index
  * \return the string
  */
-inline std::string dukx_get_std_string(duk_context *ctx, int index)
+inline std::string dukx_get_std_string(duk_context* ctx, int index)
 {
     duk_size_t size;
-    const char *text = duk_get_lstring(ctx, index, &size);
+    const char* text = duk_get_lstring(ctx, index, &size);
 
     return std::string(text, size);
 }
@@ -396,10 +451,10 @@
  * \param index the index
  * \return the string
  */
-inline std::string dukx_require_std_string(duk_context *ctx, int index)
+inline std::string dukx_require_std_string(duk_context* ctx, int index)
 {
     duk_size_t size;
-    const char *text = duk_require_lstring(ctx, index, &size);
+    const char* text = duk_require_lstring(ctx, index, &size);
 
     return std::string(text, size);
 }
@@ -410,96 +465,9 @@
  * \param ctx the context
  * \param str the string
  */
-inline void dukx_push_std_string(duk_context *ctx, const std::string &str)
+inline void dukx_push_std_string(duk_context* ctx, const std::string& str)
 {
     duk_push_lstring(ctx, str.data(), str.length());
 }
 
-/**
- * Get an array.
- *
- * \param ctx the context
- * \param index the array index
- * \param get the conversion function (e.g. duk_get_int)
- */
-template <typename Getter>
-auto dukx_get_array(duk_context *ctx, duk_idx_t index, Getter &&get)
-{
-    using T = decltype(get(ctx, 0));
-
-    std::vector<T> result;
-    std::size_t length = duk_get_length(ctx, index);
-
-    for (std::size_t i = 0; i < length; ++i) {
-        duk_get_prop_index(ctx, -1, i);
-        result.push_back(get(ctx, -1));
-        duk_pop(ctx);
-    }
-
-    return result;
-}
-
-/**
- * Push an array.
- *
- * \param ctx the context
- * \param values the values
- * \param push the function to push values
- */
-template <typename T, typename Pusher>
-void dukx_push_array(duk_context *ctx, const std::vector<T> &values, Pusher &&push)
-{
-    duk_push_array(ctx);
-
-    int i = 0;
-    for (auto x : values) {
-        push(ctx, x);
-        duk_put_prop_index(ctx, -2, i++);
-    }
-}
-
-/**
- * Get an object.
- *
- * \param ctx the context
- * \param index the object index
- * \param get the conversion function (e.g. duk_get_int)
- */
-template <typename Getter>
-auto dukx_get_object(duk_context *ctx, duk_idx_t index, Getter &&get)
-{
-    using T = decltype(get(ctx, 0));
-
-    std::unordered_map<std::string, T> result;
-
-    duk_enum(ctx, index, 0);
-
-    while (duk_next(ctx, -1, true)) {
-        result.emplace(dukx_get_std_string(ctx, -2), get(ctx, -1));
-        duk_pop_2(ctx);
-    }
-
-    duk_pop(ctx);
-
-    return result;
-}
-
-/**
- * Push an object.
- *
- * \param ctx the context
- * \param values the values
- * \param push the function to push values
- */
-template <typename T, typename Pusher>
-void dukx_push_object(duk_context *ctx, const std::unordered_map<std::string, T> &values, Pusher &&push)
-{
-    duk_push_object(ctx);
-
-    for (const auto &pair : values) {
-        push(ctx, pair.second);
-        duk_put_prop_string(ctx, -2, pair.first.c_str());
-    }
-}
-
 #endif // !DUKTAPE_HPP
--- a/modules/js/test/main.cpp	Sat Jul 01 07:35:13 2017 +0200
+++ b/modules/js/test/main.cpp	Mon Aug 21 11:08:49 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * TestJsUnicode.cpp -- test irccd JS functions
+ * main.cpp -- test Duktape extras
  *
  * Copyright (c) 2016 David Demelier <markand@malikania.fr>
  *
@@ -16,277 +16,176 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <gtest/gtest.h>
+#define BOOST_TEST_MODULE "Duktape"
+#include <boost/test/unit_test.hpp>
 
 #include <duktape.hpp>
 
-TEST(Push, array)
-{
-    UniqueContext ctx;
-
-    std::vector<int> v{1, 2, 3};
-
-    dukx_push_array(ctx, v, duk_push_int);
-    ASSERT_EQ(v, dukx_get_array(ctx, -1, duk_get_int));
-}
-
-TEST(Push, object)
-{
-    UniqueContext ctx;
-
-    std::unordered_map<std::string, std::string> o{
-        { "file", "foo.txt" },
-        { "password", "test" }
-    };
-
-    dukx_push_object(ctx, o, dukx_push_std_string);
-    ASSERT_EQ(o, dukx_get_object(ctx, -1, dukx_get_std_string));
-}
-
-#if 0
-
-TEST(Basics, enumerate)
-{
-    duk::UniqueContext context;
-
-    ASSERT_EQ(0, duk::top(context));
-    duk::push(context, duk::Object{});
-    duk::putProperty(context, -1, "x", 123);
-    duk::putProperty(context, -1, "y", 456);
-    ASSERT_EQ(1, duk::top(context));
-    duk::enumerate(context, -1, 0, true, [] (duk::Context *ctx) {
-        ASSERT_EQ(DUK_TYPE_STRING, duk::type(ctx, -2));
-        ASSERT_EQ(DUK_TYPE_NUMBER, duk::type(ctx, -1));
-
-        if (duk::get<std::string>(ctx, -2) == "x")
-            ASSERT_EQ(123, duk::get<int>(ctx, -1));
-        if (duk::get<std::string>(ctx, -2) == "y")
-            ASSERT_EQ(456, duk::get<int>(ctx, -1));
-    });
-    ASSERT_EQ(1, duk::top(context));
-}
-
-/*
- * Exception handling.
- * ------------------------------------------------------------------
- */
-
-TEST(Exception, raise)
-{
-    duk::UniqueContext context;
-
-    duk::putGlobal(context, "f", duk::Function{[] (duk::Context *ctx) -> duk_idx_t {
-        duk::raise(ctx, DUK_ERR_ERROR, "error thrown");
-
-        return 0;
-    }});
-    duk::evalString(context,
-        "try {"
-        "  f();"
-        "} catch (ex) {"
-        "  name = ex.name;"
-        "  message = ex.message;"
-        "  received = true;"
-        "}"
-    );
-
-    ASSERT_TRUE(duk::getGlobal<bool>(context, "received"));
-    ASSERT_EQ("Error", duk::getGlobal<std::string>(context, "name"));
-    ASSERT_EQ("error thrown", duk::getGlobal<std::string>(context, "message"));
-}
-
 /*
  * Standard exceptions.
  * --------------------------------------------------------
  */
 
-TEST(StandardExceptions, error)
+BOOST_AUTO_TEST_SUITE(standard_exceptions)
+
+BOOST_AUTO_TEST_CASE(error)
 {
-    duk::UniqueContext context;
-
-    duk::putGlobal(context, "f", duk::Function{[] (duk::Context *ctx) -> duk_idx_t {
-        duk::raise(ctx, duk::Error("error thrown"));
+    dukx_unique_context ctx;
 
-        return 0;
-    }});
-    duk::evalString(context,
-        "try {"
-        "  f();"
-        "} catch (ex) {"
-        "  name = ex.name;"
-        "  message = ex.message;"
-        "  received = true;"
-        "  correct = (ex instanceof Error);"
-        "}"
-    );
-
-    ASSERT_TRUE(duk::getGlobal<bool>(context, "received"));
-    ASSERT_EQ("Error", duk::getGlobal<std::string>(context, "name"));
-    ASSERT_EQ("error thrown", duk::getGlobal<std::string>(context, "message"));
-    ASSERT_TRUE(duk::getGlobal<bool>(context, "correct"));
-}
-
-TEST(StandardExceptions, evalError)
-{
-    duk::UniqueContext context;
-
-    duk::putGlobal(context, "f", duk::Function{[] (duk::Context *ctx) -> duk_idx_t {
-        duk::raise(ctx, duk::EvalError("error thrown"));
-
-        return 0;
-    }});
-    duk::evalString(context,
+    duk_push_c_function(ctx, [] (duk_context* ctx) -> duk_idx_t {
+        return dukx_throw(ctx, dukx_error("error thrown"));
+    }, 0);
+    duk_put_global_string(ctx, "f");
+    duk_peval_string(ctx,
         "try {"
         "  f();"
         "} catch (ex) {"
         "  name = ex.name;"
         "  message = ex.message;"
-        "  received = true;"
-        "  correct = (ex instanceof EvalError);"
+        "  instance = (ex instanceof Error);"
         "}"
     );
 
-    ASSERT_TRUE(duk::getGlobal<bool>(context, "received"));
-    ASSERT_EQ("EvalError", duk::getGlobal<std::string>(context, "name"));
-    ASSERT_EQ("error thrown", duk::getGlobal<std::string>(context, "message"));
-    ASSERT_TRUE(duk::getGlobal<bool>(context, "correct"));
+    duk_get_global_string(ctx, "name");
+    BOOST_REQUIRE_EQUAL("Error", dukx_get_std_string(ctx, -1));
+    duk_get_global_string(ctx, "message");
+    BOOST_REQUIRE_EQUAL("error thrown", dukx_get_std_string(ctx, -1));
+    duk_get_global_string(ctx, "instance");
+    BOOST_REQUIRE(duk_get_boolean(ctx, -1));
 }
 
-TEST(StandardExceptions, rangeError)
+BOOST_AUTO_TEST_CASE(eval_error)
 {
-    duk::UniqueContext context;
+    dukx_unique_context ctx;
 
-    duk::putGlobal(context, "f", duk::Function{[] (duk::Context *ctx) -> duk_idx_t {
-        duk::raise(ctx, duk::RangeError("error thrown"));
-
-        return 0;
-    }});
-    duk::evalString(context,
+    duk_push_c_function(ctx, [] (duk_context* ctx) -> duk_idx_t {
+        return dukx_throw(ctx, dukx_eval_error("error thrown"));
+    }, 0);
+    duk_put_global_string(ctx, "f");
+    duk_peval_string(ctx,
         "try {"
         "  f();"
         "} catch (ex) {"
         "  name = ex.name;"
         "  message = ex.message;"
-        "  received = true;"
-        "  correct = (ex instanceof RangeError);"
+        "  instance = (ex instanceof EvalError);"
         "}"
     );
 
-    ASSERT_TRUE(duk::getGlobal<bool>(context, "received"));
-    ASSERT_EQ("RangeError", duk::getGlobal<std::string>(context, "name"));
-    ASSERT_EQ("error thrown", duk::getGlobal<std::string>(context, "message"));
-    ASSERT_TRUE(duk::getGlobal<bool>(context, "correct"));
+    duk_get_global_string(ctx, "name");
+    BOOST_REQUIRE_EQUAL("EvalError", dukx_get_std_string(ctx, -1));
+    duk_get_global_string(ctx, "message");
+    BOOST_REQUIRE_EQUAL("error thrown", dukx_get_std_string(ctx, -1));
+    duk_get_global_string(ctx, "instance");
+    BOOST_REQUIRE(duk_get_boolean(ctx, -1));
 }
 
-TEST(StandardExceptions, referenceError)
+BOOST_AUTO_TEST_CASE(range_error)
 {
-    duk::UniqueContext context;
+    dukx_unique_context ctx;
 
-    duk::putGlobal(context, "f", duk::Function{[] (duk::Context *ctx) -> duk_idx_t {
-        duk::raise(ctx, duk::ReferenceError("error thrown"));
-
-        return 0;
-    }});
-    duk::evalString(context,
+    duk_push_c_function(ctx, [] (duk_context* ctx) -> duk_idx_t {
+        return dukx_throw(ctx, dukx_range_error("error thrown"));
+    }, 0);
+    duk_put_global_string(ctx, "f");
+    duk_peval_string(ctx,
         "try {"
         "  f();"
         "} catch (ex) {"
         "  name = ex.name;"
         "  message = ex.message;"
-        "  received = true;"
-        "  correct = (ex instanceof ReferenceError);"
+        "  instance = (ex instanceof RangeError);"
         "}"
     );
 
-    ASSERT_TRUE(duk::getGlobal<bool>(context, "received"));
-    ASSERT_EQ("ReferenceError", duk::getGlobal<std::string>(context, "name"));
-    ASSERT_EQ("error thrown", duk::getGlobal<std::string>(context, "message"));
-    ASSERT_TRUE(duk::getGlobal<bool>(context, "correct"));
+    duk_get_global_string(ctx, "name");
+    BOOST_REQUIRE_EQUAL("RangeError", dukx_get_std_string(ctx, -1));
+    duk_get_global_string(ctx, "message");
+    BOOST_REQUIRE_EQUAL("error thrown", dukx_get_std_string(ctx, -1));
+    duk_get_global_string(ctx, "instance");
+    BOOST_REQUIRE(duk_get_boolean(ctx, -1));
 }
 
-TEST(StandardExceptions, syntaxError)
+BOOST_AUTO_TEST_CASE(reference_error)
 {
-    duk::UniqueContext context;
+    dukx_unique_context ctx;
 
-    duk::putGlobal(context, "f", duk::Function{[] (duk::Context *ctx) -> duk_idx_t {
-        duk::raise(ctx, duk::SyntaxError("error thrown"));
-
-        return 0;
-    }});
-    duk::evalString(context,
+    duk_push_c_function(ctx, [] (duk_context* ctx) -> duk_idx_t {
+        return dukx_throw(ctx, dukx_reference_error("error thrown"));
+    }, 0);
+    duk_put_global_string(ctx, "f");
+    duk_peval_string(ctx,
         "try {"
         "  f();"
         "} catch (ex) {"
         "  name = ex.name;"
         "  message = ex.message;"
-        "  received = true;"
-        "  correct = (ex instanceof SyntaxError);"
+        "  instance = (ex instanceof ReferenceError);"
         "}"
     );
 
-    ASSERT_TRUE(duk::getGlobal<bool>(context, "received"));
-    ASSERT_EQ("SyntaxError", duk::getGlobal<std::string>(context, "name"));
-    ASSERT_EQ("error thrown", duk::getGlobal<std::string>(context, "message"));
-    ASSERT_TRUE(duk::getGlobal<bool>(context, "correct"));
+    duk_get_global_string(ctx, "name");
+    BOOST_REQUIRE_EQUAL("ReferenceError", dukx_get_std_string(ctx, -1));
+    duk_get_global_string(ctx, "message");
+    BOOST_REQUIRE_EQUAL("error thrown", dukx_get_std_string(ctx, -1));
+    duk_get_global_string(ctx, "instance");
+    BOOST_REQUIRE(duk_get_boolean(ctx, -1));
 }
 
-TEST(StandardExceptions, typeError)
+BOOST_AUTO_TEST_CASE(syntax_error)
 {
-    duk::UniqueContext context;
+    dukx_unique_context ctx;
 
-    duk::putGlobal(context, "f", duk::Function{[] (duk::Context *ctx) -> duk_idx_t {
-        duk::raise(ctx, duk::TypeError("error thrown"));
-
-        return 0;
-    }});
-    duk::evalString(context,
+    duk_push_c_function(ctx, [] (duk_context* ctx) -> duk_idx_t {
+        return dukx_throw(ctx, dukx_syntax_error("error thrown"));
+    }, 0);
+    duk_put_global_string(ctx, "f");
+    duk_peval_string(ctx,
         "try {"
         "  f();"
         "} catch (ex) {"
         "  name = ex.name;"
         "  message = ex.message;"
-        "  received = true;"
-        "  correct = (ex instanceof TypeError);"
+        "  instance = (ex instanceof SyntaxError);"
         "}"
     );
 
-    ASSERT_TRUE(duk::getGlobal<bool>(context, "received"));
-    ASSERT_EQ("TypeError", duk::getGlobal<std::string>(context, "name"));
-    ASSERT_EQ("error thrown", duk::getGlobal<std::string>(context, "message"));
-    ASSERT_TRUE(duk::getGlobal<bool>(context, "correct"));
+    duk_get_global_string(ctx, "name");
+    BOOST_REQUIRE_EQUAL("SyntaxError", dukx_get_std_string(ctx, -1));
+    duk_get_global_string(ctx, "message");
+    BOOST_REQUIRE_EQUAL("error thrown", dukx_get_std_string(ctx, -1));
+    duk_get_global_string(ctx, "instance");
+    BOOST_REQUIRE(duk_get_boolean(ctx, -1));
 }
 
-TEST(StandardExceptions, uriError)
+BOOST_AUTO_TEST_CASE(type_error)
 {
-    duk::UniqueContext context;
+    dukx_unique_context ctx;
 
-    duk::putGlobal(context, "f", duk::Function{[] (duk::Context *ctx) -> duk_idx_t {
-        duk::raise(ctx, duk::URIError("error thrown"));
-
-        return 0;
-    }});
-    duk::evalString(context,
+    duk_push_c_function(ctx, [] (duk_context* ctx) -> duk_idx_t {
+        return dukx_throw(ctx, dukx_type_error("error thrown"));
+    }, 0);
+    duk_put_global_string(ctx, "f");
+    duk_peval_string(ctx,
         "try {"
         "  f();"
         "} catch (ex) {"
         "  name = ex.name;"
         "  message = ex.message;"
-        "  received = true;"
-        "  correct = (ex instanceof URIError);"
+        "  instance = (ex instanceof TypeError);"
         "}"
     );
 
-    ASSERT_TRUE(duk::getGlobal<bool>(context, "received"));
-    ASSERT_EQ("URIError", duk::getGlobal<std::string>(context, "name"));
-    ASSERT_EQ("error thrown", duk::getGlobal<std::string>(context, "message"));
-    ASSERT_TRUE(duk::getGlobal<bool>(context, "correct"));
+    duk_get_global_string(ctx, "name");
+    BOOST_REQUIRE_EQUAL("TypeError", dukx_get_std_string(ctx, -1));
+    duk_get_global_string(ctx, "message");
+    BOOST_REQUIRE_EQUAL("error thrown", dukx_get_std_string(ctx, -1));
+    duk_get_global_string(ctx, "instance");
+    BOOST_REQUIRE(duk_get_boolean(ctx, -1));
 }
 
-#endif
-
-int main(int argc, char **argv)
+BOOST_AUTO_TEST_CASE(uriError)
 {
-    testing::InitGoogleTest(&argc, argv);
+}
 
-    return RUN_ALL_TESTS();
-}
+BOOST_AUTO_TEST_SUITE_END()