diff --git a/tests/unit/test_repository_tool.py b/tests/unit/test_repository_tool.py new file mode 100755 index 00000000..cb6f61a5 --- /dev/null +++ b/tests/unit/test_repository_tool.py @@ -0,0 +1,308 @@ +""" + + test_repository_tool.py + + + Vladimir Diaz + + + April 7, 2014. + + + See LICENSE for licensing information. + + + Unit test for 'repository_tool.py'. +""" + +import unittest +import logging + +import tuf +import tuf.log +import tuf.formats +import tuf.roledb +import tuf.keydb +import tuf.repository_tool as repo_tool + +logger = logging.getLogger('tuf.test_repository_tool') + + + +class TestRepository(unittest.TestCase): + def setUp(self): + pass + + + + def tearDown(self): + tuf.roledb.clear_roledb() + tuf.keydb.clear_keydb() + + + def test_init(self): + + # Test normal case. + repository = repo_tool.Repository('repository_directory/', + 'metadata_directory/', + 'targets_directory/') + self.assertTrue(isinstance(repository.root, repo_tool.Root)) + self.assertTrue(isinstance(repository.snapshot, repo_tool.Snapshot)) + self.assertTrue(isinstance(repository.timestamp, repo_tool.Timestamp)) + self.assertTrue(isinstance(repository.targets, repo_tool.Targets)) + + # Test improperly formatted arguments. + self.assertRaises(tuf.FormatError, repo_tool.Repository, 3, + 'metadata_directory/', 'targets_directory') + self.assertRaises(tuf.FormatError, repo_tool.Repository, + 'repository_directory', 3, 'targets_directory') + self.assertRaises(tuf.FormatError, repo_tool.Repository, + 'repository_directory', 'metadata_directory', 3) + + + +class TestMetadata(unittest.TestCase): + def setUp(self): + pass + + + + def tearDown(self): + pass + + + + + +class TestRoot(unittest.TestCase): + def setUp(self): + pass + + + + def tearDown(self): + tuf.roledb.clear_roledb() + tuf.keydb.clear_keydb() + + + + def test_init(self): + + # Test normal case. + # Root() subclasses Metadata(), and creates a 'root' role in 'tuf.roledb'. + root_object = repo_tool.Root() + self.assertTrue(isinstance(root_object, repo_tool.Metadata)) + self.assertTrue(tuf.roledb.role_exists('root')) + + + +class TestTimestamp(unittest.TestCase): + def setUp(self): + pass + + + + def tearDown(self): + tuf.roledb.clear_roledb() + tuf.keydb.clear_keydb() + + + + def test_init(self): + + # Test normal case. + # Timestamp() subclasses Metadata(), and creates a 'timestamp' role in + # 'tuf.roledb'. + timestamp_object = repo_tool.Timestamp() + self.assertTrue(isinstance(timestamp_object, repo_tool.Metadata)) + self.assertTrue(tuf.roledb.role_exists('timestamp')) + + + + + +class TestSnapshot(unittest.TestCase): + def setUp(self): + pass + + + + def tearDown(self): + tuf.roledb.clear_roledb() + tuf.keydb.clear_keydb() + + + + def test_init(self): + + # Test normal case. + # Snapshot() subclasses Metadata(), and creates a 'snapshot' role in + # 'tuf.roledb'. + snapshot_object = repo_tool.Snapshot() + self.assertTrue(isinstance(snapshot_object, repo_tool.Metadata)) + self.assertTrue(tuf.roledb.role_exists('snapshot')) + + + + + +class TestTargets(unittest.TestCase): + def setUp(self): + pass + + + + def tearDown(self): + tuf.roledb.clear_roledb() + tuf.keydb.clear_keydb() + + + + def test_init(self): + + # Test normal case. + # Snapshot() subclasses Metadata(), and creates a 'snapshot' role in + # 'tuf.roledb'. + targets_object = repo_tool.Targets('targets_directory/') + self.assertTrue(isinstance(targets_object, repo_tool.Metadata)) + self.assertTrue(tuf.roledb.role_exists('targets')) + + # Custom Targets object rolename. + targets_object = repo_tool.Targets('targets_directory/', 'project') + self.assertTrue(isinstance(targets_object, repo_tool.Metadata)) + self.assertTrue(tuf.roledb.role_exists('project')) + + # Custom roleinfo object (i.e., tuf.formats.ROLEDB_SCHEMA). 'keyids' and + # 'threshold' are required, the rest are optional. + roleinfo = {'keyids': + ['66c4cb5fef5e4d62b7013ef1cab4b8a827a36c14056d5603c3a970e21eb30e6f'], + 'threshold': 8} + self.assertTrue(tuf.formats.ROLEDB_SCHEMA.matches(roleinfo)) + + targets_object = repo_tool.Targets('targets_directory/', 'package', roleinfo) + self.assertTrue(isinstance(targets_object, repo_tool.Metadata)) + self.assertTrue(tuf.roledb.role_exists('package')) + + + # Test improperly formatted arguments. + self.assertRaises(tuf.FormatError, repo_tool.Targets, 3) + self.assertRaises(tuf.FormatError, repo_tool.Targets, 'targets_directory/', 3) + self.assertRaises(tuf.FormatError, repo_tool.Targets, 'targets_directory/', + 'targets', 3) + + + +class TestRepositoryToolFunctions(unittest.TestCase): + def setUp(self): + pass + + + def tearDown(self): + pass + + + + def test_create_new_repository(self): + pass + + + + def test_load_repository(self): + pass + + + + def test_generate_and_write_rsa_keypair(self): + pass + + + + def test_import_rsa_privatekey_from_file(self): + pass + + + + def test_import_rsa_publickey_from_file(self): + pass + + + + def test_generate_and_write_ed25519_keypair(self): + pass + + + + def test_import_ed25519_publickey_from_file(self): + pass + + + + def test_import_ed25519_privatekey_from_file(self): + pass + + + + def test_get_metadata_filenames(self): + pass + + + + def test_get_metadata_file_info(self): + pass + + + + def test_get_target_hash(self): + # Test normal case. + expected_target_hashes = { + '/file1.txt': 'e3a3d89eb3b70ce3fbce6017d7b8c12d4abd5635427a0e8a238f53157df85b3d', + '/README.txt': '8faee106f1bb69f34aaf1df1e3c2e87d763c4d878cb96b91db13495e32ceb0b0', + '/packages/file2.txt': 'c9c4a5cdd84858dd6a23d98d7e6e6b2aec45034946c16b2200bc317c75415e92' + } + for filepath, target_hash in expected_target_hashes.items(): + self.assertTrue(tuf.formats.RELPATH_SCHEMA.matches(filepath)) + self.assertTrue(tuf.formats.HASH_SCHEMA.matches(target_hash)) + self.assertEqual(repo_tool.get_target_hash(filepath), target_hash) + + # Test for improperly formatted argument. + self.assertRaises(tuf.FormatError, repo_tool.get_target_hash, 8) + + + + def test_generate_root_metadata(self): + pass + + + + def test_generate_targets_metadata(self): + pass + + + + def test_generate_snapshot_metadata(self): + pass + + + + def test_generate_timestamp_metadata(self): + pass + + + + def test_sign_metadata(self): + pass + + + + def test_write_metadata_file(self): + pass + + + + def test_create_tuf_client_directory(self): + pass + + +# Run the test cases. +if __name__ == '__main__': + unittest.main() diff --git a/tuf/repository_tool.py b/tuf/repository_tool.py index 69211c4e..32408475 100755 --- a/tuf/repository_tool.py +++ b/tuf/repository_tool.py @@ -188,7 +188,7 @@ def write(self, write_partial=False, consistent_snapshot=False): private keys, etc. - write_partial: + mrite_partial: A boolean indicating whether partial metadata should be written to disk. Partial metadata may be written to allow multiple maintainters to independently sign and update role metadata. write() raises an @@ -1479,13 +1479,14 @@ class Targets(Metadata): tuf.FormatError, if the arguments are improperly formatted. - Modifies the roleinfo of the targets role in 'tuf.roledb'. + Modifies the roleinfo of the targets role in 'tuf.roledb', or creates + a default one named 'targets'. None. """ - def __init__(self, targets_directory, rolename, roleinfo=None): + def __init__(self, targets_directory, rolename='targets', roleinfo=None): # Do the arguments have the correct format? # Ensure the arguments have the appropriate number of objects and object @@ -3831,30 +3832,7 @@ def get_target_hash(target_filepath): The hash of 'target_filepath'. """ - # Does 'target_filepath' have the correct format? - # Ensure the arguments have the appropriate number of objects and object - # types, and that all dict keys are properly named. - # Raise 'tuf.FormatError' if there is a mismatch. - tuf.formats.RELPATH_SCHEMA.check_match(target_filepath) - - # Calculate the hash of the filepath to determine which bin to find the - # target. The client currently assumes the repository uses - # 'HASH_FUNCTION' to generate hashes. - digest_object = tuf.hash.digest(HASH_FUNCTION) - - try: - digest_object.update(target_filepath) - - except UnicodeEncodeError: - # Sometimes, there are Unicode characters in target paths. We assume a - # UTF-8 encoding and try to hash that. - digest_object = tuf.hash.digest(HASH_FUNCTION) - encoded_target_filepath = target_filepath.encode('utf-8') - digest_object.update(encoded_target_filepath) - - target_filepath_hash = digest_object.hexdigest() - - return target_filepath_hash + return tuf.util.get_target_hash(target_filepath)