Merged PR 324526: Enable module tests as part of npm test

Enable module tests as part of npm test
This commit is contained in:
Asi Bross 2017-07-14 20:45:28 +00:00 коммит произвёл Asi Bross
Родитель 42549269cb
Коммит 0dc3a40d00
66 изменённых файлов: 727 добавлений и 2470 удалений

Просмотреть файл

@ -1,6 +1,5 @@
bin
build
cpp-test
tools
.npmrc

1
cpp-test/.gitignore поставляемый
Просмотреть файл

@ -1 +0,0 @@
!node_modules

Просмотреть файл

@ -1,3 +0,0 @@
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "napa-catch-reporter.h"

Просмотреть файл

@ -1,172 +0,0 @@
#include "catch.hpp"
#include "napa-initialization-guard.h"
#include <napa-memory.h>
#include <napa/memory/allocator-debugger.h>
#include <napa/stl/allocator.h>
#include <napa/stl/string.h>
#include <napa/stl/vector.h>
#include <napa/stl/map.h>
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<Allocator>(&GetDefaultAllocator(), [](Allocator*){}));
REQUIRE(std::string(debugger.GetType()) == "SimpleAllocatorDebugger<DefaultAllocator>");
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<int> _vector;
napa::stl::Map<size_t, int> _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<Foo>("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<Foo>("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();
}

Просмотреть файл

@ -1,57 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(EnvironmentConfig)" />
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.Default.props" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{4D4E992D-79A5-419D-8161-55D93069C606}</ProjectGuid>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup>
<TestDir>$(OutDir)api-tests</TestDir>
</PropertyGroup>
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.props" />
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)\memory-tests.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)\zone-tests.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(NapaVanillaRoot)\src\napa.vcxproj" />
</ItemGroup>
<!-- Test artifacts binplace -->
<ItemGroup>
<Robocopy Include="$(OutputPath)\$(TargetFileName)">
<DestinationFolder>$(IntermediateOutputPath)\api-tests\node_modules\napajs\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="$(NapaVanillaRoot)\package\$(IntermediateOutputPath)\node_modules\napajs">
<DestinationFolder>$(IntermediateOutputPath)\api-tests\node_modules\napajs</DestinationFolder>
</Robocopy>
</ItemGroup>
<!-- Use napa catch adapter -->
<Import Project="$(NapaVanillaRoot)\tools\catch-adapter\napa-catch.targets" />
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.targets" />
</Project>

Просмотреть файл

@ -1,24 +0,0 @@
#pragma once
#include <napa.h>
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();
}
};
};

Просмотреть файл

@ -1,190 +0,0 @@
#include "catch.hpp"
#include "napa-initialization-guard.h"
#include <napa.h>
#include <future>
// 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<napa::Result> 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<napa::Result> 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<napa::Result> 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<napa::Result> promise1;
auto future1 = promise1.get_future();
std::promise<napa::Result> 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\"");
}
}

Просмотреть файл

@ -1,3 +0,0 @@
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "napa-catch-reporter.h"

Просмотреть файл

@ -1,122 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(EnvironmentConfig)" />
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.Default.props" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{2C45E1F3-34B4-4F39-A4F5-4CEE2512878C}</ProjectGuid>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup>
<TestDir>$(OutDir)component-tests</TestDir>
</PropertyGroup>
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.props" />
<ItemDefinitionGroup>
<ClCompile>
<DisableSpecificWarnings>4100;4251;4459;4996</DisableSpecificWarnings>
<PreprocessorDefinitions>NAPA_EXPORTS;NAPA_BINDING_EXPORTS;BUILDING_NAPA_EXTENSION;BUILDING_V8_SHARED;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\test\component;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>Winmm.lib;Dbghelp.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>$(NapaVanillaRoot)\src\$(IntermediateOutputPath)\napa.lib;%(AdditionalDependencies)</AdditionalDependencies>
<!-- This is for testing only since V8 can export platform APIs at the latest version. -->
<AdditionalDependencies>$(Pkgnapa_nodelib_vc140)\lib\$(BuildType)\$(BuildTarget)\v8_libbase.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>$(Pkgnapa_nodelib_vc140)\lib\$(BuildType)\$(BuildTarget)\v8_libplatform.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<!-- Product code that is tested and needs to compile -->
<ItemGroup>
<ClCompile Include="$(NapaVanillaRoot)\src\api\api.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\memory\built-in-allocators.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\binary-module-loader.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\core-module-loader.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\javascript-module-loader.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\json-module-loader.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\module-cache.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\module-loader.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\module-loader-helpers.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\module-resolver.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\module\module.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\platform\win\platform.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\platform\win\thread-local-storage.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\providers\providers.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\settings\settings-parser.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\store\store.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\v8\v8-common.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\async-complete-task.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\call-context.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\call-task.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\eval-task.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\napa-zone.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\node-zone.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\simple-thread-pool.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\terminable-task.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\timeout-service.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\worker.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\worker-context.cpp" />
</ItemGroup>
<!-- Core modules -->
<Import Project="$(NapaVanillaRoot)\src\module\core-modules\napa\napa-core-modules.proj" />
<Import Project="$(NapaVanillaRoot)\src\module\core-modules\node\node-core-modules.proj" />
<!-- Test code -->
<ItemGroup>
<ClCompile Include="main.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)\node-zone-tests.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)\tasks-tests.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)\worker-tests.cpp" />
</ItemGroup>
<!-- Test artifacts binplace -->
<ItemGroup>
<Robocopy Include="$(OutputPath)\$(TargetFileName)">
<DestinationFolder>$(IntermediateOutputPath)\component-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="$(NapaVanillaRoot)\lib\$(IntermediateOutputPath)">
<DestinationFolder>$(IntermediateOutputPath)\component-tests\lib</DestinationFolder>
<FileMatch>*.j*</FileMatch>
<IsRecursive>true</IsRecursive>
</Robocopy>
<Robocopy Include="$(NapaVanillaRoot)\src\$(IntermediateOutputPath)\napa.dll">
<DestinationFolder>$(IntermediateOutputPath)\component-tests\bin</DestinationFolder>
</Robocopy>
</ItemGroup>
<!-- Use napa catch adapter -->
<Import Project="$(NapaVanillaRoot)\tools\catch-adapter\napa-catch.targets" />
<!-- Package dependencies -->
<Import Project="$(Pkgboost)\build\native\boost.targets" />
<Import Project="$(Pkgboost_chrono_vc140)\build\native\boost_chrono-vc140.targets" />
<Import Project="$(Pkgboost_date_time_vc140)\build\native\boost_date_time-vc140.targets" />
<Import Project="$(Pkgboost_filesystem_vc140)\build\native\boost_filesystem-vc140.targets" />
<Import Project="$(Pkgboost_program_options_vc140)\build\native\boost_program_options-vc140.targets" />
<Import Project="$(Pkgboost_regex_vc140)\build\native\boost_regex-vc140.targets" />
<Import Project="$(Pkgboost_system_vc140)\build\native\boost_system-vc140.targets" />
<Import Project="$(Pkgboost_thread_vc140)\build\native\boost_thread-vc140.targets" />
<Import Project="$(Pkgnapa_nodelib_vc140)\exports_v8_includes.props" />
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.targets" />
</Project>

Просмотреть файл

@ -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();
}
};
};

Просмотреть файл

@ -1,53 +0,0 @@
#include "catch.hpp"
#include "zone/node-zone.h"
#include <future>
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<ResultCode> 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<Result> 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");
}
}

Просмотреть файл

@ -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 <vector>
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<v8::Context> 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<CallContext>(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<CallContext>(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<CallContext>(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<CallTask>(500ms, std::make_shared<CallContext>(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<CallTask>(500ms, std::make_shared<CallContext>(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<CallTask>(500ms, std::make_shared<CallContext>(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<CallTask>(500ms, std::make_shared<CallContext>(request2, [&](Result res) {
response2 = std::move(res);
})).Execute();
REQUIRE(response2.code == NAPA_RESULT_SUCCESS);
REQUIRE(response2.returnValue == "8");
}
}

Просмотреть файл

@ -1,146 +0,0 @@
#include "catch.hpp"
#include "zone/worker.h"
#include "napa-initialization-guard.h"
#include "v8.h"
#include <atomic>
#include <condition_variable>
#include <mutex>
using namespace napa;
using namespace napa::settings;
using namespace napa::zone;
class TestTask : public Task {
public:
TestTask(std::function<std::string(void)> func = []() { return ""; })
: numberOfExecutions(0), _func(std::move(func)) {}
virtual void Execute() override {
result = _func();
numberOfExecutions++;
}
std::atomic<uint32_t> numberOfExecutions;
std::string result;
private:
std::function<std::string(void)> _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<Worker>(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<Worker>(0, ZoneSettings(), [](WorkerId) {}, [](WorkerId) {});
auto task = std::make_shared<TestTask>();
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<Worker>(0, ZoneSettings(), [](WorkerId) {}, [&cv](WorkerId) {
cv.notify_one();
});
worker->Schedule(std::make_shared<TestTask>());
std::unique_lock<std::mutex> 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<Worker>(0, ZoneSettings(), [](WorkerId) {}, [](WorkerId) {});
auto task = std::make_shared<TestTask>();
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<Worker>(0, ZoneSettings(), [](WorkerId) {}, [](WorkerId) {});
auto task = std::make_shared<TestTask>([]() {
auto isolate = v8::Isolate::GetCurrent();
auto context = isolate->GetCurrentContext();
v8::Local<v8::String> 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<Worker>(0, ZoneSettings(), [](WorkerId) {}, [](WorkerId) {});
auto task = std::make_shared<TestTask>([]() {
auto isolate = v8::Isolate::GetCurrent();
auto context = isolate->GetCurrentContext();
v8::Local<v8::String> 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");
}

Просмотреть файл

@ -1,88 +0,0 @@
#include <napa-module.h>
#include <napa-async.h>
#include <atomic>
#include <functional>
using namespace napa;
using namespace napa::module;
using namespace v8;
namespace {
std::atomic<uint32_t> _now(0);
}
/// <summary> It increases a number by a given parameter asynchronously and run a callback at the next execution loop. </summary>
void Increase(const FunctionCallbackInfo<Value>& 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<Function>::Cast(args[1]),
[value]() {
// This runs at the separate thread.
_now += value;
return reinterpret_cast<void*>(static_cast<uintptr_t>(_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<Value> argv[] =
{ Integer::NewFromUnsigned(isolate, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(result))) };
jsCallback->Call(isolate->GetCurrentContext()->Global(), argc, argv);
}
);
}
/// <summary> It increases a number by a given parameter synchronously and run a callback at the next execution loop. </summary>
void IncreaseSync(const FunctionCallbackInfo<Value>& 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<Function>::Cast(args[1]),
[value](auto complete) {
// This runs at the same thread.
_now += value;
complete(reinterpret_cast<void*>(static_cast<uintptr_t>(_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<Value> argv[] =
{ Integer::NewFromUnsigned(isolate, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(result))) };
jsCallback->Call(isolate->GetCurrentContext()->Global(), argc, argv);
}
);
}
/// <summary> It returns the current value of a number. </summary>
void Now(const FunctionCallbackInfo<Value>& args) {
auto isolate = args.GetIsolate();
HandleScope scope(isolate);
args.GetReturnValue().Set(Integer::NewFromUnsigned(isolate, _now));
}
void Init(Local<Object> exports) {
NAPA_SET_METHOD(exports, "increase", Increase);
NAPA_SET_METHOD(exports, "increaseSync", IncreaseSync);
NAPA_SET_METHOD(exports, "now", Now);
}
NAPA_MODULE(addon, Init)

Просмотреть файл

@ -1,43 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(EnvironmentConfig)" />
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.Default.props" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<AddonName>async</AddonName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<AddonName>async</AddonName>
</PropertyGroup>
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.props" />
<ItemDefinitionGroup>
<Link>
<AdditionalDependencies>$(NapaVanillaRoot)\src\$(IntermediateOutputPath)\napa.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ClCompile>
<PreprocessorDefinitions>BUILDING_NAPA_EXTENSION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)\async.cpp" />
</ItemGroup>
<Target Name="ChangeExtention" AfterTargets="Build">
<Move SourceFiles="$(OutputPath)\$(TargetFileName)" DestinationFiles="$(OutputPath)\$(AddonName).napa" />
</Target>
<Import Project="$(Pkgnapa_nodelib_vc140)\exports_v8_includes.props" />
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.targets" />
</Project>

Просмотреть файл

@ -1,10 +0,0 @@
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(EnvironmentConfig)" />
<ItemGroup>
<ProjectFile Include="sample\sample.vcxproj" />
<ProjectFile Include="module-loader\napa-module-loader-tests.vcxproj" />
</ItemGroup>
<Import Project="$(ExtendedTargetsPath)\Traversal.targets" />
</Project>

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;

Просмотреть файл

@ -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"
}
]

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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');

Просмотреть файл

@ -1 +0,0 @@
{ "query" : "query", "document" : "document" }

Просмотреть файл

@ -1,4 +0,0 @@
exports.run = function() {
global.toGlobal = 'toGlobal';
return global.fromGlobal;
}

Просмотреть файл

@ -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;

Просмотреть файл

@ -1,6 +0,0 @@
var exports = module.exports = {};
exports.print = function(data) {
var proxy = require('./test/toproxy');
return proxy.run(data);
};

Просмотреть файл

@ -1,5 +0,0 @@
var obj = require('./fstest.json');
if (obj.query == 'query' && obj.document == 'document')
true;
else
false;

Просмотреть файл

@ -1,9 +0,0 @@
var tconsole = exports;
for (var prop in console) {
tconsole[prop] = console[prop];
}
tconsole.runTest = function() {
return 'tconsole.runTest';
}

Просмотреть файл

@ -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';
}

Просмотреть файл

@ -1,3 +0,0 @@
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include "napa-catch-reporter.h"

Просмотреть файл

@ -1,393 +0,0 @@
#include <catch.hpp>
#include <module/loader/module-loader.h>
#include <napa/module/module-internal.h>
#include <napa/v8-helpers.h>
#include <platform/dll.h>
#include <platform/filesystem.h>
#include <platform/platform.h>
#include <utils/string.h>
#include <zone/scheduler.h>
#include <zone/napa-zone.h>
#include <v8/array-buffer-allocator.h>
#include <v8/v8-common.h>
#include <chrono>
#include <condition_variable>
#include <iostream>
#include <future>
#include <mutex>
#include <thread>
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<bool(v8::Local<v8::Value>)> verifier) {
v8_extensions::ArrayBufferAllocator allocator;
v8::Isolate::CreateParams params;
params.array_buffer_allocator = &allocator;
auto isolate = v8::Isolate::New(params);
std::unique_ptr<v8::Isolate, std::function<void(v8::Isolate*)>> 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<bool(v8::Local<v8::Value>)> 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<v8::Value> 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<v8::Value> 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<v8::Value> run) {
return run->BooleanValue();
});
}
void RunAtThreads(std::function<bool(int)> tester) {
std::vector<std::future<bool>> 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<v8::Value> 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<v8::Value> 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<v8::Value> 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<v8::Value> 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<v8::Value> run) {
auto argc = run->Int32Value();
return argc > 0;
});
REQUIRE(result);
oss.str("");
oss << "process.argv[0];";
result = RunScript(oss.str(), [](v8::Local<v8::Value> 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<v8::Value> run) {
v8::String::Utf8Value value(run);
return dll::ThisLineLocation() == *value;
});
REQUIRE(result);
result = RunScriptFile("processtest.js", [](v8::Local<v8::Value> run) {
return run->BooleanValue();
});
REQUIRE(result);
}
TEST_CASE("assert", "[module-loader]") {
auto result = RunScriptFile("asserttest.js", [](v8::Local<v8::Value> run) {
return run->BooleanValue();
});
REQUIRE(result);
}
TEST_CASE("file system", "[module-loader]") {
auto result = RunScriptFile("fstest.js", [](v8::Local<v8::Value> run) {
return run->BooleanValue();
});
REQUIRE(result);
}
TEST_CASE("global", "[module-loader]") {
auto result = RunScriptFile("globaltest.js", [](v8::Local<v8::Value> run) {
return run->BooleanValue();
});
REQUIRE(result);
}
TEST_CASE("path", "[module-loader]") {
auto result = RunScriptFile("pathtest.js", [](v8::Local<v8::Value> run) {
return run->BooleanValue();
});
REQUIRE(result);
}
TEST_CASE("os", "[module-loader]") {
auto result = RunScriptFile("ostest.js", [](v8::Local<v8::Value> run) {
return run->BooleanValue();
});
REQUIRE(result);
}
TEST_CASE("util", "[module-loader]") {
auto result = RunScriptFile("utiltest.js", [](v8::Local<v8::Value> run) {
return run->BooleanValue();
});
REQUIRE(result);
}
TEST_CASE("tty", "[module-loader]") {
auto result = RunScriptFile("ttytest.js", [](v8::Local<v8::Value> run) {
return run->BooleanValue();
});
REQUIRE(result);
}
TEST_CASE("cycling import", "[module-loader]") {
auto result = RunScriptFile("cycle-main.js", [](v8::Local<v8::Value> run) {
return run->BooleanValue();
});
REQUIRE(result);
}
TEST_CASE("resolve modules", "[module-loader]") {
auto result = RunScriptFile("module-resolution-test.js", [](v8::Local<v8::Value> 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<v8::Value> 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<void*>(_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<std::condition_variable,
std::function<void(std::condition_variable*)>> 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<std::mutex> 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<AsyncTestTask>(zone.get(), std::string()));
auto task = std::make_shared<AsyncTestTask>(zone.get(), "asynctest1.js");
scheduler->Schedule(task);
REQUIRE(task->ok());
task = std::make_shared<AsyncTestTask>(zone.get(), "asynctest2.js");
scheduler->Schedule(task);
REQUIRE(task->ok());
}

Просмотреть файл

@ -1 +0,0 @@
require('./tests/sub/module-resolution-test-root.js')();

Просмотреть файл

@ -1,207 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(EnvironmentConfig)" />
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.Default.props" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{718EC282-8C1B-44FB-BD98-97F2E09E0389}</ProjectGuid>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup>
<TestDir>$(OutDir)module-tests</TestDir>
</PropertyGroup>
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.props" />
<ItemDefinitionGroup>
<Link>
<AdditionalDependencies>Winmm.lib;Dbghelp.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>$(NapaVanillaRoot)\src\$(IntermediateOutputPath)\napa.lib;%(AdditionalDependencies)</AdditionalDependencies>
<!-- This is for testing only since V8 can export platform APIs at the latest version. -->
<AdditionalDependencies>$(Pkgnapa_nodelib_vc140)\lib\$(BuildType)\$(BuildTarget)\v8_libbase.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>$(Pkgnapa_nodelib_vc140)\lib\$(BuildType)\$(BuildTarget)\v8_libplatform.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ClCompile>
<DisableSpecificWarnings>4100;4251;4996</DisableSpecificWarnings>
<PreprocessorDefinitions>NAPA_EXPORTS;NAPA_BINDING_EXPORTS;BUILDING_NAPA_EXTENSION;BUILDING_V8_SHARED;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
<ClCompile Include="module-loader-tests.cpp" />
</ItemGroup>
<!-- To avoid exporting module-loader APIs -->
<ItemGroup>
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\binary-module-loader.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\core-module-loader.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\javascript-module-loader.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\json-module-loader.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\module-cache.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\module-loader.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\module-loader-helpers.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\module\loader\module-resolver.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\module\module.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\platform\win\platform.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\providers\providers.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\v8\v8-common.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\async-complete-task.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\async-runner.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\call-context.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\call-task.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\eval-task.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\napa-zone.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\node-zone.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\simple-thread-pool.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\terminable-task.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\timeout-service.cpp" />
<ClCompile Include="$(NapaVanillaRoot)\src\zone\worker.cpp" />
</ItemGroup>
<Import Project="$(NapaVanillaRoot)\src\module\core-modules\napa\napa-core-modules.proj" />
<Import Project="$(NapaVanillaRoot)\src\module\core-modules\node\node-core-modules.proj" />
<ItemGroup>
<ProjectReference Include="$(NapaVanillaRoot)\src\napa.vcxproj" />
<ProjectReference Include="$(NapaVanillaRoot)\test\module\async\async.vcxproj" />
<ProjectReference Include="$(NapaVanillaRoot)\test\module\sample\sample.vcxproj" />
</ItemGroup>
<!-- Test artifacts binplace -->
<ItemGroup>
<Robocopy Include="$(OutputPath)\$(TargetFileName)">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="$(NapaVanillaRoot)\lib\$(IntermediateOutputPath)">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\lib</DestinationFolder>
<FileMatch>*.j*</FileMatch>
<IsRecursive>true</IsRecursive>
</Robocopy>
<Robocopy Include="$(NapaVanillaRoot)\src\$(IntermediateOutputPath)\napa.dll">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="$(NapaVanillaRoot)\test\module\async\$(IntermediateOutputPath)\async.napa">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="$(NapaVanillaRoot)\test\module\sample\$(IntermediateOutputPath)\sample.napa">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="asserttest.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="asynctest1.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="asynctest2.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="core-module-tests.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="core-modules.json">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\lib\core</DestinationFolder>
</Robocopy>
<Robocopy Include="cycle-a.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="cycle-b.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="cycle-main.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="jsmodule.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="jsontest.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="fstest.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="fstest.json">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="globaltest.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="globaltest-module.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="module-resolution-test.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="ostest.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="pathtest.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="processtest.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="sample-test.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="ttytest.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="utiltest.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin</DestinationFolder>
</Robocopy>
<Robocopy Include="toproxy.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin\test</DestinationFolder>
</Robocopy>
<Robocopy Include="toupper.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin\test</DestinationFolder>
</Robocopy>
<Robocopy Include="lib\tconsole.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\lib\core</DestinationFolder>
</Robocopy>
<Robocopy Include="lib\tfs.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\lib\core</DestinationFolder>
</Robocopy>
<Robocopy Include="tests\node_modules\file2.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin\tests\node_modules</DestinationFolder>
</Robocopy>
<Robocopy Include="tests\sub\module-resolution-test-root.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin\tests\sub</DestinationFolder>
</Robocopy>
<Robocopy Include="tests\sub\fstestsub.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin\tests\sub</DestinationFolder>
</Robocopy>
<Robocopy Include="tests\sub\fstestsub.json">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin\tests\sub</DestinationFolder>
</Robocopy>
<Robocopy Include="tests\sub\sub1\file1.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin\tests\sub\sub1</DestinationFolder>
</Robocopy>
<Robocopy Include="tests\sub\sub1\file2.js">
<DestinationFolder>$(IntermediateOutputPath)\module-tests\bin\tests\sub\sub1</DestinationFolder>
</Robocopy>
</ItemGroup>
<!-- Use napa catch adapter -->
<Import Project="$(NapaVanillaRoot)\tools\catch-adapter\napa-catch.targets" />
<Import Project="$(Pkgboost)\build\native\boost.targets" />
<Import Project="$(Pkgboost_chrono_vc140)\build\native\boost_chrono-vc140.targets" />
<Import Project="$(Pkgboost_date_time_vc140)\build\native\boost_date_time-vc140.targets" />
<Import Project="$(Pkgboost_system_vc140)\build\native\boost_system-vc140.targets" />
<Import Project="$(Pkgboost_thread_vc140)\build\native\boost_thread-vc140.targets" />
<Import Project="$(Pkgboost_filesystem_vc140)\build\native\boost_filesystem-vc140.targets" />
<Import Project="$(Pkgnapa_nodelib_vc140)\exports_v8_includes.props" />
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.targets" />
</Project>

Просмотреть файл

@ -1,6 +0,0 @@
var assert = require('assert');
var os = require('os');
assert(os.type == "Windows_NT" || os.type == "Darwin" || os.type == "Linux");
true;

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;
}

1
cpp-test/module/module-loader/tests/node_modules/file2.js сгенерированный поставляемый
Просмотреть файл

@ -1 +0,0 @@
module.exports = {}

Просмотреть файл

@ -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();

Просмотреть файл

@ -1 +0,0 @@
{ "subQuery" : "sub-query", "subDocument" : "sub-document" }

Просмотреть файл

@ -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"));

Просмотреть файл

@ -1 +0,0 @@
module.exports = {}

Просмотреть файл

@ -1 +0,0 @@
module.exports = {}

Просмотреть файл

@ -1,6 +0,0 @@
var exports = module.exports = {};
exports.run = function(data) {
var toupper = require('./toupper');
return toupper.toupper(data);
};

Просмотреть файл

@ -1,5 +0,0 @@
var exports = module.exports = {};
exports.toupper = function(data) {
return data.toUpperCase();
};

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;

Просмотреть файл

@ -1,214 +0,0 @@
#include <napa-module.h>
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<v8::Value>& args) {
auto isolate = v8::Isolate::GetCurrent();
v8::HandleScope scope(isolate);
const int argc = 1;
v8::Local<v8::Value> 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<v8::Object> NewInstance(uint32_t score) {
auto isolate = v8::Isolate::GetCurrent();
v8::EscapableHandleScope scope(isolate);
const int argc = 1;
v8::Local<v8::Value> 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<v8::Value>& 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<v8::String>,
const v8::PropertyCallbackInfo<v8::Value>& args) {
auto isolate = v8::Isolate::GetCurrent();
v8::HandleScope scope(isolate);
auto sampleNode = NAPA_OBJECTWRAP::Unwrap<SampleNode>(args.Holder());
args.GetReturnValue().Set(v8::Number::New(isolate, sampleNode->_score));
}
static void SetScoreCallback(v8::Local<v8::String>,
v8::Local<v8::Value> value,
const v8::PropertyCallbackInfo<void>& 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<SampleNode>(args.Holder());
sampleNode->_score = value->Uint32Value();
args.GetReturnValue().SetUndefined();
}
static void GetValueCallback(const v8::FunctionCallbackInfo<v8::Value>& 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<v8::Value>& 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<v8::Value>& 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<v8::Value>& 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<v8::Value>& 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<v8::Value>& args) {
SampleNode::NewInstance(args);
}
void CreateSampleContainer(const v8::FunctionCallbackInfo<v8::Value>& args) {
SampleContainer::NewInstance(args);
}
void Print(const v8::FunctionCallbackInfo<v8::Value>& 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<v8::Object> 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);

Просмотреть файл

@ -1,43 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(EnvironmentConfig)" />
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.Default.props" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<AddonName>sample</AddonName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<AddonName>sample</AddonName>
</PropertyGroup>
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.props" />
<ItemDefinitionGroup>
<Link>
<AdditionalDependencies>$(NapaVanillaRoot)\src\$(IntermediateOutputPath)\napa.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ClCompile>
<PreprocessorDefinitions>BUILDING_NAPA_EXTENSION;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(NapaVanillaRoot)\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)\sample.cpp" />
</ItemGroup>
<Target Name="ChangeExtention" AfterTargets="Build">
<Move SourceFiles="$(OutputPath)\$(TargetFileName)" DestinationFiles="$(OutputPath)\$(AddonName).napa" />
</Target>
<Import Project="$(Pkgnapa_nodelib_vc140)\exports_v8_includes.props" />
<Import Project="$(ExtendedTargetsPath)\Microsoft.Cpp.targets" />
</Project>

Просмотреть файл

@ -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"
}

Просмотреть файл

@ -6,7 +6,6 @@
#include <memory>
namespace napa {
namespace module {
@ -14,8 +13,6 @@ namespace module {
class MetricWrap : public NAPA_OBJECTWRAP {
public:
/// <summary> Initializes the wrap. </summary>
static void Init();

Просмотреть файл

@ -6,13 +6,18 @@
using namespace napa;
using namespace napa::module;
void TypeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
auto isolate = v8::Isolate::GetCurrent();
v8::HandleScope scope(isolate);
args.GetReturnValue().Set(v8_helpers::MakeV8String(isolate, platform::GetOSType()));
}
void os::Init(v8::Local<v8::Object> 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);
}

440
test/module-test.ts Normal file
Просмотреть файл

@ -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);
});
});
});
});

7
test/module/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,7 @@
test-dir
test-file
!node_modules
# unignore js files used for module testing
!**/*.js

Просмотреть файл

@ -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
)

Просмотреть файл

@ -0,0 +1,28 @@
#include <napa-module.h>
#include "simple-object-wrap.h"
using namespace napa;
using namespace napa::test;
using namespace napa::module;
void GetModuleName(const v8::FunctionCallbackInfo<v8::Value>& 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<v8::Value>& args) {
SimpleObjectWrap::NewInstance(args);
}
void Init(v8::Local<v8::Object> exports) {
SimpleObjectWrap::Init();
NAPA_SET_METHOD(exports, "getModuleName", GetModuleName);
NAPA_SET_METHOD(exports, "createSimpleObjectWrap", CreateSimpleObjectWrap);
}
NAPA_MODULE(addon, Init);

Просмотреть файл

@ -0,0 +1,113 @@
#include "simple-object-wrap.h"
#include <napa.h>
#include <napa-assert.h>
#include <napa-async.h>
#include <napa/v8-helpers.h>
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<SimpleObjectWrap>);
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<v8::Value>& 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<v8::Value>& args) {
auto isolate = v8::Isolate::GetCurrent();
auto wrap = ObjectWrap::Unwrap<SimpleObjectWrap>(args.Holder());
args.GetReturnValue().Set(wrap->value);
}
void SimpleObjectWrap::SetValue(const v8::FunctionCallbackInfo<v8::Value>& args) {
auto isolate = v8::Isolate::GetCurrent();
CHECK_ARG(isolate, args[0]->IsUint32(), "first argument to setValue must be a uint32");
auto wrap = ObjectWrap::Unwrap<SimpleObjectWrap>(args.Holder());
wrap->value = args[0]->Uint32Value();
}
void SimpleObjectWrap::DoIncrementWork(const v8::FunctionCallbackInfo<v8::Value>& 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<SimpleObjectWrap>(args.Holder());
napa::zone::DoAsyncWork(
v8::Local<v8::Function>::Cast(args[0]),
[wrap](auto complete) {
// This runs at the same thread.
auto newValue = ++wrap->value;
complete(reinterpret_cast<void*>(static_cast<uintptr_t>(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<v8::Value> argv[] = {
v8::Integer::NewFromUnsigned(isolate, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(result)))
};
jsCallback->Call(isolate->GetCurrentContext()->Global(), argc, argv);
}
);
}
void SimpleObjectWrap::PostIncrementWork(const v8::FunctionCallbackInfo<v8::Value>& 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<SimpleObjectWrap>(args.Holder());
napa::zone::PostAsyncWork(
v8::Local<v8::Function>::Cast(args[0]),
[wrap]() {
// This runs at the separate thread.
auto newValue = ++wrap->value;
return reinterpret_cast<void*>(static_cast<uintptr_t>(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<v8::Value> argv[] = {
v8::Integer::NewFromUnsigned(isolate, static_cast<uint32_t>(reinterpret_cast<uintptr_t>(result)))
};
jsCallback->Call(isolate->GetCurrentContext()->Global(), argc, argv);
}
);
}

Просмотреть файл

@ -0,0 +1,42 @@
#pragma once
#include <napa-module.h>
#include <napa/module/common.h>
#include <atomic>
namespace napa {
namespace test {
/// <summary> A simple object wrap for testing. </summary>
class SimpleObjectWrap : public NAPA_OBJECTWRAP {
public:
/// <summary> Exported class name. </summary>
static constexpr const char* exportName = "SimpleObjectWrap";
/// <summary> Initializes the wrap. </summary>
static void Init();
/// <summary> Create a new wrap instance. </summary>
static void NewInstance(const v8::FunctionCallbackInfo<v8::Value>& args);
std::atomic<uint32_t> value = 0;
private:
/// <summary> Declare persistent constructor to create Zone Javascript wrapper instance. </summary>
NAPA_DECLARE_PERSISTENT_CONSTRUCTOR;
// SimpleObjectWrap methods
static void GetValue(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetValue(const v8::FunctionCallbackInfo<v8::Value>& args);
static void DoIncrementWork(const v8::FunctionCallbackInfo<v8::Value>& args);
static void PostIncrementWork(const v8::FunctionCallbackInfo<v8::Value>& args);
/// <summary> Friend default constructor callback. </summary>
template <typename WrapType>
friend void napa::module::DefaultConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>&);
};
}
}

Просмотреть файл

Просмотреть файл

1
test/module/jsmodule.js Normal file
Просмотреть файл

@ -0,0 +1 @@
exports.wasLoaded = true;

0
test/module/node_modules/file.js сгенерированный поставляемый Normal file
Просмотреть файл

Просмотреть файл

@ -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;

Просмотреть файл

4
test/module/test.json Normal file
Просмотреть файл

@ -0,0 +1,4 @@
{
"prop1": "val1",
"prop2": "val2"
}