summaryrefslogtreecommitdiff
path: root/test/embedding
diff options
context:
space:
mode:
authorAnna Henningsen <anna@addaleax.net>2020-02-27 18:54:13 -0800
committerAnna Henningsen <anna@addaleax.net>2020-03-21 10:58:23 +0100
commit43d32b073f42a1544ebd907f4050d03c9a65f26d (patch)
treeff2be93010632ba34f6b3e875acd48238f8bb377 /test/embedding
parenta8cf886de723437cecbf220ad4e32eef301fde71 (diff)
downloadnode-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.cc135
-rw-r--r--test/embedding/test.js19
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);