diff --git a/changelog/dustmite-timeout.dd b/changelog/dustmite-timeout.dd new file mode 100644 index 0000000000..6d7eb2278f --- /dev/null +++ b/changelog/dustmite-timeout.dd @@ -0,0 +1,6 @@ +Added `--timeout` option to `dub dustmite` command. + +Adds a timeout (in seconds) for each oracle invocation, preventing +the dustmite process from hanging indefinitely when the test command +does not terminate. Requires the `timeout` command to be available +(coreutils on Linux/macOS). diff --git a/scripts/fish-completion/dub.fish b/scripts/fish-completion/dub.fish index 1ed8fb801c..4574ae772c 100644 --- a/scripts/fish-completion/dub.fish +++ b/scripts/fish-completion/dub.fish @@ -88,6 +88,7 @@ for cmd in dustmite complete -c dub -n "contains '$cmd' (commandline -poc)" -l program-status -x -d "Expected program status code" complete -c dub -n "contains '$cmd' (commandline -poc)" -l program-regex -x -d "Program output regular expression" complete -c dub -n "contains '$cmd' (commandline -poc)" -l test-package -x -d "Perform a test run" + complete -c dub -n "contains '$cmd' (commandline -poc)" -l timeout -x -d "Timeout for each oracle invocation in seconds" end for cmd in fetch remove diff --git a/scripts/zsh-completion/_dub b/scripts/zsh-completion/_dub index 4550cd8073..a186fe8374 100644 --- a/scripts/zsh-completion/_dub +++ b/scripts/zsh-completion/_dub @@ -255,6 +255,7 @@ _dub_dustmite() { '--linker-regex=[A regular expression used to match against the linker output]:regex: ' '--program-status=[The expected status code of the built executable]:status code: ' '--program-regex=[A regular expression used to match against the program output]:regex: ' + '--timeout=[Timeout for each oracle invocation in seconds]:seconds: ' '--[End of dub arguments, the following will be sent to the program]' ) diff --git a/source/dub/commandline.d b/source/dub/commandline.d index 3c3efd4402..21e8535939 100644 --- a/source/dub/commandline.d +++ b/source/dub/commandline.d @@ -2726,6 +2726,7 @@ class DustmiteCommand : PackageBuildCommand { string m_strategy; uint m_jobCount; // zero means not specified bool m_trace; + uint m_timeout; // in seconds, zero means not specified } this() @safe pure nothrow @@ -2757,6 +2758,7 @@ class DustmiteCommand : PackageBuildCommand { args.getopt("strategy", &m_strategy, ["Set strategy (careful/lookback/pingpong/indepth/inbreadth)"]); args.getopt("j", &m_jobCount, ["Set number of look-ahead processes"]); args.getopt("trace", &m_trace, ["Save all attempted reductions to DIR.trace"]); + args.getopt("timeout", &m_timeout, ["Timeout for each oracle invocation in seconds"]); super.prepare(args); // speed up loading when in test mode @@ -2875,6 +2877,8 @@ class DustmiteCommand : PackageBuildCommand { logInfo("Starting", Color.light_green, "Executing dustmite..."); auto testcmd = appender!string(); + if (m_timeout) + testcmd.formattedWrite("timeout %s ", m_timeout); testcmd.formattedWrite("%s dustmite --test-package=%s --build=%s --config=%s", std.file.thisExePath, prj.name, this.baseSettings.buildType, this.baseSettings.config); diff --git a/test/dustmite-no-redirect.sh b/test/dustmite-no-redirect.sh index 30c6b9c308..ecf324ab36 100755 --- a/test/dustmite-no-redirect.sh +++ b/test/dustmite-no-redirect.sh @@ -15,7 +15,7 @@ LOG="$DM_TEST.log" rm -rf $DM_TMP $DM_TMP.* -$DUB --root=$DM_TEST dustmite --no-redirect --program-status=1 $DM_TMP &> $LOG || true +$DUB --root=$DM_TEST dustmite --no-redirect --program-status=1 --timeout=60 $DM_TMP &> $LOG || true if ! grep -q "$EXPECTED" "$LOG" then