LCOV - code coverage report
Current view: top level - test/unittests - test-utils.h (source / functions) Hit Total Coverage
Test: app.info Lines: 74 76 97.4 %
Date: 2019-04-17 Functions: 68 76 89.5 %

          Line data    Source code
       1             : // Copyright 2014 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_UNITTESTS_TEST_UTILS_H_
       6             : #define V8_UNITTESTS_TEST_UTILS_H_
       7             : 
       8             : #include <vector>
       9             : 
      10             : #include "include/v8.h"
      11             : #include "src/api-inl.h"
      12             : #include "src/base/macros.h"
      13             : #include "src/base/utils/random-number-generator.h"
      14             : #include "src/handles.h"
      15             : #include "src/objects-inl.h"
      16             : #include "src/objects.h"
      17             : #include "src/zone/accounting-allocator.h"
      18             : #include "src/zone/zone.h"
      19             : #include "testing/gtest-support.h"
      20             : 
      21             : namespace v8 {
      22             : 
      23             : class ArrayBufferAllocator;
      24             : 
      25             : typedef std::map<std::string, int> CounterMap;
      26             : 
      27             : // RAII-like Isolate instance wrapper.
      28             : class IsolateWrapper final {
      29             :  public:
      30             :   // When enforce_pointer_compression is true the Isolate is created with
      31             :   // enabled pointer compression. When it's false then the Isolate is created
      32             :   // with the default pointer compression state for current build.
      33             :   explicit IsolateWrapper(CounterLookupCallback counter_lookup_callback,
      34             :                           bool enforce_pointer_compression = false);
      35             :   ~IsolateWrapper();
      36             : 
      37             :   v8::Isolate* isolate() const { return isolate_; }
      38             : 
      39             :  private:
      40             :   v8::ArrayBuffer::Allocator* array_buffer_allocator_;
      41             :   v8::Isolate* isolate_;
      42             : 
      43             :   DISALLOW_COPY_AND_ASSIGN(IsolateWrapper);
      44             : };
      45             : 
      46             : class SharedIsolateHolder final {
      47             :  public:
      48      801246 :   static v8::Isolate* isolate() { return isolate_wrapper_->isolate(); }
      49             : 
      50        1267 :   static void CreateIsolate() {
      51        1267 :     CHECK_NULL(isolate_wrapper_);
      52             :     isolate_wrapper_ =
      53       25878 :         new IsolateWrapper([](const char* name) -> int* { return nullptr; });
      54        1267 :   }
      55             : 
      56        1267 :   static void DeleteIsolate() {
      57        1267 :     CHECK_NOT_NULL(isolate_wrapper_);
      58        1267 :     delete isolate_wrapper_;
      59        1267 :     isolate_wrapper_ = nullptr;
      60        1267 :   }
      61             : 
      62             :  private:
      63             :   static v8::IsolateWrapper* isolate_wrapper_;
      64             : 
      65             :   DISALLOW_IMPLICIT_CONSTRUCTORS(SharedIsolateHolder);
      66             : };
      67             : 
      68             : class SharedIsolateAndCountersHolder final {
      69             :  public:
      70          87 :   static v8::Isolate* isolate() { return isolate_wrapper_->isolate(); }
      71             : 
      72           3 :   static void CreateIsolate() {
      73           3 :     CHECK_NULL(counter_map_);
      74           3 :     CHECK_NULL(isolate_wrapper_);
      75           6 :     counter_map_ = new CounterMap();
      76           3 :     isolate_wrapper_ = new IsolateWrapper(LookupCounter);
      77           3 :   }
      78             : 
      79           3 :   static void DeleteIsolate() {
      80           3 :     CHECK_NOT_NULL(counter_map_);
      81           3 :     CHECK_NOT_NULL(isolate_wrapper_);
      82           3 :     delete isolate_wrapper_;
      83           3 :     isolate_wrapper_ = nullptr;
      84           6 :     delete counter_map_;
      85           3 :     counter_map_ = nullptr;
      86           3 :   }
      87             : 
      88             :  private:
      89             :   static int* LookupCounter(const char* name);
      90             :   static CounterMap* counter_map_;
      91             :   static v8::IsolateWrapper* isolate_wrapper_;
      92             : 
      93             :   DISALLOW_IMPLICIT_CONSTRUCTORS(SharedIsolateAndCountersHolder);
      94             : };
      95             : 
      96             : //
      97             : // A set of mixins from which the test fixtures will be constructed.
      98             : //
      99             : template <typename TMixin>
     100           1 : class WithPrivateIsolateMixin : public TMixin {
     101             :  public:
     102             :   explicit WithPrivateIsolateMixin(bool enforce_pointer_compression = false)
     103          27 :       : isolate_wrapper_([](const char* name) -> int* { return nullptr; },
     104           1 :                          enforce_pointer_compression) {}
     105             : 
     106             :   v8::Isolate* v8_isolate() const { return isolate_wrapper_.isolate(); }
     107             : 
     108             :   static void SetUpTestCase() { TMixin::SetUpTestCase(); }
     109             :   static void TearDownTestCase() { TMixin::TearDownTestCase(); }
     110             : 
     111             :  private:
     112             :   v8::IsolateWrapper isolate_wrapper_;
     113             : 
     114             :   DISALLOW_COPY_AND_ASSIGN(WithPrivateIsolateMixin);
     115             : };
     116             : 
     117             : template <typename TMixin, typename TSharedIsolateHolder = SharedIsolateHolder>
     118        1270 : class WithSharedIsolateMixin : public TMixin {
     119             :  public:
     120        1270 :   WithSharedIsolateMixin() = default;
     121             : 
     122             :   v8::Isolate* v8_isolate() const { return TSharedIsolateHolder::isolate(); }
     123             : 
     124             :   static void SetUpTestCase() {
     125             :     TMixin::SetUpTestCase();
     126        1270 :     TSharedIsolateHolder::CreateIsolate();
     127             :   }
     128             : 
     129             :   static void TearDownTestCase() {
     130        1270 :     TSharedIsolateHolder::DeleteIsolate();
     131             :     TMixin::TearDownTestCase();
     132             :   }
     133             : 
     134             :  private:
     135             :   DISALLOW_COPY_AND_ASSIGN(WithSharedIsolateMixin);
     136             : };
     137             : 
     138             : template <typename TMixin>
     139           2 : class WithPointerCompressionIsolateMixin
     140             :     : public WithPrivateIsolateMixin<TMixin> {
     141             :  public:
     142           1 :   WithPointerCompressionIsolateMixin()
     143           1 :       : WithPrivateIsolateMixin<TMixin>(true) {}
     144             : 
     145             :  private:
     146             :   DISALLOW_COPY_AND_ASSIGN(WithPointerCompressionIsolateMixin);
     147             : };
     148             : 
     149             : template <typename TMixin>
     150        2542 : class WithIsolateScopeMixin : public TMixin {
     151             :  public:
     152        1271 :   WithIsolateScopeMixin()
     153        2542 :       : isolate_scope_(v8_isolate()), handle_scope_(v8_isolate()) {}
     154             : 
     155             :   v8::Isolate* isolate() const { return v8_isolate(); }
     156             :   v8::Isolate* v8_isolate() const { return TMixin::v8_isolate(); }
     157             : 
     158             :   v8::internal::Isolate* i_isolate() const {
     159             :     return reinterpret_cast<v8::internal::Isolate*>(v8_isolate());
     160             :   }
     161             : 
     162         162 :   static void SetUpTestCase() { TMixin::SetUpTestCase(); }
     163         162 :   static void TearDownTestCase() { TMixin::TearDownTestCase(); }
     164             : 
     165             :  private:
     166             :   v8::Isolate::Scope isolate_scope_;
     167             :   v8::HandleScope handle_scope_;
     168             : 
     169             :   DISALLOW_COPY_AND_ASSIGN(WithIsolateScopeMixin);
     170             : };
     171             : 
     172             : template <typename TMixin>
     173        1694 : class WithContextMixin : public TMixin {
     174             :  public:
     175         847 :   WithContextMixin()
     176        2541 :       : context_(Context::New(v8_isolate())), context_scope_(context_) {}
     177             : 
     178             :   v8::Isolate* v8_isolate() const { return TMixin::v8_isolate(); }
     179             : 
     180             :   const Local<Context>& context() const { return v8_context(); }
     181          18 :   const Local<Context>& v8_context() const { return context_; }
     182             : 
     183          66 :   Local<Value> RunJS(const char* source) {
     184          66 :     return RunJS(v8::String::NewFromUtf8(v8_isolate(), source,
     185             :                                          v8::NewStringType::kNormal)
     186          66 :                      .ToLocalChecked());
     187             :   }
     188             : 
     189           6 :   Local<Value> RunJS(v8::String::ExternalOneByteStringResource* source) {
     190           6 :     return RunJS(
     191           6 :         v8::String::NewExternalOneByte(v8_isolate(), source).ToLocalChecked());
     192             :   }
     193             : 
     194          16 :   v8::Local<v8::String> NewString(const char* string) {
     195             :     return v8::String::NewFromUtf8(v8_isolate(), string,
     196             :                                    v8::NewStringType::kNormal)
     197          32 :         .ToLocalChecked();
     198             :   }
     199             : 
     200          13 :   void SetGlobalProperty(const char* name, v8::Local<v8::Value> value) {
     201          52 :     CHECK(v8_context()
     202             :               ->Global()
     203             :               ->Set(v8_context(), NewString(name), value)
     204             :               .FromJust());
     205          13 :   }
     206             : 
     207          78 :   static void SetUpTestCase() { TMixin::SetUpTestCase(); }
     208          78 :   static void TearDownTestCase() { TMixin::TearDownTestCase(); }
     209             : 
     210             :  private:
     211          72 :   Local<Value> RunJS(Local<String> source) {
     212          72 :     auto context = v8_isolate()->GetCurrentContext();
     213             :     Local<Script> script =
     214          72 :         v8::Script::Compile(context, source).ToLocalChecked();
     215         144 :     return script->Run(context).ToLocalChecked();
     216             :   }
     217             : 
     218             :   v8::Local<v8::Context> context_;
     219             :   v8::Context::Scope context_scope_;
     220             : 
     221             :   DISALLOW_COPY_AND_ASSIGN(WithContextMixin);
     222             : };
     223             : 
     224             : // Use v8::internal::TestWithIsolate if you are testing internals,
     225             : // aka. directly work with Handles.
     226             : using TestWithIsolate =          //
     227             :     WithIsolateScopeMixin<       //
     228             :         WithSharedIsolateMixin<  //
     229             :             ::testing::Test>>;
     230             : 
     231             : // Use v8::internal::TestWithNativeContext if you are testing internals,
     232             : // aka. directly work with Handles.
     233             : using TestWithContext =              //
     234             :     WithContextMixin<                //
     235             :         WithIsolateScopeMixin<       //
     236             :             WithSharedIsolateMixin<  //
     237             :                 ::testing::Test>>>;
     238             : 
     239             : using TestWithIsolateAndPointerCompression =     //
     240             :     WithContextMixin<                            //
     241             :         WithIsolateScopeMixin<                   //
     242             :             WithPointerCompressionIsolateMixin<  //
     243             :                 ::testing::Test>>>;
     244             : 
     245             : namespace internal {
     246             : 
     247             : // Forward declarations.
     248             : class Factory;
     249             : 
     250             : template <typename TMixin>
     251        1955 : class WithInternalIsolateMixin : public TMixin {
     252             :  public:
     253        1141 :   WithInternalIsolateMixin() = default;
     254             : 
     255             :   Factory* factory() const { return isolate()->factory(); }
     256             :   Isolate* isolate() const { return TMixin::i_isolate(); }
     257             : 
     258             :   Handle<NativeContext> native_context() const {
     259          19 :     return isolate()->native_context();
     260             :   }
     261             : 
     262             :   template <typename T = Object>
     263             :   Handle<T> RunJS(const char* source) {
     264             :     return Handle<T>::cast(RunJSInternal(source));
     265             :   }
     266             : 
     267             :   Handle<Object> RunJSInternal(const char* source) {
     268          79 :     return Utils::OpenHandle(*TMixin::RunJS(source));
     269             :   }
     270             : 
     271             :   template <typename T = Object>
     272             :   Handle<T> RunJS(::v8::String::ExternalOneByteStringResource* source) {
     273             :     return Handle<T>::cast(RunJSInternal(source));
     274             :   }
     275             : 
     276             :   Handle<Object> RunJSInternal(
     277             :       ::v8::String::ExternalOneByteStringResource* source) {
     278          12 :     return Utils::OpenHandle(*TMixin::RunJS(source));
     279             :   }
     280             : 
     281             :   base::RandomNumberGenerator* random_number_generator() const {
     282         319 :     return isolate()->random_number_generator();
     283             :   }
     284             : 
     285         672 :   static void SetUpTestCase() { TMixin::SetUpTestCase(); }
     286         672 :   static void TearDownTestCase() { TMixin::TearDownTestCase(); }
     287             : 
     288             :  private:
     289             :   DISALLOW_COPY_AND_ASSIGN(WithInternalIsolateMixin);
     290             : };
     291             : 
     292             : template <typename TMixin>
     293        2763 : class WithZoneMixin : public TMixin {
     294             :  public:
     295        4768 :   WithZoneMixin() : zone_(&allocator_, ZONE_NAME) {}
     296             : 
     297      265276 :   Zone* zone() { return &zone_; }
     298             : 
     299        2466 :   static void SetUpTestCase() { TMixin::SetUpTestCase(); }
     300        2466 :   static void TearDownTestCase() { TMixin::TearDownTestCase(); }
     301             : 
     302             :  private:
     303             :   v8::internal::AccountingAllocator allocator_;
     304             :   Zone zone_;
     305             : 
     306             :   DISALLOW_COPY_AND_ASSIGN(WithZoneMixin);
     307             : };
     308             : 
     309             : using TestWithIsolate =              //
     310             :     WithInternalIsolateMixin<        //
     311             :         WithIsolateScopeMixin<       //
     312             :             WithSharedIsolateMixin<  //
     313             :                 ::testing::Test>>>;
     314             : 
     315             : using TestWithZone = WithZoneMixin<::testing::Test>;
     316             : 
     317             : using TestWithIsolateAndZone =       //
     318             :     WithInternalIsolateMixin<        //
     319             :         WithIsolateScopeMixin<       //
     320             :             WithSharedIsolateMixin<  //
     321             :                 WithZoneMixin<       //
     322             :                     ::testing::Test>>>>;
     323             : 
     324             : using TestWithNativeContext =            //
     325             :     WithInternalIsolateMixin<            //
     326             :         WithContextMixin<                //
     327             :             WithIsolateScopeMixin<       //
     328             :                 WithSharedIsolateMixin<  //
     329             :                     ::testing::Test>>>>;
     330             : 
     331             : using TestWithNativeContextAndCounters =  //
     332             :     WithInternalIsolateMixin<             //
     333             :         WithContextMixin<                 //
     334             :             WithIsolateScopeMixin<        //
     335             :                 WithSharedIsolateMixin<   //
     336             :                     ::testing::Test,      //
     337             :                     SharedIsolateAndCountersHolder>>>>;
     338             : 
     339             : using TestWithNativeContextAndZone =         //
     340             :     WithZoneMixin<                           //
     341             :         WithInternalIsolateMixin<            //
     342             :             WithContextMixin<                //
     343             :                 WithIsolateScopeMixin<       //
     344             :                     WithSharedIsolateMixin<  //
     345             :                         ::testing::Test>>>>>;
     346             : 
     347             : class SaveFlags {
     348             :  public:
     349             :   SaveFlags();
     350             :   ~SaveFlags();
     351             : 
     352             :  private:
     353             : #define FLAG_MODE_APPLY(ftype, ctype, nam, def, cmt) ctype SAVED_##nam;
     354             : #include "src/flag-definitions.h"  // NOLINT
     355             : #undef FLAG_MODE_APPLY
     356             : 
     357             :   DISALLOW_COPY_AND_ASSIGN(SaveFlags);
     358             : };
     359             : 
     360             : // For GTest.
     361             : inline void PrintTo(Object o, ::std::ostream* os) {
     362           0 :   *os << reinterpret_cast<void*>(o.ptr());
     363             : }
     364             : inline void PrintTo(Smi o, ::std::ostream* os) {
     365           0 :   *os << reinterpret_cast<void*>(o.ptr());
     366             : }
     367             : 
     368             : }  // namespace internal
     369             : }  // namespace v8
     370             : 
     371             : #endif  // V8_UNITTESTS_TEST_UTILS_H_

Generated by: LCOV version 1.10