/* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include "../UtilsHost.h" using android::base::testing::Ok; using testing::Optional; namespace android { TEST(UtilsHost, ExecuteImmediately) { auto result = execute({"echo", "foo"}, nullptr); ASSERT_TRUE(result.has_value()); EXPECT_THAT(result->exitCode, Optional(EX_OK)); EXPECT_EQ(result->stdoutStr, "foo\n"); } template auto millisSince(std::chrono::time_point now) { auto elapsed = std::chrono::system_clock::now() - now; return std::chrono::duration_cast(elapsed).count(); } TEST(UtilsHost, ExecuteLongRunning) { auto start = std::chrono::system_clock::now(); { std::vector args{"sh", "-c", "sleep 0.5 && echo -n f && sleep 0.5 && echo oo && sleep 100"}; auto result = execute(std::move(args), [&](const CommandResult& commandResult) { std::cout << millisSince(start) << "ms: GOT PARTIAL COMMAND RESULT:" << commandResult.stdoutStr << std::endl; return android::base::EndsWith(commandResult.stdoutStr, "\n"); }); auto elapsedMs = millisSince(start); EXPECT_GE(elapsedMs, 1000); EXPECT_LT(elapsedMs, 3000); // b/377571547: higher to reduce flake ASSERT_TRUE(result.has_value()); EXPECT_EQ(std::nullopt, result->exitCode); EXPECT_EQ(result->stdoutStr, "foo\n"); } // ~CommandResult() called, child process is killed. // Assert that the second sleep does not finish. EXPECT_LT(millisSince(start), 3000); } TEST(UtilsHost, ExecuteLongRunning2) { auto start = std::chrono::system_clock::now(); { std::vector args{"sh", "-c", "sleep 2 && echo -n f && sleep 2 && echo oo && sleep 100"}; auto result = execute(std::move(args), [&](const CommandResult& commandResult) { std::cout << millisSince(start) << "ms: GOT PARTIAL COMMAND RESULT:" << commandResult.stdoutStr << std::endl; return android::base::EndsWith(commandResult.stdoutStr, "\n"); }); auto elapsedMs = millisSince(start); EXPECT_GE(elapsedMs, 4000); EXPECT_LT(elapsedMs, 6000); ASSERT_TRUE(result.has_value()); EXPECT_EQ(std::nullopt, result->exitCode); EXPECT_EQ(result->stdoutStr, "foo\n"); } // ~CommandResult() called, child process is killed. // Assert that the second sleep does not finish. EXPECT_LT(millisSince(start), 6000); } TEST(UtilsHost, KillWithSigKill) { std::vector args{"sh", "-c", "echo foo && sleep 10"}; auto result = execute(std::move(args), [](const CommandResult& commandResult) { // FOR TEST PURPOSE ONLY. DON'T DO THIS! if (commandResult.pid.has_value()) { (void)kill(*commandResult.pid, SIGKILL); } // FOR TEST PURPOSE ONLY. DON'T DO THIS! return false; }); ASSERT_TRUE(result.has_value()); EXPECT_EQ(std::nullopt, result->exitCode); EXPECT_THAT(result->signal, Optional(SIGKILL)); } } // namespace android