1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
Description: Apply patch from upstream to fix e2e test fail
The test e2e is failing in Debian CI under certain condition. This patch
is a commit from upstream to fix this fail.
Author: Austin Macdonald
Origin: https://github.com/con/duct/pull/258
Bug: https://bugs.debian.org/1103059
Applied-Upstream: https://github.com/con/duct/commit/645691e5037c771687622e988c03282dcaa62c3c
Last-Update: 2025-05-08
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
--- a/test/data/abandoning_parent.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/bash
-
-nchildren=$1
-shift
-
-for i in `seq 1 $nchildren`; do
- "$@" &
-done
-
-echo "Started $nchildren for $$"
-# Can be useful when running manually, but commented out so we can count pids in tests
-# pstree -c -p "$$"
-
-echo "Starting one more in subprocess"
-
-( "$@" & )
-
-jobs
-
-# Can be useful when running manually, but commented out so we can count pids in tests
-# pstree -c -p "$$"
-echo "waiting"
-wait
--- /dev/null
+++ b/test/data/spawn_children.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+mode=$1
+nchildren=$2
+sleeptime=$3
+
+# Ensure at least one background process for `wait` to track, we want this to take longer than the children.
+long_sleep=$(awk "BEGIN {print $sleeptime * 1.5}")
+sleep "$long_sleep" &
+
+for _ in $(seq 1 "$nchildren"); do
+ case "$mode" in
+ subshell)
+ ( sleep "$sleeptime" & ) ;;
+ nohup)
+ ( nohup sleep "$sleeptime" & disown ) & ;;
+ setsid)
+ setsid sleep "$sleeptime" & ;;
+ plain)
+ sleep "$sleeptime" & ;;
+ *)
+ echo "Unknown mode: $mode" >&2
+ exit 1
+ ;;
+ esac
+done
+
+wait
--- a/test/test_e2e.py
+++ b/test/test_e2e.py
@@ -1,11 +1,10 @@
from __future__ import annotations
-from itertools import chain
import json
from pathlib import Path
import subprocess
import pytest
-ABANDONING_PARENT = str(Path(__file__).with_name("data") / "abandoning_parent.sh")
+TEST_SCRIPT_DIR = Path(__file__).with_name("data")
def test_sanity(temp_output_dir: str) -> None:
@@ -13,16 +12,27 @@
subprocess.check_output(command, shell=True)
+@pytest.mark.parametrize("mode", ["plain", "subshell", "nohup", "setsid"])
@pytest.mark.parametrize("num_children", [1, 2, 10])
-def test_abandoning_parent(temp_output_dir: str, num_children: int) -> None:
+def test_spawn_children(temp_output_dir: str, mode: str, num_children: int) -> None:
duct_prefix = f"{temp_output_dir}log_"
- command = f"duct --s-i 0.001 --r-i 0.01 -p {duct_prefix} {ABANDONING_PARENT} {num_children} sleep 0.2"
+ script_path = TEST_SCRIPT_DIR / "spawn_children.sh"
+ dur = "0.2"
+ command = f"duct -q --s-i 0.001 --r-i 0.01 -p {duct_prefix} {script_path} {mode} {num_children} {dur}"
subprocess.check_output(command, shell=True)
with open(f"{duct_prefix}usage.json") as usage_file:
all_samples = [json.loads(line) for line in usage_file]
- all_pids = set(chain.from_iterable(sample["processes"] for sample in all_samples))
-
- # 1 for each child, 1 for pstree, 1 for parent
- assert len(all_pids) == num_children + 2
+ # Only count the child sleep processes
+ all_child_pids = set(
+ pid
+ for sample in all_samples
+ for pid, proc in sample["processes"].items()
+ if proc["cmd"].startswith("sleep")
+ )
+ # Add one pid for the hold-the-door process, see spawn_children.sh line 7
+ if mode == "setsid":
+ assert len(all_child_pids) == 1
+ else:
+ assert len(all_child_pids) == num_children + 1
|