catalan42 (31) [Avatar] Offline
#1
Hi,

I was re-reading GINA recently and recognized upon closer inspection that asserts #1 and #2 in Listing 7.8 (page 184) are a bit misleading, since they are never executed.

#1. Since map.a.x is null, the logical expression is false and the assert is never reached.

#2. Since map.a.x is null, the reference to map.a.x.c causes a NullPointerException before anything else happens (e.g. the == operator), so the assert is never reached.

This is a bit of a subtle error. The two assert statements are there in the code, big as life, but in fact are never executed and so don't provide any protection. I have had similar (painful) experience in the past with JUnit/CppUnit test cases that were written but were accidentally left unexecuted. This can really send one on a wild goose chase when your own (non-executing) test cases falsely steer you away from the real problem!

Perhaps the following version of the example will better illustrate the concept to the reader:
-------------------------------------------------------------------------------------------------------------
def map = [a:[b:[c:1]]]

if (map.a.x) {
assert false; // #1. Never reached
} else {
println "map.a.x == " + map.a.x
assert map.a.x == null
}

try {
println "The value of map.a.x.c: " + map.a.x.c // #2. Doesn't complete execution
assert false; // #3. Never reached
} catch (NullPointerException npe) {
println "map.a.x == " + map.a.x + " (still)"
assert map.a.x == null
}

println "map?.a?.x?.c == " + map?.a?.x?.c
assert map?.a?.x?.c == null // Safe dereferencing
-------------------------------------------------------------------------------------------------------------

The output is:
--------------------------------------------------------------------------------------------------------------
map.a.x == null
map.a.x == null (still)
map?.a?.x?.c == null
-------------------------------------------------------------------------------------------------------------

Clearly, assert #1 is never reached. Also, the NPE in #2 aborts the statement before the println is executed, so #3 is never reached either.

Thanks again for writing such an informative and will-written book!
Alan Thompson
Mittie (397) [Avatar] Offline
#2
Re: Listing 7.8 asserts misleading
Hi Alan,

this is a misunderstanding. Wherever it says
assert false
this is an indication that this statement is never reached, because otherwise the code would throw an AssertionError smilie . I should have stated that more clearly.
Issue raised: http://groovy.canoo.com/errata/erratum/show/24

thanks for posting
Dierk
catalan42 (31) [Avatar] Offline
#3
Re: Listing 7.8 asserts misleading
Hi Dierk,

I think you misunderstood my post. The original listing 7.8 does not use "assert false" anywhere. I added that to my revised listing above to clarify things.

Alan