diff options
author | Anna Henningsen <anna@addaleax.net> | 2020-02-27 18:54:13 -0800 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2020-03-21 10:58:23 +0100 |
commit | 43d32b073f42a1544ebd907f4050d03c9a65f26d (patch) | |
tree | ff2be93010632ba34f6b3e875acd48238f8bb377 /test/embedding | |
parent | a8cf886de723437cecbf220ad4e32eef301fde71 (diff) | |
download | node-new-43d32b073f42a1544ebd907f4050d03c9a65f26d.tar.gz |
src,test: add full-featured embedder API test
PR-URL: https://github.com/nodejs/node/pull/30467
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
Diffstat (limited to 'test/embedding')
-rw-r--r-- | test/embedding/embedtest.cc | 135 | ||||
-rw-r--r-- | test/embedding/test.js | 19 |
2 files changed, 154 insertions, 0 deletions
diff --git a/test/embedding/embedtest.cc b/test/embedding/embedtest.cc new file mode 100644 index 0000000000..14e2dfb802 --- /dev/null +++ b/test/embedding/embedtest.cc @@ -0,0 +1,135 @@ +#include "node.h" +#include "uv.h" +#include <assert.h> + +// Note: This file is being referred to from doc/api/embedding.md, and excerpts +// from it are included in the documentation. Try to keep these in sync. + +using node::ArrayBufferAllocator; +using node::Environment; +using node::IsolateData; +using node::MultiIsolatePlatform; +using v8::Context; +using v8::HandleScope; +using v8::Isolate; +using v8::Local; +using v8::Locker; +using v8::MaybeLocal; +using v8::SealHandleScope; +using v8::Value; +using v8::V8; + +static int RunNodeInstance(MultiIsolatePlatform* platform, + const std::vector<std::string>& args, + const std::vector<std::string>& exec_args); + +int main(int argc, char** argv) { + std::vector<std::string> args(argv, argv + argc); + std::vector<std::string> exec_args; + std::vector<std::string> errors; + int exit_code = node::InitializeNodeWithArgs(&args, &exec_args, &errors); + for (const std::string& error : errors) + fprintf(stderr, "%s: %s\n", args[0].c_str(), error.c_str()); + if (exit_code != 0) { + return exit_code; + } + + std::unique_ptr<MultiIsolatePlatform> platform = + MultiIsolatePlatform::Create(4); + V8::InitializePlatform(platform.get()); + V8::Initialize(); + + int ret = RunNodeInstance(platform.get(), args, exec_args); + + V8::Dispose(); + V8::ShutdownPlatform(); + return ret; +} + +int RunNodeInstance(MultiIsolatePlatform* platform, + const std::vector<std::string>& args, + const std::vector<std::string>& exec_args) { + int exit_code = 0; + uv_loop_t loop; + int ret = uv_loop_init(&loop); + if (ret != 0) { + fprintf(stderr, "%s: Failed to initialize loop: %s\n", + args[0].c_str(), + uv_err_name(ret)); + return 1; + } + + std::shared_ptr<ArrayBufferAllocator> allocator = + ArrayBufferAllocator::Create(); + + Isolate* isolate = NewIsolate(allocator, &loop, platform); + if (isolate == nullptr) { + fprintf(stderr, "%s: Failed to initialize V8 Isolate\n", args[0].c_str()); + return 1; + } + + { + Locker locker(isolate); + Isolate::Scope isolate_scope(isolate); + + std::unique_ptr<IsolateData, decltype(&node::FreeIsolateData)> isolate_data( + node::CreateIsolateData(isolate, &loop, platform, allocator.get()), + node::FreeIsolateData); + + HandleScope handle_scope(isolate); + Local<Context> context = node::NewContext(isolate); + if (context.IsEmpty()) { + fprintf(stderr, "%s: Failed to initialize V8 Context\n", args[0].c_str()); + return 1; + } + + Context::Scope context_scope(context); + std::unique_ptr<Environment, decltype(&node::FreeEnvironment)> env( + node::CreateEnvironment(isolate_data.get(), context, args, exec_args), + node::FreeEnvironment); + + MaybeLocal<Value> loadenv_ret = node::LoadEnvironment( + env.get(), + "const publicRequire =" + " require('module').createRequire(process.cwd() + '/');" + "globalThis.require = publicRequire;" + "require('vm').runInThisContext(process.argv[1]);"); + + if (loadenv_ret.IsEmpty()) // There has been a JS exception. + return 1; + + { + SealHandleScope seal(isolate); + bool more; + do { + uv_run(&loop, UV_RUN_DEFAULT); + + platform->DrainTasks(isolate); + more = uv_loop_alive(&loop); + if (more) continue; + + node::EmitBeforeExit(env.get()); + more = uv_loop_alive(&loop); + } while (more == true); + } + + exit_code = node::EmitExit(env.get()); + + node::Stop(env.get()); + } + + bool platform_finished = false; + platform->AddIsolateFinishedCallback(isolate, [](void* data) { + *static_cast<bool*>(data) = true; + }, &platform_finished); + platform->UnregisterIsolate(isolate); + isolate->Dispose(); + + // Wait until the platform has cleaned up all relevant resources. + while (!platform_finished) + uv_run(&loop, UV_RUN_ONCE); + int err = uv_loop_close(&loop); + assert(err == 0); + + return exit_code; +} diff --git a/test/embedding/test.js b/test/embedding/test.js new file mode 100644 index 0000000000..a802de1849 --- /dev/null +++ b/test/embedding/test.js @@ -0,0 +1,19 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const child_process = require('child_process'); + +common.allowGlobals(global.require); + +assert.strictEqual( + child_process.spawnSync(process.execPath, ['console.log(42)']) + .stdout.toString().trim(), + '42'); + +assert.strictEqual( + child_process.spawnSync(process.execPath, ['throw new Error()']).status, + 1); + +assert.strictEqual( + child_process.spawnSync(process.execPath, ['process.exitCode = 8']).status, + 8); |