| | import pytest |
| |
|
| | from .._events import * |
| | from .._state import * |
| | from .._state import _SWITCH_CONNECT, _SWITCH_UPGRADE, ConnectionState |
| | from .._util import LocalProtocolError |
| |
|
| |
|
| | def test_ConnectionState(): |
| | cs = ConnectionState() |
| |
|
| | |
| |
|
| | assert cs.states == {CLIENT: IDLE, SERVER: IDLE} |
| |
|
| | cs.process_event(CLIENT, Request) |
| | |
| | assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_RESPONSE} |
| |
|
| | |
| | with pytest.raises(LocalProtocolError): |
| | cs.process_event(CLIENT, Request) |
| | assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_RESPONSE} |
| |
|
| | cs.process_event(SERVER, InformationalResponse) |
| | assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_RESPONSE} |
| |
|
| | cs.process_event(SERVER, Response) |
| | assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_BODY} |
| |
|
| | cs.process_event(CLIENT, EndOfMessage) |
| | cs.process_event(SERVER, EndOfMessage) |
| | assert cs.states == {CLIENT: DONE, SERVER: DONE} |
| |
|
| | |
| |
|
| | cs.process_event(SERVER, ConnectionClosed) |
| | assert cs.states == {CLIENT: MUST_CLOSE, SERVER: CLOSED} |
| |
|
| |
|
| | def test_ConnectionState_keep_alive(): |
| | |
| | cs = ConnectionState() |
| | cs.process_event(CLIENT, Request) |
| | cs.process_keep_alive_disabled() |
| | cs.process_event(CLIENT, EndOfMessage) |
| | assert cs.states == {CLIENT: MUST_CLOSE, SERVER: SEND_RESPONSE} |
| |
|
| | cs.process_event(SERVER, Response) |
| | cs.process_event(SERVER, EndOfMessage) |
| | assert cs.states == {CLIENT: MUST_CLOSE, SERVER: MUST_CLOSE} |
| |
|
| |
|
| | def test_ConnectionState_keep_alive_in_DONE(): |
| | |
| | |
| | |
| | cs = ConnectionState() |
| | cs.process_event(CLIENT, Request) |
| | cs.process_event(CLIENT, EndOfMessage) |
| | assert cs.states[CLIENT] is DONE |
| | cs.process_keep_alive_disabled() |
| | assert cs.states[CLIENT] is MUST_CLOSE |
| |
|
| |
|
| | def test_ConnectionState_switch_denied(): |
| | for switch_type in (_SWITCH_CONNECT, _SWITCH_UPGRADE): |
| | for deny_early in (True, False): |
| | cs = ConnectionState() |
| | cs.process_client_switch_proposal(switch_type) |
| | cs.process_event(CLIENT, Request) |
| | cs.process_event(CLIENT, Data) |
| | assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_RESPONSE} |
| |
|
| | assert switch_type in cs.pending_switch_proposals |
| |
|
| | if deny_early: |
| | |
| | cs.process_event(SERVER, Response) |
| | assert not cs.pending_switch_proposals |
| |
|
| | cs.process_event(CLIENT, EndOfMessage) |
| |
|
| | if deny_early: |
| | assert cs.states == {CLIENT: DONE, SERVER: SEND_BODY} |
| | else: |
| | assert cs.states == { |
| | CLIENT: MIGHT_SWITCH_PROTOCOL, |
| | SERVER: SEND_RESPONSE, |
| | } |
| |
|
| | cs.process_event(SERVER, InformationalResponse) |
| | assert cs.states == { |
| | CLIENT: MIGHT_SWITCH_PROTOCOL, |
| | SERVER: SEND_RESPONSE, |
| | } |
| |
|
| | cs.process_event(SERVER, Response) |
| | assert cs.states == {CLIENT: DONE, SERVER: SEND_BODY} |
| | assert not cs.pending_switch_proposals |
| |
|
| |
|
| | _response_type_for_switch = { |
| | _SWITCH_UPGRADE: InformationalResponse, |
| | _SWITCH_CONNECT: Response, |
| | None: Response, |
| | } |
| |
|
| |
|
| | def test_ConnectionState_protocol_switch_accepted(): |
| | for switch_event in [_SWITCH_UPGRADE, _SWITCH_CONNECT]: |
| | cs = ConnectionState() |
| | cs.process_client_switch_proposal(switch_event) |
| | cs.process_event(CLIENT, Request) |
| | cs.process_event(CLIENT, Data) |
| | assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_RESPONSE} |
| |
|
| | cs.process_event(CLIENT, EndOfMessage) |
| | assert cs.states == {CLIENT: MIGHT_SWITCH_PROTOCOL, SERVER: SEND_RESPONSE} |
| |
|
| | cs.process_event(SERVER, InformationalResponse) |
| | assert cs.states == {CLIENT: MIGHT_SWITCH_PROTOCOL, SERVER: SEND_RESPONSE} |
| |
|
| | cs.process_event(SERVER, _response_type_for_switch[switch_event], switch_event) |
| | assert cs.states == {CLIENT: SWITCHED_PROTOCOL, SERVER: SWITCHED_PROTOCOL} |
| |
|
| |
|
| | def test_ConnectionState_double_protocol_switch(): |
| | |
| | |
| | for server_switch in [None, _SWITCH_UPGRADE, _SWITCH_CONNECT]: |
| | cs = ConnectionState() |
| | cs.process_client_switch_proposal(_SWITCH_UPGRADE) |
| | cs.process_client_switch_proposal(_SWITCH_CONNECT) |
| | cs.process_event(CLIENT, Request) |
| | cs.process_event(CLIENT, EndOfMessage) |
| | assert cs.states == {CLIENT: MIGHT_SWITCH_PROTOCOL, SERVER: SEND_RESPONSE} |
| | cs.process_event( |
| | SERVER, _response_type_for_switch[server_switch], server_switch |
| | ) |
| | if server_switch is None: |
| | assert cs.states == {CLIENT: DONE, SERVER: SEND_BODY} |
| | else: |
| | assert cs.states == {CLIENT: SWITCHED_PROTOCOL, SERVER: SWITCHED_PROTOCOL} |
| |
|
| |
|
| | def test_ConnectionState_inconsistent_protocol_switch(): |
| | for client_switches, server_switch in [ |
| | ([], _SWITCH_CONNECT), |
| | ([], _SWITCH_UPGRADE), |
| | ([_SWITCH_UPGRADE], _SWITCH_CONNECT), |
| | ([_SWITCH_CONNECT], _SWITCH_UPGRADE), |
| | ]: |
| | cs = ConnectionState() |
| | for client_switch in client_switches: |
| | cs.process_client_switch_proposal(client_switch) |
| | cs.process_event(CLIENT, Request) |
| | with pytest.raises(LocalProtocolError): |
| | cs.process_event(SERVER, Response, server_switch) |
| |
|
| |
|
| | def test_ConnectionState_keepalive_protocol_switch_interaction(): |
| | |
| | cs = ConnectionState() |
| | cs.process_client_switch_proposal(_SWITCH_UPGRADE) |
| | cs.process_event(CLIENT, Request) |
| | cs.process_keep_alive_disabled() |
| | cs.process_event(CLIENT, Data) |
| | assert cs.states == {CLIENT: SEND_BODY, SERVER: SEND_RESPONSE} |
| |
|
| | |
| | cs.process_event(CLIENT, EndOfMessage) |
| | assert cs.states == {CLIENT: MIGHT_SWITCH_PROTOCOL, SERVER: SEND_RESPONSE} |
| |
|
| | |
| | cs.process_event(SERVER, Response) |
| | assert cs.states == {CLIENT: MUST_CLOSE, SERVER: SEND_BODY} |
| |
|
| |
|
| | def test_ConnectionState_reuse(): |
| | cs = ConnectionState() |
| |
|
| | with pytest.raises(LocalProtocolError): |
| | cs.start_next_cycle() |
| |
|
| | cs.process_event(CLIENT, Request) |
| | cs.process_event(CLIENT, EndOfMessage) |
| |
|
| | with pytest.raises(LocalProtocolError): |
| | cs.start_next_cycle() |
| |
|
| | cs.process_event(SERVER, Response) |
| | cs.process_event(SERVER, EndOfMessage) |
| |
|
| | cs.start_next_cycle() |
| | assert cs.states == {CLIENT: IDLE, SERVER: IDLE} |
| |
|
| | |
| |
|
| | cs.process_event(CLIENT, Request) |
| | cs.process_keep_alive_disabled() |
| | cs.process_event(CLIENT, EndOfMessage) |
| | cs.process_event(SERVER, Response) |
| | cs.process_event(SERVER, EndOfMessage) |
| |
|
| | with pytest.raises(LocalProtocolError): |
| | cs.start_next_cycle() |
| |
|
| | |
| |
|
| | cs = ConnectionState() |
| | cs.process_event(CLIENT, Request) |
| | cs.process_event(CLIENT, EndOfMessage) |
| | cs.process_event(CLIENT, ConnectionClosed) |
| | cs.process_event(SERVER, Response) |
| | cs.process_event(SERVER, EndOfMessage) |
| |
|
| | with pytest.raises(LocalProtocolError): |
| | cs.start_next_cycle() |
| |
|
| | |
| |
|
| | cs = ConnectionState() |
| | cs.process_client_switch_proposal(_SWITCH_UPGRADE) |
| | cs.process_event(CLIENT, Request) |
| | cs.process_event(CLIENT, EndOfMessage) |
| | cs.process_event(SERVER, InformationalResponse, _SWITCH_UPGRADE) |
| |
|
| | with pytest.raises(LocalProtocolError): |
| | cs.start_next_cycle() |
| |
|
| | |
| |
|
| | cs = ConnectionState() |
| | cs.process_client_switch_proposal(_SWITCH_UPGRADE) |
| | cs.process_event(CLIENT, Request) |
| | cs.process_event(CLIENT, EndOfMessage) |
| | cs.process_event(SERVER, Response) |
| | cs.process_event(SERVER, EndOfMessage) |
| |
|
| | cs.start_next_cycle() |
| | assert cs.states == {CLIENT: IDLE, SERVER: IDLE} |
| |
|
| |
|
| | def test_server_request_is_illegal(): |
| | |
| | |
| | cs = ConnectionState() |
| | with pytest.raises(LocalProtocolError): |
| | cs.process_event(SERVER, Request) |
| |
|