import pytest from mirage.io.stream import materialize from mirage.workspace.executor.builtins.vars import (handle_read, handle_return, handle_shift) from mirage.workspace.executor.control import ReturnSignal from mirage.workspace.session.session import Session def make_session() -> Session: return Session(session_id="s1") @pytest.mark.asyncio async def test_shift_non_numeric_errors_like_bash(): _, io, _ = await handle_shift(["x"], None, session=make_session()) assert io.exit_code == 1 assert (await materialize(io.stderr)) == b"shift: x: numeric argument required\n" @pytest.mark.asyncio async def test_shift_too_many_arguments(): _, io, _ = await handle_shift(["1", "2"], None, session=make_session()) assert io.exit_code == 1 assert await materialize(io.stderr) == b"shift: too many arguments\n" @pytest.mark.asyncio async def test_shift_default_one(): session = make_session() session.positional_args = ["a", "b"] _, io, _ = await handle_shift([], None, session=session) assert io.exit_code == 0 assert session.positional_args == ["b"] @pytest.mark.asyncio async def test_return_non_numeric_raises_2_with_message(): with pytest.raises(ReturnSignal) as exc: await handle_return(["x"]) assert exc.value.exit_code == 2 assert exc.value.stderr == b"return: x: numeric argument required\n" @pytest.mark.asyncio async def test_return_numeric(): with pytest.raises(ReturnSignal) as exc: await handle_return(["7"]) assert exc.value.exit_code == 7 assert exc.value.stderr == b"" @pytest.mark.asyncio async def test_read_invalid_option_exits_2(): _, io, _ = await handle_read(["-q", "v"], make_session(), b"line\n") assert io.exit_code == 2 assert await materialize(io.stderr) == b"read: -q: invalid option\n" @pytest.mark.asyncio async def test_read_dash_r_consumed_not_a_variable(): session = make_session() _, io, _ = await handle_read(["-r", "v"], session, b"hello world\n") assert io.exit_code == 0 assert session.env["v"] == "hello world" assert "-r" not in session.env @pytest.mark.asyncio async def test_read_defaults_to_reply(): session = make_session() _, io, _ = await handle_read([], session, b"hi\n") assert io.exit_code == 0 assert session.env["REPLY"] == "hi"