diff --git a/.npmignore b/.npmignore index 5706e37..a6c4e2b 100644 --- a/.npmignore +++ b/.npmignore @@ -1,6 +1,5 @@ bin build -cpp-test tools .npmrc diff --git a/cpp-test/.gitignore b/cpp-test/.gitignore deleted file mode 100644 index cf4bab9..0000000 --- a/cpp-test/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!node_modules diff --git a/cpp-test/api/main.cpp b/cpp-test/api/main.cpp deleted file mode 100644 index b40c52d..0000000 --- a/cpp-test/api/main.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define CATCH_CONFIG_MAIN -#include "catch.hpp" -#include "napa-catch-reporter.h" \ No newline at end of file diff --git a/cpp-test/api/memory-tests.cpp b/cpp-test/api/memory-tests.cpp deleted file mode 100644 index 2ebe0cc..0000000 --- a/cpp-test/api/memory-tests.cpp +++ /dev/null @@ -1,172 +0,0 @@ -#include "catch.hpp" - -#include "napa-initialization-guard.h" - -#include -#include -#include -#include -#include -#include - -using namespace napa::memory; - -// Make sure Napa is initialized exactly once. -static NapaInitializationGuard _guard; - -namespace custom_allocator { - char buffer[1024]; - size_t allocated = 0; - size_t countMalloc = 0; - size_t countFree = 0; - - void* malloc(size_t size) { - void* pointer = buffer + allocated; - allocated += size; - countMalloc++; - return pointer; - } - - void free(void* pointer, size_t sizeHint) { - countFree++; - allocated -= sizeHint; - - // Do nothing but check memory are allocated from buffer. - if (pointer < buffer && pointer >= buffer + sizeof(buffer)) { - throw std::exception("bad memory in free"); - } - } - - void reset() { - allocated = 0; - countMalloc = 0; - countFree = 0; - } -} - -TEST_CASE("Napa memory C api tests", "[memory-capi]") { - SECTION("C runtime malloc/free from napa.dll") { - void* pointer = NAPA_MALLOC(4); - REQUIRE(pointer != nullptr); - - NAPA_FREE(pointer, 4); - } - - SECTION("Set default allocator and use it") { - NAPA_SET_DEFAULT_ALLOCATOR(custom_allocator::malloc, custom_allocator::free); - - size_t size = 5; - void* pointer = NAPA_ALLOCATE(size); - REQUIRE(pointer == custom_allocator::buffer); - REQUIRE(custom_allocator::allocated == size); - REQUIRE(custom_allocator::countMalloc == 1); - - NAPA_DEALLOCATE(pointer, size); - REQUIRE(custom_allocator::countFree == 1); - REQUIRE(custom_allocator::allocated == 0); - - NAPA_RESET_DEFAULT_ALLOCATOR(); - custom_allocator::reset(); - } -} - -TEST_CASE("Napa memory allocator tests", "[memory-allocators]") { - SECTION("Test CrtAllocator.") { - auto& allocator = NAPA_CRT_ALLOCATOR; - REQUIRE(std::string(allocator.GetType()) == "CrtAllocator"); - - auto pointer = allocator.Allocate(4); - REQUIRE(pointer != nullptr); - - allocator.Deallocate(pointer, 4); - } - - SECTION("Test GetDefaultAllocator.") { - NAPA_SET_DEFAULT_ALLOCATOR(custom_allocator::malloc, custom_allocator::free); - - auto& allocator = NAPA_DEFAULT_ALLOCATOR; - REQUIRE(std::string(allocator.GetType()) == "DefaultAllocator"); - - size_t size = 5; - auto pointer = allocator.Allocate(size); - REQUIRE(pointer == custom_allocator::buffer); - REQUIRE(custom_allocator::allocated == size); - REQUIRE(custom_allocator::countMalloc == 1); - - allocator.Deallocate(pointer, size); - REQUIRE(custom_allocator::countFree == 1); - REQUIRE(custom_allocator::allocated == 0); - - NAPA_RESET_DEFAULT_ALLOCATOR(); - custom_allocator::reset(); - } - - SECTION("Test CreateSimpleAllocatorDebugger") { - NAPA_SET_DEFAULT_ALLOCATOR(custom_allocator::malloc, custom_allocator::free); - - SimpleAllocatorDebugger debugger(std::shared_ptr(&GetDefaultAllocator(), [](Allocator*){})); - REQUIRE(std::string(debugger.GetType()) == "SimpleAllocatorDebugger"); - - size_t size = 5; - auto pointer = debugger.Allocate(size); - REQUIRE(pointer == custom_allocator::buffer); - REQUIRE(custom_allocator::allocated == size); - REQUIRE(custom_allocator::countMalloc == 1); - - debugger.Deallocate(pointer, size); - REQUIRE(custom_allocator::countFree == 1); - - REQUIRE(debugger.GetDebugInfo() == "{ \"allocate\": 1, \"deallocate\": 1, \"allocatedSize\": 5, \"deallocatedSize\": 5 }"); - NAPA_RESET_DEFAULT_ALLOCATOR(); - custom_allocator::reset(); - } -} - -struct Foo { - napa::stl::String _str; - napa::stl::Vector _vector; - napa::stl::Map _map; - Foo(const char* str, size_t size, int elements[]) - : _str(str) { - for (size_t i = 0; i < size; ++i) { - _vector.push_back(elements[i]); - _map.insert(std::make_pair(i, elements[i])); - } - } -}; - -TEST_CASE("Memory helpers", "[memory-helpers]") { - NAPA_SET_DEFAULT_ALLOCATOR(custom_allocator::malloc, custom_allocator::free); - - SECTION("NAPA_MAKE_UNIQUE") { - constexpr size_t count = 2; - int elems[count] = {1, 2}; - { - auto pointer = NAPA_MAKE_UNIQUE("hello world", count, elems); - REQUIRE(pointer != nullptr); - - REQUIRE(pointer->_str == "hello world"); - REQUIRE(pointer->_vector.size() == 2); - REQUIRE(pointer->_map.size() == 2); - } - REQUIRE(custom_allocator::allocated == 0); - custom_allocator::reset(); - } - - SECTION("NAPA_MAKE_SHARED") { - constexpr size_t count = 2; - int elems[count] = { 1, 2 }; - { - auto pointer = NAPA_MAKE_SHARED("hello world", count, elems); - REQUIRE(pointer != nullptr); - - REQUIRE(pointer->_str == "hello world"); - REQUIRE(pointer->_vector.size() == 2); - REQUIRE(pointer->_map.size() == 2); - } - REQUIRE(custom_allocator::allocated == 0); - custom_allocator::reset(); - } - - NAPA_RESET_DEFAULT_ALLOCATOR(); -} \ No newline at end of file diff --git a/cpp-test/api/napa-api-tests.vcxproj b/cpp-test/api/napa-api-tests.vcxproj deleted file mode 100644 index 055f005..0000000 --- a/cpp-test/api/napa-api-tests.vcxproj +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - Debug - x64 - - - Release - x64 - - - - {4D4E992D-79A5-419D-8161-55D93069C606} - - - Application - true - - - Application - false - - - $(OutDir)api-tests - - - - - $(NapaVanillaRoot)\inc;%(AdditionalIncludeDirectories) - - - - - - - - - - - - - - $(IntermediateOutputPath)\api-tests\node_modules\napajs\bin - - - $(IntermediateOutputPath)\api-tests\node_modules\napajs - - - - - - - - diff --git a/cpp-test/api/napa-initialization-guard.h b/cpp-test/api/napa-initialization-guard.h deleted file mode 100644 index 21139ce..0000000 --- a/cpp-test/api/napa-initialization-guard.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include - -class NapaInitializationGuard { -public: - NapaInitializationGuard() { - static NapaInitialization initialization; - } - -private: - class NapaInitialization { - public: - NapaInitialization() { - // Only call napa::Initialize once per process. - napa::Initialize("--loggingProvider console"); - } - - ~NapaInitialization() { - // Only call napa::Shutdown once per process. - napa::Shutdown(); - } - }; -}; diff --git a/cpp-test/api/zone-tests.cpp b/cpp-test/api/zone-tests.cpp deleted file mode 100644 index be49b83..0000000 --- a/cpp-test/api/zone-tests.cpp +++ /dev/null @@ -1,190 +0,0 @@ -#include "catch.hpp" - -#include "napa-initialization-guard.h" - -#include - -#include - -// Make sure Napa is initialized exactly once. -static NapaInitializationGuard _guard; - -TEST_CASE("zone apis", "[api]") { - - SECTION("create zone") { - napa::Zone zone("zone1"); - - REQUIRE(zone.GetId() == "zone1"); - } - - SECTION("broadcast valid javascript") { - napa::Zone zone("zone1"); - - auto result = zone.BroadcastSync("var i = 3 + 5;"); - - REQUIRE(result == NAPA_RESULT_SUCCESS); - } - - SECTION("broadcast illegal javascript") { - napa::Zone zone("zone1"); - - auto result = zone.BroadcastSync("var i = 3 +"); - - REQUIRE(result == NAPA_RESULT_BROADCAST_SCRIPT_ERROR); - } - - SECTION("broadcast and execute javascript") { - napa::Zone zone("zone1"); - - auto resultCode = zone.BroadcastSync("function func(a, b) { return Number(a) + Number(b); }"); - REQUIRE(resultCode == NAPA_RESULT_SUCCESS); - - napa::FunctionSpec spec; - spec.function = NAPA_STRING_REF("func"); - spec.arguments = { NAPA_STRING_REF("2"), NAPA_STRING_REF("3") }; - - auto result = zone.ExecuteSync(spec); - REQUIRE(result.code == NAPA_RESULT_SUCCESS); - REQUIRE(result.returnValue == "5"); - } - - SECTION("broadcast and execute javascript async") { - napa::Zone zone("zone1"); - - std::promise promise; - auto future = promise.get_future(); - - zone.Broadcast("function func(a, b) { return Number(a) + Number(b); }", [&promise, &zone](napa::ResultCode) { - napa::FunctionSpec spec; - spec.function = NAPA_STRING_REF("func"); - spec.arguments = { NAPA_STRING_REF("2"), NAPA_STRING_REF("3") }; - - zone.Execute(spec, [&promise](napa::Result result) { - promise.set_value(std::move(result)); - }); - }); - - auto result = future.get(); - REQUIRE(result.code == NAPA_RESULT_SUCCESS); - REQUIRE(result.returnValue == "5"); - } - - SECTION("broadcast and execute javascript without timing out") { - napa::Zone zone("zone1"); - - std::promise promise; - auto future = promise.get_future(); - - // Warmup to avoid loading napajs on first call - zone.BroadcastSync("require('napajs');"); - - zone.Broadcast("function func(a, b) { return Number(a) + Number(b); }", [&promise, &zone](napa::ResultCode) { - napa::FunctionSpec spec; - spec.function = NAPA_STRING_REF("func"); - spec.arguments = { NAPA_STRING_REF("2"), NAPA_STRING_REF("3") }; - spec.options.timeout = 100; - - zone.Execute(spec, [&promise](napa::Result result) { - promise.set_value(std::move(result)); - }); - }); - - auto result = future.get(); - REQUIRE(result.code == NAPA_RESULT_SUCCESS); - REQUIRE(result.returnValue == "5"); - } - - SECTION("broadcast and execute javascript with exceeded timeout") { - napa::Zone zone("zone1"); - - std::promise promise; - auto future = promise.get_future(); - - // Warmup to avoid loading napajs on first call - zone.BroadcastSync("require('napajs');"); - - zone.Broadcast("function func() { while(true) {} }", [&promise, &zone](napa::ResultCode) { - napa::FunctionSpec spec; - spec.function = NAPA_STRING_REF("func"); - spec.options.timeout = 200; - - zone.Execute(spec, [&promise](napa::Result result) { - promise.set_value(std::move(result)); - }); - }); - - auto result = future.get(); - REQUIRE(result.code == NAPA_RESULT_TIMEOUT); - REQUIRE(result.errorMessage == "Terminated due to timeout"); - } - - SECTION("execute 2 javascript functions, one succeeds and one times out") { - napa::Zone zone("zone1"); - - // Warmup to avoid loading napajs on first call - zone.BroadcastSync("require('napajs');"); - - auto res = zone.BroadcastSync("function f1(a, b) { return Number(a) + Number(b); }"); - REQUIRE(res == NAPA_RESULT_SUCCESS); - res = zone.BroadcastSync("function f2() { while(true) {} }"); - REQUIRE(res == NAPA_RESULT_SUCCESS); - - std::promise promise1; - auto future1 = promise1.get_future(); - - std::promise promise2; - auto future2 = promise2.get_future(); - - napa::FunctionSpec request1; - request1.function = NAPA_STRING_REF("f1"); - request1.arguments = { NAPA_STRING_REF("2"), NAPA_STRING_REF("3") }; - request1.options.timeout = 100; - - napa::FunctionSpec request2; - request2.function = NAPA_STRING_REF("f2"); - request2.options.timeout = 100; - - zone.Execute(request1, [&promise1](napa::Result result) { - promise1.set_value(std::move(result)); - }); - - zone.Execute(request2, [&promise2](napa::Result result) { - promise2.set_value(std::move(result)); - }); - - auto result = future1.get(); - REQUIRE(result.code == NAPA_RESULT_SUCCESS); - REQUIRE(result.returnValue == "5"); - - result = future2.get(); - REQUIRE(result.code == NAPA_RESULT_TIMEOUT); - REQUIRE(result.errorMessage == "Terminated due to timeout"); - } - - SECTION("broadcast javascript requiring a module") { - napa::Zone zone("zone1"); - - auto resultCode = zone.BroadcastSync("var path = require('path'); function func() { return path.extname('test.txt'); }"); - REQUIRE(resultCode == NAPA_RESULT_SUCCESS); - - napa::FunctionSpec spec; - spec.function = NAPA_STRING_REF("func"); - - auto result = zone.ExecuteSync(spec); - REQUIRE(result.code == NAPA_RESULT_SUCCESS); - REQUIRE(result.returnValue == "\".txt\""); - } - - SECTION("execute function in a module") { - napa::Zone zone("zone1"); - - napa::FunctionSpec spec; - spec.module = NAPA_STRING_REF("path"); - spec.function = NAPA_STRING_REF("extname"); - spec.arguments = { NAPA_STRING_REF("\"test.txt\"") }; - - auto result = zone.ExecuteSync(spec); - REQUIRE(result.code == NAPA_RESULT_SUCCESS); - REQUIRE(result.returnValue == "\".txt\""); - } -} diff --git a/cpp-test/component/main.cpp b/cpp-test/component/main.cpp deleted file mode 100644 index b40c52d..0000000 --- a/cpp-test/component/main.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define CATCH_CONFIG_MAIN -#include "catch.hpp" -#include "napa-catch-reporter.h" \ No newline at end of file diff --git a/cpp-test/component/napa-component-tests.vcxproj b/cpp-test/component/napa-component-tests.vcxproj deleted file mode 100644 index 27f1053..0000000 --- a/cpp-test/component/napa-component-tests.vcxproj +++ /dev/null @@ -1,122 +0,0 @@ - - - - - - - Debug - x64 - - - Release - x64 - - - - {2C45E1F3-34B4-4F39-A4F5-4CEE2512878C} - - - Application - true - - - Application - false - - - $(OutDir)component-tests - - - - - 4100;4251;4459;4996 - NAPA_EXPORTS;NAPA_BINDING_EXPORTS;BUILDING_NAPA_EXTENSION;BUILDING_V8_SHARED;%(PreprocessorDefinitions) - $(NapaVanillaRoot)\inc;%(AdditionalIncludeDirectories) - $(NapaVanillaRoot)\src;%(AdditionalIncludeDirectories) - $(NapaVanillaRoot)\test\component;%(AdditionalIncludeDirectories) - - - Winmm.lib;Dbghelp.lib;Shlwapi.lib;%(AdditionalDependencies) - $(NapaVanillaRoot)\src\$(IntermediateOutputPath)\napa.lib;%(AdditionalDependencies) - - - $(Pkgnapa_nodelib_vc140)\lib\$(BuildType)\$(BuildTarget)\v8_libbase.lib;%(AdditionalDependencies) - $(Pkgnapa_nodelib_vc140)\lib\$(BuildType)\$(BuildTarget)\v8_libplatform.lib;%(AdditionalDependencies) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $(IntermediateOutputPath)\component-tests\bin - - - $(IntermediateOutputPath)\component-tests\lib - *.j* - true - - - $(IntermediateOutputPath)\component-tests\bin - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/cpp-test/component/napa-initialization-guard.h b/cpp-test/component/napa-initialization-guard.h deleted file mode 100644 index 0b4567e..0000000 --- a/cpp-test/component/napa-initialization-guard.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include "providers/providers.h" -#include "settings/settings.h" -#include "v8/v8-common.h" - -class NapaInitializationGuard { -public: - NapaInitializationGuard() { - static NapaInitialization initialization; - } - -private: - class NapaInitialization { - public: - NapaInitialization() { - napa::settings::PlatformSettings settings; - settings.loggingProvider = "console"; - napa::providers::Initialize(settings); - - napa::v8_common::Initialize(); - } - - ~NapaInitialization() { - napa::v8_common::Shutdown(); - } - }; -}; diff --git a/cpp-test/component/node-zone-tests.cpp b/cpp-test/component/node-zone-tests.cpp deleted file mode 100644 index b337095..0000000 --- a/cpp-test/component/node-zone-tests.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "catch.hpp" - -#include "zone/node-zone.h" - -#include - -using namespace napa; -using namespace napa::zone; - -TEST_CASE("node zone not available before init", "[node-zone]") { - auto zone = NodeZone::Get(); - REQUIRE(zone == nullptr); -} - -TEST_CASE("node zone delegate should work after init", "[node-zone]") { - auto broadcast = [](const std::string& source, BroadcastCallback callback){ - callback(NAPA_RESULT_SUCCESS); - }; - - auto execute = [](const FunctionSpec& spec, ExecuteCallback callback) { - callback({ NAPA_RESULT_SUCCESS, "", std::string("hello world"), nullptr }); - }; - - NodeZone::Init(broadcast, execute); - - auto zone = NodeZone::Get(); - REQUIRE(zone != nullptr); - - { - std::promise promise; - auto future = promise.get_future(); - - zone->Broadcast("", [&promise](ResultCode resultCode) { - promise.set_value(NAPA_RESULT_SUCCESS); - }); - - REQUIRE(future.get() == NAPA_RESULT_SUCCESS); - } - - { - std::promise promise; - auto future = promise.get_future(); - - FunctionSpec spec; - zone->Execute(spec, [&promise](Result result) { - promise.set_value(std::move(result)); - }); - - auto result = future.get(); - REQUIRE(result.code == NAPA_RESULT_SUCCESS); - REQUIRE(result.returnValue == "hello world"); - } -} diff --git a/cpp-test/component/tasks-tests.cpp b/cpp-test/component/tasks-tests.cpp deleted file mode 100644 index ddb10f0..0000000 --- a/cpp-test/component/tasks-tests.cpp +++ /dev/null @@ -1,174 +0,0 @@ -#include "catch.hpp" - -#include "module/loader/module-loader.h" -#include "providers/providers.h" -#include "zone/eval-task.h" -#include "zone/call-task.h" -#include "zone/task-decorators.h" -#include "zone/worker-context.h" -#include "settings/settings.h" -#include "v8/array-buffer-allocator.h" -#include "napa-initialization-guard.h" - -#include "v8.h" - -#include - -using namespace napa; -using namespace napa::zone; -using namespace std::chrono_literals; - -// Make sure V8 it initialized exactly once. -static NapaInitializationGuard _guard; - -TEST_CASE("tasks", "[tasks]") { - // Create a new Isolate and make it the current one. - napa::v8_extensions::ArrayBufferAllocator allocator; - v8::Isolate::CreateParams createParams; - createParams.array_buffer_allocator = &allocator; - auto isolate = v8::Isolate::New(createParams); - - // Required scope/isolate guards - v8::Locker locker(isolate); - v8::Isolate::Scope isolateScope(isolate); - v8::HandleScope handleScope(isolate); - v8::Local context = v8::Context::New(isolate); - context->SetSecurityToken(v8::Undefined(isolate)); - v8::Context::Scope contextScope(context); - - INIT_WORKER_CONTEXT(); - CREATE_MODULE_LOADER(); - - EvalTask("require('../lib/index');").Execute(); - - SECTION("load valid javascript") { - ResultCode loadResponseCode; - EvalTask("var i = 3 + 5;", "", [&loadResponseCode](ResultCode code) { - loadResponseCode = code; - }).Execute(); - - REQUIRE(loadResponseCode == NAPA_RESULT_SUCCESS); - } - - SECTION("load fails when javascript is malformed") { - ResultCode loadResponseCode; - EvalTask("var j = 3 +", "", [&loadResponseCode](ResultCode code) { - loadResponseCode = code; - }).Execute(); - - REQUIRE(loadResponseCode == NAPA_RESULT_BROADCAST_SCRIPT_ERROR); - } - - SECTION("load fails when javascript exception is thrown") { - ResultCode loadResponseCode; - EvalTask("throw Error('error');", "", [&loadResponseCode](ResultCode code) { - loadResponseCode = code; - }).Execute(); - - REQUIRE(loadResponseCode == NAPA_RESULT_BROADCAST_SCRIPT_ERROR); - } - - SECTION("execute succeeds with a valid and existing function") { - EvalTask("function foo(a, b) { return a + b; }").Execute(); - - FunctionSpec spec; - spec.function = NAPA_STRING_REF("foo"); - spec.arguments = { NAPA_STRING_REF("3"), NAPA_STRING_REF("5") }; - - Result result; - CallTask(std::make_shared(spec, [&](Result res) { - result = std::move(res); - })).Execute(); - - REQUIRE(result.code == NAPA_RESULT_SUCCESS); - REQUIRE(result.returnValue == "8"); - } - - SECTION("execute fails for non-existing function") { - FunctionSpec spec; - spec.function = NAPA_STRING_REF("bar"); - spec.arguments = { NAPA_STRING_REF("3"), NAPA_STRING_REF("5") }; - - Result result; - CallTask(std::make_shared(spec, [&](Result res) { - result = std::move(res); - })).Execute(); - - REQUIRE(result.code == NAPA_RESULT_EXECUTE_FUNC_ERROR); - } - - SECTION("execute fails when function throws exception") { - EvalTask("function f1(a, b) { throw 'an error' }").Execute(); - - FunctionSpec spec; - spec.function = NAPA_STRING_REF("f1"); - spec.arguments = { NAPA_STRING_REF("3"), NAPA_STRING_REF("5") }; - - Result result; - CallTask(std::make_shared(spec, [&](Result res) { - result = std::move(res); - })).Execute(); - - REQUIRE(result.code == NAPA_RESULT_EXECUTE_FUNC_ERROR); - REQUIRE(result.errorMessage == "an error"); - } - - SECTION("execute succeeds when timeout was not exceeded") { - EvalTask("function f2(a, b) { return a + b; }").Execute(); - - FunctionSpec spec; - spec.function = NAPA_STRING_REF("f2"); - spec.arguments = { NAPA_STRING_REF("3"), NAPA_STRING_REF("5") }; - - Result result; - TimeoutTaskDecorator(500ms, std::make_shared(spec, [&](Result res) { - result = std::move(res); - })).Execute(); - - REQUIRE(result.code == NAPA_RESULT_SUCCESS); - REQUIRE(result.returnValue == "8"); - } - - SECTION("execute fails when timeout exceeded") { - EvalTask("function f3() { while(true) {} }").Execute(); - - FunctionSpec spec; - spec.function = NAPA_STRING_REF("f3"); - - Result result; - TimeoutTaskDecorator(500ms, std::make_shared(spec, [&](Result res) { - result = std::move(res); - })).Execute(); - - REQUIRE(result.code == NAPA_RESULT_TIMEOUT); - REQUIRE(result.errorMessage == "Terminated due to timeout"); - } - - SECTION("execute succeeds after a failed task") { - EvalTask("function f4() { while(true) {} }").Execute(); - EvalTask("function f5(a, b) { return Number(a) + Number(b); }").Execute(); - - FunctionSpec request1; - request1.function = NAPA_STRING_REF("f4"); - - Result response1; - TimeoutTaskDecorator(500ms, std::make_shared(request1, [&](Result res) { - response1 = std::move(res); - })).Execute(); - - REQUIRE(response1.code == NAPA_RESULT_TIMEOUT); - REQUIRE(response1.errorMessage == "Terminated due to timeout"); - - FunctionSpec request2; - request2.function = NAPA_STRING_REF("f5"); - request2.arguments = { NAPA_STRING_REF("3"), NAPA_STRING_REF("5") }; - - Result response2; - TimeoutTaskDecorator(500ms, std::make_shared(request2, [&](Result res) { - response2 = std::move(res); - })).Execute(); - - REQUIRE(response2.code == NAPA_RESULT_SUCCESS); - REQUIRE(response2.returnValue == "8"); - } -} diff --git a/cpp-test/component/worker-tests.cpp b/cpp-test/component/worker-tests.cpp deleted file mode 100644 index d4549dc..0000000 --- a/cpp-test/component/worker-tests.cpp +++ /dev/null @@ -1,146 +0,0 @@ -#include "catch.hpp" - -#include "zone/worker.h" -#include "napa-initialization-guard.h" - -#include "v8.h" - -#include -#include -#include - -using namespace napa; -using namespace napa::settings; -using namespace napa::zone; - - - -class TestTask : public Task { -public: - TestTask(std::function func = []() { return ""; }) - : numberOfExecutions(0), _func(std::move(func)) {} - - virtual void Execute() override { - result = _func(); - numberOfExecutions++; - } - - std::atomic numberOfExecutions; - std::string result; -private: - std::function _func; -}; - -// Make sure V8 it initialized exactly once. -static NapaInitializationGuard _guard; - -TEST_CASE("worker runs setup complete callback", "[scheduler-worker]") { - std::mutex mutex; - std::condition_variable cv; - - auto worker = std::make_unique(0, ZoneSettings(), [&cv](WorkerId) { - cv.notify_one(); - }, [](WorkerId) {}); - - bool setupCompleted = (cv.wait_for(lock, std::chrono::milliseconds(1000)) == std::cv_status::no_timeout); - REQUIRE(setupCompleted == true); -} - -TEST_CASE("worker runs scheduled task", "[scheduler-worker]") { - auto worker = std::make_unique(0, ZoneSettings(), [](WorkerId) {}, [](WorkerId) {}); - - auto task = std::make_shared(); - worker->Schedule(task); - - worker = nullptr; // Wait for worker to complete all tasks. - - REQUIRE(task->numberOfExecutions == 1); -} - -TEST_CASE("worker notifies idle condition", "[scheduler-worker]") { - std::mutex mutex; - std::condition_variable cv; - - auto worker = std::make_unique(0, ZoneSettings(), [](WorkerId) {}, [&cv](WorkerId) { - cv.notify_one(); - }); - - worker->Schedule(std::make_shared()); - - std::unique_lock lock(mutex); - bool idleNotificationReceived = (cv.wait_for(lock, std::chrono::milliseconds(1000)) == std::cv_status::no_timeout); - - REQUIRE(idleNotificationReceived == true); -} - -TEST_CASE("worker runs all tasks before shutting down", "[scheduler-worker]") { - auto worker = std::make_unique(0, ZoneSettings(), [](WorkerId) {}, [](WorkerId) {}); - - auto task = std::make_shared(); - - for (size_t i = 0; i < 100; i++) { - worker->Schedule(task); - } - - worker = nullptr; // Wait for worker to complete all tasks. - - REQUIRE(task->numberOfExecutions == 100); -} - -TEST_CASE("worker runs javascript task", "[scheduler-worker]") { - auto worker = std::make_unique(0, ZoneSettings(), [](WorkerId) {}, [](WorkerId) {}); - - auto task = std::make_shared([]() { - auto isolate = v8::Isolate::GetCurrent(); - auto context = isolate->GetCurrentContext(); - - v8::Local source = v8::String::NewFromUtf8(isolate, "'Hello' + ', World!'", - v8::NewStringType::kNormal).ToLocalChecked(); - - auto script = v8::Script::Compile(context, source).ToLocalChecked(); - - auto result = script->Run(context).ToLocalChecked(); - - v8::String::Utf8Value utf8(result); - - return std::string(*utf8); - }); - - worker->Schedule(task); - - worker = nullptr; // Wait for worker to complete all tasks. - - REQUIRE(task->result == "Hello, World!"); -} - -TEST_CASE("worker runs javascript with stack overflow", "[scheduler-worker]") { - auto worker = std::make_unique(0, ZoneSettings(), [](WorkerId) {}, [](WorkerId) {}); - - auto task = std::make_shared([]() { - auto isolate = v8::Isolate::GetCurrent(); - auto context = isolate->GetCurrentContext(); - - v8::Local source = v8::String::NewFromUtf8(isolate, "function test() { test(); }; test();", - v8::NewStringType::kNormal).ToLocalChecked(); - - auto script = v8::Script::Compile(context, source).ToLocalChecked(); - - v8::TryCatch tryCatch(isolate); - script->Run(context); - - if (tryCatch.HasCaught()) { - auto exception = tryCatch.Exception(); - v8::String::Utf8Value errorMessage(exception); - - return std::string(*errorMessage); - } - - return std::string(); - }); - - worker->Schedule(task); - - worker = nullptr; // Wait for worker to complete all tasks. - - REQUIRE(task->result == "RangeError: Maximum call stack size exceeded"); -} diff --git a/cpp-test/module/async/async.cpp b/cpp-test/module/async/async.cpp deleted file mode 100644 index ec03ec8..0000000 --- a/cpp-test/module/async/async.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include -#include - -#include -#include - -using namespace napa; -using namespace napa::module; - -using namespace v8; - -namespace { - std::atomic _now(0); -} - -/// It increases a number by a given parameter asynchronously and run a callback at the next execution loop. -void Increase(const FunctionCallbackInfo& args) { - auto isolate = args.GetIsolate(); - - CHECK_ARG(isolate, - args.Length() == 2 && args[0]->IsUint32() && args[1]->IsFunction(), - "It requires unsigned integer and callback as arguments"); - - auto value = args[0]->Uint32Value(); - - napa::zone::PostAsyncWork(Local::Cast(args[1]), - [value]() { - // This runs at the separate thread. - _now += value; - return reinterpret_cast(static_cast(_now.load())); - }, - [](auto jsCallback, void* result) { - // This runs at the same thread as one Increase() is called. - auto isolate = Isolate::GetCurrent(); - - int32_t argc = 1; - Local argv[] = - { Integer::NewFromUnsigned(isolate, static_cast(reinterpret_cast(result))) }; - - jsCallback->Call(isolate->GetCurrentContext()->Global(), argc, argv); - } - ); -} - -/// It increases a number by a given parameter synchronously and run a callback at the next execution loop. -void IncreaseSync(const FunctionCallbackInfo& args) { - auto isolate = args.GetIsolate(); - - CHECK_ARG(isolate, - args.Length() == 2 && args[0]->IsUint32() && args[1]->IsFunction(), - "It requires unsigned integer and callback as arguments"); - - auto value = args[0]->Uint32Value(); - - napa::zone::DoAsyncWork(Local::Cast(args[1]), - [value](auto complete) { - // This runs at the same thread. - _now += value; - complete(reinterpret_cast(static_cast(_now.load()))); - }, - [](auto jsCallback, void* result) { - // This runs at the same thread as one IncreaseSync() is called. - auto isolate = Isolate::GetCurrent(); - - int32_t argc = 1; - Local argv[] = - { Integer::NewFromUnsigned(isolate, static_cast(reinterpret_cast(result))) }; - - jsCallback->Call(isolate->GetCurrentContext()->Global(), argc, argv); - } - ); -} - -/// It returns the current value of a number. -void Now(const FunctionCallbackInfo& args) { - auto isolate = args.GetIsolate(); - HandleScope scope(isolate); - - args.GetReturnValue().Set(Integer::NewFromUnsigned(isolate, _now)); -} - -void Init(Local exports) { - NAPA_SET_METHOD(exports, "increase", Increase); - NAPA_SET_METHOD(exports, "increaseSync", IncreaseSync); - NAPA_SET_METHOD(exports, "now", Now); -} - -NAPA_MODULE(addon, Init) \ No newline at end of file diff --git a/cpp-test/module/async/async.vcxproj b/cpp-test/module/async/async.vcxproj deleted file mode 100644 index 66b0eb1..0000000 --- a/cpp-test/module/async/async.vcxproj +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - Debug - x64 - - - Release - x64 - - - - DynamicLibrary - true - async - - - DynamicLibrary - false - async - - - - - $(NapaVanillaRoot)\src\$(IntermediateOutputPath)\napa.lib;%(AdditionalDependencies) - - - BUILDING_NAPA_EXTENSION;%(PreprocessorDefinitions) - $(NapaVanillaRoot)\inc;%(AdditionalIncludeDirectories) - - - - - - - - - - - \ No newline at end of file diff --git a/cpp-test/module/dirs.proj b/cpp-test/module/dirs.proj deleted file mode 100644 index 09c628e..0000000 --- a/cpp-test/module/dirs.proj +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/cpp-test/module/module-loader/asserttest.js b/cpp-test/module/module-loader/asserttest.js deleted file mode 100644 index baa0070..0000000 --- a/cpp-test/module/module-loader/asserttest.js +++ /dev/null @@ -1,58 +0,0 @@ -var assert = require('assert'); - -assert(1 == 1); - -const obj1 = { a : { b : 1 } }; -const obj2 = { a : { b : 2 } }; -const obj3 = { a : { b : 1 } }; -const obj4 = Object.create(obj1); - -assert.deepEqual(obj1, obj1); - -assert.notDeepEqual(obj1, obj2); - -assert.deepEqual(obj1, obj3); - -assert.notDeepEqual(obj1, obj4); - -assert.deepEqual({a:1}, {a:'1'}); - -assert.notStrictEqual({a:1}, {a:'1'}); - -assert.equal(1, 1); - -assert.equal(1, '1'); - -assert.deepEqual(1, '1'); - -assert.deepEqual(1, 1); - -assert.notStrictEqual(1, '1'); - -assert.notEqual(1, 2); - -assert.notEqual({a: {b: 1}}, {a: {b: 1}}); - -assert.ifError(0); - -assert.throws(() => { assert.ifError(1);}); - -assert.throws(() => { assert.ifError('error');}); - -assert.throws(() => { assert.ifError(new Error());}); - -assert.throws(() => { assert.fail(1, 2, undefined, '>'); }); - -assert.ok(true); - -assert.ok(1); - -assert.throws(() => { assert.ok(false); }); - -assert.throws(() => { assert.ok(0); }); - -assert.throws(() => { - assert.doesNotThrow(() => { throw new TypeError('Wrong value'); }, TypeError); -}); - -true; diff --git a/cpp-test/module/module-loader/asynctest1.js b/cpp-test/module/module-loader/asynctest1.js deleted file mode 100644 index 1dda28e..0000000 --- a/cpp-test/module/module-loader/asynctest1.js +++ /dev/null @@ -1,22 +0,0 @@ -var assert = require('assert'); -var async = require('./async'); - -var now = async.now(); -assert.equal(now, 0); - -var promise = new Promise((resolve) => { - async.increase(3, (value) => { - resolve(value); - }); -}); - -promise.then((value) => { - assert.equal(value, 3); - - now = async.now(); - assert.equal(now, 6); -}); - -async.increaseSync(3, (value) => {}); - -true; \ No newline at end of file diff --git a/cpp-test/module/module-loader/asynctest2.js b/cpp-test/module/module-loader/asynctest2.js deleted file mode 100644 index 05243e5..0000000 --- a/cpp-test/module/module-loader/asynctest2.js +++ /dev/null @@ -1,13 +0,0 @@ -now = async.now(); -assert.equal(now, 6); - -async.increaseSync(3, (value) => { - assert.equal(value, 9); - - now = async.now(); - assert.equal(now, 12); -}); - -async.increaseSync(3, (value) => {}); - -true; diff --git a/cpp-test/module/module-loader/core-module-tests.js b/cpp-test/module/module-loader/core-module-tests.js deleted file mode 100644 index 6f32a70..0000000 --- a/cpp-test/module/module-loader/core-module-tests.js +++ /dev/null @@ -1,10 +0,0 @@ -var assert = require('assert'); - -assert.equal(typeof tfs, 'undefined'); -var tfs = require('tfs'); -assert.equal(tfs.runTest(), 'tfs.runTest'); - -assert.notEqual(typeof tconsole, 'undefined'); -assert.equal(tconsole.runTest(), 'tconsole.runTest'); - -true; \ No newline at end of file diff --git a/cpp-test/module/module-loader/core-modules.json b/cpp-test/module/module-loader/core-modules.json deleted file mode 100644 index 0b7fa8c..0000000 --- a/cpp-test/module/module-loader/core-modules.json +++ /dev/null @@ -1,30 +0,0 @@ -[ - { - "name": "assert", - "type": "core" - }, - { - "name": "events", - "type": "core" - }, - { - "name": "process", - "type": "builtin" - }, - { - "name": "tconsole", - "type": "builtin" - }, - { - "name": "tfs", - "type": "core" - }, - { - "name": "tty", - "type": "core" - }, - { - "name": "util", - "type": "core" - } -] diff --git a/cpp-test/module/module-loader/cycle-main.js b/cpp-test/module/module-loader/cycle-main.js deleted file mode 100644 index ca9a7de..0000000 --- a/cpp-test/module/module-loader/cycle-main.js +++ /dev/null @@ -1,7 +0,0 @@ -var cycle_a = require('./cycle-a.js'); -var cycle_b = require('./cycle-b.js'); -if (cycle_a.done && cycle_b.done) { - true; -} else { - false; -} diff --git a/cpp-test/module/module-loader/fstest.js b/cpp-test/module/module-loader/fstest.js deleted file mode 100644 index ee0a5b2..0000000 --- a/cpp-test/module/module-loader/fstest.js +++ /dev/null @@ -1,19 +0,0 @@ -var assert = require('assert'); -var fs = require('fs'); - -assert.ifError(fs.existsSync('file-not-exist.json')); - -assert.ok(fs.existsSync('fstest.json')); - -var content = JSON.parse(fs.readFileSync('fstest.json')); -assert.equal(content.query, 'query'); -assert.equal(content.document, 'document'); - -fs.mkdirSync('fstest-dir'); -fs.mkdirSync('fstest-dir/1'); -fs.mkdirSync('fstest-dir/2'); -fs.writeFileSync('fstest-dir/3.dat', '3.dat'); -var names = fs.readdirSync('fstest-dir'); -assert.deepEqual(names, ['1', '2', '3.dat']); - -require('./tests/sub/fstestsub'); diff --git a/cpp-test/module/module-loader/fstest.json b/cpp-test/module/module-loader/fstest.json deleted file mode 100644 index e7cb1a3..0000000 --- a/cpp-test/module/module-loader/fstest.json +++ /dev/null @@ -1 +0,0 @@ -{ "query" : "query", "document" : "document" } diff --git a/cpp-test/module/module-loader/globaltest-module.js b/cpp-test/module/module-loader/globaltest-module.js deleted file mode 100644 index 2f21b42..0000000 --- a/cpp-test/module/module-loader/globaltest-module.js +++ /dev/null @@ -1,4 +0,0 @@ -exports.run = function() { - global.toGlobal = 'toGlobal'; - return global.fromGlobal; -} diff --git a/cpp-test/module/module-loader/globaltest.js b/cpp-test/module/module-loader/globaltest.js deleted file mode 100644 index ac5402b..0000000 --- a/cpp-test/module/module-loader/globaltest.js +++ /dev/null @@ -1,10 +0,0 @@ -var assert = require('assert'); - -assert.equal(global.Math.floor(1.1), 1); - -var test = require('./globaltest-module'); -global.fromGlobal = 'fromGlobal'; -assert.equal(test.run(), 'fromGlobal'); -assert.equal(global.toGlobal, 'toGlobal'); - -true; \ No newline at end of file diff --git a/cpp-test/module/module-loader/jsmodule.js b/cpp-test/module/module-loader/jsmodule.js deleted file mode 100644 index edc9a15..0000000 --- a/cpp-test/module/module-loader/jsmodule.js +++ /dev/null @@ -1,6 +0,0 @@ -var exports = module.exports = {}; - -exports.print = function(data) { - var proxy = require('./test/toproxy'); - return proxy.run(data); -}; diff --git a/cpp-test/module/module-loader/jsontest.js b/cpp-test/module/module-loader/jsontest.js deleted file mode 100644 index 109ee2e..0000000 --- a/cpp-test/module/module-loader/jsontest.js +++ /dev/null @@ -1,5 +0,0 @@ -var obj = require('./fstest.json'); -if (obj.query == 'query' && obj.document == 'document') - true; -else - false; diff --git a/cpp-test/module/module-loader/lib/tconsole.js b/cpp-test/module/module-loader/lib/tconsole.js deleted file mode 100644 index 86f1745..0000000 --- a/cpp-test/module/module-loader/lib/tconsole.js +++ /dev/null @@ -1,9 +0,0 @@ -var tconsole = exports; - -for (var prop in console) { - tconsole[prop] = console[prop]; -} - -tconsole.runTest = function() { - return 'tconsole.runTest'; -} \ No newline at end of file diff --git a/cpp-test/module/module-loader/lib/tfs.js b/cpp-test/module/module-loader/lib/tfs.js deleted file mode 100644 index 0962869..0000000 --- a/cpp-test/module/module-loader/lib/tfs.js +++ /dev/null @@ -1,10 +0,0 @@ -var binding = process.binding('fs'); -var tfs = exports; - -for (var prop in binding) { - tfs[prop] = binding[prop]; -} - -tfs.runTest = function() { - return 'tfs.runTest'; -} \ No newline at end of file diff --git a/cpp-test/module/module-loader/main.cpp b/cpp-test/module/module-loader/main.cpp deleted file mode 100644 index b40c52d..0000000 --- a/cpp-test/module/module-loader/main.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#define CATCH_CONFIG_MAIN -#include "catch.hpp" -#include "napa-catch-reporter.h" \ No newline at end of file diff --git a/cpp-test/module/module-loader/module-loader-tests.cpp b/cpp-test/module/module-loader/module-loader-tests.cpp deleted file mode 100644 index b2ad6c3..0000000 --- a/cpp-test/module/module-loader/module-loader-tests.cpp +++ /dev/null @@ -1,393 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -using namespace napa; -using namespace napa::module; -using namespace napa::settings; -using namespace napa::zone; - - -class V8InitializationGuard { -public: - V8InitializationGuard() { - static V8Initialization initialization; - } - -private: - class V8Initialization { - public: - V8Initialization() { - v8_common::Initialize(); - } - - ~V8Initialization() { - v8_common::Shutdown(); - } - }; -}; - -// Make sure V8 it initialized exactly once. -static V8InitializationGuard _guard; - -bool RunScript(const std::string& input, std::function)> verifier) { - v8_extensions::ArrayBufferAllocator allocator; - v8::Isolate::CreateParams params; - params.array_buffer_allocator = &allocator; - - auto isolate = v8::Isolate::New(params); - - std::unique_ptr> deferred(isolate, [](auto isolate) { - isolate->Dispose(); - }); - - v8::Isolate::Scope isolateScope(isolate); - v8::HandleScope handleScope(isolate); - - auto context = v8::Context::New(isolate); - context->SetSecurityToken(v8::Undefined(isolate)); - v8::Context::Scope contextScope(context); - - INIT_WORKER_CONTEXT(); - CREATE_MODULE_LOADER(); - - auto source = v8_helpers::MakeV8String(isolate, input); - - v8::TryCatch tryCatch; - auto script = v8::Script::Compile(source); - if (tryCatch.HasCaught()) { - return false; - } - - auto run = script->Run(); - if (tryCatch.HasCaught()) { - return false; - } - - return verifier(run); -} - -bool RunScriptFile(const std::string& filename, std::function)> verifier) { - std::ifstream file(filename); - std::stringstream buffer; - buffer << file.rdbuf(); - - return RunScript(buffer.str(), verifier); -} - -bool LoadJavascript(int index) { - std::string input; - input.append("jsmodule").append(std::to_string(index)); - - std::ostringstream oss; - oss << "var js = require('./jsmodule');" - << "js.print('" << input << "');" - << "js = require('./jsmodule.js');" - << "js.print('" << input << "');" - << "js = require('./test/../jsmodule.js');" - << "js.print('" << input << "');"; - - return RunScript(oss.str(), [&input](v8::Local run) { - std::transform(input.begin(), input.end(), input.begin(), toupper); - - v8::String::Utf8Value value(run); - return input.compare(*value) == 0; - }); -} - -bool LoadNapaModule(int index) { - std::string input; - input.append("sample").append(std::to_string(index)); - - std::ostringstream oss; - oss << "var sample = require('./sample.napa');" - << "sample.print('" << input << "');" - << "sample = require('./test/../sample.napa');" - << "sample.print('" << input << "');"; - - return RunScript(oss.str(), [&input](v8::Local run) { - v8::String::Utf8Value value(run); - return input.compare(*value) == 0; - }); -} - -bool LoadObjectWrapModule(int index) { - std::ifstream file("sample-test.js"); - - std::stringstream buffer; - buffer << file.rdbuf(); - - return RunScript(buffer.str(), [](v8::Local run) { - return run->BooleanValue(); - }); -} - -void RunAtThreads(std::function tester) { - std::vector> futures; - - for (int i = 0; i < 16; ++i) { - futures.push_back(std::async(std::launch::async, tester, i)); - } - - for (auto& result : futures) { - REQUIRE(result.get() == true); - } -} - -TEST_CASE("load javascript", "[module-loader]") { - RunAtThreads(LoadJavascript); -} - -TEST_CASE("load json module", "[module-loader]") { - auto result = RunScriptFile("jsontest.js", [](v8::Local run) { - return run->BooleanValue(); - }); - REQUIRE(result); -} - -TEST_CASE("load napa module", "[module-loader]") { - RunAtThreads(LoadNapaModule); -} - -TEST_CASE("load object wrap module", "[module-loader]") { - RunAtThreads(LoadObjectWrapModule); -} - -TEST_CASE("require.resolve", "[module-loader]") { - std::ostringstream oss; - oss << "require.resolve('./jsmodule.js');"; - - auto result = RunScript(oss.str(), [](v8::Local run) { - v8::String::Utf8Value value(run); - auto filePath = filesystem::CurrentDirectory() / "jsmodule.js"; - return filePath.String().compare(*value) == 0; - }); - REQUIRE(result); - - oss.str(""); - oss << "require.resolve('./jsmodule.napa');"; - - result = RunScript(oss.str(), [](v8::Local run) { - v8::String::Utf8Value value(run); - return value.length() == 0; - }); - REQUIRE(result); -} - -TEST_CASE("core modules", "[module-loader]") { - auto result = RunScriptFile("core-module-tests.js", [](v8::Local run) { - return run->BooleanValue(); - }); - REQUIRE(result); -} - -TEST_CASE("process", "[module-loader]") { - std::ostringstream oss; - oss << "process.argv.length;"; - - auto result = RunScript(oss.str(), [](v8::Local run) { - auto argc = run->Int32Value(); - return argc > 0; - }); - REQUIRE(result); - - oss.str(""); - oss << "process.argv[0];"; - - result = RunScript(oss.str(), [](v8::Local run) { - v8::String::Utf8Value value(run); - return filesystem::Exists(filesystem::Path(*value)); - }); - REQUIRE(result); - - oss.str(""); - oss << "process.execPath;"; - - result = RunScript(oss.str(), [](v8::Local run) { - v8::String::Utf8Value value(run); - return dll::ThisLineLocation() == *value; - }); - REQUIRE(result); - - result = RunScriptFile("processtest.js", [](v8::Local run) { - return run->BooleanValue(); - }); - REQUIRE(result); -} - -TEST_CASE("assert", "[module-loader]") { - auto result = RunScriptFile("asserttest.js", [](v8::Local run) { - return run->BooleanValue(); - }); - REQUIRE(result); -} - -TEST_CASE("file system", "[module-loader]") { - auto result = RunScriptFile("fstest.js", [](v8::Local run) { - return run->BooleanValue(); - }); - REQUIRE(result); -} - -TEST_CASE("global", "[module-loader]") { - auto result = RunScriptFile("globaltest.js", [](v8::Local run) { - return run->BooleanValue(); - }); - REQUIRE(result); -} - -TEST_CASE("path", "[module-loader]") { - auto result = RunScriptFile("pathtest.js", [](v8::Local run) { - return run->BooleanValue(); - }); - REQUIRE(result); -} - -TEST_CASE("os", "[module-loader]") { - auto result = RunScriptFile("ostest.js", [](v8::Local run) { - return run->BooleanValue(); - }); - REQUIRE(result); -} - -TEST_CASE("util", "[module-loader]") { - auto result = RunScriptFile("utiltest.js", [](v8::Local run) { - return run->BooleanValue(); - }); - REQUIRE(result); -} - -TEST_CASE("tty", "[module-loader]") { - auto result = RunScriptFile("ttytest.js", [](v8::Local run) { - return run->BooleanValue(); - }); - REQUIRE(result); -} - -TEST_CASE("cycling import", "[module-loader]") { - auto result = RunScriptFile("cycle-main.js", [](v8::Local run) { - return run->BooleanValue(); - }); - REQUIRE(result); -} - -TEST_CASE("resolve modules", "[module-loader]") { - auto result = RunScriptFile("module-resolution-test.js", [](v8::Local run) { - return run->BooleanValue(); - }); - REQUIRE(result); -} - -TEST_CASE("resolve full path modules", "[module-loader]") { - auto filePath = filesystem::CurrentDirectory() / "tests\\sub\\sub1\\file2.js"; - auto filePathString = filePath.String(); - utils::string::ReplaceAll(filePathString, "\\", "\\\\"); - - std::ostringstream oss; - oss << "var file = require('" << filePathString << "');\r\n" - << "(file != null);"; - - auto result = RunScript(oss.str(), [](v8::Local run) { - return run->BooleanValue(); - }); - REQUIRE(result); -} - -class AsyncTestTask : public Task { -public: - AsyncTestTask(zone::NapaZone* zone, std::string filename) - : _zone(zone), _filename(std::move(filename)), _succeeded(false) {} - - void Execute() override { - // TODO @suchoi: Remove this line after Asi checks in the separation of zone construct and init. - WorkerContext::Set(WorkerContextItem::ZONE, reinterpret_cast(_zone)); - - if (_filename.empty()) { - return; - } - - auto isolate = v8::Isolate::GetCurrent(); - v8::HandleScope scope(isolate); - - std::ifstream file(_filename); - std::stringstream buffer; - buffer << file.rdbuf(); - - auto source = napa::v8_helpers::MakeV8String(isolate, buffer.str()); - - std::unique_ptr> deferred(&_cond, [](auto cond) { - cond->notify_one(); - }); - - v8::TryCatch tryCatch; - auto script = v8::Script::Compile(source); - if (tryCatch.HasCaught()) { - _succeeded = false; - return; - } - - auto run = script->Run(); - if (tryCatch.HasCaught()) { - _succeeded = false; - return; - } - - _succeeded = true; - } - - bool ok() { - std::unique_lock lock(_lock); - _cond.wait(lock); - - return _succeeded; - } - -private: - - zone::NapaZone* _zone; - - std::string _filename; - bool _succeeded = false; - - std::mutex _lock; - std::condition_variable _cond; -}; - -TEST_CASE("async", "[module-loader]") { - ZoneSettings settings; - settings.id = "zone"; - settings.workers = 1; - - auto zone = zone::NapaZone::Create(settings); - - auto scheduler = zone->GetScheduler(); - scheduler->ScheduleOnAllWorkers(std::make_shared(zone.get(), std::string())); - - auto task = std::make_shared(zone.get(), "asynctest1.js"); - scheduler->Schedule(task); - - REQUIRE(task->ok()); - - task = std::make_shared(zone.get(), "asynctest2.js"); - scheduler->Schedule(task); - - REQUIRE(task->ok()); -} \ No newline at end of file diff --git a/cpp-test/module/module-loader/module-resolution-test.js b/cpp-test/module/module-loader/module-resolution-test.js deleted file mode 100644 index 13432fc..0000000 --- a/cpp-test/module/module-loader/module-resolution-test.js +++ /dev/null @@ -1 +0,0 @@ -require('./tests/sub/module-resolution-test-root.js')(); diff --git a/cpp-test/module/module-loader/napa-module-loader-tests.vcxproj b/cpp-test/module/module-loader/napa-module-loader-tests.vcxproj deleted file mode 100644 index 53205a2..0000000 --- a/cpp-test/module/module-loader/napa-module-loader-tests.vcxproj +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - - Debug - x64 - - - Release - x64 - - - - {718EC282-8C1B-44FB-BD98-97F2E09E0389} - - - Application - true - - - Application - false - - - $(OutDir)module-tests - - - - - Winmm.lib;Dbghelp.lib;Shlwapi.lib;%(AdditionalDependencies) - $(NapaVanillaRoot)\src\$(IntermediateOutputPath)\napa.lib;%(AdditionalDependencies) - - - $(Pkgnapa_nodelib_vc140)\lib\$(BuildType)\$(BuildTarget)\v8_libbase.lib;%(AdditionalDependencies) - $(Pkgnapa_nodelib_vc140)\lib\$(BuildType)\$(BuildTarget)\v8_libplatform.lib;%(AdditionalDependencies) - - - 4100;4251;4996 - NAPA_EXPORTS;NAPA_BINDING_EXPORTS;BUILDING_NAPA_EXTENSION;BUILDING_V8_SHARED;%(PreprocessorDefinitions) - $(NapaVanillaRoot)\inc;%(AdditionalIncludeDirectories) - $(NapaVanillaRoot)\src;%(AdditionalIncludeDirectories) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\lib - *.j* - true - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\lib\core - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin - - - $(IntermediateOutputPath)\module-tests\bin\test - - - $(IntermediateOutputPath)\module-tests\bin\test - - - $(IntermediateOutputPath)\module-tests\lib\core - - - $(IntermediateOutputPath)\module-tests\lib\core - - - $(IntermediateOutputPath)\module-tests\bin\tests\node_modules - - - $(IntermediateOutputPath)\module-tests\bin\tests\sub - - - $(IntermediateOutputPath)\module-tests\bin\tests\sub - - - $(IntermediateOutputPath)\module-tests\bin\tests\sub - - - $(IntermediateOutputPath)\module-tests\bin\tests\sub\sub1 - - - $(IntermediateOutputPath)\module-tests\bin\tests\sub\sub1 - - - - - - - - - - - - - - diff --git a/cpp-test/module/module-loader/ostest.js b/cpp-test/module/module-loader/ostest.js deleted file mode 100644 index 806cf8b..0000000 --- a/cpp-test/module/module-loader/ostest.js +++ /dev/null @@ -1,6 +0,0 @@ -var assert = require('assert'); -var os = require('os'); - -assert(os.type == "Windows_NT" || os.type == "Darwin" || os.type == "Linux"); - -true; \ No newline at end of file diff --git a/cpp-test/module/module-loader/pathtest.js b/cpp-test/module/module-loader/pathtest.js deleted file mode 100644 index 66a1672..0000000 --- a/cpp-test/module/module-loader/pathtest.js +++ /dev/null @@ -1,106 +0,0 @@ -var assert = require('assert'); -var path = require('path'); - -assert.equal( - path.normalize('a\\b\\..\\c/./d/././.'), - "a\\c\\d\\."); - -assert.equal( - path.resolve('c:\\foo/bar', "a.txt"), - "c:\\foo\\bar\\a.txt"); - -assert.equal( - path.resolve("abc.txt"), - process.cwd() + "\\abc.txt"); - -assert.equal( - path.resolve("abc", "efg", "../hij", "./xyz.txt"), - process.cwd() + "\\abc\\hij\\xyz.txt"); - -assert.equal( - path.resolve("abc", "d:/a.txt"), - "d:\\a.txt"); - -assert.equal( - path.join("/foo", "bar", "baz/asdf", "quux", ".."), - "\\foo\\bar\\baz\\asdf"); - -assert.equal( - path.dirname("c:"), - "c:"); - -assert.equal( - path.dirname("c:\\windows"), - "c:\\"); - -assert.equal( - path.dirname("c:\\windows\\abc.txt"), - "c:\\windows"); - -assert.equal( - path.basename("c:\\windows\\abc.txt"), - "abc.txt"); - -assert.equal( - path.basename("c:\\windows\\a"), - "a"); - -assert.equal( - path.basename("c:\\windows\\abc.txt", ".txt"), - "abc"); - -assert.equal( - path.basename("c:\\windows\\abc.txt", ".Txt"), - "abc.txt"); - -assert.equal( - path.extname("c:\\windows\\abc.txt"), - ".txt"); - -assert.equal( - path.extname("c:\\windows\\a.json.txt"), - ".txt"); - -assert.equal( - path.extname("c:\\windows\\a."), - "."); - -assert.equal( - path.isAbsolute("c:\\windows\\a."), - true); - -assert.equal( - path.isAbsolute("c:/windows/.."), - true); - -assert.equal( - path.isAbsolute("../abc"), - false); - -assert.equal( - path.isAbsolute("./abc"), - false); - -assert.equal( - path.isAbsolute("abc"), - false); - -assert.equal( - path.relative("c:\\a\\..\\b", "c:\\b"), - "."); - -assert.equal( - path.relative("c:/a", "d:/b/../c"), - "d:\\c"); - -assert.equal( - path.relative("z:/a", "a.txt"), - process.cwd() + "\\a.txt"); - -assert.equal( - path.relative("c:/a", "c:/"), - ".."); - -assert.notEqual("foo/bar\\baz".indexOf(path.sep), -1); - -true; \ No newline at end of file diff --git a/cpp-test/module/module-loader/processtest.js b/cpp-test/module/module-loader/processtest.js deleted file mode 100644 index fe78686..0000000 --- a/cpp-test/module/module-loader/processtest.js +++ /dev/null @@ -1,29 +0,0 @@ -var fs = require('fs'); -var events = require('events'); -var assert = require('assert'); - -process.env.NAPA_TEST = "process"; -assert.equal(process.env.NAPA_TEST, "process"); - -assert(typeof process.platform != undefined && process.platform != null); - -assert(typeof process.umask != undefined); -assert(process.umask() == process.umask(0)); -assert(process.umask() == process.umask("0")); - -try { - process.chdir('./test'); - process.chdir(process.cwd()); - process.chdir('..'); - fs.existsSync('napa.dll'); -} catch (err) { - throw err; -} - -assert(typeof process.pid != undefined && !isNaN(process.pid)); - -events.defaultMaxListeners = 1; -process.on('foo', () => {}); -assert.throws(() => { process.on('foo', () => {})}); - -true; \ No newline at end of file diff --git a/cpp-test/module/module-loader/sample-test.js b/cpp-test/module/module-loader/sample-test.js deleted file mode 100644 index 08fd622..0000000 --- a/cpp-test/module/module-loader/sample-test.js +++ /dev/null @@ -1,39 +0,0 @@ -var sample = require('./sample.napa'); - -var runSampleNode = function() { - // Create wrapped C++ object. - var sampleNode = sample.createSampleNode(1); - - // Calls C++ function through accessor. - sampleNode.score = 2; - - // Add property from javascript world. - sampleNode.margin = 3; - - // Access new property from C++ world. - sampleNode.score += sampleNode.getValue('margin'); - - return sampleNode.score; -} - -var runSampleContainer = function(score) { - var sampleContainer = sample.createSampleContainer(); - - // Access built-in member. - sampleContainer.node.score = score; - - var sum = sampleContainer.node.score; - var sampleNode = sample.createSampleNode(score * 2); - - // replace built-in member. - sampleContainer.setNode(sampleNode); - sum += sampleContainer.getNode().score; - - return sum; -} - -if (runSampleNode(3) + runSampleContainer(3) == 14) { - true; -} else { - false; -} diff --git a/cpp-test/module/module-loader/tests/node_modules/file2.js b/cpp-test/module/module-loader/tests/node_modules/file2.js deleted file mode 100644 index 7c6d6c7..0000000 --- a/cpp-test/module/module-loader/tests/node_modules/file2.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = {} \ No newline at end of file diff --git a/cpp-test/module/module-loader/tests/sub/fstestsub.js b/cpp-test/module/module-loader/tests/sub/fstestsub.js deleted file mode 100644 index b942063..0000000 --- a/cpp-test/module/module-loader/tests/sub/fstestsub.js +++ /dev/null @@ -1,12 +0,0 @@ -function fstestsub() { - var filesystem = require('fs'); - var path = require('path'); - var content = JSON.parse(filesystem.readFileSync(path.resolve(__dirname, 'fstestsub.json'))); - if (content.subQuery != 'sub-query' || content.subDocument != 'sub-document') { - return false; - } else { - return true; - } -} - -module.exports = fstestsub(); \ No newline at end of file diff --git a/cpp-test/module/module-loader/tests/sub/fstestsub.json b/cpp-test/module/module-loader/tests/sub/fstestsub.json deleted file mode 100644 index e15af6f..0000000 --- a/cpp-test/module/module-loader/tests/sub/fstestsub.json +++ /dev/null @@ -1 +0,0 @@ -{ "subQuery" : "sub-query", "subDocument" : "sub-document" } diff --git a/cpp-test/module/module-loader/tests/sub/module-resolution-test-root.js b/cpp-test/module/module-loader/tests/sub/module-resolution-test-root.js deleted file mode 100644 index ec54306..0000000 --- a/cpp-test/module/module-loader/tests/sub/module-resolution-test-root.js +++ /dev/null @@ -1,37 +0,0 @@ -var assert = require('assert'); - -// -// Test require with path information -// -module.exports = function () { - var paths = [ - "fs", - "./sub1/file1.js", - "./sub1/file1", - "../sub/sub1/file1.js", - // From module root via relative path. - "../../sample.napa", - "../../sample", - // from .\node_modules to parents' recursively. - "file2.js", - "file2" - ]; - - for (i = 0; i < paths.length; i++) { - var file = require(paths[i]); - if (file == null) { - console.log("Failed to resolve module at " + path[i]); - return false; - } - } - - return true; -}; - -var path = require('path'); - -assert.equal(__filename, path.resolve(__dirname, "module-resolution-test-root.js")); - -assert.equal(__dirname, path.resolve("tests\\sub")); - -assert.equal(module.id, path.resolve(__dirname, "module-resolution-test-root.js")); \ No newline at end of file diff --git a/cpp-test/module/module-loader/tests/sub/sub1/file1.js b/cpp-test/module/module-loader/tests/sub/sub1/file1.js deleted file mode 100644 index 7c6d6c7..0000000 --- a/cpp-test/module/module-loader/tests/sub/sub1/file1.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = {} \ No newline at end of file diff --git a/cpp-test/module/module-loader/tests/sub/sub1/file2.js b/cpp-test/module/module-loader/tests/sub/sub1/file2.js deleted file mode 100644 index 7c6d6c7..0000000 --- a/cpp-test/module/module-loader/tests/sub/sub1/file2.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = {} \ No newline at end of file diff --git a/cpp-test/module/module-loader/toproxy.js b/cpp-test/module/module-loader/toproxy.js deleted file mode 100644 index 42d6115..0000000 --- a/cpp-test/module/module-loader/toproxy.js +++ /dev/null @@ -1,6 +0,0 @@ -var exports = module.exports = {}; - -exports.run = function(data) { - var toupper = require('./toupper'); - return toupper.toupper(data); -}; diff --git a/cpp-test/module/module-loader/toupper.js b/cpp-test/module/module-loader/toupper.js deleted file mode 100644 index 930200f..0000000 --- a/cpp-test/module/module-loader/toupper.js +++ /dev/null @@ -1,5 +0,0 @@ -var exports = module.exports = {}; - -exports.toupper = function(data) { - return data.toUpperCase(); -}; diff --git a/cpp-test/module/module-loader/ttytest.js b/cpp-test/module/module-loader/ttytest.js deleted file mode 100644 index a60e687..0000000 --- a/cpp-test/module/module-loader/ttytest.js +++ /dev/null @@ -1,9 +0,0 @@ -var assert = require('assert'); -var tty = require('tty'); - -var result = process.binding('tty_wrap').guessHandleType(1); -assert.equal(result, 'UNKNOWN'); - -assert.equal(tty.isatty(3), false); - -true; diff --git a/cpp-test/module/module-loader/utiltest.js b/cpp-test/module/module-loader/utiltest.js deleted file mode 100644 index 7320f5b..0000000 --- a/cpp-test/module/module-loader/utiltest.js +++ /dev/null @@ -1,30 +0,0 @@ -const assert = require('assert'); -const util = require('util'); -const EventEmitter = require('events'); - -function MyStream() { - EventEmitter.call(this); -} - -util.inherits(MyStream, EventEmitter); - -MyStream.prototype.write = function(data) { - this.emit('data', data); -}; - -const stream = new MyStream(); - -assert(stream instanceof EventEmitter); -assert.equal(MyStream.super_, EventEmitter); - -stream.on('data', (data) => { - assert.equal(data, 'test'); -}); -stream.write('test'); - -var inspect = util.inspect(stream.write); -assert.equal(inspect, '[Function]'); - -assert.equal(util.format('%s:%s', 'foo', 'bar', 'baz'), 'foo:bar baz'); - -true; diff --git a/cpp-test/module/sample/sample.cpp b/cpp-test/module/sample/sample.cpp deleted file mode 100644 index 3343727..0000000 --- a/cpp-test/module/sample/sample.cpp +++ /dev/null @@ -1,214 +0,0 @@ -#include - -using namespace napa; -using namespace napa::module; - -class SampleNode : public NAPA_OBJECTWRAP { -public: - - static void Init() { - auto isolate = v8::Isolate::GetCurrent(); - - auto functionTemplate = v8::FunctionTemplate::New(isolate, NewCallback); - functionTemplate->SetClassName(v8_helpers::MakeV8String(isolate, _exportName)); - functionTemplate->InstanceTemplate()->SetInternalFieldCount(1); - - NAPA_SET_PROTOTYPE_METHOD(functionTemplate, "getValue", GetValueCallback); - NAPA_SET_ACCESSOR(functionTemplate, "score", GetScoreCallback, SetScoreCallback); - - NAPA_SET_PERSISTENT_CONSTRUCTOR(_exportName, functionTemplate->GetFunction()); - } - - static void NewInstance(const v8::FunctionCallbackInfo& args) { - auto isolate = v8::Isolate::GetCurrent(); - v8::HandleScope scope(isolate); - - const int argc = 1; - v8::Local argv[argc] = { args[0] }; - - auto constructor = NAPA_GET_PERSISTENT_CONSTRUCTOR(_exportName, SampleNode); - auto context = isolate->GetCurrentContext(); - auto instance = constructor->NewInstance(context, argc, argv).ToLocalChecked(); - - args.GetReturnValue().Set(instance); - } - - static v8::Local NewInstance(uint32_t score) { - auto isolate = v8::Isolate::GetCurrent(); - v8::EscapableHandleScope scope(isolate); - - const int argc = 1; - v8::Local argv[argc] = { v8::Number::New(isolate, score) }; - - auto constructor = NAPA_GET_PERSISTENT_CONSTRUCTOR(_exportName, SampleNode); - return scope.Escape(constructor->NewInstance(argc, argv)); - } - -private: - - friend class SampleContainer; - - static constexpr const char* _exportName = "SampleNode"; - - explicit SampleNode(uint32_t score = 0) : _score(score) {} - - static void NewCallback(const v8::FunctionCallbackInfo& args) { - auto isolate = v8::Isolate::GetCurrent(); - v8::HandleScope scope(isolate); - - JS_ASSERT(isolate, args.IsConstructCall(), "Only constructor call is allowed"); - - uint32_t score = args[0]->IsUndefined() ? 0 : args[0]->Uint32Value(); - - auto sampleNode = new SampleNode(score); - sampleNode->Wrap(args.Holder()); - args.GetReturnValue().Set(args.Holder()); - } - - static void GetScoreCallback(v8::Local, - const v8::PropertyCallbackInfo& args) { - auto isolate = v8::Isolate::GetCurrent(); - v8::HandleScope scope(isolate); - - auto sampleNode = NAPA_OBJECTWRAP::Unwrap(args.Holder()); - args.GetReturnValue().Set(v8::Number::New(isolate, sampleNode->_score)); - } - - static void SetScoreCallback(v8::Local, - v8::Local value, - const v8::PropertyCallbackInfo& args) { - auto isolate = v8::Isolate::GetCurrent(); - v8::HandleScope scope(isolate); - - CHECK_ARG(isolate, - value->IsUint32(), - "Value must be a number."); - - auto sampleNode = NAPA_OBJECTWRAP::Unwrap(args.Holder()); - sampleNode->_score = value->Uint32Value(); - - args.GetReturnValue().SetUndefined(); - } - - static void GetValueCallback(const v8::FunctionCallbackInfo& args) { - auto isolate = v8::Isolate::GetCurrent(); - v8::HandleScope scope(isolate); - - CHECK_ARG(isolate, - args.Length() > 0 && !args[0]->IsUndefined(), - "The first argument must be a string."); - - auto that = args.Holder(); - auto target = that->Get(args[0]->ToString())->ToObject(); - - args.GetReturnValue().Set(target); - } - - uint32_t _score; -}; - -class SampleContainer : public NAPA_OBJECTWRAP { -public: - - static void Init() { - auto isolate = v8::Isolate::GetCurrent(); - - auto functionTemplate = v8::FunctionTemplate::New(isolate, NewCallback); - functionTemplate->SetClassName(v8_helpers::MakeV8String(isolate, _exportName)); - functionTemplate->InstanceTemplate()->SetInternalFieldCount(1); - - functionTemplate->InstanceTemplate()->Set( - v8_helpers::MakeV8String(isolate, "node"), - v8::FunctionTemplate::New(isolate, SampleNode::NewCallback)); - - NAPA_SET_PROTOTYPE_METHOD(functionTemplate, "setNode", SetNodeCallback); - NAPA_SET_PROTOTYPE_METHOD(functionTemplate, "getNode", GetNodeCallback); - - NAPA_SET_PERSISTENT_CONSTRUCTOR(_exportName, functionTemplate->GetFunction()); - } - - static void NewInstance(const v8::FunctionCallbackInfo& args) { - auto isolate = v8::Isolate::GetCurrent(); - v8::HandleScope scope(isolate); - - auto constructor = NAPA_GET_PERSISTENT_CONSTRUCTOR(_exportName, SampleContainer); - JS_ASSERT(isolate, !constructor.IsEmpty(), "No registered constructor."); - - auto context = isolate->GetCurrentContext(); - auto instance = constructor->NewInstance(context).ToLocalChecked(); - - args.GetReturnValue().Set(instance); - } - -private: - - static constexpr const char* _exportName = "SampleContainer"; - - static void NewCallback(const v8::FunctionCallbackInfo& args) { - auto isolate = v8::Isolate::GetCurrent(); - v8::HandleScope scope(isolate); - - JS_ASSERT(isolate, args.IsConstructCall(), "Only constructor call is allowed"); - - auto container = new SampleContainer(); - container->Wrap(args.Holder()); - args.GetReturnValue().Set(args.Holder()); - } - - static void SetNodeCallback(const v8::FunctionCallbackInfo& args) { - auto isolate = v8::Isolate::GetCurrent(); - v8::HandleScope scope(isolate); - - CHECK_ARG(isolate, - args.Length() > 0 && !args[0]->IsUndefined(), - "The first argument must be a SampleNode instance."); - - auto that = args.Holder(); - that->CreateDataProperty(isolate->GetCurrentContext(), - v8_helpers::MakeV8String(isolate, "node"), - args[0]->ToObject()); - - args.GetReturnValue().SetUndefined(); - } - - static void GetNodeCallback(const v8::FunctionCallbackInfo& args) { - auto isolate = v8::Isolate::GetCurrent(); - v8::HandleScope scope(isolate); - - auto that = args.Holder(); - auto node = that->Get(v8_helpers::MakeV8String(isolate, "node"))->ToObject(); - - args.GetReturnValue().Set(node); - } -}; - -void CreateSampleNode(const v8::FunctionCallbackInfo& args) { - SampleNode::NewInstance(args); -} - -void CreateSampleContainer(const v8::FunctionCallbackInfo& args) { - SampleContainer::NewInstance(args); -} - -void Print(const v8::FunctionCallbackInfo& args) { - auto isolate = v8::Isolate::GetCurrent(); - v8::HandleScope scope(isolate); - - CHECK_ARG(isolate, - args.Length() > 0 && !args[0]->IsUndefined(), - "The first argument must be a string."); - - v8::String::Utf8Value value(args[0]); - args.GetReturnValue().Set(v8_helpers::MakeV8String(isolate, *value)); -} - -void Init(v8::Local exports) { - SampleNode::Init(); - SampleContainer::Init(); - - NAPA_SET_METHOD(exports, "createSampleNode", CreateSampleNode); - NAPA_SET_METHOD(exports, "createSampleContainer", CreateSampleContainer); - NAPA_SET_METHOD(exports, "print", Print); -} - -NAPA_MODULE(addon, Init); diff --git a/cpp-test/module/sample/sample.vcxproj b/cpp-test/module/sample/sample.vcxproj deleted file mode 100644 index 0258a3e..0000000 --- a/cpp-test/module/sample/sample.vcxproj +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - Debug - x64 - - - Release - x64 - - - - DynamicLibrary - true - sample - - - DynamicLibrary - false - sample - - - - - $(NapaVanillaRoot)\src\$(IntermediateOutputPath)\napa.lib;%(AdditionalDependencies) - - - BUILDING_NAPA_EXTENSION;%(PreprocessorDefinitions) - $(NapaVanillaRoot)\inc;%(AdditionalIncludeDirectories) - - - - - - - - - - - diff --git a/package.json b/package.json index 000b867..c58939d 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "install": "cmake-js compile", "buildd": "cmake-js compile --debug", "prepare": "tsc -p lib", - "pretest": "tsc -p test", + "pretest": "cmake-js compile -d test/module/addon && tsc -p test", "test": "mocha test --recursive", "unittest": "cmake-js compile -d unittest && node unittest/run.js" } diff --git a/src/module/core-modules/napa/metric-wrap.h b/src/module/core-modules/napa/metric-wrap.h index 6f2245c..14c3d48 100644 --- a/src/module/core-modules/napa/metric-wrap.h +++ b/src/module/core-modules/napa/metric-wrap.h @@ -6,7 +6,6 @@ #include - namespace napa { namespace module { @@ -14,8 +13,6 @@ namespace module { class MetricWrap : public NAPA_OBJECTWRAP { public: - - /// Initializes the wrap. static void Init(); diff --git a/src/module/core-modules/node/os.cpp b/src/module/core-modules/node/os.cpp index f1072bc..e4cae99 100644 --- a/src/module/core-modules/node/os.cpp +++ b/src/module/core-modules/node/os.cpp @@ -6,13 +6,18 @@ using namespace napa; using namespace napa::module; +void TypeCallback(const v8::FunctionCallbackInfo& args) { + auto isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + + args.GetReturnValue().Set(v8_helpers::MakeV8String(isolate, platform::GetOSType())); +} + void os::Init(v8::Local exports) { auto isolate = v8::Isolate::GetCurrent(); v8::HandleScope scope(isolate); auto context = isolate->GetCurrentContext(); - (void)exports->CreateDataProperty(context, - v8_helpers::MakeV8String(isolate, "type"), - v8_helpers::MakeV8String(isolate, platform::GetOSType())); + NAPA_SET_METHOD(exports, "type", TypeCallback); } \ No newline at end of file diff --git a/test/module-test.ts b/test/module-test.ts new file mode 100644 index 0000000..9f2e07f --- /dev/null +++ b/test/module-test.ts @@ -0,0 +1,440 @@ +import * as napa from ".."; +import * as assert from "assert"; +import * as path from "path"; + +type Zone = napa.zone.Zone; + +describe('napajs/module', function () { + this.timeout(0); + let napaZone = napa.zone.create('module-tests-zone', { workers: 1 }); + + describe('load', function () { + it('javascript module', () => { + return napaZone.execute((thisFilePath: string) => { + var assert = require("assert"); + var jsmodule = require(thisFilePath + '/module/jsmodule'); + + assert.notEqual(jsmodule, undefined); + assert.equal(jsmodule.wasLoaded, true); + }, [__dirname]); + }); + + it('json module', () => { + return napaZone.execute((thisFilePath: string) => { + var assert = require("assert"); + var jsonModule = require(thisFilePath + '/module/test.json'); + + assert.notEqual(jsonModule, undefined); + assert.equal(jsonModule.prop1, "val1"); + assert.equal(jsonModule.prop2, "val2"); + }, [__dirname]); + }); + + it('napa module', () => { + return napaZone.execute((thisFilePath: string) => { + var assert = require("assert"); + var napaModule = require(thisFilePath + '/module/addon/build/simple-napa-addon.napa'); + + assert.notEqual(napaModule, undefined); + assert.equal(napaModule.getModuleName(), "simple-napa-addon"); + }, [__dirname]); + }); + + it('object wrap module', () => { + return napaZone.execute((thisFilePath: string) => { + var assert = require("assert"); + var napaModule = require(thisFilePath + '/module/addon/build/simple-napa-addon.napa'); + + var obj = napaModule.createSimpleObjectWrap(); + assert.notEqual(obj, undefined); + obj.setValue(3); + assert.equal(obj.getValue(), 3); + }, [__dirname]); + }); + + it('circular dependencies', () => { + return napaZone.execute((thisFilePath: string) => { + var assert = require("assert"); + + var cycle_a = require(thisFilePath + '/module/cycle-a.js'); + var cycle_b = require(thisFilePath + '/module/cycle-b.js'); + + assert(cycle_a.done); + assert(cycle_b.done); + }, [__dirname]); + }); + }); + + describe('resolve', function () { + // TODO: support correct __dirname in annoymous function and move tests from 'esolution-tests.js' here. + it('require.resolve', () => { + return napaZone.execute(__dirname + "/module/resolution-tests.js", "run", []); + }); + }); + + describe('core-modules', function () { + describe('process', function () { + it.skip('argv', () => { + return napaZone.execute(() => { + var assert = require("assert"); + + assert(process.argv.length > 0); + assert(process.argv[0].includes('node')); + }, []); + }); + + it('execPath', () => { + return napaZone.execute(() => { + var assert = require("assert"); + + assert(process.execPath.includes('node')); + }, []); + }); + + it('env', () => { + return napaZone.execute(() => { + var assert = require("assert"); + + process.env.test = "napa-test"; + assert.equal(process.env.test, "napa-test"); + }, []); + }); + + it('platform', () => { + return napaZone.execute(() => { + var assert = require("assert"); + + assert(process.platform == 'win32' || + process.platform == 'darwin' || + process.platform == 'linux' || + process.platform == 'freebsd'); + }, []); + }); + + it('umask', () => { + return napaZone.execute(() => { + var assert = require("assert"); + + var old = process.umask(0); + assert.equal(process.umask(old), 0); + }, []); + }); + + it('chdir', () => { + return napaZone.execute(() => { + var assert = require("assert"); + + var cwd = process.cwd(); + process.chdir('..'); + assert.notEqual(cwd, process.cwd()); + assert(cwd.includes(process.cwd())); + process.chdir(cwd); + assert.equal(cwd, process.cwd()); + }, []); + }); + + it('pid', () => { + return napaZone.execute(() => { + var assert = require("assert"); + + assert.notEqual(typeof process.pid, undefined); + assert(!isNaN(process.pid)); + }, []); + }); + }); + + describe('fs', function () { + it('existsSync', () => { + return napaZone.execute((thisFilePath: string) => { + var assert = require("assert"); + var fs = require('fs'); + + assert(fs.existsSync(thisFilePath + '/module/jsmodule.js')); + assert.ifError(fs.existsSync('non-existing-file.txt')); + }, [__dirname]); + }); + + it('readFileSync', () => { + return napaZone.execute((thisFilePath: string) => { + var assert = require("assert"); + var fs = require('fs'); + + var content = JSON.parse(fs.readFileSync(thisFilePath + '/module/test.json')); + assert.equal(content.prop1, 'val1'); + assert.equal(content.prop2, 'val2'); + }, [__dirname]); + }); + + it('mkdirSync', () => { + return napaZone.execute((thisFilePath: string) => { + var assert = require("assert"); + var fs = require('fs'); + + fs.mkdirSync(thisFilePath + '/module/test-dir'); + assert(fs.existsSync(thisFilePath + '/module/test-dir')); + }, [__dirname]).then(()=> { + // Cleanup + var fs = require('fs'); + if (fs.existsSync('./module/test-dir')) { + fs.rmdir('./module/test-dir'); + } + }) + }); + + it('writeFileSync', () => { + return napaZone.execute((thisFilePath: string) => { + var assert = require("assert"); + var fs = require('fs'); + + fs.writeFileSync(thisFilePath + '/module/test-file', 'test'); + assert.equal(fs.readFileSync(thisFilePath + '/module/test-file'), 'test'); + }, [__dirname]).then(()=> { + // Cleanup + var fs = require('fs'); + if (fs.existsSync('./module/test-file')) { + fs.unlinkSync('./module/test-file'); + } + }) + }); + + it('readFileSync', () => { + return napaZone.execute((thisFilePath: string) => { + var assert = require("assert"); + var fs = require('fs'); + + var testDir = thisFilePath + '/module/test-dir'; + fs.mkdirSync(testDir); + fs.writeFileSync(testDir + '/1', 'test'); + fs.writeFileSync(testDir + '/2', 'test'); + + assert.deepEqual(fs.readdirSync(testDir), ['1', '2']); + }, [__dirname]).then(()=> { + // Cleanup + var fs = require('fs'); + if (fs.existsSync('./module/test-dir')) { + fs.unlinkSync('./module/test-dir/1'); + fs.unlinkSync('./module/test-dir/2'); + fs.rmdir('./module/test-dir'); + } + }) + }); + }); + + describe('path', function () { + it('normalize', () => { + return napaZone.execute(() => { + var assert = require("assert"); + var path = require("path"); + + if (process.platform == 'win32') { + assert.equal(path.normalize('a\\b\\..\\c/./d/././.'), "a\\c\\d"); + } else { + assert.equal(path.normalize('a\\b\\..\\c/./d/././.'), "a/c/d"); + } + }, []); + }); + + it('resolve', () => { + return napaZone.execute(() => { + var assert = require("assert"); + var path = require("path"); + + if (process.platform == 'win32') { + assert.equal(path.resolve('c:\\foo/bar', "a.txt"), "c:\\foo\\bar\\a.txt"); + assert.equal(path.resolve("abc.txt"), process.cwd() + "\\abc.txt"); + assert.equal(path.resolve("abc", "efg", "../hij", "./xyz.txt"), process.cwd() + "\\abc\\hij\\xyz.txt"); + assert.equal(path.resolve("abc", "d:/a.txt"), "d:\\a.txt"); + } else { + assert.equal(path.resolve('/foo/bar', "a.txt"), "/foo/bar/a.txt"); + assert.equal(path.resolve("abc.txt"), process.cwd() + "/abc.txt"); + assert.equal(path.resolve("abc", "efg", "../hij", "./xyz.txt"), process.cwd() + "/abc/hij/xyz.txt"); + assert.equal(path.resolve("abc", "/a.txt"), "/a.txt"); + } + }, []); + }); + + it('join', () => { + return napaZone.execute(() => { + var assert = require("assert"); + var path = require("path"); + + if (process.platform == 'win32') { + assert.equal(path.join("/foo", "bar", "baz/asdf", "quux", ".."), "\\foo\\bar\\baz\\asdf"); + } else { + assert.equal(path.join("/foo", "bar", "baz/asdf", "quux", ".."), "/foo/bar/baz/asdf"); + } + }, []); + }); + + // TODO: fix bugs + // 1. Error: the string "AssertionError: '.' == 'c:'" was thrown, throw an Error :) + // 2. Error: the string "AssertionError: 'c:' == 'c:\\\\'" was thrown, throw an Error :) + it.skip('dirname', () => { + return napaZone.execute(() => { + var assert = require("assert"); + var path = require("path"); + + if (process.platform == 'win32') { + assert.equal(path.dirname("c:"), "c:"); + assert.equal(path.dirname("c:\\windows"), "c:\\"); + assert.equal(path.dirname("c:\\windows\\abc.txt"), "c:\\windows"); + } else { + assert.equal(path.dirname("/"), "/"); + assert.equal(path.dirname("/etc"), "/"); + assert.equal(path.dirname("/etc/passwd"), "/etc"); + } + }, []); + }); + + it('basename', () => { + return napaZone.execute(() => { + var assert = require("assert"); + var path = require("path"); + + if (process.platform == 'win32') { + assert.equal(path.basename("c:\\windows\\abc.txt"), "abc.txt"); + assert.equal(path.basename("c:\\windows\\a"), "a"); + assert.equal(path.basename("c:\\windows\\abc.txt", ".txt"), "abc"); + assert.equal(path.basename("c:\\windows\\abc.txt", ".Txt"), "abc.txt"); + } else { + assert.equal(path.basename("/test//abc.txt"), "abc.txt"); + assert.equal(path.basename("/test//a"), "a"); + assert.equal(path.basename("/test/abc.txt", ".txt"), "abc"); + assert.equal(path.basename("/windows/abc.txt", ".Txt"), "abc.txt"); + } + }, []); + }); + + // TODO: fix bugs + // 1. Error: the string "AssertionError: '' == '.'" was thrown, throw an Error :) + it.skip('extname', () => { + return napaZone.execute(() => { + var assert = require("assert"); + var path = require("path"); + + if (process.platform == 'win32') { + assert.equal(path.extname("c:\\windows\\abc.txt"), ".txt"); + assert.equal(path.extname("c:\\windows\\a.json.txt"), ".txt"); + assert.equal(path.extname("c:\\windows\\a."), "."); + } else { + assert.equal(path.extname("/test/abc.txt"), ".txt"); + assert.equal(path.extname("/test/a.json.txt"), ".txt"); + assert.equal(path.extname("/test/a."), "."); + } + }, []); + }); + + it('isAbsolute', () => { + return napaZone.execute(() => { + var assert = require("assert"); + var path = require("path"); + + if (process.platform == 'win32') { + assert.equal(path.isAbsolute("c:\\windows\\a."), true); + assert.equal(path.isAbsolute("c:/windows/.."), true); + assert.equal(path.isAbsolute("../abc"), false); + assert.equal(path.isAbsolute("./abc"), false); + assert.equal(path.isAbsolute("abc"), false); + } else { + assert.equal(path.isAbsolute("/test/a."), true); + assert.equal(path.isAbsolute("/test/.."), true); + assert.equal(path.isAbsolute("../abc"), false); + assert.equal(path.isAbsolute("./abc"), false); + assert.equal(path.isAbsolute("abc"), false); + } + }, []); + }); + + it('relative', () => { + return napaZone.execute(() => { + var assert = require("assert"); + var path = require("path"); + + if (process.platform == 'win32') { + assert.equal(path.relative("c:\\a\\..\\b", "c:\\b"), ""); + assert.equal(path.relative("c:/a", "d:/b/../c"), "d:\\c"); + assert.equal(path.relative("z:/a", "a.txt"), process.cwd() + "\\a.txt"); + assert.equal(path.relative("c:/a", "c:/"), ".."); + } else { + assert.equal(path.relative("/test/a/../b", "/test/b"), ""); + assert.equal(path.relative("/test/a", "/test1/b/../c"), "/test1/c"); + assert.equal(path.relative("/test/a", "a.txt"), process.cwd() + "/a.txt"); + assert.equal(path.relative("/test/a", "/test/"), ".."); + } + }, []); + }); + + it('sep', () => { + return napaZone.execute(() => { + var assert = require("assert"); + var path = require("path"); + + if (process.platform == 'win32') { + assert.equal(path.sep, "\\"); + } else { + assert.equal(path.sep, "/"); + } + }, []); + }); + }); + + describe('os', function () { + it('type', () => { + return napaZone.execute(() => { + var assert = require("assert"); + var os = require("os"); + + assert(os.type() == "Windows_NT" || os.type() == "Darwin" || os.type() == "Linux"); + }, []); + }); + }); + }); + + describe('async', function () { + it('post async work', () => { + return napaZone.execute((thisFilePath: string) => { + var assert = require("assert"); + var napaModule = require(thisFilePath + '/module/addon/build/simple-napa-addon.napa'); + + var obj = napaModule.createSimpleObjectWrap(); + obj.setValue(3); + + var promise = new Promise((resolve) => { + obj.postIncrementWork((newValue: number) => { + resolve(newValue); + }); + }); + + // The value shouldn't have changed yet. + assert.equal(obj.getValue(), 3); + + return promise; + }, [__dirname]).then((result) => { + assert.equal(result.value, 4); + }); + }); + + it('do async work', () => { + return napaZone.execute((thisFilePath: string) => { + var assert = require("assert"); + var napaModule = require(thisFilePath + '/module/addon/build/simple-napa-addon.napa'); + + var obj = napaModule.createSimpleObjectWrap(); + obj.setValue(8); + + var promise = new Promise((resolve) => { + obj.doIncrementWork((newValue: number) => { + resolve(newValue); + }); + }); + + // The actual increment happened in the same thread. + assert.equal(obj.getValue(), 9); + + return promise; + }, [__dirname]).then((result) => { + assert.equal(result.value, 9); + }); + }); + }); +}); \ No newline at end of file diff --git a/test/module/.gitignore b/test/module/.gitignore new file mode 100644 index 0000000..1ed1a21 --- /dev/null +++ b/test/module/.gitignore @@ -0,0 +1,7 @@ +test-dir +test-file + +!node_modules + +# unignore js files used for module testing +!**/*.js diff --git a/test/module/addon/CMakeLists.txt b/test/module/addon/CMakeLists.txt new file mode 100644 index 0000000..f539c5a --- /dev/null +++ b/test/module/addon/CMakeLists.txt @@ -0,0 +1,45 @@ +cmake_minimum_required(VERSION 3.2 FATAL_ERROR) + +project("simple-napa-addon") + +set(NAPA_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../..) + +# Require Cxx14 features +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# The target name +set(TARGET_NAME ${PROJECT_NAME}) + +# The generated library +add_library(${TARGET_NAME} SHARED + addon.cpp + simple-object-wrap.cpp) + +# Change output extension to 'napa' +set_target_properties(${TARGET_NAME} PROPERTIES PREFIX "" SUFFIX ".napa") + +# Include directories +target_include_directories(${TARGET_NAME} + PRIVATE + ${NAPA_ROOT}/inc + ${CMAKE_JS_INC}) + +# Link libraries +target_link_libraries(${TARGET_NAME} PRIVATE ${CMAKE_JS_LIB}) + +# Link with napa shared library +if (WIN32) + target_link_libraries(${TARGET_NAME} PRIVATE ${NAPA_ROOT}/bin/napa.lib) +else() + target_link_libraries(${TARGET_NAME} PRIVATE ${NAPA_ROOT}/bin/libnapa.so) +endif() + +# Compiler definitions +target_compile_definitions(${TARGET_NAME} PRIVATE BUILDING_NAPA_EXTENSION) + +# Set output directory for the addon +set_target_properties(${TARGET_NAME} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_SOURCE_DIR}/build + RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_SOURCE_DIR}/build +) diff --git a/test/module/addon/addon.cpp b/test/module/addon/addon.cpp new file mode 100644 index 0000000..34172fa --- /dev/null +++ b/test/module/addon/addon.cpp @@ -0,0 +1,28 @@ +#include + +#include "simple-object-wrap.h" + +using namespace napa; +using namespace napa::test; +using namespace napa::module; + + +void GetModuleName(const v8::FunctionCallbackInfo& args) { + auto isolate = v8::Isolate::GetCurrent(); + v8::HandleScope scope(isolate); + + args.GetReturnValue().Set(v8_helpers::MakeV8String(isolate, "simple-napa-addon")); +} + +void CreateSimpleObjectWrap(const v8::FunctionCallbackInfo& args) { + SimpleObjectWrap::NewInstance(args); +} + +void Init(v8::Local exports) { + SimpleObjectWrap::Init(); + + NAPA_SET_METHOD(exports, "getModuleName", GetModuleName); + NAPA_SET_METHOD(exports, "createSimpleObjectWrap", CreateSimpleObjectWrap); +} + +NAPA_MODULE(addon, Init); diff --git a/test/module/addon/simple-object-wrap.cpp b/test/module/addon/simple-object-wrap.cpp new file mode 100644 index 0000000..4cf4de5 --- /dev/null +++ b/test/module/addon/simple-object-wrap.cpp @@ -0,0 +1,113 @@ +#include "simple-object-wrap.h" + +#include +#include +#include +#include + +using namespace napa::module; +using namespace napa::test; +using namespace napa::v8_helpers; + +NAPA_DEFINE_PERSISTENT_CONSTRUCTOR(SimpleObjectWrap); + +void SimpleObjectWrap::Init() { + auto isolate = v8::Isolate::GetCurrent(); + + // Prepare constructor template. + auto functionTemplate = v8::FunctionTemplate::New(isolate, DefaultConstructorCallback); + functionTemplate->SetClassName(MakeV8String(isolate, exportName)); + functionTemplate->InstanceTemplate()->SetInternalFieldCount(1); + + // Prototypes. + NAPA_SET_PROTOTYPE_METHOD(functionTemplate, "getValue", GetValue); + NAPA_SET_PROTOTYPE_METHOD(functionTemplate, "setValue", SetValue); + NAPA_SET_PROTOTYPE_METHOD(functionTemplate, "doIncrementWork", DoIncrementWork); + NAPA_SET_PROTOTYPE_METHOD(functionTemplate, "postIncrementWork", PostIncrementWork); + + // Set persistent constructor into V8. + NAPA_SET_PERSISTENT_CONSTRUCTOR(exportName, functionTemplate->GetFunction()); +} + +void SimpleObjectWrap::NewInstance(const v8::FunctionCallbackInfo& args) { + auto isolate = v8::Isolate::GetCurrent(); + auto context = isolate->GetCurrentContext(); + + auto constructor = NAPA_GET_PERSISTENT_CONSTRUCTOR(exportName, ZoneWrap); + args.GetReturnValue().Set(constructor->NewInstance(context).ToLocalChecked()); +} + +void SimpleObjectWrap::GetValue(const v8::FunctionCallbackInfo& args) { + auto isolate = v8::Isolate::GetCurrent(); + + auto wrap = ObjectWrap::Unwrap(args.Holder()); + + args.GetReturnValue().Set(wrap->value); +} + +void SimpleObjectWrap::SetValue(const v8::FunctionCallbackInfo& args) { + auto isolate = v8::Isolate::GetCurrent(); + + CHECK_ARG(isolate, args[0]->IsUint32(), "first argument to setValue must be a uint32"); + + auto wrap = ObjectWrap::Unwrap(args.Holder()); + wrap->value = args[0]->Uint32Value(); +} + +void SimpleObjectWrap::DoIncrementWork(const v8::FunctionCallbackInfo& args) { + auto isolate = v8::Isolate::GetCurrent(); + + CHECK_ARG(isolate, args.Length() == 1 && args[0]->IsFunction(), "It requires a callback as arguments"); + + auto wrap = ObjectWrap::Unwrap(args.Holder()); + + napa::zone::DoAsyncWork( + v8::Local::Cast(args[0]), + [wrap](auto complete) { + // This runs at the same thread. + auto newValue = ++wrap->value; + + complete(reinterpret_cast(static_cast(newValue))); + }, + [](auto jsCallback, void* result) { + // This runs at the same thread as one DoIncrementWork() is called. + auto isolate = v8::Isolate::GetCurrent(); + + int32_t argc = 1; + v8::Local argv[] = { + v8::Integer::NewFromUnsigned(isolate, static_cast(reinterpret_cast(result))) + }; + + jsCallback->Call(isolate->GetCurrentContext()->Global(), argc, argv); + } + ); +} + +void SimpleObjectWrap::PostIncrementWork(const v8::FunctionCallbackInfo& args) { + auto isolate = v8::Isolate::GetCurrent(); + + CHECK_ARG(isolate, args.Length() == 1 && args[0]->IsFunction(), "It requires a callback as arguments"); + + auto wrap = ObjectWrap::Unwrap(args.Holder()); + + napa::zone::PostAsyncWork( + v8::Local::Cast(args[0]), + [wrap]() { + // This runs at the separate thread. + auto newValue = ++wrap->value; + + return reinterpret_cast(static_cast(newValue)); + }, + [](auto jsCallback, void* result) { + // This runs at the same thread as one PostIncrementWork() is called. + auto isolate = v8::Isolate::GetCurrent(); + + int32_t argc = 1; + v8::Local argv[] = { + v8::Integer::NewFromUnsigned(isolate, static_cast(reinterpret_cast(result))) + }; + + jsCallback->Call(isolate->GetCurrentContext()->Global(), argc, argv); + } + ); +} diff --git a/test/module/addon/simple-object-wrap.h b/test/module/addon/simple-object-wrap.h new file mode 100644 index 0000000..6fc66c7 --- /dev/null +++ b/test/module/addon/simple-object-wrap.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include + +#include + +namespace napa { +namespace test { + + /// A simple object wrap for testing. + class SimpleObjectWrap : public NAPA_OBJECTWRAP { + public: + + /// Exported class name. + static constexpr const char* exportName = "SimpleObjectWrap"; + + /// Initializes the wrap. + static void Init(); + + /// Create a new wrap instance. + static void NewInstance(const v8::FunctionCallbackInfo& args); + + std::atomic value = 0; + + private: + + /// Declare persistent constructor to create Zone Javascript wrapper instance. + NAPA_DECLARE_PERSISTENT_CONSTRUCTOR; + + // SimpleObjectWrap methods + static void GetValue(const v8::FunctionCallbackInfo& args); + static void SetValue(const v8::FunctionCallbackInfo& args); + static void DoIncrementWork(const v8::FunctionCallbackInfo& args); + static void PostIncrementWork(const v8::FunctionCallbackInfo& args); + + /// Friend default constructor callback. + template + friend void napa::module::DefaultConstructorCallback(const v8::FunctionCallbackInfo&); + }; +} +} \ No newline at end of file diff --git a/cpp-test/module/module-loader/cycle-a.js b/test/module/cycle-a.js similarity index 100% rename from cpp-test/module/module-loader/cycle-a.js rename to test/module/cycle-a.js diff --git a/cpp-test/module/module-loader/cycle-b.js b/test/module/cycle-b.js similarity index 100% rename from cpp-test/module/module-loader/cycle-b.js rename to test/module/cycle-b.js diff --git a/test/module/jsmodule.js b/test/module/jsmodule.js new file mode 100644 index 0000000..3833525 --- /dev/null +++ b/test/module/jsmodule.js @@ -0,0 +1 @@ +exports.wasLoaded = true; \ No newline at end of file diff --git a/test/module/node_modules/file.js b/test/module/node_modules/file.js new file mode 100644 index 0000000..e69de29 diff --git a/test/module/resolution-tests.js b/test/module/resolution-tests.js new file mode 100644 index 0000000..4516483 --- /dev/null +++ b/test/module/resolution-tests.js @@ -0,0 +1,38 @@ +var assert = require('assert'); + +function run() { + // Core module + assert(require.resolve('fs'), 'fs'); + + // Full path with extension + assert(require.resolve(__dirname + '/sub-folder/file.js'), __dirname + '/sub-folder/file.js'); + + // Full path without extension + assert(require.resolve(__dirname + '/sub-folder/file'), __dirname + '/sub-folder/file.js'); + + // Relative path with extension + assert(require.resolve('./sub-folder/file.js'), __dirname + '/sub-folder/file.js'); + + // Relative path without extension + assert(require.resolve('./sub-folder/file'), __dirname + '/sub-folder/file.js'); + + // Relative path with non normalized path + assert(require.resolve('./sub-folder/.././sub-folder/file.js'), __dirname + '/sub-folder/file.js'); + + // Relative path without extension to napa addon + assert(require.resolve('./addon/build/simple-napa-addon'), __dirname + '/addon/build/simple-napa-addon.napa'); + + // From node_modules with extension + assert(require.resolve('file.js'), __dirname + '/node_modules/file.js'); + + // From node_modules without extension + assert(require.resolve('file'), __dirname + '/node_modules/file.js'); + + // TODO: Fix this issue: require.resolve should throw an exception if file doesn't exist. + // Resolving non-existing file should throw + // assert.throws(() => { + // require.resolve('./sub-folder/non-existing-file.js'); + // }); +} + +exports.run = run; diff --git a/test/module/sub-folder/file.js b/test/module/sub-folder/file.js new file mode 100644 index 0000000..e69de29 diff --git a/test/module/test.json b/test/module/test.json new file mode 100644 index 0000000..c0506ee --- /dev/null +++ b/test/module/test.json @@ -0,0 +1,4 @@ +{ + "prop1": "val1", + "prop2": "val2" +}