Track bundled vendor runtime sources
Some checks failed
CI / main (push) Has been cancelled
CI / release-e2e (push) Has been cancelled

This commit is contained in:
2026-07-07 10:05:50 +08:00
parent fbe179ab53
commit 52636c91ae
2111 changed files with 1850012 additions and 14 deletions

View File

@@ -0,0 +1,66 @@
import pytest
import os
import tempfile
from folder_paths import filter_files_content_types, extension_mimetypes_cache
from unittest.mock import patch
@pytest.fixture(scope="module")
def file_extensions():
return {
'image': ['gif', 'heif', 'ico', 'jpeg', 'jpg', 'png', 'pnm', 'ppm', 'svg', 'tiff', 'webp', 'xbm', 'xpm'],
'audio': ['aif', 'aifc', 'aiff', 'au', 'flac', 'm4a', 'mp2', 'mp3', 'ogg', 'snd', 'wav'],
'video': ['avi', 'm2v', 'm4v', 'mkv', 'mov', 'mp4', 'mpeg', 'mpg', 'ogv', 'qt', 'webm', 'wmv'],
'model': ['gltf', 'glb', 'obj', 'fbx', 'stl']
}
@pytest.fixture(scope="module")
def mock_dir(file_extensions):
with tempfile.TemporaryDirectory() as directory:
for content_type, extensions in file_extensions.items():
for extension in extensions:
with open(f"{directory}/sample_{content_type}.{extension}", "w") as f:
f.write(f"Sample {content_type} file in {extension} format")
yield directory
@pytest.fixture
def patched_mimetype_cache(file_extensions):
# Mock model file extensions since they may not be in the test-runner system's mimetype cache
new_cache = extension_mimetypes_cache.copy()
for extension in file_extensions["model"]:
new_cache[extension] = "model"
with patch("folder_paths.extension_mimetypes_cache", new_cache):
yield
def test_categorizes_all_correctly(mock_dir, file_extensions, patched_mimetype_cache):
files = os.listdir(mock_dir)
for content_type, extensions in file_extensions.items():
filtered_files = filter_files_content_types(files, [content_type])
for extension in extensions:
assert f"sample_{content_type}.{extension}" in filtered_files
def test_categorizes_all_uniquely(mock_dir, file_extensions, patched_mimetype_cache):
files = os.listdir(mock_dir)
for content_type, extensions in file_extensions.items():
filtered_files = filter_files_content_types(files, [content_type])
assert len(filtered_files) == len(extensions)
def test_handles_bad_extensions():
files = ["file1.txt", "file2.py", "file3.example", "file4.pdf", "file5.ini", "file6.doc", "file7.md"]
assert filter_files_content_types(files, ["image", "audio", "video"]) == []
def test_handles_no_extension():
files = ["file1", "file2", "file3", "file4", "file5", "file6", "file7"]
assert filter_files_content_types(files, ["image", "audio", "video"]) == []
def test_handles_no_files():
files = []
assert filter_files_content_types(files, ["image", "audio", "video"]) == []

View File

@@ -0,0 +1,51 @@
import pytest
import os
import tempfile
from folder_paths import get_input_subfolders, set_input_directory
@pytest.fixture(scope="module")
def mock_folder_structure():
with tempfile.TemporaryDirectory() as temp_dir:
# Create a nested folder structure
folders = [
"folder1",
"folder1/subfolder1",
"folder1/subfolder2",
"folder2",
"folder2/deep",
"folder2/deep/nested",
"empty_folder"
]
# Create the folders
for folder in folders:
os.makedirs(os.path.join(temp_dir, folder))
# Add some files to test they're not included
with open(os.path.join(temp_dir, "root_file.txt"), "w") as f:
f.write("test")
with open(os.path.join(temp_dir, "folder1", "test.txt"), "w") as f:
f.write("test")
set_input_directory(temp_dir)
yield temp_dir
def test_gets_all_folders(mock_folder_structure):
folders = get_input_subfolders()
expected = ["folder1", "folder1/subfolder1", "folder1/subfolder2",
"folder2", "folder2/deep", "folder2/deep/nested", "empty_folder"]
assert sorted(folders) == sorted(expected)
def test_handles_nonexistent_input_directory():
with tempfile.TemporaryDirectory() as temp_dir:
nonexistent = os.path.join(temp_dir, "nonexistent")
set_input_directory(nonexistent)
assert get_input_subfolders() == []
def test_empty_input_directory():
with tempfile.TemporaryDirectory() as temp_dir:
set_input_directory(temp_dir)
assert get_input_subfolders() == [] # Empty since we don't include root

View File

@@ -0,0 +1,206 @@
"""Tests for System User Protection in folder_paths.py
Tests cover:
- get_system_user_directory(): Internal API for custom nodes to access System User directories
- get_public_user_directory(): HTTP endpoint access with System User blocking
- Backward compatibility: Existing APIs unchanged
- Security: Path traversal and injection prevention
"""
import pytest
import os
import tempfile
from folder_paths import (
get_system_user_directory,
get_public_user_directory,
get_user_directory,
set_user_directory,
)
@pytest.fixture(scope="module")
def mock_user_directory():
"""Create a temporary user directory for testing."""
with tempfile.TemporaryDirectory() as temp_dir:
original_dir = get_user_directory()
set_user_directory(temp_dir)
yield temp_dir
set_user_directory(original_dir)
class TestGetSystemUserDirectory:
"""Tests for get_system_user_directory() - internal API for System User directories.
Verifies:
- Custom nodes can access System User directories via internal API
- Input validation prevents path traversal attacks
"""
def test_default_name(self, mock_user_directory):
"""Test default 'system' name."""
path = get_system_user_directory()
assert path.endswith("__system")
assert mock_user_directory in path
def test_custom_name(self, mock_user_directory):
"""Test custom system user name."""
path = get_system_user_directory("cache")
assert path.endswith("__cache")
assert "__cache" in path
def test_name_with_underscore(self, mock_user_directory):
"""Test name with underscore in middle."""
path = get_system_user_directory("my_cache")
assert "__my_cache" in path
def test_empty_name_raises(self):
"""Test empty name raises ValueError."""
with pytest.raises(ValueError, match="cannot be empty"):
get_system_user_directory("")
def test_none_name_raises(self):
"""Test None name raises ValueError."""
with pytest.raises(ValueError, match="cannot be empty"):
get_system_user_directory(None)
def test_name_starting_with_underscore_raises(self):
"""Test name starting with underscore raises ValueError."""
with pytest.raises(ValueError, match="should not start with underscore"):
get_system_user_directory("_system")
def test_path_traversal_raises(self):
"""Test path traversal attempt raises ValueError (security)."""
with pytest.raises(ValueError, match="Invalid system user name"):
get_system_user_directory("../escape")
def test_path_traversal_middle_raises(self):
"""Test path traversal in middle raises ValueError (security)."""
with pytest.raises(ValueError, match="Invalid system user name"):
get_system_user_directory("system/../other")
def test_special_chars_raise(self):
"""Test special characters raise ValueError (security)."""
with pytest.raises(ValueError, match="Invalid system user name"):
get_system_user_directory("system!")
def test_returns_absolute_path(self, mock_user_directory):
"""Test returned path is absolute."""
path = get_system_user_directory("test")
assert os.path.isabs(path)
class TestGetPublicUserDirectory:
"""Tests for get_public_user_directory() - HTTP endpoint access with System User blocking.
Verifies:
- System Users (__ prefix) return None, blocking HTTP access
- Public Users get valid paths
- New endpoints using this function are automatically protected
"""
def test_normal_user(self, mock_user_directory):
"""Test normal user returns valid path."""
path = get_public_user_directory("default")
assert path is not None
assert "default" in path
assert mock_user_directory in path
def test_system_user_returns_none(self):
"""Test System User (__ prefix) returns None - blocks HTTP access."""
assert get_public_user_directory("__system") is None
def test_system_user_cache_returns_none(self):
"""Test System User cache returns None."""
assert get_public_user_directory("__cache") is None
def test_empty_user_returns_none(self):
"""Test empty user returns None."""
assert get_public_user_directory("") is None
def test_none_user_returns_none(self):
"""Test None user returns None."""
assert get_public_user_directory(None) is None
def test_header_injection_returns_none(self):
"""Test header injection attempt returns None (security)."""
assert get_public_user_directory("__system\r\nX-Injected: true") is None
def test_null_byte_injection_returns_none(self):
"""Test null byte injection handling (security)."""
# Note: startswith check happens before any path operations
result = get_public_user_directory("user\x00__system")
# This should return a path since it doesn't start with __
# The actual security comes from the path not being __*
assert result is not None or result is None # Depends on validation
def test_path_traversal_attempt(self, mock_user_directory):
"""Test path traversal attempt handling."""
# This function doesn't validate paths, only reserved prefix
# Path traversal should be handled by the caller
path = get_public_user_directory("../../../etc/passwd")
# Returns path but doesn't start with __, so not None
# Actual path validation happens in user_manager
assert path is not None or "__" not in "../../../etc/passwd"
def test_returns_absolute_path(self, mock_user_directory):
"""Test returned path is absolute."""
path = get_public_user_directory("testuser")
assert path is not None
assert os.path.isabs(path)
class TestBackwardCompatibility:
"""Tests for backward compatibility with existing APIs.
Verifies:
- get_user_directory() API unchanged
- Existing user data remains accessible
"""
def test_get_user_directory_unchanged(self, mock_user_directory):
"""Test get_user_directory() still works as before."""
user_dir = get_user_directory()
assert user_dir is not None
assert os.path.isabs(user_dir)
assert user_dir == mock_user_directory
def test_existing_user_accessible(self, mock_user_directory):
"""Test existing users can access their directories."""
path = get_public_user_directory("default")
assert path is not None
assert "default" in path
class TestEdgeCases:
"""Tests for edge cases in System User detection.
Verifies:
- Only __ prefix is blocked (not _, not middle __)
- Bypass attempts are prevented
"""
def test_prefix_only(self):
"""Test prefix-only string is blocked."""
assert get_public_user_directory("__") is None
def test_single_underscore_allowed(self):
"""Test single underscore prefix is allowed (not System User)."""
path = get_public_user_directory("_system")
assert path is not None
assert "_system" in path
def test_triple_underscore_blocked(self):
"""Test triple underscore is blocked (starts with __)."""
assert get_public_user_directory("___system") is None
def test_underscore_in_middle_allowed(self):
"""Test underscore in middle is allowed."""
path = get_public_user_directory("my__system")
assert path is not None
assert "my__system" in path
def test_leading_space_allowed(self):
"""Test leading space + prefix is allowed (doesn't start with __)."""
path = get_public_user_directory(" __system")
assert path is not None