November 28, 2013
On 28/11/13 17:40, Dicebot wrote:
> I have quickly tested it and looks like asserts are not removed from unittest
> blocks in release builds, only from normal code. Which does not seem to be
> documented on dlang.org but was probably introduced exactly to prevent existing
> tests from breaking in release mode. I have just learned something new :)

Snap, I just came to the same conclusion after finding that version(assert) seemed to be working fine in a main() function but that it continued to be ignored inside a unittest scope :-)
November 28, 2013
On 28/11/13 17:40, Dicebot wrote:
> I have quickly tested it and looks like asserts are not removed from unittest blocks in release builds, only from normal code. Which does not seem to be documented on dlang.org but was probably introduced exactly to prevent existing tests from breaking in release mode. I have just learned something new :)

Both version(assert) and version(release) are ignored inside unittest blocks. Consider the attached code: running with rdmd -unittest -release results in output:

     I don't respect release mode inside unittest blocks
     Release mode is disabled.

Which is interesting but irritating to say the least, because it means things like testing contracts are more difficult to unittest effectively.

OK, OK, I could do

     version(assert)
     {
         unittest { ... }
     }

... but that makes for an annoying separation out of unittests.


November 28, 2013
version(assert) is negated by -unittest at all actually:

import std.stdio;

void main()
{
    version ( assert )
    {
        writeln("errr");
    }
}

$ rdmd -release test.d
$ rdmd -release -unittest test.d
errr

That is so bad >_<
November 28, 2013
On 28/11/13 17:59, Dicebot wrote:
> version(assert) is negated by -unittest at all actually:
>
> import std.stdio;
>
> void main()
> {
>      version ( assert )
>      {
>          writeln("errr");
>      }
> }
>
> $ rdmd -release test.d
> $ rdmd -release -unittest test.d
> errr
>
> That is so bad >_<

Aaaaaack!! :-\

And to add to the confusion and inconsistency, it _does_ still strip in- and out-contracts of functions -- see e.g.:

    import std.stdio;

    void foo(int i)
    in
    {
        writeln("In contract enabled.");
    }
    out
    {
        writeln("Out contract enabled.");
    }
    body
    {
        writeln("This is the body of foo.");
    }

    void main()
    {
        foo(4);
    }

which will output all 3 messages in normal mode, but only the "body" one when compiled with -release.

This is the reason for my original help request -- an in-contract was triggering an AssertError in regular unittests, but not in release-mode unittests.
November 28, 2013
On Thursday, 28 November 2013 at 16:40:57 UTC, Dicebot wrote:
> I have quickly tested it and looks like asserts are not removed from unittest blocks in release builds, only from normal code. Which does not seem to be documented on dlang.org but was probably introduced exactly to prevent existing tests from breaking in release mode. I have just learned something new :)

I found this out too during the development of DUnit: https://github.com/nomad-software/dunit#notes

The asserts remain then the runtime just catches anything Throwable during unit test execution: https://github.com/D-Programming-Language/druntime/blob/master/src/core/runtime.d#L389-L419
November 28, 2013
I don't know what is the proper way to handle this but current situation is clearly worth a bugzilla entry. It is just weird.
November 28, 2013
On Thursday, 28 November 2013 at 17:22:20 UTC, Dicebot wrote:
> I don't know what is the proper way to handle this but current situation is clearly worth a bugzilla entry. It is just weird.

Maybe this is intended behaviour to handle testing AssertErrors in unit tests? How else could you test them.
November 28, 2013
On Thursday, 28 November 2013 at 17:28:56 UTC, Gary Willoughby wrote:
> On Thursday, 28 November 2013 at 17:22:20 UTC, Dicebot wrote:
>> I don't know what is the proper way to handle this but current situation is clearly worth a bugzilla entry. It is just weird.
>
> Maybe this is intended behaviour to handle testing AssertErrors in unit tests? How else could you test them.

It is tricky.

a) by not using asserts
b) by compiling unittest blocks in separate pass from main app

(a) breaks many existing tests in release, (b) does not fit well into existing compilation model but can be worth considering

There is also (c) of course : document the fact that -unittest overrides -release with big red words everywhere :)

I don't know what is good way to handle this. I know for sure that current situation is damn obscure though.
November 28, 2013
On 28/11/13 19:01, Dicebot wrote:
> On Thursday, 28 November 2013 at 17:28:56 UTC, Gary Willoughby wrote:
>> On Thursday, 28 November 2013 at 17:22:20 UTC, Dicebot wrote:
>>> I don't know what is the proper way to handle this but current situation is clearly worth a bugzilla entry. It is just weird.
>>
>> Maybe this is intended behaviour to handle testing AssertErrors in unit tests? How else could you test them.
>
> It is tricky.

The basic problem is this: if you compile something with -release -unittest, it will strip out all assert statements and contracts _in the main code_, while preserving assert statements etc. inside the unittest blocks.

Now, if you compile with -release -unittest, quite obviously you want the unittests to test the code _as compiled for release_, so the above is entirely correct behaviour.  It becomes problematic when you want to start testing behaviour that should take place in non-release mode but not in release mode (or vice versa).

The _reason_ it's problematic is because inside the unittest blocks, the
version(release) and version(assert) conditionals don't work as they do outside.
  So you can't use them inside the unittest { ... } blocks as conditionals for
what tests get run.

Now, I can see the case here for version(assert) -- after all, asserts are enabled inside the unittest blocks -- but not so much for version(release). After all, if release mode is enabled, it's enabled.  (Presumably the actual fact is that release-mode-style compilation is also disabled inside the unittest blocks.)

> a) by not using asserts
> b) by compiling unittest blocks in separate pass from main app
>
> (a) breaks many existing tests in release, (b) does not fit well into existing
> compilation model but can be worth considering
>
> There is also (c) of course : document the fact that -unittest overrides
> -release with big red words everywhere :)

I thought that it might also work to group together unittests that are conditional on version(release) or version(assert) or whatever, and put the unittest block _inside_ the version() { ... } scope.  But it turns out not.

I think it may actually be a bug in whether -release implies version(release). Try out the attached code.  (r)dmd -release release.d produces an executable that still reports that release mode is disabled.


November 28, 2013
On Thursday, 28 November 2013 at 18:26:15 UTC, Joseph Rushton Wakeling wrote:
> I think it may actually be a bug in whether -release implies version(release).
> Try out the attached code.  (r)dmd -release release.d produces an executable
> that still reports that release mode is disabled.

There is no pre-defined version(release) in D according to spec.