Files
rohit267-champdev-comfyui-n…/tests/test_fm_core.py
2026-05-23 12:08:47 +05:30

301 lines
9.1 KiB
Python

import fm_core
import os
import pytest
def test_classify_kind_by_extension():
assert fm_core.classify_kind("a.png") == "image"
assert fm_core.classify_kind("b.JPG") == "image"
assert fm_core.classify_kind("c.mp4") == "video"
assert fm_core.classify_kind("d.wav") == "audio"
assert fm_core.classify_kind("e.txt") == "text"
assert fm_core.classify_kind("f.bin") == "other"
assert fm_core.classify_kind("noext") == "other"
def test_safe_realpath_normalizes_and_expands(tmp_path):
sub = tmp_path / "a" / ".." / "b"
(tmp_path / "b").mkdir()
resolved = fm_core.safe_realpath(str(sub))
assert resolved == os.path.realpath(str(tmp_path / "b"))
def test_safe_realpath_rejects_empty():
with pytest.raises(ValueError):
fm_core.safe_realpath("")
def test_list_dir_returns_sorted_entries(tmp_path):
(tmp_path / "z_folder").mkdir()
(tmp_path / "a.png").write_bytes(b"x")
(tmp_path / "b.txt").write_text("hello")
(tmp_path / ".hidden").write_text("secret")
result = fm_core.list_dir(str(tmp_path))
assert result["cwd"] == os.path.realpath(str(tmp_path))
assert result["parent"] == os.path.realpath(str(tmp_path.parent))
names = [e["name"] for e in result["entries"]]
# folders first, then files; hidden excluded by default
assert names == ["z_folder", "a.png", "b.txt"]
folder = result["entries"][0]
assert folder["is_dir"] is True
assert folder["kind"] == "folder"
png = result["entries"][1]
assert png["is_dir"] is False
assert png["kind"] == "image"
assert png["size"] == 1
assert png["ext"] == ".png"
assert "mtime" in png and "ctime" in png
def test_list_dir_can_include_hidden(tmp_path):
(tmp_path / ".hidden").write_text("secret")
names = [e["name"] for e in fm_core.list_dir(str(tmp_path), show_hidden=True)["entries"]]
assert ".hidden" in names
def test_list_dir_errors_on_missing_and_nondir(tmp_path):
with pytest.raises(FileNotFoundError):
fm_core.list_dir(str(tmp_path / "nope"))
f = tmp_path / "f.txt"
f.write_text("x")
with pytest.raises(NotADirectoryError):
fm_core.list_dir(str(f))
def test_get_properties_of_file(tmp_path):
f = tmp_path / "note.txt"
f.write_text("hello")
props = fm_core.get_properties(str(f))
assert props["name"] == "note.txt"
assert props["kind"] == "text"
assert props["size"] == 5
assert props["is_dir"] is False
def test_get_properties_includes_image_dimensions(tmp_path):
from PIL import Image
img = tmp_path / "pic.png"
Image.new("RGB", (12, 7)).save(str(img))
props = fm_core.get_properties(str(img))
assert props["kind"] == "image"
assert props["width"] == 12
assert props["height"] == 7
def test_get_properties_missing_raises(tmp_path):
with pytest.raises(FileNotFoundError):
fm_core.get_properties(str(tmp_path / "nope.txt"))
def test_delete_paths_removes_files_and_folders(tmp_path):
f = tmp_path / "f.txt"
f.write_text("x")
d = tmp_path / "d"
d.mkdir()
(d / "inner.txt").write_text("y")
results = fm_core.delete_paths([str(f), str(d)])
assert all(r["ok"] for r in results)
assert not f.exists()
assert not d.exists()
def test_delete_paths_reports_errors(tmp_path):
results = fm_core.delete_paths([str(tmp_path / "missing")])
assert results[0]["ok"] is False
assert "error" in results[0]
def test_rename_path_renames_in_place(tmp_path):
f = tmp_path / "old.txt"
f.write_text("x")
res = fm_core.rename_path(str(f), "new.txt")
assert res["ok"] is True
assert os.path.basename(res["path"]) == "new.txt"
assert (tmp_path / "new.txt").exists()
assert not f.exists()
def test_rename_path_rejects_separators(tmp_path):
f = tmp_path / "old.txt"
f.write_text("x")
with pytest.raises(ValueError):
fm_core.rename_path(str(f), "sub/new.txt")
def test_rename_path_rejects_existing_target(tmp_path):
a = tmp_path / "a.txt"
a.write_text("x")
(tmp_path / "b.txt").write_text("y")
with pytest.raises(FileExistsError):
fm_core.rename_path(str(a), "b.txt")
def test_make_dir_creates_folder(tmp_path):
res = fm_core.make_dir(str(tmp_path), "newfolder")
assert res["ok"] is True
assert os.path.isdir(res["path"])
assert os.path.basename(res["path"]) == "newfolder"
def test_make_dir_rejects_separators(tmp_path):
with pytest.raises(ValueError):
fm_core.make_dir(str(tmp_path), "a/b")
def test_make_dir_rejects_existing(tmp_path):
(tmp_path / "dup").mkdir()
with pytest.raises(OSError):
fm_core.make_dir(str(tmp_path), "dup")
def test_move_paths_moves_file(tmp_path):
src = tmp_path / "f.txt"
src.write_text("x")
dest = tmp_path / "dest"
dest.mkdir()
results = fm_core.move_paths([str(src)], str(dest))
assert results[0]["ok"] is True
assert (dest / "f.txt").exists()
assert not src.exists()
def test_move_paths_copies_when_copy_true(tmp_path):
src = tmp_path / "f.txt"
src.write_text("x")
dest = tmp_path / "dest"
dest.mkdir()
results = fm_core.move_paths([str(src)], str(dest), copy=True)
assert results[0]["ok"] is True
assert (dest / "f.txt").exists()
assert src.exists() # original kept
def test_move_paths_reports_conflict(tmp_path):
src = tmp_path / "f.txt"
src.write_text("x")
dest = tmp_path / "dest"
dest.mkdir()
(dest / "f.txt").write_text("existing")
results = fm_core.move_paths([str(src)], str(dest))
assert results[0]["ok"] is False
assert "error" in results[0]
assert src.exists()
def test_move_paths_dest_must_be_dir(tmp_path):
src = tmp_path / "f.txt"
src.write_text("x")
with pytest.raises(NotADirectoryError):
fm_core.move_paths([str(src)], str(tmp_path / "nope"))
def test_save_upload_bytes_writes_file(tmp_path):
res = fm_core.save_upload_bytes(str(tmp_path), "up.bin", b"hello")
assert res["ok"] is True
assert (tmp_path / "up.bin").read_bytes() == b"hello"
def test_save_upload_bytes_strips_path_components(tmp_path):
res = fm_core.save_upload_bytes(str(tmp_path), "../escape.txt", b"x")
# filename is reduced to its basename; nothing escapes the dest
assert os.path.dirname(res["path"]) == os.path.realpath(str(tmp_path))
assert os.path.basename(res["path"]) == "escape.txt"
def test_save_upload_bytes_dest_must_be_dir(tmp_path):
with pytest.raises(NotADirectoryError):
fm_core.save_upload_bytes(str(tmp_path / "nope"), "a.txt", b"x")
def test_make_thumbnail_creates_cached_jpeg(tmp_path):
from PIL import Image
src = tmp_path / "big.png"
Image.new("RGB", (1000, 500), "red").save(str(src))
cache = tmp_path / "cache"
out = fm_core.make_thumbnail(str(src), str(cache), size=128)
assert os.path.isfile(out)
with Image.open(out) as im:
assert max(im.size) <= 128
# second call returns the same cached path without error
out2 = fm_core.make_thumbnail(str(src), str(cache), size=128)
assert out2 == out
def test_make_thumbnail_rejects_non_image(tmp_path):
f = tmp_path / "f.txt"
f.write_text("x")
with pytest.raises(ValueError):
fm_core.make_thumbnail(str(f), str(tmp_path / "cache"))
# --- Change 1: symlink deletion operates on the link, not its target ---
def test_delete_paths_removes_symlink_not_target(tmp_path):
target_dir = tmp_path / "target"
target_dir.mkdir()
(target_dir / "keep.txt").write_text("important")
link = tmp_path / "link"
os.symlink(str(target_dir), str(link))
results = fm_core.delete_paths([str(link)])
assert results[0]["ok"] is True
assert not link.exists() # link removed
assert target_dir.exists() # target tree preserved
assert (target_dir / "keep.txt").read_text() == "important"
# --- Change 2: save_upload_bytes does not overwrite existing files ---
def test_save_upload_bytes_does_not_overwrite(tmp_path):
(tmp_path / "up.bin").write_bytes(b"original")
res = fm_core.save_upload_bytes(str(tmp_path), "up.bin", b"new")
assert (tmp_path / "up.bin").read_bytes() == b"original" # untouched
assert os.path.basename(res["path"]) == "up_00001.bin"
assert (tmp_path / "up_00001.bin").read_bytes() == b"new"
# --- Change 4: _reject_separators also rejects "." and ".." ---
def test_rename_path_rejects_dot_dot(tmp_path):
f = tmp_path / "old.txt"
f.write_text("x")
with pytest.raises(ValueError):
fm_core.rename_path(str(f), "..")
with pytest.raises(ValueError):
fm_core.rename_path(str(f), ".")
# --- Change 5: list_dir sort by mtime orders file entries by mtime ---
def test_list_dir_sort_by_mtime(tmp_path):
f1 = tmp_path / "alpha.txt"
f2 = tmp_path / "beta.txt"
f1.write_text("a")
f2.write_text("b")
# set f1 mtime older, f2 mtime newer
os.utime(str(f1), (1000000, 1000000))
os.utime(str(f2), (2000000, 2000000))
result = fm_core.list_dir(str(tmp_path), sort="mtime")
file_entries = [e for e in result["entries"] if not e["is_dir"]]
names = [e["name"] for e in file_entries]
# ascending mtime: older first
assert names == ["alpha.txt", "beta.txt"]