def test_run_s3_validations_binary_access_denied(
            self, storage_service_mock: Mock) -> None:
        expected_report = ValidationReport(
            validation_result=ValidationResult.FAILED,
            validator_name=BINARY_FILE_VALIDATOR_NAME,
            message=
            f"You don't have permission to access some private computation software (Repo path: {DEFAULT_BINARY_REPOSITORY}, software version: {DEFAULT_BINARY_VERSION}). Please contact your representative at Meta",
            details={
                f"{DEFAULT_BINARY_REPOSITORY}package/3/latest/binary":
                "An error occurred (403) when calling the HeadObject operation: Forbidden"
            },
        )
        storage_service_mock.__init__(return_value=storage_service_mock)
        storage_service_mock.file_exists.side_effect = [
            True,
            True,
            PcpError(
                Exception(
                    "An error occurred (403) when calling the HeadObject operation: Forbidden"
                )),
        ]
        validator = BinaryFileValidator(TEST_REGION, TEST_BINARY_INFOS)
        report = validator.validate()

        self.assertEqual(report, expected_report)
        self.assertEqual(storage_service_mock.file_exists.call_count,
                         len(TEST_BINARY_INFOS))
    def test_run_local_validations_success(self, storage_service_mock: Mock,
                                           mock_file_exists: Mock) -> None:
        expected_report = ValidationReport(
            validation_result=ValidationResult.SUCCESS,
            validator_name=BINARY_FILE_VALIDATOR_NAME,
            message=
            f"Completed binary accessibility validation successfully (Repo path: LOCAL, binary folder: {DEFAULT_EXE_FOLDER}).",
        )
        mock_file_exists.return_value = True

        validator = BinaryFileValidator(TEST_REGION, TEST_BINARY_INFOS)
        report = validator.validate()

        self.assertEqual(report, expected_report)
        self.assertEqual(mock_file_exists.call_count, len(TEST_BINARY_INFOS))
    def test_run_local_validations_binary_not_exist(
            self, storage_service_mock: Mock, mock_file_exists: Mock) -> None:
        expected_report = ValidationReport(
            validation_result=ValidationResult.FAILED,
            validator_name=BINARY_FILE_VALIDATOR_NAME,
            message=
            f"You don't have permission to access some private computation software (Repo path: LOCAL, binary folder: {DEFAULT_EXE_FOLDER}). Please contact your representative at Meta",
            details={f"{DEFAULT_EXE_FOLDER}1": "binary does not exist"},
        )
        mock_file_exists.side_effect = [False, True, True]

        validator = BinaryFileValidator(TEST_REGION, TEST_BINARY_INFOS)
        report = validator.validate()

        self.assertEqual(report, expected_report)
        self.assertEqual(mock_file_exists.call_count, len(TEST_BINARY_INFOS))
    def test_run_s3_validations_unexpected_error(
            self, storage_service_mock: Mock) -> None:
        expected_report = ValidationReport(
            validation_result=ValidationResult.SUCCESS,
            validator_name=BINARY_FILE_VALIDATOR_NAME,
            message=
            f"WARNING: {BINARY_FILE_VALIDATOR_NAME} threw an unexpected error: An internal error occurred (500)",
        )
        storage_service_mock.__init__(return_value=storage_service_mock)
        storage_service_mock.file_exists.side_effect = PcpError(
            Exception("An internal error occurred (500)"))
        validator = BinaryFileValidator(TEST_REGION, TEST_BINARY_INFOS)
        report = validator.validate()

        self.assertEqual(report, expected_report)
        self.assertEqual(storage_service_mock.file_exists.call_count, 1)
    def test_run_s3_validations_binary_not_exist(
            self, storage_service_mock: Mock) -> None:
        expected_report = ValidationReport(
            validation_result=ValidationResult.FAILED,
            validator_name=BINARY_FILE_VALIDATOR_NAME,
            message=
            f"You don't have permission to access some private computation software (Repo path: {DEFAULT_BINARY_REPOSITORY}, software version: {DEFAULT_BINARY_VERSION}). Please contact your representative at Meta",
            details={
                f"{DEFAULT_BINARY_REPOSITORY}package/1/latest/1":
                "binary does not exist"
            },
        )
        storage_service_mock.__init__(return_value=storage_service_mock)
        storage_service_mock.file_exists.side_effect = [False, True, True]

        validator = BinaryFileValidator(TEST_REGION, TEST_BINARY_INFOS)
        report = validator.validate()

        self.assertEqual(report, expected_report)
        self.assertEqual(storage_service_mock.file_exists.call_count,
                         len(TEST_BINARY_INFOS))
def main(argv: OptionalType[List[str]] = None) -> None:
    optional_string = Or(None, str)
    cloud_provider_from_string = Use(lambda arg: CloudProvider[arg])

    s = Schema({
        INPUT_FILE_PATH: str,
        CLOUD_PROVIDER: cloud_provider_from_string,
        REGION: str,
        Optional(ACCESS_KEY_ID): optional_string,
        Optional(ACCESS_KEY_DATA): optional_string,
        Optional(START_TIMESTAMP): optional_string,
        Optional(END_TIMESTAMP): optional_string,
        Optional(BINARY_VERSION): optional_string,
    })
    arguments = s.validate(docopt(__doc__, argv))
    assert arguments
    print("Parsed pc_pre_validation_cli arguments")

    validators = [
        cast(
            Validator,
            InputDataValidator(
                input_file_path=arguments[INPUT_FILE_PATH],
                cloud_provider=arguments[CLOUD_PROVIDER],
                region=arguments[REGION],
                start_timestamp=arguments[START_TIMESTAMP],
                end_timestamp=arguments[END_TIMESTAMP],
                access_key_id=arguments[ACCESS_KEY_ID],
                access_key_data=arguments[ACCESS_KEY_DATA],
            ),
        ),
        cast(
            Validator,
            BinaryFileValidator(
                region=arguments[REGION],
                access_key_id=arguments[ACCESS_KEY_ID],
                access_key_data=arguments[ACCESS_KEY_DATA],
                binary_version=arguments[BINARY_VERSION],
            ),
        ),
    ]

    (aggregated_result, aggregated_report) = run_validators(validators)
    overall_result_str = f"Overall Validation Result: {aggregated_result.value}"

    if aggregated_result == ValidationResult.FAILED:
        raise Exception(f"{aggregated_report}\n{overall_result_str}")
    elif aggregated_result == ValidationResult.SUCCESS:
        print(f"Success: {aggregated_report}\n{overall_result_str}")
    else:
        raise Exception(
            f"Unknown validation result: {aggregated_result}.\n" +
            f"Validation report: {aggregated_report}\n{overall_result_str}")
    def test_run_s3_validations_success(self,
                                        storage_service_mock: Mock) -> None:
        expected_report = ValidationReport(
            validation_result=ValidationResult.SUCCESS,
            validator_name=BINARY_FILE_VALIDATOR_NAME,
            message=
            f"Completed binary accessibility validation successfully (Repo path: {DEFAULT_BINARY_REPOSITORY}, software version: {DEFAULT_BINARY_VERSION}).",
        )
        storage_service_mock.__init__(return_value=storage_service_mock)
        storage_service_mock.file_exists.return_value = True

        validator = BinaryFileValidator(TEST_REGION, TEST_BINARY_INFOS)
        report = validator.validate()

        self.assertEqual(report, expected_report)
        self.assertEqual(storage_service_mock.file_exists.call_count,
                         len(TEST_BINARY_INFOS))
        storage_service_mock.file_exists.assert_has_calls([
            call(f"{DEFAULT_BINARY_REPOSITORY}package/1/latest/1"),
            call(f"{DEFAULT_BINARY_REPOSITORY}package/2/latest/2"),
            call(f"{DEFAULT_BINARY_REPOSITORY}package/3/latest/binary"),
        ])
 def test_get_exe_folder_non_default(self,
                                     storage_service_mock: Mock) -> None:
     validator = BinaryFileValidator(TEST_REGION, TEST_BINARY_INFOS)
     self.assertEqual("/non-default/folder/", validator._get_exe_folder())
 def test_get_exe_folder_default(self, storage_service_mock: Mock) -> None:
     validator = BinaryFileValidator(TEST_REGION, TEST_BINARY_INFOS)
     self.assertEqual(DEFAULT_EXE_FOLDER, validator._get_exe_folder())
 def test_get_binary_repo_non_default(self,
                                      storage_service_mock: Mock) -> None:
     validator = BinaryFileValidator(TEST_REGION, TEST_BINARY_INFOS)
     self.assertEqual("non-default", validator._get_repo_path())