March 09, 2012
On Fri, 09 Mar 2012 11:12:44 -0000, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> On Friday, March 09, 2012 11:03:38 Regan Heath wrote:
>> On Fri, 09 Mar 2012 08:20:33 -0000, Chris Pons <cmpons@gmail.com> wrote:
>> > Any idea why, system("PAUSE") does work?
>>
>> As Jonathan says, assert throws AssertError... which means, if you wanted
>> to you could catch it, for example...
>>
>> module asserting;
>>
>> import std.stdio;
>> import core.exception;
>>
>> debug
>> {
>>      import std.c.windows.windows;
>>      extern (C) int kbhit();
>> }
>>
>> void main()
>> {
>>      try
>>      {
>>          assert(false, "testing assert");
>>      }
>>      catch(AssertError e)
>>      {
>>          debug
>>          {
>>              writefln("Assertion failed: %s", e);
>>              writefln("Press any key to exit...");
>>              while(!kbhit())
>>                  Sleep(1);
>>          }
>>          throw e;
>>      }
>> }
>>
>> So, for debug builds your exe will output the assertion manually, and wait
>> for a key press.  Then re-throw the assertion (resulting in the d runtime
>> outputting the assertion again).  In release, no pause.
>>
>> Note: kbhit and Sleep are windows specific (sleep would be the unix
>> equivalent, not sure on one for kbhit).
>
> Bet advised that catching anything not derived from Exception is generally a
> _bad_ idea (most of which are derived from Error), and AssertError is _not_
> derived from Exception but rather Error. AssertErrors are not guaranteed to
> invoke finally blocks, scope statements, or destructors. Your program is in an
> invalid state when you catch an Error. So, while it may work in this
> particular case, it is _not_ something that you should be doing in general. By
> far the worst thing to do would be to catch an Error and then continue
> executing. Errors are _supposed_ to kill your program.

Sound advice :)

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
March 09, 2012
On 2012-03-09 12:12, Jonathan M Davis wrote:
> On Friday, March 09, 2012 11:03:38 Regan Heath wrote:
>> On Fri, 09 Mar 2012 08:20:33 -0000, Chris Pons<cmpons@gmail.com>  wrote:
>>> Any idea why, system("PAUSE") does work?
>>
>> As Jonathan says, assert throws AssertError... which means, if you wanted
>> to you could catch it, for example...
>>
>> module asserting;
>>
>> import std.stdio;
>> import core.exception;
>>
>> debug
>> {
>>       import std.c.windows.windows;
>>       extern (C) int kbhit();
>> }
>>
>> void main()
>> {
>>       try
>>       {
>>           assert(false, "testing assert");
>>       }
>>       catch(AssertError e)
>>       {
>>           debug
>>           {
>>               writefln("Assertion failed: %s", e);
>>               writefln("Press any key to exit...");
>>               while(!kbhit())
>>                   Sleep(1);
>>           }
>>           throw e;
>>       }
>> }
>>
>> So, for debug builds your exe will output the assertion manually, and wait
>> for a key press.  Then re-throw the assertion (resulting in the d runtime
>> outputting the assertion again).  In release, no pause.
>>
>> Note: kbhit and Sleep are windows specific (sleep would be the unix
>> equivalent, not sure on one for kbhit).
>
> Bet advised that catching anything not derived from Exception is generally a
> _bad_ idea (most of which are derived from Error), and AssertError is _not_
> derived from Exception but rather Error. AssertErrors are not guaranteed to
> invoke finally blocks, scope statements, or destructors. Your program is in an
> invalid state when you catch an Error. So, while it may work in this
> particular case, it is _not_ something that you should be doing in general. By
> far the worst thing to do would be to catch an Error and then continue
> executing. Errors are _supposed_ to kill your program.
>
> - Jonathan M Davis

Then I would say it's bad design to have "assert" throw an AssertError. Whatever "assert" throws needs to be catchable, this is essential for writing unit test frameworks. It needs to be possible to write a unit test framework that catches all AssertErrors and prints a nice report at the end (or similar).

-- 
/Jacob Carlborg
March 09, 2012
On 09.03.2012 11:42, Chris Pons wrote:
> I am new to D and have been playing around with Assert. I figured that
> using a message with assert would be very helpful, but unfortunately
> when the message is printed to the console, the console closes and my
> program ends.
>
> Is there any way to get a more permanent message?


>
> I've tried adding system("PAUSE") and it doesn't have any effect.
>
> Is there any way I could have the assert function print the message to a
> file?
>
> I'm using VS2010 and Visual D if that is of any importance.
>
There is an option to redirect all console output to "Output" window. Right on the same window where you can choose a debugger (mago/visual studio) IRC.


-- 
Dmitry Olshansky
March 09, 2012
On 03/09/2012 01:20 PM, Jacob Carlborg wrote:
> On 2012-03-09 12:12, Jonathan M Davis wrote:
>> On Friday, March 09, 2012 11:03:38 Regan Heath wrote:
>>> On Fri, 09 Mar 2012 08:20:33 -0000, Chris Pons<cmpons@gmail.com> wrote:
>>>> Any idea why, system("PAUSE") does work?
>>>
>>> As Jonathan says, assert throws AssertError... which means, if you
>>> wanted
>>> to you could catch it, for example...
>>>
>>> module asserting;
>>>
>>> import std.stdio;
>>> import core.exception;
>>>
>>> debug
>>> {
>>> import std.c.windows.windows;
>>> extern (C) int kbhit();
>>> }
>>>
>>> void main()
>>> {
>>> try
>>> {
>>> assert(false, "testing assert");
>>> }
>>> catch(AssertError e)
>>> {
>>> debug
>>> {
>>> writefln("Assertion failed: %s", e);
>>> writefln("Press any key to exit...");
>>> while(!kbhit())
>>> Sleep(1);
>>> }
>>> throw e;
>>> }
>>> }
>>>
>>> So, for debug builds your exe will output the assertion manually, and
>>> wait
>>> for a key press. Then re-throw the assertion (resulting in the d runtime
>>> outputting the assertion again). In release, no pause.
>>>
>>> Note: kbhit and Sleep are windows specific (sleep would be the unix
>>> equivalent, not sure on one for kbhit).
>>
>> Bet advised that catching anything not derived from Exception is
>> generally a
>> _bad_ idea (most of which are derived from Error), and AssertError is
>> _not_
>> derived from Exception but rather Error. AssertErrors are not
>> guaranteed to
>> invoke finally blocks, scope statements, or destructors. Your program
>> is in an
>> invalid state when you catch an Error. So, while it may work in this
>> particular case, it is _not_ something that you should be doing in
>> general. By
>> far the worst thing to do would be to catch an Error and then continue
>> executing. Errors are _supposed_ to kill your program.
>>
>> - Jonathan M Davis
>
> Then I would say it's bad design to have "assert" throw an AssertError.
> Whatever "assert" throws needs to be catchable, this is essential for
> writing unit test frameworks. It needs to be possible to write a unit
> test framework that catches all AssertErrors and prints a nice report at
> the end (or similar).
>

This is a special case. Jonathan was specifically referring to the general case.
March 09, 2012
On 2012-03-09 15:13, Timon Gehr wrote:
> On 03/09/2012 01:20 PM, Jacob Carlborg wrote:
>> On 2012-03-09 12:12, Jonathan M Davis wrote:
>>> On Friday, March 09, 2012 11:03:38 Regan Heath wrote:
>>>> On Fri, 09 Mar 2012 08:20:33 -0000, Chris Pons<cmpons@gmail.com> wrote:
>>>>> Any idea why, system("PAUSE") does work?
>>>>
>>>> As Jonathan says, assert throws AssertError... which means, if you
>>>> wanted
>>>> to you could catch it, for example...
>>>>
>>>> module asserting;
>>>>
>>>> import std.stdio;
>>>> import core.exception;
>>>>
>>>> debug
>>>> {
>>>> import std.c.windows.windows;
>>>> extern (C) int kbhit();
>>>> }
>>>>
>>>> void main()
>>>> {
>>>> try
>>>> {
>>>> assert(false, "testing assert");
>>>> }
>>>> catch(AssertError e)
>>>> {
>>>> debug
>>>> {
>>>> writefln("Assertion failed: %s", e);
>>>> writefln("Press any key to exit...");
>>>> while(!kbhit())
>>>> Sleep(1);
>>>> }
>>>> throw e;
>>>> }
>>>> }
>>>>
>>>> So, for debug builds your exe will output the assertion manually, and
>>>> wait
>>>> for a key press. Then re-throw the assertion (resulting in the d
>>>> runtime
>>>> outputting the assertion again). In release, no pause.
>>>>
>>>> Note: kbhit and Sleep are windows specific (sleep would be the unix
>>>> equivalent, not sure on one for kbhit).
>>>
>>> Bet advised that catching anything not derived from Exception is
>>> generally a
>>> _bad_ idea (most of which are derived from Error), and AssertError is
>>> _not_
>>> derived from Exception but rather Error. AssertErrors are not
>>> guaranteed to
>>> invoke finally blocks, scope statements, or destructors. Your program
>>> is in an
>>> invalid state when you catch an Error. So, while it may work in this
>>> particular case, it is _not_ something that you should be doing in
>>> general. By
>>> far the worst thing to do would be to catch an Error and then continue
>>> executing. Errors are _supposed_ to kill your program.
>>>
>>> - Jonathan M Davis
>>
>> Then I would say it's bad design to have "assert" throw an AssertError.
>> Whatever "assert" throws needs to be catchable, this is essential for
>> writing unit test frameworks. It needs to be possible to write a unit
>> test framework that catches all AssertErrors and prints a nice report at
>> the end (or similar).
>>
>
> This is a special case. Jonathan was specifically referring to the
> general case.

Then way is it an error? I still want it to call finally blocks, scope statements, and destructors.

-- 
/Jacob Carlborg
March 09, 2012
On 03/09/2012 03:24 PM, Jacob Carlborg wrote:
> On 2012-03-09 15:13, Timon Gehr wrote:
>> On 03/09/2012 01:20 PM, Jacob Carlborg wrote:
>>> On 2012-03-09 12:12, Jonathan M Davis wrote:
>>>> On Friday, March 09, 2012 11:03:38 Regan Heath wrote:
>>>>> On Fri, 09 Mar 2012 08:20:33 -0000, Chris Pons<cmpons@gmail.com>
>>>>> wrote:
>>>>>> Any idea why, system("PAUSE") does work?
>>>>>
>>>>> As Jonathan says, assert throws AssertError... which means, if you
>>>>> wanted
>>>>> to you could catch it, for example...
>>>>>
>>>>> module asserting;
>>>>>
>>>>> import std.stdio;
>>>>> import core.exception;
>>>>>
>>>>> debug
>>>>> {
>>>>> import std.c.windows.windows;
>>>>> extern (C) int kbhit();
>>>>> }
>>>>>
>>>>> void main()
>>>>> {
>>>>> try
>>>>> {
>>>>> assert(false, "testing assert");
>>>>> }
>>>>> catch(AssertError e)
>>>>> {
>>>>> debug
>>>>> {
>>>>> writefln("Assertion failed: %s", e);
>>>>> writefln("Press any key to exit...");
>>>>> while(!kbhit())
>>>>> Sleep(1);
>>>>> }
>>>>> throw e;
>>>>> }
>>>>> }
>>>>>
>>>>> So, for debug builds your exe will output the assertion manually, and
>>>>> wait
>>>>> for a key press. Then re-throw the assertion (resulting in the d
>>>>> runtime
>>>>> outputting the assertion again). In release, no pause.
>>>>>
>>>>> Note: kbhit and Sleep are windows specific (sleep would be the unix
>>>>> equivalent, not sure on one for kbhit).
>>>>
>>>> Bet advised that catching anything not derived from Exception is
>>>> generally a
>>>> _bad_ idea (most of which are derived from Error), and AssertError is
>>>> _not_
>>>> derived from Exception but rather Error. AssertErrors are not
>>>> guaranteed to
>>>> invoke finally blocks, scope statements, or destructors. Your program
>>>> is in an
>>>> invalid state when you catch an Error. So, while it may work in this
>>>> particular case, it is _not_ something that you should be doing in
>>>> general. By
>>>> far the worst thing to do would be to catch an Error and then continue
>>>> executing. Errors are _supposed_ to kill your program.
>>>>
>>>> - Jonathan M Davis
>>>
>>> Then I would say it's bad design to have "assert" throw an AssertError.
>>> Whatever "assert" throws needs to be catchable, this is essential for
>>> writing unit test frameworks. It needs to be possible to write a unit
>>> test framework that catches all AssertErrors and prints a nice report at
>>> the end (or similar).
>>>
>>
>> This is a special case. Jonathan was specifically referring to the
>> general case.
>
> Then way is it an error?

So that it does not get caught by catch(Exception){}.

> I still want it to call finally blocks, scope
> statements, and destructors.
>

I have never actually observed that those are not run for assertion failures.
March 09, 2012
On Friday, March 09, 2012 16:07:10 Timon Gehr wrote:
> On 03/09/2012 03:24 PM, Jacob Carlborg wrote:
> > On 2012-03-09 15:13, Timon Gehr wrote:
> >> On 03/09/2012 01:20 PM, Jacob Carlborg wrote:
> >>> On 2012-03-09 12:12, Jonathan M Davis wrote:
> >>>> On Friday, March 09, 2012 11:03:38 Regan Heath wrote:
> >>>>> On Fri, 09 Mar 2012 08:20:33 -0000, Chris Pons<cmpons@gmail.com>
> >>>>> 
> >>>>> wrote:
> >>>>>> Any idea why, system("PAUSE") does work?
> >>>>> 
> >>>>> As Jonathan says, assert throws AssertError... which means, if you
> >>>>> wanted
> >>>>> to you could catch it, for example...
> >>>>> 
> >>>>> module asserting;
> >>>>> 
> >>>>> import std.stdio;
> >>>>> import core.exception;
> >>>>> 
> >>>>> debug
> >>>>> {
> >>>>> import std.c.windows.windows;
> >>>>> extern (C) int kbhit();
> >>>>> }
> >>>>> 
> >>>>> void main()
> >>>>> {
> >>>>> try
> >>>>> {
> >>>>> assert(false, "testing assert");
> >>>>> }
> >>>>> catch(AssertError e)
> >>>>> {
> >>>>> debug
> >>>>> {
> >>>>> writefln("Assertion failed: %s", e);
> >>>>> writefln("Press any key to exit...");
> >>>>> while(!kbhit())
> >>>>> Sleep(1);
> >>>>> }
> >>>>> throw e;
> >>>>> }
> >>>>> }
> >>>>> 
> >>>>> So, for debug builds your exe will output the assertion manually, and
> >>>>> wait
> >>>>> for a key press. Then re-throw the assertion (resulting in the d
> >>>>> runtime
> >>>>> outputting the assertion again). In release, no pause.
> >>>>> 
> >>>>> Note: kbhit and Sleep are windows specific (sleep would be the unix equivalent, not sure on one for kbhit).
> >>>> 
> >>>> Bet advised that catching anything not derived from Exception is
> >>>> generally a
> >>>> _bad_ idea (most of which are derived from Error), and AssertError is
> >>>> _not_
> >>>> derived from Exception but rather Error. AssertErrors are not
> >>>> guaranteed to
> >>>> invoke finally blocks, scope statements, or destructors. Your program
> >>>> is in an
> >>>> invalid state when you catch an Error. So, while it may work in this
> >>>> particular case, it is _not_ something that you should be doing in
> >>>> general. By
> >>>> far the worst thing to do would be to catch an Error and then continue
> >>>> executing. Errors are _supposed_ to kill your program.
> >>>> 
> >>>> - Jonathan M Davis
> >>> 
> >>> Then I would say it's bad design to have "assert" throw an AssertError. Whatever "assert" throws needs to be catchable, this is essential for writing unit test frameworks. It needs to be possible to write a unit test framework that catches all AssertErrors and prints a nice report at the end (or similar).
> >> 
> >> This is a special case. Jonathan was specifically referring to the general case.
> > 
> > Then way is it an error?
> 
> So that it does not get caught by catch(Exception){}.
> 
> > I still want it to call finally blocks, scope
> > statements, and destructors.
> 
> I have never actually observed that those are not run for assertion failures.

The current implementation may not skip them, but if so, that might actually be a bug. Errors are not intended to be recoverable, so you can't rely on them hitting finally blocks, scope statements, or destructors. They may very well do so at present. While it's not guaranteed that they will, I'm not sure that it's guaranteed that they _won't_. So, it may or may not be a bug if they do.

It was never intended that AssertError or any other Error be particularly catchable, but it's also true that D is a systems programming language, so it'll let you do stuff which is unsafe, so if you know what you're doing, then there are circumstances where you can get away with (unit testing is one example of where catching AssertErrors might make sense). But you have to know what you're doing, since it's _not_ safe.

- Jonathan M Davis
March 09, 2012
On Fri, Mar 09, 2012 at 08:56:10AM -0800, Jonathan M Davis wrote:
> On Friday, March 09, 2012 16:07:10 Timon Gehr wrote:
> > On 03/09/2012 03:24 PM, Jacob Carlborg wrote:
[...]
> > > I still want it to call finally blocks, scope statements, and destructors.
> > 
> > I have never actually observed that those are not run for assertion failures.
> 
> The current implementation may not skip them, but if so, that might actually be a bug. Errors are not intended to be recoverable, so you can't rely on them hitting finally blocks, scope statements, or destructors. They may very well do so at present. While it's not guaranteed that they will, I'm not sure that it's guaranteed that they _won't_. So, it may or may not be a bug if they do.
> 
> It was never intended that AssertError or any other Error be particularly catchable, but it's also true that D is a systems programming language, so it'll let you do stuff which is unsafe, so if you know what you're doing, then there are circumstances where you can get away with (unit testing is one example of where catching AssertErrors might make sense). But you have to know what you're doing, since it's _not_ safe.
[...]

This opens up the question of, what's the *recommended* way of writing unittests that check for these sorts of stuff?

For example, I believe in being thorough in unit tests, so I like to use them to verify that the complicated in-contract I just wrote actually prevents the erroneous calls that I *think* it prevents. But if catching AssertError's may leave the program in an undefined state, then that pretty much invalidates any further testing past that point (the program may appear to work when compiled with -funittest but actually fail in release mode).

I agree, though, that catching Errors outside of unittests is a very, very bad idea in general.


T

-- 
Everybody talks about it, but nobody does anything about it!  -- Mark Twain
March 09, 2012
On 03/09/2012 05:56 PM, Jonathan M Davis wrote:
> The current implementation may not skip them, but if so, that might actually
> be a bug. Errors are not intended to be recoverable, so you can't rely on them
> hitting finally blocks, scope statements, or destructors. They may very well do
> so at present. While it's not guaranteed that they will, I'm not sure that
> it's guaranteed that they _won't_. So, it may or may not be a bug if they do.
>
> It was never intended that AssertError or any other Error be particularly
> catchable, but it's also true that D is a systems programming language, so
> it'll let you do stuff which is unsafe, so if you know what you're doing, then
> there are circumstances where you can get away with (unit testing is one
> example of where catching AssertErrors might make sense). But you have to know
> what you're doing, since it's _not_ safe.
>
> - Jonathan M Davis

AssertErrors must be recoverable because of the way contracts work.
March 09, 2012
On Fri, Mar 09, 2012 at 07:23:20PM +0100, Timon Gehr wrote:
> On 03/09/2012 05:56 PM, Jonathan M Davis wrote:
[...]
> >It was never intended that AssertError or any other Error be particularly catchable, but it's also true that D is a systems programming language, so it'll let you do stuff which is unsafe, so if you know what you're doing, then there are circumstances where you can get away with (unit testing is one example of where catching AssertErrors might make sense). But you have to know what you're doing, since it's _not_ safe.
> >
> >- Jonathan M Davis
> 
> AssertErrors must be recoverable because of the way contracts work.

Are you referring to contract AssertErrors in unittests, or in general?

In general, I think contracts *should* terminate the program with extreme prejudice when they fail. It represents assumptions about internal consistency being broken, which makes it unsafe to do otherwise.

But in unittests where these assumptions are deliberately broken (to ensure the contract does what you think it does), it makes sense to be able to "recover" from AssertErrors.


T

-- 
Everybody talks about it, but nobody does anything about it!  -- Mark Twain