[dmd-internals] changeset 455

Denis 2korden at gmail.com
Fri Apr 30 07:12:27 PDT 2010


On Fri, Apr 30, 2010 at 4:25 PM, Steve Schveighoffer
<schveiguy at yahoo.com> wrote:
>
>
> --- On Wed, 4/28/10, Andrei Alexandrescu <andrei at erdani.com> wrote:
>> On 04/28/2010 04:17 PM, Robert
>> Clipsham wrote:
>> > There's a GNU library for handling this, libsigsegv (
>> > http://libsigsegv.sourceforge.net/ ). I
>> took the liberty of downloading
>> > and inspecting this, it's 5659 LoC to handle segfaults
>> (So say, 3000 if
>> > we rewrote it in D :P). That's a lot of extra code to
>> handle a segfault
>> > for unittests. Add to this not all platforms support
>> it, and it needs
>> > reimplementing on every platform. If you want this
>> code in
>> > druntime/phobos then you'll have to write it from
>> scratch due to
>> > licensing issues and be unable to look at this well
>> written/tested
>> > library as a reference... It seems like a lot of extra
>> effort for
>> > something I maintain should be done with a debugger.
>>
>> Ouch.
>
> This is not important.  A library to print out the last unit test failure is really easy.  printf is not required, write will be sufficient.  All it needs is a little compiler help.
>
> At the beginning of every unit test, the compiler should insert the following code:
>
> unittest {    __unittestFile = __FILE__;    __unittestLine = __LINE__;
>    ...
> }
>
> Then, during unittest, the runtime inserts a signal handler for SEGV:
>
> __gshared string __unittestFile = "";
> __gshared uint __unittestLine = 0;
> __gshared string msg = "unittest SEGV: ";
>
> extern(C) void unittestSegv(int sig)
> {
>   char[11] lineno;
>   int linenostart = 0;
>   do
>   {
>      lineno[$-1-linenolength] = '0' + __unittestLine  % 10;
>      __unittestLine /= 10;
>      --linenostart;
>   } while(__unittestLine > 0);
>
>   write(2, msg.ptr, msg.length);
>   write(2, __unittestFile.ptr, __unittestFile.length);
>   write(2, "@", 1);
>   write(2, lineno.ptr + linenostart, lineno.length - linenostart);
>   write(2, "\n", 1);
>   exit(1);
> }
>
> Note that performance problems due to instrumentation or bloating does not matter whatsoever, because unittest mode is not normal.  You only ever compile with unittest mode when you are testing unittests, not when you are trying to run a program.
>
> The point is, something simple that at least displays some info is better than nothing.  Saying someone should use a debugger is both useless after the fact (the program already crashed!) and doesn't really apply to unittesting.  Unittesting is not the normal mode of operation, so making an exception there does not muddy any principles.  The unit test system should make a best effort to report any failures.  If the program somehow corrupts the global variables, then the worst that happens is the signal handler segfaults, and you get the same error message you get now.  Then you can use a debugger :)
>
> Note that this just reports the start of the unit test that failed, not where the actual failure occurs.  This should be plenty info in most cases, you can and should have multiple unit test functions in each module.
>
> -Steve
>
>
>
>
> _______________________________________________
> dmd-internals mailing list
> dmd-internals at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/dmd-internals
>

I believe filling some UnitTestResult class/struct info would be a lot
better solution. Once all the unittests are run, some special function
could be run that would parse it and (by default) output to the
console. User would be able to substitute it (at link time) with his
own one (e.g. one that would should a MessageBox or other GUI dialog).


More information about the dmd-internals mailing list