Skip to content

Commit

Permalink
Trying to unflake the unit test of ChildrenTracker
Browse files Browse the repository at this point in the history
  • Loading branch information
mikekazakov committed Jan 8, 2024
1 parent d08c32d commit 1514c55
Showing 1 changed file with 38 additions and 15 deletions.
53 changes: 38 additions & 15 deletions Source/Term/tests/ChildrenTracker_UT.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2023 Michael Kazakov. Subject to GNU General Public License version 3.
// Copyright (C) 2023-2024 Michael Kazakov. Subject to GNU General Public License version 3.

#include "Tests.h"
#include "AtomicHolder.h"
Expand All @@ -10,44 +10,51 @@ using namespace nc::term;
using namespace std::chrono_literals;
#define PREFIX "nc::term::ChildrenTracker "

TEST_CASE(PREFIX "Generic cases")
TEST_CASE(PREFIX "Generic cases", "[!mayfail]")
{
const int mypid = getpid();
const int p1 = getpid();
QueuedAtomicHolder<int> ncalled{0};
auto cb = [&ncalled, next = 1] mutable { ncalled.store(next++); };

ChildrenTracker tracker{mypid, cb};
ChildrenTracker tracker{p1, cb};

SECTION("Nothing") {}
SECTION("Single fork")
{
int p2;
int p2 = 0;
if( (p2 = fork()) == 0 ) {
std::this_thread::sleep_for(1ms);
exit(0);
}
CHECK(p2 > 0);
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 1)); // p1 fork -> p2
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 2)); // p2 exit
waitpid(p2, nullptr, 0);
CHECK(waitpid(p2, nullptr, 0) == p2);
}
SECTION("Two sequent forks")
{
if( fork() == 0 ) {
int p2 = 0, p3 = 0;
if( (p2 = fork()) == 0 ) {
std::this_thread::sleep_for(1ms);
exit(0);
}
CHECK(p2 > 0);
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 1)); // p1 fork -> p2
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 2)); // p2 exit
if( fork() == 0 ) {
if( (p3 = fork()) == 0 ) {
std::this_thread::sleep_for(1ms);
exit(0);
}
CHECK(p3 > 0);
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 3)); // p1 fork -> p3
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 4)); // p3 exit
CHECK(waitpid(p2, nullptr, 0) == p2);
CHECK(waitpid(p3, nullptr, 0) == p3);
}
SECTION("Two recursive forks")
{
if( fork() == 0 ) {
int p2 = 0;
if( (p2 = fork()) == 0 ) {
std::this_thread::sleep_for(1ms);
if( int p3; (p3 = fork()) == 0 ) {
std::this_thread::sleep_for(1ms);
Expand All @@ -57,14 +64,17 @@ TEST_CASE(PREFIX "Generic cases")
waitpid(p3, nullptr, 0);
exit(0);
}
CHECK(p2 > 0);
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 1)); // p1 fork -> p2
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 2)); // p2 fork -> p3
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 3)); // p3 exit
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 4)); // p2 exit
CHECK(waitpid(p2, nullptr, 0) == p2);
}
SECTION("Three recursive forks")
{
if( fork() == 0 ) {
int p2 = 0;
if( (p2 = fork()) == 0 ) {
std::this_thread::sleep_for(1ms);
if( int p3; (p3 = fork()) == 0 ) {
std::this_thread::sleep_for(1ms);
Expand All @@ -80,16 +90,19 @@ TEST_CASE(PREFIX "Generic cases")
waitpid(p3, nullptr, 0);
exit(0);
}
CHECK(p2 > 0);
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 1)); // p1 fork -> p2
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 2)); // p2 fork -> p3
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 3)); // p3 fork -> p4
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 4)); // p4 exit
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 5)); // p3 exit
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 6)); // p2 exit
CHECK(waitpid(p2, nullptr, 0) == p2);
}
SECTION("2 x two recursive forks")
{
if( fork() == 0 ) {
int p2 = 0, p4 = 0;
if( (p2 = fork()) == 0 ) {
std::this_thread::sleep_for(1ms);
if( int p3; (p3 = fork()) == 0 ) {
std::this_thread::sleep_for(1ms);
Expand All @@ -99,7 +112,7 @@ TEST_CASE(PREFIX "Generic cases")
waitpid(p3, nullptr, 0);
exit(0);
}
if( fork() == 0 ) {
if( (p4 = fork()) == 0 ) {
std::this_thread::sleep_for(1ms);
if( int p3; (p3 = fork()) == 0 ) {
std::this_thread::sleep_for(1ms);
Expand All @@ -109,29 +122,37 @@ TEST_CASE(PREFIX "Generic cases")
waitpid(p3, nullptr, 0);
exit(0);
}
CHECK(p2 > 0);
CHECK(p4 > 0);
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 1)); // p1 fork -> p2
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 2)); // p1 fork -> p4
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 3)); // p2 fork -> p3
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 4)); // p4 fork -> p5
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 5)); // p3 exit
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 6)); // p5 exit
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 7)); // p2 exit
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 8)); // p4 exit
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 8)); // p4 exit <-- this one fails on GHA
CHECK(waitpid(p2, nullptr, 0) == p2);
CHECK(waitpid(p4, nullptr, 0) == p4);
}
SECTION("Fork and exec")
{
if( fork() == 0 ) {
int p2 = 0;
if( (p2 = fork()) == 0 ) {
std::this_thread::sleep_for(1ms);
close(1);
execl("/usr/bin/uptime", "uptime", nullptr);
}
CHECK(p2 > 0);
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 1)); // p1 fork -> p2
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 2)); // p2 exec
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 3)); // p2 exit
CHECK(waitpid(p2, nullptr, 0) == p2);
}
SECTION("Two recursive forks and exec")
{
if( fork() == 0 ) {
int p2 = 0;
if( (p2 = fork()) == 0 ) {
std::this_thread::sleep_for(1ms);
if( int p3; (p3 = fork()) == 0 ) {
std::this_thread::sleep_for(1ms);
Expand All @@ -142,11 +163,13 @@ TEST_CASE(PREFIX "Generic cases")
waitpid(p3, nullptr, 0);
exit(0);
}
CHECK(p2 > 0);
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 1)); // p1 fork -> p2
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 2)); // p2 fork -> p3
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 3)); // p3 exec
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 4)); // p3 exit
CHECK(ncalled.wait_to_become_with_runloop(5s, 1ms, 5)); // p2 exit
CHECK(waitpid(p2, nullptr, 0) == p2);
}
}

Expand Down

0 comments on commit 1514c55

Please sign in to comment.