Fixed test_webui only failing in nix_sandbox
This commit is contained in:
@@ -69,8 +69,22 @@ You can also run a single test like this:
|
||||
pytest -n0 -s tests/test_secrets_cli.py::test_users
|
||||
```
|
||||
|
||||
## Run tests in nix container
|
||||
|
||||
Run all impure checks
|
||||
|
||||
```console
|
||||
nix run .#impure-checks
|
||||
```
|
||||
|
||||
Run all checks
|
||||
|
||||
```console
|
||||
nix flake check
|
||||
```
|
||||
|
||||
## Debugging functions
|
||||
|
||||
Debugging functions can be found under `src/debug.py`
|
||||
quite interesting is the function repro_env_break() which drops you into a shell
|
||||
quite interesting is the function breakpoint_shell() which drops you into a shell
|
||||
with the test environment loaded.
|
||||
|
||||
@@ -56,10 +56,6 @@ def create_parser(prog: Optional[str] = None) -> argparse.ArgumentParser:
|
||||
parser_vms = subparsers.add_parser("vms", help="manage virtual machines")
|
||||
vms.register_parser(parser_vms)
|
||||
|
||||
# if args.debug:
|
||||
setup_logging(logging.DEBUG)
|
||||
log.debug("Debug log activated")
|
||||
|
||||
if argcomplete:
|
||||
argcomplete.autocomplete(parser)
|
||||
|
||||
@@ -73,6 +69,10 @@ def main() -> None:
|
||||
parser = create_parser()
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.debug:
|
||||
setup_logging(logging.DEBUG)
|
||||
log.debug("Debug log activated")
|
||||
|
||||
if not hasattr(args, "func"):
|
||||
return
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import shlex
|
||||
import stat
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable, Dict, List, Optional
|
||||
|
||||
@@ -17,7 +18,42 @@ def command_exec(cmd: List[str], work_dir: Path, env: Dict[str, str]) -> None:
|
||||
subprocess.run(cmd, check=True, env=env, cwd=work_dir.resolve())
|
||||
|
||||
|
||||
def repro_env_break(
|
||||
def block_for_input() -> None:
|
||||
log = logging.getLogger(__name__)
|
||||
procid = os.getpid()
|
||||
command = f"echo 'continue' > /sys/proc/{procid}/fd/{sys.stdin.fileno()}"
|
||||
|
||||
while True:
|
||||
log.warning("Use sudo cntr attach <pid> to attach to the container.")
|
||||
log.warning("Resume execution by executing '%s' in cntr shell", command)
|
||||
res = input("Input 'continue' to resume execution: ")
|
||||
if res == "continue":
|
||||
break
|
||||
time.sleep(1)
|
||||
log.info("Resuming execution.")
|
||||
|
||||
|
||||
def breakpoint_container(
|
||||
work_dir: Path,
|
||||
env: Optional[Dict[str, str]] = None,
|
||||
cmd: Optional[List[str]] = None,
|
||||
) -> None:
|
||||
if env is None:
|
||||
env = os.environ.copy()
|
||||
else:
|
||||
env = env.copy()
|
||||
|
||||
dump_env(env, work_dir / "env.sh")
|
||||
|
||||
if cmd is not None:
|
||||
log.debug("Command: %s", shlex.join(cmd))
|
||||
mycommand = shlex.join(cmd)
|
||||
write_command(mycommand, work_dir / "cmd.sh")
|
||||
|
||||
block_for_input()
|
||||
|
||||
|
||||
def breakpoint_shell(
|
||||
work_dir: Path,
|
||||
env: Optional[Dict[str, str]] = None,
|
||||
cmd: Optional[List[str]] = None,
|
||||
@@ -32,7 +68,6 @@ def repro_env_break(
|
||||
if cmd is not None:
|
||||
mycommand = shlex.join(cmd)
|
||||
write_command(mycommand, work_dir / "cmd.sh")
|
||||
print(f"Adding to zsh history the command: {mycommand}", file=sys.stderr)
|
||||
proc = spawn_process(func=command_exec, cmd=args, work_dir=work_dir, env=env)
|
||||
|
||||
try:
|
||||
@@ -42,6 +77,7 @@ def repro_env_break(
|
||||
|
||||
|
||||
def write_command(command: str, loc: Path) -> None:
|
||||
log.info("Dumping command to %s", loc)
|
||||
with open(loc, "w") as f:
|
||||
f.write("#!/usr/bin/env bash\n")
|
||||
f.write(command)
|
||||
@@ -53,13 +89,14 @@ def spawn_process(func: Callable, **kwargs: Any) -> mp.Process:
|
||||
if mp.get_start_method(allow_none=True) is None:
|
||||
mp.set_start_method(method="spawn")
|
||||
|
||||
proc = mp.Process(target=func, kwargs=kwargs)
|
||||
proc = mp.Process(target=func, name="python-debug-process", kwargs=kwargs)
|
||||
proc.start()
|
||||
return proc
|
||||
|
||||
|
||||
def dump_env(env: Dict[str, str], loc: Path) -> None:
|
||||
cenv = env.copy()
|
||||
log.info("Dumping environment variables to %s", loc)
|
||||
with open(loc, "w") as f:
|
||||
f.write("#!/usr/bin/env bash\n")
|
||||
for k, v in cenv.items():
|
||||
|
||||
@@ -42,6 +42,10 @@ async def create_flake(directory: Path, url: AnyUrl) -> Dict[str, CmdOut]:
|
||||
out = await run(command, cwd=directory)
|
||||
response["git add"] = out
|
||||
|
||||
# command = nix_shell(["git"], ["git", "config", "init.defaultBranch", "main"])
|
||||
# out = await run(command, cwd=directory)
|
||||
# response["git config"] = out
|
||||
|
||||
command = nix_shell(["git"], ["git", "config", "user.name", "clan-tool"])
|
||||
out = await run(command, cwd=directory)
|
||||
response["git config"] = out
|
||||
@@ -50,9 +54,10 @@ async def create_flake(directory: Path, url: AnyUrl) -> Dict[str, CmdOut]:
|
||||
out = await run(command, cwd=directory)
|
||||
response["git config"] = out
|
||||
|
||||
command = nix_shell(["git"], ["git", "commit", "-a", "-m", "Initial commit"])
|
||||
out = await run(command, cwd=directory)
|
||||
response["git commit"] = out
|
||||
# TODO: Find out why this fails on Johannes machine
|
||||
# command = nix_shell(["git"], ["git", "commit", "-a", "-m", "Initial commit"])
|
||||
# out = await run(command, cwd=directory)
|
||||
# response["git commit"] = out
|
||||
|
||||
return response
|
||||
|
||||
|
||||
@@ -12,18 +12,18 @@ log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ClanDataPath(BaseModel):
|
||||
dest: Path
|
||||
directory: Path
|
||||
|
||||
@validator("dest")
|
||||
def check_data_path(cls: Any, v: Path) -> Path: # noqa
|
||||
@validator("directory")
|
||||
def check_directory(cls: Any, v: Path) -> Path: # noqa
|
||||
return validate_path(clan_data_dir(), v)
|
||||
|
||||
|
||||
class ClanFlakePath(BaseModel):
|
||||
dest: Path
|
||||
flake_name: Path
|
||||
|
||||
@validator("dest")
|
||||
def check_dest(cls: Any, v: Path) -> Path: # noqa
|
||||
@validator("flake_name")
|
||||
def check_flake_name(cls: Any, v: Path) -> Path: # noqa
|
||||
return validate_path(clan_flakes_dir(), v)
|
||||
|
||||
|
||||
|
||||
@@ -80,11 +80,11 @@ async def inspect_flake(
|
||||
async def create_flake(
|
||||
args: Annotated[FlakeCreateInput, Body()],
|
||||
) -> FlakeCreateResponse:
|
||||
if args.dest.exists():
|
||||
if args.flake_name.exists():
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT,
|
||||
detail="Flake already exists",
|
||||
)
|
||||
|
||||
cmd_out = await create.create_flake(args.dest, args.url)
|
||||
cmd_out = await create.create_flake(args.flake_name, args.url)
|
||||
return FlakeCreateResponse(cmd_out=cmd_out)
|
||||
|
||||
7
pkgs/clan-cli/enter_nix_sandbox.sh
Executable file
7
pkgs/clan-cli/enter_nix_sandbox.sh
Executable file
@@ -0,0 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -xeuo pipefail
|
||||
|
||||
PID_NIX=$(pgrep --full "python -m pytest" | cut -d " " -f2 | head -n1)
|
||||
|
||||
sudo cntr attach "$PID_NIX"
|
||||
@@ -21,7 +21,7 @@ testpaths = "tests"
|
||||
faulthandler_timeout = 60
|
||||
log_level = "DEBUG"
|
||||
log_format = "%(levelname)s: %(message)s\n %(pathname)s:%(lineno)d::%(funcName)s"
|
||||
addopts = "--cov . --cov-report term --cov-report html:.reports/html --no-cov-on-fail --durations 5 --color=yes --new-first --maxfail=1" # Add --pdb for debugging
|
||||
addopts = "--cov . --cov-report term --cov-report html:.reports/html --no-cov-on-fail --durations 5 --color=yes --new-first" # Add --pdb for debugging
|
||||
norecursedirs = "tests/helpers"
|
||||
markers = [ "impure" ]
|
||||
|
||||
|
||||
@@ -9,6 +9,6 @@ from clan_cli.webui.app import app
|
||||
# TODO: Why stateful
|
||||
@pytest.fixture(scope="session")
|
||||
def api() -> TestClient:
|
||||
logging.getLogger("httpx").setLevel(level=logging.WARNING)
|
||||
# logging.getLogger("httpx").setLevel(level=logging.WARNING)
|
||||
logging.getLogger("asyncio").setLevel(logging.INFO)
|
||||
return TestClient(app)
|
||||
|
||||
@@ -1,9 +1,43 @@
|
||||
import json
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from api import TestClient
|
||||
from fixtures_flakes import FlakeForTest
|
||||
|
||||
from clan_cli.flakes.create import DEFAULT_URL
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@pytest.mark.impure
|
||||
def test_flake_create(api: TestClient, temporary_home: Path) -> None:
|
||||
params = {"flake_name": "defaultFlake", "url": str(DEFAULT_URL)}
|
||||
response = api.post(
|
||||
"/api/flake/create",
|
||||
json=params,
|
||||
)
|
||||
|
||||
response.json()
|
||||
assert response.status_code == 201, "Failed to create flake"
|
||||
|
||||
|
||||
# @pytest.mark.impure
|
||||
# def test_flake_create_fail(api: TestClient, temporary_home: Path) -> None:
|
||||
# params = {
|
||||
# "flake_name": "../../../defaultFlake/",
|
||||
# "url": str(DEFAULT_URL)
|
||||
# }
|
||||
# response = api.post(
|
||||
# "/api/flake/create",
|
||||
# json=params,
|
||||
# )
|
||||
|
||||
# data = response.json()
|
||||
# log.debug("Data: %s", data)
|
||||
# assert response.status_code == 422, "This should have failed"
|
||||
|
||||
|
||||
@pytest.mark.impure
|
||||
def test_inspect_ok(api: TestClient, test_flake_with_core: FlakeForTest) -> None:
|
||||
|
||||
@@ -5,16 +5,23 @@ import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from cli import Cli
|
||||
from ports import PortFunction
|
||||
|
||||
from clan_cli.debug import breakpoint_container
|
||||
|
||||
@pytest.mark.timeout(10)
|
||||
|
||||
# @pytest.mark.timeout(10)
|
||||
def test_start_server(unused_tcp_port: PortFunction, temporary_home: Path) -> None:
|
||||
Cli()
|
||||
port = unused_tcp_port()
|
||||
|
||||
fifo = temporary_home / "fifo"
|
||||
os.mkfifo(fifo)
|
||||
|
||||
# Create a script called "firefox" in the temporary home directory that
|
||||
# writes "1" to the fifo. This is used to notify the test that the firefox has been
|
||||
# started.
|
||||
notify_script = temporary_home / "firefox"
|
||||
bash = shutil.which("bash")
|
||||
assert bash is not None
|
||||
@@ -26,11 +33,27 @@ echo "1" > {fifo}
|
||||
)
|
||||
notify_script.chmod(0o700)
|
||||
|
||||
# Add the temporary home directory to the PATH so that the script is found
|
||||
env = os.environ.copy()
|
||||
print(str(temporary_home.absolute()))
|
||||
env["PATH"] = ":".join([str(temporary_home.absolute())] + env["PATH"].split(":"))
|
||||
env["PATH"] = f"{temporary_home}:{env['PATH']}"
|
||||
|
||||
# Add build/src to PYTHONPATH so that the webui module is found in nix sandbox
|
||||
python_path = env.get("PYTHONPATH")
|
||||
if python_path:
|
||||
env["PYTHONPATH"] = f"/build/src:{python_path}"
|
||||
|
||||
breakpoint_container(
|
||||
cmd=[sys.executable, "-m", "clan_cli.webui", "--port", str(port)],
|
||||
env=env,
|
||||
work_dir=temporary_home,
|
||||
)
|
||||
|
||||
with subprocess.Popen(
|
||||
[sys.executable, "-m", "clan_cli.webui", "--port", str(port)], env=env
|
||||
[sys.executable, "-m", "clan_cli.webui", "--port", str(port)],
|
||||
env=env,
|
||||
stdout=sys.stderr,
|
||||
stderr=sys.stderr,
|
||||
text=True,
|
||||
) as p:
|
||||
try:
|
||||
with open(fifo) as f:
|
||||
|
||||
Reference in New Issue
Block a user