class CsvToBin(TestCase):
    def test_directory_only_contains_excluded_files___tar_is_empty(self):
        with TemporaryDirectory() as csv_dir, TemporaryDirectory() as bin_dir:
            with io.open(os.path.join(csv_dir, 'another_file'),
                         'w',
                         encoding='utf-8') as f:
                f.write('file data')

            csv_to_bin(csv_dir, bin_dir)

            self.assertEqual(0, len(glob.glob(os.path.join(csv_dir, '*.bin'))))

    @given(standard_input_files(min_size=1), il_input_files(min_size=1))
    @settings(deadline=1000, suppress_health_check=[HealthCheck.too_slow])
    def test_contains_il_and_standard_files_but_il_is_false___il_files_are_excluded(
            self, standard, il):
        with patch('oasislmf.model_execution.bin.INPUT_FILES',
                   ECHO_CONVERSION_INPUT_FILES), TemporaryDirectory(
                   ) as csv_dir, TemporaryDirectory() as bin_dir:
            for target in chain(standard, il):
                with io.open(os.path.join(csv_dir, target + '.csv'),
                             'w',
                             encoding='utf-8') as f:
                    f.write(target)

            csv_to_bin(csv_dir, bin_dir, il=False)

            self.assertEqual(len(standard),
                             len(glob.glob(os.path.join(bin_dir, '*.bin'))))
            for filename in (f + '.bin' for f in standard):
                self.assertTrue(os.path.exists(os.path.join(bin_dir,
                                                            filename)))

    @given(standard_input_files(min_size=1), il_input_files(min_size=1))
    @settings(deadline=None, suppress_health_check=[HealthCheck.too_slow])
    def test_contains_il_and_standard_files_but_il_is_true___all_files_are_included(
            self, standard, il):
        with patch('oasislmf.model_execution.bin.INPUT_FILES',
                   ECHO_CONVERSION_INPUT_FILES), TemporaryDirectory(
                   ) as csv_dir, TemporaryDirectory() as bin_dir:
            for target in chain(standard, il):
                with io.open(os.path.join(csv_dir, target + '.csv'),
                             'w',
                             encoding='utf-8') as f:
                    f.write(target)

            csv_to_bin(csv_dir, bin_dir, il=True)

            self.assertEqual(
                len(standard) + len(il),
                len(glob.glob(os.path.join(bin_dir, '*.bin'))))
            for filename in (f + '.bin' for f in chain(standard, il)):
                self.assertTrue(os.path.exists(os.path.join(bin_dir,
                                                            filename)))

    def test_subprocess_raises___oasis_exception_is_raised(self):
        with TemporaryDirectory() as csv_dir, TemporaryDirectory() as bin_dir:
            Path(os.path.join(csv_dir, 'events.csv')).touch()

            with patch('oasislmf.model_execution.bin.subprocess.check_call',
                       Mock(side_effect=subprocess.CalledProcessError(1, ''))):
                with self.assertRaises(OasisException):
                    csv_to_bin(csv_dir, bin_dir, il=True)

    @given(standard_input_files(min_size=1), il_input_files(min_size=1))
    @settings(deadline=None, suppress_health_check=[HealthCheck.too_slow])
    def test_single_ri_folder(self, standard, il):
        with patch('oasislmf.model_execution.bin.INPUT_FILES',
                   ECHO_CONVERSION_INPUT_FILES), TemporaryDirectory(
                   ) as csv_dir, TemporaryDirectory() as bin_dir:
            files = standard + il

            for target in files:
                with io.open(os.path.join(csv_dir, target + '.csv'),
                             'w',
                             encoding='utf-8') as f:
                    f.write(target)
            os.mkdir(os.path.join(csv_dir, "RI_1"))
            for target in files:
                with io.open(os.path.join(csv_dir, "RI_1", target + '.csv'),
                             'w',
                             encoding='utf-8') as f:
                    f.write(target)

            csv_to_bin(csv_dir, bin_dir, il=True, ri=True)

            self.assertEqual(len(files),
                             len(glob.glob(os.path.join(bin_dir, '*.bin'))))
            for filename in (f + '.bin' for f in files):
                self.assertTrue(os.path.exists(os.path.join(bin_dir,
                                                            filename)))

            self.assertEqual(
                len(files),
                len(
                    glob.glob(
                        os.path.join(bin_dir, 'RI_1{}*.bin'.format(os.sep)))))
            for filename in (f + '.bin' for f in files):
                self.assertTrue(
                    os.path.exists(os.path.join(bin_dir, 'RI_1', filename)))
            print("ok")

    @given(standard_input_files(min_size=1), il_input_files(min_size=1))
    @settings(deadline=None, suppress_health_check=[HealthCheck.too_slow])
    def test_multiple_ri_folders(self, standard, il):
        with patch('oasislmf.model_execution.bin.INPUT_FILES',
                   ECHO_CONVERSION_INPUT_FILES), TemporaryDirectory(
                   ) as csv_dir, TemporaryDirectory() as bin_dir:
            files = standard + il

            for target in files:
                with io.open(os.path.join(csv_dir, target + '.csv'),
                             'w',
                             encoding='utf-8') as f:
                    f.write(target)
            os.mkdir(os.path.join(csv_dir, "RI_1"))
            for target in files:
                with io.open(os.path.join(csv_dir, "RI_1", target + '.csv'),
                             'w',
                             encoding='utf-8') as f:
                    f.write(target)
            os.mkdir(os.path.join(csv_dir, "RI_2"))
            for target in files:
                with io.open(os.path.join(csv_dir, "RI_2", target + '.csv'),
                             'w',
                             encoding='utf-8') as f:
                    f.write(target)

            csv_to_bin(csv_dir, bin_dir, il=True, ri=True)

            self.assertEqual(len(files),
                             len(glob.glob(os.path.join(bin_dir, '*.bin'))))
            for filename in (f + '.bin' for f in files):
                self.assertTrue(os.path.exists(os.path.join(bin_dir,
                                                            filename)))

            self.assertEqual(
                len(files),
                len(
                    glob.glob(
                        os.path.join(bin_dir, 'RI_1{}*.bin'.format(os.sep)))))
            for filename in (f + '.bin' for f in files):
                self.assertTrue(
                    os.path.exists(os.path.join(bin_dir, 'RI_1', filename)))

            self.assertEqual(
                len(files),
                len(
                    glob.glob(
                        os.path.join(bin_dir, 'RI_2{}*.bin'.format(os.sep)))))
            for filename in (f + '.bin' for f in files):
                self.assertTrue(
                    os.path.exists(os.path.join(bin_dir, 'RI_2', filename)))
class CheckInputsDirectory(TestCase):
    def test_tar_file_already_exists___exception_is_raised(self):
        with TemporaryDirectory() as d:
            Path(os.path.join(d, TAR_FILE)).touch()
            with self.assertRaises(OasisException):
                check_inputs_directory(d, False)

    @given(il_input_files())
    def test_il_is_false_non_il_input_files_are_missing__exception_is_raised(
            self, il_files):
        with TemporaryDirectory() as d:
            for p in il_files:
                Path(os.path.join(d, p + '.csv')).touch()

            with self.assertRaises(OasisException):
                check_inputs_directory(d, False)

    def test_do_is_is_false_non_il_input_files_are_present___no_exception_is_raised(
            self):
        with TemporaryDirectory() as d:
            for input_file in GUL_INPUT_FILES.values():
                Path(os.path.join(d, input_file['name'] + '.csv')).touch()

            try:
                check_inputs_directory(d, False)
            except Exception as e:
                self.fail('Exception was raised {}: {}'.format(type(e), e))

    def test_il_is_true_all_input_files_are_missing__exception_is_raised(self):
        with TemporaryDirectory() as d:
            with self.assertRaises(OasisException):
                check_inputs_directory(d, True)

    def test_il_is_true_gul_input_files_are_missing__exception_is_raised(self):
        with TemporaryDirectory() as d:
            for p in IL_INPUT_FILES.values():
                Path(os.path.join(d, p['name'] + '.csv')).touch()

            with self.assertRaises(OasisException):
                check_inputs_directory(d, True)

    def test_il_is_true_il_input_files_are_missing__exception_is_raised(self):
        with TemporaryDirectory() as d:
            for p in GUL_INPUT_FILES.values():
                Path(os.path.join(d, p['name'] + '.csv')).touch()

            with self.assertRaises(OasisException):
                check_inputs_directory(d, True)

    def test_il_is_true_all_input_files_are_present___no_exception_is_raised(
            self):
        with TemporaryDirectory() as d:
            for p in chain(GUL_INPUT_FILES.values(), IL_INPUT_FILES.values()):
                Path(os.path.join(d, p['name'] + '.csv')).touch()

            try:
                check_inputs_directory(d, True)
            except Exception as e:
                self.fail('Exception was raised {}: {}'.format(type(e), e))

    def test_il_is_false_il_bin_files_are_present___no_exception_is_raised(
            self):
        with TemporaryDirectory() as d:
            for p in chain(GUL_INPUT_FILES.values(), IL_INPUT_FILES.values()):
                Path(os.path.join(d, p['name'] + '.csv')).touch()

            for p in IL_INPUT_FILES.values():
                Path(os.path.join(d, p['name'] + '.bin')).touch()

            try:
                check_inputs_directory(d, False)
            except Exception as e:
                self.fail('Exception was raised {}: {}'.format(type(e), e))

    def test_il_is_false_gul_bin_files_are_present___exception_is_raised(self):
        with TemporaryDirectory() as d:
            for p in chain(GUL_INPUT_FILES.values(), IL_INPUT_FILES.values()):
                Path(os.path.join(d, p['name'] + '.csv')).touch()

            for p in GUL_INPUT_FILES.values():
                Path(os.path.join(d, p['name'] + '.bin')).touch()

            with self.assertRaises(OasisException):
                check_inputs_directory(d, False)

    def test_il_is_true_gul_bin_files_are_present___exception_is_raised(self):
        with TemporaryDirectory() as d:
            for p in chain(GUL_INPUT_FILES.values(), IL_INPUT_FILES.values()):
                Path(os.path.join(d, p['name'] + '.csv')).touch()

            for p in GUL_INPUT_FILES.values():
                Path(os.path.join(d, p['name'] + '.bin')).touch()

            with self.assertRaises(OasisException):
                check_inputs_directory(d, True)

    def test_il_is_true_il_bin_files_are_present___exception_is_raised(self):
        with TemporaryDirectory() as d:
            for p in chain(GUL_INPUT_FILES.values(), IL_INPUT_FILES.values()):
                Path(os.path.join(d, p['name'] + '.csv')).touch()

            for p in IL_INPUT_FILES.values():
                Path(os.path.join(d, p['name'] + '.bin')).touch()

            with self.assertRaises(OasisException):
                check_inputs_directory(d, True)

    def test_il_is_true_no_bin_files_are_present___no_exception_is_raised(
            self):
        with TemporaryDirectory() as d:
            for p in chain(GUL_INPUT_FILES.values(), IL_INPUT_FILES.values()):
                Path(os.path.join(d, p['name'] + '.csv')).touch()

            for p in IL_INPUT_FILES.values():
                Path(os.path.join(d, p['name'] + '.bin')).touch()

            try:
                check_inputs_directory(d, False)
            except Exception as e:
                self.fail('Exception was raised {}: {}'.format(type(e), e))

    def test_il_is_true_bin_files_are_present_but_check_bin_files_are_true___no_exception_is_raised(
            self):
        with TemporaryDirectory() as d:
            for p in INPUT_FILES.values():
                Path(os.path.join(d, p['name'] + '.csv')).touch()

            for p in INPUT_FILES.values():
                Path(os.path.join(d, p['name'] + '.bin')).touch()

            try:
                check_inputs_directory(d, il=True, check_binaries=False)
            except Exception as e:
                self.fail('Exception was raised {}: {}'.format(type(e), e))

    def test_check_gul_and_il_and_single_ri_directory_structure(self):
        with TemporaryDirectory() as d:
            for p in INPUT_FILES.values():
                Path(os.path.join(d, p['name'] + '.csv')).touch()
            os.mkdir(os.path.join(d, "RI_1"))
            for p in INPUT_FILES.values():
                f = os.path.join(d, "RI_1", p['name'] + '.csv')
                Path(f).touch()
            try:
                check_inputs_directory(d,
                                       il=True,
                                       ri=True,
                                       check_binaries=True)
            except Exception as e:
                self.fail('Exception was raised {}: {}'.format(type(e), e))

    def test_check_gul_and_il_and_single_ri_directory_structure_binaries_fail(
            self):
        with TemporaryDirectory() as d:
            for p in INPUT_FILES.values():
                Path(os.path.join(d, p['name'] + '.csv')).touch()
                Path(os.path.join(d, p['name'] + '.bin')).touch()
            os.mkdir(os.path.join(d, "RI_1"))
            for p in INPUT_FILES.values():
                Path(os.path.join(d, "RI_1", p['name'] + '.csv')).touch()
                Path(os.path.join(d, "RI_1", p['name'] + '.bin')).touch()

            with self.assertRaises(OasisException):
                check_inputs_directory(d,
                                       il=True,
                                       ri=True,
                                       check_binaries=True)

    def test_check_gul_and_il_and_multiple_ri_directories(self):
        with TemporaryDirectory() as d:
            for p in INPUT_FILES.values():
                Path(os.path.join(d, p['name'] + '.csv')).touch()

            os.mkdir(os.path.join(d, "RI_1"))
            for p in INPUT_FILES.values():
                Path(os.path.join(d, "RI_1", p['name'] + '.csv')).touch()

            os.mkdir(os.path.join(d, "RI_2"))
            for p in INPUT_FILES.values():
                Path(os.path.join(d, "RI_2", p['name'] + '.csv')).touch()

            try:
                check_inputs_directory(d,
                                       il=True,
                                       ri=True,
                                       check_binaries=True)
            except Exception as e:
                self.fail('Exception was raised {}: {}'.format(type(e), e))

    def test_check_gul_and_il_and_multiple_ri_directories_binaries_fail(self):
        with TemporaryDirectory() as d:
            for p in INPUT_FILES.values():
                Path(os.path.join(d, p['name'] + '.csv')).touch()
                Path(os.path.join(d, p['name'] + '.bin')).touch()
            os.mkdir(os.path.join(d, "RI_1"))
            for p in INPUT_FILES.values():
                Path(f=os.path.join(d, "RI_1", p['name'] + '.csv')).touch()
                Path(f=os.path.join(d, "RI_1", p['name'] + '.bin')).touch()
            os.mkdir(os.path.join(d, "RI_2"))
            for p in INPUT_FILES.values():
                Path(os.path.join(d, "RI_2", p['name'] + '.bin')).touch()
                Path(os.path.join(d, "RI_2", p['name'] + '.bin')).touch()

            with self.assertRaises(OasisException):
                check_inputs_directory(d,
                                       il=True,
                                       ri=True,
                                       check_binaries=True)