Skip to content

Commit

Permalink
Fix randomness (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
BenjaminPelletier authored Oct 20, 2022
1 parent 51d8e16 commit 0c4d11e
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 25 deletions.
28 changes: 18 additions & 10 deletions src/uas_standards/ansi_cta_2063_a.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations
import random
from typing import Optional


class SerialNumber(str):
Expand Down Expand Up @@ -35,18 +36,23 @@ def valid(self) -> bool:
return False
return True

def make_invalid_by_changing_payload_length(self) -> SerialNumber:
def make_invalid_by_changing_payload_length(self, r: Optional[random.Random] = None) -> SerialNumber:
"""Generates an invalid serial number similar to this serial number."""
if r is None:
r = random
my_length = self.length_code
lengths_except_mine = [
c for c in SerialNumber.length_code_points if c != my_length
]
new_length_code = random.choice(lengths_except_mine)
new_length_code = r.choice(lengths_except_mine)
k = SerialNumber.length_code_points.index(new_length_code) + 1
random_serial_number = "".join(random.choices(SerialNumber.code_points, k=k))
return SerialNumber(
self.manufacturer_code + self.length_code + random_serial_number
)
while True:
random_serial_number = "".join(r.choices(SerialNumber.code_points, k=k))
result = SerialNumber(
self.manufacturer_code + self.length_code + random_serial_number
)
if not result.valid:
return result

@staticmethod
def from_components(
Expand All @@ -61,9 +67,11 @@ def from_components(
)

@staticmethod
def generate_valid() -> SerialNumber:
def generate_valid(r: Optional[random.Random] = None) -> SerialNumber:
"""Generates a valid and random UAV serial number per ANSI/CTA-2063-A."""
manufacturer_code = "".join(random.choices(SerialNumber.code_points, k=4))
k = random.randrange(0, len(SerialNumber.length_code_points)) + 1
random_serial_number = "".join(random.choices(SerialNumber.code_points, k=k))
if r is None:
r = random
manufacturer_code = "".join(r.choices(SerialNumber.code_points, k=4))
k = r.randrange(0, len(SerialNumber.length_code_points)) + 1
random_serial_number = "".join(r.choices(SerialNumber.code_points, k=k))
return SerialNumber.from_components(manufacturer_code, random_serial_number)
30 changes: 19 additions & 11 deletions src/uas_standards/en4709_02.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations
import random
import string
from typing import Optional


class OperatorRegistrationNumber(str):
Expand Down Expand Up @@ -65,16 +66,21 @@ def valid(self) -> bool:
return self.checksum == checksum

def make_invalid_by_changing_final_control_string(
self,
self, r: Optional[random.Random] = None
) -> OperatorRegistrationNumber:
"""A method to generate an invalid Operator Registration number by replacing the control string"""
new_random_string = "".join(
random.choice(string.ascii_lowercase)
for _ in range(OperatorRegistrationNumber.final_random_string_length)
)
return OperatorRegistrationNumber(
self.checksum_control + "-" + new_random_string
)
if r is None:
r = random
while True:
new_random_string = "".join(
r.choice(string.ascii_lowercase)
for _ in range(OperatorRegistrationNumber.final_random_string_length)
)
result = OperatorRegistrationNumber(
self.checksum_control + "-" + new_random_string
)
if not result.valid:
return result

@staticmethod
def validate_prefix(prefix: str) -> None:
Expand Down Expand Up @@ -142,14 +148,16 @@ def generate_checksum(base_id: str, final_random_string: str) -> str:
]

@staticmethod
def generate_valid(prefix: str) -> OperatorRegistrationNumber:
def generate_valid(prefix: str, r: Optional[random.Random] = None) -> OperatorRegistrationNumber:
"""Generate a random operator registration number with the specified prefix"""
if r is None:
r = random
final_random_string = "".join(
random.choice(string.ascii_lowercase)
r.choice(string.ascii_lowercase)
for _ in range(OperatorRegistrationNumber.final_random_string_length)
)
base_id = "".join(
random.choice(string.ascii_lowercase + string.digits)
r.choice(string.ascii_lowercase + string.digits)
for _ in range(OperatorRegistrationNumber.base_id_length)
)
return OperatorRegistrationNumber.from_components(
Expand Down
7 changes: 5 additions & 2 deletions tests/test_ansi_cta_2063_a.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import json
import random

from uas_standards.ansi_cta_2063_a import SerialNumber


def test_basic_usage():
sn = SerialNumber.generate_valid()
r = random.Random(12345)

sn = SerialNumber.generate_valid(r)
assert sn.valid

sn2 = SerialNumber.from_components(sn.manufacturer_code, sn.manufacturer_serial_number)
Expand All @@ -16,6 +19,6 @@ def test_basic_usage():
assert sn3.valid
assert sn3 == sn

sn_invalid = sn.make_invalid_by_changing_payload_length()
sn_invalid = sn.make_invalid_by_changing_payload_length(r)
assert sn.valid
assert not sn_invalid.valid
7 changes: 5 additions & 2 deletions tests/test_en4709_02.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import json
import random
import pytest

from uas_standards.en4709_02 import OperatorRegistrationNumber


def test_basic_usage():
rn = OperatorRegistrationNumber.generate_valid('EXM')
r = random.Random(12345)

rn = OperatorRegistrationNumber.generate_valid('EXM', r)
assert rn.valid
OperatorRegistrationNumber.validate_prefix(rn.prefix)
OperatorRegistrationNumber.validate_base_id(rn.base_id)
Expand All @@ -20,7 +23,7 @@ def test_basic_usage():
assert rn3.valid
assert rn3 == rn

rn_invalid = rn.make_invalid_by_changing_final_control_string()
rn_invalid = rn.make_invalid_by_changing_final_control_string(r)
assert rn.valid
assert not rn_invalid.valid
OperatorRegistrationNumber.validate_prefix(rn_invalid.prefix)
Expand Down

0 comments on commit 0c4d11e

Please sign in to comment.