#!/usr/bin/env python """ test_developer_tool.py Santiago Torres Arias See LICENSE for licensing inforation Unit tests for the 'developer_tool' module """ import os import time import datetime import unittest import logging import tempfile import shutil import tuf import tuf.log import tuf.formats import tuf.roledb import tuf.keydb import tuf.developer_tool as developer_tool from tuf.developer_tool import METADATA_DIRECTORY_NAME from tuf.developer_tool import TARGETS_DIRECTORY_NAME logger = logging.getLogger("tuf.test_developer_tool") class TestProject(unittest.TestCase): tmp_dir = None @classmethod def setUpClass(cls): cls.tmp_dir = tempfile.mkdtemp(dir = os.getcwd()) @classmethod def tearDownClass(cls): shutil.rmtree(cls.tmp_dir) def setUp(self): # called before every test case pass def tearDown(self): # called after every test case tuf.roledb.clear_roledb() tuf.keydb.clear_keydb() pass def test_emtpy(self): return def test_create_new_project(self): # test cases for the create_new_project function. In this test we will # check input, correct file creation and format. We also check # that a proper object is generated. We will use the normal layout for this # test suite. # create a local subfolder for this test. local_tmp = tempfile.mkdtemp(dir = self.tmp_dir) # these are the usual values we will be throwing to the function, however # we will swap these for nulls or malformed values every now and then to # test input project_name = "test_suite" metadata_directory = local_tmp location_in_repository = '/prefix' targets_directory = None key = None # create a blank project project = developer_tool.create_new_project(project_name, metadata_directory, location_in_repository) self.assertTrue(isinstance(project, developer_tool.Project)) self.assertTrue(project.layout_type == 'repo-like') self.assertTrue(project.prefix == location_in_repository) self.assertTrue(project._project_name == project_name) self.assertTrue(project._metadata_directory == os.path.join(metadata_directory,METADATA_DIRECTORY_NAME)) self.assertTrue(project._targets_directory == os.path.join(metadata_directory,TARGETS_DIRECTORY_NAME)) # create a blank project without a prefix project = developer_tool.create_new_project(project_name, metadata_directory) self.assertTrue(isinstance(project, developer_tool.Project)) self.assertTrue(project.layout_type == 'repo-like') self.assertTrue(project.prefix == '') self.assertTrue(project._project_name == project_name) self.assertTrue(project._metadata_directory == os.path.join(metadata_directory,METADATA_DIRECTORY_NAME)) self.assertTrue(project._targets_directory == os.path.join(metadata_directory,TARGETS_DIRECTORY_NAME)) # create a blank project without a valid metadata directory self.assertRaises(tuf.FormatError, developer_tool.create_new_project, 0, metadata_directory, location_in_repository) self.assertRaises(tuf.FormatError, developer_tool.create_new_project, project_name, 0, location_in_repository) self.assertRaises(tuf.FormatError, developer_tool.create_new_project, project_name, metadata_directory, 0) # create a new project with a flat layout targets_directory = tempfile.mkdtemp(dir = local_tmp) metadata_directory = tempfile.mkdtemp(dir = local_tmp) project = developer_tool.create_new_project(project_name, metadata_directory, location_in_repository, targets_directory) self.assertTrue(isinstance(project, developer_tool.Project)) self.assertTrue(project.layout_type == 'flat') self.assertTrue(project.prefix == location_in_repository) self.assertTrue(project._project_name == project_name) self.assertTrue(project._metadata_directory == metadata_directory) self.assertTrue(project._targets_directory == targets_directory) # finally, check that if targets_directory is set, it is valid self.assertRaises(tuf.FormatError, developer_tool.create_new_project, project_name, metadata_directory, location_in_repository, 0) # copy a key to our workspace and create a new project with it. keystore_path = os.path.join('repository_data','keystore') # I will use the same key as the one provided in the repository # tool tests for the root role, but this is not a root role... root_key_path = os.path.join(keystore_path,'root_key.pub') project_key = developer_tool.import_rsa_publickey_from_file(root_key_path) # test create new project with a key added by default project = developer_tool.create_new_project(project_name, metadata_directory, location_in_repository, targets_directory, project_key) self.assertTrue(isinstance(project, developer_tool.Project)) self.assertTrue(project.layout_type == 'flat') self.assertTrue(project.prefix == location_in_repository) self.assertTrue(project._project_name == project_name) self.assertTrue(project._metadata_directory == metadata_directory) self.assertTrue(project._targets_directory == targets_directory) self.assertTrue(len(project.keys) == 1) self.assertTrue(project.keys[0] == project_key['keyid']) shutil.rmtree(local_tmp) def test_load_project(self): # this test case will try to load an existing project and test for the result # then we will try to load a nonexisting project and expect a correct error # handler # finally, we will try to overwrite the existing prefix on the loaded project # create a local subfolder for this test. local_tmp = tempfile.mkdtemp(dir = self.tmp_dir) # test inexisting project filepath nonexistent_path = os.path.join(local_tmp, "nonexistent") self.assertRaises(IOError, developer_tool.load_project, nonexistent_path) # copy the pregenerated metadata project_data_filepath = os.path.join('repository_data', 'project') target_project_data_filepath = os.path.join(local_tmp, 'project') shutil.copytree("repository_data/project", target_project_data_filepath) # load a project properly... repo_filepath = os.path.join(local_tmp, 'project', 'test-repo') project = developer_tool.load_project(repo_filepath) self.assertTrue(project.layout_type == "repo-like") repo_filepath = os.path.join(local_tmp, 'project', 'test-flat') project = developer_tool.load_project(repo_filepath) self.assertTrue(project.layout_type == 'flat') # load a project ovrwriting the prefix project = developer_tool.load_project(repo_filepath, prefix='new') self.assertTrue(project.prefix == 'new') def test_add_verification_keys(self): # maybe we need to clear the roledb and keydb # create a new project instance project = developer_tool.Project("test_verification_keys", "somepath", "someotherpath", "prefix") # add invalid verification key self.assertRaises(tuf.FormatError, project.add_verification_key, "invalid") # add verification key # - load it first keystore_path = os.path.join('repository_data','keystore') first_verification_key_path = os.path.join(keystore_path,'root_key.pub') first_verification_key = \ developer_tool.import_rsa_publickey_from_file(first_verification_key_path) project.add_verification_key(first_verification_key) # add another verification key (should expect exception) second_verification_key_path = os.path.join(keystore_path,'snapshot_key.pub') second_verification_key = \ developer_tool.import_rsa_publickey_from_file(second_verification_key_path) self.assertRaises(tuf.Error, project.add_verification_key,(second_verification_key)) # add a verification key for the delegation project.delegate("somedelegation", [], []) project("somedelegation").add_verification_key(first_verification_key) project("somedelegation").add_verification_key(second_verification_key) # add another delegation of the delegation project("somedelegation").delegate("somesubdelegation", [], []) project("somedelegation")("somesubdelegation").add_verification_key( first_verification_key) project("somedelegation")("somesubdelegation").add_verification_key( second_verification_key) def test_write(self): # create tmp directory local_tmp = tempfile.mkdtemp(dir=self.tmp_dir) # create new project inside tmp directory project = developer_tool.create_new_project("test_write", local_tmp, "prefix"); # create some target files inside the tmp directory target_filepath = os.path.join(local_tmp, "targets", "test_target") with open(target_filepath, "wt") as fp: fp.write("testing file") # add the targets project.add_target(target_filepath) # add verification keys keystore_path = os.path.join('repository_data','keystore') project_key_path = os.path.join(keystore_path,'root_key.pub') project_key = \ developer_tool.import_rsa_publickey_from_file(project_key_path) # call status (for the sake of doing it) project.status() project.add_verification_key(project_key) # add another verification key (should expect exception) delegation_key_path = os.path.join(keystore_path,'snapshot_key.pub') delegation_key = \ developer_tool.import_rsa_publickey_from_file(delegation_key_path) # add a subdelegation subdelegation_key_path = os.path.join(keystore_path,'timestamp_key.pub') subdelegation_key = \ developer_tool.import_rsa_publickey_from_file(subdelegation_key_path) # add a delegation project.delegate("delegation", [delegation_key], []) project("delegation").delegate("subdelegation", [subdelegation_key], []) # call write (except) self.assertRaises(tuf.Error, project.write, ()) # call status (for the sake of doing it) project.status() # load private keys project_private_key_path = os.path.join(keystore_path, 'root_key') project_private_key = \ developer_tool.import_rsa_privatekey_from_file(project_private_key_path, 'password') delegation_private_key_path = os.path.join(keystore_path, 'snapshot_key') delegation_private_key = \ developer_tool.import_rsa_privatekey_from_file(delegation_private_key_path, 'password') subdelegation_private_key_path = \ os.path.join(keystore_path, 'timestamp_key') subdelegation_private_key = \ developer_tool.import_rsa_privatekey_from_file(subdelegation_private_key_path, 'password') # test partial write # backup everything (again) # + backup targets: targets_backup = project.target_files # + backup delegations delegations_backup = \ tuf.roledb.get_delegated_rolenames(project._project_name) # + backup layout type layout_type_backup = project.layout_type # + backup keyid's keys_backup = project.keys delegation_keys_backup = project("delegation").keys # + backup the prefix prefix_backup = project.prefix # + backup the name name_backup = project._project_name # set the compressions, we will be checking this part here too project.compressions = ['gz'] project('delegation').compressions = project.compressions # write an reload project.write(write_partial=True) # import pdb; pdb.set_trace() project = developer_tool.load_project(local_tmp) # check against backup self.assertEquals(project.target_files, targets_backup) new_delegations = tuf.roledb.get_delegated_rolenames(project._project_name) self.assertEquals(new_delegations, delegations_backup) self.assertEquals(project.layout_type, layout_type_backup) self.assertEquals(project.keys, keys_backup) self.assertEquals(project("delegation").keys, delegation_keys_backup) self.assertEquals(project.prefix, prefix_backup) self.assertEquals(project._project_name, name_backup) roleinfo = tuf.roledb.get_roleinfo(project._project_name) #import pdb;pdb.set_trace() self.assertEquals(roleinfo['partial_loaded'], True) # load_signing_keys project.load_signing_key(project_private_key) project("delegation").load_signing_key(delegation_private_key) project("delegation")("subdelegation").load_signing_key( subdelegation_private_key) project.status() # backup everything # + backup targets: targets_backup = project.target_files # + backup delegations delegations_backup = \ tuf.roledb.get_delegated_rolenames(project._project_name) # + backup layout type layout_type_backup = project.layout_type # + backup keyid's keys_backup = project.keys delegation_keys_backup = project("delegation").keys # + backup the prefix prefix_backup = project.prefix # + backup the name name_backup = project._project_name # call status (for the sake of doing it) # project.status() # call write project.write() # call load project = developer_tool.load_project(local_tmp) # check against backup self.assertEquals(project.target_files, targets_backup) new_delegations = tuf.roledb.get_delegated_rolenames(project._project_name) self.assertEquals(new_delegations, delegations_backup) self.assertEquals(project.layout_type, layout_type_backup) self.assertEquals(project.keys, keys_backup) self.assertEquals(project("delegation").keys, delegation_keys_backup) self.assertEquals(project.prefix, prefix_backup) self.assertEquals(project._project_name, name_backup) if __name__ == '__main__': unittest.main()