www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Assert and the optional Message

reply "Chris Pons" <cmpons gmail.com> writes:
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.
Mar 08 2012
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, March 09, 2012 08:42:25 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.

Assertions throw an AssertError when they fail. No statements after the assertion failure will be run. Rather, the AssertError will unwind the stack until it exits main. When it exits main, it gets caught, and it's printed out. Whatever message you gave assert it is part of that. It has nothing to do with files. If you want to specifically write to a file, then you're going to have to check with your own function, write to the file if it fails, and then assert afterwards. And I'd argue that that is horribly ugly and should be avoided. Screwing with your program like that just because your dev environment is annoying enough to close its console window when the program exits isn't a good idea. What you should almost certainly be doing is changing Visual Studio's settings so that it doesn't close the Window when the program exits. I know that it's possible. I've done it, but I rarely use Windows, and I don't remember what you have to do. So, unfortunately, I can't be of much help to you there, but that's the solution that you should almost certainly be using. If no one else around here can post how to do it, then I would think that you'd be able to find how via google easily enough. - Jonathan M Davis
Mar 08 2012
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/09/2012 03:02 AM, Jonathan M Davis wrote:

 contorting your program to try and print assert
 messages to a file just because VisualD has problems with closing the 

 you is a _bad_ idea IMHO.

Absolutely! Inserting lines at the end of programs is not the correct solution to the problem at hand. Those lines have nothing to do with the program that is being written.
 If it really has that problem, and you really need
 to see the assertion without running the debugger on it, I'd advise just
 running the program on the command line.

+1. That is a correct solution because it does not maim the very program that is being developed.
 - Jonathan M Davis

Ali
Mar 09 2012
prev sibling next sibling parent "Chris Pons" <cmpons gmail.com> writes:
Ok, thank you for the advice. I will look into it.
Mar 09 2012
prev sibling next sibling parent reply "Chris Pons" <cmpons gmail.com> writes:
Any idea why, system("PAUSE") does work?
Mar 09 2012
parent reply Jacob Carlborg <doob me.com> writes:
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
Mar 09 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
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.
Mar 09 2012
parent reply Jacob Carlborg <doob me.com> writes:
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
Mar 09 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
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.
Mar 09 2012
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
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.
Mar 09 2012
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 03/09/2012 07:37 PM, H. S. Teoh wrote:
 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

'in' contracts must catch assertion failures because it is enough if one of them passes. class Foo{ void foo(int x)in{assert(x==0);}body{} } class Bar: Foo{ void foo(int x)in{assert(x==1);}body{} } void main(){ Bar bar = new Bar; bar.foo(0); // ok bar.foo(1); // ok }
Mar 09 2012
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-03-09 20:06, Jonathan M Davis wrote:

 In what way? Yes, they're _catchable_, but everything that was on the unwound
 portion of the stack is now in an undefined state. So, recovering from the
 AssertError and continuing execution doesn't work. So, a handler can catch the
 AssertError and do something before letting it kill the program, but portions
 of the program are definitely in an undefined state when an AssertError is
 caught. The closer the catch point is to the throw point, the less of an issue
 that is, but unless you can guarantee that no destructors, scope statements,
 or finally blocks were between the throw point and the catch point, then some
 portion of the program is in an undefined state, and continuing program
 execution is a bad idea. It _is_ possible to catch an AssertError, but you
 have to be very careful about what you do after that.

 I'm not aware of anything in contracts which would involve catching an
 AssertError and then continuing execution. When a contract fails, it's going
 to kill the program just like any other assertion failure does. So, I'm not
 quite sure what you're referring to.

 - Jonathan M Davis

This might be how it works today, but I think it's a broken design. AssertError MUST be SAFELY catchable to be able to write unit testing frameworks. -- /Jacob Carlborg
Mar 10 2012
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-03-10 18:08, Jonathan M Davis wrote:

 I honestly don't think that Walter even considered unit testing frameworks
 when he came up with the design. He built unit tests into the language. So,
 from his point of view, why would you need a unit testing framework? He
 probably didn't even consider it.

I don't think he considered unit testing frameworks either.
 And if you really want to do your own unit testing framework, maybe you should
 just create your own custom assertion functions which throw something other
 than AssertError - though if they don't throw Errors, then any unittest blocks
 with a catch(Exception() {} in them may not work properly, so that's not
 necessarily all that great a solution either, depending.

 - Jonathan M Davis

Yeah, exactly. And it feels a bit stupid to duplicate the assert statement just to throw something that isn't an AssertError. -- /Jacob Carlborg
Mar 11 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-03-11 22:12, Jonathan M Davis wrote:
 On Sunday, March 11, 2012 13:13:58 Jacob Carlborg wrote:

 Yeah, exactly. And it feels a bit stupid to duplicate the assert
 statement just to throw something that isn't an AssertError.

Not to say that it's what you have to do, but I _would_ point out that all of the unit testing frameworks that I've seen in other langages _do_ create their own custom assert statements, so that wouldn't be abnormal at all. Now, in C++, assert doesn't throw anything (I don't remember if it does in Java or not), and there's no built-in unit testing framework using assert, so it's not as weird to use your own as it would be in D, but it's still not uncommon in unit testing frameworks to define a set of custom assertion functions specfically for unit testing. - Jonathan M Davis

They usually define "assertEqual", "assertNotEqual" and so on. But basically all unit testing frameworks also have a basic "assert". I see know reason why the basic assert needs to be redefined. -- /Jacob Carlborg
Mar 12 2012
prev sibling next sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-03-12 15:08, Steven Schveighoffer wrote:
 My thoughts on assert/unit test:

 1. AssertError (and any other Error) should not be caught by normal user
 code. Ever. It should only be caught by the runtime. However, the
 handler in the runtime could provide a hook specific to the
 OS/application and whether it is running unit tests. Obviously the hook
 would have to be set up before main runs, so that is an issue, but you
 may just need to alter the runtime in that case.

That's a good idea.
 2. Any assert in a unit test block should halt execution in the unit
 test block. Often subsequent asserts are just noise because you are
 depending on the conditions that make the prior asserts pass.
 3. unit test blocks should be tested individually, not on a module-level
 IMO. I'm not sure if this currently is the case.
 4. Jonathan's statement that the program is in an "undefined state" is
 not quite true. It's in an unwound state, but not undefined. Certainly,
 you should be able to continue running more unit tests. Unit tests
 should be a) unaffected by other unit test blocks, and b) should not
 affect the running of any other code in any way. Otherwise, a program
 would run differently depending on whether unit tests ran.
 5. If *any* unit tests fail, the main() function should not be run. If
 an assert is triggered while running main(), the program should exit.

 -Steve

Makes sense. -- /Jacob Carlborg
Mar 12 2012
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-03-12 15:08, Steven Schveighoffer wrote:
 I contended that unit test asserts should result in a hook that by
 default kills the program, but could be hooked into a unit testing
 handler. But the consensus was just to switch back to the original
 behavior (all asserts kill the program). If you look through the phobos
 or druntime mailing list archives you might find the relevant
 conversations. It may even be so old that the archives don't have it (it
 was on a private mailing list on Andrei's server for a time).

 My thoughts on assert/unit test:

 1. AssertError (and any other Error) should not be caught by normal user
 code. Ever. It should only be caught by the runtime. However, the
 handler in the runtime could provide a hook specific to the
 OS/application and whether it is running unit tests. Obviously the hook
 would have to be set up before main runs, so that is an issue, but you
 may just need to alter the runtime in that case.

I had a look through the source code of druntime and found "onAssertError". I don't know if it's used or not but sounds exactly like the function I need. But unfortunately the function to set the assert handler is deprecated. http://dlang.org/phobos/core_exception.html#onAssertError http://dlang.org/phobos/core_exception.html#setAssertHandler -- /Jacob Carlborg
Mar 12 2012
prev sibling next sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-03-09 17:56, 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

"might make sense". It makes perfectly sense to catch AssertErros in a unit testing framework. -- /Jacob Carlborg
Mar 10 2012
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-03-09 17:56, 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

If it's not safe to catch AssertErrors, how is the executable supposed to be able to continue a unit test run when an AssertError has been thrown? I'm referring to the suggested changes that a unit test run should be able to continue in other modules even if an AssertError has been thrown. It seems to be issue 5283: http://d.puremagic.com/issues/show_bug.cgi?id=5283 -- /Jacob Carlborg
Mar 10 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-03-10 17:58, Jonathan M Davis wrote:

 2. As long as unit tests are properly isolated, then it's unlikely to be a big
 issue, and even if it _is_ problem, it's only a problem as long as tests are
 failing. So, while this may cause problems in some cases, it's still arguably
 worth it, since the _first_ test failure is still completely valid (as it is
 now), and the rest are _likely_ to be valid, so you'd generally be getting
 more information than before.

Yeah, it's only a problem when a test is failing. But I don't want the whole unit test run to potentially crash because of a failing unit test.
 If it's a big enough problem, it could probably be made so that AssertErrors
 are treated differently in unit tests such that they _are_ guaranteed to hit
 destructors, scope statements, and finally. But the basic design of Errors is
 that they're supposed to be unrecoverable, so skipping all of those isn't
 generally an issue. And given that can get Errors thrown from nothrow
 functions, running them might actually do funny things in some cases, because
 the assumptions surrounding nothrow have been effectively violated.

 - Jonathan M Davis

I understand that you're not supposed to catch errors but this needs to be fixed somehow. I don't know what's the best solution would be but I do know we need to find one. -- /Jacob Carlborg
Mar 11 2012
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-03-09 18:59, H. S. Teoh wrote:

 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.

I don't see what's so bad in making AssertError an exception instead of an error. -- /Jacob Carlborg
Mar 10 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-03-10 17:48, Jonathan M Davis wrote:
 On Saturday, March 10, 2012 16:53:42 Jacob Carlborg wrote:
 On 2012-03-09 18:59, H. S. Teoh wrote:
 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.

I don't see what's so bad in making AssertError an exception instead of an error.

Then catch(Excetion e) {} would catch it. This would be a huge problem in normal code. Assertions are supposed to kill the program. This is specifically mentioned in TDPL. - Jonathan M Davis

Maybe so. But the current design is broken and need to be fixed somehow. -- /Jacob Carlborg
Mar 11 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, March 09, 2012 09:20:33 Chris Pons wrote:
 Any idea why, system("PAUSE") does work?

Because that line never gets run. A failed assertion throws an AssertError which skips everything until it gets handled by the runtime after it exits main. So, if you have assert(condition); system("PAUSE"); the second line will never execute as long as condition is false. - Jonathan M Davis
Mar 09 2012
prev sibling next sibling parent "Mars" <- -.-> writes:
On Friday, 9 March 2012 at 07:55:56 UTC, Jonathan M Davis wrote:
 What you should almost certainly be doing is changing Visual 
 Studio's settings
 so that it doesn't close the Window when the program exits. I 
 know that it's
 possible. I've done it, but I rarely use Windows, and I don't 
 remember what
 you have to do. So, unfortunately, I can't be of much help to 
 you there, but
 that's the solution that you should almost certainly be using. 
 If no one else
 around here can post how to do it, then I would think that 
 you'd be able to
 find how via google easily enough.

 - Jonathan M Davis

Are you sure you've tested this with D? Because VisualD doesn't support that yet, afaik.
Mar 09 2012
prev sibling next sibling parent "Regan Heath" <regan netmail.co.nz> writes:
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). Regan Heath -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Mar 09 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, March 09, 2012 10:55:10 Mars wrote:
 On Friday, 9 March 2012 at 07:55:56 UTC, Jonathan M Davis wrote:
 What you should almost certainly be doing is changing Visual
 Studio's settings
 so that it doesn't close the Window when the program exits. I
 know that it's
 possible. I've done it, but I rarely use Windows, and I don't
 remember what
 you have to do. So, unfortunately, I can't be of much help to
 you there, but
 that's the solution that you should almost certainly be using.
 If no one else
 around here can post how to do it, then I would think that
 you'd be able to
 find how via google easily enough.
 
 - Jonathan M Davis

Are you sure you've tested this with D? Because VisualD doesn't support that yet, afaik.

I've never used Visual Studio with D, and I wouldn't expect telling it not close the window after execution to be any different in D than it is in C++, but I don't know. Regardless, contorting your program to try and print assert messages to a file just because VisualD has problems with closing the Window on you is a _bad_ idea IMHO. If it really has that problem, and you really need to see the assertion without running the debugger on it, I'd advise just running the program on the command line. - Jonathan M Davis
Mar 09 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
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
Mar 09 2012
prev sibling next sibling parent Mike Parker <aldacron gmail.com> writes:
On 3/9/2012 4:42 PM, 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.

In this case, you can just open up a command window, navigate to your executable directory, and execute the app manually from the command line. Then you don't have to worry about it closing. Of course, this doesn't work if you are using the default output directories for your executable, but you have resources in the working directory. When I use VisualD, I generally configure my executables to all go a single bin directory (foo.exe for release, foo_dbg.exe for Debug). Then I keep a command window open in the background. That way, if I need to run from the command line, it's easy to do so without any copying around.
Mar 09 2012
prev sibling next sibling parent "Regan Heath" <regan netmail.co.nz> writes:
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/
Mar 09 2012
prev sibling next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
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.

Right on the same window where you can choose a debugger (mago/visual studio) IRC. -- Dmitry Olshansky
Mar 09 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
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
Mar 09 2012
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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
Mar 09 2012
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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
Mar 09 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, March 09, 2012 09:59:42 H. S. Teoh wrote:
 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).

If you're testing that contracts throw when they're supposed to, you're going to have to be very careful. Depending on what code is involved, catching the AssertError could have no problems whatsoever. For example assertThrown!AssertError(func(5)); void func(int i) in { assert(i == 2); } body {} wouldn't be a problem at all. There are no destructors, scope statements, or finally blocks involved. But something like assertThrown!AssertError(foo(5)); int foo(int i) out(result) { assert(result = == 2); } body { Bar bar; return i; } could have issues if Bar has a constructor than needs to run. You just need to understand that destructors, scope statements, and finally blocks are not guaranteed to be run if an Error is thrown and avoid catching Errors in cases where they'd be skipped (or know enough about the state that the program would be in if they _were_ skipped to know that it's not going to cause problems). Personally, I think that checking contracts is overkill, but you can do it if you're careful. - Jonathan M Davis
Mar 09 2012
prev sibling next sibling parent "Chris Pons" <cmpons gmail.com> writes:
You are right, there is also an option to "Pause when program 
finishes".

I never saw it until now. Thank you for all the replies.

On Friday, 9 March 2012 at 13:39:02 UTC, Dmitry Olshansky wrote:
 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.

window. Right on the same window where you can choose a debugger (mago/visual studio) IRC.

Mar 09 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, March 09, 2012 19:23:20 Timon Gehr wrote:
 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.

In what way? Yes, they're _catchable_, but everything that was on the unwound portion of the stack is now in an undefined state. So, recovering from the AssertError and continuing execution doesn't work. So, a handler can catch the AssertError and do something before letting it kill the program, but portions of the program are definitely in an undefined state when an AssertError is caught. The closer the catch point is to the throw point, the less of an issue that is, but unless you can guarantee that no destructors, scope statements, or finally blocks were between the throw point and the catch point, then some portion of the program is in an undefined state, and continuing program execution is a bad idea. It _is_ possible to catch an AssertError, but you have to be very careful about what you do after that. I'm not aware of anything in contracts which would involve catching an AssertError and then continuing execution. When a contract fails, it's going to kill the program just like any other assertion failure does. So, I'm not quite sure what you're referring to. - Jonathan M Davis
Mar 09 2012
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Mar 09, 2012 at 01:37:38PM -0500, Jonathan M Davis wrote:
 On Friday, March 09, 2012 09:59:42 H. S. Teoh wrote:

 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).

If you're testing that contracts throw when they're supposed to, you're going to have to be very careful. Depending on what code is involved, catching the AssertError could have no problems whatsoever. For example assertThrown!AssertError(func(5)); void func(int i) in { assert(i == 2); } body {} wouldn't be a problem at all. There are no destructors, scope statements, or finally blocks involved. But something like assertThrown!AssertError(foo(5)); int foo(int i) out(result) { assert(result = == 2); } body { Bar bar; return i; } could have issues if Bar has a constructor than needs to run. You just need to understand that destructors, scope statements, and finally blocks are not guaranteed to be run if an Error is thrown and avoid catching Errors in cases where they'd be skipped (or know enough about the state that the program would be in if they _were_ skipped to know that it's not going to cause problems). Personally, I think that checking contracts is overkill, but you can do it if you're careful.

Hmph. Well, then that defeats the purpose of checking contracts, because checking contracts is only justifiable if it's complex enough, which means that it's liable to involve things like dtors and scope statements. It's silly to want to check a trivial contract like assert(x>0);, because if something *that* simple can go wrong, then so can the unittest, so you're not proving anything at all. But this isn't that big a deal. One could argue that if a contract is convoluted enough to warrant a unit test, then perhaps most (or all) of its complexity should be factored out into a separate, unit tested function, which is then just invoked from the contract. (I find this a bit ironic, since TDPL states that the reason contracts allow statements is so that complicated conditions can be tested for, rather than being limited to just a single expression, as is the case in most other languages that support DbC. Now it seems that simple contracts are the way to go.) T -- MASM = Mana Ada Sistem, Man!
Mar 09 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 03/09/2012 08:29 PM, H. S. Teoh wrote:
 On Fri, Mar 09, 2012 at 01:37:38PM -0500, Jonathan M Davis wrote:
 On Friday, March 09, 2012 09:59:42 H. S. Teoh wrote:

 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).

If you're testing that contracts throw when they're supposed to, you're going to have to be very careful. Depending on what code is involved, catching the AssertError could have no problems whatsoever. For example assertThrown!AssertError(func(5)); void func(int i) in { assert(i == 2); } body {} wouldn't be a problem at all. There are no destructors, scope statements, or finally blocks involved. But something like assertThrown!AssertError(foo(5)); int foo(int i) out(result) { assert(result = == 2); } body { Bar bar; return i; } could have issues if Bar has a constructor than needs to run. You just need to understand that destructors, scope statements, and finally blocks are not guaranteed to be run if an Error is thrown and avoid catching Errors in cases where they'd be skipped (or know enough about the state that the program would be in if they _were_ skipped to know that it's not going to cause problems). Personally, I think that checking contracts is overkill, but you can do it if you're careful.

Hmph. Well, then that defeats the purpose of checking contracts, because checking contracts is only justifiable if it's complex enough, which means that it's liable to involve things like dtors and scope statements. It's silly to want to check a trivial contract like assert(x>0);, because if something *that* simple can go wrong, then so can the unittest, so you're not proving anything at all. But this isn't that big a deal. One could argue that if a contract is convoluted enough to warrant a unit test, then perhaps most (or all) of its complexity should be factored out into a separate, unit tested function, which is then just invoked from the contract. (I find this a bit ironic, since TDPL states that the reason contracts allow statements is so that complicated conditions can be tested for, rather than being limited to just a single expression, as is the case in most other languages that support DbC. Now it seems that simple contracts are the way to go.) T

Jonathan is just speculating. And I think he is wrong.
Mar 09 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 03/09/2012 10:43 PM, Jonathan M Davis wrote:
...
 Jonathan is just speculating. And I think he is wrong.

Speculating about what? - Jonathan M Davis

About how assertion failures affect struct destructors, finally statements and scope statements. If they wouldn't be executed upon thrown AssertError, then a _passing_ in contract could screw up the program state. Furthermore, the implementation does execute them.
Mar 09 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, March 09, 2012 11:29:43 H. S. Teoh wrote:
 Hmph. Well, then that defeats the purpose of checking contracts, because
 checking contracts is only justifiable if it's complex enough, which
 means that it's liable to involve things like dtors and scope
 statements. It's silly to want to check a trivial contract like
 assert(x>0);, because if something *that* simple can go wrong, then so
 can the unittest, so you're not proving anything at all.
 
 But this isn't that big a deal. One could argue that if a contract is
 convoluted enough to warrant a unit test, then perhaps most (or all) of
 its complexity should be factored out into a separate, unit tested
 function, which is then just invoked from the contract.
 
 (I find this a bit ironic, since TDPL states that the reason contracts
 allow statements is so that complicated conditions can be tested for,
 rather than being limited to just a single expression, as is the case in
 most other languages that support DbC. Now it seems that simple
 contracts are the way to go.)

It's only an issue if you're trying to test your contracts, and I don't think that that's a very typical thing to do. That's kind of like writing tests to test your unit tests. And the ability to have complicated conditions in contracts is still better than having a single expression even if you do want to test your more complicated contracts, because it allows you to have multiple assertions rather than just one expression, and then you know _which_ condition was false and can provide a decent error message (e.g. one which included the values of some of the arguments) instead of having one big condition that either succeeds or fails and really doesn't give you any useful information beyond that (like you get with template constraints). - Jonathan M Davis
Mar 09 2012
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Mar 09, 2012 at 02:38:48PM -0500, Jonathan M Davis wrote:
 On Friday, March 09, 2012 11:29:43 H. S. Teoh wrote:
 Hmph. Well, then that defeats the purpose of checking contracts,
 because checking contracts is only justifiable if it's complex
 enough, which means that it's liable to involve things like dtors
 and scope statements. It's silly to want to check a trivial contract
 like assert(x>0);, because if something *that* simple can go wrong,
 then so can the unittest, so you're not proving anything at all.
 
 But this isn't that big a deal. One could argue that if a contract
 is convoluted enough to warrant a unit test, then perhaps most (or
 all) of its complexity should be factored out into a separate, unit
 tested function, which is then just invoked from the contract.
 
 (I find this a bit ironic, since TDPL states that the reason
 contracts allow statements is so that complicated conditions can be
 tested for, rather than being limited to just a single expression,
 as is the case in most other languages that support DbC. Now it
 seems that simple contracts are the way to go.)

It's only an issue if you're trying to test your contracts, and I don't think that that's a very typical thing to do. That's kind of like writing tests to test your unit tests.

I was thinking of cases like a function that performs complicated numerical computations, and the out contract is to assert that the results make sense (e.g., you're not getting total garbage due to accumulated roundoff errors). Sometimes checking if the results are consistent is non-trivial. But then again, if it's *that* non-trivial, it really shouldn't be directly inside a contract, but in a separate function.
 And the ability to have complicated conditions in contracts is still
 better than having a single expression even if you do want to test
 your more complicated contracts, because it allows you to have
 multiple assertions rather than just one expression, and then you know
 _which_ condition was false and can provide a decent error message
 (e.g. one which included the values of some of the arguments) instead
 of having one big condition that either succeeds or fails and really
 doesn't give you any useful information beyond that (like you get with
 template constraints).

I wasn't arguing for using only a single expression in contracts at all. I was just commenting that allowing statements makes it possible to do a whole lot more, including stuff that perhaps one shouldn't be doing inside a contract. But I've always believed in flexibility vs. unnecessary restrictions. Preventing the programmer from doing stupid things will also prevent her from doing clever things, as the saying goes. T -- MAS = Mana Ada Sistem?
Mar 09 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, March 09, 2012 22:03:11 Timon Gehr wrote:
 On 03/09/2012 08:29 PM, H. S. Teoh wrote:
 On Fri, Mar 09, 2012 at 01:37:38PM -0500, Jonathan M Davis wrote:
 On Friday, March 09, 2012 09:59:42 H. S. Teoh wrote:

 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).

If you're testing that contracts throw when they're supposed to, you're going to have to be very careful. Depending on what code is involved, catching the AssertError could have no problems whatsoever. For example assertThrown!AssertError(func(5)); void func(int i) in { assert(i == 2); } body {} wouldn't be a problem at all. There are no destructors, scope statements, or finally blocks involved. But something like assertThrown!AssertError(foo(5)); int foo(int i) out(result) { assert(result = == 2); } body { Bar bar; return i; } could have issues if Bar has a constructor than needs to run. You just need to understand that destructors, scope statements, and finally blocks are not guaranteed to be run if an Error is thrown and avoid catching Errors in cases where they'd be skipped (or know enough about the state that the program would be in if they _were_ skipped to know that it's not going to cause problems). Personally, I think that checking contracts is overkill, but you can do it if you're careful.

[...] Hmph. Well, then that defeats the purpose of checking contracts, because checking contracts is only justifiable if it's complex enough, which means that it's liable to involve things like dtors and scope statements. It's silly to want to check a trivial contract like assert(x>0);, because if something *that* simple can go wrong, then so can the unittest, so you're not proving anything at all. But this isn't that big a deal. One could argue that if a contract is convoluted enough to warrant a unit test, then perhaps most (or all) of its complexity should be factored out into a separate, unit tested function, which is then just invoked from the contract. (I find this a bit ironic, since TDPL states that the reason contracts allow statements is so that complicated conditions can be tested for, rather than being limited to just a single expression, as is the case in most other languages that support DbC. Now it seems that simple contracts are the way to go.) T

Jonathan is just speculating. And I think he is wrong.

Speculating about what? - Jonathan M Davis
Mar 09 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, March 09, 2012 22:48:25 Timon Gehr wrote:
 On 03/09/2012 10:43 PM, Jonathan M Davis wrote:
 ...
 
 Jonathan is just speculating. And I think he is wrong.

Speculating about what? - Jonathan M Davis

About how assertion failures affect struct destructors, finally statements and scope statements. If they wouldn't be executed upon thrown AssertError, then a _passing_ in contract could screw up the program state. Furthermore, the implementation does execute them.

It's not speculation. There's no guessing involved. It's what I've understood the rules of the language to be. But I asked on dmd-internals to verify it, and Walter has stated that it just so happens that the destructors, scope statements, and finally blocks do currently get run for non-Exception exceptions, but it's not guaranteed: http://forum.dlang.org/post/4F5AE8EC.4040408 digitalmars.com - Jonathan M Davis
Mar 09 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, March 10, 2012 16:53:42 Jacob Carlborg wrote:
 On 2012-03-09 18:59, H. S. Teoh wrote:
 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.

I don't see what's so bad in making AssertError an exception instead of an error.

Then catch(Excetion e) {} would catch it. This would be a huge problem in normal code. Assertions are supposed to kill the program. This is specifically mentioned in TDPL. - Jonathan M Davis
Mar 10 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, March 10, 2012 16:52:43 Jacob Carlborg wrote:
 On 2012-03-09 17:56, 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

If it's not safe to catch AssertErrors, how is the executable supposed to be able to continue a unit test run when an AssertError has been thrown? I'm referring to the suggested changes that a unit test run should be able to continue in other modules even if an AssertError has been thrown. It seems to be issue 5283: http://d.puremagic.com/issues/show_bug.cgi?id=5283

1. Assertions are treated a bit differently in unit tests. I don't remember what the exact differences are at the moment (and I think that they've changed over time), but they're not completely normal from what I recall. So, the situation may or may not be somewhat different in unit tests. At minimum, they get left in when -unittest is used, even if -release is used, and I believe that they have a somewhat different handler. They probably function the same with regards to destructors, scope statements, and finally though. 2. As long as unit tests are properly isolated, then it's unlikely to be a big issue, and even if it _is_ problem, it's only a problem as long as tests are failing. So, while this may cause problems in some cases, it's still arguably worth it, since the _first_ test failure is still completely valid (as it is now), and the rest are _likely_ to be valid, so you'd generally be getting more information than before. If it's a big enough problem, it could probably be made so that AssertErrors are treated differently in unit tests such that they _are_ guaranteed to hit destructors, scope statements, and finally. But the basic design of Errors is that they're supposed to be unrecoverable, so skipping all of those isn't generally an issue. And given that can get Errors thrown from nothrow functions, running them might actually do funny things in some cases, because the assumptions surrounding nothrow have been effectively violated. - Jonathan M Davis
Mar 10 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, March 10, 2012 17:03:43 Jacob Carlborg wrote:
 On 2012-03-09 20:06, Jonathan M Davis wrote:
 In what way? Yes, they're _catchable_, but everything that was on the
 unwound portion of the stack is now in an undefined state. So, recovering
 from the AssertError and continuing execution doesn't work. So, a handler
 can catch the AssertError and do something before letting it kill the
 program, but portions of the program are definitely in an undefined state
 when an AssertError is caught. The closer the catch point is to the throw
 point, the less of an issue that is, but unless you can guarantee that no
 destructors, scope statements, or finally blocks were between the throw
 point and the catch point, then some portion of the program is in an
 undefined state, and continuing program execution is a bad idea. It _is_
 possible to catch an AssertError, but you have to be very careful about
 what you do after that.
 
 I'm not aware of anything in contracts which would involve catching an
 AssertError and then continuing execution. When a contract fails, it's
 going to kill the program just like any other assertion failure does. So,
 I'm not quite sure what you're referring to.
 
 - Jonathan M Davis

This might be how it works today, but I think it's a broken design. AssertError MUST be SAFELY catchable to be able to write unit testing frameworks.

I honestly don't think that Walter even considered unit testing frameworks when he came up with the design. He built unit tests into the language. So, from his point of view, why would you need a unit testing framework? He probably didn't even consider it. And AssertErrors _are_ catchable. You just have to deal with the fact that destructors, scope statements, and finally blocks all get skipped by them. So, cleanup doesn't tend to happen in their presence. That's more of an issue with a general unit testing framework than it would be if you were doing it closer to the throw point, but it doesn't necessarily make it so that the unit test framework doesn't work. It _does_ risk making it flakier though. What would be particularly risky is trying to continue a particular unit test block after a failed assertion, since the failures wouldn't be isolated (though personally, I think that that would be a bad idea even AssertErrors _didn't_ skip anything, simply because the failures aren't isolated, and you get a bunch of failures simply because you already had one). Running subsequent unittest blocks should be less risky (though not necessarily without risk), because unittest blocks are normally isolated. Regardless, if you don't like the fact that there's no guarantee that AssertErrors execute finally blocks, scope statements, and destructors, take it up with Walter. I'm just pointing out what the design is. I didn't make the decision - though in general, I do think that it was the correct one. It's just that there are a few cases (e.g. some unit testing stuff) where it can become an issue. And if you really want to do your own unit testing framework, maybe you should just create your own custom assertion functions which throw something other than AssertError - though if they don't throw Errors, then any unittest blocks with a catch(Exception() {} in them may not work properly, so that's not necessarily all that great a solution either, depending. - Jonathan M Davis
Mar 10 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, March 11, 2012 13:13:58 Jacob Carlborg wrote:
 On 2012-03-10 18:08, Jonathan M Davis wrote:
 I honestly don't think that Walter even considered unit testing frameworks
 when he came up with the design. He built unit tests into the language.
 So,
 from his point of view, why would you need a unit testing framework? He
 probably didn't even consider it.

I don't think he considered unit testing frameworks either.
 And if you really want to do your own unit testing framework, maybe you
 should just create your own custom assertion functions which throw
 something other than AssertError - though if they don't throw Errors,
 then any unittest blocks with a catch(Exception() {} in them may not work
 properly, so that's not necessarily all that great a solution either,
 depending.
 
 - Jonathan M Davis

Yeah, exactly. And it feels a bit stupid to duplicate the assert statement just to throw something that isn't an AssertError.

Not to say that it's what you have to do, but I _would_ point out that all of the unit testing frameworks that I've seen in other langages _do_ create their own custom assert statements, so that wouldn't be abnormal at all. Now, in C++, assert doesn't throw anything (I don't remember if it does in Java or not), and there's no built-in unit testing framework using assert, so it's not as weird to use your own as it would be in D, but it's still not uncommon in unit testing frameworks to define a set of custom assertion functions specfically for unit testing. - Jonathan M Davis
Mar 11 2012
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sat, 10 Mar 2012 11:03:43 -0500, Jacob Carlborg <doob me.com> wrote:

 On 2012-03-09 20:06, Jonathan M Davis wrote:

 In what way? Yes, they're _catchable_, but everything that was on the  
 unwound
 portion of the stack is now in an undefined state. So, recovering from  
 the
 AssertError and continuing execution doesn't work. So, a handler can  
 catch the
 AssertError and do something before letting it kill the program, but  
 portions
 of the program are definitely in an undefined state when an AssertError  
 is
 caught. The closer the catch point is to the throw point, the less of  
 an issue
 that is, but unless you can guarantee that no destructors, scope  
 statements,
 or finally blocks were between the throw point and the catch point,  
 then some
 portion of the program is in an undefined state, and continuing program
 execution is a bad idea. It _is_ possible to catch an AssertError, but  
 you
 have to be very careful about what you do after that.

 I'm not aware of anything in contracts which would involve catching an
 AssertError and then continuing execution. When a contract fails, it's  
 going
 to kill the program just like any other assertion failure does. So, I'm  
 not
 quite sure what you're referring to.

 - Jonathan M Davis

This might be how it works today, but I think it's a broken design. AssertError MUST be SAFELY catchable to be able to write unit testing frameworks.

There was a period of time where unit test asserts were handled differently than normal asserts. The unit tests would continue even if a unit test asserted. This is no longer the case. The issue was that sometimes when you have one small problem in your code, you get thousands of asserts from different unit tests, making it impossible to find the "real issue". I contended that unit test asserts should result in a hook that by default kills the program, but could be hooked into a unit testing handler. But the consensus was just to switch back to the original behavior (all asserts kill the program). If you look through the phobos or druntime mailing list archives you might find the relevant conversations. It may even be so old that the archives don't have it (it was on a private mailing list on Andrei's server for a time). My thoughts on assert/unit test: 1. AssertError (and any other Error) should not be caught by normal user code. Ever. It should only be caught by the runtime. However, the handler in the runtime could provide a hook specific to the OS/application and whether it is running unit tests. Obviously the hook would have to be set up before main runs, so that is an issue, but you may just need to alter the runtime in that case. 2. Any assert in a unit test block should halt execution in the unit test block. Often subsequent asserts are just noise because you are depending on the conditions that make the prior asserts pass. 3. unit test blocks should be tested individually, not on a module-level IMO. I'm not sure if this currently is the case. 4. Jonathan's statement that the program is in an "undefined state" is not quite true. It's in an unwound state, but not undefined. Certainly, you should be able to continue running more unit tests. Unit tests should be a) unaffected by other unit test blocks, and b) should not affect the running of any other code in any way. Otherwise, a program would run differently depending on whether unit tests ran. 5. If *any* unit tests fail, the main() function should not be run. If an assert is triggered while running main(), the program should exit. -Steve
Mar 12 2012
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sat, 10 Mar 2012 01:09:02 -0500, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 On Friday, March 09, 2012 22:48:25 Timon Gehr wrote:
 On 03/09/2012 10:43 PM, Jonathan M Davis wrote:
 ...

 Jonathan is just speculating. And I think he is wrong.

Speculating about what? - Jonathan M Davis

About how assertion failures affect struct destructors, finally statements and scope statements. If they wouldn't be executed upon thrown AssertError, then a _passing_ in contract could screw up the program state. Furthermore, the implementation does execute them.

It's not speculation. There's no guessing involved. It's what I've understood the rules of the language to be. But I asked on dmd-internals to verify it, and Walter has stated that it just so happens that the destructors, scope statements, and finally blocks do currently get run for non-Exception exceptions, but it's not guaranteed: http://forum.dlang.org/post/4F5AE8EC.4040408 digitalmars.com

I understood this to mean, in release mode, assert(0) may simply abort without being catchable. If assert isn't going to properly unwind the stack, then we are using the wrong tool for unit tests. Asserts during unit tests do not protect some valid program state, they are simply a means to test that a function is operating as designed. A unit test should test one thing, maybe repeated times, and then exit. It should not save any state or affect any other unit tests or the program. If there is ever an effort to prevent assert from running finally/scope blocks, special effort should be take to continue running those blocks during unit tests. -Steve
Mar 12 2012
prev sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Monday, March 12, 2012 09:40:44 Jacob Carlborg wrote:
 On 2012-03-11 22:12, Jonathan M Davis wrote:
 On Sunday, March 11, 2012 13:13:58 Jacob Carlborg wrote:
 Yeah, exactly. And it feels a bit stupid to duplicate the assert
 statement just to throw something that isn't an AssertError.

Not to say that it's what you have to do, but I _would_ point out that all of the unit testing frameworks that I've seen in other langages _do_ create their own custom assert statements, so that wouldn't be abnormal at all. Now, in C++, assert doesn't throw anything (I don't remember if it does in Java or not), and there's no built-in unit testing framework using assert, so it's not as weird to use your own as it would be in D, but it's still not uncommon in unit testing frameworks to define a set of custom assertion functions specfically for unit testing. - Jonathan M Davis

They usually define "assertEqual", "assertNotEqual" and so on. But basically all unit testing frameworks also have a basic "assert". I see know reason why the basic assert needs to be redefined.

It does if you need it to function differently than it does normally, which is more or less what you're looking to do here, but aside from that, no, there's probably no reason to. - Jonathan M Davis
Mar 12 2012