def test_extract_payload_compressed(self, request_generator):
        data, headers = multipart_encode({
            "ProductName":
            "Firefox",
            "Version":
            "1.0",
            "upload_file_minidump":
            ("fakecrash.dump", io.BytesIO(b"abcd1234")),
        })

        data = compress(data)
        headers["Content-Encoding"] = "gzip"

        req = request_generator(method="POST",
                                path="/submit",
                                headers=headers,
                                body=data)

        bsp = BreakpadSubmitterResource(self.empty_config)
        expected_raw_crash = {
            "ProductName": "Firefox",
            "Version": "1.0",
            "payload": "multipart",
        }
        expected_dumps = {"upload_file_minidump": b"abcd1234"}
        assert bsp.extract_payload(req) == (expected_raw_crash, expected_dumps)
    def test_extract_payload_compressed(self, request_generator):
        data, headers = multipart_encode({
            'ProductName': 'Firefox',
            'Version': '1.0',
            'upload_file_minidump': ('fakecrash.dump', io.BytesIO(b'abcd1234'))
        })

        data = compress(data)
        headers['Content-Encoding'] = 'gzip'

        req = request_generator(
            method='POST',
            path='/submit',
            headers=headers,
            body=data,
        )

        bsp = BreakpadSubmitterResource(self.empty_config)
        expected_raw_crash = {
            'ProductName': 'Firefox',
            'Version': '1.0',
        }
        expected_dumps = {
            'upload_file_minidump': b'abcd1234'
        }
        assert bsp.extract_payload(req) == (expected_raw_crash, expected_dumps)
    def test_extract_payload_2_dumps(self, request_generator):
        data, headers = multipart_encode({
            'ProductName': 'Test',
            'Version': '1',
            'upload_file_minidump': ('fakecrash.dump', io.BytesIO(b'deadbeef')),
            'upload_file_minidump_flash1': ('fakecrash2.dump', io.BytesIO(b'abcd1234')),
        })

        req = request_generator(
            method='POST',
            path='/submit',
            headers=headers,
            body=data,
        )

        bsp = BreakpadSubmitterResource(self.empty_config)
        expected_raw_crash = {
            'ProductName': 'Test',
            'Version': '1',
            'dump_checksums': {
                'upload_file_minidump': '4f41243847da693a4f356c0486114bc6',
                'upload_file_minidump_flash1': 'e19d5cd5af0378da05f63f891c7467af',
            }
        }
        expected_dumps = {
            'upload_file_minidump': b'deadbeef',
            'upload_file_minidump_flash1': b'abcd1234'
        }
        assert bsp.extract_payload(req) == (expected_raw_crash, expected_dumps)
    def test_extract_payload_2_dumps(self, request_generator):
        data, headers = multipart_encode({
            'ProductName':
            'Firefox',
            'Version':
            '1',
            'upload_file_minidump':
            ('fakecrash.dump', io.BytesIO(b'deadbeef')),
            'upload_file_minidump_flash1':
            ('fakecrash2.dump', io.BytesIO(b'abcd1234')),
        })

        req = request_generator(
            method='POST',
            path='/submit',
            headers=headers,
            body=data,
        )

        bsp = BreakpadSubmitterResource(self.empty_config)
        expected_raw_crash = {
            'ProductName': 'Firefox',
            'Version': '1',
        }
        expected_dumps = {
            'upload_file_minidump': b'deadbeef',
            'upload_file_minidump_flash1': b'abcd1234'
        }
        assert bsp.extract_payload(req) == (expected_raw_crash, expected_dumps)
    def test_extract_payload_2_dumps(self, request_generator):
        data, headers = multipart_encode({
            'ProductName': 'Firefox',
            'Version': '1',
            'upload_file_minidump': ('fakecrash.dump', io.BytesIO(b'deadbeef')),
            'upload_file_minidump_flash1': ('fakecrash2.dump', io.BytesIO(b'abcd1234')),
        })

        req = request_generator(
            method='POST',
            path='/submit',
            headers=headers,
            body=data,
        )

        bsp = BreakpadSubmitterResource(self.empty_config)
        expected_raw_crash = {
            'ProductName': 'Firefox',
            'Version': '1',
        }
        expected_dumps = {
            'upload_file_minidump': b'deadbeef',
            'upload_file_minidump_flash1': b'abcd1234'
        }
        assert bsp.extract_payload(req) == (expected_raw_crash, expected_dumps)
    def test_extract_payload_2_dumps(self, request_generator):
        data, headers = multipart_encode({
            'ProductName':
            'Test',
            'Version':
            '1',
            'upload_file_minidump':
            ('fakecrash.dump', io.BytesIO(b'deadbeef')),
            'upload_file_minidump_flash1':
            ('fakecrash2.dump', io.BytesIO(b'abcd1234')),
        })

        req = request_generator(
            method='POST',
            path='/submit',
            headers=headers,
            body=data,
        )

        bsp = BreakpadSubmitterResource(self.empty_config)
        expected_raw_crash = {
            'ProductName': 'Test',
            'Version': '1',
            'dump_checksums': {
                'upload_file_minidump': '4f41243847da693a4f356c0486114bc6',
                'upload_file_minidump_flash1':
                'e19d5cd5af0378da05f63f891c7467af',
            }
        }
        expected_dumps = {
            'upload_file_minidump': b'deadbeef',
            'upload_file_minidump_flash1': b'abcd1234'
        }
        assert bsp.extract_payload(req) == (expected_raw_crash, expected_dumps)
    def test_extract_payload_compressed(self, request_generator):
        data, headers = multipart_encode({
            'ProductName':
            'Firefox',
            'Version':
            '1.0',
            'upload_file_minidump': ('fakecrash.dump', io.BytesIO(b'abcd1234'))
        })

        data = compress(data)
        headers['Content-Encoding'] = 'gzip'

        req = request_generator(
            method='POST',
            path='/submit',
            headers=headers,
            body=data,
        )

        bsp = BreakpadSubmitterResource(self.empty_config)
        expected_raw_crash = {
            'ProductName': 'Firefox',
            'Version': '1.0',
        }
        expected_dumps = {'upload_file_minidump': b'abcd1234'}
        assert bsp.extract_payload(req) == (expected_raw_crash, expected_dumps)
    def test_extract_payload_2_dumps(self, request_generator):
        data, headers = multipart_encode({
            "ProductName":
            "Firefox",
            "Version":
            "1",
            "upload_file_minidump":
            ("fakecrash.dump", io.BytesIO(b"deadbeef")),
            "upload_file_minidump_flash1": (
                "fakecrash2.dump",
                io.BytesIO(b"abcd1234"),
            ),
        })

        req = request_generator(method="POST",
                                path="/submit",
                                headers=headers,
                                body=data)

        bsp = BreakpadSubmitterResource(self.empty_config)
        expected_raw_crash = {
            "ProductName": "Firefox",
            "Version": "1",
            "payload": "multipart",
        }
        expected_dumps = {
            "upload_file_minidump": b"deadbeef",
            "upload_file_minidump_flash1": b"abcd1234",
        }
        assert bsp.extract_payload(req) == (expected_raw_crash, expected_dumps)
    def test_get_throttle_result(self):
        raw_crash = {'ProductName': 'Firefox', 'ReleaseChannel': 'nightly'}

        bsp = BreakpadSubmitterResource(self.empty_config)
        assert bsp.get_throttle_result(raw_crash) == (ACCEPT, 'is_nightly',
                                                      100)
        assert raw_crash['legacy_processing'] == ACCEPT
        assert raw_crash['throttle_rate'] == 100
    def test_get_throttle_result(self):
        raw_crash = {"ProductName": "Firefox", "ReleaseChannel": "nightly"}

        bsp = BreakpadSubmitterResource(self.empty_config)
        assert bsp.get_throttle_result(raw_crash) == (ACCEPT, "is_nightly",
                                                      100)
        assert raw_crash["legacy_processing"] == ACCEPT
        assert raw_crash["throttle_rate"] == 100
    def test_get_throttle_result(self):
        raw_crash = {
            'ProductName': 'Firefox',
            'ReleaseChannel': 'nightly'
        }

        bsp = BreakpadSubmitterResource(self.empty_config)
        assert bsp.get_throttle_result(raw_crash) == (ACCEPT, 'is_nightly', 100)
        assert raw_crash['legacy_processing'] == ACCEPT
        assert raw_crash['throttle_rate'] == 100
    def test_extract_payload_bad_content_type(self, request_generator):
        headers = {"Content-Type": "application/json"}
        req = request_generator(method="POST",
                                path="/submit",
                                headers=headers,
                                body="{}")

        bsp = BreakpadSubmitterResource(self.empty_config)
        with pytest.raises(MalformedCrashReport, match="wrong_content_type"):
            bsp.extract_payload(req)
    def test_extract_payload_with_nulls(self, data, expected_raw_crash,
                                        expected_dumps, request_generator):
        data, headers = multipart_encode(data)

        req = request_generator(
            method='POST',
            path='/submit',
            headers=headers,
            body=data,
        )

        bsp = BreakpadSubmitterResource(self.empty_config)
        assert bsp.extract_payload(req) == (expected_raw_crash, expected_dumps)
    def test_extract_payload_bad_json(self, request_generator):
        # If the JSON doesn't parse (invalid control character), it raises
        # a MalformedCrashReport
        data, headers = multipart_encode(
            {"extra": '{"ProductName":"Firefox\n"}'})
        req = request_generator(method="POST",
                                path="/submit",
                                headers=headers,
                                body=data)

        bsp = BreakpadSubmitterResource(self.empty_config)
        with pytest.raises(MalformedCrashReport, match="bad_json"):
            bsp.extract_payload(req)
    def text_extract_payload_kvpairs_and_json(self, request_generator, metricsmock):
        # If there's a JSON blob and also kv pairs, then that's a malformed
        # crash
        data, headers = multipart_encode({
            'extra': '{"ProductName":"Firefox","Version":"1.0"}',
            'BadKey': 'BadValue',
            'upload_file_minidump': ('fakecrash.dump', io.BytesIO(b'abcd1234'))
        })
        req = request_generator(
            method='POST',
            path='/submit',
            headers=headers,
            body=data,
        )

        bsp = BreakpadSubmitterResource(self.empty_config)
        with metricsmock as metrics:
            result = bsp.extract_payload(req)
            assert result == ({}, {})
            assert metrics.has_record(
                stat='malformed',
                tags=['reason:has_json_and_kv']
            )
    def text_extract_payload_kvpairs_and_json(self, request_generator,
                                              metricsmock):
        # If there's a JSON blob and also kv pairs, then that's a malformed
        # crash
        data, headers = multipart_encode({
            "extra":
            '{"ProductName":"Firefox","Version":"1.0"}',
            "BadKey":
            "BadValue",
            "upload_file_minidump":
            ("fakecrash.dump", io.BytesIO(b"abcd1234")),
        })
        req = request_generator(method="POST",
                                path="/submit",
                                headers=headers,
                                body=data)

        bsp = BreakpadSubmitterResource(self.empty_config)
        with metricsmock as metrics:
            result = bsp.extract_payload(req)
            assert result == ({}, {})
            assert metrics.has_record(stat="malformed",
                                      tags=["reason:has_json_and_kv"])
    def text_extract_payload_kvpairs_and_json(self, request_generator,
                                              metricsmock):
        # If there's a JSON blob and also kv pairs, then that's a malformed
        # crash
        data, headers = multipart_encode({
            'extra':
            '{"ProductName":"Firefox","Version":"1.0"}',
            'BadKey':
            'BadValue',
            'upload_file_minidump': ('fakecrash.dump', io.BytesIO(b'abcd1234'))
        })
        req = request_generator(
            method='POST',
            path='/submit',
            headers=headers,
            body=data,
        )

        bsp = BreakpadSubmitterResource(self.empty_config)
        with metricsmock as metrics:
            result = bsp.extract_payload(req)
            assert result == ({}, {})
            assert metrics.has_record(stat='malformed',
                                      tags=['reason:has_json_and_kv'])
    def test_get_throttle_result(self, data, expected, request_generator):
        data['ProductName'] = 'Firefox'
        data['Comments'] = 'foo bar baz'

        bsp = BreakpadSubmitterResource(self.empty_config)
        assert bsp.get_throttle_result(data) == expected
 def test_cleanup_crash_report(self, client, raw_crash, expected):
     bsp = BreakpadSubmitterResource(self.empty_config)
     bsp.cleanup_crash_report(raw_crash)
     assert raw_crash == expected