OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/public/cpp/application/application_test_base.h" | 5 #include "mojo/public/cpp/application/application_test_base.h" |
6 | 6 |
7 #include "mojo/public/cpp/application/application_delegate.h" | |
8 #include "mojo/public/cpp/application/application_impl.h" | 7 #include "mojo/public/cpp/application/application_impl.h" |
| 8 #include "mojo/public/cpp/bindings/binding.h" |
9 #include "mojo/public/cpp/environment/environment.h" | 9 #include "mojo/public/cpp/environment/environment.h" |
10 #include "mojo/public/cpp/system/message_pipe.h" | 10 #include "mojo/public/cpp/system/message_pipe.h" |
| 11 #include "mojo/public/interfaces/application/application.mojom.h" |
11 | 12 |
12 namespace mojo { | 13 namespace mojo { |
13 namespace test { | 14 namespace test { |
14 | 15 |
15 namespace { | 16 namespace { |
16 | |
17 // This shell handle is shared by multiple test application instances. | |
18 ShellPtr g_shell; | |
19 // Share the application command-line arguments with multiple application tests. | 17 // Share the application command-line arguments with multiple application tests. |
20 Array<String> g_args; | 18 Array<String> g_args; |
21 | 19 |
22 class ArgumentGrabber : public InterfaceImpl<Application> { | 20 // Application request handle passed from the shell in MojoMain, stored in |
| 21 // between SetUp()/TearDown() so we can (re-)intialize new ApplicationImpls. |
| 22 InterfaceRequest<Application> g_application_request; |
| 23 |
| 24 // Shell pointer passed in the initial mojo.Application.Initialize() call, |
| 25 // stored in between initial setup and the first test and between SetUp/TearDown |
| 26 // calls so we can (re-)initialize new ApplicationImpls. |
| 27 ShellPtr g_shell; |
| 28 |
| 29 void InitializeArgs(int argc, std::vector<const char*> argv) { |
| 30 MOJO_CHECK(g_args.is_null()); |
| 31 for (const char* arg : argv) { |
| 32 if (arg) |
| 33 g_args.push_back(arg); |
| 34 } |
| 35 } |
| 36 |
| 37 class ShellAndArgumentGrabber : public Application { |
23 public: | 38 public: |
24 ArgumentGrabber(Array<String>* args, ShellPtr shell) | 39 ShellAndArgumentGrabber(Array<String>* args, |
25 : args_(args), shell_(shell.Pass()) { | 40 InterfaceRequest<Application> application_request) |
26 shell_.set_client(this); | 41 : args_(args), binding_(this, application_request.Pass()) {} |
27 } | |
28 | 42 |
29 void WaitForInitialize() { | 43 void WaitForInitialize() { |
30 // Initialize is always the first call made on Application. | 44 // Initialize is always the first call made on Application. |
31 shell_.WaitForIncomingMethodCall(); | 45 binding_.WaitForIncomingMethodCall(); |
32 } | |
33 | |
34 ShellPtr UnbindShell() { | |
35 ShellPtr unbound_shell; | |
36 unbound_shell.Bind(shell_.PassMessagePipe()); | |
37 return unbound_shell.Pass(); | |
38 } | 46 } |
39 | 47 |
40 private: | 48 private: |
41 // Application implementation. | 49 // Application implementation. |
42 void Initialize(Array<String> args) override { *args_ = args.Pass(); } | 50 void Initialize(ShellPtr shell, Array<String> args) override { |
| 51 *args_ = args.Pass(); |
| 52 g_application_request = binding_.Unbind(); |
| 53 g_shell = shell.Pass(); |
| 54 } |
43 | 55 |
44 void AcceptConnection(const String& requestor_url, | 56 void AcceptConnection(const String& requestor_url, |
45 InterfaceRequest<ServiceProvider> services, | 57 InterfaceRequest<ServiceProvider> services, |
46 ServiceProviderPtr exposed_services) override { | 58 ServiceProviderPtr exposed_services) override { |
47 MOJO_CHECK(false); | 59 MOJO_CHECK(false); |
48 } | 60 } |
49 | 61 |
50 void RequestQuit() override { MOJO_CHECK(false); } | 62 void RequestQuit() override { MOJO_CHECK(false); } |
51 | 63 |
52 Array<String>* args_; | 64 Array<String>* args_; |
53 ShellPtr shell_; | 65 Binding<Application> binding_; |
54 }; | 66 }; |
55 | 67 |
56 ShellPtr PassShellHandle() { | |
57 MOJO_CHECK(g_shell); | |
58 return g_shell.Pass(); | |
59 } | |
60 | |
61 void SetShellHandle(ShellPtr shell) { | |
62 MOJO_CHECK(shell); | |
63 MOJO_CHECK(!g_shell); | |
64 g_shell = shell.Pass(); | |
65 } | |
66 | |
67 void InitializeArgs(int argc, std::vector<const char*> argv) { | |
68 MOJO_CHECK(g_args.is_null()); | |
69 for (const char* arg : argv) { | |
70 if (arg) | |
71 g_args.push_back(arg); | |
72 } | |
73 } | |
74 | |
75 } // namespace | 68 } // namespace |
76 | 69 |
77 const Array<String>& Args() { | 70 const Array<String>& Args() { |
78 return g_args; | 71 return g_args; |
79 } | 72 } |
80 | 73 |
81 MojoResult RunAllTests(ShellPtr shell) { | 74 MojoResult RunAllTests(MojoHandle application_request_handle) { |
82 { | 75 { |
83 // This loop is used for init, and then destroyed before running tests. | 76 // This loop is used for init, and then destroyed before running tests. |
84 Environment::InstantiateDefaultRunLoop(); | 77 Environment::InstantiateDefaultRunLoop(); |
85 | 78 |
| 79 // Grab the shell handle and GTEST commandline arguments. |
| 80 // GTEST command line arguments are supported amid application arguments: |
| 81 // $ mojo_shell mojo:example_apptests |
| 82 // --args-for='mojo:example_apptests arg1 --gtest_filter=foo arg2' |
86 Array<String> args; | 83 Array<String> args; |
87 ArgumentGrabber grab(&args, shell.Pass()); | 84 ShellAndArgumentGrabber grabber( |
88 grab.WaitForInitialize(); | 85 &args, MakeRequest<Application>(MakeScopedHandle( |
| 86 MessagePipeHandle(application_request_handle)))); |
| 87 grabber.WaitForInitialize(); |
| 88 MOJO_CHECK(g_shell); |
| 89 MOJO_CHECK(g_application_request.is_pending()); |
89 | 90 |
90 // InitGoogleTest expects (argc + 1) elements, including a terminating null. | 91 // InitGoogleTest expects (argc + 1) elements, including a terminating null. |
91 // It also removes GTEST arguments from |argv| and updates the |argc| count. | 92 // It also removes GTEST arguments from |argv| and updates the |argc| count. |
92 MOJO_CHECK(args.size() < | 93 MOJO_CHECK(args.size() < |
93 static_cast<size_t>(std::numeric_limits<int>::max())); | 94 static_cast<size_t>(std::numeric_limits<int>::max())); |
94 int argc = static_cast<int>(args.size()); | 95 int argc = static_cast<int>(args.size()); |
95 std::vector<const char*> argv(argc + 1); | 96 std::vector<const char*> argv(argc + 1); |
96 for (int i = 0; i < argc; ++i) | 97 for (int i = 0; i < argc; ++i) |
97 argv[i] = args[i].get().c_str(); | 98 argv[i] = args[i].get().c_str(); |
98 argv[argc] = nullptr; | 99 argv[argc] = nullptr; |
99 | 100 |
100 testing::InitGoogleTest(&argc, const_cast<char**>(&(argv[0]))); | 101 testing::InitGoogleTest(&argc, const_cast<char**>(&(argv[0]))); |
101 SetShellHandle(grab.UnbindShell()); | |
102 InitializeArgs(argc, argv); | 102 InitializeArgs(argc, argv); |
103 | 103 |
104 Environment::DestroyDefaultRunLoop(); | 104 Environment::DestroyDefaultRunLoop(); |
105 } | 105 } |
106 | 106 |
107 int result = RUN_ALL_TESTS(); | 107 int result = RUN_ALL_TESTS(); |
108 | 108 |
109 shell = mojo::test::PassShellHandle(); | 109 // Shut down our message pipes before exiting. |
110 shell.reset(); | 110 (void)g_application_request.PassMessagePipe(); |
| 111 (void)g_shell.PassMessagePipe(); |
111 | 112 |
112 return (result == 0) ? MOJO_RESULT_OK : MOJO_RESULT_UNKNOWN; | 113 return (result == 0) ? MOJO_RESULT_OK : MOJO_RESULT_UNKNOWN; |
113 } | 114 } |
114 | 115 |
115 ApplicationTestBase::ApplicationTestBase() : application_impl_(nullptr) { | 116 ApplicationTestBase::ApplicationTestBase() : application_impl_(nullptr) { |
116 } | 117 } |
117 | 118 |
118 ApplicationTestBase::~ApplicationTestBase() { | 119 ApplicationTestBase::~ApplicationTestBase() { |
119 } | 120 } |
120 | 121 |
121 ApplicationDelegate* ApplicationTestBase::GetApplicationDelegate() { | 122 ApplicationDelegate* ApplicationTestBase::GetApplicationDelegate() { |
122 return &default_application_delegate_; | 123 return &default_application_delegate_; |
123 } | 124 } |
124 | 125 |
125 void ApplicationTestBase::SetUpWithArgs(const Array<String>& args) { | 126 void ApplicationTestBase::SetUp() { |
126 // A run loop is recommended for ApplicationImpl initialization and | 127 // A run loop is recommended for ApplicationImpl initialization and |
127 // communication. | 128 // communication. |
128 if (ShouldCreateDefaultRunLoop()) | 129 if (ShouldCreateDefaultRunLoop()) |
129 Environment::InstantiateDefaultRunLoop(); | 130 Environment::InstantiateDefaultRunLoop(); |
130 | 131 |
| 132 MOJO_CHECK(g_application_request.is_pending()); |
| 133 MOJO_CHECK(g_shell); |
| 134 |
131 // New applications are constructed for each test to avoid persisting state. | 135 // New applications are constructed for each test to avoid persisting state. |
132 application_impl_ = new ApplicationImpl(GetApplicationDelegate(), | 136 application_impl_ = new ApplicationImpl(GetApplicationDelegate(), |
133 PassShellHandle()); | 137 g_application_request.Pass()); |
134 | 138 |
135 // Fake application initialization with the given command line arguments. | 139 // Fake application initialization with the given command line arguments. |
136 application_impl_->Initialize(args.Clone()); | 140 application_impl_->Initialize(g_shell.Pass(), g_args.Clone()); |
137 } | |
138 | |
139 void ApplicationTestBase::SetUp() { | |
140 SetUpWithArgs(Args()); | |
141 } | 141 } |
142 | 142 |
143 void ApplicationTestBase::TearDown() { | 143 void ApplicationTestBase::TearDown() { |
144 SetShellHandle(application_impl_->UnbindShell()); | 144 MOJO_CHECK(!g_application_request.is_pending()); |
| 145 MOJO_CHECK(!g_shell); |
| 146 |
| 147 application_impl_->UnbindConnections(&g_application_request, &g_shell); |
145 delete application_impl_; | 148 delete application_impl_; |
146 if (ShouldCreateDefaultRunLoop()) | 149 if (ShouldCreateDefaultRunLoop()) |
147 Environment::DestroyDefaultRunLoop(); | 150 Environment::DestroyDefaultRunLoop(); |
148 } | 151 } |
149 | 152 |
150 bool ApplicationTestBase::ShouldCreateDefaultRunLoop() { | 153 bool ApplicationTestBase::ShouldCreateDefaultRunLoop() { |
151 return true; | 154 return true; |
152 } | 155 } |
153 | 156 |
154 } // namespace test | 157 } // namespace test |
155 } // namespace mojo | 158 } // namespace mojo |
OLD | NEW |