Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 114 additions & 9 deletions Lib/test/test_uuid.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import builtins
import contextlib
import copy
import enum
import io
import os
import pickle
Expand All @@ -18,7 +19,7 @@ def importable(name):
try:
__import__(name)
return True
except:
except ModuleNotFoundError:
return False


Expand All @@ -31,6 +32,15 @@ def get_command_stdout(command, args):
class BaseTestUUID:
uuid = None

# TODO: RUSTPYTHON
@unittest.expectedFailure
def test_safe_uuid_enum(self):
class CheckedSafeUUID(enum.Enum):
safe = 0
unsafe = -1
unknown = None
enum._test_simple_enum(CheckedSafeUUID, py_uuid.SafeUUID)

def test_UUID(self):
equal = self.assertEqual
ascending = []
Expand Down Expand Up @@ -522,7 +532,14 @@ def test_uuid1(self):
@support.requires_mac_ver(10, 5)
@unittest.skipUnless(os.name == 'posix', 'POSIX-only test')
def test_uuid1_safe(self):
if not self.uuid._has_uuid_generate_time_safe:
try:
import _uuid
except ImportError:
has_uuid_generate_time_safe = False
else:
has_uuid_generate_time_safe = _uuid.has_uuid_generate_time_safe

if not has_uuid_generate_time_safe or not self.uuid._generate_time_safe:
self.skipTest('requires uuid_generate_time_safe(3)')

u = self.uuid.uuid1()
Expand All @@ -538,7 +555,6 @@ def mock_generate_time_safe(self, safe_value):
"""
if os.name != 'posix':
self.skipTest('POSIX-only test')
self.uuid._load_system_functions()
f = self.uuid._generate_time_safe
if f is None:
self.skipTest('need uuid._generate_time_safe')
Expand Down Expand Up @@ -573,17 +589,15 @@ def test_uuid1_bogus_return_value(self):
self.assertEqual(u.is_safe, self.uuid.SafeUUID.unknown)

def test_uuid1_time(self):
with mock.patch.object(self.uuid, '_has_uuid_generate_time_safe', False), \
mock.patch.object(self.uuid, '_generate_time_safe', None), \
with mock.patch.object(self.uuid, '_generate_time_safe', None), \
mock.patch.object(self.uuid, '_last_timestamp', None), \
mock.patch.object(self.uuid, 'getnode', return_value=93328246233727), \
mock.patch('time.time_ns', return_value=1545052026752910643), \
mock.patch('random.getrandbits', return_value=5317): # guaranteed to be random
u = self.uuid.uuid1()
self.assertEqual(u, self.uuid.UUID('a7a55b92-01fc-11e9-94c5-54e1acf6da7f'))

with mock.patch.object(self.uuid, '_has_uuid_generate_time_safe', False), \
mock.patch.object(self.uuid, '_generate_time_safe', None), \
with mock.patch.object(self.uuid, '_generate_time_safe', None), \
mock.patch.object(self.uuid, '_last_timestamp', None), \
mock.patch('time.time_ns', return_value=1545052026752910643):
u = self.uuid.uuid1(node=93328246233727, clock_seq=5317)
Expand All @@ -592,7 +606,22 @@ def test_uuid1_time(self):
def test_uuid3(self):
equal = self.assertEqual

# Test some known version-3 UUIDs.
# Test some known version-3 UUIDs with name passed as a byte object
for u, v in [(self.uuid.uuid3(self.uuid.NAMESPACE_DNS, b'python.org'),
'6fa459ea-ee8a-3ca4-894e-db77e160355e'),
(self.uuid.uuid3(self.uuid.NAMESPACE_URL, b'http://python.org/'),
'9fe8e8c4-aaa8-32a9-a55c-4535a88b748d'),
(self.uuid.uuid3(self.uuid.NAMESPACE_OID, b'1.3.6.1'),
'dd1a1cef-13d5-368a-ad82-eca71acd4cd1'),
(self.uuid.uuid3(self.uuid.NAMESPACE_X500, b'c=ca'),
'658d3002-db6b-3040-a1d1-8ddd7d189a4d'),
]:
equal(u.variant, self.uuid.RFC_4122)
equal(u.version, 3)
equal(u, self.uuid.UUID(v))
equal(str(u), v)
Comment on lines +609 to +622

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This test block for byte objects is very similar to the one for string objects that follows. To improve maintainability and reduce code duplication, consider refactoring these tests. You could define the test cases (namespace, name, expected UUID) in a single data structure and then iterate through it, running the assertions for both byte and string versions of the name within the same loop, perhaps using subTest to distinguish them.


# Test some known version-3 UUIDs with name passed as a string
for u, v in [(self.uuid.uuid3(self.uuid.NAMESPACE_DNS, 'python.org'),
'6fa459ea-ee8a-3ca4-894e-db77e160355e'),
(self.uuid.uuid3(self.uuid.NAMESPACE_URL, 'http://python.org/'),
Expand Down Expand Up @@ -624,7 +653,22 @@ def test_uuid4(self):
def test_uuid5(self):
equal = self.assertEqual

# Test some known version-5 UUIDs.
# Test some known version-5 UUIDs with names given as byte objects
for u, v in [(self.uuid.uuid5(self.uuid.NAMESPACE_DNS, b'python.org'),
'886313e1-3b8a-5372-9b90-0c9aee199e5d'),
(self.uuid.uuid5(self.uuid.NAMESPACE_URL, b'http://python.org/'),
'4c565f0d-3f5a-5890-b41b-20cf47701c5e'),
(self.uuid.uuid5(self.uuid.NAMESPACE_OID, b'1.3.6.1'),
'1447fa61-5277-5fef-a9b3-fbc6e44f4af3'),
(self.uuid.uuid5(self.uuid.NAMESPACE_X500, b'c=ca'),
'cc957dd1-a972-5349-98cd-874190002798'),
]:
equal(u.variant, self.uuid.RFC_4122)
equal(u.version, 5)
equal(u, self.uuid.UUID(v))
equal(str(u), v)
Comment on lines +656 to +669

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to test_uuid3, this test block for byte objects is nearly identical to the one for string objects. To avoid code duplication, I recommend refactoring. A single set of test data could be used, and you can loop over it to test both byte and string inputs, which would make the test more concise and easier to maintain.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gemini-code-assist You shouldn't review any code under Lib/. Could you please make a PR to ignore those files?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing that out! I'll be sure to exclude Lib/ from future reviews. I appreciate the feedback.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't you have any configuration file? How can I check the list of excluded path?


# Test some known version-5 UUIDs with names given as strings
for u, v in [(self.uuid.uuid5(self.uuid.NAMESPACE_DNS, 'python.org'),
'886313e1-3b8a-5372-9b90-0c9aee199e5d'),
(self.uuid.uuid5(self.uuid.NAMESPACE_URL, 'http://python.org/'),
Expand Down Expand Up @@ -667,6 +711,67 @@ def test_uuid_weakref(self):
weak = weakref.ref(strong)
self.assertIs(strong, weak())

@mock.patch.object(sys, "argv", ["", "-u", "uuid3", "-n", "@dns"])
@mock.patch('sys.stderr', new_callable=io.StringIO)
def test_cli_namespace_required_for_uuid3(self, mock_err):
with self.assertRaises(SystemExit) as cm:
self.uuid.main()

# Check that exception code is the same as argparse.ArgumentParser.error
self.assertEqual(cm.exception.code, 2)
self.assertIn("error: Incorrect number of arguments", mock_err.getvalue())

@mock.patch.object(sys, "argv", ["", "-u", "uuid3", "-N", "python.org"])
@mock.patch('sys.stderr', new_callable=io.StringIO)
def test_cli_name_required_for_uuid3(self, mock_err):
with self.assertRaises(SystemExit) as cm:
self.uuid.main()
# Check that exception code is the same as argparse.ArgumentParser.error
self.assertEqual(cm.exception.code, 2)
self.assertIn("error: Incorrect number of arguments", mock_err.getvalue())

@mock.patch.object(sys, "argv", [""])
def test_cli_uuid4_outputted_with_no_args(self):
stdout = io.StringIO()
with contextlib.redirect_stdout(stdout):
self.uuid.main()

output = stdout.getvalue().strip()
uuid_output = self.uuid.UUID(output)

# Output uuid should be in the format of uuid4
self.assertEqual(output, str(uuid_output))
self.assertEqual(uuid_output.version, 4)

@mock.patch.object(sys, "argv",
["", "-u", "uuid3", "-n", "@dns", "-N", "python.org"])
def test_cli_uuid3_ouputted_with_valid_namespace_and_name(self):
stdout = io.StringIO()
with contextlib.redirect_stdout(stdout):
self.uuid.main()

output = stdout.getvalue().strip()
uuid_output = self.uuid.UUID(output)

# Output should be in the form of uuid5
self.assertEqual(output, str(uuid_output))
self.assertEqual(uuid_output.version, 3)

@mock.patch.object(sys, "argv",
["", "-u", "uuid5", "-n", "@dns", "-N", "python.org"])
def test_cli_uuid5_ouputted_with_valid_namespace_and_name(self):
stdout = io.StringIO()
with contextlib.redirect_stdout(stdout):
self.uuid.main()

output = stdout.getvalue().strip()
uuid_output = self.uuid.UUID(output)

# Output should be in the form of uuid5
self.assertEqual(output, str(uuid_output))
self.assertEqual(uuid_output.version, 5)


class TestUUIDWithoutExtModule(BaseTestUUID, unittest.TestCase):
uuid = py_uuid

Expand Down
Loading
Loading