def test_main_impl_with_all_tables_synced_successfully_should_exit_normally(self):
        # mocks prep
        with patch('pipelinewise.fastsync.s3_csv_to_snowflake.utils') as utils_mock:
            with patch('pipelinewise.fastsync.s3_csv_to_snowflake.FastSyncTargetSnowflake') as fastsync_target_sf_mock:
                with patch('pipelinewise.fastsync.s3_csv_to_snowflake.sync_table') as sync_table_mock:
                    with patch('pipelinewise.fastsync.s3_csv_to_snowflake.multiprocessing') as multiproc_mock:
                        ns = Namespace(**{
                            'tables': ['table_1', 'table_2', 'table_3', 'table_4'],
                            'target': 'sf',
                            'transform': None
                        })

                        utils_mock.parse_args.return_value = ns
                        utils_mock.get_cpu_cores.return_value = 10
                        fastsync_target_sf_mock.return_value.cache_information_schema_columns.return_value = None

                        mock_enter = Mock()
                        mock_enter.return_value.map.return_value = [True, True, True, True]

                        pool_mock = Mock(spec_set=multiprocessing.Pool).return_value

                        # to mock variable p in with statement, we need __enter__ and __exist__
                        pool_mock.__enter__ = mock_enter
                        pool_mock.__exit__ = Mock()
                        multiproc_mock.Pool.return_value = pool_mock

                        # call function
                        main_impl()

                        # assertions
                        utils_mock.parse_args.assert_called_once()
                        utils_mock.get_cpu_cores.assert_called_once()
                        mock_enter.return_value.map.assert_called_once()
                        fastsync_target_sf_mock.return_value.cache_information_schema_columns.assert_called_once()
    def test_main_impl_with_one_table_fails_to_sync_should_exit_with_error(self):
        # mocks prep
        with patch('pipelinewise.fastsync.s3_csv_to_snowflake.utils') as utils_mock:
            with patch('pipelinewise.fastsync.s3_csv_to_snowflake.FastSyncTargetSnowflake') as fastsync_target_sf_mock:
                with patch('pipelinewise.fastsync.s3_csv_to_snowflake.sync_table') as sync_table_mock:
                    with patch('pipelinewise.fastsync.s3_csv_to_snowflake.multiprocessing') as multiproc_mock:
                        ns = Namespace(**{
                            'tables': ['table_1', 'table_2', 'table_3', 'table_4'],
                            'target': 'sf',
                            'transform': None
                        })

                        utils_mock.parse_args.return_value = ns
                        utils_mock.get_cpu_cores.return_value = 10

                        mock_enter = Mock()
                        mock_enter.return_value.map.return_value = [True, True, 'Critical: random error', True]

                        pool_mock = Mock(spec_set=multiprocessing.Pool).return_value

                        # to mock variable p in with statement, we need __enter__ and __exist__
                        pool_mock.__enter__ = mock_enter
                        pool_mock.__exit__ = Mock()
                        multiproc_mock.Pool.return_value = pool_mock

                        with self.assertRaises(SystemExit):
                            # call function
                            main_impl()

                            # assertions
                            utils_mock.parse_args.assert_called_once()
                            utils_mock.get_cpu_cores.assert_called_once()
                            mock_enter.return_value.map.assert_called_once()