| Index: util/test/multiprocess_test.cc
|
| diff --git a/util/test/multiprocess_test.cc b/util/test/multiprocess_test.cc
|
| index aab0181b1f1e40260b38585e00cee268131b4100..b1a9685645186262b3082bfd74061e96d455d795 100644
|
| --- a/util/test/multiprocess_test.cc
|
| +++ b/util/test/multiprocess_test.cc
|
| @@ -34,6 +34,8 @@ class TestMultiprocess final : public Multiprocess {
|
| ~TestMultiprocess() {}
|
|
|
| private:
|
| + // Multiprocess:
|
| +
|
| virtual void MultiprocessParent() override {
|
| int read_fd = ReadPipeFD();
|
| char c;
|
| @@ -99,6 +101,8 @@ class TestMultiprocessUnclean final : public Multiprocess {
|
| return type_;
|
| }
|
|
|
| + // Multiprocess:
|
| +
|
| virtual void MultiprocessParent() override {
|
| }
|
|
|
| @@ -115,24 +119,176 @@ class TestMultiprocessUnclean final : public Multiprocess {
|
| DISALLOW_COPY_AND_ASSIGN(TestMultiprocessUnclean);
|
| };
|
|
|
| -TEST(Multiprocess, MultiprocessSuccessfulExit) {
|
| +TEST(Multiprocess, SuccessfulExit) {
|
| TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kExitSuccess);
|
| multiprocess.Run();
|
| }
|
|
|
| -TEST(Multiprocess, MultiprocessUnsuccessfulExit) {
|
| +TEST(Multiprocess, UnsuccessfulExit) {
|
| TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kExitFailure);
|
| multiprocess.Run();
|
| }
|
|
|
| -TEST(Multiprocess, MultiprocessExit2) {
|
| +TEST(Multiprocess, Exit2) {
|
| TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kExit2);
|
| multiprocess.Run();
|
| }
|
|
|
| -TEST(Multiprocess, MultiprocessAbortSignal) {
|
| +TEST(Multiprocess, AbortSignal) {
|
| TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kAbort);
|
| multiprocess.Run();
|
| }
|
|
|
| +class TestMultiprocessClosePipe final : public Multiprocess {
|
| + public:
|
| + enum WhoCloses {
|
| + kParentCloses = 0,
|
| + kChildCloses,
|
| + };
|
| + enum WhatCloses {
|
| + kReadCloses = 0,
|
| + kWriteCloses,
|
| + kReadAndWriteClose,
|
| + };
|
| +
|
| + TestMultiprocessClosePipe(WhoCloses who_closes, WhatCloses what_closes)
|
| + : Multiprocess(),
|
| + who_closes_(who_closes),
|
| + what_closes_(what_closes) {
|
| + }
|
| +
|
| + ~TestMultiprocessClosePipe() {}
|
| +
|
| + private:
|
| + void VerifyInitial() {
|
| + ASSERT_NE(-1, ReadPipeFD());
|
| + ASSERT_NE(-1, WritePipeFD());
|
| + }
|
| +
|
| + // Verifies that the partner process did what it was supposed to do. This must
|
| + // only be called when who_closes_ names the partner process, not this
|
| + // process.
|
| + //
|
| + // If the partner was supposed to close its write pipe, the read pipe will be
|
| + // checked to ensure that it shows end-of-file.
|
| + //
|
| + // If the partner was supposed to close its read pipe, the write pipe will be
|
| + // checked to ensure that a checked write causes death. This can only be done
|
| + // if the partner also provides some type of signal when it has closed its
|
| + // read pipe, which is done in the form of it closing its write pipe, causing
|
| + // the read pipe in this process to show end-of-file.
|
| + void VerifyPartner() {
|
| + if (what_closes_ == kWriteCloses) {
|
| + CheckedReadFDAtEOF(ReadPipeFD());
|
| + } else if (what_closes_ == kReadAndWriteClose) {
|
| + CheckedReadFDAtEOF(ReadPipeFD());
|
| + char c = '\0';
|
| +
|
| + // This will raise SIGPIPE. If fatal (the normal case), that will cause
|
| + // process termination. If SIGPIPE is being handled somewhere, the write
|
| + // will still fail and set errno to EPIPE, and CheckedWriteFD() will abort
|
| + // execution. Regardless of how SIGPIPE is handled, the process will be
|
| + // terminated. Because the actual termination mechanism is not known, no
|
| + // regex can be specified.
|
| + EXPECT_DEATH(CheckedWriteFD(WritePipeFD(), &c, 1), "");
|
| + }
|
| + }
|
| +
|
| + void Close() {
|
| + switch (what_closes_) {
|
| + case kReadCloses:
|
| + CloseReadPipe();
|
| + EXPECT_NE(-1, WritePipeFD());
|
| + EXPECT_DEATH(ReadPipeFD(), "fd");
|
| + break;
|
| + case kWriteCloses:
|
| + CloseWritePipe();
|
| + EXPECT_NE(-1, ReadPipeFD());
|
| + EXPECT_DEATH(WritePipeFD(), "fd");
|
| + break;
|
| + case kReadAndWriteClose:
|
| + CloseReadPipe();
|
| + CloseWritePipe();
|
| + EXPECT_DEATH(ReadPipeFD(), "fd");
|
| + EXPECT_DEATH(WritePipeFD(), "fd");
|
| + break;
|
| + }
|
| + }
|
| +
|
| + // Multiprocess:
|
| +
|
| + virtual void MultiprocessParent() override {
|
| + VerifyInitial();
|
| + if (testing::Test::HasFatalFailure()) {
|
| + return;
|
| + }
|
| +
|
| + if (who_closes_ == kParentCloses) {
|
| + Close();
|
| + } else {
|
| + VerifyPartner();
|
| + }
|
| + }
|
| +
|
| + virtual void MultiprocessChild() override {
|
| + VerifyInitial();
|
| + if (testing::Test::HasFatalFailure()) {
|
| + return;
|
| + }
|
| +
|
| + if (who_closes_ == kChildCloses) {
|
| + Close();
|
| + } else {
|
| + VerifyPartner();
|
| + }
|
| + }
|
| +
|
| + WhoCloses who_closes_;
|
| + WhatCloses what_closes_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TestMultiprocessClosePipe);
|
| +};
|
| +
|
| +TEST(MultiprocessDeathTest, ParentClosesReadPipe) {
|
| + TestMultiprocessClosePipe multiprocess(
|
| + TestMultiprocessClosePipe::kParentCloses,
|
| + TestMultiprocessClosePipe::kReadCloses);
|
| + multiprocess.Run();
|
| +}
|
| +
|
| +TEST(MultiprocessDeathTest, ParentClosesWritePipe) {
|
| + TestMultiprocessClosePipe multiprocess(
|
| + TestMultiprocessClosePipe::kParentCloses,
|
| + TestMultiprocessClosePipe::kWriteCloses);
|
| + multiprocess.Run();
|
| +}
|
| +
|
| +TEST(MultiprocessDeathTest, ParentClosesReadAndWritePipe) {
|
| + TestMultiprocessClosePipe multiprocess(
|
| + TestMultiprocessClosePipe::kParentCloses,
|
| + TestMultiprocessClosePipe::kReadAndWriteClose);
|
| + multiprocess.Run();
|
| +}
|
| +
|
| +TEST(MultiprocessDeathTest, ChildClosesReadPipe) {
|
| + TestMultiprocessClosePipe multiprocess(
|
| + TestMultiprocessClosePipe::kChildCloses,
|
| + TestMultiprocessClosePipe::kReadCloses);
|
| + multiprocess.Run();
|
| +}
|
| +
|
| +TEST(MultiprocessDeathTest, ChildClosesWritePipe) {
|
| + TestMultiprocessClosePipe multiprocess(
|
| + TestMultiprocessClosePipe::kChildCloses,
|
| + TestMultiprocessClosePipe::kWriteCloses);
|
| + multiprocess.Run();
|
| +}
|
| +
|
| +TEST(MultiprocessDeathTest, ChildClosesReadAndWritePipe) {
|
| + TestMultiprocessClosePipe multiprocess(
|
| + TestMultiprocessClosePipe::kChildCloses,
|
| + TestMultiprocessClosePipe::kReadAndWriteClose);
|
| + multiprocess.Run();
|
| +}
|
| +
|
| } // namespace
|
|
|