def test_save_public_report(self): fake_path = "fake_path" file_manager = PublicReportFileManager(self.logger, '/some/fake/absolute/path') file_manager.write_data = Mock() file_manager.remove_file = Mock() file_manager.get_public_report_path = MagicMock(return_value=fake_path) with file_manager_set(app, file_manager): desired_responses = [{ 'name': 'Edits - test', 'cohort': { 'id': self.cohort.id, 'name': self.cohort.name, }, 'metric': { 'name': 'NamespaceEdits', 'timeseries': 'month', 'namespaces': [0, 1, 2], 'start_date': '2013-01-01 00:00:00', 'end_date': '2013-05-01 00:00:00', 'individualResults': True, 'aggregateResults': True, 'aggregateSum': False, 'aggregateAverage': True, 'aggregateStandardDeviation': False, }, }] json_to_post = json.dumps(desired_responses) response = self.client.post('/reports/create/', data=dict(responses=json_to_post)) # Wait a second for the task to get processed time.sleep(1) # Check that the task has been created response = self.client.get('/reports/list/') parsed = json.loads(response.data) result_key = parsed['reports'][-1]['result_key'] task, report = get_celery_task(result_key) assert_true(task and report) # Make the report publically accessible (save it to static/public) response = self.client.post('/reports/set-public/{}'.format( report.id)) assert_true(response.status_code == 200) assert_equal(file_manager.write_data.call_count, 1) # Now make the report private (remove it from static/public) response = self.client.post('/reports/unset-public/{}'.format( report.id)) assert_true(response.status_code == 200) file_manager.remove_file.assert_called_with(fake_path) assert_equal(file_manager.remove_file.call_count, 1)
def test_save_public_report(self): fake_path = "fake_path" file_manager = PublicReportFileManager(self.logger, '/some/fake/absolute/path') file_manager.write_data = Mock() file_manager.remove_file = Mock() file_manager.get_public_report_path = MagicMock(return_value=fake_path) with file_manager_set(app, file_manager): desired_responses = [{ 'name': 'Edits - test', 'cohort': { 'id': self.cohort.id, 'name': self.cohort.name, }, 'metric': { 'name': 'NamespaceEdits', 'timeseries': 'month', 'namespaces': [0, 1, 2], 'start_date': '2013-01-01 00:00:00', 'end_date': '2013-05-01 00:00:00', 'individualResults': True, 'aggregateResults': True, 'aggregateSum': False, 'aggregateAverage': True, 'aggregateStandardDeviation': False, }, }] json_to_post = json.dumps(desired_responses) response = self.client.post('/reports/create/', data=dict( responses=json_to_post )) # Wait a second for the task to get processed time.sleep(1) # Check that the task has been created response = self.client.get('/reports/list/') parsed = json.loads(response.data) result_key = parsed['reports'][-1]['result_key'] task, report = get_celery_task(result_key) assert_true(task and report) # Make the report publically accessible (save it to static/public) response = self.client.post('/reports/set-public/{}'.format(report.id)) assert_true(response.status_code == 200) assert_equal(file_manager.write_data.call_count, 1) # Now make the report private (remove it from static/public) response = self.client.post('/reports/unset-public/{}'.format(report.id)) assert_true(response.status_code == 200) file_manager.remove_file.assert_called_with(fake_path) assert_equal(file_manager.remove_file.call_count, 1)
def __init__(self, report_id, created, results, file_manager=None): """ TODO: Add dependency injection for the file_manager, we are passing it on the constructor for easier testing but the object should come from the application context Parameters: report_id : identifier of the report, needed to find directory to write to if report is recurrent created : date report was created, used to identify a single run of a recurrent report results : data to write to disk file_manager: PublicReportFileManager, adding to constructor for easy testing. """ self.report_id = report_id self.created_string = format_date_for_public_report_file(created) self.results = json_string(results) self.file_manager = file_manager or PublicReportFileManager( task_logger, get_absolute_path()) # there should not be a need to call these functions more than once self.path = self.file_manager.get_public_report_path(self.report_id, recurrent=True, create=True) # TODO use file manager to get function when function is available self.filepath = os.path.join(self.path, self.created_string)
def test_public_report_state_change_error(self): """ Persistent Report should propagate IO errors from PublicReportFileManager """ self.app = Mock() self.logger = Mock(spec=RootLogger) file_manager = PublicReportFileManager(self.logger, '/some/fake/absolute/path') file_manager.write_data = Mock(side_effect=PublicReportIOError('Boom!')) # do not write anything to disk file_manager.get_public_report_path = Mock() ReportStore.make_report_public( self.reports[0].id, self.reports[0].user_id, file_manager, 'testing data' )
def test_public_report_state_change_error(self): """ Persistent Report should propagate IO errors from PublicReportFileManager """ self.app = Mock() self.logger = Mock(spec=RootLogger) file_manager = PublicReportFileManager(self.logger, '/some/fake/absolute/path') file_manager.write_data = Mock( side_effect=PublicReportIOError('Boom!')) # do not write anything to disk file_manager.get_public_report_path = Mock() ReportStore.make_report_public(self.reports[0].id, self.reports[0].user_id, file_manager, 'testing data')
class PublicReportFileMangerTest(unittest.TestCase): """ Tests should have no side effects. i.e. should not create any files on disk If there is a reason why they would they should be cleaned up after Assumes /public/static directory is existing, puppet must have created it """ def setUp(self): # setup mock logger self.logger = Mock(spec=RootLogger) self.api = PublicReportFileManager(self.logger, './wikimetrics/') def tearDown(self): pass def test_get_public_report_path(self): """ Path should be constructed acording to protocol """ absolute_report_path = self.api.get_public_report_path('fake-report-id') fake_path = 'static/public/fake-report-id.json' # should end with 'static/public/fake-report-id.json' l = len(fake_path) path_len = len(absolute_report_path) substr = absolute_report_path[path_len - l:path_len] assert_equals(substr, fake_path) @raises(PublicReportIOError) def test_cannot_write_file(self): """ Correct exception is raised when we cannot write to the given path. """ self.api.write_data('/some-fake/path/to-create-file/', 'some-string') @raises(PublicReportIOError) def test_cannot_remove_file(self): """ Correct exception is raised when we cannot delete a given report """ self.api.remove_file('/some-fake/path/to-delete-file.json')
def setUp(self): logger = Mock(spec=RootLogger) self.results = {'results': 'good'} self.fake_path = '/fake/fake/path/' file_manager = PublicReportFileManager(logger, '/some/fake/absolute/path') file_manager.write_data = Mock() file_manager.remove_file = Mock() file_manager.get_public_report_path = MagicMock(return_value=self.fake_path) file_manager.coalesce_recurrent_reports = MagicMock(return_value=self.results) file_manager.remove_old_report_files = MagicMock() self.file_manager = file_manager
def setup_filemanager(): if request.endpoint is not None: if request.path.startswith('/reports'): file_manager = getattr(g, 'file_manager', None) if file_manager is None: g.file_manager = PublicReportFileManager( app.logger, app.absolute_path_to_app_root) cohort_service = getattr(g, 'cohort_service', None) centralauth_service = getattr(g, 'centralauth_service', None) if cohort_service is None: g.cohort_service = CohortService() if centralauth_service is None: g.centralauth_service = CentralAuthService()
def setUp(self): # setup mock logger self.logger = Mock(spec=RootLogger) self.api = PublicReportFileManager(self.logger, './wikimetrics/') self.test_report_path = os.path.join(get_absolute_path(), os.pardir, 'tests')
class PublicReportFileMangerTest(unittest.TestCase): """ Tests should have no side effects. i.e. should not create any files on disk If there is a reason why they would they should be cleaned up after Assumes /public/static directory is existing, puppet must have created it """ def setUp(self): # setup mock logger self.logger = Mock(spec=RootLogger) self.api = PublicReportFileManager(self.logger, './wikimetrics/') self.test_report_path = os.path.join(get_absolute_path(), os.pardir, 'tests') def tearDown(self): pass def test_get_public_report_path(self): """ Path should be constructed acording to protocol """ absolute_report_path = self.api.get_public_report_path('fake-report-id') fake_path = 'static/public/fake-report-id.json' # should end with 'static/public/fake-report-id.json' l = len(fake_path) path_len = len(absolute_report_path) substr = absolute_report_path[path_len - l:path_len] assert_equal(substr, fake_path) @raises(PublicReportIOError) def test_cannot_write_file(self): """ Correct exception is raised when we cannot write to the given path. """ self.api.write_data('/some-fake/path/to-create-file/', 'some-string') @raises(PublicReportIOError) def test_cannot_remove_file(self): """ Correct exception is raised when we cannot delete a given report """ self.api.remove_file('/some-fake/path/to-delete-file.json') def test_coalesce_recurrent_reports(self): self.api.root_dir = self.test_report_path assert_true(os.path.isdir(self.test_report_path)) test_report_id = '0000' test_report_dir = os.sep.join((self.test_report_path, 'static', 'public', test_report_id)) full_report = self.api.coalesce_recurrent_reports(test_report_id) # Confirm the coalesced file has the correct keys (the "Metric_end_date" for each # child report, and that the individual reports in the coalesced file match the # content of each child report file files_to_coalesce = [f for f in os.listdir(test_report_dir) if os.path.isfile( os.sep.join((test_report_dir, f))) and f != COALESCED_REPORT_FILE] assert_equal(len(files_to_coalesce), 4) report_results = [] users_reported = set() dates = set() for f in files_to_coalesce: with open(os.sep.join((test_report_dir, f))) as json_file: try: loaded = json.load(json_file) for u in loaded['result'][Aggregation.IND]: users_reported.add(u) for d in loaded['result'][Aggregation.AVG]['edits']: dates.add(d) report_results.append(loaded) except ValueError: pass assert_equal(len(report_results), 3) # There are 3 valid test report files assert_equal({k for k in full_report}, { 'result', 'parameters' }) assert_equal({k for k in full_report['result']}, { Aggregation.AVG, Aggregation.IND }) assert_equal({k for k in full_report['result'][Aggregation.IND]}, users_reported) assert_equal({k for k in full_report['result'][Aggregation.AVG]['edits']}, dates) @raises(PublicReportIOError) def test_remove_recurrent_report(self): # Attempt to delete a non-existent recurrent report directory self.api.root_dir = self.test_report_path test_report_id = '0001' self.api.remove_recurrent_report(test_report_id)
def setUp(self): # setup mock logger self.logger = Mock(spec=RootLogger) self.api = PublicReportFileManager(self.logger, './wikimetrics/')
class PublicReportFileMangerTest(unittest.TestCase): """ Tests should have no side effects. i.e. should not create any files on disk If there is a reason why they would they should be cleaned up after Assumes /public/static directory is existing, puppet must have created it """ def setUp(self): # setup mock logger self.logger = Mock(spec=RootLogger) self.api = PublicReportFileManager(self.logger, './wikimetrics/') self.test_report_path = os.path.join(get_absolute_path(), os.pardir, 'tests') def tearDown(self): pass def test_get_public_report_path(self): """ Path should be constructed acording to protocol """ absolute_report_path = self.api.get_public_report_path( 'fake-report-id') fake_path = 'static/public/fake-report-id.json' # should end with 'static/public/fake-report-id.json' l = len(fake_path) path_len = len(absolute_report_path) substr = absolute_report_path[path_len - l:path_len] assert_equal(substr, fake_path) @raises(PublicReportIOError) def test_cannot_write_file(self): """ Correct exception is raised when we cannot write to the given path. """ self.api.write_data('/some-fake/path/to-create-file/', 'some-string') @raises(PublicReportIOError) def test_cannot_remove_file(self): """ Correct exception is raised when we cannot delete a given report """ self.api.remove_file('/some-fake/path/to-delete-file.json') def test_coalesce_recurrent_reports(self): self.api.root_dir = self.test_report_path assert_true(os.path.isdir(self.test_report_path)) test_report_id = '0000' test_report_dir = os.sep.join( (self.test_report_path, 'static', 'public', test_report_id)) full_report = self.api.coalesce_recurrent_reports(test_report_id) # Confirm the coalesced file has the correct keys (the "Metric_end_date" for each # child report, and that the individual reports in the coalesced file match the # content of each child report file files_to_coalesce = [ f for f in os.listdir(test_report_dir) if os.path.isfile(os.sep.join((test_report_dir, f))) and f != COALESCED_REPORT_FILE ] assert_equal(len(files_to_coalesce), 4) report_results = [] users_reported = set() dates = set() for f in files_to_coalesce: with open(os.sep.join((test_report_dir, f))) as json_file: try: loaded = json.load(json_file) for u in loaded['result'][Aggregation.IND]: users_reported.add(u) for d in loaded['result'][Aggregation.AVG]['edits']: dates.add(d) report_results.append(loaded) except ValueError: pass assert_equal(len(report_results), 3) # There are 3 valid test report files assert_equal({k for k in full_report}, {'result', 'parameters'}) assert_equal({k for k in full_report['result']}, {Aggregation.AVG, Aggregation.IND}) assert_equal({k for k in full_report['result'][Aggregation.IND]}, users_reported) assert_equal( {k for k in full_report['result'][Aggregation.AVG]['edits']}, dates) @raises(PublicReportIOError) def test_remove_recurrent_report(self): # Attempt to delete a non-existent recurrent report directory self.api.root_dir = self.test_report_path test_report_id = '0001' self.api.remove_recurrent_report(test_report_id)