Пример #1
0
async def test_camera_snapshot_times_out(driver):
    """Test camera snapshot times out."""
    loop = MagicMock()
    transport = MagicMock()
    connections = {}

    def _get_snapshot(*_):
        raise asyncio.TimeoutError("timeout")

    acc = Accessory(driver, "TestAcc")
    acc.get_snapshot = _get_snapshot
    driver.add_accessory(acc)

    hap_proto = hap_protocol.HAPServerProtocol(loop, connections, driver)
    hap_proto.connection_made(transport)

    hap_proto.hap_crypto = MockHAPCrypto()
    hap_proto.handler.is_encrypted = True

    with patch.object(hap_proto.transport, "write") as writer:
        hap_proto.data_received(
            b'POST /resource HTTP/1.1\r\nHost: HASS\\032Bridge\\032BROZ\\0323BF435._hap._tcp.local\r\nContent-Length: 79\r\nContent-Type: application/hap+json\r\n\r\n{"image-height":360,"resource-type":"image","image-width":640,"aid":1411620844}'  # pylint: disable=line-too-long
        )
        try:
            await hap_proto.response.task
        except Exception:  # pylint: disable=broad-except
            pass
        await asyncio.sleep(0)

    assert b"-70402" in writer.call_args_list[0][0][0]

    hap_proto.close()
Пример #2
0
def test_upgrade_to_encrypted(driver):
    """Test we switch to encrypted wen we get a shared_key."""
    loop = MagicMock()
    transport = MagicMock()
    connections = {}

    acc = Accessory(driver, "TestAcc")
    driver.add_accessory(acc)

    hap_proto = hap_protocol.HAPServerProtocol(loop, connections, driver)
    hap_proto.connection_made(transport)

    assert hap_proto.hap_crypto is None

    def _make_response(*_):
        response = HAPResponse()
        response.shared_key = b"newkey"
        return response

    with patch.object(hap_proto.transport, "write"), patch.object(
        hap_proto.handler, "dispatch", _make_response
    ):
        hap_proto.data_received(
            b"POST /pair-setup HTTP/1.1\r\nHost: Bridge\\032C77C47._hap._tcp.local\r\nContent-Length: 6\r\nContent-Type: application/pairing+tlv8\r\n\r\n\x00\x01\x00\x06\x01\x01"  # pylint: disable=line-too-long
        )

    assert hap_proto.hap_crypto is not None

    hap_proto.close()
Пример #3
0
async def test_pairing_changed(driver):
    """Test we update mdns when the pairing changes."""
    loop = MagicMock()

    run_in_executor_called = False

    async def _run_in_executor(*_):
        nonlocal run_in_executor_called
        run_in_executor_called = True

    loop.run_in_executor = _run_in_executor
    transport = MagicMock()
    connections = {}

    acc = Accessory(driver, "TestAcc")
    driver.add_accessory(acc)

    hap_proto = hap_protocol.HAPServerProtocol(loop, connections, driver)
    hap_proto.connection_made(transport)

    def _make_response(*_):
        response = HAPResponse()
        response.pairing_changed = True
        return response

    with patch.object(hap_proto.transport, "write"), patch.object(
        hap_proto.handler, "dispatch", _make_response
    ):
        hap_proto.data_received(
            b"POST /pair-setup HTTP/1.1\r\nHost: Bridge\\032C77C47._hap._tcp.local\r\nContent-Length: 6\r\nContent-Type: application/pairing+tlv8\r\n\r\n\x00\x01\x00\x06\x01\x01"  # pylint: disable=line-too-long
        )
        await asyncio.sleep(0)

    assert run_in_executor_called is True
    hap_proto.close()
Пример #4
0
def test_get_characteristics_with_crypto(driver):
    """Verify an encrypt characteristics request."""
    loop = MagicMock()
    transport = MagicMock()
    connections = {}

    acc = Accessory(driver, "TestAcc", aid=1)
    assert acc.aid == 1
    service = acc.driver.loader.get_service("TemperatureSensor")
    acc.add_service(service)
    driver.add_accessory(acc)

    hap_proto = hap_protocol.HAPServerProtocol(loop, connections, driver)
    hap_proto.connection_made(transport)

    hap_proto.hap_crypto = MockHAPCrypto()
    hap_proto.handler.is_encrypted = True

    with patch.object(hap_proto.transport, "write") as writer:
        hap_proto.data_received(
            b"GET /characteristics?id=3762173001.7 HTTP/1.1\r\nHost: HASS\\032Bridge\\032YPHW\\032B223AD._hap._tcp.local\r\n\r\n"  # pylint: disable=line-too-long
        )
        hap_proto.data_received(
            b"GET /characteristics?id=1.5 HTTP/1.1\r\nHost: HASS\\032Bridge\\032YPHW\\032B223AD._hap._tcp.local\r\n\r\n"  # pylint: disable=line-too-long
        )

    hap_proto.close()
    assert b"Content-Length:" in writer.call_args_list[0][0][0]
    assert b"Transfer-Encoding: chunked\r\n\r\n" not in writer.call_args_list[0][0][0]
    assert b"-70402" in writer.call_args_list[0][0][0]

    assert b"Content-Length:" in writer.call_args_list[1][0][0]
    assert b"Transfer-Encoding: chunked\r\n\r\n" not in writer.call_args_list[1][0][0]
    assert b"TestAcc" in writer.call_args_list[1][0][0]
Пример #5
0
async def test_camera_snapshot_works_async(driver):
    """Test camera snapshot works if there is support for it."""
    loop = MagicMock()
    transport = MagicMock()
    connections = {}

    async def _async_get_snapshot(*_):
        return b"fakesnap"

    acc = Accessory(driver, "TestAcc")
    acc.async_get_snapshot = _async_get_snapshot
    driver.add_accessory(acc)

    hap_proto = hap_protocol.HAPServerProtocol(loop, connections, driver)
    hap_proto.connection_made(transport)

    hap_proto.hap_crypto = MockHAPCrypto()
    hap_proto.handler.is_encrypted = True

    with patch.object(hap_proto.transport, "write") as writer:
        hap_proto.data_received(
            b'POST /resource HTTP/1.1\r\nHost: HASS\\032Bridge\\032BROZ\\0323BF435._hap._tcp.local\r\nContent-Length: 79\r\nContent-Type: application/hap+json\r\n\r\n{"image-height":360,"resource-type":"image","image-width":640,"aid":1411620844}'  # pylint: disable=line-too-long
        )
        await hap_proto.response.task
        await asyncio.sleep(0)

    assert b"fakesnap" in writer.call_args_list[0][0][0]

    hap_proto.close()
Пример #6
0
def test_set_characteristics_with_crypto(driver):
    """Verify an encrypt characteristics request."""
    loop = MagicMock()
    transport = MagicMock()
    connections = {}

    acc = Accessory(driver, "TestAcc", aid=1)
    assert acc.aid == 1
    service = acc.driver.loader.get_service("GarageDoorOpener")
    acc.add_service(service)
    driver.add_accessory(acc)

    hap_proto = hap_protocol.HAPServerProtocol(loop, connections, driver)
    hap_proto.connection_made(transport)

    hap_proto.hap_crypto = MockHAPCrypto()
    hap_proto.handler.is_encrypted = True

    with patch.object(hap_proto.transport, "write") as writer:
        hap_proto.data_received(
            b'PUT /characteristics HTTP/1.1\r\nHost: HASS12\\032AD1C22._hap._tcp.local\r\nContent-Length: 49\r\nContent-Type: application/hap+json\r\n\r\n{"characteristics":[{"aid":1,"iid":9,"ev":true}]}'  # pylint: disable=line-too-long
        )

    hap_proto.close()
    assert writer.call_args_list[0][0][0] == b"HTTP/1.1 204 No Content\r\n\r\n"
Пример #7
0
def test_invalid_content_length(driver):
    """Test we handle invalid content length."""
    loop = MagicMock()
    transport = MagicMock()
    connections = {}
    driver.add_accessory(Accessory(driver, "TestAcc"))

    hap_proto = hap_protocol.HAPServerProtocol(loop, connections, driver)
    hap_proto.connection_made(transport)

    with patch.object(hap_proto.transport, "write") as writer:
        hap_proto.data_received(
            b"POST /pair-setup HTTP/1.0\r\nConnection:close\r\nHost: Bridge\\032C77C47._hap._tcp.local\r\nContent-Length: 2\r\nContent-Type: application/pairing+tlv8\r\n\r\n\x00\x01\x00\x06\x01\x01"  # pylint: disable=line-too-long
        )
        hap_proto.data_received(
            b"POST /pair-setup HTTP/1.0\r\nConnection:close\r\nHost: Bridge\\032C77C47._hap._tcp.local\r\nContent-Length: 2\r\nContent-Type: application/pairing+tlv8\r\n\r\n\x00\x01\x00\x06\x01\x01"  # pylint: disable=line-too-long
        )

    assert (
        writer.call_args_list[0][0][0].startswith(
            b"HTTP/1.1 500 Internal Server Error\r\n"
        )
        is True
    )
    assert len(writer.call_args_list) == 1
    assert connections == {}
    hap_proto.close()
Пример #8
0
def test_get_accessories_without_crypto(driver):
    """Verify an non-encrypt request that expected to be encrypted."""
    loop = MagicMock()
    transport = MagicMock()
    connections = {}

    hap_proto = hap_protocol.HAPServerProtocol(loop, connections, driver)
    hap_proto.connection_made(transport)

    with patch.object(hap_proto.transport, "write") as writer:
        hap_proto.data_received(
            b"GET /accessories HTTP/1.1\r\nHost: Bridge\\032C77C47._hap._tcp.local\r\n\r\n"  # pylint: disable=line-too-long
        )

    hap_proto.close()
    assert b"-70401" in writer.call_args_list[0][0][0]
Пример #9
0
def test_pair_setup(driver):
    """Verify an non-encrypt request."""
    loop = MagicMock()
    transport = MagicMock()
    connections = {}

    hap_proto = hap_protocol.HAPServerProtocol(loop, connections, driver)
    hap_proto.connection_made(transport)

    with patch.object(hap_proto.transport, "write") as writer:
        hap_proto.data_received(
            b"POST /pair-setup HTTP/1.1\r\nHost: Bridge\\032C77C47._hap._tcp.local\r\nContent-Length: 6\r\nContent-Type: application/pairing+tlv8\r\n\r\n\x00\x01\x00\x06\x01\x01"  # pylint: disable=line-too-long
        )

    assert writer.call_args_list[0][0][0].startswith(b"HTTP/1.1 200 OK\r\n") is True

    hap_proto.close()
Пример #10
0
async def test_does_not_timeout(driver):
    """Test we do not timeout the connection if we have not reached the idle."""
    loop = asyncio.get_event_loop()
    transport = MagicMock()
    connections = {}
    driver.add_accessory(Accessory(driver, "TestAcc"))

    hap_proto = hap_protocol.HAPServerProtocol(loop, connections, driver)
    hap_proto.connection_made(transport)

    with patch.object(hap_proto, "close") as hap_proto_close, patch.object(
        hap_proto.transport, "write"
    ) as writer:
        hap_proto.data_received(
            b"POST /pair-setup HTTP/1.1\r\nHost: Bridge\\032C77C47._hap._tcp.local\r\nContent-Length: 6\r\nContent-Type: application/pairing+tlv8\r\n\r\n\x00\x01\x00\x06\x01\x01"  # pylint: disable=line-too-long
        )
        assert writer.call_args_list[0][0][0].startswith(b"HTTP/1.1 200 OK\r\n") is True
        hap_proto.check_idle(time.time())
        assert hap_proto_close.called is False
Пример #11
0
def test_crypto_failure_closes_connection(driver):
    """Verify a decrypt failure closes the connection."""
    loop = MagicMock()
    addr_info = ("1.2.3.4", 5)
    transport = MagicMock(get_extra_info=Mock(return_value=addr_info))
    connections = {}

    driver.add_accessory(Accessory(driver, "TestAcc"))

    hap_proto = hap_protocol.HAPServerProtocol(loop, connections, driver)
    hap_proto.connection_made(transport)

    hap_proto.hap_crypto = MockHAPCrypto()
    hap_proto.handler.is_encrypted = True
    assert connections[addr_info] == hap_proto
    with patch.object(hap_proto.hap_crypto, "decrypt", side_effect=InvalidTag):
        hap_proto.data_received(b"any")  # pylint: disable=line-too-long

    assert len(connections) == 0
Пример #12
0
def test_connection_management(driver):
    """Verify closing the connection removes it from the pool."""
    loop = MagicMock()
    addr_info = ("1.2.3.4", 5)
    transport = MagicMock(get_extra_info=Mock(return_value=addr_info))
    connections = {}

    hap_proto = hap_protocol.HAPServerProtocol(loop, connections, driver)
    hap_proto.connection_made(transport)
    assert len(connections) == 1
    assert connections[addr_info] == hap_proto
    hap_proto.connection_lost(None)
    assert len(connections) == 0

    hap_proto.connection_made(transport)
    assert len(connections) == 1
    assert connections[addr_info] == hap_proto
    hap_proto.close()
    assert len(connections) == 0
Пример #13
0
def test_connection_management(driver):
    """Verify closing the connection removes it from the pool."""
    loop = MagicMock()
    addr_info = ("1.2.3.4", 5)
    addr_info2 = ("1.2.3.5", 6)

    transport = MagicMock(get_extra_info=Mock(return_value=addr_info))
    connections = {}
    driver.add_accessory(Accessory(driver, "TestAcc"))
    driver.async_subscribe_client_topic(addr_info, "1.1", True)
    driver.async_subscribe_client_topic(addr_info, "2.2", True)
    driver.async_subscribe_client_topic(addr_info2, "1.1", True)

    assert "1.1" in driver.topics
    assert "2.2" in driver.topics

    assert addr_info in driver.topics["1.1"]
    assert addr_info in driver.topics["2.2"]
    assert addr_info2 in driver.topics["1.1"]

    hap_proto = hap_protocol.HAPServerProtocol(loop, connections, driver)
    hap_proto.connection_made(transport)
    assert len(connections) == 1
    assert connections[addr_info] == hap_proto
    hap_proto.connection_lost(None)
    assert len(connections) == 0
    assert "1.1" in driver.topics
    assert "2.2" not in driver.topics
    assert addr_info not in driver.topics["1.1"]
    assert addr_info2 in driver.topics["1.1"]

    hap_proto.connection_made(transport)
    assert len(connections) == 1
    assert connections[addr_info] == hap_proto
    hap_proto.close()
    assert len(connections) == 0

    hap_proto.connection_made(transport)
    assert len(connections) == 1
    assert connections[addr_info] == hap_proto
    hap_proto.connection_lost(None)
    assert len(connections) == 0
Пример #14
0
def test_http_11_keep_alive(driver):
    """Verify we can handle multiple requests."""
    loop = MagicMock()
    transport = MagicMock()
    connections = {}
    driver.add_accessory(Accessory(driver, "TestAcc"))

    hap_proto = hap_protocol.HAPServerProtocol(loop, connections, driver)
    hap_proto.connection_made(transport)

    with patch.object(hap_proto.transport, "write") as writer:
        hap_proto.data_received(
            b"POST /pair-setup HTTP/1.1\r\nHost: Bridge\\032C77C47._hap._tcp.local\r\nContent-Length: 6\r\nContent-Type: application/pairing+tlv8\r\n\r\n\x00\x01\x00\x06\x01\x01"  # pylint: disable=line-too-long
        )
        hap_proto.data_received(
            b"POST /pair-setup HTTP/1.1\r\nHost: Bridge\\032C77C47._hap._tcp.local\r\nContent-Length: 6\r\nContent-Type: application/pairing+tlv8\r\n\r\n\x00\x01\x00\x06\x01\x01"  # pylint: disable=line-too-long
        )

    assert writer.call_args_list[0][0][0].startswith(b"HTTP/1.1 200 OK\r\n") is True
    hap_proto.close()
Пример #15
0
def test_get_accessories_with_crypto(driver):
    """Verify an encrypt accessories request."""
    loop = MagicMock()
    transport = MagicMock()
    connections = {}
    driver.add_accessory(Accessory(driver, "TestAcc"))

    hap_proto = hap_protocol.HAPServerProtocol(loop, connections, driver)
    hap_proto.connection_made(transport)

    hap_proto.hap_crypto = MockHAPCrypto()
    hap_proto.handler.is_encrypted = True

    with patch.object(hap_proto.transport, "write") as writer:
        hap_proto.data_received(
            b"GET /accessories HTTP/1.1\r\nHost: Bridge\\032C77C47._hap._tcp.local\r\n\r\n"  # pylint: disable=line-too-long
        )

    hap_proto.close()
    assert b"accessories" in writer.call_args_list[0][0][0]
Пример #16
0
async def test_camera_snapshot_missing_accessory(driver):
    """Test camera snapshot that throws an exception."""
    loop = MagicMock()
    transport = MagicMock()
    connections = {}

    bridge = Bridge(driver, "Test Bridge")
    driver.add_accessory(bridge)

    hap_proto = hap_protocol.HAPServerProtocol(loop, connections, driver)
    hap_proto.connection_made(transport)

    hap_proto.hap_crypto = MockHAPCrypto()
    hap_proto.handler.is_encrypted = True

    with patch.object(hap_proto.transport, "write") as writer:
        hap_proto.data_received(
            b'POST /resource HTTP/1.1\r\nHost: HASS\\032Bridge\\032BROZ\\0323BF435._hap._tcp.local\r\nContent-Length: 79\r\nContent-Type: application/hap+json\r\n\r\n{"image-height":360,"resource-type":"image","image-width":640,"aid":1411620844}'  # pylint: disable=line-too-long
        )
        await asyncio.sleep(0)

    assert hap_proto.response is None
    assert b"-70402" in writer.call_args_list[0][0][0]
    hap_proto.close()