def notification_forever_unsubscribed(notif_delay=30, run_once=0):
    """Connects, registers, unregisters, then repeat following steps
    every delay interval (ignoring 4XXs):
    1. send notification
    2. receive notification

    Repeats forever.
    """
    yield connect()
    yield hello(None)
    reg, endpoint = yield register(random_channel_id())
    unregister(reg["channelID"])

    while True:
        length, data = random_data(min_length=2048, max_length=4096)
        yield timer_start("update.latency")
        response, content = yield send_notification(endpoint,
                                                    data,
                                                    headers={"TTL": "60"})
        yield counter("notification.throughput.bytes", length)
        yield counter("notification.sent", 1)
        notif = yield expect_notification(reg["channelID"], 5)
        yield counter("notification.received", 1)
        yield timer_end("update.latency")
        yield ack(channel_id=notif["channelID"], version=notif["version"])
        yield counter("notification.ack", 1)
        yield wait(notif_delay)

        if run_once:
            yield unregister(reg["channelID"])
            yield disconnect()
            break
def notification_forever_unsubscribed(notif_delay=30, run_once=0):
    """Connects, registers, unregisters, then repeat following steps
    every delay interval (ignoring 4XXs):
    1. send notification
    2. receive notification

    Repeats forever.
    """
    yield connect()
    yield hello(None)
    reg, endpoint = yield register(random_channel_id())
    unregister(reg["channelID"])

    while True:
        length, data = random_data(min_length=2048, max_length=4096)
        yield timer_start("update.latency")
        response, content = yield send_notification(endpoint, data, 60)
        yield counter("notification.throughput.bytes", length)
        yield counter("notification.sent", 1)
        notif = yield expect_notification(reg["channelID"], 5)
        yield counter("notification.received", 1)
        yield timer_end("update.latency")
        yield ack(channel_id=notif["channelID"], version=notif["version"])
        yield counter("notification.ack", 1)
        yield wait(notif_delay)

        if run_once:
            yield unregister(reg["channelID"])
            yield disconnect()
            break
def basic(*args, **kwargs):
    """Connects, sends a notification, than disconnects"""

    sc_args, sc_kw = group_kw_args(*args)
    sc_kw.update(kwargs)

    # open up the connection
    yield connect()
    yield hello(None)

    # for a restricted channel, you would need to send the public key
    reg, endpoint = yield register(random_channel_id(), sc_kw.get("vapid_key"))
    yield timer_start("update.latency")

    # data is padded out to a length that is a multiple of 4
    data = "aLongStringOfEncryptedThings"
    # Send a request using minimal VAPID information as the `claims` arg.
    # This will automatically set the VAPID `aud` element from the endpoint.
    response, content = yield send_notification(
        endpoint_url=endpoint,
        data=base64.urlsafe_b64decode(data),
        claims=sc_kw.get('vapid_claims'),
        headers={"TTL": "60"})
    # response is a standard Requests response object containing
    #   code    HTTP response code
    #   headers dictionary of returned header keys and values
    #   length  length of the response body
    #   json()  response body (returned as JSON)
    #   text()  response body (returned as text)
    #   request Requesting object
    # content is the response body as text.
    assert response.code == 201, ("Did not get a proper response code. "
                                  "Expected 201; Got {}".format(response.code))
    assert content == '', "Response content wasn't empty"
    yield counter("notification.sent", 1)

    # expect a registration message for the `channelID` in `time` seconds
    notif = yield expect_notification(channel_id=reg["channelID"], time=5)

    # check that the data matches what we wanted.
    # NOTE: since encryption is more a client/application server thing,
    # we can't actually test if it worked. What the system does, however, is
    # send the data untouched.
    assert notif['data'].encode() == data, "Did not get back expected data"

    yield counter("notification.received", 1)
    yield timer_end("update.latency")
    log.msg("Got notif: ", notif)

    # tell the server we got the message.
    yield ack(channel_id=notif["channelID"], version=notif["version"])
    yield counter("notification.ack", 1)

    # drop the channelID
    yield unregister(reg["channelID"])

    # drop the connection
    yield disconnect()
def basic():
    """Connects, sends a notification, than disconnects"""
    yield connect()
    yield hello(None)
    reg, endpoint = yield register(random_channel_id())
    yield timer_start("update.latency")
    response, content = yield send_notification(endpoint, None, 60)
    yield counter("notification.sent", 1)
    notif = yield expect_notification(reg["channelID"], 5)
    yield counter("notification.received", 1)
    yield timer_end("update.latency")
    log.msg("Got notif: ", notif)
    yield ack(channel_id=notif["channelID"], version=notif["version"])
    yield counter("notification.ack", 1)
    yield unregister(reg["channelID"])
    yield disconnect()
def reconnect_forever(reconnect_delay=30, run_once=0):
    """Connects, then repeats every delay interval:
    1. send notification
    2. receive notification
    3. disconnect
    4. reconnect

    Repeats forever.
    """
    yield connect()
    response = yield hello(None)

    reg, endpoint = yield register(random_channel_id())
    assert "uaid" in response
    uaid = response["uaid"]

    while True:
        length, data = random_data(min_length=2048, max_length=4096)
        yield timer_start("update.latency")
        response, content = yield send_notification(endpoint,
                                                    data,
                                                    headers={"TTL": "60"})
        yield counter("notification.throughput.bytes", length)
        yield counter("notification.sent", 1)
        notif = yield expect_notification(reg["channelID"], 5)
        yield counter("notification.received", 1)
        yield ack(channel_id=notif["channelID"], version=notif["version"])
        yield counter("notification.ack", 1)
        yield timer_end("update.latency")
        yield wait(reconnect_delay)
        yield disconnect()
        try:
            yield connect()
            response = yield hello(uaid)
            assert response["uaid"] == uaid
        except Exception as ex:
            # Connect may not properly reconnect during some testing, the
            # following work-around ensures that tests pass for now until
            # the race condition can be identified.
            print(ex)
            break

        if run_once:
            yield unregister(reg["channelID"])
            yield disconnect()
            break
def reconnect_forever(reconnect_delay=30, run_once=0):
    """Connects, then repeats every delay interval:
    1. send notification
    2. receive notification
    3. disconnect
    4. reconnect

    Repeats forever.
    """
    yield connect()
    response = yield hello(None)

    reg, endpoint = yield register(random_channel_id())
    assert "uaid" in response
    uaid = response["uaid"]

    while True:
        length, data = random_data(min_length=2048, max_length=4096)
        yield timer_start("update.latency")
        response, content = yield send_notification(endpoint, data, 60)
        yield counter("notification.throughput.bytes", length)
        yield counter("notification.sent", 1)
        notif = yield expect_notification(reg["channelID"], 5)
        yield counter("notification.received", 1)
        yield ack(channel_id=notif["channelID"], version=notif["version"])
        yield counter("notification.ack", 1)
        yield timer_end("update.latency")
        yield wait(reconnect_delay)
        yield disconnect()
        yield connect()
        response = yield hello(uaid)
        assert response["uaid"] == uaid

        if run_once:
            yield unregister(reg["channelID"])
            yield disconnect()
            break
def basic_topic(*args, **kwargs):
    """Connects, sends a notification, than disconnects"""

    sc_args, sc_kw = group_kw_args(*args)
    sc_kw.update(kwargs)
    topic_name = "aaaa"

    # open up the connection
    yield connect()
    response = yield hello(None)

    uaid = response['uaid']

    # for a restricted channel, you would need to send the public key
    reg, endpoint = yield register(random_channel_id(), sc_kw.get("vapid_key"))
    yield timer_start("update.latency")

    # Remember to disconnect! Messages are only overwritten if they're not
    # delivered!
    yield disconnect()

    # data is padded out to a length that is a multiple of 4
    data = "aLongStringOfEncryptedThings"
    # Send a request using minimal VAPID information as the `claims` arg.
    # This will automatically set the VAPID `aud` element from the endpoint.
    response, content = yield send_notification(
        endpoint_url=endpoint,
        data=base64.urlsafe_b64decode(data),
        headers={
            "TTL": "60",
            "Topic": topic_name
        },
        claims=sc_kw.get('vapid_claims'))
    # response is a standard Requests response object containing
    #   code    HTTP response code
    #   headers dictionary of returned header keys and values
    #   length  length of the response body
    #   json()  response body (returned as JSON)
    #   text()  response body (returned as text)
    #   request Requesting object
    # content is the response body as text.
    assert response.code == 201, ("Did not get a proper response code. "
                                  "Expected 201; Got {}".format(response.code))
    assert content == '', "Response content wasn't empty"
    yield counter("notification.sent", 1)
    # Send a second request with the same topic. This should overwrite the
    # prior.
    data2 = "aDiffferentStringFullOfStuff"
    response, content = yield send_notification(
        endpoint_url=endpoint,
        data=base64.urlsafe_b64decode(data2),
        headers={
            "TTL": "60",
            "Topic": topic_name
        },
        claims=sc_kw.get('vapid_claims'))
    assert response.code == 201, ("Did not get a proper response code. "
                                  "Expected 201; Got {}".format(response.code))
    assert content == '', "Response content wasn't empty"
    yield counter("notification.sent", 1)

    yield connect()
    response = yield hello(uaid)
    assert response["uaid"] == uaid

    # expect a registration message for the `channelID` in `time` seconds
    notif = yield expect_notification(channel_id=reg["channelID"], time=5)

    # Check that the returned notification contains the second data
    # we sent.
    assert notif['data'].encode() == data2, "Did not get back expected data"

    yield counter("notification.received", 1)
    yield timer_end("update.latency")
    log.msg("Got notif: ", notif)

    # tell the server we got the message.
    yield ack(channel_id=notif["channelID"], version=notif["version"])
    yield counter("notification.ack", 1)

    # drop the channelID
    yield unregister(reg["channelID"])

    # drop the connection
    yield disconnect()