Ejemplo n.º 1
0
    def test_search_results_pagination(self):
        """Test that the pagination of results works as expected.
        """

        def mocked_supersearch_get(**params):
            assert '_columns' in params

            # Make sure a negative page does not lead to negative offset value.
            # But instead it is considered as the page 1 and thus is not added.
            assert params.get('_results_offset') == 0

            hits = []
            for i in range(140):
                hits.append({
                    "signature": "hang | nsASDOMWindowEnumerator::GetNext()",
                    "date": "2017-01-31T23:12:57",
                    "uuid": i,
                    "product": "WaterWolf",
                    "version": "1.0",
                    "platform": "Linux",
                    "build_id": 888981
                })
            return {
                "hits": self.only_certain_columns(hits, params['_columns']),
                "facets": "",
                "total": len(hits)
            }

        SuperSearchUnredacted.implementation().get.side_effect = mocked_supersearch_get

        url = reverse('supersearch:search_results')

        response = self.client.get(
            url,
            {
                'signature': 'hang | nsASDOMWindowEnumerator::GetNext()',
                '_columns': ['version'],
                '_facets': ['platform'],
            }
        )

        assert response.status_code == 200
        assert '140' in smart_text(response.content)

        # Check that the pagination URL contains all three expected parameters.
        doc = pyquery.PyQuery(response.content)
        next_page_url = str(doc('.pagination a').eq(0))
        assert '_facets=platform' in next_page_url
        assert '_columns=version' in next_page_url
        assert 'page=2' in next_page_url
        assert '#crash-reports' in next_page_url

        # Verify white spaces are correctly encoded.
        # Note we use `quote` and not `quote_plus`, so white spaces are
        # turned into '%20' instead of '+'.
        assert quote('hang | nsASDOMWindowEnumerator::GetNext()') in next_page_url

        # Test that a negative page value does not break it.
        response = self.client.get(url, {'page': '-1'})
        assert response.status_code == 200
Ejemplo n.º 2
0
    def test_topcrasher_by_build(self):

        def mocked_supersearch_get(**params):
            ok_('build_id' in params)
            return {
                'hits': [],
                'facets': {
                    'signature': []
                },
                'total': 0
            }
        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get
        )

        response = self.client.get(self.base_url, {
            'product': 'WaterWolf',
            'version': '19.0',
            '_range_type': 'build',
        })
        eq_(response.status_code, 200)

        # Test with a version that does not support builds.
        response = self.client.get(self.base_url, {
            'product': 'WaterWolf',
            'version': '18.0',
            '_range_type': 'build',
        })
        eq_(response.status_code, 200)
        ok_('versions do not support the by build date' in response.content)
        ok_('Range Type:' not in response.content)
Ejemplo n.º 3
0
    def test_topcrasher_without_any_signatures(self, rpost):
        url = self.base_url + '?product=WaterWolf&version=19.0'
        response = self.client.get(self.base_url, {
            'product': 'WaterWolf',
        })
        ok_(url in response['Location'])

        rpost.side_effect = mocked_post_123

        def mocked_supersearch_get(**params):
            return {
                'hits': [],
                'facets': {
                    'signature': []
                },
                'total': 0
            }
        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get
        )

        response = self.client.get(self.base_url, {
            'product': 'WaterWolf',
            'version': '19.0',
        })
        eq_(response.status_code, 200)
Ejemplo n.º 4
0
    def test_search_custom_parameters(self):
        self.create_custom_query_perm()

        def mocked_supersearch_get(**params):
            ok_('_return_query' in params)
            ok_('signature' in params)
            eq_(params['signature'], ['nsA'])

            return {
                "query": {
                    "query": None
                },
                "indices": ["socorro200000", "socorro200001"]
            }

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get)

        url = reverse('supersearch.search_custom')
        response = self.client.get(url, {'signature': 'nsA'})
        eq_(response.status_code, 200)
        ok_('Run a search to get some results' in response.content)
        ok_('{"query": null}' in response.content)
        ok_('socorro200000' in response.content)
        ok_('socorro200001' in response.content)
Ejemplo n.º 5
0
    def test_topcrasher_modes(self):
        def mocked_supersearch_get(**params):
            return {'hits': [], 'facets': {'signature': []}, 'total': 0}

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get)

        now = datetime.datetime.utcnow().replace(microsecond=0)
        today = now.replace(hour=0, minute=0, second=0)

        with freezegun.freeze_time(now, tz_offset=0):
            now = now.isoformat()
            today = today.isoformat()

            # By default, it returns "real-time" data.
            response = self.client.get(self.base_url, {
                'product': 'WaterWolf',
                'version': '19.0',
            })
            assert response.status_code == 200
            assert now in response.content
            assert today not in response.content

            # Now test the "day time" data.
            response = self.client.get(self.base_url, {
                'product': 'WaterWolf',
                'version': '19.0',
                '_tcbs_mode': 'byday',
            })
            assert response.status_code == 200
            assert today in response.content
            assert now not in response.content
Ejemplo n.º 6
0
    def test_signature_summary_with_many_hexes(self):
        def mocked_supersearch_get(**params):
            assert "signature" in params
            assert params["signature"] == ["=" + DUMB_SIGNATURE]

            adapters = [{"term": "0x{0:0>4}".format(i), "count": 1} for i in range(50)]
            vendors = [
                {
                    "term": "0x{0:0>4}".format(i),
                    "count": 50,
                    "facets": {"adapter_device_id": adapters},
                }
                for i in range(3)
            ]

            res = {"hits": [], "total": 4, "facets": {"adapter_vendor_id": vendors}}

            return res

        SuperSearchUnredacted.implementation().get.side_effect = mocked_supersearch_get

        # Test with no results
        url = reverse("signature:signature_summary")

        response = self.client.get(
            url, {"signature": DUMB_SIGNATURE, "product": "WaterWolf", "version": "1.0"}
        )
        assert response.status_code == 200
Ejemplo n.º 7
0
    def test_search_custom_parameters(self):
        self.create_custom_query_perm()

        def mocked_supersearch_get(**params):
            assert '_return_query' in params
            assert 'signature' in params
            assert params['signature'] == ['nsA']

            return {
                "query": {
                    "query": None
                },
                "indices": ["socorro200000", "socorro200001"]
            }

        SuperSearchUnredacted.implementation(
        ).get.side_effect = mocked_supersearch_get

        url = reverse('supersearch:search_custom')
        response = self.client.get(url, {'signature': 'nsA'})
        assert response.status_code == 200
        assert 'Run a search to get some results' in smart_text(
            response.content)
        assert '{"query": null}' in smart_text(response.content)
        assert 'socorro200000' in smart_text(response.content)
        assert 'socorro200001' in smart_text(response.content)
Ejemplo n.º 8
0
    def test_modes(self):
        def mocked_supersearch_get(**params):
            return {"hits": [], "facets": {"signature": []}, "total": 0}

        SuperSearchUnredacted.implementation(
        ).get.side_effect = mocked_supersearch_get

        now = datetime.datetime.utcnow().replace(microsecond=0)
        today = now.replace(hour=0, minute=0, second=0)

        with freezegun.freeze_time(now, tz_offset=0):
            now = now.isoformat()
            today = today.isoformat()

            # By default, it returns "real-time" data.
            response = self.client.get(self.base_url, {
                "product": "WaterWolf",
                "version": "19.0"
            })
            assert response.status_code == 200
            assert now in smart_text(response.content)
            assert today not in smart_text(response.content)

            # Now test the "day time" data.
            response = self.client.get(
                self.base_url,
                {
                    "product": "WaterWolf",
                    "version": "19.0",
                    "_tcbs_mode": "byday"
                },
            )
            assert response.status_code == 200
            assert today in smart_text(response.content)
            assert now not in smart_text(response.content)
Ejemplo n.º 9
0
    def test_search_results_pagination(self):
        """Test that the pagination of results works as expected.
        """
        def mocked_supersearch_get(**params):
            assert '_columns' in params

            # Make sure a negative page does not lead to negative offset value.
            # But instead it is considered as the page 1 and thus is not added.
            eq_(params.get('_results_offset'), 0)

            hits = []
            for i in range(140):
                hits.append({
                    "signature": "hang | nsASDOMWindowEnumerator::GetNext()",
                    "date": "2017-01-31T23:12:57",
                    "uuid": i,
                    "product": "WaterWolf",
                    "version": "1.0",
                    "platform": "Linux",
                    "build_id": 888981
                })
            return {
                "hits": self.only_certain_columns(hits, params['_columns']),
                "facets": "",
                "total": len(hits)
            }

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get)

        url = reverse('supersearch.search_results')

        response = self.client.get(
            url, {
                'signature': 'hang | nsASDOMWindowEnumerator::GetNext()',
                '_columns': ['version'],
                '_facets': ['platform'],
            })

        eq_(response.status_code, 200)
        ok_('140' in response.content)

        # Check that the pagination URL contains all three expected parameters.
        doc = pyquery.PyQuery(response.content)
        next_page_url = str(doc('.pagination a').eq(0))
        ok_('_facets=platform' in next_page_url)
        ok_('_columns=version' in next_page_url)
        ok_('page=2' in next_page_url)
        ok_('#crash-reports' in next_page_url)

        # Verify white spaces are correctly encoded.
        ok_(
            # Note we use `quote` and not `quote_plus`, so white spaces are
            # turned into '%20' instead of '+'.
            urllib.quote('hang | nsASDOMWindowEnumerator::GetNext()') in
            next_page_url)

        # Test that a negative page value does not break it.
        response = self.client.get(url, {'page': '-1'})
        eq_(response.status_code, 200)
Ejemplo n.º 10
0
    def test_signature_reports_pagination(self):
        """Test that the pagination of results works as expected"""

        def mocked_supersearch_get(**params):
            assert "_columns" in params

            # Make sure a negative page does not lead to negative offset value.
            # But instead it is considered as the page 1 and thus is not added.
            assert params.get("_results_offset") == 0

            hits = []
            for i in range(140):
                hits.append(
                    {
                        "signature": "nsASDOMWindowEnumerator::GetNext()",
                        "date": "2017-01-31T23:12:57",
                        "uuid": i,
                        "product": "WaterWolf",
                        "version": "1.0",
                        "platform": "Linux",
                        "build_id": 888981,
                    }
                )
            return {
                "hits": self.only_certain_columns(hits, params["_columns"]),
                "facets": "",
                "total": len(hits),
            }

        SuperSearchUnredacted.implementation().get.side_effect = mocked_supersearch_get

        url = reverse("signature:signature_reports")

        response = self.client.get(
            url,
            {
                "signature": DUMB_SIGNATURE,
                "product": ["WaterWolf"],
                "_columns": ["platform"],
            },
        )

        assert response.status_code == 200
        assert "140" in smart_text(response.content)

        # Check that the pagination URL contains all three expected parameters.
        doc = pyquery.PyQuery(response.content)
        next_page_url = str(doc(".pagination a").eq(0))
        assert "product=WaterWolf" in next_page_url
        assert "_columns=platform" in next_page_url
        assert "page=2" in next_page_url

        # Verify white spaces are correctly encoded.
        # Note we use `quote` and not `quote_plus`, so white spaces are
        # turned into '%20' instead of '+'.
        assert quote(DUMB_SIGNATURE) in next_page_url

        # Test that a negative page value does not break it.
        response = self.client.get(url, {"signature": DUMB_SIGNATURE, "page": "-1"})
        assert response.status_code == 200
Ejemplo n.º 11
0
    def test_parameters(self):
        def mocked_supersearch_get(**params):
            # Verify that all expected parameters are in the URL.
            ok_('product' in params)
            ok_('WaterWolf' in params['product'])
            ok_('NightTrain' in params['product'])

            ok_('address' in params)
            ok_('0x0' in params['address'])
            ok_('0xa' in params['address'])

            ok_('reason' in params)
            ok_('^hello' in params['reason'])
            ok_('$thanks' in params['reason'])

            ok_('java_stack_trace' in params)
            ok_('Exception' in params['java_stack_trace'])

            return {"hits": [], "facets": "", "total": 0}

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get)

        url = reverse('signature:signature_reports')

        response = self.client.get(
            url, {
                'signature': DUMB_SIGNATURE,
                'product': ['WaterWolf', 'NightTrain'],
                'address': ['0x0', '0xa'],
                'reason': ['^hello', '$thanks'],
                'java_stack_trace': 'Exception',
            })
        eq_(response.status_code, 200)
Ejemplo n.º 12
0
    def test_topcrashers_product_sans_featured_version(self):
        def mocked_supersearch_get(**params):
            if '_columns' not in params:
                params['_columns'] = []

            # By default we range by date, so there should be no filter on
            # the build id.
            assert 'build_id' not in params

            if 'hang_type' not in params['_aggs.signature']:
                # Return results for the previous week.
                results = {'hits': [], 'facets': {'signature': []}, 'total': 0}
            else:
                # Return results for the current week.
                results = {'hits': [], 'facets': {'signature': []}, 'total': 0}

            results['hits'] = self.only_certain_columns(
                results['hits'], params['_columns'])
            return results

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get)

        response = self.client.get(self.base_url, {'product': 'SeaMonkey'})
        assert response.status_code == 302
        actual_url = self.base_url + '?product=SeaMonkey&version=9.5'
        assert actual_url in response['Location']

        response = self.client.get(self.base_url, {
            'product': 'SeaMonkey',
            'version': '9.5',
        })
        assert response.status_code == 200
Ejemplo n.º 13
0
    def test_search_results_parameters(self):
        def mocked_supersearch_get(**params):
            # Verify that all expected parameters are in the URL.
            assert 'product' in params
            assert 'WaterWolf' in params['product']
            assert 'NightTrain' in params['product']

            assert 'address' in params
            assert '0x0' in params['address']
            assert '0xa' in params['address']

            assert 'reason' in params
            assert '^hello' in params['reason']
            assert '$thanks' in params['reason']

            assert 'java_stack_trace' in params
            assert 'Exception' in params['java_stack_trace']

            return {"hits": [], "facets": "", "total": 0}

        SuperSearchUnredacted.implementation(
        ).get.side_effect = mocked_supersearch_get

        url = reverse('supersearch:search_results')

        response = self.client.get(
            url, {
                'product': ['WaterWolf', 'NightTrain'],
                'address': ['0x0', '0xa'],
                'reason': ['^hello', '$thanks'],
                'java_stack_trace': 'Exception',
            })
        assert response.status_code == 200
Ejemplo n.º 14
0
    def test_search_results_parameters(self):
        def mocked_supersearch_get(**params):
            # Verify that all expected parameters are in the URL.
            assert "product" in params
            assert "WaterWolf" in params["product"]
            assert "NightTrain" in params["product"]

            assert "address" in params
            assert "0x0" in params["address"]
            assert "0xa" in params["address"]

            assert "reason" in params
            assert "^hello" in params["reason"]
            assert "$thanks" in params["reason"]

            assert "java_stack_trace" in params
            assert "Exception" in params["java_stack_trace"]

            return {"hits": [], "facets": "", "total": 0}

        SuperSearchUnredacted.implementation(
        ).get.side_effect = mocked_supersearch_get

        url = reverse("supersearch:search_results")

        response = self.client.get(
            url,
            {
                "product": ["WaterWolf", "NightTrain"],
                "address": ["0x0", "0xa"],
                "reason": ["^hello", "$thanks"],
                "java_stack_trace": "Exception",
            },
        )
        assert response.status_code == 200
Ejemplo n.º 15
0
    def test_search_custom_parameters(self):
        self.create_custom_query_perm()

        def mocked_supersearch_get(**params):
            assert "_return_query" in params
            assert "signature" in params
            assert params["signature"] == ["nsA"]

            return {
                "query": {
                    "query": None
                },
                "indices": ["socorro200000", "socorro200001"],
            }

        SuperSearchUnredacted.implementation(
        ).get.side_effect = mocked_supersearch_get

        url = reverse("supersearch:search_custom")
        response = self.client.get(url, {"signature": "nsA"})
        assert response.status_code == 200
        assert "Run a search to get some results" in smart_text(
            response.content)
        assert "{"query": null}" in smart_text(response.content)
        assert "socorro200000" in smart_text(response.content)
        assert "socorro200001" in smart_text(response.content)
Ejemplo n.º 16
0
    def test_topcrasher_by_build(self, rpost):
        rpost.side_effect = mocked_post_123

        def mocked_supersearch_get(**params):
            ok_('build_id' in params)
            return {'hits': [], 'facets': {'signature': []}, 'total': 0}

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get)

        response = self.client.get(self.base_url, {
            'product': 'WaterWolf',
            'version': '19.0',
            '_range_type': 'build',
        })
        eq_(response.status_code, 200)

        # Test with a version that does not support builds.
        response = self.client.get(self.base_url, {
            'product': 'WaterWolf',
            'version': '18.0',
            '_range_type': 'build',
        })
        eq_(response.status_code, 200)
        ok_('versions do not support the by build date' in response.content)
        ok_('Range Type:' not in response.content)
Ejemplo n.º 17
0
    def test_signature_reports_pagination(self):
        """Test that the pagination of results works as expected.
        """

        def mocked_supersearch_get(**params):
            assert '_columns' in params

            # Make sure a negative page does not lead to negative offset value.
            # But instead it is considered as the page 1 and thus is not added.
            eq_(params.get('_results_offset'), 0)

            hits = []
            for i in range(140):
                hits.append({
                    "signature": "nsASDOMWindowEnumerator::GetNext()",
                    "date": "2017-01-31T23:12:57",
                    "uuid": i,
                    "product": "WaterWolf",
                    "version": "1.0",
                    "platform": "Linux",
                    "build_id": 888981
                })
            return {
                "hits": self.only_certain_columns(hits, params['_columns']),
                "facets": "",
                "total": len(hits)
            }

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get
        )

        url = reverse('signature:signature_reports')

        response = self.client.get(
            url,
            {
                'signature': DUMB_SIGNATURE,
                'product': ['WaterWolf'],
                '_columns': ['platform']
            }
        )

        eq_(response.status_code, 200)
        ok_('140' in response.content)

        # Check that the pagination URL contains all three expected parameters.
        doc = pyquery.PyQuery(response.content)
        next_page_url = str(doc('.pagination a').eq(0))
        ok_('product=WaterWolf' in next_page_url)
        ok_('_columns=platform' in next_page_url)
        ok_('page=2' in next_page_url)

        # Test that a negative page value does not break it.
        response = self.client.get(url, {
            'signature': DUMB_SIGNATURE,
            'page': '-1',
        })
        eq_(response.status_code, 200)
Ejemplo n.º 18
0
    def test_signature_aggregation(self):
        def mocked_supersearch_get(**params):
            assert 'signature' in params
            assert params['signature'] == ['=' + DUMB_SIGNATURE]

            assert '_facets' in params

            if 'product' in params['_facets']:
                return {
                    "hits": [],
                    "facets": {
                        "product": [
                            {
                                "term": "windows",
                                "count": 42,
                            },
                            {
                                "term": "linux",
                                "count": 1337,
                            },
                            {
                                "term": "mac",
                                "count": 3,
                            },
                        ]
                    },
                    "total": 1382
                }

            # the default
            return {
                "hits": [],
                "facets": {
                    "platform": []
                },
                "total": 0
            }

        SuperSearchUnredacted.implementation().get.side_effect = mocked_supersearch_get

        # Test with no results.
        url = reverse('signature:signature_aggregation', args=('platform',))

        response = self.client.get(url, {'signature': DUMB_SIGNATURE})
        assert response.status_code == 200
        assert 'Product' not in smart_text(response.content)
        assert 'No results were found' in smart_text(response.content)

        # Test with results.
        url = reverse('signature:signature_aggregation', args=('product',))

        response = self.client.get(url, {'signature': DUMB_SIGNATURE})
        assert response.status_code == 200
        assert 'Product' in smart_text(response.content)
        assert '1337' in smart_text(response.content)
        assert 'linux' in smart_text(response.content)
        assert str(int(1337 / 1382 * 100)) in smart_text(response.content)
        assert 'windows' in smart_text(response.content)
        assert 'mac' in smart_text(response.content)
Ejemplo n.º 19
0
    def test_SuperSearchUnredacted(self):
        def mocked_supersearch_get(**params):
            assert 'exploitability' in params
            if 'product' in params:
                assert params['product'] == ['WaterWolf', 'NightTrain']
            return {
                'hits': [{
                    'signature': 'abcdef',
                    'product': 'WaterWolf',
                    'version': '1.0',
                    'email': '*****@*****.**',
                    'exploitability': 'high',
                    'url': 'http://embarassing.website.com',
                    'user_comments': 'hey I am [email protected]',
                }],
                'facets': {
                    'signature': []
                },
                'total':
                0
            }

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get)

        url = reverse('api:model_wrapper', args=('SuperSearchUnredacted', ))
        response = self.client.get(url, {'exploitability': 'high'})
        assert response.status_code == 403
        assert response['Content-Type'] == 'application/json'
        error = json.loads(response.content)['error']
        permission = Permission.objects.get(codename='view_exploitability')
        assert permission.name in error

        # Log in to get permissions.
        user = self._login()
        self._add_permission(user, 'view_pii')
        self._add_permission(user, 'view_exploitability')

        response = self.client.get(url, {'exploitability': 'high'})
        assert response.status_code == 200
        res = json.loads(response.content)

        assert res['hits']
        assert res['facets']

        # Verify forbidden fields are exposed.
        assert 'email' in res['hits'][0]
        assert 'exploitability' in res['hits'][0]
        assert 'url' in res['hits'][0]

        # Verify user comments are not scrubbed.
        assert '*****@*****.**' in res['hits'][0]['user_comments']

        # Verify values can be lists.
        response = self.client.get(url, {
            'exploitability': 'high',
            'product': ['WaterWolf', 'NightTrain']
        })
        assert response.status_code == 200
Ejemplo n.º 20
0
    def test_SuperSearchUnredacted(self):
        def mocked_supersearch_get(**params):
            assert 'exploitability' in params
            if 'product' in params:
                assert params['product'] == ['WaterWolf', 'NightTrain']
            return {
                'hits': [
                    {
                        'signature': 'abcdef',
                        'product': 'WaterWolf',
                        'version': '1.0',
                        'email': '*****@*****.**',
                        'exploitability': 'high',
                        'url': 'http://embarassing.website.com',
                        'user_comments': 'hey I am [email protected]',
                    }
                ],
                'facets': {
                    'signature': []
                },
                'total': 0
            }

        SuperSearchUnredacted.implementation().get.side_effect = mocked_supersearch_get

        url = reverse('api:model_wrapper', args=('SuperSearchUnredacted',))
        response = self.client.get(url, {'exploitability': 'high'})
        assert response.status_code == 403
        assert response['Content-Type'] == 'application/json'
        error = json.loads(response.content)['error']
        permission = Permission.objects.get(
            codename='view_exploitability'
        )
        assert permission.name in error

        # Log in to get permissions.
        user = self._login()
        self._add_permission(user, 'view_pii')
        self._add_permission(user, 'view_exploitability')

        response = self.client.get(url, {'exploitability': 'high'})
        assert response.status_code == 200
        res = json.loads(response.content)

        assert res['hits']
        assert res['facets']

        # Verify forbidden fields are exposed.
        assert 'email' in res['hits'][0]
        assert 'exploitability' in res['hits'][0]
        assert 'url' in res['hits'][0]
        assert '*****@*****.**' in res['hits'][0]['user_comments']

        # Verify values can be lists.
        response = self.client.get(url, {
            'exploitability': 'high',
            'product': ['WaterWolf', 'NightTrain']
        })
        assert response.status_code == 200
Ejemplo n.º 21
0
    def test_signature_aggregation(self):
        def mocked_supersearch_get(**params):
            assert 'signature' in params
            assert params['signature'] == ['=' + DUMB_SIGNATURE]

            assert '_facets' in params

            if 'product' in params['_facets']:
                return {
                    "hits": [],
                    "facets": {
                        "product": [
                            {
                                "term": "windows",
                                "count": 42,
                            },
                            {
                                "term": "linux",
                                "count": 1337,
                            },
                            {
                                "term": "mac",
                                "count": 3,
                            },
                        ]
                    },
                    "total": 1382
                }

            # the default
            return {
                "hits": [],
                "facets": {
                    "platform": []
                },
                "total": 0
            }

        SuperSearchUnredacted.implementation().get.side_effect = mocked_supersearch_get

        # Test with no results.
        url = reverse('signature:signature_aggregation', args=('platform',))

        response = self.client.get(url, {'signature': DUMB_SIGNATURE})
        assert response.status_code == 200
        assert 'Product' not in smart_text(response.content)
        assert 'No results were found' in smart_text(response.content)

        # Test with results.
        url = reverse('signature:signature_aggregation', args=('product',))

        response = self.client.get(url, {'signature': DUMB_SIGNATURE})
        assert response.status_code == 200
        assert 'Product' in smart_text(response.content)
        assert '1337' in smart_text(response.content)
        assert 'linux' in smart_text(response.content)
        assert str(int(1337 / 1382 * 100)) in smart_text(response.content)
        assert 'windows' in smart_text(response.content)
        assert 'mac' in smart_text(response.content)
Ejemplo n.º 22
0
    def test_signature_comments_pagination(self):
        """Test that the pagination of comments works as expected"""
        def mocked_supersearch_get(**params):
            assert '_columns' in params

            if params.get('_results_offset') != 0:
                hits_range = range(100, 140)
            else:
                hits_range = range(100)

            hits = []
            for i in hits_range:
                hits.append({
                    "date": "2017-01-31T23:12:57",
                    "uuid": i,
                    "user_comments": "hi",
                })

            return {
                'hits': self.only_certain_columns(hits, params['_columns']),
                'total': 140
            }

        SuperSearchUnredacted.implementation().get.side_effect = mocked_supersearch_get

        user = self._login()
        user.groups.add(self._create_group_with_permission('view_pii'))
        assert user.has_perm('crashstats.view_pii')

        url = reverse('signature:signature_comments')

        response = self.client.get(
            url,
            {
                'signature': DUMB_SIGNATURE,
                'product': ['WaterWolf'],
            }
        )

        assert response.status_code == 200
        assert '140' in smart_text(response.content)
        assert '99' in smart_text(response.content)
        assert '139' not in smart_text(response.content)

        # Check that the pagination URL contains all expected parameters.
        doc = pyquery.PyQuery(response.content)
        next_page_url = str(doc('.pagination a').eq(0))
        assert 'product=WaterWolf' in next_page_url
        assert 'page=2' in next_page_url

        response = self.client.get(url, {
            'signature': DUMB_SIGNATURE,
            'page': '2',
        })
        assert response.status_code == 200
        assert '140' in smart_text(response.content)
        assert '99' not in smart_text(response.content)
        assert '139' in smart_text(response.content)
Ejemplo n.º 23
0
    def test_signature_comments_pagination(self):
        """Test that the pagination of comments works as expected. """

        def mocked_supersearch_get(**params):
            assert '_columns' in params

            if params.get('_results_offset') != 0:
                hits_range = range(100, 140)
            else:
                hits_range = range(100)

            hits = []
            for i in hits_range:
                hits.append({
                    "date": "2017-01-31T23:12:57",
                    "uuid": i,
                    "user_comments": "hi",
                })

            return {
                "hits": self.only_certain_columns(hits, params['_columns']),
                "total": 140
            }

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get
        )

        url = reverse('signature:signature_comments')

        response = self.client.get(
            url,
            {
                'signature': DUMB_SIGNATURE,
                'product': ['WaterWolf'],
            }
        )

        eq_(response.status_code, 200)
        ok_('140' in response.content)
        ok_('99' in response.content)
        ok_('139' not in response.content)

        # Check that the pagination URL contains all expected parameters.
        doc = pyquery.PyQuery(response.content)
        next_page_url = str(doc('.pagination a').eq(0))
        ok_('product=WaterWolf' in next_page_url)
        ok_('page=2' in next_page_url)

        response = self.client.get(url, {
            'signature': DUMB_SIGNATURE,
            'page': '2',
        })
        eq_(response.status_code, 200)
        ok_('140' in response.content)
        ok_('99' not in response.content)
        ok_('139' in response.content)
Ejemplo n.º 24
0
    def test_signature_comments_pagination(self):
        """Test that the pagination of comments works as expected. """

        def mocked_supersearch_get(**params):
            assert '_columns' in params

            if params.get('_results_offset') != 0:
                hits_range = range(100, 140)
            else:
                hits_range = range(100)

            hits = []
            for i in hits_range:
                hits.append({
                    "date": "2017-01-31T23:12:57",
                    "uuid": i,
                    "user_comments": "hi",
                })

            return {
                'hits': self.only_certain_columns(hits, params['_columns']),
                'total': 140
            }

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get
        )

        url = reverse('signature:signature_comments')

        response = self.client.get(
            url,
            {
                'signature': DUMB_SIGNATURE,
                'product': ['WaterWolf'],
            }
        )

        assert response.status_code == 200
        assert '140' in response.content
        assert '99' in response.content
        assert '139' not in response.content

        # Check that the pagination URL contains all expected parameters.
        doc = pyquery.PyQuery(response.content)
        next_page_url = str(doc('.pagination a').eq(0))
        assert 'product=WaterWolf' in next_page_url
        assert 'page=2' in next_page_url

        response = self.client.get(url, {
            'signature': DUMB_SIGNATURE,
            'page': '2',
        })
        assert response.status_code == 200
        assert '140' in response.content
        assert '99' not in response.content
        assert '139' in response.content
Ejemplo n.º 25
0
    def test_SuperSearchUnredacted(self):
        def mocked_supersearch_get(**params):
            assert "exploitability" in params
            if "product" in params:
                assert params["product"] == ["WaterWolf", "NightTrain"]
            return {
                "hits": [{
                    "signature": "abcdef",
                    "product": "WaterWolf",
                    "version": "1.0",
                    "email": "*****@*****.**",
                    "exploitability": "high",
                    "url": "http://embarassing.website.com",
                    "user_comments": "hey I am [email protected]",
                }],
                "facets": {
                    "signature": []
                },
                "total":
                0,
            }

        SuperSearchUnredacted.implementation(
        ).get.side_effect = mocked_supersearch_get

        url = reverse("api:model_wrapper", args=("SuperSearchUnredacted", ))
        response = self.client.get(url, {"exploitability": "high"})
        assert response.status_code == 403
        assert response["Content-Type"] == "application/json"
        error = json.loads(response.content)["error"]
        permission = Permission.objects.get(codename="view_exploitability")
        assert permission.name in error

        # Log in to get permissions.
        user = self._login()
        self._add_permission(user, "view_pii")
        self._add_permission(user, "view_exploitability")

        response = self.client.get(url, {"exploitability": "high"})
        assert response.status_code == 200
        res = json.loads(response.content)

        assert res["hits"]
        assert res["facets"]

        # Verify forbidden fields are exposed.
        assert "email" in res["hits"][0]
        assert "exploitability" in res["hits"][0]
        assert "url" in res["hits"][0]
        assert "*****@*****.**" in res["hits"][0]["user_comments"]

        # Verify values can be lists.
        response = self.client.get(url, {
            "exploitability": "high",
            "product": ["WaterWolf", "NightTrain"]
        })
        assert response.status_code == 200
Ejemplo n.º 26
0
    def test_signature_comments_pagination(self):
        """Test that the pagination of comments works as expected"""
        def mocked_supersearch_get(**params):
            assert "_columns" in params

            if params.get("_results_offset") != 0:
                hits_range = range(100, 140)
            else:
                hits_range = range(100)

            hits = []
            for i in hits_range:
                hits.append({
                    "date": "2017-01-31T23:12:57",
                    "uuid": i,
                    "user_comments": "hi"
                })

            return {
                "hits": self.only_certain_columns(hits, params["_columns"]),
                "total": 140,
            }

        SuperSearchUnredacted.implementation(
        ).get.side_effect = mocked_supersearch_get

        user = self._login()
        user.groups.add(self._create_group_with_permission("view_pii"))
        assert user.has_perm("crashstats.view_pii")

        url = reverse("signature:signature_comments")

        response = self.client.get(url, {
            "signature": DUMB_SIGNATURE,
            "product": ["WaterWolf"]
        })

        assert response.status_code == 200
        assert "140" in smart_text(response.content)
        assert "99" in smart_text(response.content)
        assert "139" not in smart_text(response.content)

        # Check that the pagination URL contains all expected parameters.
        doc = pyquery.PyQuery(response.content)
        next_page_url = str(doc(".pagination a").eq(0))
        assert "product=WaterWolf" in next_page_url
        assert "page=2" in next_page_url

        response = self.client.get(url, {
            "signature": DUMB_SIGNATURE,
            "page": "2"
        })
        assert response.status_code == 200
        assert "140" in smart_text(response.content)
        assert "99" not in smart_text(response.content)
        assert "139" in smart_text(response.content)
Ejemplo n.º 27
0
    def test_signature_summary_with_many_hexes(self):

        get_calls = []

        def mocked_get(**params):
            get_calls.append(1)

            ok_(len(params['vendor_hex']) <= 50)
            ok_(len(params['adapter_hex']) <= 50)

            return {'hits': [], 'total': 0}

        models.GraphicsDevices.implementation().get.side_effect = (mocked_get)

        def mocked_supersearch_get(**params):
            ok_('signature' in params)
            eq_(params['signature'], ['=' + DUMB_SIGNATURE])

            adapters = [{
                'term': '0x{0:0>4}'.format(i),
                'count': 1
            } for i in range(50)]
            vendors = [{
                'term': '0x{0:0>4}'.format(i),
                'count': 50,
                'facets': {
                    'adapter_device_id': adapters
                }
            } for i in range(3)]

            res = {
                'hits': [],
                'total': 4,
                'facets': {
                    'adapter_vendor_id': vendors,
                }
            }

            return res

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get)

        # Test with no results
        url = reverse('signature:signature_summary')

        response = self.client.get(
            url, {
                'signature': DUMB_SIGNATURE,
                'product': 'WaterWolf',
                'version': '1.0',
            })
        eq_(response.status_code, 200)

        # There are 150 different hexes, there should be 3 calls to the API.
        eq_(len(get_calls), 3)
Ejemplo n.º 28
0
    def test_without_any_signatures(self):
        def mocked_supersearch_get(**params):
            return {"hits": [], "facets": {"signature": []}, "total": 0}

        SuperSearchUnredacted.implementation().get.side_effect = mocked_supersearch_get

        response = self.client.get(
            self.base_url, {"product": "WaterWolf", "version": "19.0"}
        )
        assert response.status_code == 200
Ejemplo n.º 29
0
    def test_signature_aggregation(self):
        def mocked_supersearch_get(**params):
            assert "signature" in params
            assert params["signature"] == ["=" + DUMB_SIGNATURE]

            assert "_facets" in params

            if "product" in params["_facets"]:
                return {
                    "hits": [],
                    "facets": {
                        "product": [
                            {
                                "term": "windows",
                                "count": 42
                            },
                            {
                                "term": "linux",
                                "count": 1337
                            },
                            {
                                "term": "mac",
                                "count": 3
                            },
                        ]
                    },
                    "total": 1382,
                }

            # the default
            return {"hits": [], "facets": {"platform": []}, "total": 0}

        SuperSearchUnredacted.implementation(
        ).get.side_effect = mocked_supersearch_get

        # Test with no results.
        url = reverse("signature:signature_aggregation", args=("platform", ))

        response = self.client.get(url, {"signature": DUMB_SIGNATURE})
        assert response.status_code == 200
        assert "Product" not in smart_text(response.content)
        assert "No results were found" in smart_text(response.content)

        # Test with results.
        url = reverse("signature:signature_aggregation", args=("product", ))

        response = self.client.get(url, {"signature": DUMB_SIGNATURE})
        assert response.status_code == 200
        assert "Product" in smart_text(response.content)
        assert "1337" in smart_text(response.content)
        assert "linux" in smart_text(response.content)
        assert str(int(1337 / 1382 * 100)) in smart_text(response.content)
        assert "windows" in smart_text(response.content)
        assert "mac" in smart_text(response.content)
Ejemplo n.º 30
0
    def test_without_any_signatures(self):
        def mocked_supersearch_get(**params):
            return {'hits': [], 'facets': {'signature': []}, 'total': 0}

        SuperSearchUnredacted.implementation(
        ).get.side_effect = mocked_supersearch_get

        response = self.client.get(self.base_url, {
            'product': 'WaterWolf',
            'version': '19.0'
        })
        assert response.status_code == 200
Ejemplo n.º 31
0
    def test_by_build(self):
        def mocked_supersearch_get(**params):
            assert "build_id" in params
            return {"hits": [], "facets": {"signature": []}, "total": 0}

        SuperSearchUnredacted.implementation().get.side_effect = mocked_supersearch_get

        response = self.client.get(
            self.base_url,
            {"product": "WaterWolf", "version": "19.0", "_range_type": "build"},
        )
        assert response.status_code == 200
    def test_search_custom(self):
        def mocked_supersearch_get(**params):
            return None

        SuperSearchUnredacted.implementation().get.side_effect = mocked_supersearch_get

        self.create_custom_query_perm()

        url = reverse('supersearch:search_custom')
        response = self.client.get(url)
        assert response.status_code == 200
        assert 'Run a search to get some results' in smart_text(response.content)
Ejemplo n.º 33
0
    def test_search_custom(self):
        def mocked_supersearch_get(**params):
            return None

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get)

        self.create_custom_query_perm()

        url = reverse('supersearch.search_custom')
        response = self.client.get(url)
        eq_(response.status_code, 200)
        ok_('Run a search to get some results' in response.content)
Ejemplo n.º 34
0
    def test_search_results_badargumenterror(self):
        def mocked_supersearch_get(**params):
            raise BadArgumentError("<script>xss")

        SuperSearchUnredacted.implementation().get.side_effect = mocked_supersearch_get

        url = reverse("supersearch:search_results")
        params = {"product": "WaterWolf"}
        response = self.client.get(url, params, HTTP_X_REQUESTED_WITH="XMLHttpRequest")
        assert response.status_code == 400
        assert response["content-type"] == "text/html; charset=utf-8"
        assert "<script>" not in smart_text(response.content)
        assert "&lt;script&gt;" in smart_text(response.content)
Ejemplo n.º 35
0
    def test_by_build(self):
        def mocked_supersearch_get(**params):
            assert 'build_id' in params
            return {'hits': [], 'facets': {'signature': []}, 'total': 0}

        SuperSearchUnredacted.implementation(
        ).get.side_effect = mocked_supersearch_get

        response = self.client.get(self.base_url, {
            'product': 'WaterWolf',
            'version': '19.0',
            '_range_type': 'build',
        })
        assert response.status_code == 200
Ejemplo n.º 36
0
    def test_search_custom(self):

        def mocked_supersearch_get(**params):
            return None

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get
        )

        self.create_custom_query_perm()

        url = reverse('supersearch.search_custom')
        response = self.client.get(url)
        eq_(response.status_code, 200)
        ok_('Run a search to get some results' in response.content)
Ejemplo n.º 37
0
    def test_topcrashers_product_sans_featured_version(self):

        def mocked_supersearch_get(**params):
            if '_columns' not in params:
                params['_columns'] = []

            # By default we range by date, so there should be no filter on
            # the build id.
            ok_('build_id' not in params)

            if 'hang_type' not in params['_aggs.signature']:
                # Return results for the previous week.
                results = {
                    'hits': [],
                    'facets': {
                        'signature': []
                    },
                    'total': 0
                }
            else:
                # Return results for the current week.
                results = {
                    'hits': [],
                    'facets': {
                        'signature': []
                    },
                    'total': 0
                }

            results['hits'] = self.only_certain_columns(
                results['hits'],
                params['_columns']
            )
            return results
        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get
        )

        response = self.client.get(self.base_url, {'product': 'SeaMonkey'})
        eq_(response.status_code, 302)
        actual_url = self.base_url + '?product=SeaMonkey&version=9.5'
        ok_(actual_url in response['Location'])

        response = self.client.get(self.base_url, {
            'product': 'SeaMonkey',
            'version': '9.5',
        })
        eq_(response.status_code, 200)
Ejemplo n.º 38
0
    def test_product_sans_featured_version(self):
        def mocked_supersearch_get(**params):
            if '_columns' not in params:
                params['_columns'] = []

            # By default we range by date, so there should be no filter on
            # the build id.
            assert 'build_id' not in params

            if 'hang_type' not in params['_aggs.signature']:
                # Return results for the previous week.
                results = {
                    'hits': [],
                    'facets': {
                        'signature': []
                    },
                    'total': 0
                }
            else:
                # Return results for the current week.
                results = {
                    'hits': [],
                    'facets': {
                        'signature': []
                    },
                    'total': 0
                }

            results['hits'] = self.only_certain_columns(
                results['hits'],
                params['_columns']
            )
            return results

        SuperSearchUnredacted.implementation().get.side_effect = mocked_supersearch_get

        self.set_product_versions(['20.0', '19.0', '18.0'])

        # Redirects to the most recent featured version
        response = self.client.get(self.base_url, {'product': 'SeaMonkey'})
        assert response.status_code == 302
        actual_url = self.base_url + '?product=SeaMonkey&version=20.0'
        assert actual_url in response['Location']

        # This version doesn't exist, but it still renders something and
        # doesn't throw an error
        response = self.client.get(self.base_url, {'product': 'SeaMonkey', 'version': '9.5'})
        assert response.status_code == 200
Ejemplo n.º 39
0
    def test_product_sans_featured_version(self):
        def mocked_supersearch_get(**params):
            if '_columns' not in params:
                params['_columns'] = []

            # By default we range by date, so there should be no filter on
            # the build id.
            assert 'build_id' not in params

            if 'hang_type' not in params['_aggs.signature']:
                # Return results for the previous week.
                results = {
                    'hits': [],
                    'facets': {
                        'signature': []
                    },
                    'total': 0
                }
            else:
                # Return results for the current week.
                results = {
                    'hits': [],
                    'facets': {
                        'signature': []
                    },
                    'total': 0
                }

            results['hits'] = self.only_certain_columns(
                results['hits'],
                params['_columns']
            )
            return results

        SuperSearchUnredacted.implementation().get.side_effect = mocked_supersearch_get

        self.set_product_versions(['20.0', '19.0', '18.0'])

        # Redirects to the most recent featured version
        response = self.client.get(self.base_url, {'product': 'SeaMonkey'})
        assert response.status_code == 302
        actual_url = self.base_url + '?product=SeaMonkey&version=20.0'
        assert actual_url in response['Location']

        # This version doesn't exist, but it still renders something and
        # doesn't throw an error
        response = self.client.get(self.base_url, {'product': 'SeaMonkey', 'version': '9.5'})
        assert response.status_code == 200
Ejemplo n.º 40
0
    def test_search_results_parameters(self, rpost):
        def mocked_post(**options):
            assert 'bugs' in options['url'], options['url']
            return Response({
                "hits": [],
                "total": 0
            })

        rpost.side_effect = mocked_post

        def mocked_supersearch_get(**params):
            # Verify that all expected parameters are in the URL.
            ok_('product' in params)
            ok_('WaterWolf' in params['product'])
            ok_('NightTrain' in params['product'])

            ok_('address' in params)
            ok_('0x0' in params['address'])
            ok_('0xa' in params['address'])

            ok_('reason' in params)
            ok_('^hello' in params['reason'])
            ok_('$thanks' in params['reason'])

            ok_('java_stack_trace' in params)
            ok_('Exception' in params['java_stack_trace'])

            return {
                "hits": [],
                "facets": "",
                "total": 0
            }

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get
        )

        url = reverse('supersearch.search_results')

        response = self.client.get(
            url, {
                'product': ['WaterWolf', 'NightTrain'],
                'address': ['0x0', '0xa'],
                'reason': ['^hello', '$thanks'],
                'java_stack_trace': 'Exception',
            }
        )
        eq_(response.status_code, 200)
Ejemplo n.º 41
0
    def test_search_results_badargumenterror(self):
        def mocked_supersearch_get(**params):
            raise BadArgumentError('<script>xss')

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get)

        url = reverse('supersearch.search_results')
        params = {'product': 'WaterWolf'}
        response = self.client.get(url,
                                   params,
                                   HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        eq_(response.status_code, 400)
        eq_(response['content-type'], 'text/html; charset=utf-8')
        ok_('<script>' not in response.content)
        ok_('&lt;script&gt;' in response.content)
Ejemplo n.º 42
0
    def test_search_results_badargumenterror(self):

        def mocked_supersearch_get(**params):
            raise BadArgumentError('<script>xss')

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get
        )

        url = reverse('supersearch.search_results')
        params = {'product': 'WaterWolf'}
        self.client.get(url, params)
        response = self.client.get(url, params)
        eq_(response.status_code, 400)
        eq_(response['content-type'], 'text/html; charset=utf-8')
        ok_('<script>' not in response.content)
        ok_('&lt;script&gt;' in response.content)
Ejemplo n.º 43
0
    def test_without_any_signatures(self):
        def mocked_supersearch_get(**params):
            return {
                'hits': [],
                'facets': {
                    'signature': []
                },
                'total': 0
            }

        SuperSearchUnredacted.implementation().get.side_effect = mocked_supersearch_get

        response = self.client.get(self.base_url, {
            'product': 'WaterWolf',
            'version': '19.0'
        })
        assert response.status_code == 200
Ejemplo n.º 44
0
    def test_search_results_badargumenterror(self):

        def mocked_supersearch_get(**params):
            raise BadArgumentError('<script>xss')

        SuperSearchUnredacted.implementation().get.side_effect = mocked_supersearch_get

        url = reverse('supersearch:search_results')
        params = {'product': 'WaterWolf'}
        response = self.client.get(
            url,
            params,
            HTTP_X_REQUESTED_WITH='XMLHttpRequest'
        )
        assert response.status_code == 400
        assert response['content-type'] == 'text/html; charset=utf-8'
        assert '<script>' not in smart_text(response.content)
        assert '&lt;script&gt;' in smart_text(response.content)
Ejemplo n.º 45
0
    def test_signature_summary_with_many_hexes(self):
        def mocked_supersearch_get(**params):
            assert 'signature' in params
            assert params['signature'] == ['=' + DUMB_SIGNATURE]

            adapters = [
                {
                    'term': '0x{0:0>4}'.format(i),
                    'count': 1
                }
                for i in range(50)
            ]
            vendors = [
                {
                    'term': '0x{0:0>4}'.format(i),
                    'count': 50,
                    'facets': {
                        'adapter_device_id': adapters
                    }
                }
                for i in range(3)
            ]

            res = {
                'hits': [],
                'total': 4,
                'facets': {
                    'adapter_vendor_id': vendors,
                }
            }

            return res

        SuperSearchUnredacted.implementation().get.side_effect = mocked_supersearch_get

        # Test with no results
        url = reverse('signature:signature_summary')

        response = self.client.get(url, {
            'signature': DUMB_SIGNATURE,
            'product': 'WaterWolf',
            'version': '1.0',
        })
        assert response.status_code == 200
Ejemplo n.º 46
0
    def test_by_build(self):
        def mocked_supersearch_get(**params):
            assert 'build_id' in params
            return {
                'hits': [],
                'facets': {
                    'signature': []
                },
                'total': 0
            }

        SuperSearchUnredacted.implementation().get.side_effect = mocked_supersearch_get

        response = self.client.get(self.base_url, {
            'product': 'WaterWolf',
            'version': '19.0',
            '_range_type': 'build',
        })
        assert response.status_code == 200
Ejemplo n.º 47
0
    def test_topcrasher_modes(self, rpost):
        rpost.side_effect = mocked_post_123

        def mocked_supersearch_get(**params):
            return {
                'hits': [],
                'facets': {
                    'signature': []
                },
                'total': 0
            }
        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get
        )

        now = datetime.datetime.utcnow()
        today = now.replace(hour=0, minute=0, second=0, microsecond=0)

        timestr = '%Y-%m-%d %H:%M:%S'
        now = now.strftime(timestr)
        today = today.strftime(timestr)

        with freezegun.freeze_time(now, tz_offset=0):
            # By default, it returns "real-time" data.
            response = self.client.get(self.base_url, {
                'product': 'WaterWolf',
                'version': '19.0',
            })
            eq_(response.status_code, 200)
            ok_(now in response.content, now)
            ok_(today not in response.content)

            # Now test the "day time" data.
            response = self.client.get(self.base_url, {
                'product': 'WaterWolf',
                'version': '19.0',
                '_tcbs_mode': 'byday',
            })
            eq_(response.status_code, 200)
            ok_(today in response.content)
            ok_(now not in response.content)
Ejemplo n.º 48
0
    def test_parameters(self):

        def mocked_supersearch_get(**params):
            # Verify that all expected parameters are in the URL.
            ok_('product' in params)
            ok_('WaterWolf' in params['product'])
            ok_('NightTrain' in params['product'])

            ok_('address' in params)
            ok_('0x0' in params['address'])
            ok_('0xa' in params['address'])

            ok_('reason' in params)
            ok_('^hello' in params['reason'])
            ok_('$thanks' in params['reason'])

            ok_('java_stack_trace' in params)
            ok_('Exception' in params['java_stack_trace'])

            return {
                "hits": [],
                "facets": "",
                "total": 0
            }

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get
        )

        url = reverse('signature:signature_reports')

        response = self.client.get(
            url, {
                'signature': DUMB_SIGNATURE,
                'product': ['WaterWolf', 'NightTrain'],
                'address': ['0x0', '0xa'],
                'reason': ['^hello', '$thanks'],
                'java_stack_trace': 'Exception',
            }
        )
        eq_(response.status_code, 200)
Ejemplo n.º 49
0
    def test_search_results_ratelimited(self):

        def mocked_supersearch_get(**params):
            return {"hits": [], "facets": [], "total": 0}

        SuperSearchUnredacted.implementation().get.side_effect = mocked_supersearch_get

        url = reverse('supersearch:search_results')
        limit = int(re.findall(r'(\d+)', settings.RATELIMIT_SUPERSEARCH)[0])
        params = {'product': 'WaterWolf'}
        # double to avoid https://bugzilla.mozilla.org/show_bug.cgi?id=1148470
        for i in range(limit * 2):
            self.client.get(url, params)
        response = self.client.get(
            url,
            params,
            HTTP_X_REQUESTED_WITH='XMLHttpRequest'
        )
        assert response.status_code == 429
        assert smart_text(response.content) == 'Too Many Requests'
        assert response['content-type'] == 'text/plain'
Ejemplo n.º 50
0
    def test_search_results_parameters(self):

        def mocked_supersearch_get(**params):
            # Verify that all expected parameters are in the URL.
            assert 'product' in params
            assert 'WaterWolf' in params['product']
            assert 'NightTrain' in params['product']

            assert 'address' in params
            assert '0x0' in params['address']
            assert '0xa' in params['address']

            assert 'reason' in params
            assert '^hello' in params['reason']
            assert '$thanks' in params['reason']

            assert 'java_stack_trace' in params
            assert 'Exception' in params['java_stack_trace']

            return {
                "hits": [],
                "facets": "",
                "total": 0
            }

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get
        )

        url = reverse('supersearch.search_results')

        response = self.client.get(
            url, {
                'product': ['WaterWolf', 'NightTrain'],
                'address': ['0x0', '0xa'],
                'reason': ['^hello', '$thanks'],
                'java_stack_trace': 'Exception',
            }
        )
        assert response.status_code == 200
Ejemplo n.º 51
0
    def test_topcrasher_modes(self):

        def mocked_supersearch_get(**params):
            return {
                'hits': [],
                'facets': {
                    'signature': []
                },
                'total': 0
            }
        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get
        )

        now = datetime.datetime.utcnow().replace(microsecond=0)
        today = now.replace(hour=0, minute=0, second=0)

        with freezegun.freeze_time(now, tz_offset=0):
            now = now.isoformat()
            today = today.isoformat()

            # By default, it returns "real-time" data.
            response = self.client.get(self.base_url, {
                'product': 'WaterWolf',
                'version': '19.0',
            })
            assert response.status_code == 200
            assert now in response.content
            assert today not in response.content

            # Now test the "day time" data.
            response = self.client.get(self.base_url, {
                'product': 'WaterWolf',
                'version': '19.0',
                '_tcbs_mode': 'byday',
            })
            assert response.status_code == 200
            assert today in response.content
            assert now not in response.content
Ejemplo n.º 52
0
    def test_search_custom_parameters(self):
        self.create_custom_query_perm()

        def mocked_supersearch_get(**params):
            assert '_return_query' in params
            assert 'signature' in params
            assert params['signature'] == ['nsA']

            return {
                "query": {"query": None},
                "indices": ["socorro200000", "socorro200001"]
            }

        SuperSearchUnredacted.implementation().get.side_effect = mocked_supersearch_get

        url = reverse('supersearch:search_custom')
        response = self.client.get(url, {'signature': 'nsA'})
        assert response.status_code == 200
        assert 'Run a search to get some results' in smart_text(response.content)
        assert '{&#34;query&#34;: null}' in smart_text(response.content)
        assert 'socorro200000' in smart_text(response.content)
        assert 'socorro200001' in smart_text(response.content)
Ejemplo n.º 53
0
    def test_search_custom_parameters(self):
        self.create_custom_query_perm()

        def mocked_supersearch_get(**params):
            ok_('_return_query' in params)
            ok_('signature' in params)
            eq_(params['signature'], ['nsA'])

            return {
                "query": {"query": None},
                "indices": ["socorro200000", "socorro200001"]
            }

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get
        )

        url = reverse('supersearch.search_custom')
        response = self.client.get(url, {'signature': 'nsA'})
        eq_(response.status_code, 200)
        ok_('Run a search to get some results' in response.content)
        ok_('{&#34;query&#34;: null}' in response.content)
        ok_('socorro200000' in response.content)
        ok_('socorro200001' in response.content)
Ejemplo n.º 54
0
    def test_signature_summary_with_many_hexes(self):

        get_calls = []

        def mocked_get(**params):
            get_calls.append(1)

            ok_(len(params['vendor_hex']) <= 50)
            ok_(len(params['adapter_hex']) <= 50)

            return {
                'hits': [],
                'total': 0
            }

        models.GraphicsDevices.implementation().get.side_effect = (
            mocked_get
        )

        def mocked_supersearch_get(**params):
            ok_('signature' in params)
            eq_(params['signature'], ['=' + DUMB_SIGNATURE])

            adapters = [
                {
                    'term': '0x{0:0>4}'.format(i),
                    'count': 1
                }
                for i in range(50)
            ]
            vendors = [
                {
                    'term': '0x{0:0>4}'.format(i),
                    'count': 50,
                    'facets': {
                        'adapter_device_id': adapters
                    }
                }
                for i in range(3)
            ]

            res = {
                'hits': [],
                'total': 4,
                'facets': {
                    'adapter_vendor_id': vendors,
                }
            }

            return res

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get
        )

        # Test with no results
        url = reverse('signature:signature_summary')

        response = self.client.get(url, {
            'signature': DUMB_SIGNATURE,
            'product': 'WaterWolf',
            'version': '1.0',
        })
        eq_(response.status_code, 200)

        # There are 150 different hexes, there should be 3 calls to the API.
        eq_(len(get_calls), 3)
Ejemplo n.º 55
0
    def test_profile(self):

        def mocked_supersearch_get(**params):
            assert '_columns' in params
            assert '_sort' in params
            assert 'email' in params
            assert params['email'] == ['*****@*****.**']

            results = {
                'hits': [
                    {
                        'uuid': '1234abcd-ef56-7890-ab12-abcdef130802',
                        'date': '2000-01-02T00:00:00'
                    },
                    {
                        'uuid': '1234abcd-ef56-7890-ab12-abcdef130801',
                        'date': '2000-01-01T00:00:00'
                    },
                ],
                'total': 2
            }
            return results

        def mocked_supersearch_get_no_data(**params):
            assert 'email' in params
            assert params['email'] == ['*****@*****.**']

            return {
                'hits': [],
                'total': 0
            }

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get
        )

        url = reverse('profile:profile')

        # Test that the user must be signed in.
        response = self.client.get(url)
        eq_(response.status_code, 302)
        self.assertRedirects(
            response,
            reverse('crashstats:login') + '?next=%s' % url
        )

        # Now log in for the remaining tests.
        user = self._login()

        # Test with results and check email is there.
        response = self.client.get(url)
        eq_(response.status_code, 200)
        ok_('1234abcd-ef56-7890-ab12-abcdef130801' in response.content)
        ok_('1234abcd-ef56-7890-ab12-abcdef130802' in response.content)
        ok_('*****@*****.**' in response.content)

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get_no_data
        )

        # Test with no results.
        response = self.client.get(url)
        eq_(response.status_code, 200)
        ok_('*****@*****.**' in response.content)
        ok_('no crash report' in response.content)

        # Make some permissions.
        self._create_group_with_permission(
            'view_pii', 'Group A'
        )
        group_b = self._create_group_with_permission(
            'view_exploitability', 'Group B'
        )
        user.groups.add(group_b)
        assert not user.has_perm('crashstats.view_pii')
        assert user.has_perm('crashstats.view_exploitability')

        # Test permissions.
        response = self.client.get(url)
        ok_(PERMISSIONS['view_pii'] in response.content)
        ok_(PERMISSIONS['view_exploitability'] in response.content)
        doc = pyquery.PyQuery(response.content)
        for row in doc('table.permissions tbody tr'):
            cells = []
            for td in doc('td', row):
                cells.append(td.text.strip())
            if cells[0] == PERMISSIONS['view_pii']:
                eq_(cells[1], 'No')
            elif cells[0] == PERMISSIONS['view_exploitability']:
                eq_(cells[1], 'Yes!')
Ejemplo n.º 56
0
    def test_search_results_admin_mode(self, rpost):
        """Test that an admin can see more fields, and that a non-admin cannot.
        """
        def mocked_post(**options):
            assert 'bugs' in options['url'], options['url']
            return Response({"hits": [], "total": 0})

        rpost.side_effect = mocked_post

        def mocked_supersearch_get(**params):
            assert '_columns' in params

            if '_facets' in params and 'url' in params['_facets']:
                facets = {
                    "platform": [
                        {
                            "term": "Linux",
                            "count": 3
                        }
                    ],
                    "url": [
                        {
                            "term": "http://example.org",
                            "count": 3
                        }
                    ]
                }
            else:
                facets = {
                    "platform": [
                        {
                            "term": "Linux",
                            "count": 3
                        }
                    ]
                }

            results = {
                "hits": [
                    {
                        "signature": "nsASDOMWindowEnumerator::GetNext()",
                        "date": "2017-01-31T23:12:57",
                        "uuid": "aaaaaaaaaaaaa1",
                        "product": "WaterWolf",
                        "version": "1.0",
                        "platform": "Linux",
                        "build_id": 888981,
                        "email": "*****@*****.**",
                        "url": "http://example.org",
                        "exploitability": "high"
                    },
                    {
                        "signature": "mySignatureIsCool",
                        "date": "2017-01-31T23:12:57",
                        "uuid": "aaaaaaaaaaaaa2",
                        "product": "WaterWolf",
                        "version": "1.0",
                        "platform": "Linux",
                        "build_id": 888981,
                        "email": "*****@*****.**",
                        "url": "http://example.org",
                        "exploitability": "low"
                    },
                    {
                        "signature": "mineIsCoolerThanYours",
                        "date": "2017-01-31T23:12:57",
                        "uuid": "aaaaaaaaaaaaa3",
                        "product": "WaterWolf",
                        "version": "1.0",
                        "platform": "Linux",
                        "build_id": None,
                        "email": "*****@*****.**",
                        "url": "http://example.org",
                        "exploitability": "error"
                    }
                ],
                "facets": facets,
                "total": 3
            }
            results['hits'] = self.only_certain_columns(
                results['hits'],
                params['_columns']
            )
            return results

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get
        )

        url = reverse('supersearch.search_results')

        # Logged in user, can see the email field
        user = self._login()
        group = self._create_group_with_permission('view_pii')
        user.groups.add(group)

        response = self.client.get(
            url,
            {
                '_columns': ['version', 'email', 'url', 'exploitability'],
                '_facets': ['url', 'platform']
            }
        )

        eq_(response.status_code, 200)
        ok_('Email' in response.content)
        ok_('*****@*****.**' in response.content)
        ok_('Url facet' in response.content)
        ok_('http://example.org' in response.content)
        ok_('Version' in response.content)
        ok_('1.0' in response.content)

        # Without the correct permission the user cannot see exploitability.
        ok_('Exploitability' not in response.content)

        exp_group = self._create_group_with_permission('view_exploitability')
        user.groups.add(exp_group)

        response = self.client.get(
            url,
            {
                '_columns': ['version', 'email', 'url', 'exploitability'],
                '_facets': ['url', 'platform']
            }
        )

        eq_(response.status_code, 200)
        ok_('Email' in response.content)
        ok_('Exploitability' in response.content)
        ok_('high' in response.content)

        # Logged out user, cannot see the email field
        self._logout()
        response = self.client.get(
            url,
            {
                '_columns': ['version', 'email', 'url'],
                '_facets': ['url', 'platform']
            }
        )

        eq_(response.status_code, 200)
        ok_('Email' not in response.content)
        ok_('*****@*****.**' not in response.content)
        ok_('Url facet' not in response.content)
        ok_('http://example.org' not in response.content)
        ok_('Version' in response.content)
        ok_('1.0' in response.content)
Ejemplo n.º 57
0
    def test_search_results(self, cpost):
        def mocked_post(**options):
            return {
                "hits": [
                    {
                        "id": "123456",
                        "signature": u"nsASDOMWindowEnumerator::GetNext()"
                    }
                ],
                "total": 1
            }

        cpost.side_effect = mocked_post

        def mocked_supersearch_get(**params):
            assert '_columns' in params

            if 'product' in params and 'WaterWolf' in params['product']:
                results = {
                    "hits": [
                        {
                            "signature": "nsASDOMWindowEnumerator::GetNext()",
                            "date": "2017-01-31T23:12:57",
                            "uuid": "aaaaaaaaaaaaa1",
                            "product": "WaterWolf",
                            "version": "1.0",
                            "platform": "Linux",
                            "build_id": 888981
                        },
                        {
                            "signature": "mySignatureIsCool",
                            "date": "2017-01-31T23:12:57",
                            "uuid": "aaaaaaaaaaaaa2",
                            "product": "WaterWolf",
                            "version": "1.0",
                            "platform": "Linux",
                            "build_id": 888981
                        },
                        {
                            "signature": "mineIsCoolerThanYours",
                            "date": "2017-01-31T23:12:57",
                            "uuid": "aaaaaaaaaaaaa3",
                            "product": "WaterWolf",
                            "version": "1.0",
                            "platform": "Linux",
                            "build_id": None
                        },
                        {
                            "signature": "EMPTY",
                            "date": "2017-01-31T23:12:57",
                            "uuid": "aaaaaaaaaaaaa4",
                            "product": "WaterWolf",
                            "version": "1.0",
                            "platform": "Linux",
                            "build_id": None
                        }
                    ],
                    "facets": {
                        "signature": [
                            {
                                "term": "nsASDOMWindowEnumerator::GetNext()",
                                "count": 1
                            },
                            {
                                "term": "mySignatureIsCool",
                                "count": 1
                            },
                            {
                                "term": "mineIsCoolerThanYours",
                                "count": 1
                            },
                            {
                                "term": "EMPTY",
                                "count": 1
                            }
                        ]
                    },
                    "total": 4
                }
                results['hits'] = self.only_certain_columns(
                    results['hits'],
                    params['_columns']
                )
                return results
            elif 'product' in params and 'SeaMonkey' in params['product']:
                results = {
                    "hits": [
                        {
                            "signature": "nsASDOMWindowEnumerator::GetNext()",
                            "date": "2017-01-31T23:12:57",
                            "uuid": "aaaaaaaaaaaaa",
                            "product": "WaterWolf",
                            "version": "1.0",
                            "platform": "Linux",
                            "build_id": 888981
                        },
                        {
                            "signature": "mySignatureIsCool",
                            "date": "2017-01-31T23:12:57",
                            "uuid": "aaaaaaaaaaaaa",
                            "product": "WaterWolf",
                            "version": "1.0",
                            "platform": "Linux",
                            "build_id": 888981
                        }
                    ],
                    "facets": {
                        "build_id": [
                            {
                                "term": "888981",
                                "count": 2
                            }
                        ]
                    },
                    "total": 2
                }
                results['hits'] = self.only_certain_columns(
                    results['hits'],
                    params['_columns']
                )
                return results
            elif (
                'signature' in params and
                '~nsASDOMWindowEnumerator' in params['signature']
            ):
                results = {
                    "hits": [
                        {
                            "signature": "nsASDOMWindowEnumerator::GetNext()",
                            "date": "2017-01-31T23:12:57",
                            "uuid": "aaaaaaaaaaaaa",
                            "product": "WaterWolf",
                            "version": "1.0",
                            "platform": "Linux",
                            "build_id": 12345678
                        }
                    ],
                    "facets": {
                        "signature": [
                            {
                                "term": "nsASDOMWindowEnumerator::GetNext()",
                                "count": 1
                            }
                        ]
                    },
                    "total": 1
                }
                results['hits'] = self.only_certain_columns(
                    results['hits'],
                    params['_columns']
                )
                return results
            else:
                return {"hits": [], "facets": [], "total": 0}

        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get
        )

        url = reverse('supersearch.search_results')
        response = self.client.get(
            url,
            {'product': 'WaterWolf'}
        )
        eq_(response.status_code, 200)
        # Test results are existing
        ok_('table id="reports-list"' in response.content)
        ok_('nsASDOMWindowEnumerator::GetNext()' in response.content)
        ok_('mySignatureIsCool' in response.content)
        ok_('mineIsCoolerThanYours' in response.content)
        ok_('EMPTY' in response.content)
        ok_('aaaaaaaaaaaaa1' in response.content)
        ok_('888981' in response.content)
        ok_('Linux' in response.content)
        ok_('2017-01-31 23:12:57' in response.content)
        # Test facets are existing
        ok_('table id="facets-list-' in response.content)
        # Test bugs are existing
        ok_('<th scope="col">Bugs</th>' in response.content)
        ok_('123456' in response.content)
        # Test links on terms are existing
        ok_('product=%3DWaterWolf' in response.content)

        # Test with empty results
        response = self.client.get(url, {
            'product': 'NightTrain',
            'date': '2012-01-01'
        })
        eq_(response.status_code, 200)
        ok_('table id="reports-list"' not in response.content)
        ok_('No results were found' in response.content)

        # Test with a signature param
        response = self.client.get(
            url,
            {'signature': '~nsASDOMWindowEnumerator'}
        )
        eq_(response.status_code, 200)
        ok_('table id="reports-list"' in response.content)
        ok_('nsASDOMWindowEnumerator::GetNext()' in response.content)
        ok_('123456' in response.content)

        # Test with a different facet
        response = self.client.get(
            url,
            {'_facets': 'build_id', 'product': 'SeaMonkey'}
        )
        eq_(response.status_code, 200)
        ok_('table id="reports-list"' in response.content)
        ok_('table id="facets-list-' in response.content)
        ok_('888981' in response.content)
        # Bugs should not be there, they appear only in the signature facet
        ok_('<th>Bugs</th>' not in response.content)
        ok_('123456' not in response.content)

        # Test with a different columns list
        response = self.client.get(
            url,
            {'_columns': ['build_id', 'platform'], 'product': 'WaterWolf'}
        )
        eq_(response.status_code, 200)
        ok_('table id="reports-list"' in response.content)
        ok_('table id="facets-list-' in response.content)
        # The build and platform appear
        ok_('888981' in response.content)
        ok_('Linux' in response.content)
        # The crash id is always shown
        ok_('aaaaaaaaaaaaa1' in response.content)
        # The version and date do not appear
        ok_('1.0' not in response.content)
        ok_('2017' not in response.content)

        # Test missing parameters don't raise an exception.
        response = self.client.get(
            url,
            {'product': 'WaterWolf', 'date': '', 'build_id': ''}
        )
        eq_(response.status_code, 200)
Ejemplo n.º 58
0
    def test_topcrashers(self, rpost, bugs_get):

        def mocked_bugs(**options):
            return {
                "hits": [
                    {"id": 123456789,
                     "signature": "Something"},
                    {"id": 22222,
                     "signature": u"FakeSignature1 \u7684 Japanese"},
                    {"id": 33333,
                     "signature": u"FakeSignature1 \u7684 Japanese"}
                ]
            }
        bugs_get.side_effect = mocked_bugs

        def mocked_sigs(url, **options):
            if 'signature/first_date' in url:
                return Response({
                    "hits": [
                        {
                            "signature": u"FakeSignature1 \u7684 Japanese",
                            "first_date": "2000-01-01T12:23:34",
                            "first_build": "20000101122334",
                        },
                    ],
                    "total": 1
                })
            raise NotImplementedError(url)
        rpost.side_effect = mocked_sigs

        def mocked_supersearch_get(**params):
            if '_columns' not in params:
                params['_columns'] = []

            if 'hang_type' not in params['_aggs.signature']:
                # Return results for the previous week.
                results = {
                    'hits': [],
                    'facets': {
                        'signature': [{
                            'term': u'FakeSignature1 \u7684 Japanese',
                            'count': 100,
                            'facets': {
                                'platform': [{
                                    'term': 'WaterWolf',
                                    'count': 50,
                                }],
                                'is_garbage_collecting': [{
                                    'term': 't',
                                    'count': 50,
                                }],
                                'hang_type': [{
                                    'term': 1,
                                    'count': 50,
                                }],
                                'process_type': [{
                                    'term': 'plugin',
                                    'count': 50,
                                }],
                                'histogram_uptime': [{
                                    'term': 0,
                                    'count': 40,
                                }],
                            }
                        }]
                    },
                    'total': 250
                }
            else:
                # Return results for the current week.
                results = {
                    'hits': [],
                    'facets': {
                        'signature': [{
                            'term': u'FakeSignature1 \u7684 Japanese',
                            'count': 100,
                            'facets': {
                                'platform': [{
                                    'term': 'WaterWolf',
                                    'count': 50,
                                }],
                                'is_garbage_collecting': [{
                                    'term': 't',
                                    'count': 50,
                                }],
                                'hang_type': [{
                                    'term': 1,
                                    'count': 50,
                                }],
                                'process_type': [{
                                    'term': 'plugin',
                                    'count': 50,
                                }],
                                'histogram_uptime': [{
                                    'term': 0,
                                    'count': 60,
                                }],
                            }
                        }, {
                            'term': u'mozCool()',
                            'count': 80,
                            'facets': {
                                'platform': [{
                                    'term': 'WaterWolf',
                                    'count': 50,
                                }],
                                'is_garbage_collecting': [{
                                    'term': 't',
                                    'count': 50,
                                }],
                                'hang_type': [{
                                    'term': 1,
                                    'count': 50,
                                }],
                                'process_type': [{
                                    'term': 'browser',
                                    'count': 50,
                                }],
                                'histogram_uptime': [{
                                    'term': 0,
                                    'count': 40,
                                }],
                            }
                        }]
                    },
                    'total': 250
                }

            results['hits'] = self.only_certain_columns(
                results['hits'],
                params['_columns']
            )
            return results
        SuperSearchUnredacted.implementation().get.side_effect = (
            mocked_supersearch_get
        )

        url = self.base_url + '?product=WaterWolf&version=19.0'

        response = self.client.get(self.base_url, {'product': 'WaterWolf'})
        ok_(url in response['Location'])

        # Test that several versions do not raise an error.
        response = self.client.get(self.base_url, {
            'product': 'WaterWolf',
            'version': '19.0;20.0',
        })
        eq_(response.status_code, 200)

        response = self.client.get(self.base_url, {
            'product': 'WaterWolf',
            'version': '19.0',
        })
        eq_(response.status_code, 200)
        doc = pyquery.PyQuery(response.content)
        selected_count = doc('.tc-result-count a[class="selected"]')
        eq_(selected_count.text(), '50')

        # there's actually only one such TD
        bug_ids = [x.text for x in doc('td.bug_ids_more > a')]
        # higher bug number first
        eq_(bug_ids, ['33333', '22222'])

        # Check the first appearance date is there.
        ok_('2000-01-01 12:23:34' in response.content)

        response = self.client.get(self.base_url, {
            'product': 'WaterWolf',
            'version': '19.0',
            '_facets_size': '100',
        })
        eq_(response.status_code, 200)
        doc = pyquery.PyQuery(response.content)
        selected_count = doc('.tc-result-count a[class="selected"]')
        eq_(selected_count.text(), '100')

        # Check the startup crash icon is there.
        ok_('Startup Crash' in response.content)