Bug 388800 - [1.8] adjust tests to 1.8 JRE
Summary: [1.8] adjust tests to 1.8 JRE
Status: RESOLVED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.8   Edit
Hardware: All All
: P3 enhancement (vote)
Target Milestone: BETA J8   Edit
Assignee: Stephan Herrmann CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on: 382347
Blocks: 380190
  Show dependency tree
 
Reported: 2012-09-04 18:54 EDT by Stephan Herrmann CLA
Modified: 2013-01-28 01:55 EST (History)
5 users (show)

See Also:


Attachments
Updates for MethodVerifierTest (3.21 KB, patch)
2012-09-04 18:59 EDT, Stephan Herrmann CLA
no flags Details | Diff
test results (430.43 KB, application/octet-stream)
2012-09-24 19:20 EDT, Stephan Herrmann CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Stephan Herrmann CLA 2012-09-04 18:54:45 EDT
BETA_JAVA8

When using a current beta of a lambda-enabled JRE (lambda-8-b50), some tests fail due to changes in class libraries.

During the first bunch of testing I found that List.remove() is now a default method, which triggers a warning re missing @Override in some tests in MethodVerifierTest.
Comment 1 Stephan Herrmann CLA 2012-09-04 18:59:18 EDT
Created attachment 220709 [details]
Updates for MethodVerifierTest

Here's the first bunch of updates.

Please let me know, when everybody is in the position to run Java8 tests on a matching JRE, so I can release these changes into the branch.
Comment 2 Srikanth Sankaran CLA 2012-09-05 00:52:46 EDT
(In reply to comment #1)

> Please let me know, when everybody is in the position to run Java8 tests on
> a matching JRE, so I can release these changes into the branch.

I am not aware of any reasons why someone must stay locked in with
an earlier JRE8. So please feel free to release the changes as long as they
will not cause any failures/issues when running the tests with JRE7.
Thanks!
Comment 3 Stephan Herrmann CLA 2012-09-05 18:41:20 EDT
I've pushed the changes in MethodVerifierTest via commit 4da3045d875134bb37de1ca00076288feb78d111.

Now org.eclipse.jdt.core.test.compiler.regression.TestAll is green on the lambda enabled JRE,
but I still need to check the rest of the test suite.

I believe most tests are unaffected because those use our own jclMinX.Y.jar for compilation.
Should we eventually create a jclMin1.8.jar using a few J8 features to get better test coverage?
This let's me to ask: is it correct that sources for the various jclMinX.Y.jar are only persisted via the corresponding jclMinX.Ysrc.zip?
Comment 4 Srikanth Sankaran CLA 2012-09-06 01:58:00 EDT
(In reply to comment #3)
> Should we eventually create a jclMin1.8.jar using a few J8 features to get
> better test coverage?

Sure, sounds good. At the very least I would raise a [1.8] tagged defect
so this is in the radar.

> This let's me to ask: is it correct that sources for the various
> jclMinX.Y.jar are only persisted via the corresponding jclMinX.Ysrc.zip?

Not sure I understand the question - What are you proposing we do and why ?
Comment 5 Stephan Herrmann CLA 2012-09-06 08:39:38 EDT
(In reply to comment #4)
> (In reply to comment #3)
> > Should we eventually create a jclMin1.8.jar using a few J8 features to get
> > better test coverage?
> 
> Sure, sounds good. At the very least I would raise a [1.8] tagged defect
> so this is in the radar.

Bug 388936
 
> > This let's me to ask: is it correct that sources for the various
> > jclMinX.Y.jar are only persisted via the corresponding jclMinX.Ysrc.zip?
> 
> Not sure I understand the question - What are you proposing we do and why ?

Not a proposal, I just want to learn how these files are created and maintained.

If you want a "why?":
- why don't I see any individual source files under version control?
Comment 6 Stephan Herrmann CLA 2012-09-06 09:56:34 EDT
There are 5 more distinct test cases failing on the new JRE:

org.eclipse.jdt.core.tests.compiler.regression.JavadocTestForClass
 - test054
 - test055
 - test056
org.eclipse.jdt.core.tests.compiler.regression.VarargsTest
 - test066
org.eclipse.jdt.core.tests.compiler.regression.GenericTypeTest
 - test0809

Failures in VarargsTest and GenericTypeTest are again caused by Iterator.remove() having an implementation now.
(comment 0 should've said Iterator, too, List.remove() is not part of the game).


Failures in JavadocTestForClass report problems like:

public interface X extends Map {
                 ^
The return types are incompatible for the inherited methods MapStream.values(), Map.values()

Type MapStream is new in 1.8, it declares:

     Iterable<V> values();

Now Map says:

  public interface Map<K,V> extends MapStream<K, V> {
  ...
     Collection<V> values();

Given that Collection<E> extends Iterable<E> this should be a legal covariant override. Looks like a bug in our compiler to complain if an interface just tries to extend Map<#RAW>.
Comment 7 Stephan Herrmann CLA 2012-09-06 10:49:17 EDT
My previous judgement re Iterator.remove() was wrong: the extra errors are caused by the fact that our compiler sees this default method as a regular non-abstract method.

Instead of changing the tests we should fix bug 388954.
Comment 8 Stephan Herrmann CLA 2012-09-06 12:18:44 EDT
With my current thinking regarding bug 388954 we'll end up with roughly 100 tests that cannot run on JRE 8. I hope it's all a misunderstanding on my side and someone has a more compelling compatibility story here.
Comment 9 Srikanth Sankaran CLA 2012-09-20 05:23:48 EDT
(In reply to comment #8)
> With my current thinking regarding bug 388954 we'll end up with roughly 100
> tests that cannot run on JRE 8. I hope it's all a misunderstanding on my
> side and someone has a more compelling compatibility story here.

I am sorry - this is a bit confusing due to some going back and forth as
you pieced together the puzzle. If for https://bugs.eclipse.org/bugs/show_bug.cgi?id=388954, we say the right course is to force inject the AccAbstract flag
on default methods while compiling for 1.7-, do we still have issues here ?

Is the question of how to proceed on bug 388954 the only question or are
there more ?
Comment 10 Srikanth Sankaran CLA 2012-09-20 05:44:52 EDT
(In reply to comment #9)

Just realized that 308 and 335 early access compilers come from different
branches. This is further going to make for interesting times. We need to
build in as much resilience as possible into the tests.
Comment 11 Stephan Herrmann CLA 2012-09-24 19:12:13 EDT
(In reply to comment #9)
> I am sorry - this is a bit confusing due to some going back and forth as
> you pieced together the puzzle.

I'm sorry, indeed I was oscillating between "oh, that's easy" and "No, that can't be!".

> If for
> https://bugs.eclipse.org/bugs/show_bug.cgi?id=388954, we say the right course is
> to force inject the AccAbstract flag
> on default methods while compiling for 1.7-, do we still have issues here ?

Yes. See below.
 
> Is the question of how to proceed on bug 388954 the only question or are
> there more ?

- with the above strategy for bug 388954, JDT/Core tests exhibit 102 failures.
- most of these relate to classes that fail to implement a method from their declared superinterface (a newly introduced default method forced to be considered as abstract in 1.7-)
- some failures I haven't yet analyzed.
- one issue is fundamentally new: the expected test result now depends on two versions instead of one:
  - the compliance level the test runs in (old)
  - the JRE that the test runs *on* (new)
That last item is what worries me: tests that are supposed to pass, will fail when run on 1.8 JRE and we'll probably have to provide different test-*input* depending on the JRE we run on.
Tests will effectively be matrix-based (JRE x compliance).
Comment 12 Stephan Herrmann CLA 2012-09-24 19:20:45 EDT
Created attachment 221447 [details]
test results

FYI this is the junit-export showing the 102 failures.
Comment 13 Stephan Herrmann CLA 2012-09-24 19:33:30 EDT
For easier access here's the list of unique failing test cases (multiply by compliance levels):

I'll try to classify those, later.

org.eclipse.jdt.core.tests.compiler.regression.AmbiguousMethodTest.test009
org.eclipse.jdt.core.tests.compiler.regression.ForeachStatementTest.test023
org.eclipse.jdt.core.tests.compiler.regression.ForeachStatementTest.test034
org.eclipse.jdt.core.tests.compiler.regression.ForeachStatementTest.test035
org.eclipse.jdt.core.tests.compiler.regression.ForeachStatementTest.test036
org.eclipse.jdt.core.tests.compiler.regression.GenericTypeTest.test0146
org.eclipse.jdt.core.tests.compiler.regression.GenericTypeTest.test0149
org.eclipse.jdt.core.tests.compiler.regression.GenericTypeTest.test0204
org.eclipse.jdt.core.tests.compiler.regression.GenericTypeTest.test0298
org.eclipse.jdt.core.tests.compiler.regression.GenericTypeTest.test0316
org.eclipse.jdt.core.tests.compiler.regression.GenericTypeTest.test0361
org.eclipse.jdt.core.tests.compiler.regression.GenericTypeTest.test0379
org.eclipse.jdt.core.tests.compiler.regression.GenericTypeTest.test0460
org.eclipse.jdt.core.tests.compiler.regression.GenericTypeTest.test0766
org.eclipse.jdt.core.tests.compiler.regression.GenericTypeTest.test0767
org.eclipse.jdt.core.tests.compiler.regression.GenericTypeTest.test0779
org.eclipse.jdt.core.tests.compiler.regression.GenericTypeTest.test0868
org.eclipse.jdt.core.tests.compiler.regression.GenericTypeTest.test0968
org.eclipse.jdt.core.tests.compiler.regression.GenericTypeTest.test0992
org.eclipse.jdt.core.tests.compiler.regression.GenericTypeTest.test1030
org.eclipse.jdt.core.tests.compiler.regression.GenericTypeTest.test1035
org.eclipse.jdt.core.tests.compiler.regression.GenericTypeTest.test1137
org.eclipse.jdt.core.tests.compiler.regression.GenericTypeTest.test1358
org.eclipse.jdt.core.tests.compiler.regression.InnerEmulationTest.test173
org.eclipse.jdt.core.tests.compiler.regression.InnerEmulationTest.test174
org.eclipse.jdt.core.tests.compiler.regression.JavadocTestForClass.test054
org.eclipse.jdt.core.tests.compiler.regression.JavadocTestForClass.test055
org.eclipse.jdt.core.tests.compiler.regression.JavadocTestForClass.test056
org.eclipse.jdt.core.tests.compiler.regression.LookupTest.test075
org.eclipse.jdt.core.tests.compiler.regression.MethodVerifyTest.test026b
org.eclipse.jdt.core.tests.compiler.regression.MethodVerifyTest.test088
org.eclipse.jdt.core.tests.compiler.regression.MethodVerifyTest.test089
org.eclipse.jdt.core.tests.compiler.regression.MethodVerifyTest.test091
org.eclipse.jdt.core.tests.compiler.regression.MethodVerifyTest.test092
org.eclipse.jdt.core.tests.compiler.regression.MethodVerifyTest.test093
org.eclipse.jdt.core.tests.compiler.regression.MethodVerifyTest.test203
org.eclipse.jdt.core.tests.compiler.regression.MethodVerifyTest.test331446
org.eclipse.jdt.core.tests.compiler.regression.MethodVerifyTest.test331446a
org.eclipse.jdt.core.tests.compiler.regression.StackMapAttributeTest.test018
org.eclipse.jdt.core.tests.compiler.regression.SuperTypeTest.test013
org.eclipse.jdt.core.tests.compiler.regression.SwitchTest.testMultipleSwitches
Comment 14 Srikanth Sankaran CLA 2012-09-24 22:33:35 EDT
(In reply to comment #11)

> > If for
> > https://bugs.eclipse.org/bugs/show_bug.cgi?id=388954, we say the right course is
> > to force inject the AccAbstract flag
> > on default methods while compiling for 1.7-, do we still have issues here ?
> 
> Yes. See below.

Thanks, I understand better now.
 
> > Is the question of how to proceed on bug 388954 the only question or are
> > there more ?
> 
> - with the above strategy for bug 388954, JDT/Core tests exhibit 102
> failures.

Now, is there any question that this is the most reasonable strategy ?
Given this is how javac is behaving ? 

> - most of these relate to classes that fail to implement a method from their
> declared superinterface (a newly introduced default method forced to be
> considered as abstract in 1.7-)

So to confirm, the code from this category of tests as is will also fail
to compile with JDK8 - right ? 

Does this category of failures lend themselves to a resilient fix by providing
an implementation ? Or does that somehow mess up the test ?

> - one issue is fundamentally new: the expected test result now depends on
> two versions instead of one:
>   - the compliance level the test runs in (old)
>   - the JRE that the test runs *on* (new)
> That last item is what worries me: tests that are supposed to pass, will
> fail when run on 1.8 JRE and we'll probably have to provide different
> test-*input* depending on the JRE we run on.

This is due to the same underlying cause as above ? as in the test failing 
to build against JRE8 due to a brand new default method showing up ? If so
does providing a stub implementation work ? (same question asked earlier)

I am comfortable if this is the situation with a small number of tests 
cases (that may gradually expand over time.) I would not codify any behavior
that is not javac compliant, but otherwise it is ok.
Comment 15 Stephan Herrmann CLA 2012-09-25 05:14:27 EDT
(In reply to comment #14)

Looking at the issues immediately at hand (spec, javac, tests) I can answer all your questions affirmatively.

My uneasy feelings can be concretized like this:

Assume a team develops code for Java X, they have their build server properly configured to compile for and with Java X, so all compatibility errors are detected. Projects properly configure the compiler for compliance Java X. Individual developers are allowed to install any Java Y for Y >= X on their machines. 

In this situation for Y <= 7 the worst thing that could happen is: developer writes code that calls a method introduced in Java Y, which compiles fine locally but will be detected on the build server. This is tolerable. The build server detects all problems and all code accepted on the build server also compiles on all developer machines.

Starting with Y = 8 we have a new kind of issue: a developer who installed Java Y on his local machine will see new compile errors despite the compiler settings. The code may be unchanged since years and the project configuration remains unchanged. Still it cannot be compiled unless also the older JRE X is installed and bound.

I'm afraid that many developers will not be happy with this situation. I expect a significant number of future bug reports along these lines.
Comment 16 Srikanth Sankaran CLA 2012-09-25 05:20:31 EDT
Dani & Markus,



(In reply to comment #15)
> (In reply to comment #14)
> 
> Looking at the issues immediately at hand (spec, javac, tests) I can answer
> all your questions affirmatively.
> 
> My uneasy feelings can be concretized like this:
> 
> Assume a team develops code for Java X, they have their build server
> properly configured to compile for and with Java X, so all compatibility
> errors are detected. Projects properly configure the compiler for compliance
> Java X. Individual developers are allowed to install any Java Y for Y >= X
> on their machines. 
> 
> In this situation for Y <= 7 the worst thing that could happen is: developer
> writes code that calls a method introduced in Java Y, which compiles fine
> locally but will be detected on the build server. This is tolerable. The
> build server detects all problems and all code accepted on the build server
> also compiles on all developer machines.
> 
> Starting with Y = 8 we have a new kind of issue: a developer who installed
> Java Y on his local machine will see new compile errors despite the compiler
> settings. The code may be unchanged since years and the project
> configuration remains unchanged. Still it cannot be compiled unless also the
> older JRE X is installed and bound.
> 
> I'm afraid that many developers will not be happy with this situation. I
> expect a significant number of future bug reports along these lines.
Comment 17 Srikanth Sankaran CLA 2012-09-25 05:24:18 EDT
Dani & Markus,

    What is your take on this matter ? Stephan is raising alert on a situation
where Java 7- code will not compile against JRE8 due to the presence of default
methods that never existed in an extant interface (not just providing a default
implementation for an existing abstract method.)

    For the time being we are converging on an approach that will be
compatible with javac8 - where code that used to compile will stop compiling
when built against JRE8.
Comment 18 Stephan Herrmann CLA 2012-09-25 05:37:07 EDT
Pondering more the potential solution space I fail to see a good strategy given that JRE8 introduces default methods in both these ways:
a. introduce new interface methods and avoid compatibility issues by giving a default implementation (good)
b. change existing interface methods into default methods

This makes me wonder whether (b) is actually a good idea, it causes far more trouble than I can see benefit in it. With only (a) the compiler could much better cope with the situation. Of course we can't prevent all library vendors from doing (b) but seeing this in the JRE looks wrong to me.
Comment 19 Stephan Herrmann CLA 2012-09-25 07:52:57 EDT
(In reply to comment #14)
> (In reply to comment #11)
> > - most of these relate to classes that fail to implement a method from their
> > declared superinterface (a newly introduced default method forced to be
> > considered as abstract in 1.7-)
> 
> So to confirm, the code from this category of tests as is will also fail
> to compile with JDK8 - right ?
> 
> Does this category of failures lend themselves to a resilient fix by providing
> an implementation ? Or does that somehow mess up the test ?

Yes, it works, kind-of, but while inching along I see that still the tests have to check the host JRE because those stubs will have to refer to types (mostly from java.util.functions) which are not present in 1.7-. Sigh.
Comment 20 Stephan Herrmann CLA 2012-09-25 17:52:09 EDT
(In reply to comment #18)
> b. change existing interface methods into default methods

I just noticed that my previous example was slightly off, here is the corrected example:

Method java.util.Iterator#remove().

Java7:
    void remove();

Java8-lambda:
    void remove() default {
        throw new UnsupportedOperationException("remove");
    }

To illustrate my point in comment 18: If we could rule out this kind of introduction we *could* say: if in 1.7- mode we see
- a non-abstract interface method
- a class that implements the interface but does not implement this method
we could classify this as an "unavoidable compatibility issue" and allow to downgrade this to warning or ignore (assuming the default method doesn't exist in the 1.7 target platform).
However, due to examples like the above it would be wrong to downgrade, because on the intended target platform this interface method exists as an abstract method and not implementing it is a definite error.
Comment 21 Stephan Herrmann CLA 2012-09-25 19:00:11 EDT
Back to the task of adjusting the tests for JRE8:

in bug 388954 I did most of the leg work [1] to handle all combinations of compliance and JRE, with these results currently:
- all JDT/Core tests are green on JRE7
- tests are green with compliance 1.7- on JRE8-lambda
- tests with compliance 1.8 on JRE8-lambda show some failures:
  - 16 instances of of bug 382347 comment 6 (re-opened)

[1] commit dd3bff4d99a5193497eb7e3c0e1bc46a32b7c36a
Comment 22 Markus Keller CLA 2012-09-26 10:41:41 EDT
Mixed setups are always problematic and will bite the user sooner or later. Filed bug 390446 to set the existing diagnostic for this problem to "warning" by default.

The Java 8 spec doesn't have to care about this, since this not a setup that is supported by the spec.

In Eclipse, we should support the invalid setup as good as we can, but if it's impossible or too much work, then that's also OK.

> a. introduce new interface methods and avoid compatibility issues by giving a
> default implementation (good)
> b. change existing interface methods into default methods

Since the class file will not allow to distinguish the two cases, I guess the best fallback we could have is to consider all default methods as abstract interface methods when the source level is smaller than 1.8.
Comment 23 Srikanth Sankaran CLA 2012-09-26 22:01:52 EDT
(In reply to comment #22)

> Since the class file will not allow to distinguish the two cases, I guess
> the best fallback we could have is to consider all default methods as
> abstract interface methods when the source level is smaller than 1.8.

Thanks for weighing in Markus. Since this is also how javac8 behaves when invoked
with -source 1.7 option, I would settle for this unless other considerations
emerge.
Comment 24 Srikanth Sankaran CLA 2012-10-02 02:47:53 EDT
I think this can be closed now that all tests are green
with the resolution of https://bugs.eclipse.org/bugs/show_bug.cgi?id=390761.

We have two separate issues:

    - How do manage/maintain our test suite - solved.
    - What should we do when we encounter this scenario in a user application
      build set up.

I suggest we track the latter in a separate issue and per comment#22 
evaluate how to "support the invalid setup as good as we can". 
Could you please crisply document the problem scenarios annotating each
with a small snippet and also our options at https://bugs.eclipse.org/bugs/show_bug.cgi?id=390889 ? Thanks, I would
place the actual work at lower priority than other default methods
related issues, though discussions could be initiated right away as
and when you are able to find time.
Comment 25 Srikanth Sankaran CLA 2012-10-02 04:01:33 EDT
Pushed a minor tweak to a test that fails with JRE7. With this all tests are
green on JRE7 also.
Comment 26 Srikanth Sankaran CLA 2012-10-02 07:20:19 EDT
For good measure, I verified that the tests are all green with JRE7s
of both IBM and Sun vintage. 

Resolving as all is well now.