Beispiel #1
0
    def test_no_accounts_received(self, mock_render_to_response,
                                  mock_get_user_info):
        responses.reset()
        responses.add(
            responses.GET,
            "https://app.vssps.visualstudio.com/_apis/accounts",
            json={
                "value": [],
                "count": 0
            },
            status=200,
        )

        view = AccountConfigView()
        request = Mock()
        request.POST = {}
        request.user = self.user

        pipeline = Mock()
        pipeline.fetch_state = lambda key: {
            "data": {
                "access_token": "1234567890"
            }
        }
        pipeline.organization = self.organization

        view.dispatch(request, pipeline)
        assert mock_get_user_info.called is True
        assert mock_render_to_response.called is True
        assert mock_render_to_response.call_args[1]["context"] == {
            "no_accounts": True
        }
class OrganizationRateLimitsTest(AcceptanceTestCase):
    def setUp(self):
        super().setUp()
        self.user = self.create_user("*****@*****.**")
        self.org = self.create_organization(name="Rowdy Tiger", owner=None)
        self.team = self.create_team(organization=self.org,
                                     name="Mariachi Band")
        self.project = self.create_project(organization=self.org,
                                           teams=[self.team],
                                           name="Bengal")
        self.create_member(user=self.user,
                           organization=self.org,
                           role="owner",
                           teams=[self.team])
        self.login_as(self.user)
        self.path = f"/organizations/{self.org.slug}/rate-limits/"

    @patch("sentry.app.quotas.get_maximum_quota", Mock(return_value=(100, 60)))
    def test_with_rate_limits(self):
        self.project.update(first_event=timezone.now())
        self.browser.get(self.path)
        self.browser.wait_until_not(".loading-indicator")
        self.browser.wait_until_test_id("rate-limit-editor")
        self.browser.snapshot("organization rate limits with quota")
        assert self.browser.element_exists_by_test_id("rate-limit-editor")

    @patch("sentry.app.quotas.get_maximum_quota", Mock(return_value=(0, 60)))
    def test_without_rate_limits(self):
        self.project.update(first_event=timezone.now())
        self.browser.get(self.path)
        self.browser.wait_until_not(".loading-indicator")
        self.browser.wait_until_test_id("rate-limit-editor")
        self.browser.snapshot("organization rate limits without quota")
        assert self.browser.element_exists_by_test_id("rate-limit-editor")
Beispiel #3
0
    def test_rule_processor(self, mock_processor):
        event = self.store_event(data={"message": "testing"},
                                 project_id=self.project.id)
        cache_key = write_event_to_cache(event)

        mock_callback = Mock()
        mock_futures = [Mock()]

        mock_processor.return_value.apply.return_value = [(mock_callback,
                                                           mock_futures)]

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

        mock_processor.assert_called_once_with(EventMatcher(event), True,
                                               False, True, False)
        mock_processor.return_value.apply.assert_called_once_with()

        mock_callback.assert_called_once_with(EventMatcher(event),
                                              mock_futures)
Beispiel #4
0
    def test_service_hook_fires_on_alert(self, mock_processor,
                                         mock_process_service_hook):
        event = self.store_event(data={}, project_id=self.project.id)
        cache_key = write_event_to_cache(event)

        mock_callback = Mock()
        mock_futures = [Mock()]

        mock_processor.return_value.apply.return_value = [(mock_callback,
                                                           mock_futures)]

        hook = self.create_service_hook(
            project=self.project,
            organization=self.project.organization,
            actor=self.user,
            events=["event.alert"],
        )

        with self.feature("projects:servicehooks"):
            post_process_group(
                is_new=False,
                is_regression=False,
                is_new_group_environment=False,
                cache_key=cache_key,
                group_id=event.group_id,
            )

        mock_process_service_hook.delay.assert_called_once_with(
            servicehook_id=hook.id, event=EventMatcher(event))
Beispiel #5
0
    def test_group_refresh(self, mock_processor):
        event = self.store_event(data={"message": "testing"},
                                 project_id=self.project.id)
        cache_key = write_event_to_cache(event)

        group1 = event.group
        group2 = self.create_group(project=self.project)

        assert event.group_id == group1.id
        assert event.group == group1

        with self.tasks():
            merge_groups([group1.id], group2.id)

        mock_callback = Mock()
        mock_futures = [Mock()]

        mock_processor.return_value.apply.return_value = [(mock_callback,
                                                           mock_futures)]

        post_process_group(
            is_new=True,
            is_regression=False,
            is_new_group_environment=True,
            cache_key=cache_key,
            group_id=event.group_id,
        )
        # Ensure that rule processing sees the merged group.
        mock_processor.assert_called_with(EventMatcher(event, group=group2),
                                          True, False, True, False)
Beispiel #6
0
class MailPluginShouldNotifyTest(TestCase):
    @fixture
    def plugin(self):
        return MailPlugin()

    @mock.patch("sentry.mail.adapter.MailAdapter.get_sendable_users",
                Mock(return_value=[]))
    def test_should_notify_no_sendable_users_has_issue_alerts_targeting(self):
        self.group.project.flags.has_issue_alerts_targeting = True
        self.group.project.save()
        assert not self.plugin.should_notify(group=self.group, event=Mock())

    @mock.patch("sentry.mail.adapter.MailAdapter.get_sendable_users",
                Mock(return_value=[]))
    def test_should_notify_no_sendable_users_not_has_issue_alerts_targeting(
            self):
        self.group.project.flags.has_issue_alerts_targeting = False
        self.group.project.save()
        assert not self.plugin.should_notify(group=self.group, event=Mock())

    @mock.patch("sentry.mail.adapter.MailAdapter.get_sendable_users",
                Mock(return_value=[1]))
    def test_should_notify_sendable_users_has_issue_alerts_targetting(self):
        self.group.project.flags.has_issue_alerts_targeting = True
        self.group.project.save()
        assert not self.plugin.should_notify(group=self.group, event=Mock())

    @mock.patch("sentry.mail.adapter.MailAdapter.get_sendable_users",
                Mock(return_value=[1]))
    def test_should_notify_sendable_users_not_has_issue_alerts_targetting(
            self):
        self.group.project.flags.has_issue_alerts_targeting = False
        self.group.project.save()
        assert self.plugin.should_notify(group=self.group, event=Mock())
Beispiel #7
0
 def test_handler(self):
     mock_handler = Mock()
     mock_method = getattr(mock_handler.return_value, self.method)
     mock_method.return_value = "test"
     type = AlertRuleTriggerAction.Type.EMAIL
     AlertRuleTriggerAction.register_type("something", type, [])(mock_handler)
     trigger = AlertRuleTriggerAction(type=type.value)
     assert getattr(trigger, self.method)(Mock(), Mock()) == mock_method.return_value
Beispiel #8
0
    def test_handled(self):
        mock_handler = Mock()
        type = AlertRuleTriggerAction.Type.EMAIL
        AlertRuleTriggerAction.register_type("something", type, [])(mock_handler)

        trigger = AlertRuleTriggerAction(type=AlertRuleTriggerAction.Type.EMAIL.value)
        incident = Mock()
        project = Mock()
        trigger.build_handler(incident, project)
        mock_handler.assert_called_once_with(trigger, incident, project)
        assert not self.metrics.incr.called
Beispiel #9
0
    def test_user_success(self):
        user = self.create_user()
        organization = self.create_organization(owner=user)
        project = self.create_project(organization=organization)
        hook = HerokuReleaseHook(project)
        hook.set_refs = Mock()

        req = Mock()
        req.POST = {"head_long": "abcd123", "url": "http://example.com", "user": user.email}
        hook.handle(req)
        assert Release.objects.filter(version=req.POST["head_long"]).exists()
        assert hook.set_refs.call_count == 1
Beispiel #10
0
 def test_show_notify_event_service_action(self):
     rules = RuleRegistry()
     rule = Mock()
     rule.id = APP_ACTION
     rule.rule_type = "action/lol"
     node = rule.return_value
     node.id = rule.id
     node.label = "hello"
     node.prompt = "hello"
     node.is_enabled.return_value = True
     node.form_fields = {}
     node.get_services.return_value = [Mock()]
     rules.add(rule)
     self.run_mock_rules_test(1, {}, rules=rules)
Beispiel #11
0
    def test_basic_flow(self, mock_sha):
        sha = Mock()
        sha.hexdigest.return_value = "secret-token"
        mock_sha.return_value = sha

        self.assert_setup_flow()

        integration = Integration.objects.get(provider=self.provider.key)

        assert integration.external_id == "gitlab.example.com:4"
        assert integration.name == "Cool"
        assert integration.metadata == {
            "instance": "gitlab.example.com",
            "scopes": ["api"],
            "icon": u"https://gitlab.example.com/uploads/group/avatar/4/foo.jpg",
            "domain_name": u"gitlab.example.com/cool-group",
            "verify_ssl": True,
            "base_url": "https://gitlab.example.com",
            "webhook_secret": "secret-token",
            "group_id": self.default_group_id,
            "include_subgroups": True,
        }
        oi = OrganizationIntegration.objects.get(
            integration=integration, organization=self.organization
        )
        assert oi.config == {}

        idp = IdentityProvider.objects.get(type="gitlab")
        identity = Identity.objects.get(
            idp=idp, user=self.user, external_id="gitlab.example.com:user_id_1"
        )
        assert identity.status == IdentityStatus.VALID
        assert identity.data == {"access_token": "xxxxx-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxxxxx"}
    def test_normal(self):
        cluster_name = settings.KAFKA_TOPICS[self.topic]["cluster"]

        conf = {
            "bootstrap.servers":
            settings.KAFKA_CLUSTERS[cluster_name]["bootstrap.servers"],
            "session.timeout.ms":
            6000,
        }

        producer = Producer(conf)
        producer.produce(self.topic, json.dumps(self.valid_wrapper))
        producer.flush()
        mock_callback = Mock()
        mock_callback.side_effect = KeyboardInterrupt()
        register_subscriber(self.registration_key)(mock_callback)
        sub = QuerySubscription.objects.create(
            project=self.project,
            type=self.registration_key,
            subscription_id=self.subscription_id,
            dataset="something",
            query="hello",
            aggregation=0,
            time_window=1,
            resolution=1,
        )
        consumer = QuerySubscriptionConsumer("hi",
                                             topic=self.topic,
                                             commit_batch_size=1)
        consumer.run()
        mock_callback.assert_called_once_with(self.valid_payload, sub)
Beispiel #13
0
    def test_webhook_subscription_created_once(self, mock_get_scopes):
        self.assert_installation()

        state = {
            "account": {"accountName": self.vsts_account_name, "accountId": self.vsts_account_id},
            "base_url": self.vsts_base_url,
            "identity": {
                "data": {
                    "access_token": self.access_token,
                    "expires_in": "3600",
                    "refresh_token": self.refresh_token,
                    "token_type": "jwt-bearer",
                }
            },
        }

        # The above already created the Webhook, so subsequent calls to
        # ``build_integration`` should omit that data.
        provider = VstsIntegrationProvider()
        pipeline = Mock()
        pipeline.organization = self.organization
        provider.set_pipeline(pipeline)
        data = provider.build_integration(state)
        assert "subscription" in data["metadata"]
        assert (
            Integration.objects.get(provider="vsts").metadata["subscription"]
            == data["metadata"]["subscription"]
        )
    def test_normal(self):
        cluster_name = settings.KAFKA_TOPICS[self.topic]["cluster"]

        conf = {
            "bootstrap.servers":
            settings.KAFKA_CLUSTERS[cluster_name]["bootstrap.servers"],
            "session.timeout.ms":
            6000,
        }

        producer = Producer(conf)
        producer.produce(self.topic, json.dumps(self.valid_wrapper))
        producer.flush()
        mock_callback = Mock()
        mock_callback.side_effect = KeyboardInterrupt()
        register_subscriber(self.registration_key)(mock_callback)
        sub = self.create_subscription()
        consumer = QuerySubscriptionConsumer("hi",
                                             topic=self.topic,
                                             commit_batch_size=1)
        consumer.run()

        payload = self.valid_payload
        payload["values"] = payload["result"]
        payload["timestamp"] = parse_date(
            payload["timestamp"]).replace(tzinfo=pytz.utc)
        mock_callback.assert_called_once_with(payload, sub)
    def test_subscription_registered(self):
        registration_key = "registered_test"
        mock_callback = Mock()
        register_subscriber(registration_key)(mock_callback)
        with self.tasks():
            snuba_query = create_snuba_query(
                QueryDatasets.EVENTS,
                "hello",
                QueryAggregations.TOTAL,
                timedelta(minutes=10),
                timedelta(minutes=1),
                None,
            )
            sub = create_snuba_subscription(self.project, registration_key,
                                            snuba_query)
        sub.refresh_from_db()

        data = self.valid_wrapper
        data["payload"]["subscription_id"] = sub.subscription_id
        self.consumer.handle_message(self.build_mock_message(data))
        data = deepcopy(data)
        data["payload"]["values"] = data["payload"]["result"]
        data["payload"]["timestamp"] = parse_date(
            data["payload"]["timestamp"]).replace(tzinfo=pytz.utc)
        mock_callback.assert_called_once_with(data["payload"], sub)
Beispiel #16
0
    def test_update_comment(self):
        org = self.organization

        self.user.name = "Sentry Admin"
        self.user.save()
        self.login_as(self.user)

        integration = Integration.objects.create(provider="jira",
                                                 name="Example Jira")
        integration.add_organization(org, self.user)
        installation = integration.get_installation(org.id)

        group_note = Mock()
        comment = "hello world\nThis is a comment.\n\n\n    I've changed it"
        group_note.data = {}
        group_note.data["text"] = comment
        group_note.data["external_id"] = "123"
        with mock.patch.object(MockJiraApiClient,
                               "update_comment") as mock_update_comment:

            def get_client():
                return MockJiraApiClient()

            with mock.patch.object(installation, "get_client", get_client):
                installation.update_comment(1, self.user.id, group_note)
                assert mock_update_comment.call_args[0] == (
                    1,
                    "123",
                    "Sentry Admin wrote:\n\n{quote}%s{quote}" % comment,
                )
Beispiel #17
0
    def test_exchange_token(self):
        def redirect_url():
            return "https://app.vssps.visualstudio.com/oauth2/authorize"

        view = VSTSOAuth2CallbackView(
            access_token_url="https://app.vssps.visualstudio.com/oauth2/token",
            client_id="vsts-client-id",
            client_secret="vsts-client-secret",
        )
        request = Mock()
        pipeline = Mock()

        pipeline.redirect_url = redirect_url

        responses.add(
            responses.POST,
            "https://app.vssps.visualstudio.com/oauth2/token",
            json={
                "access_token": "xxxxxxxxx",
                "token_type": "jwt-bearer",
                "expires_in": "3599",
                "refresh_token": "zzzzzzzzzz",
            },
        )

        result = view.exchange_token(request, pipeline, "oauth-code")
        mock_request = responses.calls[0].request
        req_params = parse_qs(mock_request.body)

        assert req_params["grant_type"] == [
            "urn:ietf:params:oauth:grant-type:jwt-bearer"
        ]
        assert req_params["assertion"] == ["oauth-code"]
        assert req_params["redirect_uri"] == [
            "https://app.vssps.visualstudio.com/oauth2/authorize"
        ]
        assert req_params["client_assertion_type"] == [
            "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
        ]
        assert req_params["client_assertion"] == ["vsts-client-secret"]

        assert result["access_token"] == "xxxxxxxxx"
        assert result["token_type"] == "jwt-bearer"
        assert result["expires_in"] == "3599"
        assert result["refresh_token"] == "zzzzzzzzzz"
Beispiel #18
0
    def test_rule_processor(self, mock_processor):
        event = self.store_event(data={}, project_id=self.project.id)

        mock_callback = Mock()
        mock_futures = [Mock()]

        mock_processor.return_value.apply.return_value = [(mock_callback,
                                                           mock_futures)]

        post_process_group(event=event,
                           is_new=True,
                           is_regression=False,
                           is_new_group_environment=True)

        mock_processor.assert_called_once_with(event, True, False, True, False)
        mock_processor.return_value.apply.assert_called_once_with()

        mock_callback.assert_called_once_with(event, mock_futures)
Beispiel #19
0
 def test_exchange_token_no_json(self):
     responses.add(responses.POST, "https://example.org/oauth/token", body="")
     pipeline = IdentityProviderPipeline(request=Mock(), provider_key="dummy")
     code = "auth-code"
     result = self.view.exchange_token(None, pipeline, code)
     assert "token" not in result
     assert "error" in result
     assert "error_description" in result
     assert "JSON" in result["error_description"]
Beispiel #20
0
 def test_exchange_token_success(self):
     responses.add(
         responses.POST, "https://example.org/oauth/token", json={"token": "a-fake-token"}
     )
     pipeline = IdentityProviderPipeline(request=Mock(), provider_key="dummy")
     code = "auth-code"
     result = self.view.exchange_token(None, pipeline, code)
     assert "token" in result
     assert "a-fake-token" == result["token"]
Beispiel #21
0
    def test_bad_version(self):
        project = self.create_project()
        user = self.create_user()
        hook = HerokuReleaseHook(project)

        req = Mock()
        req.POST = {"head_long": "", "url": "http://example.com", "user": user.email}
        with self.assertRaises(HookValidationError):
            hook.handle(req)
    def test_shutdown(self):
        self.producer.produce(self.topic, json.dumps(self.valid_wrapper))
        valid_wrapper_2 = deepcopy(self.valid_wrapper)
        valid_wrapper_2["payload"]["values"]["hello"] = 25
        valid_wrapper_3 = deepcopy(valid_wrapper_2)
        valid_wrapper_3["payload"]["values"]["hello"] = 5000
        self.producer.produce(self.topic, json.dumps(valid_wrapper_2))
        self.producer.flush()

        counts = [0]

        def mock_callback(*args, **kwargs):
            counts[0] += 1
            if counts[0] > 1:
                raise KeyboardInterrupt()

        mock = Mock()
        mock.side_effect = mock_callback

        register_subscriber(self.registration_key)(mock)
        sub = QuerySubscription.objects.create(
            project=self.project,
            type=self.registration_key,
            subscription_id=self.subscription_id,
            dataset="something",
            query="hello",
            aggregation=0,
            time_window=1,
            resolution=1,
        )
        consumer = QuerySubscriptionConsumer("hi",
                                             topic=self.topic,
                                             commit_batch_size=100)
        consumer.run()
        valid_payload = self.valid_payload
        valid_payload["timestamp"] = parse_date(
            valid_payload["timestamp"]).replace(tzinfo=pytz.utc)
        valid_wrapper_2["payload"]["timestamp"] = parse_date(
            valid_wrapper_2["payload"]["timestamp"]).replace(tzinfo=pytz.utc)
        mock.assert_has_calls(
            [call(valid_payload, sub),
             call(valid_wrapper_2["payload"], sub)])
        # Offset should be committed for the first message, so second run should process
        # the second message again
        self.producer.produce(self.topic, json.dumps(valid_wrapper_3))
        self.producer.flush()
        mock.reset_mock()
        counts[0] = 0
        consumer.run()
        valid_wrapper_3["payload"]["timestamp"] = parse_date(
            valid_wrapper_3["payload"]["timestamp"]).replace(tzinfo=pytz.utc)

        mock.assert_has_calls([
            call(valid_wrapper_2["payload"], sub),
            call(valid_wrapper_3["payload"], sub)
        ])
Beispiel #23
0
class LinkSharedEventTest(BaseEventTest):
    @responses.activate
    @patch(
        "sentry.integrations.slack.endpoints.event.match_link",
        # match_link will be called twice, for each our links. Resolve into
        # two unique links and one duplicate.
        side_effect=[
            ("mock_link", {"arg1": "value1"}),
            ("mock_link", {"arg1", "value2"}),
            ("mock_link", {"arg1": "value1"}),
        ],
    )
    @patch(
        "sentry.integrations.slack.endpoints.event.link_handlers",
        {
            "mock_link": Handler(
                matcher=re.compile(r"test"),
                arg_mapper=make_type_coercer({}),
                fn=Mock(return_value={"link1": "unfurl", "link2": "unfurl"}),
            )
        },
    )
    def share_links(self, mock_match_link):
        responses.add(responses.POST, "https://slack.com/api/chat.unfurl", json={"ok": True})

        resp = self.post_webhook(event_data=json.loads(LINK_SHARED_EVENT))
        assert resp.status_code == 200, resp.content
        assert len(mock_match_link.mock_calls) == 3

        data = dict(parse_qsl(responses.calls[0].request.body))
        unfurls = json.loads(data["unfurls"])

        # We only have two unfurls since one link was duplicated
        assert len(unfurls) == 2
        assert unfurls["link1"] == "unfurl"
        assert unfurls["link2"] == "unfurl"

        return data

    def test_valid_token(self):
        data = self.share_links()
        assert data["token"] == "xoxb-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxxxxx"

    def test_user_access_token(self):
        # this test is needed to make sure that classic bots installed by on-prem users
        # still work since they needed to use a user_access_token for unfurl
        self.integration.metadata.update(
            {
                "user_access_token": "xoxt-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxxxxx",
                "access_token": "xoxm-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxxxxx",
            }
        )
        self.integration.save()

        data = self.share_links()
        assert data["token"] == "xoxt-xxxxxxxxx-xxxxxxxxxx-xxxxxxxxxxxx"
Beispiel #24
0
 def setUp(self):
     super(ProcessUpdateTest, self).setUp()
     self.old_handlers = AlertRuleTriggerAction._type_registrations
     AlertRuleTriggerAction._type_registrations = {}
     self.email_action_handler = Mock()
     AlertRuleTriggerAction.register_type("email", AlertRuleTriggerAction.Type.EMAIL, [])(
         self.email_action_handler
     )
     self._run_tasks = self.tasks()
     self._run_tasks.__enter__()
Beispiel #25
0
    def test_email_mismatch(self):
        user = self.create_user()
        organization = self.create_organization(owner=user)
        project = self.create_project(organization=organization)
        hook = HerokuReleaseHook(project)

        req = Mock()
        req.POST = {"head_long": "v999", "url": "http://example.com", "user": "******"}
        hook.handle(req)
        assert Release.objects.filter(version=req.POST["head_long"]).exists()
Beispiel #26
0
    def test_with_expected_errors(self, mock_get_logger):
        mock_log = Mock()
        mock_get_logger.return_value = mock_log

        def simple(a):
            raise ValueError()

        assert safe_execute(simple, 1, expected_errors=(ValueError,)) is None
        assert mock_log.info.called
        assert mock_log.error.called is False
Beispiel #27
0
    def test_adds_type(self):
        sub = self.create_subscription(QuerySubscription.Status.CREATING)
        with patch("sentry.snuba.tasks._snuba_pool") as pool:
            resp = Mock()
            resp.status = 202
            resp.data = json.dumps({"subscription_id": "123"})
            pool.urlopen.return_value = resp

            create_subscription_in_snuba(sub.id)
            request_body = json.loads(pool.urlopen.call_args[1]["body"])
            assert ["type", "=", "error"] in request_body["conditions"]
Beispiel #28
0
    def test_with_authorization_and_no_auth(self):
        responses.add(responses.GET, "http://example.com", json={})

        auth = Mock()
        auth.tokens = {"access_token": "access-token"}

        resp = AuthApiClient(auth=auth).get("http://example.com", auth=None)
        assert resp.status_code == 200

        request = responses.calls[-1].request
        assert not request.headers.get("Authorization")
Beispiel #29
0
    def test_simple(self):
        request = Mock()
        request.GET = QueryDict("member=1&cursor=foo")
        request.method = "GET"
        request.path = "/api/0/organizations/"
        endpoint = Endpoint()
        result = endpoint.build_cursor_link(request, "next",
                                            "1492107369532:0:0")

        assert result == (
            "<http://testserver/api/0/organizations/?member=1&cursor=1492107369532:0:0>;"
            ' rel="next"; results="true"; cursor="1492107369532:0:0"')
Beispiel #30
0
    def test_unicode_path(self):
        request = Mock()
        request.GET = {"member": ["1"]}
        request.method = "GET"
        request.path = "/api/0/organizations/üuuuu/"
        endpoint = Endpoint()
        result = endpoint.build_cursor_link(request, "next",
                                            "1492107369532:0:0")

        assert result == (
            "<http://testserver/api/0/organizations/%C3%BCuuuu/?member=%5B%271%27%5D&cursor=1492107369532:0:0>;"
            ' rel="next"; results="true"; cursor="1492107369532:0:0"')