def test_update_required_not_forced(self): """ Test that we check if we're on the latest version if the latest local installation update was 3 days ago and the frequency is set to daily. The local repository is in the latest version (git pull is run before) """ git_client = GitClient(".") git_client.pull() self.vmgr._start_cfg = start_cfg = StartUpConfig() start_cfg._autoupd = True start_cfg._freq = StartUpConfig.FREQ_DAILY last_upd = datetime.date.today() - datetime.timedelta(days=3) start_cfg._lastupd = last_upd on_update_check_mock = MagicMock() on_already_latest_mock = MagicMock() on_update_mock = MagicMock() self.vmgr.register(VersionMgr.ON_UPDATE_CHECK, on_update_check_mock, None) self.vmgr.register(VersionMgr.ON_ALREADY_LATEST, on_already_latest_mock, None) self.vmgr.register(VersionMgr.ON_UPDATE, on_update_mock, None) self.vmgr.update() self.assertEqual(on_update_check_mock.call_count, 1) self.assertEqual(on_already_latest_mock.call_count, 1) self.assertEqual(on_update_mock.call_count, 0)
def test_get_remote_head_id(self): # For some strange reason jenkins creates a branch called # jenkins-<job name> during the build, which makes this test FAIL # if we don't take that into account if get_current_branch().startswith('jenkins-'): raise SkipTest('Workaround for Jenkins Git plugin wierdness.') client = GitClient(W3AF_LOCAL_PATH) # I don't really want to wait for the local repo to update itself # using "git fetch", so I simply put this as a mock client.fetch = MagicMock() remote_head = client.get_remote_head_id() client.fetch.assert_called_once_with() self.assertEqual(len(remote_head), 40) self.assertIsInstance(remote_head, basestring) # Get the ID using an alternative way for double checking branch = 'refs/remotes/origin/%s' % get_current_branch() proc = subprocess.Popen(['git', 'for-each-ref', branch], stdout=subprocess.PIPE) commit_id_line = proc.stdout.readline() commit_id_line = commit_id_line.strip() commit_id, _ = commit_id_line.split(' ') self.assertEqual(remote_head, commit_id)
def test_update_required_not_forced(self): ''' Test that we check if we're on the latest version if the latest local installation update was 3 days ago and the frequency is set to daily. The local repository is in the latest version (git pull is run before) ''' git_client = GitClient('.') git_client.pull() self.vmgr._start_cfg = start_cfg = StartUpConfig() start_cfg._autoupd = True start_cfg._freq = StartUpConfig.FREQ_DAILY last_upd = datetime.date.today() - datetime.timedelta(days=3) start_cfg._lastupd = last_upd on_update_check_mock = MagicMock() on_already_latest_mock = MagicMock() on_update_mock = MagicMock() self.vmgr.register(VersionMgr.ON_UPDATE_CHECK, on_update_check_mock, None) self.vmgr.register(VersionMgr.ON_ALREADY_LATEST, on_already_latest_mock, None) self.vmgr.register(VersionMgr.ON_UPDATE, on_update_mock, None) self.vmgr.update() self.assertEqual(on_update_check_mock.call_count, 1) self.assertEqual(on_already_latest_mock.call_count, 1) self.assertEqual(on_update_mock.call_count, 0)
def test_get_local_head_id(self): client = GitClient(W3AF_LOCAL_PATH) local_head = client.get_local_head_id() self.assertEqual(len(local_head), 40) self.assertIsInstance(local_head, basestring) # Get the ID using an alternative way for double checking proc = subprocess.Popen(['git', 'log', '-n', '1'], stdout=subprocess.PIPE) commit_id_line = proc.stdout.readline() commit_id_line = commit_id_line.strip() _, commit_id = commit_id_line.split(' ') self.assertEqual(local_head, commit_id)
def test_get_URL(self): client = GitClient(W3AF_LOCAL_PATH) # https://github.com/andresriancho/w3af/ provides a list of all the # URLs which can be used to clone the repo REPO_URLS = ('[email protected]:andresriancho/w3af.git', 'https://github.com/andresriancho/w3af.git', 'git://github.com/andresriancho/w3af.git') self.assertIn(client.URL, REPO_URLS)
def __init__(self, localpath=W3AF_LOCAL_PATH, log=None): ''' w3af version manager class. Handles the logic concerning the automatic update/commit process of the code. :param localpath: Working directory :param log: Default output function ''' self._localpath = localpath self._client = GitClient(localpath) self._client.add_observer(self._client_progress) log = log if log is not None else om.out.console self._log = log # Set default events self.register_default_events(log) # Startup configuration self._start_cfg = StartUpConfig()
def test_update_required_outdated_not_forced(self): ''' Test that we check if we're on the latest version if the latest local installation update was 3 days ago and the frequency is set to daily. The local repository is NOT in the latest version. A 'git reset --hard' is run at the beginning of this test to reset the repo to a revision before the latest one. ''' try: git_client = GitClient('.') head_id = git_client.get_local_head_id() one_before_head = git_client.get_parent_for_revision(head_id) git_client.reset_to_previous_state(one_before_head) self.vmgr._start_cfg = start_cfg = StartUpConfig() start_cfg._autoupd = True start_cfg._freq = StartUpConfig.FREQ_DAILY last_upd = datetime.date.today() - datetime.timedelta(days=3) start_cfg._lastupd = last_upd on_update_check_mock = MagicMock() on_already_latest_mock = MagicMock() on_update_mock = MagicMock() self.vmgr.register(VersionMgr.ON_UPDATE_CHECK, on_update_check_mock, None) self.vmgr.register(VersionMgr.ON_ALREADY_LATEST, on_already_latest_mock, None) self.vmgr.register(VersionMgr.ON_UPDATE, on_update_mock, None) self.vmgr.callback_onupdate_confirm = MagicMock(side_effect=[ True, ]) self.vmgr.update() self.assertEqual(on_update_check_mock.call_count, 1) self.assertEqual(on_already_latest_mock.call_count, 0) self.assertEqual(on_update_mock.call_count, 1) finally: git_client.pull()
def test_update_required_outdated_not_forced(self): """ Test that we check if we're on the latest version if the latest local installation update was 3 days ago and the frequency is set to daily. The local repository is NOT in the latest version. A 'git reset --hard' is run at the beginning of this test to reset the repo to a revision before the latest one. """ try: git_client = GitClient(".") head_id = git_client.get_local_head_id() one_before_head = git_client.get_parent_for_revision(head_id) git_client.reset_to_previous_state(one_before_head) self.vmgr._start_cfg = start_cfg = StartUpConfig() start_cfg._autoupd = True start_cfg._freq = StartUpConfig.FREQ_DAILY last_upd = datetime.date.today() - datetime.timedelta(days=3) start_cfg._lastupd = last_upd on_update_check_mock = MagicMock() on_already_latest_mock = MagicMock() on_update_mock = MagicMock() self.vmgr.register(VersionMgr.ON_UPDATE_CHECK, on_update_check_mock, None) self.vmgr.register(VersionMgr.ON_ALREADY_LATEST, on_already_latest_mock, None) self.vmgr.register(VersionMgr.ON_UPDATE, on_update_mock, None) self.vmgr.callback_onupdate_confirm = MagicMock(side_effect=[True]) self.vmgr.update() self.assertEqual(on_update_check_mock.call_count, 1) self.assertEqual(on_already_latest_mock.call_count, 0) self.assertEqual(on_update_mock.call_count, 1) finally: git_client.pull()
class VersionMgr(object): ''' Perform SVN w3af code update and commit. When an instance is created loads data from a .conf file that will be used when actions are executed. Also provides some callbacks as well as events to register to. Callbacks on: UPDATE: * callback_onupdate_confirm(msg) Return True/False * callback_onupdate_show_log(msg, log_func) Displays 'msg' to the user and depending on user's answer call 'log_func()' which returns a string with the summary of the commit logs from the from local revision to repo's. * callback_onupdate_error If an SVNError occurs this callback is called in order to the client class handles the error. Probably notify the user. COMMIT: {implementation pending} Events: ON_UPDATE ON_UPDATE_ADDED_DEP ON_UPDATE_CHECK ON_ACTION_ERROR ''' # Events constants ON_UPDATE = 1 ON_UPDATE_ADDED_DEP = 2 ON_UPDATE_CHECK = 3 ON_ALREADY_LATEST = 4 ON_ACTION_ERROR = 5 ON_COMMIT = 6 ON_PROGRESS = 7 # Callbacks callback_onupdate_confirm = None callback_onupdate_show_log = None callback_onupdate_error = None # Revision constants HEAD = 'HEAD' BACK = 'BACK' def __init__(self, localpath=W3AF_LOCAL_PATH, log=None): ''' w3af version manager class. Handles the logic concerning the automatic update/commit process of the code. :param localpath: Working directory :param log: Default output function ''' self._localpath = localpath self._client = GitClient(localpath) self._client.add_observer(self._client_progress) log = log if log is not None else om.out.console self._log = log # Set default events self.register_default_events(log) # Startup configuration self._start_cfg = StartUpConfig() def _client_progress(self, op_code, cur_count, max_count, message): ''' The GitClient will call this method when it has progress to show for fetch() and pull(). Please note that because I don't need it at this moment, I'm simply ignoring all parameters and just letting the observers know that this event was triggered. ''' self._notify(VersionMgr.ON_PROGRESS) def register_default_events(self, log): ''' Default events registration :param log: Log function to call for events :return: None, all saved in self._reg_funcs ''' # Registered functions self._reg_funcs = {} msg = ('Checking if a new version is available in our git repository.' ' Please wait...') self.register(VersionMgr.ON_UPDATE_CHECK, log, msg) msg = ('Your installation is already on the latest available version.') self.register(VersionMgr.ON_ALREADY_LATEST, log, msg) msg = 'w3af is updating from github.com ...' self.register(VersionMgr.ON_UPDATE, log, msg) msg = ('The third-party dependencies for w3af have changed, please' ' exit the framework and run it again to load all changes' ' and install any missing modules.') self.register(VersionMgr.ON_UPDATE_ADDED_DEP, log, msg) def update(self, force=False): ''' Perform code update if necessary. Return three elems tuple with the ChangeLog of the changed files, the local and the final commit id. :param force: Force update ignoring the startup config. :return: (changelog: A ChangeLog instance, local_head_id: The local id before the update, commit_id: The commit id after the update) ''' if not force and not self._has_to_update(): # No need to update based on user preferences return # Save the latest update date, always, even when the update had errors # or there was no update available self._start_cfg.last_upd = date.today() self._start_cfg.save() local_head_id = self._client.get_local_head_id() short_local_head_id = to_short_id(local_head_id) # Lets update! self._notify(VersionMgr.ON_UPDATE_CHECK) # This performs a fetch() which takes time remote_head_id = self._client.get_remote_head_id() short_remote_head_id = to_short_id(remote_head_id) if local_head_id == remote_head_id: # If local and repo's rev are the same => Nothing to do. self._notify(VersionMgr.ON_ALREADY_LATEST) return if self._user_confirmed_update(short_local_head_id, local_head_id, short_remote_head_id, remote_head_id): return self.__update_impl() def _user_confirmed_update(self, short_local_head_id, local_head_id, short_remote_head_id, remote_head_id): ''' Ask the user if he wants to update or not. :return: True if the user wants to update. ''' # Call callback function if self.callback_onupdate_confirm is not None: callback = self.callback_onupdate_confirm # pylint: disable=E1102 # pylint: disable=E1103 msg = 'Your current w3af installation is %s (%s). Do you want '\ 'to update to %s (%s)?' proceed_upd = callback(msg % (short_local_head_id, get_commit_id_date(local_head_id), short_remote_head_id, get_commit_id_date(remote_head_id))) return proceed_upd def __update_impl(self): ''' Finally call the Git client's pull! :return: (changelog, local_head_id, target_commit) ''' self._notify(VersionMgr.ON_UPDATE) try: changelog = self._client.pull() except GitClientError, exc: msg = '%s' % exc self._notify(VersionMgr.ON_ACTION_ERROR, msg) return else:
class VersionMgr(object): ''' Perform SVN w3af code update and commit. When an instance is created loads data from a .conf file that will be used when actions are executed. Also provides some callbacks as well as events to register to. Callbacks on: UPDATE: * callback_onupdate_confirm(msg) Return True/False * callback_onupdate_show_log(msg, log_func) Displays 'msg' to the user and depending on user's answer call 'log_func()' which returns a string with the summary of the commit logs from the from local revision to repo's. * callback_onupdate_error If an SVNError occurs this callback is called in order to the client class handles the error. Probably notify the user. COMMIT: {implementation pending} Events: ON_UPDATE ON_UPDATE_ADDED_DEP ON_UPDATE_CHECK ON_ACTION_ERROR ''' # Events constants ON_UPDATE = 1 ON_UPDATE_ADDED_DEP = 2 ON_UPDATE_CHECK = 3 ON_ALREADY_LATEST = 4 ON_ACTION_ERROR = 5 ON_COMMIT = 6 ON_PROGRESS = 7 # Callbacks callback_onupdate_confirm = None callback_onupdate_show_log = None callback_onupdate_error = None # Revision constants HEAD = 'HEAD' BACK = 'BACK' def __init__(self, localpath=W3AF_LOCAL_PATH, log=None): ''' w3af version manager class. Handles the logic concerning the automatic update/commit process of the code. :param localpath: Working directory :param log: Default output function ''' self._localpath = localpath self._client = GitClient(localpath) self._client.add_observer(self._client_progress) log = log if log is not None else om.out.console self._log = log # Set default events self.register_default_events(log) # Startup configuration self._start_cfg = StartUpConfig() def _client_progress(self, op_code, cur_count, max_count, message): ''' The GitClient will call this method when it has progress to show for fetch() and pull(). Please note that because I don't need it at this moment, I'm simply ignoring all parameters and just letting the observers know that this event was triggered. ''' self._notify(VersionMgr.ON_PROGRESS) def register_default_events(self, log): ''' Default events registration :param log: Log function to call for events :return: None, all saved in self._reg_funcs ''' # Registered functions self._reg_funcs = {} msg = ('Checking if a new version is available in our git repository.' ' Please wait...') self.register(VersionMgr.ON_UPDATE_CHECK, log, msg) msg = ('Your installation is already on the latest available version.') self.register(VersionMgr.ON_ALREADY_LATEST, log, msg) msg = 'w3af is updating from github.com ...' self.register(VersionMgr.ON_UPDATE, log, msg) msg = ('The third-party dependencies for w3af have changed, please' ' exit the framework and run it again to load all changes' ' and install any missing modules.') self.register(VersionMgr.ON_UPDATE_ADDED_DEP, log, msg) def update(self, force=False): ''' Perform code update if necessary. Return three elems tuple with the ChangeLog of the changed files, the local and the final commit id. :param force: Force update ignoring the startup config. :return: (changelog: A ChangeLog instance, local_head_id: The local id before the update, commit_id: The commit id after the update) ''' if not force and not self._has_to_update(): # No need to update based on user preferences return # Save the latest update date, always, even when the update had errors # or there was no update available self._start_cfg.last_upd = date.today() self._start_cfg.save() local_head_id = self._client.get_local_head_id() short_local_head_id = to_short_id(local_head_id) # Lets update! self._notify(VersionMgr.ON_UPDATE_CHECK) # This performs a fetch() which takes time remote_head_id = self._client.get_remote_head_id() short_remote_head_id = to_short_id(remote_head_id) if local_head_id == remote_head_id: # If local and repo's rev are the same => Nothing to do. self._notify(VersionMgr.ON_ALREADY_LATEST) return if self._user_confirmed_update(short_local_head_id, local_head_id, short_remote_head_id, remote_head_id): return self.__update_impl() def _user_confirmed_update(self, short_local_head_id, local_head_id, short_remote_head_id, remote_head_id): ''' Ask the user if he wants to update or not. :return: True if the user wants to update. ''' # Call callback function if self.callback_onupdate_confirm is not None: callback = self.callback_onupdate_confirm # pylint: disable=E1102 # pylint: disable=E1103 msg = 'Your current w3af installation is %s (%s). Do you want '\ 'to update to %s (%s)?' proceed_upd = callback( msg % (short_local_head_id, get_commit_id_date(local_head_id), short_remote_head_id, get_commit_id_date(remote_head_id))) return proceed_upd def __update_impl(self): ''' Finally call the Git client's pull! :return: (changelog, local_head_id, target_commit) ''' self._notify(VersionMgr.ON_UPDATE) try: changelog = self._client.pull() except GitClientError, exc: msg = '%s' % exc self._notify(VersionMgr.ON_ACTION_ERROR, msg) return else: