def test_successful_base64_conversion(original, base64_encoded): # all unicode characters should be handled correctly assert to_base64(original) == base64_encoded assert from_base64(base64_encoded) == original # "to" and "from" should be inverses assert from_base64(to_base64(original)) == original assert to_base64(from_base64(base64_encoded)) == base64_encoded
def reinflate_tracestate(encoded_tracestate): # type: (str) -> typing.Optional[Mapping[str, str]] """ Given a sentry tracestate value in its encoded form, translate it back into a dictionary of data. """ inflated_tracestate = None if encoded_tracestate: # Base64-encoded strings always come out with a length which is a # multiple of 4. In order to achieve this, the end is padded with one or # more `=` signs. Because the tracestate standard calls for using `=` # signs between vendor name and value (`sentry=xxx,dogsaregreat=yyy`), # to avoid confusion we strip the `=` when the data is initially # encoded. Python's decoding function requires they be put back. # Fortunately, it doesn't complain if there are too many, so we just # attach two `=` on spec (there will never be more than 2, see # https://en.wikipedia.org/wiki/Base64#Decoding_Base64_without_padding). tracestate_json = from_base64(encoded_tracestate + "==") try: assert tracestate_json is not None inflated_tracestate = json.loads(tracestate_json) except Exception as err: logger.warning( ("Unable to attach tracestate data to envelope header: {err}" + "\nTracestate value is {encoded_tracestate}").format( err=err, encoded_tracestate=encoded_tracestate), ) return inflated_tracestate
def test_failed_base64_conversion(input): # conversion from base64 should fail if given input of the wrong type or # input which isn't a valid base64 string assert from_base64(input) is None # any string can be converted to base64, so only type errors will cause # failures if type(input) not in string_types: assert to_base64(input) is None
def test_tracestate_computation(sentry_init): sentry_init( dsn= "https://[email protected]/12312012", environment="dogpark", release="off.leash.park", ) sentry_sdk.set_user({"id": 12312013, "segment": "bigs"}) transaction = Transaction( name="/interactions/other-dogs/new-dog", op="greeting.sniff", trace_id="12312012123120121231201212312012", ) # force lazy computation to create a value transaction.to_tracestate() computed_value = transaction._sentry_tracestate.replace("sentry=", "") # we have to decode and reinflate the data because we can guarantee that the # order of the entries in the jsonified dict will be the same here as when # the tracestate is computed reinflated_trace_data = json.loads(from_base64(computed_value)) assert reinflated_trace_data == { "trace_id": "12312012123120121231201212312012", "environment": "dogpark", "release": "off.leash.park", "public_key": "dogsarebadatkeepingsecrets", "user": { "id": 12312013, "segment": "bigs" }, "transaction": "/interactions/other-dogs/new-dog", }