| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 <string.h> | 5 #include <string.h> |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
| 12 #include "mojo/public/cpp/bindings/interface_request.h" | 12 #include "mojo/public/cpp/bindings/interface_request.h" |
| 13 #include "mojo/public/cpp/system/macros.h" | 13 #include "mojo/public/cpp/system/macros.h" |
| 14 #include "mojo/services/files/cpp/output_stream_file.h" | 14 #include "mojo/services/files/cpp/output_stream_file.h" |
| 15 #include "mojo/services/files/interfaces/file.mojom.h" | 15 #include "mojo/services/files/interfaces/file.mojom.h" |
| 16 #include "mojo/services/files/interfaces/types.mojom.h" | 16 #include "mojo/services/files/interfaces/types.mojom.h" |
| 17 // FIXME |
| 18 #include "mojo/services/native_support/interfaces/process.mojom.h" |
| 17 #include "services/native_support/process_test_base.h" | 19 #include "services/native_support/process_test_base.h" |
| 18 | 20 |
| 21 using mojo::SynchronousInterfacePtr; |
| 22 |
| 19 namespace native_support { | 23 namespace native_support { |
| 20 namespace { | 24 namespace { |
| 21 | 25 |
| 22 using ProcessImplTest = ProcessTestBase; | 26 using ProcessImplTest = ProcessTestBase; |
| 23 | 27 |
| 24 mojo::Array<uint8_t> ToByteArray(const std::string& s) { | 28 mojo::Array<uint8_t> ToByteArray(const std::string& s) { |
| 25 auto rv = mojo::Array<uint8_t>::New(s.size()); | 29 auto rv = mojo::Array<uint8_t>::New(s.size()); |
| 26 memcpy(rv.data(), s.data(), s.size()); | 30 memcpy(rv.data(), s.data(), s.size()); |
| 27 return rv; | 31 return rv; |
| 28 } | 32 } |
| 29 | 33 |
| 30 // This also (slightly) tests |Wait()|, since we want to have some evidence that | 34 // This also (slightly) tests |Wait()|, since we want to have some evidence that |
| 31 // we ran the specified binary (/bin/true versus /bin/false). | 35 // we ran the specified binary (/bin/true versus /bin/false). |
| 32 TEST_F(ProcessImplTest, Spawn) { | 36 TEST_F(ProcessImplTest, Spawn) { |
| 33 mojo::files::Error error; | 37 mojo::files::Error error; |
| 34 | 38 |
| 35 { | 39 { |
| 36 ProcessControllerPtr process_controller; | 40 SynchronousInterfacePtr<ProcessController> process_controller; |
| 37 error = mojo::files::Error::INTERNAL; | 41 error = mojo::files::Error::INTERNAL; |
| 38 process()->Spawn(ToByteArray("/bin/true"), nullptr, nullptr, nullptr, | 42 ASSERT_TRUE(process()->Spawn( |
| 39 nullptr, nullptr, GetProxy(&process_controller), | 43 ToByteArray("/bin/true"), nullptr, nullptr, nullptr, nullptr, nullptr, |
| 40 Capture(&error)); | 44 GetSynchronousProxy(&process_controller), &error)); |
| 41 ASSERT_TRUE(process().WaitForIncomingResponse()); | |
| 42 EXPECT_EQ(mojo::files::Error::OK, error); | 45 EXPECT_EQ(mojo::files::Error::OK, error); |
| 43 | 46 |
| 44 error = mojo::files::Error::INTERNAL; | 47 error = mojo::files::Error::INTERNAL; |
| 45 int32_t exit_status = 42; | 48 int32_t exit_status = 42; |
| 46 process_controller->Wait(Capture(&error, &exit_status)); | 49 ASSERT_TRUE(process_controller->Wait(&error, &exit_status)); |
| 47 ASSERT_TRUE(process_controller.WaitForIncomingResponse()); | |
| 48 EXPECT_EQ(mojo::files::Error::OK, error); | 50 EXPECT_EQ(mojo::files::Error::OK, error); |
| 49 EXPECT_EQ(0, exit_status); | 51 EXPECT_EQ(0, exit_status); |
| 50 } | 52 } |
| 51 | 53 |
| 52 { | 54 { |
| 53 ProcessControllerPtr process_controller; | 55 SynchronousInterfacePtr<ProcessController> process_controller; |
| 54 error = mojo::files::Error::INTERNAL; | 56 error = mojo::files::Error::INTERNAL; |
| 55 process()->Spawn(ToByteArray("/bin/false"), nullptr, nullptr, nullptr, | 57 ASSERT_TRUE(process()->Spawn( |
| 56 nullptr, nullptr, GetProxy(&process_controller), | 58 ToByteArray("/bin/false"), nullptr, nullptr, nullptr, nullptr, nullptr, |
| 57 Capture(&error)); | 59 GetSynchronousProxy(&process_controller), &error)); |
| 58 ASSERT_TRUE(process().WaitForIncomingResponse()); | |
| 59 EXPECT_EQ(mojo::files::Error::OK, error); | 60 EXPECT_EQ(mojo::files::Error::OK, error); |
| 60 | 61 |
| 61 error = mojo::files::Error::INTERNAL; | 62 error = mojo::files::Error::INTERNAL; |
| 62 int32_t exit_status = 0; | 63 int32_t exit_status = 0; |
| 63 process_controller->Wait(Capture(&error, &exit_status)); | 64 ASSERT_TRUE(process_controller->Wait(&error, &exit_status)); |
| 64 ASSERT_TRUE(process_controller.WaitForIncomingResponse()); | |
| 65 EXPECT_EQ(mojo::files::Error::OK, error); | 65 EXPECT_EQ(mojo::files::Error::OK, error); |
| 66 EXPECT_NE(exit_status, 0); | 66 EXPECT_NE(exit_status, 0); |
| 67 } | 67 } |
| 68 } | 68 } |
| 69 | 69 |
| 70 void QuitMessageLoop() { | 70 void QuitMessageLoop() { |
| 71 base::MessageLoop::current()->QuitWhenIdle(); | 71 base::MessageLoop::current()->QuitWhenIdle(); |
| 72 } | 72 } |
| 73 | 73 |
| 74 void RunMessageLoop() { | 74 void RunMessageLoop() { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 // it. | 106 // it. |
| 107 TEST_F(ProcessImplTest, SpawnRedirectStdout) { | 107 TEST_F(ProcessImplTest, SpawnRedirectStdout) { |
| 108 static const char kOutput[] = "hello mojo!"; | 108 static const char kOutput[] = "hello mojo!"; |
| 109 | 109 |
| 110 mojo::files::FilePtr file; | 110 mojo::files::FilePtr file; |
| 111 CaptureOutputFile file_impl(GetProxy(&file)); | 111 CaptureOutputFile file_impl(GetProxy(&file)); |
| 112 | 112 |
| 113 mojo::Array<mojo::Array<uint8_t>> argv; | 113 mojo::Array<mojo::Array<uint8_t>> argv; |
| 114 argv.push_back(ToByteArray("/bin/echo")); | 114 argv.push_back(ToByteArray("/bin/echo")); |
| 115 argv.push_back(ToByteArray(kOutput)); | 115 argv.push_back(ToByteArray(kOutput)); |
| 116 ProcessControllerPtr process_controller; | 116 SynchronousInterfacePtr<ProcessController> process_controller; |
| 117 mojo::files::Error error = mojo::files::Error::INTERNAL; | 117 mojo::files::Error error = mojo::files::Error::INTERNAL; |
| 118 process()->Spawn(ToByteArray("/bin/echo"), argv.Pass(), nullptr, nullptr, | 118 ASSERT_TRUE(process()->Spawn( |
| 119 file.Pass(), nullptr, GetProxy(&process_controller), | 119 ToByteArray("/bin/echo"), argv.Pass(), nullptr, nullptr, file.Pass(), |
| 120 Capture(&error)); | 120 nullptr, GetSynchronousProxy(&process_controller), &error)); |
| 121 ASSERT_TRUE(process().WaitForIncomingResponse()); | |
| 122 EXPECT_EQ(mojo::files::Error::OK, error); | 121 EXPECT_EQ(mojo::files::Error::OK, error); |
| 123 | 122 |
| 124 // Since |file|'s impl is on our thread, we have to spin our message loop. | 123 // Since |file|'s impl is on our thread, we have to spin our message loop. |
| 125 RunMessageLoop(); | 124 RunMessageLoop(); |
| 126 // /bin/echo adds a newline (alas, POSIX /bin/echo doesn't specify "-n"). | 125 // /bin/echo adds a newline (alas, POSIX /bin/echo doesn't specify "-n"). |
| 127 EXPECT_EQ(std::string(kOutput) + "\n", file_impl.output()); | 126 EXPECT_EQ(std::string(kOutput) + "\n", file_impl.output()); |
| 128 | 127 |
| 129 error = mojo::files::Error::INTERNAL; | 128 error = mojo::files::Error::INTERNAL; |
| 130 int32_t exit_status = 0; | 129 int32_t exit_status = 0; |
| 131 process_controller->Wait(Capture(&error, &exit_status)); | 130 ASSERT_TRUE(process_controller->Wait(&error, &exit_status)); |
| 132 ASSERT_TRUE(process_controller.WaitForIncomingResponse()); | |
| 133 EXPECT_EQ(mojo::files::Error::OK, error); | 131 EXPECT_EQ(mojo::files::Error::OK, error); |
| 134 EXPECT_EQ(0, exit_status); | 132 EXPECT_EQ(0, exit_status); |
| 135 | 133 |
| 136 // TODO(vtl): Currently, |file| won't be closed until the process controller | 134 // TODO(vtl): Currently, |file| won't be closed until the process controller |
| 137 // is closed, even if the child has been waited on and all output read. | 135 // is closed, even if the child has been waited on and all output read. |
| 138 // Possibly this should be changed, but we currently can't since the I/O | 136 // Possibly this should be changed, but we currently can't since the I/O |
| 139 // thread doesn't have facilities for informing us that an FD will never be | 137 // thread doesn't have facilities for informing us that an FD will never be |
| 140 // readable. | 138 // readable. |
| 141 EXPECT_FALSE(file_impl.is_closed()); | 139 EXPECT_FALSE(file_impl.is_closed()); |
| 142 process_controller.reset(); | 140 process_controller.reset(); |
| 143 RunMessageLoop(); | 141 RunMessageLoop(); |
| 144 EXPECT_TRUE(file_impl.is_closed()); | 142 EXPECT_TRUE(file_impl.is_closed()); |
| 145 } | 143 } |
| 146 | 144 |
| 147 } // namespace | 145 } // namespace |
| 148 } // namespace native_support | 146 } // namespace native_support |
| OLD | NEW |