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(¤t_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(¤t_loop)) { 82 uv_run(¤t_loop, UV_RUN_ONCE); 83 } 84 v8::V8::ShutdownPlatform(); 85 CHECK_EQ(0, uv_loop_close(¤t_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