Discussion:
Program logic bugs vs input/environmental errors
(too old to reply)
Bruno Medeiros via Digitalmars-d
2014-10-08 15:14:51 UTC
Permalink
Sean, I fully agree with the points you have been making so far.
But if Walter is fixated on thinking that all the practical uses of D
will be
critical systems, or simple (ie, single-use, non-interactive)
command-line
applications, it will be hard for him to comprehend the whole point
that "simply
aborting on error is too brittle in some cases".
Airplane avionics systems all abort on error, yet the airplanes don't
fall out of the sky.
http://www.drdobbs.com/architecture-and-design/safe-systems-from-unreliable-parts/228701716
That's completely irrelevant to the "simply aborting on error is too
brittle in some cases" point above, because I wasn't talking about
avionics systems, or any kind of mission critical systems at all. In
fact, the opposite (non critical systems).
--
Bruno Medeiros
https://twitter.com/brunodomedeiros
Bruno Medeiros via Digitalmars-d
2014-10-08 15:30:19 UTC
Permalink
On Friday, 3 October 2014 at 17:38:40 UTC, Brad Roberts via
The part of Walter's point that is either deliberately overlooked or
somewhat misunderstood here is the notion of a fault domain. In a
typical unix or windows based environment, it's a process. A fault
within the process yields the aborting of the process but not all
processes. Erlang introduces within it's execution model a concept of
a process within the higher level notion of the os level process.
Within the erlang runtime it's individual processes run independently
and can each fail independently. The erlang runtime guarantees a
higher level of separation than a typical threaded java or c++
application. An error within the erlang runtime itself would
justifiably cause the entire system to be halted. Just as within an
airplane, to use Walter's favorite analogy, the seat entertainment
system is physically and logically separated from flight control
systems thus a fault within the former has no impact on the latter.
Yep. And I think it's a fair assertion that the default fault
domain in a D program is at the process level, since D is not
inherently memory safe. But I don't think the language should
necessarily make that assertion to the degree that no other
definition is possible.
Yes to Brad, and then yes to Sean. That nailed the point.

To that I would only add that, when encountering a fault in a process,
even an estimation (that is, not a 100% certainty) that such fault only
affects a certain domain of the process, that would still be useful to
certain kinds of systems and applications.

I don't think memory-safety is at the core of the issue. Java is
memory-safe, yet if you encounter a null pointer exception, you're still
not sure if your whole application is now in an unusable state, or if
the NPE was just confined to say, the operation the user just tried to
do, or some other component of the application. There are no guarantees.
--
Bruno Medeiros
https://twitter.com/brunodomedeiros
Marco Leise via Digitalmars-d
2014-10-10 09:26:28 UTC
Permalink
Am Wed, 08 Oct 2014 16:30:19 +0100
Post by Bruno Medeiros via Digitalmars-d
I don't think memory-safety is at the core of the issue. Java is
memory-safe, yet if you encounter a null pointer exception, you're still
not sure if your whole application is now in an unusable state, or if
the NPE was just confined to say, the operation the user just tried to
do, or some other component of the application. There are no guarantees.
I know a Karaoke software written in .NET, that doesn't check
if a list view is empty when trying to select the first
element. It results in a popup message about the Exception and
you can continue from there.

It is a logic error (aka assertion), but being tailored
towards user interfaces, .NET doesn't kill the app.
Heck, if Mono-D closed down on every NPE I wouldn't be using
it any more. ;)
--
Marco
Brad Roberts via Digitalmars-d
2014-10-10 18:53:14 UTC
Permalink
Post by Marco Leise via Digitalmars-d
Am Wed, 08 Oct 2014 16:30:19 +0100
Post by Bruno Medeiros via Digitalmars-d
I don't think memory-safety is at the core of the issue. Java is
memory-safe, yet if you encounter a null pointer exception, you're still
not sure if your whole application is now in an unusable state, or if
the NPE was just confined to say, the operation the user just tried to
do, or some other component of the application. There are no guarantees.
I know a Karaoke software written in .NET, that doesn't check
if a list view is empty when trying to select the first
element. It results in a popup message about the Exception and
you can continue from there.
It is a logic error (aka assertion), but being tailored
towards user interfaces, .NET doesn't kill the app.
Heck, if Mono-D closed down on every NPE I wouldn't be using
it any more. ;)
How much you want to bet that if it did exit the app, that the bug would
actually have been addressed rather than still remain broken?
Dicebot via Digitalmars-d
2014-10-11 03:47:30 UTC
Permalink
On Friday, 10 October 2014 at 18:53:46 UTC, Brad Roberts via
Post by Brad Roberts via Digitalmars-d
How much you want to bet that if it did exit the app, that the
bug would actually have been addressed rather than still remain
broken?
It more likely would cause maintainer to abandon the project
after encountering raging users he can't help. Most of such
Mono-D issues simply are not reproducable on Alex side and remain
unfixed because of that. I can't remember a single case when he
remained willingly ignorant of an unhandled exception.
Dicebot via Digitalmars-d
2014-10-09 13:10:34 UTC
Permalink
Can we at least agree that Dicebot's request for having the
behaviour of
inadvisable constructs defined such that an implementation
cannot randomly
change behaviour and then have the developers close down the
corresponding
bugzilla issue because it was the user's fault anyway is not
unreasonable by
definition because the system will not reach a perfect state
anyway, and then
retire this discussion?
I've been working with Dicebot behind the scenes to help
resolve the particular issues with the code he's responsible
for.
As for D, D cannot offer any guarantees about behavior after a
program crash. Nor can any other language.
Just wanted to point out that resulting solution (== manually
switching many of contracts to exceptions from asserts) to me is
an unhappy workaround to deal with overly opinionated language
and not actually a solution. I still consider this a problem.
Johannes Pfau via Digitalmars-d
2014-10-09 16:33:48 UTC
Permalink
Am Thu, 09 Oct 2014 13:10:34 +0000
Post by Dicebot via Digitalmars-d
Can we at least agree that Dicebot's request for having the
behaviour of
inadvisable constructs defined such that an implementation
cannot randomly
change behaviour and then have the developers close down the
corresponding
bugzilla issue because it was the user's fault anyway is not
unreasonable by
definition because the system will not reach a perfect state
anyway, and then
retire this discussion?
I've been working with Dicebot behind the scenes to help
resolve the particular issues with the code he's responsible
for.
As for D, D cannot offer any guarantees about behavior after a
program crash. Nor can any other language.
Just wanted to point out that resulting solution (== manually
switching many of contracts to exceptions from asserts) to me is
an unhappy workaround to deal with overly opinionated language
and not actually a solution. I still consider this a problem.
A point which hasn't been discussed yet:

Errors and therefore assert can be used in nothrow functions. This is a
pita for compilers because it now can't do certain optimizations. When
porting GDC to ARM we started to see problems because of that (can't
unwind from nothrow functions on ARM, program just aborts). And now we
therefore have to worsen the codegen for nothrow functions because of
this.

I think Walter sometimes suggested that it would be valid for a
compiler to not unwind Errors at all (in release mode), but simply kill
the program and dump a error message. This would finally allow us to
optimize nothrow functions.
Iain Buclaw via Digitalmars-d
2014-10-09 16:43:10 UTC
Permalink
On 9 October 2014 17:33, Johannes Pfau via Digitalmars-d
Post by Johannes Pfau via Digitalmars-d
Am Thu, 09 Oct 2014 13:10:34 +0000
Post by Dicebot via Digitalmars-d
Can we at least agree that Dicebot's request for having the
behaviour of
inadvisable constructs defined such that an implementation
cannot randomly
change behaviour and then have the developers close down the
corresponding
bugzilla issue because it was the user's fault anyway is not
unreasonable by
definition because the system will not reach a perfect state
anyway, and then
retire this discussion?
I've been working with Dicebot behind the scenes to help
resolve the particular issues with the code he's responsible
for.
As for D, D cannot offer any guarantees about behavior after a
program crash. Nor can any other language.
Just wanted to point out that resulting solution (== manually
switching many of contracts to exceptions from asserts) to me is
an unhappy workaround to deal with overly opinionated language
and not actually a solution. I still consider this a problem.
Errors and therefore assert can be used in nothrow functions. This is a
pita for compilers because it now can't do certain optimizations. When
porting GDC to ARM we started to see problems because of that (can't
unwind from nothrow functions on ARM, program just aborts). And now we
therefore have to worsen the codegen for nothrow functions because of
this.
I think Walter sometimes suggested that it would be valid for a
compiler to not unwind Errors at all (in release mode), but simply kill
the program and dump a error message. This would finally allow us to
optimize nothrow functions.
This behaviour was agreed at the bar at DConf. We'd have to put it in
the spec to give it the official stamp of approval though.

Iain.
Dicebot via Digitalmars-d
2014-10-09 17:31:31 UTC
Permalink
Post by Johannes Pfau via Digitalmars-d
I think Walter sometimes suggested that it would be valid for a
compiler to not unwind Errors at all (in release mode), but
simply kill
the program and dump a error message. This would finally allow
us to
optimize nothrow functions.
I think this is reasonable in general but as long as assert
throws Error and assert is encouraged to be used in unittest
blocks such implementation would mark compiler as unusable for me.

We may need to have another look at what is truly an Error and
what is not before going that path.
via Digitalmars-d
2014-10-09 18:32:53 UTC
Permalink
On Thursday, 9 October 2014 at 16:33:53 UTC, Johannes Pfau
Post by Johannes Pfau via Digitalmars-d
I think Walter sometimes suggested that it would be valid for a
compiler to not unwind Errors at all (in release mode), but
simply kill
the program and dump a error message. This would finally allow us to
optimize nothrow functions.
I think this is reasonable in general but as long as assert
throws Error and assert is encouraged to be used in unittest
blocks such implementation would mark compiler as unusable for
me.
Can it simply skip unwinding up to the next not-nothrow function?
I.e. destructors of objects (and finally/scope(exit)) inside
`nothrow` functions will not be executed, but unwinding will
continue as normal at the first function up the call stack that
supports it?

Would this work for both GDC and LDC? If yes, your unittest
framework will probably continue to work as is.
Dicebot via Digitalmars-d
2014-10-09 18:46:49 UTC
Permalink
Post by via Digitalmars-d
Can it simply skip unwinding up to the next not-nothrow
function? I.e. destructors of objects (and finally/scope(exit))
inside `nothrow` functions will not be executed, but unwinding
will continue as normal at the first function up the call stack
that supports it?
Would this work for both GDC and LDC? If yes, your unittest
framework will probably continue to work as is.
Funny that it happens other way around right now with dmd
(http://dpaste.dzfl.pl/e685c0c32b0d) :

struct S
{
string id;

~this() nothrow
{
import core.stdc.stdio;
printf("%s\n", id.ptr);
}
}

void foo() nothrow
{
auto s = S("foo");
throw new Error("hmm");
}

void main()
{
auto s = S("main");
foo();
}

====

foo

object.Error: hmm
----------------
./f57(_Dmain+0x23) [0x4171cf]
./f57(void rt.dmain2._d_run_main(int, char**, extern (C) int
function(char[][])*).runAll().void __lambda1()+0x18) [0x417f40]
./f57(void rt.dmain2._d_run_main(int, char**, extern (C) int
function(char[][])*).tryExec(scope void delegate())+0x2a)
[0x417e9a]
./f57(void rt.dmain2._d_run_main(int, char**, extern (C) int
function(char[][])*).runAll()+0x30) [0x417f00]
./f57(void rt.dmain2._d_run_main(int, char**, extern (C) int
function(char[][])*).tryExec(scope void delegate())+0x2a)
[0x417e9a]
./f57(_d_run_main+0x1a3) [0x417e1b]
./f57(main+0x17) [0x4171f3]
/usr/lib/libc.so.6(__libc_start_main+0xf5) [0x40967a15]
Walter Bright via Digitalmars-d
2014-10-11 22:06:39 UTC
Permalink
Post by Johannes Pfau via Digitalmars-d
I think Walter sometimes suggested that it would be valid for a
compiler to not unwind Errors at all (in release mode), but simply kill
the program and dump a error message. This would finally allow us to
optimize nothrow functions.
I think this is reasonable in general but as long as assert throws Error and
assert is encouraged to be used in unittest blocks such implementation would
mark compiler as unusable for me.
All assert actually does is call a function in druntime. You can override and
insert your own assert handling function, and have it do as you need. It was
deliberately designed that way.
We may need to have another look at what is truly an Error and what is not
before going that path.
This involves making some hard decisions, but is worthwhile.
Dicebot via Digitalmars-d
2014-10-15 03:03:17 UTC
Permalink
Post by Walter Bright via Digitalmars-d
All assert actually does is call a function in druntime. You
can override and insert your own assert handling function, and
have it do as you need. It was deliberately designed that way.
A while ago I have been a looking for a way to throw Exception
instead of Error for failing assertions inside unittest blocks
but druntime didn't seem to provide needed context. Do you think
this can be a worthy addition?
Walter Bright via Digitalmars-d
2014-10-15 03:17:33 UTC
Permalink
Post by Walter Bright via Digitalmars-d
All assert actually does is call a function in druntime. You can override and
insert your own assert handling function, and have it do as you need. It was
deliberately designed that way.
A while ago I have been a looking for a way to throw Exception instead of Error
for failing assertions inside unittest blocks but druntime didn't seem to
provide needed context. Do you think this can be a worthy addition?
assert() in a unittest calls:

__d_unittest(string file, uint line)

which calls:

onUnittestErrorMsg(string file, size_t line, string msg)

which calls:

extern (C) void onAssertError( string file = __FILE__, size_t line =
__LINE__ ) nothrow
{
if( _assertHandler is null )
throw new AssertError( file, line );
_assertHandler( file, line, null);
}

You can use setAssertHandler() to set _assertHandler to do whatever you wish.

However, the compiler is still going to regard the assert() as nothrow, so the
unwinding from an Exception won't happen until up stack a throwing function is
encountered.
Dicebot via Digitalmars-d
2014-10-15 03:36:32 UTC
Permalink
On Wednesday, 15 October 2014 at 03:18:31 UTC, Walter Bright
Post by Walter Bright via Digitalmars-d
However, the compiler is still going to regard the assert() as
nothrow, so the unwinding from an Exception won't happen until
up stack a throwing function is encountered.
This makes impossible to have non-fatal unittests and the very
reason I was looking for a replacement.
Walter Bright via Digitalmars-d
2014-10-15 05:57:23 UTC
Permalink
Post by Walter Bright via Digitalmars-d
However, the compiler is still going to regard the assert() as nothrow, so the
unwinding from an Exception won't happen until up stack a throwing function is
encountered.
This makes impossible to have non-fatal unittests and the very reason I was
looking for a replacement.
I don't really understand the issue. Unittests are usually run with a separate
build of the app, not in the main app. When they are run in the main app, they
are run before the app even gets to main().

Why do you need non-fatal unittests?
Jacob Carlborg via Digitalmars-d
2014-10-15 06:23:38 UTC
Permalink
Post by Walter Bright via Digitalmars-d
Why do you need non-fatal unittests?
I don't know if this would cause problems with the current approach. But
most unit test frameworks don't NOT stop on the first failure, like D
does. It catches the exception, continues with the next test and in the
end prints a final report.
--
/Jacob Carlborg
Walter Bright via Digitalmars-d
2014-10-15 07:25:04 UTC
Permalink
Post by Walter Bright via Digitalmars-d
Why do you need non-fatal unittests?
I don't know if this would cause problems with the current approach. But most
unit test frameworks don't NOT stop on the first failure, like D does. It
catches the exception, continues with the next test and in the end prints a
final report.
I understand that, but I don't think that is what Dicebot is looking for. He's
looking to recover from unittests, not just continue.
Ary Borenszweig via Digitalmars-d
2014-10-15 13:57:35 UTC
Permalink
Post by Walter Bright via Digitalmars-d
Post by Walter Bright via Digitalmars-d
Why do you need non-fatal unittests?
I don't know if this would cause problems with the current approach. But most
unit test frameworks don't NOT stop on the first failure, like D does. It
catches the exception, continues with the next test and in the end prints a
final report.
I understand that, but I don't think that is what Dicebot is looking
for. He's looking to recover from unittests, not just continue.
I think this means you can't get stack traces for exceptions thrown in
unit tests, right?
Dicebot via Digitalmars-d
2014-10-15 14:25:42 UTC
Permalink
On Wednesday, 15 October 2014 at 07:26:03 UTC, Walter Bright
Post by Walter Bright via Digitalmars-d
Post by Jacob Carlborg via Digitalmars-d
Post by Walter Bright via Digitalmars-d
Why do you need non-fatal unittests?
I don't know if this would cause problems with the current
approach. But most
unit test frameworks don't NOT stop on the first failure, like D does. It
catches the exception, continues with the next test and in the end prints a
final report.
I understand that, but I don't think that is what Dicebot is
looking for. He's looking to recover from unittests, not just
continue.
How can one continue without recovering? This will result in any
kind of environment not being cleaned and false failures of other
tests that share it.
via Digitalmars-d
2014-10-15 14:47:32 UTC
Permalink
Post by Dicebot via Digitalmars-d
How can one continue without recovering? This will result in
any kind of environment not being cleaned and false failures of
other tests that share it.
fork()?
eles via Digitalmars-d
2014-10-15 16:39:46 UTC
Permalink
On Wednesday, 15 October 2014 at 14:47:33 UTC, Ola Fosheim
Post by via Digitalmars-d
Post by Dicebot via Digitalmars-d
How can one continue without recovering? This will result in
any kind of environment not being cleaned and false failures
of other tests that share it.
fork()?
http://check.sourceforge.net/doc/check_html/check_2.html

"Writing a framework for C requires solving some special problems
that frameworks for Smalltalk, Java or Python don’t have to face.
In all of those language, the worst that a unit test can do is
fail miserably, throwing an exception of some sort. In C, a unit
test is just as likely to trash its address space as it is to
fail to meet its test requirements, and if the test framework
sits in the same address space, goodbye test framework.

To solve this problem, Check uses the fork() system call to
create a new address space in which to run each unit test, and
then uses message queues to send information on the testing
process back to the test framework. That way, your unit test can
do all sorts of nasty things with pointers, and throw a
segmentation fault, and the test framework will happily note a
unit test error, and chug along. "
Dan Olson via Digitalmars-d
2014-10-16 15:39:44 UTC
Permalink
Post by via Digitalmars-d
Post by Dicebot via Digitalmars-d
How can one continue without recovering? This will result in any
kind of environment not being cleaned and false failures of other
tests that share it.
fork()?
Forking each unittest sounds like a good solution.
--
dano
monnoroch via Digitalmars-d
2014-10-16 18:53:21 UTC
Permalink
Hi all!
I've read the topic and I am really surprised so many engeneers
arguing for so long and not having systematic approach to the
problem.

As I see it, Walter states that there are eenvironmental errors
and program bugs, which are non-recoverable. So use exceptions
(enforce) for first ones and asserts for the latter.

Other folks argue, that you might want to recover from a program
bug or not recover from invalid input. Also, exception might be
itself a program bug. This is a valid point too.

So if both are true, that clearly means that the right solution
would be to introduce four categories: a cross product of the
obove:

- bugs, that are recoverable
- bugs, that are unrecoverable
- input errors, that are recoverable
- input errors, that are not

Given that, makes sence to use exceptions for recoverable errors,
doesn't matter whether they are bugs or environmental errors, and
use asserts, if you can't recover.

So, the programmer decides, if his program can recover and puts
an assert or an enforce call in his code.

The problem is, as always, with libraries. The library writer
cannot possibly decide, is some unexpected condition recoverable
or not, so he just can't put both assert and enforce into his
library function and the caller must check the arguments before
calling the function. Yes, this is annoying, but it it the only
correct way.

But what if he didn't? This brings us to error codes. Yes, they
are the best for library error handling, imo, of course, in a
form of Maby and Error monads. They are as clear as asking the
ccaller to decide, what to do with the error. But I realize, that
you, guys, are all against error codes of any kind, so...

I would say, that since the caller didn't check the arguments
himself the bug becomes unrecoverable by default and there should
be an assert, which gives stack trace, so the programmer would
insert appropriate enforces before the function call.

Finally, this brings me to the conclusion: you don't need a stack
trace in the exception, it is never a bug.
Sean Kelly via Digitalmars-d
2014-10-16 19:11:18 UTC
Permalink
Post by monnoroch via Digitalmars-d
So if both are true, that clearly means that the right solution
would be to introduce four categories: a cross product of the
- bugs, that are recoverable
- bugs, that are unrecoverable
- input errors, that are recoverable
- input errors, that are not
Yes, I've already started a thread for this:

http://forum.dlang.org/thread/zwnycclpgvfsfaactcyl at forum.dlang.org

but almost no one replied.
Jacob Carlborg via Digitalmars-d
2014-10-16 06:11:46 UTC
Permalink
How can one continue without recovering? This will result in any kind of
environment not being cleaned and false failures of other tests that
share it.
I will probably use something else than "assert" in my unit tests.
Something like assertEq, assertNotEq and so on. It's more flexible, can
give better error message and I can have it throw an exception instead
of an error. But there's still the problem with asserts in contracts and
other parts of the code.
--
/Jacob Carlborg
Dicebot via Digitalmars-d
2014-10-16 19:21:49 UTC
Permalink
On Thursday, 16 October 2014 at 06:11:46 UTC, Jacob Carlborg
Post by Jacob Carlborg via Digitalmars-d
Post by Dicebot via Digitalmars-d
How can one continue without recovering? This will result in
any kind of
environment not being cleaned and false failures of other
tests that
share it.
I will probably use something else than "assert" in my unit
tests. Something like assertEq, assertNotEq and so on. It's
more flexible, can give better error message and I can have it
throw an exception instead of an error. But there's still the
problem with asserts in contracts and other parts of the code.
This is what we are using right now:

public void test ( char[] op, T1, T2 ) ( T1 a, T2 b, char[] file
= __FILE__, size_t line = __LINE__ )
{
enforce!(op, TestException)(a, b, file, line);
}

but it won't work well with 3d-party libraries that use
assertions.
Walter Bright via Digitalmars-d
2014-10-16 19:35:39 UTC
Permalink
How can one continue without recovering? This will result in any kind of
environment not being cleaned and false failures of other tests that
share it.
I will probably use something else than "assert" in my unit tests. Something
like assertEq, assertNotEq and so on. It's more flexible, can give better
error message and I can have it throw an exception instead of an error. But
there's still the problem with asserts in contracts and other parts of the code.
public void test ( char[] op, T1, T2 ) ( T1 a, T2 b, char[] file = __FILE__,
size_t line = __LINE__ )
{
enforce!(op, TestException)(a, b, file, line);
}
but it won't work well with 3d-party libraries that use assertions.
Ok, but why would 3rd party library unittests be a concern? They shouldn't have
shipped it if their own unittests fail - that's the whole point of having unittests.
Dicebot via Digitalmars-d
2014-10-16 19:56:56 UTC
Permalink
Post by Walter Bright via Digitalmars-d
Ok, but why would 3rd party library unittests be a concern?
They shouldn't have shipped it if their own unittests fail -
that's the whole point of having unittests.
Libraries tend to be forked and modified. Libraries aren't always
tested in environment similar to specific production case. At the
same time not being able to use same test runner in all
Continious Integration jobs greatly reduces the value of having
standard unittest blocks in the very first place.
Sean Kelly via Digitalmars-d
2014-10-16 20:16:27 UTC
Permalink
Post by Dicebot via Digitalmars-d
Libraries tend to be forked and modified. Libraries aren't
always tested in environment similar to specific production
case.
This seems relevant:

http://www.tele-task.de/archive/video/flash/16130/
Walter Bright via Digitalmars-d
2014-10-16 20:18:03 UTC
Permalink
Post by Dicebot via Digitalmars-d
Post by Walter Bright via Digitalmars-d
Ok, but why would 3rd party library unittests be a concern? They shouldn't
have shipped it if their own unittests fail - that's the whole point of having
unittests.
Libraries tend to be forked and modified.
If you're willing to go that far, then yes, you do wind up owning the unittests,
in which case s/assert/myassert/ should do it.
Post by Dicebot via Digitalmars-d
Libraries aren't always tested in
environment similar to specific production case.
Unittests should not be testing their environment. They should be testing the
function's logic, and should mock up input for them as required.
Post by Dicebot via Digitalmars-d
At the same time not being able
to use same test runner in all Continious Integration jobs greatly reduces the
value of having standard unittest blocks in the very first place.
I understand that, but wouldn't you be modifying the unittests anyway if using
an external test runner tool?
Dicebot via Digitalmars-d
2014-10-16 22:04:44 UTC
Permalink
Post by Walter Bright via Digitalmars-d
On Thursday, 16 October 2014 at 19:35:40 UTC, Walter Bright
Post by Walter Bright via Digitalmars-d
Ok, but why would 3rd party library unittests be a concern?
They shouldn't
have shipped it if their own unittests fail - that's the
whole point of having
unittests.
Libraries tend to be forked and modified.
If you're willing to go that far, then yes, you do wind up
owning the unittests, in which case s/assert/myassert/ should
do it.
Which means changing almost all sources and resolving conflicts
upon each merge. Forking library for few tweaks is not "going
that far", it is an absolutely minor routine. It also complicates
propagating changes back upstream because all tests need to be
re-adjusted back to original style.
Post by Walter Bright via Digitalmars-d
Libraries aren't always tested in
environment similar to specific production case.
Unittests should not be testing their environment. They should
be testing the function's logic, and should mock up input for
them as required.
compiler version, libc version, kernel version - all it can
affect behaviour or pretty self-contained function. Perfectly
tested library is as much reality as program with 0 bugs.
Post by Walter Bright via Digitalmars-d
At the same time not being able
to use same test runner in all Continious Integration jobs
greatly reduces the
value of having standard unittest blocks in the very first
place.
I understand that, but wouldn't you be modifying the unittests
anyway if using an external test runner tool?
No, right now one can affect the way tests are run by simply
replacing the runner to a custom one and it will work for any
amount of modules compiled in. Beauty of `unittest` block
approach is that it is simply a bunch of functions that are
somewhat easy to discover from the combined sources of the
program - custom runner can do pretty much anything with those.
Or it could if not the issue with AssertError and cleanup.
Atila Neves via Digitalmars-d
2014-10-17 08:26:42 UTC
Permalink
Post by Dicebot via Digitalmars-d
No, right now one can affect the way tests are run by simply
replacing the runner to a custom one and it will work for any
amount of modules compiled in. Beauty of `unittest` block
approach is that it is simply a bunch of functions that are
somewhat easy to discover from the combined sources of the
program - custom runner can do pretty much anything with those.
Or it could if not the issue with AssertError and cleanup.
Is cleaning up in a unittest build a problem? I'd say no, if it
the tests fail it doesn't make much sense to clean up unless it
affects the reporting of tests failing.

I catch assertion errors in unit-threaded exactly to support the
standard unittest blocks and can't see why I'd care about
clean-up. At least in practice it hasn't been an issue, although
to be fair I haven't used that functionality a lot (of using
unit-threaded to run unittest blocks).

Atila

Walter Bright via Digitalmars-d
2014-10-16 07:33:28 UTC
Permalink
How can one continue without recovering? This will result in any kind of
environment not being cleaned and false failures of other tests that share it.
Unittest asserts are top level - they shouldn't need recovering from (i.e.
unwinding). Just continuing.
Dan Olson via Digitalmars-d
2014-10-15 14:35:41 UTC
Permalink
Post by Walter Bright via Digitalmars-d
Post by Walter Bright via Digitalmars-d
Why do you need non-fatal unittests?
I don't know if this would cause problems with the current approach. But most
unit test frameworks don't NOT stop on the first failure, like D does. It
catches the exception, continues with the next test and in the end prints a
final report.
I understand that, but I don't think that is what Dicebot is looking
for. He's looking to recover from unittests, not just continue.
That is what I am looking for, just being able to continue from a failed
assert in a unittest. On iOS, it is easier to build one app with all
unit tests. This is because I don't know of a way to automate the
download/run of a bunch of smaller unittests. The test driver catches
Throwables, records failure, then goes on to the next test. After
catching up on this thread, I feel like unittests should throw
an Exceptions.
Walter Bright via Digitalmars-d
2014-10-16 07:35:20 UTC
Permalink
Post by Dan Olson via Digitalmars-d
That is what I am looking for, just being able to continue from a failed
assert in a unittest.
Just use enforce() or something similar instead of assert(). Nothing says you
have to use assert() in a unittest.
Dan Olson via Digitalmars-d
2014-10-16 15:36:33 UTC
Permalink
Post by Walter Bright via Digitalmars-d
Post by Dan Olson via Digitalmars-d
That is what I am looking for, just being able to continue from a failed
assert in a unittest.
Just use enforce() or something similar instead of assert(). Nothing
says you have to use assert() in a unittest.
Makes sense. However it is druntime and phobos unittests that already use assert. I have convinced myself that catching Throwable is just fine in my case because at worst, unittests that follow an Error might be tainted, but only a perfect score of passing all tests really counts.
--
dano
Walter Bright via Digitalmars-d
2014-10-16 18:50:30 UTC
Permalink
Post by Dan Olson via Digitalmars-d
Post by Walter Bright via Digitalmars-d
Post by Dan Olson via Digitalmars-d
That is what I am looking for, just being able to continue from a failed
assert in a unittest.
Just use enforce() or something similar instead of assert(). Nothing says
you have to use assert() in a unittest.
Makes sense. However it is druntime and phobos unittests that already use
assert. I have convinced myself that catching Throwable is just fine in my
case because at worst, unittests that follow an Error might be tainted, but
only a perfect score of passing all tests really counts.
I don't understand why unittests in druntime/phobos are an issue for users. We
don't release a DMD unless they all pass - it should be moot for users.
Dan Olson via Digitalmars-d
2014-10-17 05:09:45 UTC
Permalink
Post by Walter Bright via Digitalmars-d
I don't understand why unittests in druntime/phobos are an issue for
users. We don't release a DMD unless they all pass - it should be moot
for users.
I think some context was lost. This is different. I am making mods to
LDC, druntime, and phobos to target iPhones and iPads (ARM-iOS). I also
can't claim victory until all unittests pass.
Sean Kelly via Digitalmars-d
2014-10-16 01:54:37 UTC
Permalink
On Wednesday, 15 October 2014 at 03:18:31 UTC, Walter Bright
Post by Walter Bright via Digitalmars-d
However, the compiler is still going to regard the assert() as
nothrow, so the unwinding from an Exception won't happen until
up stack a throwing function is encountered.
I hate to say it, but I'm inclined to treat nothrow the same as
in C++, which is to basically pretend it's not a part of the
language. The efficiency is nice, but not if it means that
throwing an Error will cause the program to be invalid. Please
tell me there's no plan to change the unwinding behavior when
Error is thrown in standard (ie not nothrow) code.

I touched on all this in my "on errors" thread that seems to have
died. I suppose I could write a DIP but I was hoping for
discussion.
Elena via Digitalmars-d
2014-10-16 03:11:55 UTC
Permalink
Hi,every one!
How can I realize mathematical rounding (not banking) for Double
in D
0.4 -> 0
0.5 -> 1
1.5 -> 2
2.5 -> 3
3.5 -> 4 ?

Thank you.
Andrei Alexandrescu via Digitalmars-d
2014-10-16 05:24:24 UTC
Permalink
Post by Elena via Digitalmars-d
Hi,every one!
How can I realize mathematical rounding (not banking) for Double in D
0.4 -> 0
0.5 -> 1
1.5 -> 2
2.5 -> 3
3.5 -> 4 ?
Thank you.
Add 0.5 and then cast to integral. -- Andrei
via Digitalmars-d
2014-10-16 07:31:13 UTC
Permalink
On Thursday, 16 October 2014 at 05:24:23 UTC, Andrei Alexandrescu
Post by Andrei Alexandrescu via Digitalmars-d
Post by Elena via Digitalmars-d
Hi,every one!
How can I realize mathematical rounding (not banking) for
Double in D
0.4 -> 0
0.5 -> 1
1.5 -> 2
2.5 -> 3
3.5 -> 4 ?
Thank you.
Add 0.5 and then cast to integral. -- Andrei
This would be the "round half up" mode that produce 0 for -0.5:

floor(x+0.5)

Whereas "round nearest" should produce -1 for -0.5:

floor(abs(x)+0.5)*sgn(x)
via Digitalmars-d
2014-10-16 05:57:32 UTC
Permalink
Post by Elena via Digitalmars-d
Hi,every one!
How can I realize mathematical rounding (not banking) for
Never used it, but:

http://dlang.org/library/std/math/FloatingPointControl.html

phobos/math.d lists the enums:

roundToNearest, roundDown, roundUp, roundToZero
Walter Bright via Digitalmars-d
2014-10-16 07:44:38 UTC
Permalink
I hate to say it, but I'm inclined to treat nothrow the same as in C++, which is
to basically pretend it's not a part of the language. The efficiency is nice,
but not if it means that throwing an Error will cause the program to be
invalid. Please tell me there's no plan to change the unwinding behavior when
Error is thrown in standard (ie not nothrow) code.
Don't throw Errors when you need to unwind. Throw Exceptions. I.e. use enforce()
instead of assert().
Sean Kelly via Digitalmars-d
2014-10-16 13:46:34 UTC
Permalink
Post by Walter Bright via Digitalmars-d
Post by Sean Kelly via Digitalmars-d
I hate to say it, but I'm inclined to treat nothrow the same
as in C++, which is
to basically pretend it's not a part of the language. The
efficiency is nice,
but not if it means that throwing an Error will cause the
program to be
invalid. Please tell me there's no plan to change the
unwinding behavior when
Error is thrown in standard (ie not nothrow) code.
Don't throw Errors when you need to unwind. Throw Exceptions.
I.e. use enforce() instead of assert().
I'm more concerned about Phobos. If it uses nothrow and asserts
in preconditions then the decision has been made for me.
Walter Bright via Digitalmars-d
2014-10-16 18:49:13 UTC
Permalink
Post by Walter Bright via Digitalmars-d
Don't throw Errors when you need to unwind. Throw Exceptions. I.e. use
enforce() instead of assert().
I'm more concerned about Phobos. If it uses nothrow and asserts in preconditions
then the decision has been made for me.
Which function(s) in particular?
Sean Kelly via Digitalmars-d
2014-10-16 19:08:49 UTC
Permalink
Post by Walter Bright via Digitalmars-d
On Thursday, 16 October 2014 at 07:44:37 UTC, Walter Bright
Post by Walter Bright via Digitalmars-d
Don't throw Errors when you need to unwind. Throw Exceptions.
I.e. use enforce() instead of assert().
I'm more concerned about Phobos. If it uses nothrow and
asserts in preconditions then the decision has been made for
me.
Which function(s) in particular?
Nothing specifically... which is kind of the problem. If I call
an impure nothrow function, it's possible the function accesses
shared state that will not be properly cleaned up in the event of
a thrown Error--say it contains a synchronized block, for
example. So even if I can be sure that the problem that resulted
in an Error being thrown did not corrupt program state, I can't
be sure that the failure to unwind did not as well.

That said, I'm inclined to say that this is only a problem
because of how many things are classified as Errors at this
point. If contracts used some checking mechanism other than
assert, perhaps this would be enough. Again I'll refer to my "on
errors" post that gets into this a bit. Using two broad
categories: exceptions and errors, is unduly limiting.
Walter Bright via Digitalmars-d
2014-10-16 19:31:05 UTC
Permalink
Post by Sean Kelly via Digitalmars-d
Post by Walter Bright via Digitalmars-d
Post by Walter Bright via Digitalmars-d
Don't throw Errors when you need to unwind. Throw Exceptions. I.e. use
enforce() instead of assert().
I'm more concerned about Phobos. If it uses nothrow and asserts in
preconditions then the decision has been made for me.
Which function(s) in particular?
Nothing specifically... which is kind of the problem. If I call
an impure nothrow function, it's possible the function accesses
shared state that will not be properly cleaned up in the event of
a thrown Error--say it contains a synchronized block, for
example. So even if I can be sure that the problem that resulted
in an Error being thrown did not corrupt program state, I can't
be sure that the failure to unwind did not as well.
Contract errors in Phobos/Druntime should be limited to having passed it invalid
arguments, which should be documented, or simply that the function has a bug in
it, or that it ran out of memory (which is generally not recoverable anyway).

I.e. I'm not seeing where this is a practical problem.
Post by Sean Kelly via Digitalmars-d
That said, I'm inclined to say that this is only a problem
because of how many things are classified as Errors at this
point. If contracts used some checking mechanism other than
assert, perhaps this would be enough. Again I'll refer to my "on
errors" post that gets into this a bit. Using two broad
categories: exceptions and errors, is unduly limiting.
My initial impression is that there's so much confusion about what should be an
Error and what should be an Exception, that adding a third category will not
improve things.
Walter Bright via Digitalmars-d
2014-10-11 22:03:47 UTC
Permalink
Post by Johannes Pfau via Digitalmars-d
Errors and therefore assert can be used in nothrow functions. This is a
pita for compilers because it now can't do certain optimizations. When
porting GDC to ARM we started to see problems because of that (can't
unwind from nothrow functions on ARM, program just aborts). And now we
therefore have to worsen the codegen for nothrow functions because of
this.
I think Walter sometimes suggested that it would be valid for a
compiler to not unwind Errors at all (in release mode), but simply kill
the program and dump a error message. This would finally allow us to
optimize nothrow functions.
Currently, Errors can be caught, but intervening finally blocks are not
necessarily run. The reasons for this are:

1. better code generation

2. since after an Error the program is likely in an unknown state, the less code
that is run after an Error, the better, because it may make things worse
Joseph Rushton Wakeling via Digitalmars-d
2014-10-10 00:32:03 UTC
Permalink
Of course it does not increase the probability to get a
"tails". Actually, it increases the probability that you'll get
"heads" again.
Er, no, unless you assume that repeated flips of the coin in some
way deform it so as to bias the outcome.

An extended run of heads might lead you to conclude that the coin
is biased, and so increase your _expectation_ that the next flip
will also result in a head, but that doesn't alter the actual
underlying probability.
Iain Buclaw via Digitalmars-d
2014-10-10 06:27:57 UTC
Permalink
On 10 Oct 2014 01:35, "Joseph Rushton Wakeling via Digitalmars-d" <
Of course it does not increase the probability to get a "tails".
Actually, it increases the probability that you'll get "heads" again.
Er, no, unless you assume that repeated flips of the coin in some way
deform it so as to bias the outcome.
An extended run of heads might lead you to conclude that the coin is
biased, and so increase your _expectation_ that the next flip will also
result in a head, but that doesn't alter the actual underlying probability.

http://www.wired.com/2012/12/what-does-randomness-look-like/
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20141010/ac88ef73/attachment.html>
eles via Digitalmars-d
2014-10-10 09:21:36 UTC
Permalink
On Friday, 10 October 2014 at 06:28:06 UTC, Iain Buclaw via
Post by Iain Buclaw via Digitalmars-d
On 10 Oct 2014 01:35, "Joseph Rushton Wakeling via
Digitalmars-d" <
Post by Joseph Rushton Wakeling via Digitalmars-d
Of course it does not increase the probability to get a
"tails".
Actually, it increases the probability that you'll get "heads"
again.
Post by Joseph Rushton Wakeling via Digitalmars-d
Er, no, unless you assume that repeated flips of the coin in
some way
deform it so as to bias the outcome.
;) It was a joke. The link that I posted was supposed to make
things clear. :)
Joseph Rushton Wakeling via Digitalmars-d
2014-10-10 09:24:11 UTC
Permalink
Post by eles via Digitalmars-d
;) It was a joke. The link that I posted was supposed to make
things clear. :)
You two-faced person, you. ;-)
eles via Digitalmars-d
2014-10-10 09:22:22 UTC
Permalink
On Friday, 10 October 2014 at 00:32:05 UTC, Joseph Rushton
Of course it does not increase the probability to get a
"tails". Actually, it increases the probability that you'll
get "heads" again.
Did you see the link? ;;)
Joseph Rushton Wakeling via Digitalmars-d
2014-10-10 09:31:09 UTC
Permalink
On Friday, 10 October 2014 at 06:28:06 UTC, Iain Buclaw via
Post by Iain Buclaw via Digitalmars-d
http://www.wired.com/2012/12/what-does-randomness-look-like/
... yes, allowing for the reasonable expectations one can have
for extended runs of heads in a regular 50/50 coin-flip process.

Actually, related to that article, in my very first stats lecture
at university, the first slide the lecturer showed us (on the
overhead projector...) was, side by side, two patterns of dots
each within a rectangular area.

He asked: "Do you think these points are distributed at random?"
Well, they pretty much looked the same to the naked eye.

Then he took another transparency, which placed grids over the
two rectangular dot-filled areas. In one, the dots were here,
there, with some grid squares containing no dots at all, some
containing clusters, whatever.

In the other, every single grid square contained exactly one dot.

I still think that was one of the single most important lessons
in probability that I ever had.
Nick Sabalausky via Digitalmars-d
2014-10-11 20:34:09 UTC
Permalink
Post by eles via Digitalmars-d
On Friday, 10 October 2014 at 06:28:06 UTC, Iain Buclaw via
Post by Iain Buclaw via Digitalmars-d
http://www.wired.com/2012/12/what-does-randomness-look-like/
... yes, allowing for the reasonable expectations one can have for
extended runs of heads in a regular 50/50 coin-flip process.
Actually, related to that article, in my very first stats lecture at
university, the first slide the lecturer showed us (on the overhead
projector...) was, side by side, two patterns of dots each within a
rectangular area.
He asked: "Do you think these points are distributed at random?" Well,
they pretty much looked the same to the naked eye.
Then he took another transparency, which placed grids over the two
rectangular dot-filled areas. In one, the dots were here, there, with
some grid squares containing no dots at all, some containing clusters,
whatever.
In the other, every single grid square contained exactly one dot.
I still think that was one of the single most important lessons in
probability that I ever had.
I like that. I actually have a similar classroom probability story too
(involving one of the best teachers I ever had):

As part of a probability homework assignment, we were asked to flip a
coin 100 times and write down the results. "Uhh, yea, there's no way I'm
doing that. I'm just gonna write down a bunch of T's and F's."

Having previously played around with PRNG's (using them, not actually
creating them), I had noticed that you do tend to get surprisingly long
runs of one value missing, or the occasional clustering. I carefully
used that knowledge to help me cheat.

During the next class, the teacher pointed out that "I can tell, most of
you didn't actually flip a coin, did you? You just wrote down T's and
F's..." Which turned out to be the whole *point* of the assignment.
Deliberately get students to "cheat" and fake randomness - poorly - in
order to *really* get them to understand the nature of randomness.

Then he turned to me and said, "Uhh, Nick, you actually DID flip a coin
didn't you?" Hehe heh heh. "Nope :)" I got a good chuckle out of that.
Walter Bright via Digitalmars-d
2014-10-15 01:12:36 UTC
Permalink
Having previously played around with PRNG's (using them, not actually creating
them), I had noticed that you do tend to get surprisingly long runs of one value
missing, or the occasional clustering. I carefully used that knowledge to help
me cheat.
Election fraud is often detected by examining the randomness of the least
significant digits of the vote totals.
Walter Bright via Digitalmars-d
2014-10-10 06:47:32 UTC
Permalink
(Note: I don't think such dichotomy and compromise *has* to exist in order to
design a great D and Phobos. But in this discussion I feel the choices and
vision were heading in a way that would likely harm the development of general
purpose software in favor of critical systems.)
I definitely believe that Phobos should aid the implementation of critical
systems over sloppy ones.

But I don't believe that harms sloppy ones.
eles via Digitalmars-d
2014-10-14 15:57:03 UTC
Permalink
On Friday, 3 October 2014 at 20:31:42 UTC, Paolo Invernizzi
http://www.popularmechanics.com/technology/aviation/crashes/what-really-happened-aboard-air-france-447-6611877
A just-printed new analysis of the same:

http://www.vanityfair.com/business/2014/10/air-france-flight-447-crash
Kagamin via Digitalmars-d
2014-10-15 07:19:06 UTC
Permalink
Do you interpret airplane safety right? As I understand,
airplanes are safe
exactly because they recover from assert failures and continue
operation.
Nope. That's exactly 180 degrees from how it works.
Any airplane system that detects a fault shuts itself down and
the backup is engaged. No way in hell is software allowed to
continue that asserted.
Sure, software is one part of an airplane, like a thread is a
part of a process. When the part fails, you discard it and
continue operation. In software it works by rolling back a failed
transaction. An airplane has some tricks to recover from
failures, but still it's a "no fail" design you argue against: it
shuts down parts one by one when and only when they fail and
continues operation no matter what until nothing works and even
then it still doesn't fail, just does nothing. The airplane
example works against your arguments.

The unreliable design you talk about would be committing a failed
transaction, but no, nobody suggests that.
Walter Bright via Digitalmars-d
2014-10-16 19:53:42 UTC
Permalink
Sure, software is one part of an airplane, like a thread is a part of a process.
When the part fails, you discard it and continue operation. In software it works
by rolling back a failed transaction. An airplane has some tricks to recover
from failures, but still it's a "no fail" design you argue against: it shuts
down parts one by one when and only when they fail and continues operation no
matter what until nothing works and even then it still doesn't fail, just does
nothing. The airplane example works against your arguments.
This is a serious misunderstanding of what I'm talking about.

Again, on an airplane, no way in hell is a software system going to be allowed
to continue operating after it has self-detected a bug. Trying to bend the
imprecise language I use into meaning the opposite doesn't change that.
Loading...