| // Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "cros-disks/process.h" |
| |
| #include <base/files/file_path.h> |
| #include <base/files/file_util.h> |
| #include <base/files/scoped_temp_dir.h> |
| |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| |
| #include "cros-disks/sandboxed_process.h" |
| |
| namespace cros_disks { |
| |
| using testing::_; |
| using testing::Contains; |
| using testing::DoAll; |
| using testing::ElementsAre; |
| using testing::Return; |
| using testing::SetArgPointee; |
| |
| // A mock process class for testing the process base class. |
| class ProcessUnderTest : public Process { |
| public: |
| ProcessUnderTest() = default; |
| |
| MOCK_METHOD4(StartImpl, |
| pid_t(std::vector<char*>& args, |
| base::ScopedFD*, |
| base::ScopedFD*, |
| base::ScopedFD*)); |
| MOCK_METHOD0(WaitImpl, int()); |
| MOCK_METHOD1(WaitNonBlockingImpl, bool(int*)); |
| }; |
| |
| class ProcessTest : public ::testing::Test { |
| protected: |
| ProcessUnderTest process_; |
| }; |
| |
| TEST_F(ProcessTest, GetArguments) { |
| static const char* const kTestArguments[] = {"/bin/ls", "-l", "", "."}; |
| for (const char* test_argument : kTestArguments) { |
| process_.AddArgument(test_argument); |
| } |
| |
| EXPECT_THAT(process_.arguments(), ElementsAre("/bin/ls", "-l", "", ".")); |
| |
| char** arguments = process_.GetArguments(); |
| EXPECT_NE(nullptr, arguments); |
| for (const char* test_argument : kTestArguments) { |
| EXPECT_STREQ(test_argument, *arguments); |
| ++arguments; |
| } |
| EXPECT_EQ(nullptr, *arguments); |
| } |
| |
| TEST_F(ProcessTest, GetArgumentsWithNoArgumentsAdded) { |
| EXPECT_EQ(nullptr, process_.GetArguments()); |
| } |
| |
| TEST_F(ProcessTest, Run_Success) { |
| process_.AddArgument("foo"); |
| EXPECT_CALL(process_, StartImpl(_, _, _, _)).WillOnce(Return(123)); |
| EXPECT_CALL(process_, WaitImpl()).WillOnce(Return(42)); |
| EXPECT_CALL(process_, WaitNonBlockingImpl(_)).Times(0); |
| EXPECT_EQ(42, process_.Run()); |
| } |
| |
| TEST_F(ProcessTest, Run_Fail) { |
| process_.AddArgument("foo"); |
| EXPECT_CALL(process_, StartImpl(_, _, _, _)).WillOnce(Return(-1)); |
| EXPECT_CALL(process_, WaitImpl()).Times(0); |
| EXPECT_CALL(process_, WaitNonBlockingImpl(_)).Times(0); |
| EXPECT_EQ(-1, process_.Run()); |
| } |
| |
| TEST_F(ProcessTest, Communicate) { |
| base::ScopedTempDir dir; |
| ASSERT_TRUE(dir.CreateUniqueTempDir()); |
| |
| std::string file1 = dir.GetPath().Append("file1").value(); |
| std::string file2 = dir.GetPath().Append("file2").value(); |
| std::string file3 = dir.GetPath().Append("file3").value(); |
| ASSERT_EQ(6, base::WriteFile(base::FilePath(file1), "data1\n", 6)); |
| ASSERT_EQ(6, base::WriteFile(base::FilePath(file2), "data2\n", 6)); |
| ASSERT_EQ(6, base::WriteFile(base::FilePath(file3), "data3\n", 6)); |
| ASSERT_EQ(0, chmod(file2.c_str(), 0)); |
| |
| // Using SandboxedProcess as it's the only real implementation. |
| SandboxedProcess sandbox; |
| Process* process = &sandbox; |
| |
| process->AddArgument("/bin/cat"); |
| process->AddArgument(file1); |
| process->AddArgument(file2); |
| process->AddArgument(file3); |
| |
| ASSERT_TRUE(process->Start()); |
| std::vector<std::string> output; |
| process->Communicate(&output); |
| EXPECT_THAT(output, Contains("OUT: data1")); |
| EXPECT_THAT(output, Contains("OUT: data3")); |
| EXPECT_THAT(output, Contains("ERR: cat: " + file2 + ": Permission denied")); |
| EXPECT_THAT(output, testing::Not(Contains("OUT: data2"))); |
| |
| process->Wait(); |
| } |
| |
| } // namespace cros_disks |