Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 369652 - SslSocketServerTest.testAvailable() fails with jdk7
Summary: SslSocketServerTest.testAvailable() fails with jdk7
Status: CLOSED FIXED
Alias: None
Product: Jetty
Classification: RT
Component: server (show other bugs)
Version: unspecified   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: 7.5.x   Edit
Assignee: Greg Wilkins CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-01-25 08:09 EST by Thomas Becker CLA
Modified: 2012-04-02 09:10 EDT (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Becker CLA 2012-01-25 08:09:07 EST
Build Identifier: 

Root cause is that InputStream.available() calls do not return the expected values as defined in the test.

The same test works fine on jdk6. SocketServerTest (without ssl) works fine on both jdk6 and 7.

All expected data can be read from the InputStream, but available returns different values than expected.

After the request + headers the following data is sent to the server:

"1234567890"
os.flush()
"abcdefghijklmnopqrst"
os.flush()

In jdk6 and without ssl on jdk7 the available calls in HttpServerTestBase.AvailableHandler return (in this order):

10 (for the 10 digits)
0
20 (for the 20 chars a-t)
0

In jdk7 however with ssl we get different chunks:

1 (for the first digit "1")
0
9 (for the remaining digits 234567890)
0

If you modify the AvailableHandler to continue reading on the InputStream you'll get the remaining chars. 

I've not (yet) tracked down the root cause of the different behaviour in jdk7 as this would require quite some time. In my opinion it's wrong to have the test rely on is.available(). Instead we should modify it to simply return the whole request data and assert that the returned data matches the sent data. If you agree feel free to assign this issue back to me and I will modify the test accordingly.
If I should dig deeper into the root cause, let me know as well. 

Reproducible: Always
Comment 1 Greg Wilkins CLA 2012-01-25 08:34:54 EST
I think we should just test that available is >0 rather than test for absolute values.
Comment 2 Thomas Becker CLA 2012-01-25 08:36:46 EST
But this alone won't fix the test. As with jdk7 + ssl we get 2 data chunks already for the first 10 digits. Whereas this was one 10 byte chunk with jdk6.

I think we shouldn't assert on available at all and just read the whole data and match it against what we've sent.
Comment 3 Thomas Becker CLA 2012-01-25 11:42:11 EST
As stated above the 4 original calls to java.io.InputStream.available() return:

1 0 9 0

available() keeps returning 0 from that point on until I do exactly TWO more in.read() calls. Then it returns 18 (20 - two bytes I've already read).

It's the underlying sun.security.ssl.AppInputStream returning different sized chunks of data. 

The corresponding change in the jdk is this one:

http://hg.openjdk.java.net/jdk7u/jdk7u-osx/jdk/rev/14d8cc19f227
Comment 4 Thomas Becker CLA 2012-01-26 13:47:52 EST
I've successfully replicated this with a simple test establishing an ssl connection and sending some bytes over the wire.

From the client I'm doing the following:

 OutputStream os = clientSocket.getOutputStream();
 os.write("1234567890".getBytes());
 os.flush();
        
 os.write("abcdefghijklmnopqrst".getBytes());
 os.flush();

During reading on the server I write the following to stdout (see the code for details):

is.available()
read one byte and write it to stdout
is.available()
write all available bytes to stdout if available>0

reiterate

The debug output is:

Waiting for connection
Connection from: /127.0.0.1:60812
Iteration: 0

avail: 0
read this byte individually: 1
avail: 9
Buffer after we read all available bytes: 1234567890
Iteration: 1

avail: 0
read this byte individually: a
avail: 0
Buffer after we read all available bytes: a
Iteration: 2

avail: 0
read this byte individually: b
avail: 18
Buffer after we read all available bytes: bcdefghijklmnopqrst
Iteration: 3

avail: 0

As you can see when writing the chars a-t I'm getting the "a" on the first manual read() call. Then available() keeps 0 until I've done another manual read() "b". Then it turns to 18 (the remaining bytes to read).

I've shared the maven project on github: 
https://github.com/thomasbecker/sslavailableissue

I'm trying to debug this a bit further, but am having issues attaching the jdk sources to eclipse for some reason. Will try again tomorrow.