Example #1
0
    def test_basic_postgres_save_processed_success_3_truncations(self):
        config =  DotDict()
        config.database_class = mock.MagicMock()
        config.transaction_executor_class = TransactionExecutorWithInfiniteBackoff
        config.redactor_class = mock.Mock()
        config.backoff_delays = [1]
        config.wait_log_interval = 10
        config.logger = mock.Mock()

        mocked_database_connection_source = config.database_class.return_value
        mocked_connection = (
            mocked_database_connection_source.return_value
            .__enter__.return_value
        )
        mocked_cursor = mocked_connection.cursor.return_value.__enter__.return_value

        # the call to be tested
        crashstorage = PostgreSQLCrashStorage(config)
        crashstorage.save_processed(a_processed_crash_with_everything_too_long)

        eq_(mocked_database_connection_source.call_count, 1)
        eq_(mocked_cursor.execute.call_count, 5)
        # check correct fragments

        first_call = mocked_cursor.execute.call_args_list[0]
        eq_(
            first_call[0][1],
            a_processed_report_with_everything_truncated * 2
        )
Example #2
0
    def test_basic_postgres_save_processed_success_3_truncations(self):
        config = DotDict()
        config.database_class = mock.MagicMock()
        config.transaction_executor_class = TransactionExecutorWithInfiniteBackoff
        config.redactor_class = mock.Mock()
        config.backoff_delays = [1]
        config.wait_log_interval = 10
        config.logger = mock.Mock()

        mocked_database_connection_source = config.database_class.return_value
        mocked_connection = (
            mocked_database_connection_source.return_value
            .__enter__.return_value
        )
        mocked_cursor = mocked_connection.cursor.return_value.__enter__.return_value

        # the call to be tested
        crashstorage = PostgreSQLCrashStorage(config)
        crashstorage.save_processed(a_processed_crash_with_everything_too_long)

        assert mocked_database_connection_source.call_count == 1
        assert mocked_cursor.execute.call_count == 3
        # check correct fragments

        first_call = mocked_cursor.execute.call_args_list[0]
        assert first_call[0][1] == a_processed_report_with_everything_truncated * 2
Example #3
0
    def test_basic_postgres_save_processed_success(self):
        config =  DotDict()
        config.database_class = mock.MagicMock()
        config.transaction_executor_class = TransactionExecutorWithInfiniteBackoff
        config.redactor_class = mock.Mock()
        config.backoff_delays = [1]
        config.wait_log_interval = 10
        config.logger = mock.Mock()

        mocked_database_connection_source = config.database_class.return_value
        mocked_connection = (
            mocked_database_connection_source.return_value
            .__enter__.return_value
        )
        mocked_cursor = mocked_connection.cursor.return_value.__enter__.return_value

        # the call to be tested
        crashstorage = PostgreSQLCrashStorage(config)
        crashstorage.save_processed(a_processed_crash)

        eq_(mocked_database_connection_source.call_count, 1)
        eq_(mocked_cursor.execute.call_count, 5)
        # check correct fragments
        sql_fragments = [
            "UPDATE reports_20120402",
            'select id from plugins',
            'delete from plugins_reports_20120402',
            'insert into plugins_reports_20120402',
            'UPDATE processed_crashes_20120402'
        ]
        for a_call, a_fragment in zip(mocked_cursor.execute.call_args_list, sql_fragments):
            ok_(a_fragment in a_call[0][0])
Example #4
0
    def test_basic_postgres_save_processed_success_3_truncations(self):

        mock_logging = mock.Mock()
        mock_postgres = mock.Mock()
        required_config = PostgreSQLCrashStorage.get_required_config()
        required_config.add_option('logger', default=mock_logging)

        config_manager = ConfigurationManager(
            [required_config],
            app_name='testapp',
            app_version='1.0',
            app_description='app description',
            values_source_list=[{
                'logger': mock_logging,
                'database_class': mock_postgres
            }],
            argv_source=[])

        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            with mock.patch(
                    'socorro.external.postgresql.crashstorage.single_value_sql'
            ) as mocked_sql_execute:
                fake_connection = mock.Mock(),
                crashstorage._save_processed_report(
                    fake_connection,
                    a_processed_crash_with_everything_too_long)
                mocked_sql_execute.assert_called_with(
                    fake_connection,
                    "\n        WITH\n        update_report AS (\n            UPDATE reports_20120402 SET\n                addons_checked = %s, address = %s, app_notes = %s, build = %s, client_crash_date = %s, completed_datetime = %s, cpu_info = %s, cpu_name = %s, date_processed = %s, distributor = %s, distributor_version = %s, email = %s, exploitability = %s, flash_version = %s, hangid = %s, install_age = %s, last_crash = %s, os_name = %s, os_version = %s, processor_notes = %s, process_type = %s, product = %s, productid = %s, reason = %s, release_channel = %s, signature = %s, started_datetime = %s, success = %s, topmost_filenames = %s, truncated = %s, uptime = %s, user_comments = %s, user_id = %s, url = %s, uuid = %s, version = %s\n            WHERE uuid = %s\n            RETURNING id\n        ),\n        insert_report AS (\n            INSERT INTO reports_20120402 (addons_checked, address, app_notes, build, client_crash_date, completed_datetime, cpu_info, cpu_name, date_processed, distributor, distributor_version, email, exploitability, flash_version, hangid, install_age, last_crash, os_name, os_version, processor_notes, process_type, product, productid, reason, release_channel, signature, started_datetime, success, topmost_filenames, truncated, uptime, user_comments, user_id, url, uuid, version)\n            ( SELECT\n                %s as addons_checked, %s as address, %s as app_notes, %s as build, %s as client_crash_date, %s as completed_datetime, %s as cpu_info, %s as cpu_name, %s as date_processed, %s as distributor, %s as distributor_version, %s as email, %s as exploitability, %s as flash_version, %s as hangid, %s as install_age, %s as last_crash, %s as os_name, %s as os_version, %s as processor_notes, %s as process_type, %s as product, %s as productid, %s as reason, %s as release_channel, %s as signature, %s as started_datetime, %s as success, %s as topmost_filenames, %s as truncated, %s as uptime, %s as user_comments, %s as user_id, %s as url, %s as uuid, %s as version\n                WHERE NOT EXISTS (\n                    SELECT uuid from reports_20120402\n                    WHERE\n                        uuid = %s\n                    LIMIT 1\n                )\n            )\n            RETURNING id\n        )\n        SELECT * from update_report\n        UNION ALL\n        SELECT * from insert_report\n        ",
                    a_processed_report_with_everything_truncated * 2)
Example #5
0
    def test_basic_postgres_save_processed_success(self):
        config = DotDict()
        config.database_class = mock.MagicMock()
        config.transaction_executor_class = TransactionExecutorWithInfiniteBackoff
        config.redactor_class = mock.Mock()
        config.backoff_delays = [1]
        config.wait_log_interval = 10
        config.logger = mock.Mock()

        mocked_database_connection_source = config.database_class.return_value
        mocked_connection = (mocked_database_connection_source.return_value.
                             __enter__.return_value)
        mocked_cursor = mocked_connection.cursor.return_value.__enter__.return_value

        # the call to be tested
        crashstorage = PostgreSQLCrashStorage(config)
        crashstorage.save_processed(a_processed_crash)

        eq_(mocked_database_connection_source.call_count, 1)
        eq_(mocked_cursor.execute.call_count, 5)
        # check correct fragments
        sql_fragments = [
            "UPDATE reports_20120402", 'select id from plugins',
            'delete from plugins_reports_20120402',
            'insert into plugins_reports_20120402',
            'UPDATE processed_crashes_20120402'
        ]
        for a_call, a_fragment in zip(mocked_cursor.execute.call_args_list,
                                      sql_fragments):
            ok_(a_fragment in a_call[0][0])
Example #6
0
    def test_basic_postgres_save_processed_success_3_truncations(self):

        mock_logging = mock.Mock()
        mock_postgres = mock.Mock()
        required_config = PostgreSQLCrashStorage.get_required_config()
        required_config.add_option('logger', default=mock_logging)

        config_manager = ConfigurationManager(
            [required_config],
            app_name='testapp',
            app_version='1.0',
            app_description='app description',
            values_source_list=[{
                'logger': mock_logging,
                'database_class': mock_postgres
            }],
            argv_source=[]
        )

        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            with mock.patch(
                'socorro.external.postgresql.crashstorage.single_value_sql'
            ) as mocked_sql_execute:
                fake_connection = mock.Mock(),
                crashstorage._save_processed_report(
                    fake_connection,
                    a_processed_crash_with_everything_too_long
                )
                mocked_sql_execute.assert_called_with(
                    fake_connection,
                    "\n        WITH\n        update_report AS (\n            UPDATE reports_20120402 SET\n                addons_checked = %s, address = %s, app_notes = %s, build = %s, client_crash_date = %s, completed_datetime = %s, cpu_info = %s, cpu_name = %s, date_processed = %s, distributor = %s, distributor_version = %s, email = %s, exploitability = %s, flash_version = %s, hangid = %s, install_age = %s, last_crash = %s, os_name = %s, os_version = %s, processor_notes = %s, process_type = %s, product = %s, productid = %s, reason = %s, release_channel = %s, signature = %s, started_datetime = %s, success = %s, topmost_filenames = %s, truncated = %s, uptime = %s, user_comments = %s, user_id = %s, url = %s, uuid = %s, version = %s\n            WHERE uuid = %s\n            RETURNING id\n        ),\n        insert_report AS (\n            INSERT INTO reports_20120402 (addons_checked, address, app_notes, build, client_crash_date, completed_datetime, cpu_info, cpu_name, date_processed, distributor, distributor_version, email, exploitability, flash_version, hangid, install_age, last_crash, os_name, os_version, processor_notes, process_type, product, productid, reason, release_channel, signature, started_datetime, success, topmost_filenames, truncated, uptime, user_comments, user_id, url, uuid, version)\n            ( SELECT\n                %s as addons_checked, %s as address, %s as app_notes, %s as build, %s as client_crash_date, %s as completed_datetime, %s as cpu_info, %s as cpu_name, %s as date_processed, %s as distributor, %s as distributor_version, %s as email, %s as exploitability, %s as flash_version, %s as hangid, %s as install_age, %s as last_crash, %s as os_name, %s as os_version, %s as processor_notes, %s as process_type, %s as product, %s as productid, %s as reason, %s as release_channel, %s as signature, %s as started_datetime, %s as success, %s as topmost_filenames, %s as truncated, %s as uptime, %s as user_comments, %s as user_id, %s as url, %s as uuid, %s as version\n                WHERE NOT EXISTS (\n                    SELECT uuid from reports_20120402\n                    WHERE\n                        uuid = %s\n                    LIMIT 1\n                )\n            )\n            RETURNING id\n        )\n        SELECT * from update_report\n        UNION ALL\n        SELECT * from insert_report\n        ",
                    a_processed_report_with_everything_truncated * 2
                )
Example #7
0
    def test_basic_key_error_on_save_processed(self):

        mock_logging = mock.Mock()
        mock_postgres = mock.Mock()
        required_config = PostgreSQLCrashStorage.get_required_config()
        required_config.add_option('logger', default=mock_logging)

        config_manager = ConfigurationManager(
            [required_config],
            app_name='testapp',
            app_version='1.0',
            app_description='app description',
            values_source_list=[{
                'logger': mock_logging,
                'database_class': mock_postgres
            }],
            argv_source=[])

        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            database = crashstorage.database.return_value = mock.MagicMock()
            ok_(isinstance(database, mock.Mock))

            broken_processed_crash = {
                "product": "Peter",
                "version": "1.0B3",
                "ooid": "abc123",
                "submitted_timestamp": time.time(),
                "unknown_field": 'whatever'
            }
            assert_raises(KeyError, crashstorage.save_processed,
                          broken_processed_crash)
    def test_basic_postgres_save_raw_crash(self):

        mock_logging = mock.Mock()
        mock_postgres = mock.Mock()
        required_config = PostgreSQLCrashStorage.get_required_config()
        required_config.add_option('logger', default=mock_logging)

        config_manager = ConfigurationManager(
          [required_config],
          app_name='testapp',
          app_version='1.0',
          app_description='app description',
          values_source_list=[{
            'logger': mock_logging,
            'database_class': mock_postgres
          }],
          argv_source=[]
        )

        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            database = crashstorage.database.return_value = mock.MagicMock()
            self.assertTrue(isinstance(database, mock.Mock))

            self.assertTrue('submitted_timestamp' in a_raw_crash)

            m = mock.MagicMock()
            m.__enter__.return_value = m
            database = crashstorage.database.return_value = m
            crashstorage.save_raw_crash(
                a_raw_crash,
                '',
                "936ce666-ff3b-4c7a-9674-367fe2120408"
            )
            self.assertEqual(m.cursor.call_count, 3)
            self.assertEqual(m.cursor().execute.call_count, 3)

            expected_execute_args = (
                (('savepoint MainThread', None),),
                (('insert into raw_crashes_20120402 (uuid, raw_crash, date_processed) values (%s, %s, %s)',
                     (
                         '936ce666-ff3b-4c7a-9674-367fe2120408',
                         '{"submitted_timestamp": "2012-04-08 10:52:42.0", "Version": "6.02E23", "ProductName": "Fennicky"}',
                         "2012-04-08 10:52:42.0"
                    )),),
                (('release savepoint MainThread', None),),
            )

            actual_execute_args = m.cursor().execute.call_args_list
            for expected, actual in zip(expected_execute_args,
                                        actual_execute_args):
                expeceted_sql, expected_params = expected[0]
                expeceted_sql = expeceted_sql.replace('\n', '')
                expeceted_sql = expeceted_sql.replace(' ', '')
                actual_sql, actual_params = actual[0]
                actual_sql = actual_sql.replace('\n', '')
                actual_sql = actual_sql.replace(' ', '')
                self.assertEqual(expeceted_sql, actual_sql)
                self.assertEqual(expected_params, actual_params)
Example #9
0
    def test_basic_postgres_save_processed_success(self):

        mock_logging = mock.Mock()
        mock_postgres = mock.Mock()
        required_config = PostgreSQLCrashStorage.required_config
        required_config.add_option('logger', default=mock_logging)

        config_manager = ConfigurationManager(
          [required_config],
          app_name='testapp',
          app_version='1.0',
          app_description='app description',
          values_source_list=[{
            'logger': mock_logging,
            'database_class': mock_postgres
          }]
        )

        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            database = crashstorage.database.return_value = mock.MagicMock()
            self.assertTrue(isinstance(database, mock.Mock))

            crashstorage.save_processed(a_processed_crash)

            fetch_all_returns = [((666,),), ((23,),), ]
            def fetch_all_func(*args):
                result = fetch_all_returns.pop(0)
                return result

            m = mock.MagicMock()
            m.__enter__.return_value = m
            database = crashstorage.database.return_value = m
            m.cursor.return_value.fetchall.side_effect=fetch_all_func
            crashstorage.save_processed(a_processed_crash)
            self.assertEqual(m.cursor.call_count, 6)
            self.assertEqual(m.cursor().fetchall.call_count, 2)
            self.assertEqual(m.cursor().execute.call_count, 6)

            expected_execute_args = (
                (('savepoint MainThread', None),),
                (('insert into reports_20120402 (addons_checked, address, app_notes, build, client_crash_date, completed_datetime, cpu_info, cpu_name, date_processed, distributor, distributor_version, email, exploitability, flash_version, hangid, install_age, last_crash, os_name, os_version, processor_notes, process_type, product, reason, release_channel, signature, started_datetime, success, topmost_filenames, truncated, uptime, user_comments, user_id, url, uuid, version) values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) returning id',
                     [None, '0x1c', '...', '20120309050057', '2012-04-08 10:52:42.0', '2012-04-08 10:56:50.902884', 'None | 0', 'arm', '2012-04-08 10:56:41.558922', None, None, '*****@*****.**', 'high', '[blank]', None, 22385, None, 'Linux', '0.0.0 Linux 2.6.35.7-perf-CL727859 #1 ', 'SignatureTool: signature truncated due to length', 'plugin', 'FennecAndroid', 'SIGSEGV', 'default', 'libxul.so@0x117441c', '2012-04-08 10:56:50.440752', True, [], False, 170, None, None, 'http://embarasing.p**n.com', '936ce666-ff3b-4c7a-9674-367fe2120408', '13.0a1']),),
                (('release savepoint MainThread', None),),
                (('select id from plugins where filename = %s and name = %s',
                     ('dwight.txt', 'wilma')),),
                (('insert into plugins_reports_20120402     (report_id, plugin_id, date_processed, version) values     (%s, %s, %s, %s)',
                     (666, 23, '2012-04-08 10:56:41.558922', '69')),),
                (('insert into extensions_20120402     (report_id, date_processed, extension_key, extension_id,      extension_version)values (%s, %s, %s, %s, %s)',
                     (666, '2012-04-08 10:56:41.558922', 0, '{1a5dabbd-0e74-41da-b532-a364bb552cab}', '1.0.4.1')),),
                (('release savepoint MainThread', None),),
            )

            actual_execute_args = m.cursor().execute.call_args_list
            for expected, actual in zip(expected_execute_args,
                                        actual_execute_args):
                self.assertEqual(expected, actual)
Example #10
0
    def test_save_processed(self):
        config_manager = self._setup_config_manager()
        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            # data doesn't contain an 'ooid' key
            crashstorage.save_processed(a_processed_crash)

            cursor = self.conn.cursor()
            cursor.execute('select uuid from %s' % self.reports_table_name)
            report, = cursor.fetchall()
            uuid, = report
            eq_(uuid, a_processed_crash['uuid'])
Example #11
0
    def test_save_processed(self):
        config_manager = self._setup_config_manager()
        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            # data doesn't contain an 'ooid' key
            crashstorage.save_processed(a_processed_crash)

            cursor = self.conn.cursor()
            cursor.execute('select uuid from %s' % self.reports_table_name)
            report, = cursor.fetchall()
            uuid, = report
            eq_(uuid, a_processed_crash['uuid'])
Example #12
0
    def test_basic_postgres_save_raw_crash(self):

        mock_logging = mock.Mock()
        mock_postgres = mock.Mock()
        required_config = PostgreSQLCrashStorage.get_required_config()
        required_config.add_option('logger', default=mock_logging)

        config_manager = ConfigurationManager(
            [required_config],
            app_name='testapp',
            app_version='1.0',
            app_description='app description',
            values_source_list=[{
                'logger': mock_logging,
                'database_class': mock_postgres
            }])

        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            database = crashstorage.database.return_value = mock.MagicMock()
            self.assertTrue(isinstance(database, mock.Mock))

            self.assertTrue('submitted_timestamp' in a_raw_crash)

            m = mock.MagicMock()
            m.__enter__.return_value = m
            database = crashstorage.database.return_value = m
            crashstorage.save_raw_crash(
                a_raw_crash, '', "936ce666-ff3b-4c7a-9674-367fe2120408")
            self.assertEqual(m.cursor.call_count, 3)
            self.assertEqual(m.cursor().execute.call_count, 3)

            expected_execute_args = (
                (('savepoint MainThread', None), ),
                (('insert into raw_crashes_20120402 (uuid, raw_crash, date_processed) values (%s, %s, %s)',
                  ('936ce666-ff3b-4c7a-9674-367fe2120408',
                   '{"submitted_timestamp": "2012-04-08 10:52:42.0", "Version": "6.02E23", "ProductName": "Fennicky"}',
                   "2012-04-08 10:52:42.0")), ),
                (('release savepoint MainThread', None), ),
            )

            actual_execute_args = m.cursor().execute.call_args_list
            for expected, actual in zip(expected_execute_args,
                                        actual_execute_args):
                expeceted_sql, expected_params = expected[0]
                expeceted_sql = expeceted_sql.replace('\n', '')
                expeceted_sql = expeceted_sql.replace(' ', '')
                actual_sql, actual_params = actual[0]
                actual_sql = actual_sql.replace('\n', '')
                actual_sql = actual_sql.replace(' ', '')
                self.assertEqual(expeceted_sql, actual_sql)
                self.assertEqual(expected_params, actual_params)
Example #13
0
    def test_basic_key_error_on_save_processed(self):

        mock_logging = mock.Mock()
        mock_postgres = mock.Mock()
        required_config = PostgreSQLCrashStorage.get_required_config()
        required_config.add_option('logger', default=mock_logging)

        config_manager = ConfigurationManager(
            [required_config],
            app_name='testapp',
            app_version='1.0',
            app_description='app description',
            values_source_list=[{
                'logger': mock_logging,
                'database_class': mock_postgres
            }],
            argv_source=[]
        )

        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            database = crashstorage.database.return_value = mock.MagicMock()
            ok_(isinstance(database, mock.Mock))

            broken_processed_crash = {
                "product": "Peter",
                "version": "1.0B3",
                "ooid": "abc123",
                "submitted_timestamp": time.time(),
                "unknown_field": 'whatever'
            }
            assert_raises(KeyError,
                          crashstorage.save_processed,
                          broken_processed_crash)
Example #14
0
    def test_basic_postgres_save_processed_operational_error(self):

        mock_logging = mock.Mock()
        mock_postgres = mock.Mock()

        required_config = PostgreSQLCrashStorage.get_required_config()
        required_config.add_option('logger', default=mock_logging)

        config_manager = ConfigurationManager(
            [required_config],
            app_name='testapp',
            app_version='1.0',
            app_description='app description',
            values_source_list=[{
                'logger': mock_logging,
                'database_class': mock_postgres,
                'transaction_executor_class':
                TransactionExecutorWithLimitedBackoff,
                'backoff_delays': [0, 0, 0],
            }])

        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            crashstorage.database.operational_exceptions = (OperationalError, )

            database = crashstorage.database.return_value = mock.MagicMock()
            self.assertTrue(isinstance(database, mock.Mock))

            fetch_all_returns = [
                ((666, ), ),
                None,
                ((23, ), ),
            ]

            def fetch_all_func(*args):
                result = fetch_all_returns.pop(0)
                return result

            m = mock.MagicMock()
            m.__enter__.return_value = m
            database = crashstorage.database.return_value = m
            m.cursor.side_effect = OperationalError('bad')
            self.assertRaises(OperationalError, crashstorage.save_processed,
                              a_processed_crash)
            self.assertEqual(m.cursor.call_count, 3)
Example #15
0
    def test_get_raw_crash(self):
        mock_logging = mock.Mock()
        mock_postgres = mock.Mock()
        mock_postgres.return_value = mock.MagicMock()

        required_config = PostgreSQLCrashStorage.get_required_config()
        required_config.add_option('logger', default=mock_logging)

        config_manager = ConfigurationManager(
            [required_config],
            app_name='testapp',
            app_version='1.0',
            app_description='app description',
            values_source_list=[{
                'logger': mock_logging,
                'database_class': mock_postgres,
                'transaction_executor_class':
                    TransactionExecutorWithLimitedBackoff,
                'backoff_delays': [0, 0, 0],
            }],
            argv_source=[]
        )

        with config_manager.context() as config:
            a_crash_id = "936ce666-ff3b-4c7a-9674-367fe2120408"
            crashstorage = PostgreSQLCrashStorage(config)

            connection = crashstorage.database.return_value.__enter__.return_value
            connection.cursor.return_value.__enter__.return_value.fetchall.return_value = [[
                {
                    'uuid': a_crash_id,
                }
            ]]

            a_crash = crashstorage.get_raw_crash(a_crash_id)

            assert a_crash['uuid'] == a_crash_id
            connection.cursor.return_value.__enter__.return_value.execute. \
                assert_called_with(
                    'select raw_crash from raw_crashes_20120402 where uuid = %s',
                    ('936ce666-ff3b-4c7a-9674-367fe2120408',)
                )
Example #16
0
    def test_get_raw_crash(self):
        mock_logging = mock.Mock()
        mock_postgres = mock.Mock()
        mock_postgres.return_value = mock.MagicMock()

        required_config = PostgreSQLCrashStorage.get_required_config()
        required_config.add_option('logger', default=mock_logging)

        config_manager = ConfigurationManager(
            [required_config],
            app_name='testapp',
            app_version='1.0',
            app_description='app description',
            values_source_list=[{
                'logger': mock_logging,
                'database_class': mock_postgres,
                'transaction_executor_class':
                    TransactionExecutorWithLimitedBackoff,
                'backoff_delays': [0, 0, 0],
            }],
            argv_source=[]
        )

        with config_manager.context() as config:
            a_crash_id = "936ce666-ff3b-4c7a-9674-367fe2120408"
            crashstorage = PostgreSQLCrashStorage(config)

            connection = crashstorage.database.return_value.__enter__.return_value
            connection.cursor.return_value.__enter__.return_value.fetchall.return_value = [[
                {
                    'uuid': a_crash_id,
                }
            ]]

            a_crash = crashstorage.get_raw_crash(a_crash_id)

            ok_(a_crash['uuid'] == a_crash_id)
            connection.cursor.return_value.__enter__.return_value.execute. \
                assert_called_with(
                    'select raw_crash from raw_crashes_20120402 where uuid = %s',
                    ('936ce666-ff3b-4c7a-9674-367fe2120408',)
                )
Example #17
0
    def test_postgres_save_processed_success_2(self):
        config = DotDict()
        config.database_class = mock.MagicMock()
        config.transaction_executor_class = TransactionExecutorWithInfiniteBackoff
        config.redactor_class = mock.Mock()
        config.backoff_delays = [1]
        config.wait_log_interval = 10
        config.logger = mock.Mock()

        mocked_database_connection_source = config.database_class.return_value
        mocked_connection = (mocked_database_connection_source.return_value.
                             __enter__.return_value)
        mocked_cursor = mocked_connection.cursor.return_value.__enter__.return_value
        fetch_all_returns = [
            ((666, ), ),
            None,
            ((23, ), ),
        ]

        def fetch_all_func(*args):
            result = fetch_all_returns.pop(0)
            return result

        mocked_cursor.fetchall = fetch_all_func

        # the call to be tested
        crashstorage = PostgreSQLCrashStorage(config)
        crashstorage.save_processed(a_processed_crash)

        assert mocked_database_connection_source.call_count == 1
        assert mocked_cursor.execute.call_count == 3
        # check correct fragments
        sql_fragments = [
            "UPDATE reports_20120402",
            'select id from plugins',
            'insert into plugins',
        ]
        for a_call, a_fragment in zip(mocked_cursor.execute.call_args_list,
                                      sql_fragments):
            assert a_fragment in a_call[0][0]
Example #18
0
    def test_basic_postgres_save_processed_operational_error(self):

        mock_logging = mock.Mock()
        mock_postgres = mock.Mock()

        required_config = PostgreSQLCrashStorage.get_required_config()
        required_config.add_option(
            'logger',
            default=mock_logging)

        config_manager = ConfigurationManager(
            [required_config],
            app_name='testapp',
            app_version='1.0',
            app_description='app description',
            values_source_list=[{
                'logger': mock_logging,
                'database_class': mock_postgres,
                'transaction_executor_class':
                    TransactionExecutorWithLimitedBackoff,
                'backoff_delays': [0, 0, 0],
            }],
            argv_source=[]
        )

        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            crashstorage.database.operational_exceptions = (OperationalError,)

            database = crashstorage.database.return_value = mock.MagicMock()
            assert isinstance(database, mock.Mock)

            m = mock.MagicMock()
            m.__enter__.return_value = m
            database = crashstorage.database.return_value = m
            m.cursor.side_effect = OperationalError('bad')
            with pytest.raises(OperationalError):
                crashstorage.save_processed(a_processed_crash)
            assert m.cursor.call_count == 3
Example #19
0
    def test_save_processed(self):
        mock_logging = mock.Mock()
        required_config = PostgreSQLCrashStorage.required_config
        required_config.add_option('logger', default=mock_logging)

        config_manager = ConfigurationManager(
            [required_config],
            app_name='testapp',
            app_version='1.0',
            app_description='app description',
            values_source_list=[{
                'logger': mock_logging,
            }, DSN])
        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            # data doesn't contain an 'ooid' key
            crashstorage.save_processed(a_processed_crash)

            cursor = self.conn.cursor()
            cursor.execute('select uuid from %s' % self.reports_table_name)
            report, = cursor.fetchall()
            uuid, = report
            self.assertEqual(uuid, a_processed_crash['uuid'])
Example #20
0
    def test_save_processed(self):
        mock_logging = mock.Mock()
        required_config = PostgreSQLCrashStorage.required_config
        required_config.add_option('logger', default=mock_logging)

        config_manager = ConfigurationManager(
          [required_config],
          app_name='testapp',
          app_version='1.0',
          app_description='app description',
          values_source_list=[{
            'logger': mock_logging,
            }, DSN]
        )
        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            # data doesn't contain an 'ooid' key
            crashstorage.save_processed(a_processed_crash)

            cursor = self.conn.cursor()
            cursor.execute('select uuid from %s' % self.reports_table_name)
            report, = cursor.fetchall()
            uuid, = report
            self.assertEqual(uuid, a_processed_crash['uuid'])
    def test_basic_postgres_save_processed_operational_error(self):

        mock_logging = mock.Mock()
        mock_postgres = mock.Mock()

        required_config = PostgreSQLCrashStorage.get_required_config()
        required_config.add_option('logger', default=mock_logging)

        config_manager = ConfigurationManager(
          [required_config],
          app_name='testapp',
          app_version='1.0',
          app_description='app description',
          values_source_list=[{
            'logger': mock_logging,
            'database_class': mock_postgres,
            'transaction_executor_class':
                TransactionExecutorWithLimitedBackoff,
            'backoff_delays': [0, 0, 0],
          }],
          argv_source=[]
        )

        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            crashstorage.database.operational_exceptions = (OperationalError,)

            database = crashstorage.database.return_value = mock.MagicMock()
            self.assertTrue(isinstance(database, mock.Mock))

            fetch_all_returns = [((666,),), None, ((23,),), ]
            def fetch_all_func(*args):
                result = fetch_all_returns.pop(0)
                return result

            m = mock.MagicMock()
            m.__enter__.return_value = m
            database = crashstorage.database.return_value = m
            m.cursor.side_effect = OperationalError('bad')
            self.assertRaises(OperationalError,
                              crashstorage.save_processed,
                              a_processed_crash)
            self.assertEqual(m.cursor.call_count, 3)
Example #22
0
    def test_basic_postgres_save_raw_crash(self):

        mock_logging = mock.Mock()
        mock_postgres = mock.Mock()
        required_config = PostgreSQLCrashStorage.get_required_config()
        required_config.add_option('logger', default=mock_logging)

        config_manager = ConfigurationManager(
            [required_config],
            app_name='testapp',
            app_version='1.0',
            app_description='app description',
            values_source_list=[{
                'logger': mock_logging,
                'database_class': mock_postgres
            }],
            argv_source=[]
        )

        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            database = crashstorage.database.return_value = mock.MagicMock()
            ok_(isinstance(database, mock.Mock))

            ok_('submitted_timestamp' in a_raw_crash)

            m = mock.MagicMock()
            m.__enter__.return_value = m
            database = crashstorage.database.return_value = m
            crashstorage.save_raw_crash(
                a_raw_crash,
                '',
                "936ce666-ff3b-4c7a-9674-367fe2120408"
            )
            eq_(m.cursor.call_count, 1)
            eq_(m.cursor().execute.call_count, 1)

            expected_execute_args = ((("""
                WITH update_raw_crash AS (
                    UPDATE raw_crashes_20120402 SET
                        raw_crash = %(raw_crash)s,
                        date_processed = %(date_processed)s
                    WHERE uuid = %(crash_id)s
                    RETURNING 1
                ),
                insert_raw_crash AS (
                    INSERT into raw_crashes_20120402
                    (uuid, raw_crash, date_processed)
                    ( SELECT
                        %(crash_id)s as uuid,
                        %(raw_crash)s as raw_crash,
                        %(date_processed)s as date_processed
                        WHERE NOT EXISTS (
                            SELECT uuid from raw_crashes_20120402
                            WHERE
                                uuid = %(crash_id)s
                            LIMIT 1
                        )
                    )
                    RETURNING 2
                )
                SELECT * from update_raw_crash
                UNION ALL
                SELECT * from insert_raw_crash
            """, {
                'crash_id': '936ce666-ff3b-4c7a-9674-367fe2120408',
                'raw_crash': '{"submitted_timestamp": "2012-04-08 10:52:42.0", "Version": "6.02E23", "ProductName": "Fennicky"}',
                'date_processed': "2012-04-08 10:52:42.0"
            }),),)

            actual_execute_args = m.cursor().execute.call_args_list
            for expected, actual in zip(expected_execute_args,
                                        actual_execute_args):
                expeceted_sql, expected_params = expected[0]
                expeceted_sql = remove_whitespace(expeceted_sql)
                actual_sql, actual_params = actual[0]
                actual_sql = remove_whitespace(actual_sql)
                eq_(expeceted_sql, actual_sql)
                eq_(expected_params, actual_params)
Example #23
0
    def test_basic_postgres_save_raw_crash(self):

        mock_logging = mock.Mock()
        mock_postgres = mock.Mock()
        required_config = PostgreSQLCrashStorage.get_required_config()
        required_config.add_option('logger', default=mock_logging)

        config_manager = ConfigurationManager(
            [required_config],
            app_name='testapp',
            app_version='1.0',
            app_description='app description',
            values_source_list=[{
                'logger': mock_logging,
                'database_class': mock_postgres
            }],
            argv_source=[])

        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            database = crashstorage.database.return_value = mock.MagicMock()
            ok_(isinstance(database, mock.Mock))

            ok_('submitted_timestamp' in a_raw_crash)

            m = mock.MagicMock()
            m.__enter__.return_value = m
            database = crashstorage.database.return_value = m
            crashstorage.save_raw_crash(
                a_raw_crash, '', "936ce666-ff3b-4c7a-9674-367fe2120408")
            eq_(m.cursor.call_count, 1)
            eq_(m.cursor().execute.call_count, 1)

            expected_execute_args = ((("""
                WITH update_raw_crash AS (
                    UPDATE raw_crashes_20120402 SET
                        raw_crash = %(raw_crash)s,
                        date_processed = %(date_processed)s
                    WHERE uuid = %(crash_id)s
                    RETURNING 1
                ),
                insert_raw_crash AS (
                    INSERT into raw_crashes_20120402
                    (uuid, raw_crash, date_processed)
                    ( SELECT
                        %(crash_id)s as uuid,
                        %(raw_crash)s as raw_crash,
                        %(date_processed)s as date_processed
                        WHERE NOT EXISTS (
                            SELECT uuid from raw_crashes_20120402
                            WHERE
                                uuid = %(crash_id)s
                            LIMIT 1
                        )
                    )
                    RETURNING 2
                )
                SELECT * from update_raw_crash
                UNION ALL
                SELECT * from insert_raw_crash
            """, {
                'crash_id':
                '936ce666-ff3b-4c7a-9674-367fe2120408',
                'raw_crash':
                '{"submitted_timestamp": "2012-04-08 10:52:42.0", "Version": "6.02E23", "ProductName": "Fennicky"}',
                'date_processed':
                "2012-04-08 10:52:42.0"
            }), ), )

            actual_execute_args = m.cursor().execute.call_args_list
            for expected, actual in zip(expected_execute_args,
                                        actual_execute_args):
                expeceted_sql, expected_params = expected[0]
                expeceted_sql = remove_whitespace(expeceted_sql)
                actual_sql, actual_params = actual[0]
                actual_sql = remove_whitespace(actual_sql)
                eq_(expeceted_sql, actual_sql)
                eq_(expected_params, actual_params)
Example #24
0
    def test_basic_postgres_save_processed_succeed_after_failures(self):

        mock_logging = mock.Mock()
        mock_postgres = mock.Mock()

        required_config = PostgreSQLCrashStorage.required_config
        required_config.add_option("logger", default=mock_logging)

        config_manager = ConfigurationManager(
            [required_config],
            app_name="testapp",
            app_version="1.0",
            app_description="app description",
            values_source_list=[
                {
                    "logger": mock_logging,
                    "database_class": mock_postgres,
                    "transaction_executor_class": TransactionExecutorWithLimitedBackoff,
                    "backoff_delays": [0, 0, 0],
                }
            ],
        )

        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            crashstorage.database.operational_exceptions = (OperationalError,)

            database = crashstorage.database.return_value = mock.MagicMock()
            self.assertTrue(isinstance(database, mock.Mock))

            fetch_all_returns = [((666,),), None, ((23,),)]

            def fetch_all_func(*args):
                result = fetch_all_returns.pop(0)
                return result

            fetch_mock = mock.Mock()
            fetch_mock.fetchall.side_effect = fetch_all_func

            connection_trouble = [OperationalError("bad"), OperationalError("worse")]

            def broken_connection(*args):
                try:
                    result = connection_trouble.pop(0)
                    raise result
                except IndexError:
                    return fetch_mock

            m = mock.MagicMock()
            m.__enter__.return_value = m
            database = crashstorage.database.return_value = m
            m.cursor.side_effect = broken_connection
            crashstorage.save_processed(a_processed_crash)
            self.assertEqual(m.cursor.call_count, 9)
            self.assertEqual(m.cursor().fetchall.call_count, 3)
            self.assertEqual(m.cursor().execute.call_count, 7)

            expected_execute_args = (
                (("savepoint MainThread", None),),
                (
                    (
                        "insert into reports_20120402 (addons_checked, address, app_notes, build, client_crash_date, completed_datetime, cpu_info, cpu_name, date_processed, distributor, distributor_version, email, exploitability, flash_version, hangid, install_age, last_crash, os_name, os_version, processor_notes, process_type, product, productid, reason, release_channel, signature, started_datetime, success, topmost_filenames, truncated, uptime, user_comments, user_id, url, uuid, version) values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) returning id",
                        [
                            None,
                            "0x1c",
                            "...",
                            "20120309050057",
                            "2012-04-08 10:52:42.0",
                            "2012-04-08 10:56:50.902884",
                            "None | 0",
                            "arm",
                            "2012-04-08 10:56:41.558922",
                            None,
                            None,
                            "*****@*****.**",
                            "high",
                            "[blank]",
                            None,
                            22385,
                            None,
                            "Linux",
                            "0.0.0 Linux 2.6.35.7-perf-CL727859 #1 ",
                            "SignatureTool: signature truncated due to length",
                            "plugin",
                            "FennecAndroid",
                            "FA-888888",
                            "SIGSEGV",
                            "default",
                            "libxul.so@0x117441c",
                            "2012-04-08 10:56:50.440752",
                            True,
                            [],
                            False,
                            170,
                            None,
                            None,
                            "http://embarrassing.p**n.com",
                            "936ce666-ff3b-4c7a-9674-367fe2120408",
                            "13.0a1",
                        ],
                    ),
                ),
                (("release savepoint MainThread", None),),
                (("select id from plugins where filename = %s and name = %s", ("dwight.txt", "wilma")),),
                (("insert into plugins (filename, name) values (%s, %s) returning id", ("dwight.txt", "wilma")),),
                (
                    (
                        "insert into plugins_reports_20120402     (report_id, plugin_id, date_processed, version) values     (%s, %s, %s, %s)",
                        (666, 23, "2012-04-08 10:56:41.558922", "69"),
                    ),
                ),
                (
                    (
                        "insert into extensions_20120402     (report_id, date_processed, extension_key, extension_id,      extension_version)values (%s, %s, %s, %s, %s)",
                        (666, "2012-04-08 10:56:41.558922", 0, "{1a5dabbd-0e74-41da-b532-a364bb552cab}", "1.0.4.1"),
                    ),
                ),
            )

            actual_execute_args = m.cursor().execute.call_args_list
            for expected, actual in zip(expected_execute_args, actual_execute_args):
                self.assertEqual(expected, actual)
Example #25
0
    def setUp(self):
        assert 'test' in databaseName.default, databaseName.default
        dsn = ('host=%(database_host)s dbname=%(database_name)s '
               'user=%(database_user)s password=%(database_password)s' % DSN)
        self.conn = psycopg2.connect(dsn)
        cursor = self.conn.cursor()
        date_suffix = PostgreSQLCrashStorage._table_suffix_for_crash_id(a_processed_crash['uuid'])
        self.reports_table_name = 'reports%s' % date_suffix
        cursor.execute("""
        DROP TABLE IF EXISTS %(table_name)s;
        CREATE TABLE %(table_name)s (
            id integer NOT NULL,
            client_crash_date timestamp with time zone,
            date_processed timestamp with time zone,
            uuid character varying(50) NOT NULL,
            product character varying(30),
            version character varying(16),
            build character varying(30),
            signature character varying(255),
            url character varying(255),
            install_age integer,
            last_crash integer,
            uptime integer,
            cpu_name character varying(100),
            cpu_info character varying(100),
            reason character varying(255),
            address character varying(20),
            os_name character varying(100),
            os_version character varying(100),
            email character varying(100),
            user_id character varying(50),
            started_datetime timestamp with time zone,
            completed_datetime timestamp with time zone,
            success boolean,
            truncated boolean,
            processor_notes text,
            user_comments character varying(1024),
            app_notes character varying(1024),
            distributor character varying(20),
            distributor_version character varying(20),
            topmost_filenames text,
            addons_checked boolean,
            flash_version text,
            hangid text,
            process_type text,
            release_channel text,
            productid text
        );
        DROP SEQUENCE reports_id_seq;
        CREATE SEQUENCE reports_id_seq
            START WITH 1
            INCREMENT BY 1
            NO MINVALUE
            NO MAXVALUE
            CACHE 1;

        ALTER TABLE ONLY %(table_name)s ALTER COLUMN id
          SET DEFAULT nextval('reports_id_seq'::regclass);

        DROP TABLE IF EXISTS plugins;
        CREATE TABLE plugins (
            id serial NOT NULL,
            filename text NOT NULL,
            name text NOT NULL
        );

        DROP TABLE IF EXISTS plugins_reports;
        CREATE TABLE plugins_reports (
            report_id integer NOT NULL,
            plugin_id integer NOT NULL,
            date_processed timestamp with time zone,
            version text NOT NULL
        );

        DROP TABLE IF EXISTS plugin_%(table_name)s;
        CREATE TABLE plugin_%(table_name)s (
            report_id integer NOT NULL,
            plugin_id integer NOT NULL,
            date_processed timestamp with time zone,
            version text NOT NULL
        );

        DROP TABLE IF EXISTS extensions;
        CREATE TABLE extensions (
            report_id serial NOT NULL,
            date_processed timestamp with time zone,
            extension_key integer NOT NULL,
            extension_id text NOT NULL,
            extension_version text
        );

        DROP TABLE IF EXISTS extensions%(date_suffix)s;
        CREATE TABLE extensions%(date_suffix)s (
            report_id serial NOT NULL,
            date_processed timestamp with time zone,
            extension_key integer NOT NULL,
            extension_id text NOT NULL,
            extension_version text
        );

        """ % dict(table_name=self.reports_table_name,
                   date_suffix=date_suffix))
        self.conn.commit()
        assert self.conn.get_transaction_status() == TRANSACTION_STATUS_IDLE
    def test_basic_postgres_save_processed_success2(self):

        mock_logging = mock.Mock()
        mock_postgres = mock.Mock()
        required_config = PostgreSQLCrashStorage.get_required_config()
        required_config.add_option('logger', default=mock_logging)

        config_manager = ConfigurationManager(
          [required_config],
          app_name='testapp',
          app_version='1.0',
          app_description='app description',
          values_source_list=[{
            'logger': mock_logging,
            'database_class': mock_postgres
          }],
          argv_source=[]
        )

        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            database = crashstorage.database.return_value = mock.MagicMock()
            self.assertTrue(isinstance(database, mock.Mock))

            fetch_all_returns = [((666,),), None, ((23,),), ]
            def fetch_all_func(*args):
                result = fetch_all_returns.pop(0)
                return result

            m = mock.MagicMock()
            m.__enter__.return_value = m
            database = crashstorage.database.return_value = m
            m.cursor.return_value.fetchall.side_effect=fetch_all_func
            crashstorage.save_processed(a_processed_crash)
            self.assertEqual(m.cursor.call_count, 10)
            self.assertEqual(m.cursor().fetchall.call_count, 3)
            self.assertEqual(m.cursor().execute.call_count, 10)

            expected_execute_args = (
                (('savepoint MainThread', None),),
                (('insert into reports_20120402 (addons_checked, address, app_notes, build, client_crash_date, completed_datetime, cpu_info, cpu_name, date_processed, distributor, distributor_version, email, exploitability, flash_version, hangid, install_age, last_crash, os_name, os_version, processor_notes, process_type, product, productid, reason, release_channel, signature, started_datetime, success, topmost_filenames, truncated, uptime, user_comments, user_id, url, uuid, version) values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) returning id',
                     [None, '0x1c', '...', '20120309050057', '2012-04-08 10:52:42.0', '2012-04-08 10:56:50.902884', 'None | 0', 'arm', '2012-04-08 10:56:41.558922', None, None, '*****@*****.**', 'high', '[blank]', None, 22385, None, 'Linux', '0.0.0 Linux 2.6.35.7-perf-CL727859 #1 ', 'SignatureTool: signature truncated due to length', 'plugin', 'FennecAndroid', 'FA-888888', 'SIGSEGV', 'default', 'libxul.so@0x117441c', '2012-04-08 10:56:50.440752', True, [], False, 170, None, None, 'http://embarrassing.p**n.com', '936ce666-ff3b-4c7a-9674-367fe2120408', '13.0a1']),),
                (('release savepoint MainThread', None),),
                (('select id from plugins where filename = %s and name = %s',
                     ('dwight.txt', 'wilma')),),
                (('insert into plugins (filename, name) values (%s, %s) returning id',
                     ('dwight.txt', 'wilma')),),
                (('insert into plugins_reports_20120402     (report_id, plugin_id, date_processed, version) values     (%s, %s, %s, %s)',
                     (666, 23, '2012-04-08 10:56:41.558922', '69')),),
                (('insert into extensions_20120402     (report_id, date_processed, extension_key, extension_id,      extension_version)values (%s, %s, %s, %s, %s)',
                     (666, '2012-04-08 10:56:41.558922', 0, '{1a5dabbd-0e74-41da-b532-a364bb552cab}', '1.0.4.1')),),
                (('savepoint MainThread', None),),
                (('insert into processed_crashes_20120402 (uuid, processed_crash, date_processed) values (%s, %s, %s)',
                    ('936ce666-ff3b-4c7a-9674-367fe2120408', '{"startedDateTime": "2012-04-08 10:56:50.440752", "crashedThread": 8, "cpu_info": "None | 0", "PluginName": "wilma", "install_age": 22385, "topmost_filenames": [], "user_comments": null, "user_id": null, "uuid": "936ce666-ff3b-4c7a-9674-367fe2120408", "flash_version": "[blank]", "os_version": "0.0.0 Linux 2.6.35.7-perf-CL727859 #1 ", "PluginVersion": "69", "addons_checked": null, "completeddatetime": "2012-04-08 10:56:50.902884", "productid": "FA-888888", "success": true, "exploitability": "high", "client_crash_date": "2012-04-08 10:52:42.0", "PluginFilename": "dwight.txt", "dump": "...", "truncated": false, "product": "FennecAndroid", "distributor": null, "processor_notes": "SignatureTool: signature truncated due to length", "uptime": 170, "release_channel": "default", "distributor_version": null, "process_type": "plugin", "id": 361399767, "hangid": null, "version": "13.0a1", "build": "20120309050057", "ReleaseChannel": "default", "email": "*****@*****.**", "app_notes": "...", "os_name": "Linux", "last_crash": null, "date_processed": "2012-04-08 10:56:41.558922", "cpu_name": "arm", "reason": "SIGSEGV", "address": "0x1c", "url": "http://embarrassing.p**n.com", "signature": "libxul.so@0x117441c", "addons": [["{1a5dabbd-0e74-41da-b532-a364bb552cab}", "1.0.4.1"]]}', '2012-04-08 10:56:41.558922')
                ),),
                (('release savepoint MainThread', None),),
            )

            actual_execute_args = m.cursor().execute.call_args_list
            for expected, actual in zip(expected_execute_args,
                                        actual_execute_args):
                expected_sql, expected_params = expected[0]
                expected_sql = expected_sql.replace('\n', '')
                expected_sql = expected_sql.replace(' ', '')
                actual_sql, actual_params = actual[0]
                actual_sql = actual_sql.replace('\n', '')
                actual_sql = actual_sql.replace(' ', '')
                self.assertEqual(expected_sql, actual_sql)
                self.assertEqual(expected_params, actual_params)
Example #27
0
    def test_basic_postgres_save_processed_succeed_after_failures(self):
        mock_logging = mock.Mock()
        mock_postgres = mock.Mock()

        required_config = PostgreSQLCrashStorage.get_required_config()
        required_config.add_option('logger', default=mock_logging)

        config_manager = ConfigurationManager(
            [required_config],
            app_name='testapp',
            app_version='1.0',
            app_description='app description',
            values_source_list=[{
                'logger': mock_logging,
                'database_class': mock_postgres,
                'transaction_executor_class':
                    TransactionExecutorWithLimitedBackoff,
                'backoff_delays': [0, 0, 0],
            }],
            argv_source=[]
        )

        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            crashstorage.database.operational_exceptions = (OperationalError,)

            database = crashstorage.database.return_value = mock.MagicMock()
            ok_(isinstance(database, mock.Mock))

            fetch_all_returns = [((666,),), None, ((23,),), ]

            def fetch_all_func(*args):
                result = fetch_all_returns.pop(0)
                return result

            fetch_mock = mock.Mock()
            fetch_mock.fetchall.side_effect = fetch_all_func

            connection_trouble = [OperationalError('bad'),
                                  OperationalError('worse'),
                                  ]

            def broken_connection(*args):
                try:
                    result = connection_trouble.pop(0)
                    raise result
                except IndexError:
                    return fetch_mock

            m = mock.MagicMock()
            m.__enter__.return_value = m
            database = crashstorage.database.return_value = m
            m.cursor.side_effect = broken_connection
            crashstorage.save_processed(a_processed_crash)
            eq_(m.cursor.call_count, 10)
            eq_(m.cursor().fetchall.call_count, 3)
            eq_(m.cursor().execute.call_count, 8)

            expected_execute_args = (
                (('WITH update_report AS (UPDATE reports_20120402 SET addons_checked=%s, address=%s, app_notes=%s, build=%s, client_crash_date=%s, completed_datetime=%s, cpu_info=%s, cpu_name=%s, date_processed=%s, distributor=%s, distributor_version=%s, email=%s, exploitability=%s, flash_version=%s, hangid=%s, install_age=%s, last_crash=%s, os_name=%s, os_version=%s, processor_notes=%s, process_type=%s, product=%s, productid=%s, reason=%s, release_channel=%s, signature=%s, started_datetime=%s, success=%s, topmost_filenames=%s, truncated=%s, uptime=%s, user_comments=%s, user_id=%s, url=%s, uuid=%s, version=%s WHERE uuid=%s RETURNING id), insert_report AS (INSERT INTO reports_20120402(addons_checked, address, app_notes, build, client_crash_date, completed_datetime, cpu_info, cpu_name, date_processed, distributor, distributor_version, email, exploitability, flash_version, hangid, install_age, last_crash, os_name, os_version, processor_notes, process_type, product, productid, reason, release_channel, signature, started_datetime, success, topmost_filenames, truncated, uptime, user_comments, user_id, url, uuid, version)(SELECT%s as addons_checked, %s as address, %s as app_notes, %s as build, %s as client_crash_date, %s as completed_datetime, %s as cpu_info, %s as cpu_name, %s as date_processed, %s as distributor, %s as distributor_version, %s as email, %s as exploitability, %s as flash_version, %s as hangid, %s as install_age, %s as last_crash, %s as os_name, %s as os_version, %s as processor_notes, %s as process_type, %s as product, %s as productid, %s as reason, %s as release_channel, %s as signature, %s as started_datetime, %s as success, %s as topmost_filenames, %s as truncated, %s as uptime, %s as user_comments, %s as user_id, %s as url, %s as uuid, %s as version WHERE NOT EXISTS(SELECT uuid from reports_20120402 WHERE uuid=%s LIMIT 1)) RETURNING id) SELECT * from update_report UNION ALL SELECT * from insert_report',
                    [None, '0x1c', '...', '20120309050057', '2012-04-08 10:52:42.0', '2012-04-08 10:56:50.902884', 'None | 0', 'arm', '2012-04-08 10:56:41.558922', None, None, '*****@*****.**', 'high', '[blank]', None, 22385, None, 'Linux', '0.0.0 Linux 2.6.35.7-perf-CL727859 #1 ', 'SignatureTool: signature truncated due to length', 'plugin', 'FennecAndroid', 'FA-888888', 'SIGSEGV', 'default', 'libxul.so@0x117441c', '2012-04-08 10:56:50.440752', True, [], False, 170, None, None, 'http://embarrassing.p**n.com', '936ce666-ff3b-4c7a-9674-367fe2120408', '13.0a1', '936ce666-ff3b-4c7a-9674-367fe2120408',
                    None, '0x1c', '...', '20120309050057', '2012-04-08 10:52:42.0', '2012-04-08 10:56:50.902884', 'None | 0', 'arm', '2012-04-08 10:56:41.558922', None, None, '*****@*****.**', 'high', '[blank]', None, 22385, None, 'Linux', '0.0.0 Linux 2.6.35.7-perf-CL727859 #1 ', 'SignatureTool: signature truncated due to length', 'plugin', 'FennecAndroid', 'FA-888888', 'SIGSEGV', 'default', 'libxul.so@0x117441c', '2012-04-08 10:56:50.440752', True, [], False, 170, None, None, 'http://embarrassing.p**n.com', '936ce666-ff3b-4c7a-9674-367fe2120408', '13.0a1', '936ce666-ff3b-4c7a-9674-367fe2120408']),),
                (('select id from plugins where filename = %s and name = %s',
                    ('dwight.txt', 'wilma')),),
                (('insert into plugins (filename, name) values (%s, %s) returning id',
                    ('dwight.txt', 'wilma')),),
                (('delete from  plugins_reports_20120402 where report_id = %s',
                    (666, )),),
                (('insert into plugins_reports_20120402     (report_id, plugin_id, date_processed, version) values     (%s, %s, %s, %s)',
                    (666, 23, '2012-04-08 10:56:41.558922', '69')),),
                (('delete from extensions_20120402 where report_id = %s',
                    (666, )),),
                (('insert into extensions_20120402     (report_id, date_processed, extension_key, extension_id,      extension_version)values (%s, %s, %s, %s, %s)',
                    (666, '2012-04-08 10:56:41.558922', 0, '{1a5dabbd-0e74-41da-b532-a364bb552cab}', '1.0.4.1')),),
                (("""WITH update_processed_crash AS ( UPDATE processed_crashes_20120402 SET processed_crash = %(processed_json)s, date_processed = %(date_processed)s WHERE uuid = %(uuid)s RETURNING 1), insert_processed_crash AS ( INSERT INTO processed_crashes_20120402 (uuid, processed_crash, date_processed) ( SELECT %(uuid)s as uuid, %(processed_json)s as processed_crash, %(date_processed)s as date_processed WHERE NOT EXISTS ( SELECT uuid from processed_crashes_20120402 WHERE uuid = %(uuid)s LIMIT 1)) RETURNING 2) SELECT * from update_processed_crash UNION ALL SELECT * from insert_processed_crash """,
                    {'uuid': '936ce666-ff3b-4c7a-9674-367fe2120408', 'processed_json': '{"startedDateTime": "2012-04-08 10:56:50.440752", "crashedThread": 8, "cpu_info": "None | 0", "PluginName": "wilma", "install_age": 22385, "topmost_filenames": [], "user_comments": null, "user_id": null, "uuid": "936ce666-ff3b-4c7a-9674-367fe2120408", "flash_version": "[blank]", "os_version": "0.0.0 Linux 2.6.35.7-perf-CL727859 #1 ", "PluginVersion": "69", "addons_checked": null, "completeddatetime": "2012-04-08 10:56:50.902884", "productid": "FA-888888", "success": true, "exploitability": "high", "client_crash_date": "2012-04-08 10:52:42.0", "PluginFilename": "dwight.txt", "dump": "...", "truncated": false, "product": "FennecAndroid", "distributor": null, "processor_notes": "SignatureTool: signature truncated due to length", "uptime": 170, "release_channel": "default", "distributor_version": null, "process_type": "plugin", "id": 361399767, "hangid": null, "version": "13.0a1", "build": "20120309050057", "ReleaseChannel": "default", "email": "*****@*****.**", "app_notes": "...", "os_name": "Linux", "last_crash": null, "date_processed": "2012-04-08 10:56:41.558922", "cpu_name": "arm", "reason": "SIGSEGV", "address": "0x1c", "url": "http://embarrassing.p**n.com", "signature": "libxul.so@0x117441c", "addons": [["{1a5dabbd-0e74-41da-b532-a364bb552cab}", "1.0.4.1"]]}', 'date_processed': '2012-04-08 10:56:41.558922'}),),
            )

            actual_execute_args = m.cursor().execute.call_args_list
            for expected, actual in zip(expected_execute_args,
                                        actual_execute_args):
                expected_sql, expected_params = expected[0]
                expected_sql = remove_whitespace(expected_sql)
                actual_sql, actual_params = actual[0]
                actual_sql = remove_whitespace(actual_sql)
                eq_(expected_sql, actual_sql)
                eq_(expected_params, actual_params)
Example #28
0
    def setUp(self):

        config_manager = self._setup_config_manager()
        with config_manager.context() as config:
            DSN = {
                "database_hostname": config.database_hostnamename,
                "database_name": config.database_name,
                "database_username": config.database_username,
                "database_password": config.database_password
            }

        dsn = ('host=%(database_hostname)s dbname=%(database_name)s '
               'user=%(database_username)s password=%(database_password)s' %
               DSN)
        self.conn = psycopg2.connect(dsn)
        cursor = self.conn.cursor()
        date_suffix = PostgreSQLCrashStorage._table_suffix_for_crash_id(
            a_processed_crash['uuid'])
        self.reports_table_name = 'reports%s' % date_suffix
        cursor.execute(
            """
        DROP TABLE IF EXISTS %(table_name)s;
        CREATE TABLE %(table_name)s (
            id integer NOT NULL,
            client_crash_date timestamp with time zone,
            date_processed timestamp with time zone,
            uuid character varying(50) NOT NULL,
            product character varying(30),
            version character varying(16),
            build character varying(30),
            signature character varying(255),
            url character varying(255),
            install_age integer,
            last_crash integer,
            uptime integer,
            cpu_name character varying(100),
            cpu_info character varying(100),
            reason character varying(255),
            address character varying(20),
            os_name character varying(100),
            os_version character varying(100),
            email character varying(100),
            user_id character varying(50),
            started_datetime timestamp with time zone,
            completed_datetime timestamp with time zone,
            success boolean,
            truncated boolean,
            processor_notes text,
            user_comments character varying(1024),
            app_notes character varying(1024),
            distributor character varying(20),
            distributor_version character varying(20),
            topmost_filenames text,
            addons_checked boolean,
            flash_version text,
            hangid text,
            process_type text,
            release_channel text,
            productid text
        );
        DROP SEQUENCE reports_id_seq;
        CREATE SEQUENCE reports_id_seq
            START WITH 1
            INCREMENT BY 1
            NO MINVALUE
            NO MAXVALUE
            CACHE 1;

        ALTER TABLE ONLY %(table_name)s ALTER COLUMN id
          SET DEFAULT nextval('reports_id_seq'::regclass);

        DROP TABLE IF EXISTS plugins;
        CREATE TABLE plugins (
            id serial NOT NULL,
            filename text NOT NULL,
            name text NOT NULL
        );

        DROP TABLE IF EXISTS plugins_reports;
        CREATE TABLE plugins_reports (
            report_id integer NOT NULL,
            plugin_id integer NOT NULL,
            date_processed timestamp with time zone,
            version text NOT NULL
        );

        DROP TABLE IF EXISTS plugin_%(table_name)s;
        CREATE TABLE plugin_%(table_name)s (
            report_id integer NOT NULL,
            plugin_id integer NOT NULL,
            date_processed timestamp with time zone,
            version text NOT NULL
        );

        DROP TABLE IF EXISTS extensions;
        CREATE TABLE extensions (
            report_id serial NOT NULL,
            date_processed timestamp with time zone,
            extension_key integer NOT NULL,
            extension_id text NOT NULL,
            extension_version text
        );

        DROP TABLE IF EXISTS extensions%(date_suffix)s;
        CREATE TABLE extensions%(date_suffix)s (
            report_id serial NOT NULL,
            date_processed timestamp with time zone,
            extension_key integer NOT NULL,
            extension_id text NOT NULL,
            extension_version text
        );

        """ %
            dict(table_name=self.reports_table_name, date_suffix=date_suffix))
        self.conn.commit()
        assert self.conn.get_transaction_status() == TRANSACTION_STATUS_IDLE
Example #29
0
    def test_basic_postgres_save_processed_succeed_after_failures(self):
        mock_logging = mock.Mock()
        mock_postgres = mock.Mock()

        required_config = PostgreSQLCrashStorage.get_required_config()
        required_config.add_option('logger', default=mock_logging)

        config_manager = ConfigurationManager(
            [required_config],
            app_name='testapp',
            app_version='1.0',
            app_description='app description',
            values_source_list=[{
                'logger': mock_logging,
                'database_class': mock_postgres,
                'transaction_executor_class':
                TransactionExecutorWithLimitedBackoff,
                'backoff_delays': [0, 0, 0],
            }],
            argv_source=[])

        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            crashstorage.database.operational_exceptions = (OperationalError, )

            database = crashstorage.database.return_value = mock.MagicMock()
            ok_(isinstance(database, mock.Mock))

            fetch_all_returns = [
                ((666, ), ),
                None,
                ((23, ), ),
            ]

            def fetch_all_func(*args):
                result = fetch_all_returns.pop(0)
                return result

            fetch_mock = mock.Mock()
            fetch_mock.fetchall.side_effect = fetch_all_func

            connection_trouble = [
                OperationalError('bad'),
                OperationalError('worse'),
            ]

            def broken_connection(*args):
                try:
                    result = connection_trouble.pop(0)
                    raise result
                except IndexError:
                    return fetch_mock

            m = mock.MagicMock()
            m.__enter__.return_value = m
            database = crashstorage.database.return_value = m
            m.cursor.side_effect = broken_connection
            crashstorage.save_processed(a_processed_crash)
            eq_(m.cursor.call_count, 8)
            eq_(m.cursor().fetchall.call_count, 3)
            eq_(m.cursor().execute.call_count, 6)

            expected_execute_args = (
                (('WITH update_report AS (UPDATE reports_20120402 SET addons_checked=%s, address=%s, app_notes=%s, build=%s, client_crash_date=%s, completed_datetime=%s, cpu_info=%s, cpu_name=%s, date_processed=%s, distributor=%s, distributor_version=%s, email=%s, exploitability=%s, flash_version=%s, hangid=%s, install_age=%s, last_crash=%s, os_name=%s, os_version=%s, processor_notes=%s, process_type=%s, product=%s, productid=%s, reason=%s, release_channel=%s, signature=%s, started_datetime=%s, success=%s, topmost_filenames=%s, truncated=%s, uptime=%s, user_comments=%s, user_id=%s, url=%s, uuid=%s, version=%s WHERE uuid=%s RETURNING id), insert_report AS (INSERT INTO reports_20120402(addons_checked, address, app_notes, build, client_crash_date, completed_datetime, cpu_info, cpu_name, date_processed, distributor, distributor_version, email, exploitability, flash_version, hangid, install_age, last_crash, os_name, os_version, processor_notes, process_type, product, productid, reason, release_channel, signature, started_datetime, success, topmost_filenames, truncated, uptime, user_comments, user_id, url, uuid, version)(SELECT%s as addons_checked, %s as address, %s as app_notes, %s as build, %s as client_crash_date, %s as completed_datetime, %s as cpu_info, %s as cpu_name, %s as date_processed, %s as distributor, %s as distributor_version, %s as email, %s as exploitability, %s as flash_version, %s as hangid, %s as install_age, %s as last_crash, %s as os_name, %s as os_version, %s as processor_notes, %s as process_type, %s as product, %s as productid, %s as reason, %s as release_channel, %s as signature, %s as started_datetime, %s as success, %s as topmost_filenames, %s as truncated, %s as uptime, %s as user_comments, %s as user_id, %s as url, %s as uuid, %s as version WHERE NOT EXISTS(SELECT uuid from reports_20120402 WHERE uuid=%s LIMIT 1)) RETURNING id) SELECT * from update_report UNION ALL SELECT * from insert_report',
                  [
                      None, '0x1c', '...', '20120309050057',
                      '2012-04-08 10:52:42.0', '2012-04-08 10:56:50.902884',
                      'None | 0', 'arm', '2012-04-08 10:56:41.558922', None,
                      None, '*****@*****.**', 'high', '[blank]', None, 22385,
                      None, 'Linux', '0.0.0 Linux 2.6.35.7-perf-CL727859 #1 ',
                      'SignatureTool: signature truncated due to length',
                      'plugin', 'FennecAndroid', 'FA-888888', 'SIGSEGV',
                      'default', 'libxul.so@0x117441c',
                      '2012-04-08 10:56:50.440752', True, [], False, 170, None,
                      None, 'http://embarrassing.p**n.com',
                      '936ce666-ff3b-4c7a-9674-367fe2120408', '13.0a1',
                      '936ce666-ff3b-4c7a-9674-367fe2120408', None, '0x1c',
                      '...', '20120309050057', '2012-04-08 10:52:42.0',
                      '2012-04-08 10:56:50.902884', 'None | 0', 'arm',
                      '2012-04-08 10:56:41.558922', None, None,
                      '*****@*****.**', 'high', '[blank]', None, 22385, None,
                      'Linux', '0.0.0 Linux 2.6.35.7-perf-CL727859 #1 ',
                      'SignatureTool: signature truncated due to length',
                      'plugin', 'FennecAndroid', 'FA-888888', 'SIGSEGV',
                      'default', 'libxul.so@0x117441c',
                      '2012-04-08 10:56:50.440752', True, [], False, 170, None,
                      None, 'http://embarrassing.p**n.com',
                      '936ce666-ff3b-4c7a-9674-367fe2120408', '13.0a1',
                      '936ce666-ff3b-4c7a-9674-367fe2120408'
                  ]), ),
                (('select id from plugins where filename = %s and name = %s',
                  ('dwight.txt', 'wilma')), ),
                (('insert into plugins (filename, name) values (%s, %s) returning id',
                  ('dwight.txt', 'wilma')), ),
                (('delete from  plugins_reports_20120402 where report_id = %s',
                  (666, )), ),
                (('insert into plugins_reports_20120402     (report_id, plugin_id, date_processed, version) values     (%s, %s, %s, %s)',
                  (666, 23, '2012-04-08 10:56:41.558922', '69')), ),
                (("""WITH update_processed_crash AS ( UPDATE processed_crashes_20120402 SET processed_crash = %(processed_json)s, date_processed = %(date_processed)s WHERE uuid = %(uuid)s RETURNING 1), insert_processed_crash AS ( INSERT INTO processed_crashes_20120402 (uuid, processed_crash, date_processed) ( SELECT %(uuid)s as uuid, %(processed_json)s as processed_crash, %(date_processed)s as date_processed WHERE NOT EXISTS ( SELECT uuid from processed_crashes_20120402 WHERE uuid = %(uuid)s LIMIT 1)) RETURNING 2) SELECT * from update_processed_crash UNION ALL SELECT * from insert_processed_crash """,
                  {
                      'uuid': '936ce666-ff3b-4c7a-9674-367fe2120408',
                      'processed_json':
                      '{"startedDateTime": "2012-04-08 10:56:50.440752", "crashedThread": 8, "cpu_info": "None | 0", "PluginName": "wilma", "install_age": 22385, "topmost_filenames": [], "user_comments": null, "user_id": null, "uuid": "936ce666-ff3b-4c7a-9674-367fe2120408", "flash_version": "[blank]", "os_version": "0.0.0 Linux 2.6.35.7-perf-CL727859 #1 ", "PluginVersion": "69", "addons_checked": null, "completeddatetime": "2012-04-08 10:56:50.902884", "productid": "FA-888888", "success": true, "exploitability": "high", "client_crash_date": "2012-04-08 10:52:42.0", "PluginFilename": "dwight.txt", "dump": "...", "truncated": false, "product": "FennecAndroid", "distributor": null, "processor_notes": "SignatureTool: signature truncated due to length", "uptime": 170, "release_channel": "default", "distributor_version": null, "process_type": "plugin", "id": 361399767, "hangid": null, "version": "13.0a1", "build": "20120309050057", "ReleaseChannel": "default", "email": "*****@*****.**", "app_notes": "...", "os_name": "Linux", "last_crash": null, "date_processed": "2012-04-08 10:56:41.558922", "cpu_name": "arm", "reason": "SIGSEGV", "address": "0x1c", "url": "http://embarrassing.p**n.com", "signature": "libxul.so@0x117441c", "addons": [["{1a5dabbd-0e74-41da-b532-a364bb552cab}", "1.0.4.1"]]}',
                      'date_processed': '2012-04-08 10:56:41.558922'
                  }), ),
            )

            actual_execute_args = m.cursor().execute.call_args_list
            for expected, actual in zip(expected_execute_args,
                                        actual_execute_args):
                expected_sql, expected_params = expected[0]
                expected_sql = remove_whitespace(expected_sql)
                actual_sql, actual_params = actual[0]
                actual_sql = remove_whitespace(actual_sql)
                eq_(expected_sql, actual_sql)
                eq_(expected_params, actual_params)
Example #30
0
    def test_basic_postgres_save_processed_succeed_after_failures(self):

        mock_logging = mock.Mock()
        mock_postgres = mock.Mock()

        required_config = PostgreSQLCrashStorage.get_required_config()
        required_config.add_option('logger', default=mock_logging)

        config_manager = ConfigurationManager(
            [required_config],
            app_name='testapp',
            app_version='1.0',
            app_description='app description',
            values_source_list=[{
                'logger': mock_logging,
                'database_class': mock_postgres,
                'transaction_executor_class':
                TransactionExecutorWithLimitedBackoff,
                'backoff_delays': [0, 0, 0],
            }])

        with config_manager.context() as config:
            crashstorage = PostgreSQLCrashStorage(config)
            crashstorage.database.operational_exceptions = (OperationalError, )

            database = crashstorage.database.return_value = mock.MagicMock()
            self.assertTrue(isinstance(database, mock.Mock))

            fetch_all_returns = [
                ((666, ), ),
                None,
                ((23, ), ),
            ]

            def fetch_all_func(*args):
                result = fetch_all_returns.pop(0)
                return result

            fetch_mock = mock.Mock()
            fetch_mock.fetchall.side_effect = fetch_all_func

            connection_trouble = [
                OperationalError('bad'),
                OperationalError('worse'),
            ]

            def broken_connection(*args):
                try:
                    result = connection_trouble.pop(0)
                    raise result
                except IndexError:
                    return fetch_mock

            m = mock.MagicMock()
            m.__enter__.return_value = m
            database = crashstorage.database.return_value = m
            m.cursor.side_effect = broken_connection
            crashstorage.save_processed(a_processed_crash)
            self.assertEqual(m.cursor.call_count, 9)
            self.assertEqual(m.cursor().fetchall.call_count, 3)
            self.assertEqual(m.cursor().execute.call_count, 7)

            expected_execute_args = (
                (('savepoint MainThread', None), ),
                (('insert into reports_20120402 (addons_checked, address, app_notes, build, client_crash_date, completed_datetime, cpu_info, cpu_name, date_processed, distributor, distributor_version, email, exploitability, flash_version, hangid, install_age, last_crash, os_name, os_version, processor_notes, process_type, product, productid, reason, release_channel, signature, started_datetime, success, topmost_filenames, truncated, uptime, user_comments, user_id, url, uuid, version) values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s) returning id',
                  [
                      None, '0x1c', '...', '20120309050057',
                      '2012-04-08 10:52:42.0', '2012-04-08 10:56:50.902884',
                      'None | 0', 'arm', '2012-04-08 10:56:41.558922', None,
                      None, '*****@*****.**', 'high', '[blank]', None, 22385,
                      None, 'Linux', '0.0.0 Linux 2.6.35.7-perf-CL727859 #1 ',
                      'SignatureTool: signature truncated due to length',
                      'plugin', 'FennecAndroid', 'FA-888888', 'SIGSEGV',
                      'default', 'libxul.so@0x117441c',
                      '2012-04-08 10:56:50.440752', True, [], False, 170, None,
                      None, 'http://embarrassing.p**n.com',
                      '936ce666-ff3b-4c7a-9674-367fe2120408', '13.0a1'
                  ]), ),
                (('release savepoint MainThread', None), ),
                (('select id from plugins where filename = %s and name = %s',
                  ('dwight.txt', 'wilma')), ),
                (('insert into plugins (filename, name) values (%s, %s) returning id',
                  ('dwight.txt', 'wilma')), ),
                (('insert into plugins_reports_20120402     (report_id, plugin_id, date_processed, version) values     (%s, %s, %s, %s)',
                  (666, 23, '2012-04-08 10:56:41.558922', '69')), ),
                (('insert into extensions_20120402     (report_id, date_processed, extension_key, extension_id,      extension_version)values (%s, %s, %s, %s, %s)',
                  (666, '2012-04-08 10:56:41.558922', 0,
                   '{1a5dabbd-0e74-41da-b532-a364bb552cab}', '1.0.4.1')), ),
            )

            actual_execute_args = m.cursor().execute.call_args_list
            for expected, actual in zip(expected_execute_args,
                                        actual_execute_args):
                self.assertEqual(expected, actual)