Skip to content

Fix some WebSocket test handlers#7345

Merged
ricea merged 2 commits intoweb-platform-tests:masterfrom
ricea:fix-pywebsocket-handlers
Nov 9, 2017
Merged

Fix some WebSocket test handlers#7345
ricea merged 2 commits intoweb-platform-tests:masterfrom
ricea:fix-pywebsocket-handlers

Conversation

@ricea
Copy link
Contributor

@ricea ricea commented Sep 14, 2017

Several of the pywebsocket handlers used in tests had the problem that they
would generate a hand-crafted header and then pywebsocket would add its own
header immediately afterwards, causing unnecessary errors.

In most cases there was no need to generate a hand-crafted header at all, so the
tests have been modified to use pywebsocket APIs to do the same
thing. simple_handshake_wsh.py still generates a hand-crafted header but now
suppresses pywebsocket's own header.

Several tests closed the WebSocket on the client side but the handler didn't
wait to receive the client-side close. These have been modified to wait for the
close frame.

Several tests had expectations that onclose would never be called but then
called close() themselves, causing onclose to be called. In some cases this was
mitigated by calling t.done() before t.unreached_func() was called, but it has
been fixed by disabling the onclose handler after calling close().

This change only fixes a subset of handlers and their affected tests. It is not
intended to be comprehensive, and many issues remain.

Several of the pywebsocket handlers used in tests had the problem that they
would generate a hand-crafted header and then pywebsocket would add its own
header immediately afterwards, causing unnecessary errors.

In most cases there was no need to generate a hand-crafted header at all, so the
tests have been modified to use pywebsocket APIs to do the same
thing. simple_handshake_wsh.py still generates a hand-crafted header but now
suppresses pywebsocket's own header.

Several tests closed the WebSocket on the client side but the handler didn't
wait to receive the client-side close. These have been modified to wait for the
close frame.

Several tests had expectations that onclose would never be called but then
called close() themselves, causing onclose to be called. In some cases this was
mitigated by calling t.done() before t.unreached_func() was called, but it has
been fixed by disabling the onclose handler after calling close().

This change only fixes a subset of handlers and their affected tests. It is not
intended to be comprehensive, and many issues remain.
@ghost
Copy link

ghost commented Sep 14, 2017

Build PASSED

Started: 2017-10-04 06:05:49
Finished: 2017-10-04 06:11:42

View more information about this build on:

@ricea
Copy link
Contributor Author

ricea commented Sep 14, 2017

@tyoshino PTAL

@Ms2ger
Copy link
Contributor

Ms2ger commented Oct 3, 2017

Several tests had expectations that onclose would never be called but then called close() themselves, causing onclose to be called. In some cases this was mitigated by calling t.done() before t.unreached_func() was called, but it has been fixed by disabling the onclose handler after calling close().

I don't think these particular changes are necessary or helpful.

@ricea
Copy link
Contributor Author

ricea commented Oct 3, 2017

I don't think these particular changes are necessary or helpful.

I have two problems with the way this works at the moment:

  1. We're relying on the test harness to ignore assertion failures that happen after we call done(). I don't know whether this is common practice, but it seems risky and fragile to me to ignore assertion failures at any time.
  2. It makes the test misleading. As written, anyone reading the test could reasonably conclude that onclose is never called, but that is not the case.

@Ms2ger
Copy link
Contributor

Ms2ger commented Oct 3, 2017

This is very much part of the design of the test harness; perhaps @gsnedders has thoughts.

@gsnedders
Copy link
Member

I've never touched any of this; defer to @jgraham.

Copy link

@tyoshino tyoshino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even if the design guarantees that, I'd like to vote for the change considering ricea's second point.


from mod_pywebsocket import common, msgutil, util
from mod_pywebsocket.handshake import hybi
import struct
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Must have been leftover from a previous iteration.

# to use the stream methods at this point because the stream hasn't been
# established from pywebsocket's point of view. Instead just read the
# appropriate number of bytes and assume they are correct.
request.connection.read(8)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we need to emulate _stream_base.receive_bytes() here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's safe to assume that if we got any bytes at all then the close frame has been sent.

It's possible that a browser could send the close frame fragmented into two parts, the server closes the connection after the first fragment and the browser gets a "Connection reset by peer" error and sets wasClean to false. But I know of no reason why a browser would fragment the close frame.

This handler is already complicated and probably pointless, so I don't want to complicate it any further.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

Copy link

@tyoshino tyoshino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy with the current patch. You can wait for jgraham's comment regarding usage of done().

@ricea
Copy link
Contributor Author

ricea commented Oct 18, 2017

@jgraham, do you have any comments on whether asserting after a async_test is done is good practice?

@ricea ricea merged commit bb8b207 into web-platform-tests:master Nov 9, 2017
@ricea ricea deleted the fix-pywebsocket-handlers branch November 9, 2017 05:45
@gsnedders
Copy link
Member

@ricea I'd hope we ignore such asserts? Probably even set the test/harness to ERROR.

@ricea
Copy link
Contributor Author

ricea commented Nov 9, 2017

@gsnedders The asserts were ignored. I found it surprising. I see the situation with uncaught promise rejections in promise_tests as analogous. Uncaught rejections cause the whole page to fail, even though they can't be attributed to a single test.

@gsnedders
Copy link
Member

@ricea Likewise uncaught exceptions do. We should definitely fix this. Lemme file a bug.

@gsnedders
Copy link
Member

Oh, thinking about this, it may actually be unsolvable as long as assertions aren't linked directly to tests and only are processed as a result of them throwing an exception. We definitely can't ever catch assert_true(true) even if it's after being done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants