1 #ifndef TEST_CCTEST_NODE_TEST_FIXTURE_H_
2 #define TEST_CCTEST_NODE_TEST_FIXTURE_H_
3 
4 #include <stdlib.h>
5 #include "gtest/gtest.h"
6 #include "node.h"
7 #include "node_platform.h"
8 #include "node_internals.h"
9 #include "env.h"
10 #include "v8.h"
11 #include "libplatform/libplatform.h"
12 
13 struct Argv {
14  public:
ArgvArgv15   Argv() : Argv({"node", "-p", "process.version"}) {}
16 
ArgvArgv17   Argv(const std::initializer_list<const char*> &args) {
18     nr_args_ = args.size();
19     int total_len = 0;
20     for (auto it = args.begin(); it != args.end(); ++it) {
21       total_len += strlen(*it) + 1;
22     }
23     argv_ = static_cast<char**>(malloc(nr_args_ * sizeof(char*)));
24     argv_[0] = static_cast<char*>(malloc(total_len));
25     int i = 0;
26     int offset = 0;
27     for (auto it = args.begin(); it != args.end(); ++it, ++i) {
28       int len = strlen(*it) + 1;
29       snprintf(argv_[0] + offset, len, "%s", *it);
30       // Skip argv_[0] as it points the correct location already
31       if (i > 0) {
32         argv_[i] = argv_[0] + offset;
33       }
34       offset += len;
35     }
36   }
37 
~ArgvArgv38   ~Argv() {
39     free(argv_[0]);
40     free(argv_);
41   }
42 
nr_argsArgv43   int nr_args() const {
44     return nr_args_;
45   }
46 
47   char** operator*() const {
48     return argv_;
49   }
50 
51  private:
52   char** argv_;
53   int nr_args_;
54 };
55 
56 using ArrayBufferUniquePtr = std::unique_ptr<node::ArrayBufferAllocator,
57       decltype(&node::FreeArrayBufferAllocator)>;
58 using TracingAgentUniquePtr = std::unique_ptr<node::tracing::Agent>;
59 using NodePlatformUniquePtr = std::unique_ptr<node::NodePlatform>;
60 
61 class NodeTestFixture : public ::testing::Test {
62  protected:
63   static ArrayBufferUniquePtr allocator;
64   static TracingAgentUniquePtr tracing_agent;
65   static NodePlatformUniquePtr platform;
66   static uv_loop_t current_loop;
67   v8::Isolate* isolate_;
68 
SetUpTestCase()69   static void SetUpTestCase() {
70     tracing_agent.reset(new node::tracing::Agent());
71     node::tracing::TraceEventHelper::SetAgent(tracing_agent.get());
72     platform.reset(
73         new node::NodePlatform(4, tracing_agent->GetTracingController()));
74     CHECK_EQ(0, uv_loop_init(&current_loop));
75     v8::V8::InitializePlatform(platform.get());
76     v8::V8::Initialize();
77   }
78 
TearDownTestCase()79   static void TearDownTestCase() {
80     platform->Shutdown();
81     while (uv_loop_alive(&current_loop)) {
82       uv_run(&current_loop, UV_RUN_ONCE);
83     }
84     v8::V8::ShutdownPlatform();
85     CHECK_EQ(0, uv_loop_close(&current_loop));
86   }
87 
SetUp()88   virtual void SetUp() {
89     allocator = ArrayBufferUniquePtr(node::CreateArrayBufferAllocator(),
90                                      &node::FreeArrayBufferAllocator);
91     isolate_ = NewIsolate(allocator.get());
92     CHECK_NE(isolate_, nullptr);
93   }
94 
TearDown()95   virtual void TearDown() {
96     isolate_->Dispose();
97     isolate_ = nullptr;
98   }
99 };
100 
101 
102 class EnvironmentTestFixture : public NodeTestFixture {
103  public:
104   class Env {
105    public:
Env(const v8::HandleScope & handle_scope,const Argv & argv)106     Env(const v8::HandleScope& handle_scope, const Argv& argv) {
107       auto isolate = handle_scope.GetIsolate();
108       context_ = node::NewContext(isolate);
109       CHECK(!context_.IsEmpty());
110       context_->Enter();
111 
112       isolate_data_ = node::CreateIsolateData(isolate,
113                                               &NodeTestFixture::current_loop,
114                                               platform.get());
115       CHECK_NE(nullptr, isolate_data_);
116       environment_ = node::CreateEnvironment(isolate_data_,
117                                              context_,
118                                              1, *argv,
119                                              argv.nr_args(), *argv);
120       CHECK_NE(nullptr, environment_);
121     }
122 
~Env()123     ~Env() {
124       node::FreeEnvironment(environment_);
125       node::FreeIsolateData(isolate_data_);
126       context_->Exit();
127     }
128 
129     node::Environment* operator*() const {
130       return environment_;
131     }
132 
context()133     v8::Local<v8::Context> context()  const {
134       return context_;
135     }
136 
137    private:
138     v8::Local<v8::Context> context_;
139     node::IsolateData* isolate_data_;
140     node::Environment* environment_;
141     DISALLOW_COPY_AND_ASSIGN(Env);
142   };
143 };
144 
145 #endif  // TEST_CCTEST_NODE_TEST_FIXTURE_H_
146