Beispiel #1
0
    def test_get_autoassign_owners_when_codeowners_and_issueowners_exists(self):
        self.team = self.create_team(
            organization=self.organization, slug="tiger-team", members=[self.user]
        )
        self.team2 = self.create_team(
            organization=self.organization, slug="dolphin-team", members=[self.user]
        )
        self.project = self.create_project(
            organization=self.organization, teams=[self.team, self.team2]
        )
        self.code_mapping = self.create_code_mapping(project=self.project)

        rule_a = Rule(Matcher("path", "*.py"), [Owner("team", self.team.slug)])
        rule_b = Rule(Matcher("path", "src/*"), [Owner("user", self.user.email)])
        rule_c = Rule(Matcher("path", "*.py"), [Owner("team", self.team2.slug)])

        ProjectOwnership.objects.create(
            project_id=self.project.id, schema=dump_schema([rule_a, rule_b]), fallthrough=True
        )

        self.create_codeowners(
            self.project, self.code_mapping, raw="*.py @tiger-team", schema=dump_schema([rule_c])
        )

        # No autoassignment on match
        assert ProjectOwnership.get_autoassign_owners(
            self.project.id, {"stacktrace": {"frames": [{"filename": "api/foo.py"}]}}
        ) == (False, [self.team, self.team2], False)
        # autoassignment is True
        owner = ProjectOwnership.objects.get(project_id=self.project.id)
        owner.auto_assignment = True
        owner.save()

        assert ProjectOwnership.get_autoassign_owners(
            self.project.id, {"stacktrace": {"frames": [{"filename": "api/foo.py"}]}}
        ) == (True, [self.team, self.team2], False)

        # # more than 2 matches
        assert ProjectOwnership.get_autoassign_owners(
            self.project.id, {"stacktrace": {"frames": [{"filename": "src/foo.py"}]}}
        ) == (True, [self.user, self.team], False)
Beispiel #2
0
    def setUp(self):
        from sentry.ownership.grammar import Rule

        self.user = self.create_user(email="*****@*****.**", is_active=True)
        self.user2 = self.create_user(email="*****@*****.**", is_active=True)

        self.organization = self.create_organization(owner=self.user)
        self.team = self.create_team(organization=self.organization)

        self.project = self.create_project(name="Test", teams=[self.team])
        OrganizationMemberTeam.objects.create(
            organizationmember=OrganizationMember.objects.get(
                user=self.user, organization=self.organization),
            team=self.team,
        )
        self.create_member(user=self.user2,
                           organization=self.organization,
                           teams=[self.team])
        self.group = self.create_group(
            first_seen=timezone.now(),
            last_seen=timezone.now(),
            project=self.project,
            message="hello  world",
            logger="root",
        )
        ProjectOwnership.objects.create(
            project_id=self.project.id,
            schema=dump_schema([
                Rule(Matcher("path", "*.py"), [Owner("team", self.team.slug)]),
                Rule(Matcher("path", "*.jx"),
                     [Owner("user", self.user2.email)]),
                Rule(
                    Matcher("path", "*.cbl"),
                    [
                        Owner("user", self.user.email),
                        Owner("user", self.user2.email)
                    ],
                ),
            ]),
            fallthrough=True,
        )
Beispiel #3
0
def test_load_schema():
    assert load_schema(
        {
            "$version": 1,
            "rules": [
                {
                    "matcher": {"type": "path", "pattern": "*.js"},
                    "owners": [{"type": "team", "identifier": "frontend"}],
                }
            ],
        }
    ) == [Rule(Matcher("path", "*.js"), [Owner("team", "frontend")])]
Beispiel #4
0
def test_parse_rules():
    assert parse_rules(fixture_data) == [
        Rule(Matcher("path", "*.js"), [Owner("team", "frontend"), Owner("user", "*****@*****.**")]),
        Rule(Matcher("url", "http://google.com/*"), [Owner("team", "backend")]),
        Rule(Matcher("path", "src/sentry/*"), [Owner("user", "*****@*****.**")]),
        Rule(Matcher("tags.foo", "bar"), [Owner("user", "*****@*****.**")]),
        Rule(Matcher("tags.foo", "bar baz"), [Owner("user", "*****@*****.**")]),
        Rule(Matcher("module", "foo.bar"), [Owner("team", "workflow")]),
        Rule(Matcher("module", "foo bar"), [Owner("user", "*****@*****.**")]),
    ]
Beispiel #5
0
    def setUp(self):
        from sentry.ownership.grammar import Rule
        self.user = self.create_user(email='*****@*****.**', is_active=True)
        self.user2 = self.create_user(email='*****@*****.**', is_active=True)

        self.organization = self.create_organization(owner=self.user)
        self.team = self.create_team(organization=self.organization)

        self.project = self.create_project(name='Test', teams=[self.team])
        OrganizationMemberTeam.objects.create(
            organizationmember=OrganizationMember.objects.get(
                user=self.user,
                organization=self.organization,
            ),
            team=self.team,
        )
        self.create_member(user=self.user2, organization=self.organization, teams=[self.team])
        self.group = self.create_group(
            first_seen=timezone.now(),
            last_seen=timezone.now(),
            project=self.project,
            message='hello  world',
            logger='root',
        )
        ProjectOwnership.objects.create(
            project_id=self.project.id,
            schema=dump_schema([
                Rule(Matcher('path', '*.py'), [
                    Owner('team', self.team.slug),
                ]),
                Rule(Matcher('path', '*.jx'), [
                    Owner('user', self.user2.email),
                ]),
                Rule(Matcher('path', '*.cbl'), [
                    Owner('user', self.user.email),
                    Owner('user', self.user2.email),
                ])
            ]),
            fallthrough=True,
        )
Beispiel #6
0
    def test_owner_assignment_when_owners_have_been_unassigned(self):
        """
        Test that ensures that if certain assignees get unassigned, and project rules are changed
        then the new group assignees should be re-calculated and re-assigned
        """
        # Create rules and check assignees
        self.make_ownership()
        event = self.store_event(
            data={
                "message": "oh no",
                "platform": "python",
                "stacktrace": {"frames": [{"filename": "src/app/example.py"}]},
            },
            project_id=self.project.id,
        )
        cache_key = write_event_to_cache(event)
        post_process_group(
            is_new=False,
            is_regression=False,
            is_new_group_environment=False,
            cache_key=cache_key,
            group_id=event.group_id,
        )
        assignee = event.group.assignee_set.first()
        assert assignee.user == self.user

        user_3 = self.create_user()
        self.create_team_membership(self.team, user=user_3)

        # De-assign group assignees
        GroupAssignee.objects.deassign(event.group, self.user)
        assert event.group.assignee_set.first() is None

        # Change ProjectOwnership rules
        rules = [
            Rule(Matcher("path", "src/*"), [Owner("user", user_3.email)]),
        ]
        self.prj_ownership.schema = dump_schema(rules)
        self.prj_ownership.save()

        cache_key = write_event_to_cache(event)
        post_process_group(
            is_new=False,
            is_regression=False,
            is_new_group_environment=False,
            cache_key=cache_key,
            group_id=event.group_id,
        )

        # Group should be re-assigned to the new group owner
        assignee = event.group.assignee_set.first()
        assert assignee.user == user_3
Beispiel #7
0
 def setUp(self):
     self.user2 = self.create_user(email="*****@*****.**", is_active=True)
     self.create_member(user=self.user2,
                        organization=self.organization,
                        teams=[self.team])
     ProjectOwnership.objects.create(
         project_id=self.project.id,
         schema=dump_schema([
             grammar.Rule(Matcher("path", "*.py"),
                          [Owner("team", self.team.slug)]),
             grammar.Rule(Matcher("path", "*.jx"),
                          [Owner("user", self.user2.email)]),
             grammar.Rule(
                 Matcher("path", "*.cbl"),
                 [
                     Owner("user", self.user.email),
                     Owner("user", self.user2.email)
                 ],
             ),
         ]),
         fallthrough=True,
     )
 def test_abs_path_when_filename_present(self):
     frame = {
         "filename": "computer.cpp",
         "abs_path": "C:\\My\\Path\\computer.cpp",
     }
     rule = Rule(Matcher("path", "*My\\Path*"),
                 [Owner("team", self.team.slug)])
     ProjectOwnership.objects.create(project_id=self.project.id,
                                     schema=dump_schema([rule]),
                                     fallthrough=True)
     assert ProjectOwnership.get_owners(
         self.project.id, {"stacktrace": {
             "frames": [frame]
         }}) == ([ActorTuple(self.team.id, Team)], [rule])
Beispiel #9
0
    def test_multiple_owners_order_matters(self):
        users = [self.user, self.user2, self.user3]
        rules = [
            Rule(Matcher("path", "*.py"), [Owner("user", users[0].email)]),
            Rule(Matcher("path", "*foo*"), [Owner("user", users[1].email)]),
            Rule(Matcher("path", "*"), [Owner("user", users[2].email)]),
        ]
        rules.reverse()

        ProjectOwnership.objects.create(project_id=self.project.id,
                                        schema=dump_schema(rules),
                                        fallthrough=True)

        event1 = self.store_event(
            data={"stacktrace": {
                "frames": [{
                    "filename": "foo.py"
                }]
            }},
            project_id=self.project.id)

        self.path = reverse(
            "sentry-api-0-event-owners",
            kwargs={
                "organization_slug": self.organization.slug,
                "project_slug": self.project.slug,
                "event_id": event1.event_id,
            },
        )

        resp = self.client.get(self.path)
        assert resp.status_code == 200
        assert len(resp.data["owners"]) == 3
        assert [o["id"] for o in resp.data["owners"]
                ] == [six.text_type(u.id) for u in reversed(users)]
        assert resp.data["rule"] == Matcher("path", "*")
        assert len(resp.data["rules"]) == 3
Beispiel #10
0
    def setUp(self):
        self.user = self.create_user(email="*****@*****.**", is_active=True)
        self.user2 = self.create_user(email="*****@*****.**", is_active=True)
        self.user3 = self.create_user(email="*****@*****.**", is_active=True)

        self.organization = self.create_organization(owner=self.user)
        self.team = self.create_team(organization=self.organization,
                                     members=[self.user2, self.user3])
        self.team2 = self.create_team(organization=self.organization,
                                      members=[self.user])
        self.project = self.create_project(name="Test",
                                           teams=[self.team, self.team2])
        self.group = self.create_group(
            first_seen=timezone.now(),
            last_seen=timezone.now(),
            project=self.project,
            message="hello  world",
            logger="root",
        )
        ProjectOwnership.objects.create(
            project_id=self.project.id,
            schema=dump_schema([
                grammar.Rule(Matcher("path", "*.py"),
                             [Owner("team", self.team.slug)]),
                grammar.Rule(Matcher("path", "*.jx"),
                             [Owner("user", self.user2.email)]),
                grammar.Rule(
                    Matcher("path", "*.cbl"),
                    [
                        Owner("user", self.user.email),
                        Owner("user", self.user2.email),
                        Owner("user", self.user3.email),
                    ],
                ),
            ]),
            fallthrough=True,
        )
def test_matcher_test_url():
    data = {"request": {"url": "http://example.com/foo.js"}}

    assert Matcher("url", "*.js").test(data)
    assert Matcher("url", "http://*.com/foo.js").test(data)
    assert not Matcher("url", "*.py").test(data)
    assert not Matcher("url", "*.jsx").test(data)
    assert not Matcher("path", "*.js").test(data)
    assert not Matcher("url", "*.js").test({})
Beispiel #12
0
def test_load_schema():
    assert load_schema({
        '$version':
        1,
        'rules': [{
            'matcher': {
                'type': 'path',
                'pattern': '*.js',
            },
            'owners': [{
                'type': 'team',
                'identifier': 'frontend',
            }]
        }]
    }) == [Rule(Matcher('path', '*.js'), [Owner('team', 'frontend')])]
Beispiel #13
0
def test_matcher_test_stacktrace():
    data = {
        "stacktrace": {
            "frames": [{"filename": "foo/file.py"}, {"abs_path": "/usr/local/src/other/app.py"}]
        }
    }

    assert Matcher("path", "*.py").test(data)
    assert Matcher("path", "foo/*.py").test(data)
    assert Matcher("path", "/usr/local/src/*/app.py").test(data)
    assert not Matcher("path", "*.js").test(data)
    assert not Matcher("path", "*.jsx").test(data)
    assert not Matcher("url", "*.py").test(data)
    assert not Matcher("path", "*.py").test({})
Beispiel #14
0
    def test_get_owners_basic(self):
        matcher = Matcher('path', '*.py')

        ProjectOwnership.objects.create(
            project_id=self.project.id,
            schema=dump_schema([
                Rule(matcher, [
                    Owner('user', self.user.email),
                    Owner('team', self.team.slug),
                ]),
            ]),
            fallthrough=True,
        )

        # No data matches
        assert ProjectOwnership.get_owners(self.project.id,
                                           {}) == (ProjectOwnership.Everyone,
                                                   None)

        assert ProjectOwnership.get_owners(self.project.id, {
            'sentry.interfaces.Stacktrace': {
                'frames': [{
                    'filename': 'foo.py',
                }]
            }
        }) == ([Actor(self.user.id, User),
                Actor(self.team.id, Team)], matcher)

        assert ProjectOwnership.get_owners(self.project.id, {
            'sentry.interfaces.Stacktrace': {
                'frames': [{
                    'filename': 'xxxx',
                }]
            }
        }) == (ProjectOwnership.Everyone, None)

        # When fallthrough = False, we don't implicitly assign to Everyone
        ProjectOwnership.objects.filter(
            project_id=self.project.id, ).update(fallthrough=False)

        assert ProjectOwnership.get_owners(self.project.id, {
            'sentry.interfaces.Stacktrace': {
                'frames': [{
                    'filename': 'xxxx',
                }]
            }
        }) == ([], None)
Beispiel #15
0
    def test_owner_assignment_existing_owners(self):
        with self.feature("projects:workflow-owners-ingestion"):
            extra_user = self.create_user()
            self.create_team_membership(self.team, user=extra_user)
            self.make_ownership([
                Rule(Matcher("path", "src/app/things/in/*"),
                     [Owner("user", extra_user.email)])
            ], )
            GroupOwner.objects.create(
                group=self.group,
                project=self.project,
                organization=self.organization,
                user=self.user,
                type=GroupOwnerType.OWNERSHIP_RULE.value,
            )
            event = self.store_event(
                data={
                    "message": "oh no",
                    "platform": "python",
                    "stacktrace": {
                        "frames": [{
                            "filename":
                            "src/app/things/in/a/path/example2.py"
                        }]
                    },
                },
                project_id=self.project.id,
            )
            cache_key = write_event_to_cache(event)
            post_process_group(
                is_new=False,
                is_regression=False,
                is_new_group_environment=False,
                cache_key=cache_key,
                group_id=event.group_id,
            )
            assignee = event.group.assignee_set.first()
            assert assignee.user == extra_user
            assert assignee.team is None

            owners = list(GroupOwner.objects.filter(group=event.group))
            assert len(owners) == 2
            assert set([(extra_user.id, None),
                        (None, self.team.id)]) == {(o.user_id, o.team_id)
                                                   for o in owners}
def test_matcher_test_url():
    data = {
        'request': {
            'url': 'http://example.com/foo.js',
        }
    }

    assert Matcher('url', '*.js').test(data)
    assert Matcher('url', 'http://*.com/foo.js').test(data)
    assert not Matcher('url', '*.py').test(data)
    assert not Matcher('url', '*.jsx').test(data)
    assert not Matcher('path', '*.js').test(data)
    assert not Matcher('url', '*.js').test({})
Beispiel #17
0
    def test_owner_assignment_existing_owners(self):
        extra_team = self.create_team()
        ProjectTeam.objects.create(team=extra_team, project=self.project)

        self.make_ownership([
            Rule(Matcher("path", "src/app/things/in/*"),
                 [Owner("team", extra_team.slug)])
        ], )
        GroupOwner.objects.create(
            group=self.group,
            project=self.project,
            organization=self.organization,
            user=self.user,
            type=GroupOwnerType.OWNERSHIP_RULE.value,
        )
        event = self.store_event(
            data={
                "message": "oh no",
                "platform": "python",
                "stacktrace": {
                    "frames": [{
                        "filename":
                        "src/app/things/in/a/path/example2.py"
                    }]
                },
            },
            project_id=self.project.id,
        )
        cache_key = write_event_to_cache(event)
        post_process_group(
            is_new=False,
            is_regression=False,
            is_new_group_environment=False,
            cache_key=cache_key,
            group_id=event.group_id,
        )
        assignee = event.group.assignee_set.first()
        assert assignee.user is None
        assert assignee.team == extra_team

        owners = list(GroupOwner.objects.filter(group=event.group))
        assert {(None, extra_team.id),
                (self.user.id, None)} == {(o.user_id, o.team_id)
                                          for o in owners}
Beispiel #18
0
def test_matcher_test_url():
    data = {
        'sentry.interfaces.Http': {
            'url': 'http://example.com/foo.js',
        }
    }

    assert Matcher('url', '*.js').test(data)
    assert Matcher('url', 'http://*.com/foo.js').test(data)
    assert not Matcher('url', '*.py').test(data)
    assert not Matcher('url', '*.jsx').test(data)
    assert not Matcher('path', '*.js').test(data)
    assert not Matcher('url', '*.js').test({})
def test_matcher_test_stacktrace():
    data = {
        'sentry.interfaces.Stacktrace': {
            'frames': [
                {'filename': 'foo/file.py'},
                {'abs_path': '/usr/local/src/other/app.py'},
            ],
        }
    }

    assert Matcher('path', '*.py').test(data)
    assert Matcher('path', 'foo/*.py').test(data)
    assert Matcher('path', '/usr/local/src/*/app.py').test(data)
    assert not Matcher('path', '*.js').test(data)
    assert not Matcher('path', '*.jsx').test(data)
    assert not Matcher('url', '*.py').test(data)
    assert not Matcher('path', '*.py').test({})
Beispiel #20
0
 def test_team_without_members(self):
     team = self.create_team()
     project = self.create_project(teams=[team], fire_project_created=True)
     ProjectOwnership.objects.create(
         project_id=project.id,
         schema=dump_schema([Rule(Matcher("path", "*.cpp"), [Owner("team", team.slug)])]),
         fallthrough=True,
     )
     rule = project.rule_set.all()[0]
     records = [
         event_to_record(event, (rule,))
         for event in self.create_events_from_filenames(
             project, ["hello.py", "goodbye.py", "hola.py", "adios.py"]
         )
     ]
     digest = build_digest(project, sort_records(records))
     user_ids = [member.user_id for member in team.member_set]
     assert not user_ids
     for user_id, user_digest in get_personalized_digests(project.id, digest, user_ids):
         assert False  # no users in this team no digests should be processed
Beispiel #21
0
    def test_owners_of_different_types_ordered_correctly(self):
        owners = [
            self.user, self.team3, self.user2, self.team2, self.user3,
            self.team
        ]
        rules = [
            Rule(Matcher("path", "*.py"), [Owner("user", owners[0].email)]),
            Rule(Matcher("path", "*py"), [Owner("team", owners[1].slug)]),
            Rule(Matcher("path", "*foo*"), [Owner("user", owners[2].email)]),
            Rule(Matcher("path", "*y"), [Owner("team", owners[3].slug)]),
            Rule(Matcher("path", "*"), [Owner("user", owners[4].email)]),
            Rule(Matcher("path", "*o.py"), [Owner("team", owners[5].slug)]),
        ]

        ProjectOwnership.objects.create(project_id=self.project.id,
                                        schema=dump_schema(rules),
                                        fallthrough=True)

        event1 = self.store_event(
            data={"stacktrace": {
                "frames": [{
                    "filename": "foo.py"
                }]
            }},
            project_id=self.project.id)

        self.path = reverse(
            "sentry-api-0-event-owners",
            kwargs={
                "organization_slug": self.organization.slug,
                "project_slug": self.project.slug,
                "event_id": event1.event_id,
            },
        )

        resp = self.client.get(self.path)
        assert resp.status_code == 200
        assert len(resp.data["owners"]) == 6
        assert [o["id"] for o in resp.data["owners"]
                ] == [six.text_type(o.id) for o in owners]
        assert [o["type"] for o in resp.data["owners"]] == ["user", "team"] * 3
        assert resp.data["rule"] == Matcher("path", "*.py")
        assert len(resp.data["rules"]) == 6
Beispiel #22
0
 def test_team_without_members(self):
     team = self.create_team()
     project = self.create_project(teams=[team], fire_project_created=True)
     ProjectOwnership.objects.create(
         project_id=project.id,
         schema=dump_schema([Rule(Matcher("path", "*.cpp"), [Owner("team", team.slug)])]),
         fallthrough=True,
     )
     rule = project.rule_set.all()[0]
     records = [
         event_to_record(event, (rule,))
         for event in self.create_events_from_filenames(
             project, ["hello.py", "goodbye.py", "hola.py", "adios.py"]
         )
     ]
     digest = build_digest(project, sort_records(records))[0]
     user_ids = [member.user_id for member in team.member_set]
     assert not user_ids
     participants_by_provider_by_event = get_participants_by_event(digest, project)
     assert not {
         actor for actors in participants_by_provider_by_event.values() for actor in actors
     }  # no users in this team no digests should be processed
Beispiel #23
0
    def test_get_autoassign_owners_only_codeowners_exists(self):
        # This case will never exist bc we create a ProjectOwnership record if none exists when creating a ProjectCodeOwner record.
        # We have this testcase for potential corrupt data.
        self.team = self.create_team(
            organization=self.organization, slug="tiger-team", members=[self.user]
        )
        self.code_mapping = self.create_code_mapping(project=self.project)

        rule_a = Rule(Matcher("path", "*.js"), [Owner("team", self.team.slug)])

        self.create_codeowners(
            self.project,
            self.code_mapping,
            raw="*.js @tiger-team",
            schema=dump_schema([rule_a]),
        )
        # No data matches
        assert ProjectOwnership.get_autoassign_owners(self.project.id, {}) == (False, [], False)

        # No autoassignment on match
        assert ProjectOwnership.get_autoassign_owners(
            self.project.id, {"stacktrace": {"frames": [{"filename": "foo.js"}]}}
        ) == (False, [self.team], True)
Beispiel #24
0
    def test_owner_assignment_extra_groups(self):
        extra_user = self.create_user()
        self.create_team_membership(self.team, user=extra_user)
        self.make_ownership([
            Rule(Matcher("path", "src/app/things/in/*"),
                 [Owner("user", extra_user.email)])
        ], )
        event = self.store_event(
            data={
                "message": "oh no",
                "platform": "python",
                "stacktrace": {
                    "frames": [{
                        "filename":
                        "src/app/things/in/a/path/example2.py"
                    }]
                },
            },
            project_id=self.project.id,
        )
        cache_key = write_event_to_cache(event)
        post_process_group(
            is_new=False,
            is_regression=False,
            is_new_group_environment=False,
            cache_key=cache_key,
            group_id=event.group_id,
        )
        assignee = event.group.assignee_set.first()
        assert assignee.user == extra_user
        assert assignee.team is None

        owners = list(GroupOwner.objects.filter(group=event.group))
        assert len(owners) == 2
        assert {(extra_user.id, None),
                (self.user.id, None)} == {(o.user_id, o.team_id)
                                          for o in owners}
 def test_team_without_members(self):
     team = self.create_team()
     project = self.create_project(teams=[team])
     ProjectOwnership.objects.create(
         project_id=project.id,
         schema=dump_schema([
             Rule(Matcher('path', '*.cpp'), [
                 Owner('team', team.slug),
             ]),
         ]),
         fallthrough=True,
     )
     rule = project.rule_set.all()[0]
     records = [
         event_to_record(event, (rule, ))
         for event in self.create_events(timezone.now(
         ), project, ['hello.py', 'goodbye.py', 'hola.py', 'adios.py'])
     ]
     digest = build_digest(project, sort_records(records))
     user_ids = [member.user_id for member in team.member_set]
     assert not user_ids
     for user_id, user_digest in get_personalized_digests(
             project.id, digest, user_ids):
         assert False  # no users in this team no digests should be processed
Beispiel #26
0
    def setUp(self):
        self.user1 = self.create_user()
        self.user2 = self.create_user()
        self.user3 = self.create_user()
        self.user4 = self.create_user()
        self.user5 = self.create_user()  # this user has no events
        self.user_ids = [
            self.user1.id, self.user2.id, self.user3.id, self.user4.id,
            self.user5.id
        ]

        self.team1 = self.create_team()
        self.team2 = self.create_team()
        self.team3 = self.create_team()

        self.project = self.create_project(
            teams=[self.team1, self.team2, self.team3])

        self.create_member(user=self.user1,
                           organization=self.organization,
                           teams=[self.team1])
        self.create_member(user=self.user2,
                           organization=self.organization,
                           teams=[self.team2])
        self.create_member(user=self.user3,
                           organization=self.organization,
                           teams=[self.team1, self.team2])
        self.create_member(user=self.user4,
                           organization=self.organization,
                           teams=[self.team3])
        self.create_member(user=self.user5,
                           organization=self.organization,
                           teams=[self.team3])

        start_time = timezone.now()

        self.team1_events = self.create_events(
            start_time, self.project,
            ["hello.py", "goodbye.py", "hola.py", "adios.py"])
        self.team2_events = self.create_events(
            start_time, self.project,
            ["old.cbl", "retro.cbl", "cool.cbl", "gem.cbl"])

        self.user4_events = [
            self.create_event(
                group=self.create_group(project=self.project),
                data=self.create_event_data("foo.bar", "helloworld.org"),
            ),
            self.create_event(
                group=self.create_group(project=self.project),
                data=self.create_event_data("bar.foo", "helloworld.org"),
            ),
        ]
        self.team1_matcher = Matcher("path", "*.py")
        self.team2_matcher = Matcher("path", "*.cbl")
        self.user4_matcher = Matcher("url", "*.org")

        ProjectOwnership.objects.create(
            project_id=self.project.id,
            schema=dump_schema([
                Rule(
                    self.team1_matcher,
                    [
                        Owner("team", self.team1.slug),
                        Owner("user", self.user3.email)
                    ],
                ),
                Rule(self.team2_matcher, [Owner("team", self.team2.slug)]),
                Rule(self.user4_matcher, [Owner("user", self.user4.email)]),
            ]),
            fallthrough=True,
        )
def test_matcher_test_none():
    data = {"request": {"url": None}}
    assert not Matcher("url", "").test(data)
    def test_get_owners_basic(self):
        rule_a = Rule(Matcher("path", "*.py"), [Owner("team", self.team.slug)])
        rule_b = Rule(Matcher("path", "src/*"),
                      [Owner("user", self.user.email)])

        ProjectOwnership.objects.create(project_id=self.project.id,
                                        schema=dump_schema([rule_a, rule_b]),
                                        fallthrough=True)

        # No data matches
        assert ProjectOwnership.get_owners(self.project.id,
                                           {}) == (ProjectOwnership.Everyone,
                                                   None)

        # Match only rule_a
        self.assert_ownership_equals(
            ProjectOwnership.get_owners(
                self.project.id,
                {"stacktrace": {
                    "frames": [{
                        "filename": "foo.py"
                    }]
                }}),
            ([Actor(self.team.id, Team)], [rule_a]),
        )

        # Match only rule_b
        self.assert_ownership_equals(
            ProjectOwnership.get_owners(
                self.project.id,
                {"stacktrace": {
                    "frames": [{
                        "filename": "src/thing.txt"
                    }]
                }}),
            ([Actor(self.user.id, User)], [rule_b]),
        )

        # Matches both rule_a and rule_b
        self.assert_ownership_equals(
            ProjectOwnership.get_owners(
                self.project.id,
                {"stacktrace": {
                    "frames": [{
                        "filename": "src/foo.py"
                    }]
                }}),
            ([Actor(self.user.id, User),
              Actor(self.team.id, Team)], [rule_a, rule_b]),
        )

        assert ProjectOwnership.get_owners(
            self.project.id,
            {"stacktrace": {
                "frames": [{
                    "filename": "xxxx"
                }]
            }}) == (ProjectOwnership.Everyone, None)

        # When fallthrough = False, we don't implicitly assign to Everyone
        owner = ProjectOwnership.objects.get(project_id=self.project.id)
        owner.fallthrough = False
        owner.save()

        assert ProjectOwnership.get_owners(
            self.project.id,
            {"stacktrace": {
                "frames": [{
                    "filename": "xxxx"
                }]
            }}) == ([], None)
    def test_get_owners_basic(self):
        rule_a = Rule(
            Matcher('path', '*.py'), [
                Owner('team', self.team.slug),
            ])

        rule_b = Rule(
            Matcher('path', 'src/*'), [
                Owner('user', self.user.email),
            ])

        ProjectOwnership.objects.create(
            project_id=self.project.id,
            schema=dump_schema([rule_a, rule_b]),
            fallthrough=True,
        )

        # No data matches
        assert ProjectOwnership.get_owners(self.project.id, {}) == (ProjectOwnership.Everyone, None)

        # Match only rule_a
        self.assert_ownership_equals(ProjectOwnership.get_owners(
            self.project.id, {
                'sentry.interfaces.Stacktrace': {
                    'frames': [{
                        'filename': 'foo.py',
                    }]
                }
            }
        ), ([Actor(self.team.id, Team)], [rule_a]))

        # Match only rule_b
        self.assert_ownership_equals(ProjectOwnership.get_owners(
            self.project.id, {
                'sentry.interfaces.Stacktrace': {
                    'frames': [{
                        'filename': 'src/thing.txt',
                    }]
                }
            }
        ), ([Actor(self.user.id, User)], [rule_b]))

        # Matches both rule_a and rule_b
        self.assert_ownership_equals(ProjectOwnership.get_owners(
            self.project.id, {
                'sentry.interfaces.Stacktrace': {
                    'frames': [{
                        'filename': 'src/foo.py',
                    }]
                }
            }
        ), ([Actor(self.user.id, User), Actor(self.team.id, Team)], [rule_a, rule_b]))

        assert ProjectOwnership.get_owners(
            self.project.id, {
                'sentry.interfaces.Stacktrace': {
                    'frames': [{
                        'filename': 'xxxx',
                    }]
                }
            }
        ) == (ProjectOwnership.Everyone, None)

        # When fallthrough = False, we don't implicitly assign to Everyone
        ProjectOwnership.objects.filter(
            project_id=self.project.id,
        ).update(fallthrough=False)

        assert ProjectOwnership.get_owners(
            self.project.id, {
                'sentry.interfaces.Stacktrace': {
                    'frames': [{
                        'filename': 'xxxx',
                    }]
                }
            }
        ) == ([], None)
def test_matcher_test_tags_without_tag_data(data):
    assert not Matcher("tags.foo", "foo_value").test(data)
    assert not Matcher("tags.bar", "barval").test(data)