class PagesCreatedWikiCohortTest(DatabaseTest): def setUp(self): """ Setup editing data using a regular cohort setup Setup a WikiCohort that will span to all users that we have in the project. """ DatabaseTest.setUp(self) self.common_cohort_4() self.create_wiki_cohort() self.cohort_service = CohortService() self.wiki_cohort = self.cohort_service.get( self.session, self.owner_user_id, by_id=self.basic_wiki_cohort.id ) # This should return an empty list, but if it returned anything, the objects # would be WikiUserStore objects, so we should treat it as such self.user_ids = [ w.mediawiki_userid for w in self.cohort_service.get_wikiusers(self.wiki_cohort) ] def test_pages_created_happy_case(self): """ Retrieve pages created metric for wiki cohort for project 'wiki' Results of tests should be identical as if we used cohort number 4 """ metric = PagesCreated( namespaces=[301, 302, 303], start_date='2013-06-19 00:00:00', end_date='2013-08-21 00:00:00' ) results = metric(self.user_ids, self.mwSession) assert_equal(results[self.editors[0].user_id]['pages_created'], 3) assert_equal(results[self.editors[1].user_id]['pages_created'], 1) def test_pages_created_extra_users(self): """ Retrieve pages created metric for wiki cohort for project 'wiki' Results should include the additional users created by `self.common_cohort_4(cohort=False)` """ self.common_cohort_4(cohort=False) metric = PagesCreated( namespaces=[301, 302, 303], start_date='2013-06-19 00:00:00', end_date='2013-08-21 00:00:00' ) results = metric(self.user_ids, self.mwSession) assert_equal(results[self.editors[0].user_id]['pages_created'], 3) assert_equal(results[self.editors[1].user_id]['pages_created'], 1) assert_equal(results[self.editors[0].user_id + 2]['pages_created'], 3) assert_equal(results[self.editors[1].user_id + 2]['pages_created'], 1)
def test_cohort_membership_basic_detail(self): def get_for_display_mock(session, user_id, by_id): assert_equal(by_id, unicode(self.cohort.id)) return self.cohort cohort_service_mock = CohortService() cohort_service_mock.get_for_display = get_for_display_mock with cohort_service_set(app, cohort_service_mock): response = self.app.get('/cohorts/{0}/membership'.format( self.cohort.id)) assert_equal(response.status_code, 200) assert_true(response.data.find(self.cohort.name) >= 0)
def test_cohort_membership_basic_detail(self): def get_for_display_mock(session, user_id, by_id): assert_equal(by_id, unicode(self.cohort.id)) return self.cohort cohort_service_mock = CohortService() cohort_service_mock.get_for_display = get_for_display_mock with cohort_service_set(app, cohort_service_mock): response = self.app.get('/cohorts/{0}/membership'.format( self.cohort.id )) assert_equal(response.status_code, 200) assert_true(response.data.find(self.cohort.name) >= 0)
def __init__(self, cohort, metric, *args, **kwargs): """ Parameters: metric : an instance of a Metric class cohort : a logical cohort object args : should include any parameters needed by ReportNode kwargs : should include any parameters needed by ReportNode """ super(MultiProjectMetricReport, self).__init__(*args, **kwargs) cohort_service = CohortService() self.children = [] for project, user_ids in cohort_service.get_users_by_project(cohort): # note that user_ids is actually just an iterator self.children.append( MetricReport(metric, cohort.id, user_ids, project, *args, **kwargs))
def __init__(self, cohort, metric, *args, **kwargs): """ Parameters: metric : an instance of a Metric class cohort : a logical cohort object args : should include any parameters needed by ReportNode kwargs : should include any parameters needed by ReportNode """ super(MultiProjectMetricReport, self).__init__(*args, **kwargs) cohort_service = CohortService() self.children = [] for project, user_ids in cohort_service.get_users_by_project(cohort): # note that user_ids is actually just an iterator self.children.append( MetricReport(metric, cohort.id, user_ids, project, *args, **kwargs) )
def __init__(self, cohort, metric, *args, **kwargs): """ Parameters: metric : an instance of a Metric class cohort : a logical cohort object args : should include any parameters needed by ReportNode kwargs : should include any parameters needed by ReportNode """ super(SumAggregateByUserReport, self).__init__(*args, **kwargs) # Get mediawiki's username map to be able to aggregate. service = CohortService() session = db.get_session() self.usernames = service.get_wikiusernames_for_cohort(cohort.id, session) self.children = [ MultiProjectMetricReport(cohort, metric, *args, **kwargs) ]
def test_delete_cohort_wikiuser(self): username_to_delete = 'To Delete' def delete_cohort_wikiuser_mock(raw_id_or_name, cohort_id, current_user_id, session, invalid_only): assert_equal(raw_id_or_name, username_to_delete) assert_equal(cohort_id, unicode(self.cohort.id)) assert_equal(invalid_only, False) cohort_service_mock = CohortService() cohort_service_mock.delete_cohort_wikiuser = delete_cohort_wikiuser_mock with cohort_service_set(app, cohort_service_mock): response = self.app.post( '/cohorts/{0}/membership/delete'.format(self.cohort.id), data={'raw_id_or_name': username_to_delete}) assert_equal(response.status_code, 200) assert_equal(json.loads(response.data)['message'], 'success')
def test_cohort_membership_full_detail(self): def get_for_display_mock(session, user_id, by_id): assert_equal(by_id, unicode(self.cohort.id)) return self.cohort def get_membership_mock(cohort, session): assert_equal(cohort, self.cohort) return 'mock' cohort_service_mock = CohortService() cohort_service_mock.get_for_display = get_for_display_mock cohort_service_mock.get_membership = get_membership_mock with cohort_service_set(app, cohort_service_mock): response = self.app.get( '/cohorts/{0}/membership?full_detail=true'.format( self.cohort.id)) assert_equal(response.status_code, 200) assert_equal(json.loads(response.data), {'membership': 'mock'})
def test_cohort_membership_full_detail(self): def get_for_display_mock(session, user_id, by_id): assert_equal(by_id, unicode(self.cohort.id)) return self.cohort def get_membership_mock(cohort, session): assert_equal(cohort, self.cohort) return 'mock' cohort_service_mock = CohortService() cohort_service_mock.get_for_display = get_for_display_mock cohort_service_mock.get_membership = get_membership_mock with cohort_service_set(app, cohort_service_mock): response = self.app.get('/cohorts/{0}/membership?full_detail=true'.format( self.cohort.id )) assert_equal(response.status_code, 200) assert_equal(json.loads(response.data), {'membership': 'mock'})
def test_delete_cohort_wikiuser(self): username_to_delete = 'To Delete' def delete_cohort_wikiuser_mock( raw_id_or_name, cohort_id, current_user_id, session, invalid_only): assert_equal(raw_id_or_name, username_to_delete) assert_equal(cohort_id, unicode(self.cohort.id)) assert_equal(invalid_only, False) cohort_service_mock = CohortService() cohort_service_mock.delete_cohort_wikiuser = delete_cohort_wikiuser_mock with cohort_service_set(app, cohort_service_mock): response = self.app.post( '/cohorts/{0}/membership/delete'.format(self.cohort.id), data={'raw_id_or_name': username_to_delete} ) assert_equal(response.status_code, 200) assert_equal(json.loads(response.data)['message'], 'success')
def setup_cohort_service(): if request.endpoint is not None: if request.path.startswith('/cohorts'): cohort_service = getattr(g, 'cohort_service', None) tag_service = getattr(g, 'tag_service', None) centralauth_service = getattr(g, 'centralauth_service', None) if cohort_service is None: g.cohort_service = CohortService() if tag_service is None: g.tag_service = TagService() if centralauth_service is None: g.centralauth_service = CentralAuthService()
def setUp(self): """ NOTE: self.cohort is a CohortStore object. When testing CohortService, one should use logical cohort objects (ie. FixedCohort, WikiCohort, etc.) """ DatabaseTest.setUp(self) self.common_cohort_1() self.editor_user_ids = [e.user_id for e in self.editors] self.cohort_service = CohortService() empty_cohort = CohortStore(enabled=True, class_name='Cohort') self.session.add(empty_cohort) self.session.commit() empty_cohort_user = CohortUserStore( user_id=self.owner_user_id, cohort_id=empty_cohort.id, role=CohortUserRole.OWNER, ) self.session.add(empty_cohort_user) self.session.commit() self.invalid_empty_cohort = CohortStore(enabled=True, class_name='FixedCohort', validated=True) self.session.add(self.invalid_empty_cohort) self.session.commit() invalid_empty_cohort_user = CohortUserStore( user_id=self.owner_user_id, cohort_id=self.invalid_empty_cohort.id, role=CohortUserRole.OWNER, ) self.session.add(invalid_empty_cohort_user) self.session.commit() self.empty_cohort = self.cohort_service.get(self.session, self.owner_user_id, by_id=empty_cohort.id) self.fixed_cohort = self.cohort_service.get(self.session, self.owner_user_id, by_id=self.cohort.id)
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 editing data using a regular cohort setup Setup a WikiCohort that will span to all users that we have in the project. """ DatabaseTest.setUp(self) self.common_cohort_4() self.create_wiki_cohort() self.cohort_service = CohortService() self.wiki_cohort = self.cohort_service.get( self.session, self.owner_user_id, by_id=self.basic_wiki_cohort.id ) # This should return an empty list, but if it returned anything, the objects # would be WikiUserStore objects, so we should treat it as such self.user_ids = [ w.mediawiki_userid for w in self.cohort_service.get_wikiusers(self.wiki_cohort) ]
def setUp(self): """ NOTE: self.cohort is a CohortStore object. When testing CohortService, one should use logical cohort objects (ie. FixedCohort, WikiCohort, etc.) """ DatabaseTest.setUp(self) self.common_cohort_1() self.editor_user_ids = [e.user_id for e in self.editors] self.cohort_service = CohortService() empty_cohort = CohortStore(enabled=True, class_name='Cohort') self.session.add(empty_cohort) self.session.commit() empty_cohort_user = CohortUserStore( user_id=self.owner_user_id, cohort_id=empty_cohort.id, role=CohortUserRole.OWNER, ) self.session.add(empty_cohort_user) self.session.commit() self.invalid_empty_cohort = CohortStore( enabled=True, class_name='FixedCohort', validated=True ) self.session.add(self.invalid_empty_cohort) self.session.commit() invalid_empty_cohort_user = CohortUserStore( user_id=self.owner_user_id, cohort_id=self.invalid_empty_cohort.id, role=CohortUserRole.OWNER, ) self.session.add(invalid_empty_cohort_user) self.session.commit() self.empty_cohort = self.cohort_service.get( self.session, self.owner_user_id, by_id=empty_cohort.id ) self.fixed_cohort = self.cohort_service.get( self.session, self.owner_user_id, by_id=self.cohort.id )
def get_validation_info(self): cohort_service = CohortService() return cohort_service.get_validation_info(self.cohort, self.session, True)
def __init__(self, parameters, user_id=0, recurrent_parent_id=None, created=None, persistent_id=None): """ Parameters: parameters : dictionary containing the following required keys: name : the name of the report cohort : dictionary defining the cohort, has keys: id : the id of the cohort metric : dictionary defining the metric, has keys: name : the name of the python class to instantiate recurrent : whether to rerun this daily public : whether to expose results publicly user_id : the user wishing to run this report recurrent_parent_id : the parent ReportStore.id for a recurrent run created : if set, represents the date of a recurrent run. This need not be the timestamp when the recurrent run has been created -- for example when backfilling. Hence, this does not fully match the semantics of the word 'created'. But since neither start nor end date have a separate column in the report table in the database, the covered period for backfilled recurring reports would be hard to identify when only looking at the raw database tables. To overcome this issue, we abuse the created date here. Raises: KeyError if required parameters are missing """ # get cohort cohort_service = CohortService() cohort_dict = parameters['cohort'] session = db.get_session() cohort = cohort_service.get(session, user_id, by_id=cohort_dict['id']) parameters['cohort']['size'] = cohort.size # construct metric metric_dict = parameters['metric'] metric = metric_classes[metric_dict['name']](**metric_dict) # if this is a recurrent run, don't show it in the UI if recurrent_parent_id is not None: self.show_in_ui = False public = parameters.get('public', False) recurrent = parameters.get('recurrent', False) super(RunReport, self).__init__( name=parameters['name'], user_id=user_id, parameters=parameters, public=public, recurrent=recurrent, recurrent_parent_id=recurrent_parent_id, created=created, store=True, persistent_id=persistent_id ) self.recurrent_parent_id = recurrent_parent_id self.public = public validate_report = ValidateReport( metric, cohort, recurrent_parent_id is None, user_id=user_id ) if validate_report.valid(): if recurrent and recurrent_parent_id is None: # Valid parent recurrent report # We do not add children that compute data as parent recurrent # reports just help the scheduler orchestrate child runs. # However, we employ a NullReport to allow coalescing even # when there was no recurrent run yet. self.children = [NullReport()] else: # Valid, but not a parent recurring report, so we add the child # node that does the real computation self.children = [AggregateReport( metric, cohort, metric_dict, parameters=parameters, user_id=user_id )] else: self.children = [validate_report]
def setUp(self): DatabaseTest.setUp(self) self.common_cohort_1() self.cohort_service = CohortService()
class CohortServiceTest(DatabaseTest): def setUp(self): """ NOTE: self.cohort is a CohortStore object. When testing CohortService, one should use logical cohort objects (ie. FixedCohort, WikiCohort, etc.) """ DatabaseTest.setUp(self) self.common_cohort_1() self.editor_user_ids = [e.user_id for e in self.editors] self.cohort_service = CohortService() empty_cohort = CohortStore(enabled=True, class_name='Cohort') self.session.add(empty_cohort) self.session.commit() empty_cohort_user = CohortUserStore( user_id=self.owner_user_id, cohort_id=empty_cohort.id, role=CohortUserRole.OWNER, ) self.session.add(empty_cohort_user) self.session.commit() self.invalid_empty_cohort = CohortStore( enabled=True, class_name='FixedCohort', validated=True ) self.session.add(self.invalid_empty_cohort) self.session.commit() invalid_empty_cohort_user = CohortUserStore( user_id=self.owner_user_id, cohort_id=self.invalid_empty_cohort.id, role=CohortUserRole.OWNER, ) self.session.add(invalid_empty_cohort_user) self.session.commit() self.empty_cohort = self.cohort_service.get( self.session, self.owner_user_id, by_id=empty_cohort.id ) self.fixed_cohort = self.cohort_service.get( self.session, self.owner_user_id, by_id=self.cohort.id ) def test_get(self): assert_equals(self.fixed_cohort.name, self.cohort.name) def test_get_by_name(self): c = self.cohort_service.get( self.session, self.owner_user_id, by_name=self.cohort.name ) assert_equals(c.name, self.cohort.name) def test_get_empty(self): assert_equals(self.empty_cohort.name, None) @raises(NoResultFound) def test_get_raises_exception_for_not_found_by_id(self): self.cohort_service.get(self.session, self.owner_user_id, by_id=0) @raises(NoResultFound) def test_get_raises_exception_for_not_found_by_name(self): self.cohort_service.get(self.session, self.owner_user_id, by_name='') @raises(Unauthorized) def test_get_unauthorized(self): self.cohort_service.get(self.session, 0, by_id=self.cohort.id) @raises(InvalidCohort) def test_get_invalid(self): self.cohort.validated = False self.session.commit() self.cohort_service.get(self.session, self.owner_user_id, by_id=self.cohort.id) @raises(InvalidCohort) def test_get_invalid_because_empty(self): self.cohort_service.get( self.session, self.owner_user_id, by_id=self.invalid_empty_cohort.id ) def test_get_size(self): assert_equals(self.fixed_cohort.size, 4) def test_get_size_empty(self): assert_equals(self.empty_cohort.size, 0) def test_get_users_by_project(self): c = self.cohort_service.get( self.session, self.owner_user_id, by_id=self.cohort.id ) by_project = self.cohort_service.get_users_by_project(c) # NOTE: generator magic, couldn't get this to work without a loop for p in by_project: wikiusers = list(p[1]) assert_equals(set(self.editor_user_ids), set(wikiusers)) assert_equals(len(wikiusers), 4) def test_get_wikiusers(self): users = self.cohort_service.get_wikiusers(self.fixed_cohort, self.session) assert_equals(users, self.editor_user_ids) def test_get_wikiusers_limited(self): users = self.cohort_service.get_wikiusers(self.fixed_cohort, self.session, 2) assert_equals(len(users), 2) def test_get_wikiusers_empty(self): users = self.cohort_service.get_wikiusers(self.empty_cohort, self.session) assert_equals(len(users), 0) def test_wiki_cohort_group_by_project_works(self): self.create_wiki_cohort() c = self.cohort_service.get( self.session, self.owner_user_id, by_id=self.basic_wiki_cohort.id ) users_by_project = list(self.cohort_service.get_users_by_project(c)) assert_equals(len(users_by_project), 1) assert_equals(users_by_project[0][0], mediawiki_project) assert_equals(users_by_project[0][1], None) def test_convert(self): cohort = self.cohort_service.convert(self.cohort) assert_true(issubclass(cohort.__class__, Cohort)) def test_add_wiki_cohort(self): dewiki1 = self.cohort_service.add_wiki_cohort(self.session, 'dewiki') assert_equals(dewiki1.name, 'dewiki') assert_equals(dewiki1.default_project, 'dewiki') assert_equals(type(dewiki1).__name__, 'WikiCohort') assert_equals(dewiki1.enabled, True) dewiki2 = self.cohort_service.add_wiki_cohort(self.session, 'dewiki') # make sure the cohort doesn't get added twice assert_equals(dewiki1.id, dewiki2.id) def test_share(self): cohorts = self.cohort_service.get_list(self.session, self.owner_user_id) assert_true('dewiki' not in [c.default_project for c in cohorts]) dewiki = self.cohort_service.add_wiki_cohort(self.session, 'dewiki') self.cohort_service.share(self.session, dewiki, self.owner_user_id) cohorts = self.cohort_service.get_list(self.session, self.owner_user_id) assert_true('dewiki' in [c.default_project for c in cohorts]) def test_wikiusernames_for_not_existing_cohort(self): """ If a cohort does not exist it returns an empty list of user names to make things easy for the UI """ user_names = self.cohort_service.get_wikiusernames_for_cohort('9999', self.session) assert_equals(len(user_names.keys()), 0) def test_wikiusernames(self): """ Make sure usernames can be retrieved using Wikiuserkey """ from wikimetrics.models.storage import ( WikiUserKey ) # let's get two users and see that names match # this returns a list of WikiUserStore objects users = self.cohort_service.get_wikiusers(self.fixed_cohort, self.session, 2) user1 = users[0] key1 = WikiUserKey(user1.mediawiki_userid, user1.project, user1.validating_cohort) user2 = users[1] key2 = WikiUserKey(user2.mediawiki_userid, user2.project, user2.validating_cohort) user_names = self.cohort_service.get_wikiusernames_for_cohort( self.fixed_cohort.id, self.session) assert_equals(user_names[key1], user1.mediawiki_username) assert_equals(user_names[key2], user2.mediawiki_username) def test_get_membership_contents(self): """ The wikiuser properties must be returned under the expected data structure. """ wikiusers = self.session.query(WikiUserStore).all() membership = self.cohort_service.get_membership(self.cohort, self.session) assert_equals(len(membership), len(wikiusers)) for i in range(len(membership)): wikiuser, member = wikiusers[i], membership[i] assert_equals(len(membership), 4) assert_equals(member['username'], wikiuser.mediawiki_username) assert_equals(len(member['projects']), 1) assert_equals(member['projects'][0], wikiuser.project) assert_equals(len(member['invalidProjects']), 0) assert_equals(len(member['invalidReasons']), 0) def test_get_membership_group_by_username(self): """ The wikiusers must be grouped by username, returning their projects, validities and reasons in the corresponding lists. """ wikiusers = self.session.query(WikiUserStore).all() username_1, username_2 = 'Username 1', 'Username 2' project_1, project_2 = 'Project 1', 'Project 2' reason_invalid_1 = 'Reason Invalid 1' wikiusers[0].raw_id_or_name = username_1 wikiusers[1].raw_id_or_name = username_1 wikiusers[2].raw_id_or_name = username_2 wikiusers[2].project = project_1 wikiusers[3].raw_id_or_name = username_2 wikiusers[3].project = project_2 wikiusers[3].valid = False wikiusers[3].reason_invalid = reason_invalid_1 self.session.commit() membership = self.cohort_service.get_membership(self.cohort, self.session) assert_equals(len(membership), 2) assert_equals(membership[0]['raw_id_or_name'], username_1) assert_equals(membership[1]['raw_id_or_name'], username_2) assert_equals(membership[1]['projects'], [project_1, project_2]) assert_equals(membership[1]['invalidProjects'], [project_2]) assert_equals(membership[1]['invalidReasons'], [reason_invalid_1]) def test_get_membership_order_by_name(self): wikiusers = self.session.query(WikiUserStore).all() wikiusers[0].mediawiki_username = '******' wikiusers[1].mediawiki_username = '******' wikiusers[2].mediawiki_username = '******' wikiusers[3].mediawiki_username = '******' self.session.commit() membership = self.cohort_service.get_membership(self.cohort, self.session) assert_equals(len(membership), len(wikiusers)) assert_equals(membership[0]['username'], 'A') assert_equals(membership[1]['username'], 'B') assert_equals(membership[2]['username'], 'C') assert_equals(membership[3]['username'], 'D') def test_delete_cohort_wikiuser(self): username = '******' wikiuser = self.session.query(WikiUserStore).first() wikiuser.raw_id_or_name = username self.session.commit() self.cohort_service.delete_cohort_wikiuser( wikiuser.raw_id_or_name, self.cohort.id, self.owner_user_id, self.session) wikiusers = ( self.session.query(WikiUserStore) .filter(WikiUserStore.raw_id_or_name == username) .filter(WikiUserStore.validating_cohort == self.cohort.id) .all()) assert_equals(len(wikiusers), 0) cohort_wikiusers = ( self.session.query(CohortWikiUserStore) .filter(CohortWikiUserStore.cohort_id == self.cohort.id) .filter(CohortWikiUserStore.wiki_user_id == wikiuser.id) .all()) assert_equals(len(cohort_wikiusers), 0) def test_delete_cohort_wikiuser_invalid_only(self): username = '******' wikiusers = self.session.query(WikiUserStore).all() wikiusers[0].raw_id_or_name = username wikiusers[1].raw_id_or_name = username wikiusers[1].valid = False wikiuser_ids = [wikiusers[0].id, wikiusers[1]] self.session.commit() self.cohort_service.delete_cohort_wikiuser( username, self.cohort.id, self.owner_user_id, self.session, True) wikiusers = ( self.session.query(WikiUserStore) .filter(WikiUserStore.raw_id_or_name == username) .filter(WikiUserStore.validating_cohort == self.cohort.id) .all()) assert_equals(len(wikiusers), 1) cohort_wikiusers = ( self.session.query(CohortWikiUserStore) .filter(CohortWikiUserStore.cohort_id == self.cohort.id) .filter(CohortWikiUserStore.wiki_user_id.in_(wikiuser_ids)) .all()) assert_equals(len(cohort_wikiusers), 1) def test_delete_cohort_wikiuser_utf8(self): username = '******' wikiuser = self.session.query(WikiUserStore).first() wikiuser.raw_id_or_name = username self.session.commit() self.cohort_service.delete_cohort_wikiuser( username, self.cohort.id, self.owner_user_id, self.session) wikiusers = ( self.session.query(WikiUserStore) .filter(WikiUserStore.raw_id_or_name == username) .filter(WikiUserStore.validating_cohort == self.cohort.id) .all()) assert_equals(len(wikiusers), 0) @raises(Unauthorized) def test_delete_cohort_wikiuser_ownership(self): self.cohort_service.delete_cohort_wikiuser( 'To Delete', self.cohort.id, self.owner_user_id + 1, self.session) def test_is_owned_by_user_positive(self): cohort_user = ( self.session.query(CohortUserStore) .filter(CohortUserStore.cohort_id == self.cohort.id) .one()) result = self.cohort_service.is_owned_by_user( self.session, self.cohort.id, cohort_user.user_id) assert_true(result) def test_is_owned_by_user_negative(self): cohort_user = ( self.session.query(CohortUserStore) .filter(CohortUserStore.cohort_id == self.cohort.id) .one()) result = self.cohort_service.is_owned_by_user( self.session, self.cohort.id, cohort_user.user_id + 1) assert_false(result) @raises(Unauthorized) def test_is_owned_by_user_exception(self): cohort_user = ( self.session.query(CohortUserStore) .filter(CohortUserStore.cohort_id == self.cohort.id) .one()) self.cohort_service.is_owned_by_user( self.session, self.cohort.id, cohort_user.user_id + 1, True) @raises(Unauthorized) def test_get_tag_exception(self): tag = TagStore(name='some_tag') self.session.add(tag) self.session.commit() cohort_tag = CohortTagStore( tag_id=tag.id, cohort_id=self.empty_cohort.id, ) self.session.add(cohort_tag) self.session.commit() cohort_user = ( self.session.query(CohortUserStore) .filter(CohortUserStore.cohort_id == self.empty_cohort.id) .one()) self.cohort_service.get_tag(self.session, tag, self.empty_cohort.id, cohort_user.user_id + 1) def test_get_tag(self): tag = TagStore(name='some_tag') self.session.add(tag) self.session.commit() cohort_tag = CohortTagStore( tag_id=tag.id, cohort_id=self.empty_cohort.id, ) self.session.add(cohort_tag) self.session.commit() cohort_user = ( self.session.query(CohortUserStore) .filter(CohortUserStore.cohort_id == self.empty_cohort.id) .one()) cohort_tags = self.cohort_service.get_tag( self.session, tag, self.empty_cohort.id, cohort_user.user_id) assert_equals(len(cohort_tags), 1) @raises(Unauthorized) def test_add_tag_exception(self): tag = TagStore(name='some_tag') self.session.add(tag) self.session.commit() cohort_user = ( self.session.query(CohortUserStore) .filter(CohortUserStore.cohort_id == self.empty_cohort.id) .one()) self.cohort_service.add_tag(self.session, tag, self.empty_cohort.id, cohort_user.user_id + 1) def test_add_tag(self): tag = TagStore(name='some_tag') self.session.add(tag) self.session.commit() cohort_user = ( self.session.query(CohortUserStore) .filter(CohortUserStore.cohort_id == self.empty_cohort.id) .one()) cohort_tags = self.cohort_service.get_tag( self.session, tag, self.empty_cohort.id, cohort_user.user_id) assert_equals(len(cohort_tags), 0) self.cohort_service.add_tag( self.session, tag, self.empty_cohort.id, cohort_user.user_id) cohort_tags = self.cohort_service.get_tag( self.session, tag, self.empty_cohort.id, cohort_user.user_id) assert_equals(len(cohort_tags), 1)
def __init__(self, parameters, user_id=0, recurrent_parent_id=None, created=None, persistent_id=None): """ Parameters: parameters : dictionary containing the following required keys: name : the name of the report cohort : dictionary defining the cohort, has keys: id : the id of the cohort metric : dictionary defining the metric, has keys: name : the name of the python class to instantiate recurrent : whether to rerun this daily public : whether to expose results publicly user_id : the user wishing to run this report recurrent_parent_id : the parent ReportStore.id for a recurrent run created : if set, represents the date of a recurrent run. This need not be the timestamp when the recurrent run has been created -- for example when backfilling. Hence, this does not fully match the semantics of the word 'created'. But since neither start nor end date have a separate column in the report table in the database, the covered period for backfilled recurring reports would be hard to identify when only looking at the raw database tables. To overcome this issue, we abuse the created date here. Raises: KeyError if required parameters are missing """ # get cohort cohort_service = CohortService() cohort_dict = parameters['cohort'] session = db.get_session() cohort = cohort_service.get(session, user_id, by_id=cohort_dict['id']) parameters['cohort']['size'] = cohort.size # construct metric metric_dict = parameters['metric'] metric = metric_classes[metric_dict['name']](**metric_dict) # if this is a recurrent run, don't show it in the UI if recurrent_parent_id is not None: self.show_in_ui = False public = parameters.get('public', False) recurrent = parameters.get('recurrent', False) super(RunReport, self).__init__(name=parameters['name'], user_id=user_id, parameters=parameters, public=public, recurrent=recurrent, recurrent_parent_id=recurrent_parent_id, created=created, store=True, persistent_id=persistent_id) self.recurrent_parent_id = recurrent_parent_id self.public = public validate_report = ValidateReport(metric, cohort, recurrent_parent_id is None, user_id=user_id) if validate_report.valid(): if recurrent and recurrent_parent_id is None: # Valid parent recurrent report # We do not add children that compute data as parent recurrent # reports just help the scheduler orchestrate child runs. # However, we employ a NullReport to allow coalescing even # when there was no recurrent run yet. self.children = [NullReport()] else: # Valid, but not a parent recurring report, so we add the child # node that does the real computation self.children = [ AggregateReport(metric, cohort, metric_dict, parameters=parameters, user_id=user_id) ] else: self.children = [validate_report]
class CohortServiceTest(DatabaseTest): def setUp(self): """ NOTE: self.cohort is a CohortStore object. When testing CohortService, one should use logical cohort objects (ie. FixedCohort, WikiCohort, etc.) """ DatabaseTest.setUp(self) self.common_cohort_1() self.editor_user_ids = [e.user_id for e in self.editors] self.cohort_service = CohortService() empty_cohort = CohortStore(enabled=True, class_name='Cohort') self.session.add(empty_cohort) self.session.commit() empty_cohort_user = CohortUserStore( user_id=self.owner_user_id, cohort_id=empty_cohort.id, role=CohortUserRole.OWNER, ) self.session.add(empty_cohort_user) self.session.commit() self.invalid_empty_cohort = CohortStore(enabled=True, class_name='FixedCohort', validated=True) self.session.add(self.invalid_empty_cohort) self.session.commit() invalid_empty_cohort_user = CohortUserStore( user_id=self.owner_user_id, cohort_id=self.invalid_empty_cohort.id, role=CohortUserRole.OWNER, ) self.session.add(invalid_empty_cohort_user) self.session.commit() self.empty_cohort = self.cohort_service.get(self.session, self.owner_user_id, by_id=empty_cohort.id) self.fixed_cohort = self.cohort_service.get(self.session, self.owner_user_id, by_id=self.cohort.id) def test_get(self): assert_equals(self.fixed_cohort.name, self.cohort.name) def test_get_by_name(self): c = self.cohort_service.get(self.session, self.owner_user_id, by_name=self.cohort.name) assert_equals(c.name, self.cohort.name) def test_get_empty(self): assert_equals(self.empty_cohort.name, None) @raises(NoResultFound) def test_get_raises_exception_for_not_found_by_id(self): self.cohort_service.get(self.session, self.owner_user_id, by_id=0) @raises(NoResultFound) def test_get_raises_exception_for_not_found_by_name(self): self.cohort_service.get(self.session, self.owner_user_id, by_name='') @raises(Unauthorized) def test_get_unauthorized(self): self.cohort_service.get(self.session, 0, by_id=self.cohort.id) @raises(InvalidCohort) def test_get_invalid(self): self.cohort.validated = False self.session.commit() self.cohort_service.get(self.session, self.owner_user_id, by_id=self.cohort.id) @raises(InvalidCohort) def test_get_invalid_because_empty(self): self.cohort_service.get(self.session, self.owner_user_id, by_id=self.invalid_empty_cohort.id) def test_get_size(self): assert_equals(self.fixed_cohort.size, 4) def test_get_size_empty(self): assert_equals(self.empty_cohort.size, 0) def test_get_users_by_project(self): c = self.cohort_service.get(self.session, self.owner_user_id, by_id=self.cohort.id) by_project = self.cohort_service.get_users_by_project(c) # NOTE: generator magic, couldn't get this to work without a loop for p in by_project: wikiusers = list(p[1]) assert_equals(set(self.editor_user_ids), set(wikiusers)) assert_equals(len(wikiusers), 4) def test_get_wikiusers(self): users = self.cohort_service.get_wikiusers(self.fixed_cohort, self.session) assert_equals(users, self.editor_user_ids) def test_get_wikiusers_limited(self): users = self.cohort_service.get_wikiusers(self.fixed_cohort, self.session, 2) assert_equals(len(users), 2) def test_get_wikiusers_empty(self): users = self.cohort_service.get_wikiusers(self.empty_cohort, self.session) assert_equals(len(users), 0) def test_wiki_cohort_group_by_project_works(self): self.create_wiki_cohort() c = self.cohort_service.get(self.session, self.owner_user_id, by_id=self.basic_wiki_cohort.id) users_by_project = list(self.cohort_service.get_users_by_project(c)) assert_equals(len(users_by_project), 1) assert_equals(users_by_project[0][0], mediawiki_project) assert_equals(users_by_project[0][1], None) def test_convert(self): cohort = self.cohort_service.convert(self.cohort) assert_true(issubclass(cohort.__class__, Cohort)) def test_add_wiki_cohort(self): dewiki1 = self.cohort_service.add_wiki_cohort(self.session, 'dewiki') assert_equals(dewiki1.name, 'dewiki') assert_equals(dewiki1.default_project, 'dewiki') assert_equals(type(dewiki1).__name__, 'WikiCohort') assert_equals(dewiki1.enabled, True) dewiki2 = self.cohort_service.add_wiki_cohort(self.session, 'dewiki') # make sure the cohort doesn't get added twice assert_equals(dewiki1.id, dewiki2.id) def test_share(self): cohorts = self.cohort_service.get_list(self.session, self.owner_user_id) assert_true('dewiki' not in [c.default_project for c in cohorts]) dewiki = self.cohort_service.add_wiki_cohort(self.session, 'dewiki') self.cohort_service.share(self.session, dewiki, self.owner_user_id) cohorts = self.cohort_service.get_list(self.session, self.owner_user_id) assert_true('dewiki' in [c.default_project for c in cohorts]) def test_wikiusernames_for_not_existing_cohort(self): """ If a cohort does not exist it returns an empty list of user names to make things easy for the UI """ user_names = self.cohort_service.get_wikiusernames_for_cohort( '9999', self.session) assert_equals(len(user_names.keys()), 0) def test_wikiusernames(self): """ Make sure usernames can be retrieved using Wikiuserkey """ from wikimetrics.models.storage import (WikiUserKey) # let's get two users and see that names match # this returns a list of WikiUserStore objects users = self.cohort_service.get_wikiusers(self.fixed_cohort, self.session, 2) user1 = users[0] key1 = WikiUserKey(user1.mediawiki_userid, user1.project, user1.validating_cohort) user2 = users[1] key2 = WikiUserKey(user2.mediawiki_userid, user2.project, user2.validating_cohort) user_names = self.cohort_service.get_wikiusernames_for_cohort( self.fixed_cohort.id, self.session) assert_equals(user_names[key1], user1.mediawiki_username) assert_equals(user_names[key2], user2.mediawiki_username) def test_get_membership_contents(self): """ The wikiuser properties must be returned under the expected data structure. """ wikiusers = self.session.query(WikiUserStore).all() membership = self.cohort_service.get_membership( self.cohort, self.session) assert_equals(len(membership), len(wikiusers)) for i in range(len(membership)): wikiuser, member = wikiusers[i], membership[i] assert_equals(len(membership), 4) assert_equals(member['username'], wikiuser.mediawiki_username) assert_equals(len(member['projects']), 1) assert_equals(member['projects'][0], wikiuser.project) assert_equals(len(member['invalidProjects']), 0) assert_equals(len(member['invalidReasons']), 0) def test_get_membership_group_by_username(self): """ The wikiusers must be grouped by username, returning their projects, validities and reasons in the corresponding lists. """ wikiusers = self.session.query(WikiUserStore).all() username_1, username_2 = 'Username 1', 'Username 2' project_1, project_2 = 'Project 1', 'Project 2' reason_invalid_1 = 'Reason Invalid 1' wikiusers[0].raw_id_or_name = username_1 wikiusers[1].raw_id_or_name = username_1 wikiusers[2].raw_id_or_name = username_2 wikiusers[2].project = project_1 wikiusers[3].raw_id_or_name = username_2 wikiusers[3].project = project_2 wikiusers[3].valid = False wikiusers[3].reason_invalid = reason_invalid_1 self.session.commit() membership = self.cohort_service.get_membership( self.cohort, self.session) assert_equals(len(membership), 2) assert_equals(membership[0]['raw_id_or_name'], username_1) assert_equals(membership[1]['raw_id_or_name'], username_2) assert_equals(membership[1]['projects'], [project_1, project_2]) assert_equals(membership[1]['invalidProjects'], [project_2]) assert_equals(membership[1]['invalidReasons'], [reason_invalid_1]) def test_get_membership_order_by_name(self): wikiusers = self.session.query(WikiUserStore).all() wikiusers[0].mediawiki_username = '******' wikiusers[1].mediawiki_username = '******' wikiusers[2].mediawiki_username = '******' wikiusers[3].mediawiki_username = '******' self.session.commit() membership = self.cohort_service.get_membership( self.cohort, self.session) assert_equals(len(membership), len(wikiusers)) assert_equals(membership[0]['username'], 'A') assert_equals(membership[1]['username'], 'B') assert_equals(membership[2]['username'], 'C') assert_equals(membership[3]['username'], 'D') def test_delete_cohort_wikiuser(self): username = '******' wikiuser = self.session.query(WikiUserStore).first() wikiuser.raw_id_or_name = username self.session.commit() self.cohort_service.delete_cohort_wikiuser(wikiuser.raw_id_or_name, self.cohort.id, self.owner_user_id, self.session) wikiusers = (self.session.query(WikiUserStore).filter( WikiUserStore.raw_id_or_name == username).filter( WikiUserStore.validating_cohort == self.cohort.id).all()) assert_equals(len(wikiusers), 0) cohort_wikiusers = (self.session.query(CohortWikiUserStore).filter( CohortWikiUserStore.cohort_id == self.cohort.id).filter( CohortWikiUserStore.wiki_user_id == wikiuser.id).all()) assert_equals(len(cohort_wikiusers), 0) def test_delete_cohort_wikiuser_invalid_only(self): username = '******' wikiusers = self.session.query(WikiUserStore).all() wikiusers[0].raw_id_or_name = username wikiusers[1].raw_id_or_name = username wikiusers[1].valid = False wikiuser_ids = [wikiusers[0].id, wikiusers[1]] self.session.commit() self.cohort_service.delete_cohort_wikiuser(username, self.cohort.id, self.owner_user_id, self.session, True) wikiusers = (self.session.query(WikiUserStore).filter( WikiUserStore.raw_id_or_name == username).filter( WikiUserStore.validating_cohort == self.cohort.id).all()) assert_equals(len(wikiusers), 1) cohort_wikiusers = (self.session.query(CohortWikiUserStore).filter( CohortWikiUserStore.cohort_id == self.cohort.id).filter( CohortWikiUserStore.wiki_user_id.in_(wikiuser_ids)).all()) assert_equals(len(cohort_wikiusers), 1) def test_delete_cohort_wikiuser_utf8(self): username = '******' wikiuser = self.session.query(WikiUserStore).first() wikiuser.raw_id_or_name = username self.session.commit() self.cohort_service.delete_cohort_wikiuser(username, self.cohort.id, self.owner_user_id, self.session) wikiusers = (self.session.query(WikiUserStore).filter( WikiUserStore.raw_id_or_name == username).filter( WikiUserStore.validating_cohort == self.cohort.id).all()) assert_equals(len(wikiusers), 0) @raises(Unauthorized) def test_delete_cohort_wikiuser_ownership(self): self.cohort_service.delete_cohort_wikiuser('To Delete', self.cohort.id, self.owner_user_id + 1, self.session) def test_is_owned_by_user_positive(self): cohort_user = (self.session.query(CohortUserStore).filter( CohortUserStore.cohort_id == self.cohort.id).one()) result = self.cohort_service.is_owned_by_user(self.session, self.cohort.id, cohort_user.user_id) assert_true(result) def test_is_owned_by_user_negative(self): cohort_user = (self.session.query(CohortUserStore).filter( CohortUserStore.cohort_id == self.cohort.id).one()) result = self.cohort_service.is_owned_by_user(self.session, self.cohort.id, cohort_user.user_id + 1) assert_false(result) @raises(Unauthorized) def test_is_owned_by_user_exception(self): cohort_user = (self.session.query(CohortUserStore).filter( CohortUserStore.cohort_id == self.cohort.id).one()) self.cohort_service.is_owned_by_user(self.session, self.cohort.id, cohort_user.user_id + 1, True) @raises(Unauthorized) def test_get_tag_exception(self): tag = TagStore(name='some_tag') self.session.add(tag) self.session.commit() cohort_tag = CohortTagStore( tag_id=tag.id, cohort_id=self.empty_cohort.id, ) self.session.add(cohort_tag) self.session.commit() cohort_user = (self.session.query(CohortUserStore).filter( CohortUserStore.cohort_id == self.empty_cohort.id).one()) self.cohort_service.get_tag(self.session, tag, self.empty_cohort.id, cohort_user.user_id + 1) def test_get_tag(self): tag = TagStore(name='some_tag') self.session.add(tag) self.session.commit() cohort_tag = CohortTagStore( tag_id=tag.id, cohort_id=self.empty_cohort.id, ) self.session.add(cohort_tag) self.session.commit() cohort_user = (self.session.query(CohortUserStore).filter( CohortUserStore.cohort_id == self.empty_cohort.id).one()) cohort_tags = self.cohort_service.get_tag(self.session, tag, self.empty_cohort.id, cohort_user.user_id) assert_equals(len(cohort_tags), 1) @raises(Unauthorized) def test_add_tag_exception(self): tag = TagStore(name='some_tag') self.session.add(tag) self.session.commit() cohort_user = (self.session.query(CohortUserStore).filter( CohortUserStore.cohort_id == self.empty_cohort.id).one()) self.cohort_service.add_tag(self.session, tag, self.empty_cohort.id, cohort_user.user_id + 1) def test_add_tag(self): tag = TagStore(name='some_tag') self.session.add(tag) self.session.commit() cohort_user = (self.session.query(CohortUserStore).filter( CohortUserStore.cohort_id == self.empty_cohort.id).one()) cohort_tags = self.cohort_service.get_tag(self.session, tag, self.empty_cohort.id, cohort_user.user_id) assert_equals(len(cohort_tags), 0) self.cohort_service.add_tag(self.session, tag, self.empty_cohort.id, cohort_user.user_id) cohort_tags = self.cohort_service.get_tag(self.session, tag, self.empty_cohort.id, cohort_user.user_id) assert_equals(len(cohort_tags), 1)
def setUp(self): WebTest.setUp(self) self.cohort_service = CohortService()
def __init__(self, parameters, user_id=0, recurrent_parent_id=None, created=None): """ Parameters: parameters : dictionary containing the following required keys: name : the name of the report cohort : dictionary defining the cohort, has keys: id : the id of the cohort metric : dictionary defining the metric, has keys: name : the name of the python class to instantiate recurrent : whether to rerun this daily public : whether to expose results publicly user_id : the user wishing to run this report recurrent_parent_id : the parent ReportStore.id for a recurrent run created : if set, represents the date of a recurrent run Raises: KeyError if required parameters are missing """ # get cohort cohort_service = CohortService() cohort_dict = parameters['cohort'] session = db.get_session() try: cohort = cohort_service.get(session, user_id, by_id=cohort_dict['id']) finally: session.close() parameters['cohort']['size'] = cohort.size # construct metric metric_dict = parameters['metric'] metric = metric_classes[metric_dict['name']](**metric_dict) # if this is a recurrent run, don't show it in the UI if recurrent_parent_id is not None: self.show_in_ui = False public = parameters.get('public', False) super(RunReport, self).__init__( name=parameters['name'], user_id=user_id, parameters=parameters, public=public, recurrent=parameters.get('recurrent', False), recurrent_parent_id=recurrent_parent_id, created=created, ) self.recurrent_parent_id = recurrent_parent_id self.public = public validate_report = ValidateReport( metric, cohort, recurrent_parent_id is None, user_id=user_id ) if validate_report.valid(): self.children = [AggregateReport( metric, cohort, metric_dict, parameters=parameters, user_id=user_id )] else: self.children = [validate_report]
from nose.tools import assert_equals, raises, assert_true, assert_is_not_none from tests.fixtures import QueueDatabaseTest, d from wikimetrics.models import RunProgramMetricsReport, ReportStore, WikiUserStore from wikimetrics.utils import parse_pretty_date, format_pretty_date from wikimetrics.enums import Aggregation from wikimetrics.api import CohortService cohort_service = CohortService() def make_pending(report): report.status = 'PENDING' class RunProgramMetricsReportWithInvalidCohort(QueueDatabaseTest): def setUp(self): QueueDatabaseTest.setUp(self) self.common_cohort_1() @raises(Exception) def test_raises_unvalidated_cohort(self): self.cohort.validated = False jr = RunProgramMetricsReport(self.cohort.id, parse_pretty_date('2015-01-01 00:00:00'), parse_pretty_date('2015-01-31 00:00:00'), self.owner_user_id) jr.task.delay(jr).get() def test_invalid_cohort_returns_failure(self): self.cohort.validated = True