Skip to content

Commit

Permalink
[SVLS-5262] change _standard_hashing_function to a normal function wi…
Browse files Browse the repository at this point in the history
…th detailed tests
  • Loading branch information
apiarian-datadog committed Sep 19, 2024
1 parent b4fa57d commit 1080854
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 30 deletions.
30 changes: 5 additions & 25 deletions ddtrace/_trace/_span_pointer.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,29 +56,9 @@ def __post_init__(self):
pass


class _StandardHashingRules:
# This is a bit of a strange class. Its instances behave like simple
# function. This allows us to do the hex_digits calculation once. It also
# allows us to write tests for the chosen base_hashing_function instead of
# having to add runtime sanity checks. This class should be instantiated
# only once, internally, and the result stored as a the
# _standard_hashing_function "function" below.
def _standard_hashing_function(*elements: bytes) -> str:
if not elements:
raise ValueError("elements must not be empty")

def __init__(self):
self.separator = b"|"

self.bits_per_hex_digit = 4
self.desired_bits = 128

self.hex_digits = self.desired_bits // self.bits_per_hex_digit

self.base_hashing_function = sha256

def __call__(self, *elements: bytes) -> str:
if not elements:
raise ValueError("elements must not be empty")

return self.base_hashing_function(self.separator.join(elements)).hexdigest()[: self.hex_digits]


_standard_hashing_function = _StandardHashingRules()
# Please see the tests for more details about this logic.
return sha256(b"|".join(elements)).hexdigest()[:32]
24 changes: 19 additions & 5 deletions tests/tracer/test_span_pointers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from hashlib import sha256
from typing import List
from typing import NamedTuple

Expand Down Expand Up @@ -36,13 +37,26 @@ class HashingCase(NamedTuple):
def test_normal_hashing(self, test_case: HashingCase) -> None:
assert _standard_hashing_function(*test_case.elements) == test_case.result

def test_validate_hashing_rules(self) -> None:
hex_digits_per_byte = 2
desired_bytes = _standard_hashing_function.hex_digits // hex_digits_per_byte
def test_validate_hash_size(self) -> None:
bits_per_hex_digit = 4
desired_bits = 128

bytes_in_digest = _standard_hashing_function.base_hashing_function().digest_size
expected_hex_digits = desired_bits // bits_per_hex_digit

assert bytes_in_digest >= desired_bytes
assert len(_standard_hashing_function(b"foo")) == expected_hex_digits

def test_validate_using_sha256_with_pipe_separator(self) -> None:
# We want this test to break if we change the logic of the standard
# function in any interesting way. If we want to change this behavior
# in the future, we'll need to make a new version of the standard
# hashing function.

bits_per_hex_digit = 4
desired_bits = 128

hex_digits = desired_bits // bits_per_hex_digit

assert _standard_hashing_function(b"foo", b"bar") == sha256(b"foo|bar").hexdigest()[:hex_digits]

def test_hashing_requries_arguments(self) -> None:
with pytest.raises(ValueError, match="elements must not be empty"):
Expand Down

0 comments on commit 1080854

Please sign in to comment.