| 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 |