Esempio n. 1
0
    def test_healthcheck(self, mocked_elasticsearch, rget):
        searches = []

        def mocked_supersearch_get(**params):
            searches.append(params)
            eq_(params['product'], [settings.DEFAULT_PRODUCT])
            eq_(params['_results_number'], 1)
            eq_(params['_columns'], ['uuid'])
            return {
                'hits': [
                    {'uuid': '12345'},
                ],
                'facets': [],
                'total': 30002,
                'errors': [],
            }

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

        def mocked_requests_get(url, **params):
            return Response(True)

        rget.side_effect = mocked_requests_get

        url = reverse('monitoring:healthcheck')
        response = self.client.get(url)
        eq_(response.status_code, 200)
        eq_(json.loads(response.content)['ok'], True)

        assert len(searches) == 1
Esempio n. 2
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}

        SuperSearch.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)
Esempio n. 3
0
    def test_assert_supersearch_errors(self):
        searches = []

        def mocked_supersearch_get(**params):
            searches.append(params)
            eq_(params['product'], [settings.DEFAULT_PRODUCT])
            eq_(params['_results_number'], 1)
            eq_(params['_columns'], ['uuid'])
            return {
                'hits': [
                    {'uuid': '12345'},
                ],
                'facets': [],
                'total': 320,
                'errors': ['bad'],
            }

        SuperSearch.implementation().get.side_effect = (
            mocked_supersearch_get
        )
        assert_raises(
            AssertionError,
            assert_supersearch_no_errors
        )
        assert len(searches) == 1
Esempio n. 4
0
    def test_topcrasher_modes(self, rpost):
        rpost.side_effect = mocked_post_123

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

        SuperSearch.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)
Esempio n. 5
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}

        SuperSearch.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)
Esempio n. 6
0
    def test_heartbeat(self, mocked_elasticsearch, rget):
        searches = []

        def mocked_supersearch_get(**params):
            searches.append(params)
            assert params["product"] == [settings.DEFAULT_PRODUCT]
            assert params["_results_number"] == 1
            assert params["_columns"] == ["uuid"]
            return {
                "hits": [{
                    "uuid": "12345"
                }],
                "facets": [],
                "total": 30002,
                "errors": [],
            }

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

        def mocked_requests_get(url, **params):
            return Response(True)

        rget.side_effect = mocked_requests_get

        # Verify the __heartbeat__ endpoint
        url = reverse("monitoring:dockerflow_heartbeat")
        response = self.client.get(url)
        assert response.status_code == 200
        assert json.loads(response.content)["ok"] is True
        assert len(searches) == 1
Esempio n. 7
0
    def test_healthcheck(self, mocked_elasticsearch, rget):
        searches = []

        def mocked_supersearch_get(**params):
            searches.append(params)
            assert params['product'] == [settings.DEFAULT_PRODUCT]
            assert params['_results_number'] == 1
            assert params['_columns'] == ['uuid']
            return {
                'hits': [
                    {'uuid': '12345'},
                ],
                'facets': [],
                'total': 30002,
                'errors': [],
            }

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

        def mocked_requests_get(url, **params):
            return Response(True)

        rget.side_effect = mocked_requests_get

        url = reverse('monitoring:healthcheck')
        response = self.client.get(url)
        assert response.status_code == 200
        assert json.loads(response.content)['ok'] is True

        assert len(searches) == 1
Esempio n. 8
0
    def test_topcrasher_modes(self, rpost):
        rpost.side_effect = mocked_post_123

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

        SuperSearch.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)
Esempio n. 9
0
    def test_search_results_pagination(self, rpost):
        """Test that the pagination of results works as expected.
        """
        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

            # 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.
            ok_('_results_offset' not in params)

            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)
            }

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

        url = reverse('supersearch.search_results')

        response = self.client.get(url, {
            '_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)

        # Test that a negative page value does not break it.
        response = self.client.get(url, {'page': '-1'})
        eq_(response.status_code, 200)
Esempio 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.
            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)
            }

        SuperSearch.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)
Esempio n. 11
0
    def test_signature_graphs(self):
        def mocked_supersearch_get(**params):
            ok_("signature" in params)
            eq_(params["signature"], ["=" + DUMB_SIGNATURE])

            ok_("_histogram.date" in params)
            ok_("_facets" in params)

            if "product" in params["_facets"]:
                return {
                    "hits": [],
                    "total": 4,
                    "facets": {
                        "product": [{"count": 4, "term": "WaterWolf"}],
                        "histogram_date": [
                            {
                                "count": 2,
                                "term": "2015-08-05T00:00:00+00:00",
                                "facets": {"product": [{"count": 2, "term": "WaterWolf"}]},
                            },
                            {
                                "count": 2,
                                "term": "2015-08-06T00:00:00+00:00",
                                "facets": {"product": [{"count": 2, "term": "WaterWolf"}]},
                            },
                        ],
                    },
                }

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

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

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

        response = self.client.get(url, {"signature": DUMB_SIGNATURE})
        eq_(response.status_code, 200)
        ok_("application/json" in response["content-type"])
        struct = json.loads(response.content)
        ok_("aggregates" in struct)
        eq_(len(struct["aggregates"]), 0)
        ok_("term_counts" in struct)
        eq_(len(struct["term_counts"]), 0)

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

        response = self.client.get(url, {"signature": DUMB_SIGNATURE})
        eq_(response.status_code, 200)
        ok_("application/json" in response["content-type"])
        struct = json.loads(response.content)
        ok_("aggregates" in struct)
        eq_(len(struct["aggregates"]), 2)
        ok_("term_counts" in struct)
        eq_(len(struct["term_counts"]), 1)
Esempio n. 12
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
            }

        SuperSearch.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)
Esempio n. 13
0
    def test_search_custom(self):
        def mocked_supersearch_get(**params):
            return None

        SuperSearch.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)
Esempio n. 14
0
    def test_signature_aggregation(self):
        def mocked_supersearch_get(**params):
            ok_('signature' in params)
            eq_(params['signature'], ['=' + DUMB_SIGNATURE])

            ok_('_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}

        SuperSearch.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})
        eq_(response.status_code, 200)
        ok_('Product' not in response.content)
        ok_('No results were found' in response.content)

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

        response = self.client.get(url, {'signature': DUMB_SIGNATURE})
        eq_(response.status_code, 200)
        ok_('Product' in response.content)
        ok_('1337' in response.content)
        ok_('linux' in response.content)
        ok_(str(1337 / 1382 * 100) in response.content)
        ok_('windows' in response.content)
        ok_('mac' in response.content)
Esempio n. 15
0
    def test_signature_summary_with_many_hexes(self, rget):
        def mocked_get(url, params, **options):
            if '/graphics_devices' in url:
                ok_(len(params['vendor_hex']) <= 50)
                ok_(len(params['adapter_hex']) <= 50)

                return Response({'hits': [], 'total': 0})

            raise NotImplementedError(url)

        rget.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

        SuperSearch.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_(rget.call_count, 3)
Esempio n. 16
0
    def test_search_custom(self):

        def mocked_supersearch_get(**params):
            return None

        SuperSearch.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)
Esempio n. 17
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 '_results_offset' in params:
                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
            }

        SuperSearch.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)
Esempio n. 18
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
            }

        SuperSearch.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)
Esempio n. 19
0
    def test_topcrasher_without_any_signatures(self, rget, 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_get(url, params, **options):
            if '/products' in url:
                return Response("""
                {
                  "hits": [
                    {
                        "is_featured": true,
                        "throttle": 1.0,
                        "end_date": "string",
                        "start_date": "integer",
                        "build_type": "string",
                        "product": "WaterWolf",
                        "version": "19.0",
                        "has_builds": true
                    }],
                    "total": "1"
                }
                """)
            raise NotImplementedError(url)
        rget.side_effect = mocked_get

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

        response = self.client.get(self.base_url, {
            'product': 'WaterWolf',
            'version': '19.0',
        })
        eq_(response.status_code, 200)
Esempio n. 20
0
    def test_topcrasher_without_any_signatures(self, rget, 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_get(url, params, **options):
            if '/products' in url:
                return Response("""
                {
                  "hits": [
                    {
                        "is_featured": true,
                        "throttle": 1.0,
                        "end_date": "string",
                        "start_date": "integer",
                        "build_type": "string",
                        "product": "WaterWolf",
                        "version": "19.0",
                        "has_builds": true
                    }],
                    "total": "1"
                }
                """)
            raise NotImplementedError(url)
        rget.side_effect = mocked_get

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

        response = self.client.get(self.base_url, {
            'product': 'WaterWolf',
            'version': '19.0',
        })
        eq_(response.status_code, 200)
Esempio n. 21
0
    def test_search_results_ratelimited(self):
        def mocked_supersearch_get(**params):
            return {"hits": [], "facets": [], "total": 0}

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

        url = reverse('supersearch.search_results')
        limit = int(re.findall('(\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')
        eq_(response.status_code, 429)
        eq_(response.content, 'Too Many Requests')
        eq_(response['content-type'], 'text/plain')
Esempio n. 22
0
    def test_signature_aggregation(self):
        def mocked_supersearch_get(**params):
            ok_("signature" in params)
            eq_(params["signature"], ["=" + DUMB_SIGNATURE])

            ok_("_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}

        SuperSearch.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})
        eq_(response.status_code, 200)
        ok_("Product" not in response.content)
        ok_("No results were found" in response.content)

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

        response = self.client.get(url, {"signature": DUMB_SIGNATURE})
        eq_(response.status_code, 200)
        ok_("Product" in response.content)
        ok_("1337" in response.content)
        ok_("linux" in response.content)
        ok_(str(1337 / 1382 * 100) in response.content)
        ok_("windows" in response.content)
        ok_("mac" in response.content)
Esempio n. 23
0
    def test_assert_supersearch_errors(self):
        searches = []

        def mocked_supersearch_get(**params):
            searches.append(params)
            assert params["product"] == [settings.DEFAULT_PRODUCT]
            assert params["_results_number"] == 1
            assert params["_columns"] == ["uuid"]
            return {
                "hits": [{"uuid": "12345"}],
                "facets": [],
                "total": 320,
                "errors": ["bad"],
            }

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get
        with pytest.raises(AssertionError):
            assert_supersearch_no_errors()

        assert len(searches) == 1
Esempio n. 24
0
    def test_change_certain_exceptions_to_bad_request(self):

        # It actually doesn't matter so much which service we use
        # because we're heavily mocking it.
        # Here we use the SuperSearch model.

        def mocked_supersearch_get(**params):
            if params.get('product'):
                raise MissingArgumentError(params['product'])
            else:
                raise BadArgumentError('That was a bad thing to do')

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

        url = reverse('api:model_wrapper', args=('SuperSearch', ))
        response = self.client.get(url)
        assert response.status_code == 400
        assert 'That was a bad thing to do' in response.content
        response = self.client.get(url, {'product': 'foobaz'})
        assert response.status_code == 400
        assert 'foobaz' in response.content
Esempio n. 25
0
    def test_search_results_ratelimited(self):

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

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

        url = reverse('supersearch.search_results')
        limit = int(re.findall('(\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'
        )
        eq_(response.status_code, 429)
        eq_(response.content, 'Too Many Requests')
        eq_(response['content-type'], 'text/plain')
Esempio n. 26
0
    def test_change_certain_exceptions_to_bad_request(self):

        # It actually doesn't matter so much which service we use
        # because we're heavily mocking it.
        # Here we use the SuperSearch model.

        def mocked_supersearch_get(**params):
            if params.get('product'):
                raise MissingArgumentError(params['product'])
            else:
                raise BadArgumentError('That was a bad thing to do')

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

        url = reverse('api:model_wrapper', args=('SuperSearch',))
        response = self.client.get(url)
        eq_(response.status_code, 400)
        ok_('That was a bad thing to do' in response.content)
        response = self.client.get(url, {'product': 'foobaz'})
        eq_(response.status_code, 400)
        ok_('foobaz' in response.content)
Esempio n. 27
0
    def test_assert_supersearch_errors(self):
        searches = []

        def mocked_supersearch_get(**params):
            searches.append(params)
            assert params['product'] == [settings.DEFAULT_PRODUCT]
            assert params['_results_number'] == 1
            assert params['_columns'] == ['uuid']
            return {
                'hits': [
                    {'uuid': '12345'},
                ],
                'facets': [],
                'total': 320,
                'errors': ['bad'],
            }

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get
        with pytest.raises(AssertionError):
            assert_supersearch_no_errors()

        assert len(searches) == 1
Esempio n. 28
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"]
            }

        SuperSearch.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)
Esempio n. 29
0
    def test_topcrasher_modes(self, rpost):
        rpost.side_effect = mocked_post_123

        def mocked_supersearch_get(**params):
            return {
                'hits': [],
                'facets': {
                    'signature': []
                },
                'total': 0
            }
        SuperSearch.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)
Esempio n. 30
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
            }

        SuperSearch.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)
Esempio n. 31
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}

        SuperSearch.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)
Esempio n. 32
0
    def test_healthcheck(self, mocked_elasticsearch, rget):
        searches = []

        def mocked_supersearch_get(**params):
            searches.append(params)
            assert params['product'] == [settings.DEFAULT_PRODUCT]
            assert params['_results_number'] == 1
            assert params['_columns'] == ['uuid']
            return {
                'hits': [
                    {'uuid': '12345'},
                ],
                'facets': [],
                'total': 30002,
                'errors': [],
            }

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

        def mocked_requests_get(url, **params):
            return Response(True)

        rget.side_effect = mocked_requests_get

        # Verify the __heartbeat__ endpoint
        url = reverse('monitoring:dockerflow_heartbeat')
        response = self.client.get(url)
        assert response.status_code == 200
        assert json.loads(response.content)['ok'] is True
        assert len(searches) == 1

        # Verify the deprecated healthcheck endpoint
        searches = []
        url = reverse('monitoring:healthcheck')
        response = self.client.get(url)
        assert response.status_code == 200
        assert json.loads(response.content)['ok'] is True
        assert len(searches) == 1
Esempio n. 33
0
    def test_signature_summary_with_many_hexes(self, rget):
        def mocked_get(url, params, **options):
            if "/graphics_devices" in url:
                ok_(len(params["vendor_hex"]) <= 50)
                ok_(len(params["adapter_hex"]) <= 50)

                return Response({"hits": [], "total": 0})

            raise NotImplementedError(url)

        rget.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

        SuperSearch.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_(rget.call_count, 3)
Esempio n. 34
0
    def test_signature_reports(self):
        def mocked_supersearch_get(**params):
            assert '_columns' in params

            ok_('uuid' in params['_columns'])

            ok_('signature' in params)
            eq_(params['signature'], ['=' + DUMB_SIGNATURE])

            if 'product' in params:
                results = {
                    "hits": [{
                        "date": "2017-01-31T23:12:57",
                        "uuid": "aaaaaaaaaaaaa1",
                        "product": "WaterWolf",
                        "version": "1.0",
                        "platform": "Linux",
                        "build_id": 888981
                    }, {
                        "date": "2017-01-31T23:12:57",
                        "uuid": "aaaaaaaaaaaaa2",
                        "product": "WaterWolf",
                        "version": "1.0",
                        "platform": "Linux",
                        "build_id": 888981
                    }, {
                        "date": "2017-01-31T23:12:57",
                        "uuid": "aaaaaaaaaaaaa3",
                        "product": "WaterWolf",
                        "version": "1.0",
                        "platform": "Linux",
                        "build_id": None
                    }, {
                        "date": "2017-01-31T23:12:57",
                        "uuid": "aaaaaaaaaaaaa4",
                        "product": "WaterWolf",
                        "version": "1.0",
                        "platform": "Linux",
                        "build_id": None
                    }],
                    "total":
                    4
                }
                results['hits'] = self.only_certain_columns(
                    results['hits'], params['_columns'])
                return results

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

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

        url = reverse('signature:signature_reports')

        # Test with no results.
        response = self.client.get(url, {
            'signature': DUMB_SIGNATURE,
            '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 results.
        response = self.client.get(url, {
            'signature': DUMB_SIGNATURE,
            'product': 'WaterWolf'
        })
        eq_(response.status_code, 200)
        ok_('table id="reports-list"' 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 with a different columns list.
        response = self.client.get(
            url, {
                'signature': DUMB_SIGNATURE,
                'product': 'WaterWolf',
                '_columns': ['build_id', 'platform'],
            })
        eq_(response.status_code, 200)
        ok_('table id="reports-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 parameter.
        response = self.client.get(url)
        eq_(response.status_code, 400)

        response = self.client.get(url, {
            'signature': '',
        })
        eq_(response.status_code, 400)
Esempio n. 35
0
    def test_signature_summary(self, rget):
        def mocked_get(url, params, **options):
            if '/graphics_devices' in url:
                return Response({
                    'hits': [{
                        'vendor_hex': '0x0086',
                        'adapter_hex': '0x1234',
                        'vendor_name': 'Intel',
                        'adapter_name': 'Device',
                    }, {
                        'vendor_hex': '0x0086',
                        'adapter_hex': '0x1239',
                        'vendor_name': 'Intel',
                        'adapter_name': 'Other',
                    }],
                    'total':
                    2
                })

            raise NotImplementedError(url)

        rget.side_effect = mocked_get

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

            if '_aggs.product.version' in params:
                ok_('product' not in params)
                ok_('version' not in params)
            else:
                ok_('_histogram.uptime' in params)
                ok_('_facets' in params)

            res = {
                "hits": [],
                "total": 4,
                "facets": {
                    "platform_pretty_version": [{
                        "count": 4,
                        "term": "Windows 7"
                    }],
                    "cpu_name": [{
                        "count": 4,
                        "term": "x86"
                    }],
                    "process_type": [{
                        "count": 4,
                        "term": "browser"
                    }],
                    "product": [{
                        "count": 4,
                        "term": "WaterWolf",
                        "facets": {
                            "version": [{
                                "term": "2.1b99",
                                "count": 2,
                                "facets": {
                                    "cardinality_install_time": {
                                        "value": 2
                                    }
                                }
                            }, {
                                "term": "1.0",
                                "count": 2,
                                "facets": {
                                    "cardinality_install_time": {
                                        "value": 2
                                    }
                                }
                            }]
                        }
                    }],
                    "flash_version": [{
                        "count": 4,
                        "term": "1.1.1.14"
                    }],
                    "adapter_vendor_id": [{
                        "term": "0x0086",
                        "count": 4,
                        "facets": {
                            "adapter_device_id": [{
                                "term": "0x1234",
                                "count": 2,
                            }, {
                                "term": "0x1239",
                                "count": 2,
                            }]
                        }
                    }],
                    "android_cpu_abi": [{
                        "term": "armeabi-v7a",
                        "count": 4,
                        "facets": {
                            "android_manufacturer": [{
                                "term": "ZTE",
                                "count": 4,
                                "facets": {
                                    "android_model": [{
                                        "term": "roamer2",
                                        "count": 4,
                                        "facets": {
                                            "android_version": [{
                                                "term": "15",
                                                "count": 4,
                                            }]
                                        }
                                    }]
                                }
                            }]
                        }
                    }],
                    "histogram_uptime": [{
                        "count": 2,
                        "term": 0,
                    }, {
                        "count": 2,
                        "term": 60,
                    }],
                }
            }

            if '_histogram.date' in params:
                res['facets']['histogram_date'] = [{
                    "count": 2,
                    "term": "2015-08-05T00:00:00+00:00",
                    "facets": {
                        "exploitability": [{
                            "count": 2,
                            "term": "high"
                        }]
                    }
                }, {
                    "count": 2,
                    "term": "2015-08-06T00:00:00+00:00",
                    "facets": {
                        "exploitability": [{
                            "count": 2,
                            "term": "low"
                        }]
                    }
                }]

            return res

        SuperSearch.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)

        # Make sure all boxes are there.
        ok_('Operating System' in response.content)
        ok_('Uptime Range' in response.content)
        ok_('Product' in response.content)
        ok_('Architecture' in response.content)
        ok_('Process Type' in response.content)
        ok_('Mobile Devices' in response.content)
        ok_('Graphics Adapter' in response.content)
        ok_('Flash&trade; Version' in response.content)

        # Logged out users can't see no exploitability
        ok_('Exploitability' not in response.content)

        # Check that some of the expected values are there.
        ok_('Windows 7' in response.content)
        ok_('x86' in response.content)
        ok_('WaterWolf' in response.content)
        ok_('2.1b99' in response.content)
        ok_('browser' in response.content)
        ok_('1.1.1.14' in response.content)
        ok_('&lt; 1 min' in response.content)
        ok_('1-5 min' in response.content)
        ok_('ZTE' in response.content)
        ok_('Intel (0x0086)' in response.content)

        user = self._login()

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

        # Logged in users without the permission can't see no exploitability
        ok_('Exploitability' not in response.content)

        group = self._create_group_with_permission('view_exploitability')
        user.groups.add(group)
        assert user.has_perm('crashstats.view_exploitability')

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

        # Logged in users with the permission can see exploitability
        ok_('Exploitability' in response.content)
Esempio n. 36
0
    def test_signature_comments(self):
        def mocked_supersearch_get(**params):
            assert '_columns' in params

            ok_('signature' in params)
            eq_(params['signature'], ['=' + DUMB_SIGNATURE])

            ok_('user_comments' in params)
            eq_(params['user_comments'], ['!__null__'])

            if 'product' in params:
                results = {
                    "hits": [{
                        "date": "2017-01-31T23:12:57",
                        "uuid": "aaaaaaaaaaaaa1",
                        "product": "WaterWolf",
                        "version": "1.0",
                        "platform": "Linux",
                        "user_comments": "hello there people!",
                        "useragent_locale": "locale1"
                    }, {
                        "date": "2017-01-31T23:12:57",
                        "uuid": "aaaaaaaaaaaaa2",
                        "product": "WaterWolf",
                        "version": "1.0",
                        "platform": "Linux",
                        "user_comments": "I love Mozilla",
                        "useragent_locale": "locale2"
                    }, {
                        "date": "2017-01-31T23:12:57",
                        "uuid": "aaaaaaaaaaaaa3",
                        "product": "WaterWolf",
                        "version": "1.0",
                        "platform": "Linux",
                        "user_comments": "this product is awesome",
                        "useragent_locale": "locale3"
                    }, {
                        "date": "2017-01-31T23:12:57",
                        "uuid": "aaaaaaaaaaaaa4",
                        "product": "WaterWolf",
                        "version": "1.0",
                        "platform": "Linux",
                        "user_comments": "WaterWolf Y U SO GOOD?",
                        "useragent_locale": "locale4"
                    }],
                    "total":
                    4
                }
                results['hits'] = self.only_certain_columns(
                    results['hits'], params['_columns'])
                return results

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

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

        url = reverse('signature:signature_comments')

        # Test with no results.
        response = self.client.get(url, {
            'signature': DUMB_SIGNATURE,
        })
        eq_(response.status_code, 200)
        ok_('Crash ID' not in response.content)
        ok_('No comments were found' in response.content)

        # Test with results.
        response = self.client.get(url, {
            'signature': DUMB_SIGNATURE,
            'product': 'WaterWolf'
        })
        eq_(response.status_code, 200)
        ok_('aaaaaaaaaaaaa1' in response.content)
        ok_('Crash ID' in response.content)
        ok_('hello there' in response.content)
        ok_('WaterWolf Y U SO GOOD' in response.content)
        ok_('locale1' in response.content)
Esempio n. 37
0
    def test_signature_aggregation(self):

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

            ok_('_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
            }

        SuperSearch.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})
        eq_(response.status_code, 200)
        ok_('Product' not in response.content)
        ok_('No results were found' in response.content)

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

        response = self.client.get(url, {'signature': DUMB_SIGNATURE})
        eq_(response.status_code, 200)
        ok_('Product' in response.content)
        ok_('1337' in response.content)
        ok_('linux' in response.content)
        ok_(str(1337 / 1382 * 100) in response.content)
        ok_('windows' in response.content)
        ok_('mac' in response.content)
Esempio n. 38
0
    def test_NewSignatures(self):
        def mocked_supersearch_get(**params):
            assert params["product"] == [settings.DEFAULT_PRODUCT]

            if "version" in params:
                assert params["version"] == ["1.0", "2.0"]

            if "signature" not in params:
                # Return a list of signatures.
                signatures = [
                    {
                        "term": "ba",
                        "count": 21
                    },
                    {
                        "term": "zin",
                        "count": 19
                    },
                    {
                        "term": "ga",
                        "count": 1
                    },
                ]
            else:
                # Return only some of the above signatures. The missing ones
                # are "new" signatures.
                signatures = [{"term": "ga", "count": 21}]

            return {
                "hits": [],
                "facets": {
                    "signature": signatures
                },
                "total": 43829
            }

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

        url = reverse("api:model_wrapper", args=("NewSignatures", ))

        # Test we get expected results.
        response = self.client.get(url)
        assert response.status_code == 200

        res_expected = ["ba", "zin"]
        res = json.loads(response.content)
        assert res["hits"] == res_expected

        # Test with versions.
        response = self.client.get(url, {"version": ["1.0", "2.0"]})
        assert response.status_code == 200

        # Test with incorrect arguments.
        response = self.client.get(
            url,
            {
                "start_date": "not a date",
                "end_date": "not a date",
                "not_after": "not a date",
            },
        )
        assert response.status_code == 400
        assert response["Content-Type"] == "application/json; charset=UTF-8"
        res = json.loads(response.content)
        assert "errors" in res
        assert len(res["errors"]) == 3
Esempio n. 39
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}

        SuperSearch.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)

        SuperSearch.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!')
Esempio n. 40
0
    def test_SuperSearch(self):
        def mocked_supersearch_get(**params):
            assert 'exploitability' not in params

            restricted_params = (
                '_facets',
                '_aggs.signature',
                '_histogram.date',
            )
            for key in restricted_params:
                if key in params:
                    assert 'url' not in params[key]
                    assert 'email' not in params[key]
                    assert '_cardinality.email' not in params[key]

            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
            }

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

        url = reverse('api:model_wrapper', args=('SuperSearch', ))
        response = self.client.get(url)
        assert response.status_code == 200
        res = json.loads(response.content)

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

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

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

        # Verify it's not possible to use restricted parameters.
        response = self.client.get(
            url, {
                'exploitability':
                'high',
                '_facets': ['url', 'email', 'product', '_cardinality.email'],
                '_aggs.signature':
                ['url', 'email', 'product', '_cardinality.email'],
                '_histogram.date':
                ['url', 'email', 'product', '_cardinality.email'],
            })
        assert response.status_code == 200

        # Verify values can be lists.
        response = self.client.get(url,
                                   {'product': ['WaterWolf', 'NightTrain']})
        assert response.status_code == 200
Esempio n. 41
0
    def test_SuperSearch(self):
        def mocked_supersearch_get(**params):
            assert 'exploitability' not in params

            restricted_params = (
                '_facets',
                '_aggs.signature',
                '_histogram.date',
            )
            for key in restricted_params:
                if key in params:
                    assert 'url' not in params[key]
                    assert 'email' not in params[key]
                    assert '_cardinality.email' not in params[key]

            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
            }

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

        url = reverse('api:model_wrapper', args=('SuperSearch',))
        response = self.client.get(url)
        assert response.status_code == 200
        res = json.loads(response.content)

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

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

        # Verify it's not possible to use restricted parameters.
        response = self.client.get(url, {
            'exploitability': 'high',
            '_facets': ['url', 'email', 'product', '_cardinality.email'],
            '_aggs.signature': [
                'url', 'email', 'product', '_cardinality.email'
            ],
            '_histogram.date': [
                'url', 'email', 'product', '_cardinality.email'
            ],
        })
        assert response.status_code == 200

        # Verify values can be lists.
        response = self.client.get(url, {
            'product': ['WaterWolf', 'NightTrain']
        })
        assert response.status_code == 200
Esempio n. 42
0
    def test_NewSignatures(self):
        def mocked_supersearch_get(**params):
            assert params['product'] == [settings.DEFAULT_PRODUCT]

            if 'version' in params:
                assert params['version'] == ['1.0', '2.0']

            if 'signature' not in params:
                # Return a list of signatures.
                signatures = [
                    {'term': 'ba', 'count': 21},
                    {'term': 'zin', 'count': 19},
                    {'term': 'ga', 'count': 1},
                ]
            else:
                # Return only some of the above signatures. The missing ones
                # are "new" signatures.
                signatures = [
                    {'term': 'ga', 'count': 21},
                ]

            return {
                'hits': [],
                'facets': {
                    'signature': signatures
                },
                'total': 43829,
            }

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

        url = reverse('api:model_wrapper', args=('NewSignatures',))

        # Test we get expected results.
        response = self.client.get(url)
        assert response.status_code == 200

        res_expected = [
            'ba',
            'zin',
        ]
        res = json.loads(response.content)
        assert res['hits'] == res_expected

        # Test with versions.
        response = self.client.get(url, {
            'version': ['1.0', '2.0']
        })
        assert response.status_code == 200

        # Test with incorrect arguments.
        response = self.client.get(url, {
            'start_date': 'not a date',
            'end_date': 'not a date',
            'not_after': 'not a date',
        })
        assert response.status_code == 400
        assert response['Content-Type'] == 'application/json; charset=UTF-8'
        res = json.loads(response.content)
        assert 'errors' in res
        assert len(res['errors']) == 3
Esempio n. 43
0
    def test_signature_summary(self):

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

            ok_('_histogram.uptime' in params)
            ok_('_facets' in params)

            res = {
                "hits": [],
                "total": 4,
                "facets": {
                    "platform_pretty_version": [
                        {
                            "count": 4,
                            "term": "WaterWolf"
                        }
                    ],
                    "cpu_name": [
                        {
                            "count": 4,
                            "term": "x86"
                        }
                    ],
                    "process_type": [
                        {
                            "count": 4,
                            "term": "browser"
                        }
                    ],
                    "flash_version": [
                        {
                            "count": 4,
                            "term": "1.1.1.14"
                        }
                    ],
                    "histogram_uptime": [
                        {
                            "count": 2,
                            "term": 0,
                        },
                        {
                            "count": 2,
                            "term": 60,
                        }
                    ],
                }
            }

            if '_histogram.date' in params:
                res['facets']['histogram_date'] = [
                    {
                        "count": 2,
                        "term": "2015-08-05T00:00:00+00:00",
                        "facets": {
                            "exploitability": [
                                {
                                    "count": 2,
                                    "term": "high"
                                }
                            ]
                        }
                    },
                    {
                        "count": 2,
                        "term": "2015-08-06T00:00:00+00:00",
                        "facets": {
                            "exploitability": [
                                {
                                    "count": 2,
                                    "term": "low"
                                }
                            ]
                        }
                    }
                ]

            return res

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

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

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

        # Make sure all boxes are there.
        ok_('Operating System' in response.content)
        ok_('Uptime Range' in response.content)
        ok_('Architecture' in response.content)
        ok_('Process Type' in response.content)
        ok_('Flash&trade; Version' in response.content)

        # Logged out users can't see no exploitability
        ok_('Exploitability' not in response.content)

        # Check that some of the expected values are there.
        ok_('WaterWolf' in response.content)
        ok_('x86' in response.content)
        ok_('browser' in response.content)
        ok_('1.1.1.14' in response.content)
        ok_('&lt; 1 min' in response.content)
        ok_('1-5 min' in response.content)

        user = self._login()

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

        # Logged in users without the permission can't see no exploitability
        ok_('Exploitability' not in response.content)

        group = self._create_group_with_permission('view_exploitability')
        user.groups.add(group)
        assert user.has_perm('crashstats.view_exploitability')

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

        # Logged in users with the permission can see exploitability
        ok_('Exploitability' in response.content)
Esempio n. 44
0
    def test_signature_reports(self):

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

            ok_('uuid' in params['_columns'])

            ok_('signature' in params)
            eq_(params['signature'], ['=' + DUMB_SIGNATURE])

            if 'product' in params:
                results = {
                    "hits": [
                        {
                            "date": "2017-01-31T23:12:57",
                            "uuid": "aaaaaaaaaaaaa1",
                            "product": "WaterWolf",
                            "version": "1.0",
                            "platform": "Linux",
                            "build_id": 888981
                        },
                        {
                            "date": "2017-01-31T23:12:57",
                            "uuid": "aaaaaaaaaaaaa2",
                            "product": "WaterWolf",
                            "version": "1.0",
                            "platform": "Linux",
                            "build_id": 888981
                        },
                        {
                            "date": "2017-01-31T23:12:57",
                            "uuid": "aaaaaaaaaaaaa3",
                            "product": "WaterWolf",
                            "version": "1.0",
                            "platform": "Linux",
                            "build_id": None
                        },
                        {
                            "date": "2017-01-31T23:12:57",
                            "uuid": "aaaaaaaaaaaaa4",
                            "product": "WaterWolf",
                            "version": "1.0",
                            "platform": "Linux",
                            "build_id": None
                        }
                    ],
                    "total": 4
                }
                results['hits'] = self.only_certain_columns(
                    results['hits'],
                    params['_columns']
                )
                return results

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

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

        url = reverse('signature:signature_reports')

        # Test with no results.
        response = self.client.get(url, {
            'signature': DUMB_SIGNATURE,
            '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 results.
        response = self.client.get(url, {
            'signature': DUMB_SIGNATURE,
            'product': 'WaterWolf'
        })
        eq_(response.status_code, 200)
        ok_('table id="reports-list"' 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 with a different columns list.
        response = self.client.get(url, {
            'signature': DUMB_SIGNATURE,
            'product': 'WaterWolf',
            '_columns': ['build_id', 'platform'],
        })
        eq_(response.status_code, 200)
        ok_('table id="reports-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 parameter.
        response = self.client.get(url)
        eq_(response.status_code, 400)

        response = self.client.get(url, {
            'signature': '',
        })
        eq_(response.status_code, 400)
Esempio n. 45
0
    def test_signature_summary(self, rget):

        def mocked_get(url, params, **options):
            if '/graphics_devices' in url:
                return Response({
                    'hits': [
                        {
                            'vendor_hex': '0x0086',
                            'adapter_hex': '0x1234',
                            'vendor_name': 'Intel',
                            'adapter_name': 'Device',
                        },
                        {
                            'vendor_hex': '0x0086',
                            'adapter_hex': '0x1239',
                            'vendor_name': 'Intel',
                            'adapter_name': 'Other',
                        }
                    ],
                    'total': 2
                })

            raise NotImplementedError(url)

        rget.side_effect = mocked_get

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

            if '_aggs.product.version' in params:
                ok_('product' not in params)
                ok_('version' not in params)
            else:
                ok_('_histogram.uptime' in params)
                ok_('_facets' in params)

            res = {
                "hits": [],
                "total": 4,
                "facets": {
                    "platform_pretty_version": [
                        {
                            "count": 4,
                            "term": "Windows 7"
                        }
                    ],
                    "cpu_name": [
                        {
                            "count": 4,
                            "term": "x86"
                        }
                    ],
                    "process_type": [
                        {
                            "count": 4,
                            "term": "browser"
                        }
                    ],
                    "product": [
                        {
                            "count": 4,
                            "term": "WaterWolf",
                            "facets": {
                                "version": [
                                    {
                                        "term": "2.1b99",
                                        "count": 2,
                                        "facets": {
                                            "cardinality_install_time": {
                                                "value": 2
                                            }
                                        }
                                    },
                                    {
                                        "term": "1.0",
                                        "count": 2,
                                        "facets": {
                                            "cardinality_install_time": {
                                                "value": 2
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    ],
                    "flash_version": [
                        {
                            "count": 4,
                            "term": "1.1.1.14"
                        }
                    ],
                    "adapter_vendor_id": [
                        {
                            "term": "0x0086",
                            "count": 4,
                            "facets": {
                                "adapter_device_id": [
                                    {
                                        "term": "0x1234",
                                        "count": 2,
                                    },
                                    {
                                        "term": "0x1239",
                                        "count": 2,
                                    }
                                ]
                            }
                        }
                    ],
                    "android_cpu_abi": [
                        {
                            "term": "armeabi-v7a",
                            "count": 4,
                            "facets": {
                                "android_manufacturer": [
                                    {
                                        "term": "ZTE",
                                        "count": 4,
                                        "facets": {
                                            "android_model": [
                                                {
                                                    "term": "roamer2",
                                                    "count": 4,
                                                    "facets": {
                                                        "android_version": [
                                                            {
                                                                "term": "15",
                                                                "count": 4,
                                                            }
                                                        ]
                                                    }
                                                }
                                            ]
                                        }
                                    }
                                ]
                            }
                        }
                    ],
                    "histogram_uptime": [
                        {
                            "count": 2,
                            "term": 0,
                        },
                        {
                            "count": 2,
                            "term": 60,
                        }
                    ],
                }
            }

            if '_histogram.date' in params:
                res['facets']['histogram_date'] = [
                    {
                        "count": 2,
                        "term": "2015-08-05T00:00:00+00:00",
                        "facets": {
                            "exploitability": [
                                {
                                    "count": 2,
                                    "term": "high"
                                }
                            ]
                        }
                    },
                    {
                        "count": 2,
                        "term": "2015-08-06T00:00:00+00:00",
                        "facets": {
                            "exploitability": [
                                {
                                    "count": 2,
                                    "term": "low"
                                }
                            ]
                        }
                    }
                ]

            return res

        SuperSearch.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)

        # Make sure all boxes are there.
        ok_('Operating System' in response.content)
        ok_('Uptime Range' in response.content)
        ok_('Product' in response.content)
        ok_('Architecture' in response.content)
        ok_('Process Type' in response.content)
        ok_('Mobile Devices' in response.content)
        ok_('Graphics Adapter' in response.content)
        ok_('Flash&trade; Version' in response.content)

        # Logged out users can't see no exploitability
        ok_('Exploitability' not in response.content)

        # Check that some of the expected values are there.
        ok_('Windows 7' in response.content)
        ok_('x86' in response.content)
        ok_('WaterWolf' in response.content)
        ok_('2.1b99' in response.content)
        ok_('browser' in response.content)
        ok_('1.1.1.14' in response.content)
        ok_('&lt; 1 min' in response.content)
        ok_('1-5 min' in response.content)
        ok_('ZTE' in response.content)
        ok_('Intel (0x0086)' in response.content)

        user = self._login()

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

        # Logged in users without the permission can't see no exploitability
        ok_('Exploitability' not in response.content)

        group = self._create_group_with_permission('view_exploitability')
        user.groups.add(group)
        assert user.has_perm('crashstats.view_exploitability')

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

        # Logged in users with the permission can see exploitability
        ok_('Exploitability' in response.content)
Esempio n. 46
0
    def test_signature_comments(self):

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

            ok_('signature' in params)
            eq_(params['signature'], ['=' + DUMB_SIGNATURE])

            ok_('user_comments' in params)
            eq_(params['user_comments'], ['!__null__'])

            if 'product' in params:
                results = {
                    "hits": [
                        {
                            "date": "2017-01-31T23:12:57",
                            "uuid": "aaaaaaaaaaaaa1",
                            "product": "WaterWolf",
                            "version": "1.0",
                            "platform": "Linux",
                            "user_comments": "hello there people!",
                            "useragent_locale": "locale1"
                        },
                        {
                            "date": "2017-01-31T23:12:57",
                            "uuid": "aaaaaaaaaaaaa2",
                            "product": "WaterWolf",
                            "version": "1.0",
                            "platform": "Linux",
                            "user_comments": "I love Mozilla",
                            "useragent_locale": "locale2"
                        },
                        {
                            "date": "2017-01-31T23:12:57",
                            "uuid": "aaaaaaaaaaaaa3",
                            "product": "WaterWolf",
                            "version": "1.0",
                            "platform": "Linux",
                            "user_comments": "this product is awesome",
                            "useragent_locale": "locale3"
                        },
                        {
                            "date": "2017-01-31T23:12:57",
                            "uuid": "aaaaaaaaaaaaa4",
                            "product": "WaterWolf",
                            "version": "1.0",
                            "platform": "Linux",
                            "user_comments": "WaterWolf Y U SO GOOD?",
                            "useragent_locale": "locale4"
                        }
                    ],
                    "total": 4
                }
                results['hits'] = self.only_certain_columns(
                    results['hits'],
                    params['_columns']
                )
                return results

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

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

        url = reverse('signature:signature_comments')

        # Test with no results.
        response = self.client.get(url, {
            'signature': DUMB_SIGNATURE,
        })
        eq_(response.status_code, 200)
        ok_('Crash ID' not in response.content)
        ok_('No comments were found' in response.content)

        # Test with results.
        response = self.client.get(url, {
            'signature': DUMB_SIGNATURE,
            'product': 'WaterWolf'
        })
        eq_(response.status_code, 200)
        ok_('aaaaaaaaaaaaa1' in response.content)
        ok_('Crash ID' in response.content)
        ok_('hello there' in response.content)
        ok_('WaterWolf Y U SO GOOD' in response.content)
        ok_('locale1' in response.content)
Esempio n. 47
0
    def test_signature_graphs(self):

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

            ok_('_histogram.date' in params)
            ok_('_facets' in params)

            if 'product' in params['_facets']:
                return {
                    "hits": [],
                    "total": 4,
                    "facets": {
                        "product": [
                            {
                                "count": 4,
                                "term": "WaterWolf"
                            }
                        ],
                        "histogram_date": [
                            {
                                "count": 2,
                                "term": "2015-08-05T00:00:00+00:00",
                                "facets": {
                                    "product": [
                                        {
                                            "count": 2,
                                            "term": "WaterWolf"
                                        }
                                    ]
                                }
                            },
                            {
                                "count": 2,
                                "term": "2015-08-06T00:00:00+00:00",
                                "facets": {
                                    "product": [
                                        {
                                            "count": 2,
                                            "term": "WaterWolf"
                                        }
                                    ]
                                }
                            }
                        ]
                    }
                }

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

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

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

        response = self.client.get(url, {'signature': DUMB_SIGNATURE})
        eq_(response.status_code, 200)
        ok_('application/json' in response['content-type'])
        struct = json.loads(response.content)
        ok_('aggregates' in struct)
        eq_(len(struct['aggregates']), 0)
        ok_('term_counts' in struct)
        eq_(len(struct['term_counts']), 0)

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

        response = self.client.get(url, {'signature': DUMB_SIGNATURE})
        eq_(response.status_code, 200)
        ok_('application/json' in response['content-type'])
        struct = json.loads(response.content)
        ok_('aggregates' in struct)
        eq_(len(struct['aggregates']), 2)
        ok_('term_counts' in struct)
        eq_(len(struct['term_counts']), 1)
Esempio n. 48
0
    def test_graphics_report(self):
        def mocked_supersearch_get(**params):
            assert params['product'] == [settings.DEFAULT_PRODUCT]
            hits = [
                {
                    'signature': 'my signature',
                    'date': '2015-10-08T23:22:21.1234 +00:00',
                    'cpu_name': 'arm',
                    'cpu_info': 'ARMv7 ARM',
                },
                {
                    'signature': 'other signature',
                    'date': '2015-10-08T13:12:11.1123 +00:00',
                    'cpu_info': 'something',
                    # note! no cpu_name
                },
            ]
            # Value for each of these needs to be in there
            # supplement missing ones from the fixtures we intend to return.
            for hit in hits:
                for head in GRAPHICS_REPORT_HEADER:
                    if head not in hit:
                        hit[head] = None
            return {'hits': hits, 'total': 2}

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

        url = reverse('graphics:report')

        # viewing this report requires that you're signed in
        response = self.client.get(url)
        assert response.status_code == 403

        # But being signed in isn't good enough, you need the right
        # permissions too.
        user = self._login()
        response = self.client.get(url)
        assert response.status_code == 403

        # Add the user to the Hackers group which has run_long_queries
        # permission
        group = Group.objects.get(name='Hackers')
        user.groups.add(group)

        # But even with the right permissions you still need to
        # provide the right minimal parameters.
        response = self.client.get(url)
        assert response.status_code == 400

        # Let's finally get it right. Permission AND the date parameter.
        data = {'date': datetime.datetime.utcnow().date()}
        response = self.client.get(url, data)
        assert response.status_code == 200
        assert response['Content-Type'] == 'text/csv'
        assert response['Content-Length'] == str(len(response.content))

        # the response content should be parseable
        length = len(response.content)
        inp = StringIO(response.content)
        reader = csv.reader(inp, delimiter='\t')
        lines = list(reader)
        assert len(lines) == 3
        header = lines[0]
        assert header == list(GRAPHICS_REPORT_HEADER)
        first = lines[1]
        assert first[GRAPHICS_REPORT_HEADER.index(
            'signature')] == 'my signature'
        assert first[GRAPHICS_REPORT_HEADER.index(
            'date_processed')] == '201510082322'

        # now fetch it with gzip
        response = self.client.get(url, data, HTTP_ACCEPT_ENCODING='gzip')
        assert response.status_code == 200
        assert response['Content-Type'] == 'text/csv'
        assert response['Content-Length'] == str(len(response.content))
        assert response['Content-Encoding'] == 'gzip'
        assert len(response.content) < length
Esempio n. 49
0
    def test_NewSignatures(self):
        def mocked_supersearch_get(**params):
            assert params['product'] == [settings.DEFAULT_PRODUCT]

            if 'version' in params:
                assert params['version'] == ['1.0', '2.0']

            if 'signature' not in params:
                # Return a list of signatures.
                signatures = [
                    {
                        'term': 'ba',
                        'count': 21
                    },
                    {
                        'term': 'zin',
                        'count': 19
                    },
                    {
                        'term': 'ga',
                        'count': 1
                    },
                ]
            else:
                # Return only some of the above signatures. The missing ones
                # are "new" signatures.
                signatures = [
                    {
                        'term': 'ga',
                        'count': 21
                    },
                ]

            return {
                'hits': [],
                'facets': {
                    'signature': signatures
                },
                'total': 43829,
            }

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

        url = reverse('api:model_wrapper', args=('NewSignatures', ))

        # Test we get expected results.
        response = self.client.get(url)
        assert response.status_code == 200

        res_expected = [
            'ba',
            'zin',
        ]
        res = json.loads(response.content)
        assert res['hits'] == res_expected

        # Test with versions.
        response = self.client.get(url, {'version': ['1.0', '2.0']})
        assert response.status_code == 200

        # Test with incorrect arguments.
        response = self.client.get(
            url, {
                'start_date': 'not a date',
                'end_date': 'not a date',
                'not_after': 'not a date',
            })
        assert response.status_code == 400
        assert response['Content-Type'] == 'application/json; charset=UTF-8'
        res = json.loads(response.content)
        assert 'errors' in res
        assert len(res['errors']) == 3
Esempio n. 50
0
    def test_topcrashers(self, rpost):
        def mocked_post(**options):
            return {
                "hits": [{
                    "id": 123456789,
                    "signature": "Something"
                }, {
                    "id": 22222,
                    "signature": u"FakeSignature1 \u7684 Japanese"
                }, {
                    "id": 33333,
                    "signature": u"FakeSignature1 \u7684 Japanese"
                }]
            }

        rpost.side_effect = mocked_post

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

            if 'date' in params:
                # 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,
                                }],
                            }
                        }]
                    },
                    '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,
                                }],
                            }
                        }]
                    },
                    'total': 250
                }

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

        SuperSearch.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'])

        response = self.client.get(self.base_url, {
            'product': 'WaterWolf',
            'version': '19.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'])

        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')
Esempio n. 51
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

        SuperSearch.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)
Esempio n. 52
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

        SuperSearch.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)
Esempio n. 53
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}

        SuperSearch.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)
Esempio n. 54
0
    def test_signature_graphs(self):
        def mocked_supersearch_get(**params):
            ok_('signature' in params)
            eq_(params['signature'], ['=' + DUMB_SIGNATURE])

            ok_('_histogram.date' in params)
            ok_('_facets' in params)

            if 'product' in params['_facets']:
                return {
                    "hits": [],
                    "total": 4,
                    "facets": {
                        "product": [{
                            "count": 4,
                            "term": "WaterWolf"
                        }],
                        "histogram_date": [{
                            "count": 2,
                            "term": "2015-08-05T00:00:00+00:00",
                            "facets": {
                                "product": [{
                                    "count": 2,
                                    "term": "WaterWolf"
                                }]
                            }
                        }, {
                            "count": 2,
                            "term": "2015-08-06T00:00:00+00:00",
                            "facets": {
                                "product": [{
                                    "count": 2,
                                    "term": "WaterWolf"
                                }]
                            }
                        }]
                    }
                }

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

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

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

        response = self.client.get(url, {'signature': DUMB_SIGNATURE})
        eq_(response.status_code, 200)
        ok_('application/json' in response['content-type'])
        struct = json.loads(response.content)
        ok_('aggregates' in struct)
        eq_(len(struct['aggregates']), 0)
        ok_('term_counts' in struct)
        eq_(len(struct['term_counts']), 0)

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

        response = self.client.get(url, {'signature': DUMB_SIGNATURE})
        eq_(response.status_code, 200)
        ok_('application/json' in response['content-type'])
        struct = json.loads(response.content)
        ok_('aggregates' in struct)
        eq_(len(struct['aggregates']), 2)
        ok_('term_counts' in struct)
        eq_(len(struct['term_counts']), 1)
Esempio n. 55
0
    def test_SuperSearch(self):
        def mocked_supersearch_get(**params):
            assert "exploitability" not in params

            restricted_params = ("_facets", "_aggs.signature",
                                 "_histogram.date")
            for key in restricted_params:
                if key in params:
                    assert "url" not in params[key]
                    assert "email" not in params[key]
                    assert "_cardinality.email" not in params[key]

            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,
            }

        SuperSearch.implementation().get.side_effect = mocked_supersearch_get

        url = reverse("api:model_wrapper", args=("SuperSearch", ))
        response = self.client.get(url)
        assert response.status_code == 200
        res = json.loads(response.content)

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

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

        # Verify it's not possible to use restricted parameters.
        response = self.client.get(
            url,
            {
                "exploitability":
                "high",
                "_facets": ["url", "email", "product", "_cardinality.email"],
                "_aggs.signature":
                ["url", "email", "product", "_cardinality.email"],
                "_histogram.date":
                ["url", "email", "product", "_cardinality.email"],
            },
        )
        assert response.status_code == 200

        # Verify values can be lists.
        response = self.client.get(url,
                                   {"product": ["WaterWolf", "NightTrain"]})
        assert response.status_code == 200
Esempio n. 56
0
    def test_signature_summary_with_many_hexes(self, rget):

        def mocked_get(url, params, **options):
            if '/graphics_devices' in url:
                ok_(len(params['vendor_hex']) <= 50)
                ok_(len(params['adapter_hex']) <= 50)

                return Response({
                    'hits': [],
                    'total': 0
                })

            raise NotImplementedError(url)

        rget.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

        SuperSearch.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_(rget.call_count, 3)