Exit before second main with -funittest
jfondren
julian.fondren at gmail.com
Fri Jul 30 02:06:32 UTC 2021
On Friday, 30 July 2021 at 01:01:02 UTC, Brian Tiffin wrote:
> Is this good, bad or indifferent (a right left choice, first
> one doesn't matter)?
I think you're opening yourself up to errors where some program
state persists from one run of main to another. You could think
that some set of flags works fine because it tests OK, but then
it doesn't work at the CLI with fresh state. This seems more
appropriate for an external tester, which could also run multiple
mains in parallel to save on time, etc.
But you could also have a smarter test runner instead of a magic
unittest, https://dlang.org/spec/traits.html#getUnitTests has an
example of replacing the built-in test runner. That could exit
before main for you, or fork and run CLI tests in a separate
process (even if just to avoid persistent state, with the parent
just waiting for the child to finish).
Quick example of that:
```d
module udatest;
struct testCLI {
}
unittest {
// unrelated test
assert(true);
}
@testCLI unittest {
main(["exe", "world"]);
}
@testCLI unittest {
main(["exe", "note: static int wasn't altered"]);
}
unittest {
import std.exception : enforce;
main(["exe"]);
enforce(false, new Exception("dummy"));
}
@testCLI unittest {
main(["exe", "up to main#2 now"]);
}
version (unittest) {
bool tester() {
import std.meta : AliasSeq, Filter;
import std.traits : getUDAs;
import core.sys.posix.unistd : fork;
import core.sys.posix.sys.wait : waitpid;
import core.sys.posix.stdlib : _Exit;
import std.stdio;
alias cli = AliasSeq!(__traits(getUnitTests, udatest));
static foreach (i; 0 .. cli.length) {
writefln!"Test %d/%d"(i + 1, cli.length);
try {
if (getUDAs!(cli[i], testCLI).length) {
if (auto child = fork) {
int res;
assert(-1 != waitpid(child, &res, 0));
assert(res == 0);
} else {
cli[i]();
stdout.flush;
stderr.flush;
_Exit(0);
}
} else
cli[i]();
} catch (Exception e) {
writeln(e);
}
}
return false;
}
shared static this() {
import core.runtime : Runtime;
Runtime.moduleUnitTester = &tester;
}
}
void main(string[] args) {
import std.stdio : writefln;
static int n = 0;
writefln!"main#%d called with %s"(++n, args[1 .. $]);
}
```
More information about the Digitalmars-d-learn
mailing list