def test_view_of_view(matrix_type, subset_func, subset_func2):
    adata = gen_adata((30, 15), X_type=matrix_type)
    adata.raw = adata
    if subset_func is single_subset:
        pytest.xfail("Other subset generating functions have trouble with this")
    var_s1 = subset_func(adata.var_names, min_size=4)
    var_view1 = adata[:, var_s1]
    var_s2 = subset_func2(var_view1.var_names)
    var_view2 = var_view1[:, var_s2]
    assert var_view2._adata_ref is adata
    obs_s1 = subset_func(adata.obs_names, min_size=4)
    obs_view1 = adata[obs_s1, :]
    obs_s2 = subset_func2(obs_view1.obs_names)
    assert adata[obs_s1, :][:, var_s1][obs_s2, :]._adata_ref is adata

    view_of_actual_copy = adata[:, var_s1].copy()[obs_s1, :].copy()[:, var_s2].copy()

    view_of_view_copy = adata[:, var_s1][obs_s1, :][:, var_s2].copy()

    assert_equal(view_of_actual_copy, view_of_view_copy, exact=True)
def _exit_with_failure(cls, terminal_msg):
        timestamp_msg = (
            f"timestamp: {cls._iso_timestamp_for_now()}\n"
            if cls._should_print_backtrace_to_terminal
            else ""
        )
        details_msg = (
            ""
            if cls._should_print_backtrace_to_terminal
            else "\n\n(Use --print-exception-stacktrace to see more error details.)"
        )
        terminal_msg = terminal_msg or "<no exit reason provided>"
        formatted_terminal_msg = cls._EXIT_FAILURE_TERMINAL_MESSAGE_FORMAT.format(
            timestamp_msg=timestamp_msg, terminal_msg=terminal_msg, details_msg=details_msg
        )
        # Exit with failure, printing a message to the terminal (or whatever the interactive stream is).
        cls._exiter.exit_and_fail(msg=formatted_terminal_msg, out=cls._interactive_output_stream)