1 // Copyright 2014 The Chromium 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 EXTENSIONS_RENDERER_MODULE_SYSTEM_TEST_H_
6 #define EXTENSIONS_RENDERER_MODULE_SYSTEM_TEST_H_
7 
8 #include <set>
9 
10 #include "base/macros.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/test/task_environment.h"
13 #include "extensions/renderer/module_system.h"
14 #include "extensions/renderer/script_context.h"
15 #include "extensions/renderer/script_context_set.h"
16 #include "extensions/renderer/test_extensions_renderer_client.h"
17 #include "gin/public/context_holder.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "v8/include/v8.h"
20 
21 namespace extensions {
22 class Extension;
23 class NativeExtensionBindingsSystem;
24 class StringSourceMap;
25 
26 class ModuleSystemTestEnvironment {
27  public:
28   class AssertNatives;
29 
30   ModuleSystemTestEnvironment(v8::Isolate* isolate,
31                               ScriptContextSet* context_set,
32                               scoped_refptr<const Extension> extension);
33   ~ModuleSystemTestEnvironment();
34 
35   // Register a named JS module in the module system.
36   void RegisterModule(const std::string& name, const std::string& code);
37 
38   // Register a named JS module with source retrieved from a ResourceBundle.
39   void RegisterModule(const std::string& name,
40                       int resource_id,
41                       bool gzipped = false);
42 
43   // Register a named JS module in the module system and tell the module system
44   // to use it to handle any requireNative() calls for native modules with that
45   // name.
46   void OverrideNativeHandler(const std::string& name, const std::string& code);
47 
48   // Registers |file_name| from chrome/test/data/extensions as a module name
49   // |module_name|.
50   void RegisterTestFile(const std::string& module_name,
51                         const std::string& file_name);
52 
53   // Create an empty object in the global scope with name |name|.
54   v8::Local<v8::Object> CreateGlobal(const std::string& name);
55 
56   void ShutdownGin();
57 
58   void ShutdownModuleSystem();
59 
module_system()60   ModuleSystem* module_system() { return context_->module_system(); }
61 
context()62   ScriptContext* context() { return context_; }
63 
isolate()64   v8::Isolate* isolate() { return isolate_; }
65 
source_map()66   StringSourceMap* source_map() { return source_map_.get(); }
67 
assert_natives()68   AssertNatives* assert_natives() { return assert_natives_; }
69 
70  private:
71   v8::Isolate* isolate_;
72   std::unique_ptr<gin::ContextHolder> context_holder_;
73   v8::HandleScope handle_scope_;
74 
75   scoped_refptr<const Extension> extension_;
76   ScriptContextSet* context_set_;
77   ScriptContext* context_;
78   AssertNatives* assert_natives_;
79   std::unique_ptr<StringSourceMap> source_map_;
80 
81   std::unique_ptr<NativeExtensionBindingsSystem> bindings_system_;
82 
83   DISALLOW_COPY_AND_ASSIGN(ModuleSystemTestEnvironment);
84 };
85 
86 // Test fixture for testing JS that makes use of the module system.
87 //
88 // Typically tests will look like:
89 //
90 // TEST_F(MyModuleSystemTest, TestStuff) {
91 //   ModuleSystem::NativesEnabledScope natives_enabled(module_system_.get());
92 //   RegisterModule("test", "requireNative('assert').AssertTrue(true);");
93 //   module_system_->Require("test");
94 // }
95 //
96 // By default a test will fail if no method in the native module 'assert' is
97 // called. This behaviour can be overridden by calling ExpectNoAssertionsMade().
98 class ModuleSystemTest : public testing::Test {
99  public:
100   ModuleSystemTest();
101   ~ModuleSystemTest() override;
102 
103   void SetUp() override;
104   void TearDown() override;
105 
106  protected:
env()107   ModuleSystemTestEnvironment* env() { return env_.get(); }
108 
109   // Create the extension used with the ModuleSystemTestEnvironment. Virtual so
110   // that subclasses can return extensions with different features.
111   virtual scoped_refptr<const Extension> CreateExtension();
112 
113   std::unique_ptr<ModuleSystemTestEnvironment> CreateEnvironment();
114 
115   // Make the test fail if any asserts are called. By default a test will fail
116   // if no asserts are called.
117   void ExpectNoAssertionsMade();
118 
119   // Runs promises that have been resolved. Resolved promises will not run
120   // until this is called.
121   void RunResolvedPromises();
122 
123  private:
124   base::test::TaskEnvironment task_environment_;
125 
126   v8::Isolate* isolate_;
127 
128   std::set<std::string> extension_ids_;
129   ScriptContextSet context_set_;
130   TestExtensionsRendererClient renderer_client_;
131   scoped_refptr<const Extension> extension_;
132 
133   std::unique_ptr<ModuleSystemTestEnvironment> env_;
134   bool should_assertions_be_made_;
135 
136  private:
137   DISALLOW_COPY_AND_ASSIGN(ModuleSystemTest);
138 };
139 
140 }  // namespace extensions
141 
142 #endif  // EXTENSIONS_RENDERER_MODULE_SYSTEM_TEST_H_
143