"""File manager: ls parsing and chmod schema validation.""" from __future__ import annotations import pytest from pydantic import ValidationError from server.api.schemas import FileChmod from server.utils.unix_ls import modified_from_ls_parts, parse_ls_la_line def test_parse_ls_la_line_file_classic(): line = "-rw-r--r-- 1 www www 1234 Jun 1 12:00 index.php" row = parse_ls_la_line(line) assert row is not None assert row["name"] == "index.php" assert row["owner"] == "www" assert row["group"] == "www" assert row["modified"] == "Jun 1 12:00" def test_parse_ls_la_line_long_iso(): line = "-rw-r--r-- 1 www www 99 2026-06-01 12:00:00.123456789 +0800 app.log" row = parse_ls_la_line(line) assert row is not None assert row["name"] == "app.log" assert row["modified"] == "2026-06-01 12:00:00" def test_parse_ls_la_line_symlink(): line = "lrwxrwxrwx 1 root root 8 2026-06-01 10:00:00 +0800 current -> release" row = parse_ls_la_line(line) assert row is not None assert row["is_link"] is True assert row["name"] == "current" assert row["link_target"] == "release" def test_parse_ls_la_line_name_with_spaces(): line = '-rw-r--r-- 1 www www 1 2026-06-01 09:00:00 +0800 my file.txt' row = parse_ls_la_line(line) assert row is not None assert row["name"] == "my file.txt" def test_parse_ls_la_line_skips_dot_dirs(): assert parse_ls_la_line("drwxr-xr-x 2 www www 4096 Jun 1 12:00 .") is None assert parse_ls_la_line("total 12") is None def test_modified_from_ls_parts_iso(): parts = "-rw-r--r-- 1 www www 1 2026-06-01 15:30:45.999 +0800".split(None, 8)[:8] assert modified_from_ls_parts(parts) == "2026-06-01 15:30:45" def test_file_chmod_group_requires_owner(): with pytest.raises(ValidationError): FileChmod(server_id=1, path="/tmp/x", mode="644", group="www") def test_file_chmod_valid_chown(): m = FileChmod(server_id=1, path="/tmp/x", mode="755", owner="www", group="www") assert m.owner == "www" def test_file_chmod_recursive_flag(): m = FileChmod(server_id=1, path="/var/www/html", mode="755", recursive=True) assert m.recursive is True def test_assert_recursive_chmod_forbidden_root(): from server.utils.files_chmod_policy import assert_recursive_chmod_allowed with pytest.raises(ValueError, match="禁止"): assert_recursive_chmod_allowed("/") def test_assert_recursive_chmod_forbidden_system_subtree(): from server.utils.files_chmod_policy import assert_recursive_chmod_allowed with pytest.raises(ValueError, match="禁止"): assert_recursive_chmod_allowed("/etc/nginx") def test_assert_recursive_chmod_allows_common_web_roots(): from server.utils.files_chmod_policy import assert_recursive_chmod_allowed assert_recursive_chmod_allowed("/www/wwwroot/site") assert_recursive_chmod_allowed("/var/www/html")