| 523 | } |
| 524 | |
| 525 | void Run(std::function<void()> f, const TString& suite, const char* name, const bool forceFork) override { |
| 526 | if (!(GetForkTests() || forceFork) || GetIsForked()) { |
| 527 | return f(); |
| 528 | } |
| 529 | |
| 530 | TList<TString> args(1, "--is-forked-internal"); |
| 531 | args.push_back(Sprintf("+%s::%s", suite.data(), name)); |
| 532 | |
| 533 | // stdin is ignored - unittest should not need them... |
| 534 | TShellCommandOptions options; |
| 535 | options |
| 536 | .SetUseShell(false) |
| 537 | .SetCloseAllFdsOnExec(true) |
| 538 | .SetAsync(false) |
| 539 | .SetLatency(1); |
| 540 | |
| 541 | TShellCommand cmd(AppName, args, options); |
| 542 | cmd.Run(); |
| 543 | |
| 544 | const TString& err = cmd.GetError(); |
| 545 | const size_t msgIndex = err.find(ForkCorrectExitMsg); |
| 546 | |
| 547 | // everything is printed by parent process except test's result output ("good" or "fail") |
| 548 | // which is printed by child. If there was no output - parent process prints default message. |
| 549 | ForkExitedCorrectly = msgIndex != TString::npos; |
| 550 | |
| 551 | // TODO: stderr output is always printed after stdout |
| 552 | Cout.Write(cmd.GetOutput()); |
| 553 | Cerr.Write(err.c_str(), Min(msgIndex, err.size())); |
| 554 | |
| 555 | // do not use default case, so gcc will warn if new element in enum will be added |
| 556 | switch (cmd.GetStatus()) { |
| 557 | case TShellCommand::SHELL_FINISHED: { |
| 558 | // test could fail with zero status if it calls exit(0) in the middle. |
| 559 | if (ForkExitedCorrectly) |
| 560 | break; |
| 561 | [[fallthrough]]; |
| 562 | } |
| 563 | case TShellCommand::SHELL_ERROR: { |
| 564 | ythrow yexception() << "Forked test failed"; |
| 565 | } |
| 566 | |
| 567 | case TShellCommand::SHELL_NONE: { |
| 568 | ythrow yexception() << "Forked test finished with unknown status"; |
| 569 | } |
| 570 | case TShellCommand::SHELL_RUNNING: { |
| 571 | Y_ABORT_UNLESS(false, "This can't happen, we used sync mode, it's a bug!"); |
| 572 | } |
| 573 | case TShellCommand::SHELL_INTERNAL_ERROR: { |
| 574 | ythrow yexception() << "Forked test failed with internal error: " << cmd.GetInternalError(); |
| 575 | } |
| 576 | } |
| 577 | } |
| 578 | |
| 579 | private: |
| 580 | bool PrintBeforeSuite_; |
nothing calls this directly
no test coverage detected