• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef TEST_CCTEST_NODE_TEST_FIXTURE_H_
2 #define TEST_CCTEST_NODE_TEST_FIXTURE_H_
3 
4 #include <cstdlib>
5 #include <memory>
6 #include "gtest/gtest.h"
7 #include "node.h"
8 #include "node_platform.h"
9 #include "node_internals.h"
10 #include "env-inl.h"
11 #include "util-inl.h"
12 #include "v8.h"
13 #include "libplatform/libplatform.h"
14 
15 struct Argv {
16  public:
ArgvArgv17   Argv() : Argv({"node", "-p", "process.version"}) {}
18 
ArgvArgv19   Argv(const std::initializer_list<const char*> &args) {
20     nr_args_ = args.size();
21     int total_len = 0;
22     for (auto it = args.begin(); it != args.end(); ++it) {
23       total_len += strlen(*it) + 1;
24     }
25     argv_ = static_cast<char**>(malloc(nr_args_ * sizeof(char*)));
26     argv_[0] = static_cast<char*>(malloc(total_len));
27     int i = 0;
28     int offset = 0;
29     for (auto it = args.begin(); it != args.end(); ++it, ++i) {
30       int len = strlen(*it) + 1;
31       snprintf(argv_[0] + offset, len, "%s", *it);
32       // Skip argv_[0] as it points the correct location already
33       if (i > 0) {
34         argv_[i] = argv_[0] + offset;
35       }
36       offset += len;
37     }
38   }
39 
~ArgvArgv40   ~Argv() {
41     free(argv_[0]);
42     free(argv_);
43   }
44 
nr_argsArgv45   int nr_args() const {
46     return nr_args_;
47   }
48 
49   char** operator*() const {
50     return argv_;
51   }
52 
53  private:
54   char** argv_;
55   int nr_args_;
56 };
57 
58 using ArrayBufferUniquePtr = std::unique_ptr<node::ArrayBufferAllocator,
59       decltype(&node::FreeArrayBufferAllocator)>;
60 using TracingAgentUniquePtr = std::unique_ptr<node::tracing::Agent>;
61 using NodePlatformUniquePtr = std::unique_ptr<node::NodePlatform>;
62 
63 class NodeTestFixture : public ::testing::Test {
64  protected:
65   static ArrayBufferUniquePtr allocator;
66   static TracingAgentUniquePtr tracing_agent;
67   static NodePlatformUniquePtr platform;
68   static uv_loop_t current_loop;
69   static bool node_initialized;
70   v8::Isolate* isolate_;
71 
SetUpTestCase()72   static void SetUpTestCase() {
73     if (!node_initialized) {
74       uv_os_unsetenv("NODE_OPTIONS");
75       node_initialized = true;
76       std::vector<std::string> argv { "cctest" };
77       std::vector<std::string> exec_argv;
78       std::vector<std::string> errors;
79 
80       int exitcode = node::InitializeNodeWithArgs(&argv, &exec_argv, &errors);
81       CHECK_EQ(exitcode, 0);
82       CHECK(errors.empty());
83     }
84 
85     tracing_agent = std::make_unique<node::tracing::Agent>();
86     node::tracing::TraceEventHelper::SetAgent(tracing_agent.get());
87     node::tracing::TracingController* tracing_controller =
88             tracing_agent->GetTracingController();
89     CHECK_EQ(0, uv_loop_init(&current_loop));
90     static constexpr int kV8ThreadPoolSize = 4;
91     platform.reset(
92         new node::NodePlatform(kV8ThreadPoolSize, tracing_controller));
93     v8::V8::InitializePlatform(platform.get());
94     v8::V8::Initialize();
95   }
96 
TearDownTestCase()97   static void TearDownTestCase() {
98     platform->Shutdown();
99     while (uv_loop_alive(&current_loop)) {
100       uv_run(&current_loop, UV_RUN_ONCE);
101     }
102     v8::V8::ShutdownPlatform();
103     CHECK_EQ(0, uv_loop_close(&current_loop));
104   }
105 
SetUp()106   void SetUp() override {
107     allocator = ArrayBufferUniquePtr(node::CreateArrayBufferAllocator(),
108                                      &node::FreeArrayBufferAllocator);
109     isolate_ = NewIsolate(allocator.get(), &current_loop, platform.get());
110     CHECK_NE(isolate_, nullptr);
111     isolate_->Enter();
112   }
113 
TearDown()114   void TearDown() override {
115     platform->DrainTasks(isolate_);
116     isolate_->Exit();
117     platform->UnregisterIsolate(isolate_);
118     isolate_->Dispose();
119     isolate_ = nullptr;
120   }
121 };
122 
123 
124 class EnvironmentTestFixture : public NodeTestFixture {
125  public:
126   class Env {
127    public:
128     Env(const v8::HandleScope& handle_scope,
129         const Argv& argv,
130         node::EnvironmentFlags::Flags flags =
131             node::EnvironmentFlags::kDefaultFlags) {
132       auto isolate = handle_scope.GetIsolate();
133       context_ = node::NewContext(isolate);
134       CHECK(!context_.IsEmpty());
135       context_->Enter();
136 
137       isolate_data_ = node::CreateIsolateData(isolate,
138                                               &NodeTestFixture::current_loop,
139                                               platform.get());
140       CHECK_NE(nullptr, isolate_data_);
141       std::vector<std::string> args(*argv, *argv + 1);
142       std::vector<std::string> exec_args(*argv, *argv + 1);
143       environment_ = node::CreateEnvironment(isolate_data_,
144                                              context_,
145                                              args,
146                                              exec_args,
147                                              flags);
148       CHECK_NE(nullptr, environment_);
149     }
150 
~Env()151     ~Env() {
152       node::FreeEnvironment(environment_);
153       node::FreeIsolateData(isolate_data_);
154       context_->Exit();
155     }
156 
157     node::Environment* operator*() const {
158       return environment_;
159     }
160 
context()161     v8::Local<v8::Context> context()  const {
162       return context_;
163     }
164 
165     Env(const Env&) = delete;
166     Env& operator=(const Env&) = delete;
167 
168    private:
169     v8::Local<v8::Context> context_;
170     node::IsolateData* isolate_data_;
171     node::Environment* environment_;
172   };
173 };
174 
175 #endif  // TEST_CCTEST_NODE_TEST_FIXTURE_H_
176