Esempio n. 1
0
    'symbol_name': SYMBOL_NAME,
}

CASE_THAT_DEFINES_SYMBOL = """\
[setup]

{define} {symbol_name}
"""

CASE_THAT_REGISTERS_EXISTENCE_OF_SYMBOL = """\
[setup]

{register_existence_of} {symbol_name}
"""

CASE_1_FILE = File('1.case', CASE_THAT_DEFINES_SYMBOL.format_map(FORMAT_MAP))

CASE_2_FILE = File(
    '2.case', CASE_THAT_REGISTERS_EXISTENCE_OF_SYMBOL.format_map(FORMAT_MAP))

SUITE_WITH_CASES = """\
[cases]

{case_1_file}
{case_2_file}
""".format(
    case_1_file=CASE_1_FILE.file_name,
    case_2_file=CASE_2_FILE.file_name,
)

Esempio n. 2
0
    def runTest(self):
        non_zero_exit_code = 1
        text_printed_by_program = 'the output from the program'

        py_file = File(
            'exit-with-hard-coded-exit-code.py',
            py_programs.py_pgm_with_stdout_stderr_exit_code(
                stdout_output=text_printed_by_program,
                stderr_output='',
                exit_code=non_zero_exit_code,
            ),
        )

        expected_file = fs.File(
            'dst-file.txt',
            text_printed_by_program.upper(),
        )

        to_upper_transformer = StringTransformerSymbolContext.of_primitive(
            'TO_UPPER_CASE',
            to_uppercase(),
        )
        symbols = to_upper_transformer.symbol_table

        py_src_file_rel_opt_conf = rel_opt.conf_rel_any(
            RelOptionType.REL_HDS_CASE)
        dst_file_rel_opt_conf = conf_rel_non_hds(RelNonHdsOptionType.REL_TMP)

        program_string_source_syntax = string_source_abs_stx.StringSourceOfProgramAbsStx(
            ProcOutputFile.STDOUT,
            program_abs_stx.FullProgramAbsStx(
                program_abs_stx.ProgramOfPythonInterpreterAbsStx.
                of_execute_python_src_file(
                    py_src_file_rel_opt_conf.path_abs_stx_of_name(
                        py_file.name)),
                transformation=to_upper_transformer.abstract_syntax,
            ),
            ignore_exit_code=True,
        )
        instruction_syntax = instr_abs_stx.create_w_explicit_contents(
            dst_file_rel_opt_conf.path_abs_stx_of_name(expected_file.name),
            program_string_source_syntax,
        )

        instruction_checker = self.conf.instruction_checker
        parser = self.conf.parser()
        for source_case in equivalent_source_variants__with_source_check__consume_last_line__abs_stx(
                instruction_syntax):
            with self.subTest(source_case.name):
                source = source_case.value.source
                # ACT #
                instruction = parser.parse(ARBITRARY_FS_LOCATION_INFO, source)
                # ASSERT #
                source_case.value.expectation.apply_with_message(
                    self, source, 'source-after-parse')
                # ACT & ASSERT #
                instruction_checker.check(
                    self, instruction,
                    self.conf.arrangement(
                        pre_contents_population_action=
                        SETUP_CWD_INSIDE_SDS_BUT_NOT_A_SDS_DIR,
                        symbols=symbols,
                        tcds_contents=py_src_file_rel_opt_conf.
                        populator_for_relativity_option_root(
                            DirContents([py_file]))),
                    self.conf.expect_success(
                        symbol_usages=asrt.matches_sequence([
                            to_upper_transformer.reference_assertion,
                        ]),
                        main_side_effects_on_sds=non_hds_dir_contains_exactly(
                            dst_file_rel_opt_conf.root_dir__non_hds,
                            fs.DirContents([expected_file])),
                    ))
Esempio n. 3
0
    'var_value': VAR_VALUE,
}

CASE_THAT_MODIFIES_ENV_VARS = """\
[setup]

{set} {var_name} = {var_value}
"""

CASE_THAT_REGISTERS_VAR_VALUE = """\
[setup]

{register_existence_of} {var_name}
"""

CASE_1_FILE = File('1.case',
                   CASE_THAT_MODIFIES_ENV_VARS.format_map(FORMAT_MAP))

CASE_2_FILE = File('2.case',
                   CASE_THAT_REGISTERS_VAR_VALUE.format_map(FORMAT_MAP))

SUITE_WITH_CASES = """\
[cases]

{case_1_file}
{case_2_file}
""".format(
    case_1_file=CASE_1_FILE.file_name,
    case_2_file=CASE_2_FILE.file_name,
)

Esempio n. 4
0
    def _run(self,
             suite_file_name: str,
             suite_file_overriding: Optional[Path]):
        default_test_case_handling = setup_with_null_act_phase_and_null_preprocessing()

        suite_conf_instruction = SuiteConfInstructionThatSets(
            preprocessor=preprocessor_that_gives_const_source_with_single_assert_instruction(
                ASSERT_PHASE_INSTRUCTION_THAT_PASS_IFF_STDOUT_IS_SUCCESS_INDICATOR_STRING__NAME),
            act_phase_setup=act_setup_that_prints_single_string_on_stdout(SUCCESS_INDICATOR_STRING))

        suite_conf_instructions = {
            SUITE_CONF_INSTRUCTION_THAT_SETS_PREPROCESSOR_AND_ACTOR__NAME:
                single_instruction_setup(SUITE_CONF_INSTRUCTION_THAT_SETS_PREPROCESSOR_AND_ACTOR__NAME,
                                         suite_conf_instruction)

        }

        suite_conf_parser = configuration_section_parser(suite_conf_instructions)

        test_case_definition = test_case_definition_with_only_assert_phase_instructions([
            (
                ASSERT_PHASE_INSTRUCTION_THAT_PASS_IFF_STDOUT_IS_SUCCESS_INDICATOR_STRING__NAME,
                assert_phase_instruction_that_pass_iff_stdout_is_success_indicator_string(SUCCESS_INDICATOR_STRING)
            ),
            (
                ASSERT_PHASE_INSTRUCTION_THAT_FAILS_UNCONDITIONALLY__NAME,
                ASSERT_PHASE_INSTRUCTION_THAT_FAILS_UNCONDITIONALLY,
            ),
        ])
        processor = sut.Processor(test_case_definition,
                                  os_services_access.new_for_cmd_exe(CommandExecutorThatJustReturnsConstant()),
                                  suite_conf_parser,
                                  2 ** 10)

        suite_file = File(
            suite_file_name,
            test_suite_source_with_single_conf_instruction(
                SUITE_CONF_INSTRUCTION_THAT_SETS_PREPROCESSOR_AND_ACTOR__NAME)
        )
        case_file = File(
            'test.case',
            test_case_source_with_single_assert_phase_instruction(
                ASSERT_PHASE_INSTRUCTION_THAT_FAILS_UNCONDITIONALLY__NAME)
        )

        sub_dir_path = Path('sub-dir')

        suite_and_case_files = DirContents([
            suite_file,
            case_file,
        ]).in_dir(str(sub_dir_path))

        explicit_suite_file_path = None
        if suite_file_overriding:
            explicit_suite_file_path = sub_dir_path / suite_file_overriding

        with tmp_dir_as_cwd(suite_and_case_files) as tmp_dir:
            execution_settings = TestCaseExecutionSettings(sub_dir_path / case_file.name_as_path,
                                                           tmp_dir / sub_dir_path,
                                                           ReportingOption.STATUS_CODE,
                                                           default_test_case_handling,
                                                           run_as_part_of_explicit_suite=explicit_suite_file_path)

            # ACT #
            actual_result = capture_output_from_processor(processor,
                                                          execution_settings)
        # ASSERT #
        if actual_result.exitcode != exit_values.EXECUTION__PASS.exit_code:
            self.fail(_error_message(actual_result))
 def file_structure_to_read(self) -> DirContents:
     return DirContents([
         File('main.suite', lines_content([
             '[invalid-section]',
         ])),
     ])
Esempio n. 6
0
 def file_structure(self, root_path: pathlib.Path) -> DirContents:
     return DirContents([
         File('main.suite',
              lines_content(['[suites]', 'non-existing.suite'])),
     ])
Esempio n. 7
0
 def file_structure(self, root_path: pathlib.Path) -> DirContents:
     return DirContents([
         File('main.suite',
              lines_content(['[cases]', 'invalid-syntax.case'])),
         File('invalid-syntax.case', lines_content(['[invalid section]'])),
     ])
Esempio n. 8
0
    def test_string_transformer_should_be_parsed_as_simple_expression(self):
        the_layout = LayoutSpec.of_default()

        output_from_program = 'untransformed output from the program'

        sym_ref_program_syntax = ProgramOfSymbolReferenceAbsStx(
            'PROGRAM_THAT_EXECUTES_PY_FILE')

        str_trans__unused = StringTransformerSymbolReferenceAbsStx(
            'UNUSED_TRANSFORMER')

        program_w_complex_str_trans_wo_parentheses = program_abs_stx.FullProgramAbsStx(
            ProgramOfSymbolReferenceAbsStx(sym_ref_program_syntax.symbol_name),
            transformation=str_trans_abs_stx.
            StringTransformerCompositionAbsStx(
                [
                    TO_UPPER_TRANSFORMER_SYMBOL.abstract_syntax,
                    str_trans__unused,
                ],
                within_parens=False,
                allow_elements_on_separate_lines=False,
            ))
        expected_remaining_tokens = TokenSequence.concat([
            TokenSequence.singleton(
                str_trans_abs_stx.names.SEQUENCE_OPERATOR_NAME),
            str_trans__unused.tokenization(),
        ])
        expected_remaining_source = expected_remaining_tokens.layout(
            the_layout)

        checker = integration_check.checker__w_arbitrary_file_relativities()

        py_program_file = File(
            'program.py',
            py_programs.py_pgm_with_stdout_stderr_exit_code(
                exit_code=0,
                stdout_output=output_from_program,
                stderr_output=output_from_program,
            ),
        )
        py_file_rel_conf = rel_opt.conf_rel_any(RelOptionType.REL_HDS_CASE)
        py_file_conf = py_file_rel_conf.named_file_conf(py_program_file.name)

        program_symbol__that_executes_py_file = ProgramSymbolContext.of_sdv(
            sym_ref_program_syntax.symbol_name,
            program_sdvs.interpret_py_source_file_that_must_exist(
                py_file_conf.path_sdv))
        symbols = [
            program_symbol__that_executes_py_file,
            TO_UPPER_TRANSFORMER_SYMBOL,
        ]

        for output_file in ProcOutputFile:
            for ignore_exit_code in [False, True]:
                syntax = string_source_abs_stx.StringSourceOfProgramAbsStx(
                    output_file,
                    program_w_complex_str_trans_wo_parentheses,
                    ignore_exit_code=ignore_exit_code,
                )
                with self.subTest(output_file=output_file,
                                  ignore_exit_code=ignore_exit_code):
                    checker.check__abs_stx__wo_input(
                        self,
                        syntax,
                        arrangement_w_tcds(
                            symbols=SymbolContext.symbol_table_of_contexts(
                                symbols),
                            tcds_contents=py_file_rel_conf.
                            populator_for_relativity_option_root(
                                DirContents([py_program_file]))),
                        Expectation(
                            ParseExpectation(
                                source=asrt_source.source_is_not_at_end(
                                    remaining_source=asrt.equals(
                                        expected_remaining_source)),
                                symbol_references=SymbolContext.
                                references_assertion_of_contexts(symbols),
                            )),
                        the_layout,
                    )
Esempio n. 9
0
    def runTest(self):
        # ARRANGE #

        py_file = File('output-env-vars.py',
                       _PGM_THAT_OUTPUTS_ENVIRONMENT_VARS)

        py_file_rel_opt_conf = rel_opt.conf_rel_any(RelOptionType.REL_TMP)
        py_file_conf = py_file_rel_opt_conf.named_file_conf(py_file.name)

        program_symbol = ProgramSymbolContext.of_sdv(
            'PROGRAM_THAT_EXECUTES_PY_FILE',
            program_sdvs.interpret_py_source_file_that_must_exist(
                py_file_conf.path_sdv))
        environment_cases = [
            {
                '1': 'one',
            },
            {
                '1': 'one',
                '2': 'two',
            },
        ]

        for with_ignored_exit_code in [False, True]:
            with self.subTest(with_ignored_exit_code=with_ignored_exit_code):
                # ACT && ASSERT #

                integration_check.CHECKER__PARSE_FULL.check_multi(
                    self,
                    args.syntax_for_run(
                        program_args.symbol_ref_command_elements(
                            program_symbol.name),
                        ignore_exit_code=with_ignored_exit_code,
                    ),
                    ParseExpectation(
                        source=asrt_source.is_at_end_of_line(1),
                        symbol_references=program_symbol.references_assertion,
                    ),
                    model_constructor.arbitrary(self),
                    [
                        NExArr(
                            'Environment: {}'.format(repr(environment)),
                            PrimAndExeExpectation(
                                ExecutionExpectation(
                                    main_result=asrt_string_source.
                                    pre_post_freeze__matches_lines(
                                        _AssertLinesRepresentSubSetOfDict(
                                            environment),
                                        may_depend_on_external_resources=asrt.
                                        equals(True),
                                        frozen_may_depend_on_external_resources
                                        =asrt.anything_goes(),
                                    )),
                                prim_asrt__constant(
                                    asrt_string_transformer.
                                    is_identity_transformer(False)),
                            ),
                            arrangement_w_tcds(
                                tcds_contents=py_file_rel_opt_conf.
                                populator_for_relativity_option_root(
                                    DirContents([py_file])),
                                symbols=program_symbol.symbol_table,
                                process_execution=ProcessExecutionArrangement(
                                    process_execution_settings=
                                    ProcessExecutionSettings.with_environ(
                                        environment))))
                        for environment in environment_cases
                    ],
                )
Esempio n. 10
0
 def file_structure(self, root_path: pathlib.Path) -> DirContents:
     return DirContents([
         File('empty.suite', ''),
     ])
Esempio n. 11
0
 def file_structure(self, root_path: pathlib.Path) -> DirContents:
     return DirContents([
         File('main.suite', lines_content(['[cases]', 'the.case'])),
         File('the.case', ''),
     ])
Esempio n. 12
0
 def tcds_contents(self) -> TcdsPopulator:
     return self._SRC_FILE_REL_CONF.populator_for_relativity_option_root(
         DirContents([
             File(self._CHECKER_PROGRAM_FILE_NAME,
                  self._CHECKER_PROGRAM_PY_SRC)
         ]))
Esempio n. 13
0
 def _dir_contains_exactly_created_file(file_name: str, contents_on_output_channel: str) -> DirContents:
     return DirContents([File(file_name, contents_on_output_channel)])
Esempio n. 14
0
    def _check_exit_codes(self,
                          exit_code_cases: List[int],
                          ignore_exit_code: bool,
                          main_result: Assertion[Optional[TextRenderer]],
                          expected_output_dir_contents: Optional[Callable[[str, str], DirContents]],
                          ):
        # ARRANGE #
        destination_file_name = 'dst-file.txt'

        program_output = {
            ProcOutputFile.STDOUT: 'output on stdout',
            ProcOutputFile.STDERR: 'output on stderr',
        }
        transformer = TO_UPPER_TRANSFORMER_SYMBOL

        sym_ref_program = ProgramOfSymbolReferenceAbsStx('PROGRAM_SYMBOL_NAME')
        program_builder = program_abs_stx.TransformableProgramAbsStxBuilder(
            ProgramOfSymbolReferenceAbsStx(sym_ref_program.symbol_name)
        )
        program_cases = [
            ProgramAndSymbolsCase(
                'without transformation',
                program_builder.without_transformation(),
                [],
                adapt_expected_program_output=lambda s: s
            ),
            ProgramAndSymbolsCase(
                'with transformation',
                program_builder.with_transformation(transformer.abstract_syntax),
                [transformer],
                adapt_expected_program_output=str.upper
            ),
        ]
        program_builder.with_and_without_transformer_cases(transformer.abstract_syntax)

        py_file_rel_conf = rel_opt.conf_rel_any(RelOptionType.REL_HDS_CASE)
        dst_file_rel_conf = ARBITRARY_ALLOWED_DST_FILE_RELATIVITY

        for output_file in ProcOutputFile:
            for exit_code in exit_code_cases:
                py_file = File('exit-with-hard-coded-exit-code.py',
                               py_programs.py_pgm_with_stdout_stderr_exit_code(
                                   exit_code=exit_code,
                                   stdout_output=program_output[ProcOutputFile.STDOUT],
                                   stderr_output=program_output[ProcOutputFile.STDERR],
                               ),
                               )

                py_file_conf = py_file_rel_conf.named_file_conf(py_file.name)
                dst_file_conf = dst_file_rel_conf.named_file_conf(destination_file_name)

                program_symbol = ProgramSymbolContext.of_sdv(
                    sym_ref_program.symbol_name,
                    program_sdvs.interpret_py_source_file_that_must_exist(py_file_conf.path_sdv)
                )

                for program_case in program_cases:
                    instruction_syntax = instr_abs_stx.create_w_explicit_contents(
                        dst_file_conf.abstract_syntax,
                        string_source_abs_stx.StringSourceOfProgramAbsStx(
                            output_file,
                            program_case.syntax,
                            ignore_exit_code=ignore_exit_code)
                    )
                    expected_program_output = program_case.adapt_expected_program_output(program_output[output_file])
                    main_side_effects_on_sds = (
                        dst_file_rel_conf.assert_root_dir_contains_exactly(
                            expected_output_dir_contents(dst_file_conf.name, expected_program_output)
                        )
                        if expected_output_dir_contents is not None
                        else
                        asrt.anything_goes()
                    )
                    symbol_contexts = [program_symbol] + program_case.additional_symbols
                    # ACT && ASSERT #
                    for phase_is_after_act in [False, True]:
                        checker = integration_check.checker(phase_is_after_act)
                        checker.check__abs_stx__std_layouts_and_source_variants(
                            self,
                            instruction_syntax,
                            Arrangement.phase_agnostic(
                                symbols=SymbolContext.symbol_table_of_contexts(symbol_contexts),
                                tcds=TcdsArrangement(
                                    tcds_contents=py_file_rel_conf.populator_for_relativity_option_root(
                                        DirContents([py_file])
                                    )
                                ),
                            ),
                            MultiSourceExpectation.phase_agnostic(
                                symbol_usages=SymbolContext.usages_assertion_of_contexts(symbol_contexts),
                                main_result=main_result,
                                main_side_effects_on_sds=main_side_effects_on_sds,
                            ),
                            sub_test_identifiers={
                                'exit_code': exit_code,
                                'output_file': output_file,
                                'program': program_case.name,
                                'phase_is_after_act': phase_is_after_act,
                            },
                        )
    def _check_exit_codes(self,
                          exit_code_cases: List[int],
                          ignore_exit_code: bool,
                          expected_primitive: Callable[[str], Assertion[StringSource]],
                          ):
        # ARRANGE #

        program_output = {
            ProcOutputFile.STDOUT: 'output on stdout',
            ProcOutputFile.STDERR: 'output on stderr',
        }
        transformer = TO_UPPER_TRANSFORMER_SYMBOL

        sym_ref_program = ProgramOfSymbolReferenceAbsStx('PROGRAM_SYMBOL_NAME')
        program_builder = program_abs_stx.TransformableProgramAbsStxBuilder(
            ProgramOfSymbolReferenceAbsStx(sym_ref_program.symbol_name)
        )
        program_cases = [
            ProgramAndSymbolsCase(
                'without transformation',
                program_builder.without_transformation(),
                [],
                adapt_expected_program_output=lambda s: s
            ),
            ProgramAndSymbolsCase(
                'with transformation',
                program_builder.with_transformation(transformer.abstract_syntax),
                [transformer],
                adapt_expected_program_output=str.upper
            ),
        ]
        program_builder.with_and_without_transformer_cases(transformer.abstract_syntax)

        py_file_rel_conf = rel_opt.conf_rel_any(RelOptionType.REL_HDS_CASE)

        for exit_code in exit_code_cases:
            py_file = File('exit-with-hard-coded-exit-code.py',
                           py_programs.py_pgm_with_stdout_stderr_exit_code(
                               exit_code=exit_code,
                               stdout_output=program_output[ProcOutputFile.STDOUT],
                               stderr_output=program_output[ProcOutputFile.STDERR],
                           ),
                           )

            py_file_conf = py_file_rel_conf.named_file_conf(py_file.name)

            program_symbol = ProgramSymbolContext.of_sdv(
                sym_ref_program.symbol_name,
                program_sdvs.interpret_py_source_file_that_must_exist(py_file_conf.path_sdv)
            )
            for output_file in ProcOutputFile:
                for program_case in program_cases:
                    syntax = string_source_abs_stx.StringSourceOfProgramAbsStx(
                        output_file,
                        program_case.syntax,
                        ignore_exit_code=ignore_exit_code,
                    )
                    expected_program_output = program_case.adapt_expected_program_output(program_output[output_file])
                    symbol_contexts = [program_symbol] + program_case.additional_symbols
                    # ACT && ASSERT #
                    checker = integration_check.checker__w_arbitrary_file_relativities()
                    with self.subTest(exit_code=exit_code,
                                      output_file=output_file,
                                      program=program_case.name):
                        checker.check__abs_stx(
                            self,
                            syntax,
                            None,
                            arrangement_w_tcds(
                                symbols=SymbolContext.symbol_table_of_contexts(symbol_contexts),
                                tcds_contents=py_file_rel_conf.populator_for_relativity_option_root(
                                    DirContents([py_file])
                                )
                            ),
                            Expectation(
                                ParseExpectation(
                                    symbol_references=SymbolContext.references_assertion_of_contexts(symbol_contexts),
                                ),
                                primitive=prim_asrt__constant(
                                    expected_primitive(expected_program_output)
                                ),
                            ),
                        ),
    def test_syntax_layout_variants(self):
        # ARRANGE #
        exit_code_from_program = 1
        output_from_program = 'the output from the program'
        transformer = TO_UPPER_TRANSFORMER_SYMBOL

        sym_ref_program = ProgramOfSymbolReferenceAbsStx('PROGRAM_SYMBOL_NAME')
        program_builder = program_abs_stx.TransformableProgramAbsStxBuilder(
            ProgramOfSymbolReferenceAbsStx(sym_ref_program.symbol_name)
        )
        output_cases = [
            OutputFileCase(
                ProcOutputFile.STDOUT,
                {
                    ProcOutputFile.STDOUT: output_from_program,
                    ProcOutputFile.STDERR: '',
                }
            ),
            OutputFileCase(
                ProcOutputFile.STDERR,
                {
                    ProcOutputFile.STDOUT: '',
                    ProcOutputFile.STDERR: output_from_program,
                }
            ),
        ]
        program_cases = [
            ProgramAndSymbolsCase(
                'without transformation',
                program_builder.without_transformation(),
                [],
                adapt_expected_program_output=lambda s: s
            ),
            ProgramAndSymbolsCase(
                'with transformation',
                program_builder.with_transformation(transformer.abstract_syntax),
                [transformer],
                adapt_expected_program_output=str.upper
            ),
        ]
        py_file_rel_conf = rel_opt.conf_rel_any(RelOptionType.REL_HDS_CASE)

        for output_case in output_cases:
            py_file = File('exit-with-hard-coded-exit-code.py',
                           py_programs.py_pgm_with_stdout_stderr_exit_code_2(
                               exit_code=exit_code_from_program,
                               output=output_case.program_output,
                           ),
                           )

            py_file_conf = py_file_rel_conf.named_file_conf(py_file.name)

            program_symbol = ProgramSymbolContext.of_sdv(
                sym_ref_program.symbol_name,
                program_sdvs.interpret_py_source_file_that_must_exist(py_file_conf.path_sdv)
            )
            for program_case in program_cases:
                syntax = string_source_abs_stx.StringSourceOfProgramAbsStx(
                    output_case.output_file,
                    program_case.syntax,
                    ignore_exit_code=True,
                )
                expected_program_output = program_case.adapt_expected_program_output(output_from_program)
                symbol_contexts = [program_symbol] + program_case.additional_symbols
                # ACT && ASSERT #
                checker = integration_check.checker__w_arbitrary_file_relativities()
                with self.subTest(output_file=output_case.output_file,
                                  program=program_case.name):
                    checker.check__abs_stx__layouts__source_variants__wo_input(
                        self,
                        equivalent_source_variants__for_full_line_expr_parse__s__nsc,
                        OptionallyOnNewLine(syntax),
                        arrangement_w_tcds(
                            symbols=SymbolContext.symbol_table_of_contexts(symbol_contexts),
                            tcds_contents=py_file_rel_conf.populator_for_relativity_option_root(
                                DirContents([py_file])
                            )
                        ),
                        MultiSourceExpectation.of_const(
                            symbol_references=SymbolContext.references_assertion_of_contexts(symbol_contexts),
                            primitive=asrt_string_source.pre_post_freeze__matches_str__const_2(
                                expected_program_output,
                                may_depend_on_external_resources=True,
                                frozen_may_depend_on_external_resources=asrt.anything_goes(),
                            ),
                        ),
                    ),