mirror of
https://github.com/ivuorinen/actions.git
synced 2026-01-26 11:34:00 +00:00
* docs: update documentation * feat: validate-inputs has it's own pyproject * security: mask DOCKERHUB_PASSWORD * chore: add tokens, checkout, recrete docs, integration tests * fix: add `statuses: write` permission to pr-lint
205 lines
7.1 KiB
Python
205 lines
7.1 KiB
Python
"""Tests for the FileValidator module."""
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest # pylint: disable=import-error
|
|
|
|
# Add the parent directory to the path
|
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
|
|
from tests.fixtures.version_test_data import FILE_PATH_INVALID, FILE_PATH_VALID
|
|
from validators.file import FileValidator
|
|
|
|
|
|
class TestFileValidator:
|
|
"""Test cases for FileValidator."""
|
|
|
|
def setup_method(self):
|
|
"""Set up test environment."""
|
|
self.validator = FileValidator()
|
|
|
|
def test_initialization(self):
|
|
"""Test validator initialization."""
|
|
assert self.validator.errors == []
|
|
rules = self.validator.get_validation_rules()
|
|
assert rules is not None
|
|
|
|
@pytest.mark.parametrize("path,description", FILE_PATH_VALID)
|
|
def test_validate_file_path_valid(self, path, description):
|
|
"""Test file path validation with valid paths."""
|
|
self.validator.errors = []
|
|
result = self.validator.validate_file_path(path)
|
|
assert result is True, f"Failed for {description}: {path}"
|
|
assert len(self.validator.errors) == 0
|
|
|
|
@pytest.mark.parametrize("path,description", FILE_PATH_INVALID)
|
|
def test_validate_file_path_invalid(self, path, description):
|
|
"""Test file path validation with invalid paths."""
|
|
self.validator.errors = []
|
|
result = self.validator.validate_file_path(path)
|
|
assert result is False, f"Should fail for {description}: {path}"
|
|
assert len(self.validator.errors) > 0
|
|
|
|
def test_validate_path_security(self):
|
|
"""Test that path traversal attempts are blocked."""
|
|
dangerous_paths = [
|
|
"../etc/passwd",
|
|
"../../etc/shadow",
|
|
"../../../root/.ssh/id_rsa",
|
|
"..\\windows\\system32",
|
|
"/etc/passwd", # Absolute path
|
|
"C:\\Windows\\System32", # Windows absolute
|
|
"~/.ssh/id_rsa", # Home directory expansion
|
|
]
|
|
|
|
for path in dangerous_paths:
|
|
self.validator.errors = []
|
|
result = self.validator.validate_path_security(path)
|
|
assert result is False, f"Should block dangerous path: {path}"
|
|
assert len(self.validator.errors) > 0
|
|
|
|
def test_validate_dockerfile_path(self):
|
|
"""Test Dockerfile path validation."""
|
|
valid_dockerfiles = [
|
|
"Dockerfile",
|
|
"dockerfile",
|
|
"Dockerfile.prod",
|
|
"Dockerfile.dev",
|
|
"docker/Dockerfile",
|
|
"./Dockerfile",
|
|
]
|
|
|
|
for path in valid_dockerfiles:
|
|
self.validator.errors = []
|
|
result = self.validator.validate_dockerfile_path(path)
|
|
assert result is True, f"Should accept Dockerfile: {path}"
|
|
|
|
def test_validate_yaml_file(self):
|
|
"""Test YAML file validation."""
|
|
valid_yaml_files = [
|
|
"config.yml",
|
|
"config.yaml",
|
|
"values.yaml",
|
|
".github/workflows/test.yml",
|
|
"docker-compose.yml",
|
|
"docker-compose.yaml",
|
|
]
|
|
|
|
for path in valid_yaml_files:
|
|
self.validator.errors = []
|
|
result = self.validator.validate_yaml_file(path)
|
|
assert result is True, f"Should accept YAML file: {path}"
|
|
|
|
invalid_yaml_files = [
|
|
"config.txt", # Wrong extension
|
|
"config", # No extension
|
|
"config.yml.txt", # Double extension
|
|
]
|
|
|
|
for path in invalid_yaml_files:
|
|
self.validator.errors = []
|
|
result = self.validator.validate_yaml_file(path)
|
|
assert result is False, f"Should reject non-YAML file: {path}"
|
|
|
|
def test_validate_json_file(self):
|
|
"""Test JSON file validation."""
|
|
valid_json_files = [
|
|
"config.json",
|
|
"package.json",
|
|
"tsconfig.json",
|
|
"composer.json",
|
|
".eslintrc.json",
|
|
]
|
|
|
|
for path in valid_json_files:
|
|
self.validator.errors = []
|
|
result = self.validator.validate_json_file(path)
|
|
assert result is True, f"Should accept JSON file: {path}"
|
|
|
|
invalid_json_files = [
|
|
"config.js", # JavaScript, not JSON
|
|
"config.jsonc", # JSON with comments
|
|
"config.txt", # Wrong extension
|
|
]
|
|
|
|
for path in invalid_json_files:
|
|
self.validator.errors = []
|
|
result = self.validator.validate_json_file(path)
|
|
assert result is False, f"Should reject non-JSON file: {path}"
|
|
|
|
def test_validate_executable_file(self):
|
|
"""Test executable file validation."""
|
|
valid_executables = [
|
|
"script.sh",
|
|
"run.bash",
|
|
"deploy.py",
|
|
"build.js",
|
|
"test.rb",
|
|
"compile", # No extension but could be executable
|
|
"./script.sh",
|
|
"bin/deploy",
|
|
]
|
|
|
|
for path in valid_executables:
|
|
self.validator.errors = []
|
|
# This might check file extensions or actual file permissions
|
|
result = self.validator.validate_executable_file(path)
|
|
assert isinstance(result, bool)
|
|
|
|
def test_empty_path_handling(self):
|
|
"""Test that empty paths are handled correctly."""
|
|
result = self.validator.validate_file_path("")
|
|
# Empty path might be allowed for optional inputs
|
|
assert isinstance(result, bool)
|
|
|
|
# But for required file validations, empty should fail
|
|
self.validator.errors = []
|
|
result = self.validator.validate_required_file("")
|
|
assert result is False
|
|
assert len(self.validator.errors) > 0
|
|
|
|
def test_whitespace_paths(self):
|
|
"""Test that whitespace-only paths are treated as empty."""
|
|
whitespace_paths = [" ", " ", "\t", "\n"]
|
|
|
|
for path in whitespace_paths:
|
|
self.validator.errors = []
|
|
result = self.validator.validate_file_path(path)
|
|
# Should be treated as empty
|
|
assert isinstance(result, bool)
|
|
|
|
def test_validate_inputs_with_file_keywords(self):
|
|
"""Test validation of inputs with file-related keywords."""
|
|
inputs = {
|
|
"config-file": "config.yml",
|
|
"dockerfile": "Dockerfile",
|
|
"compose-file": "docker-compose.yml",
|
|
"env-file": ".env",
|
|
"output-file": "output.txt",
|
|
"input-file": "input.json",
|
|
"cache-dir": ".cache",
|
|
"working-directory": "./src",
|
|
}
|
|
|
|
result = self.validator.validate_inputs(inputs)
|
|
assert isinstance(result, bool)
|
|
|
|
def test_special_characters_in_paths(self):
|
|
"""Test handling of special characters in file paths."""
|
|
special_char_paths = [
|
|
"file name.txt", # Space
|
|
"file@v1.txt", # @ symbol
|
|
"file#1.txt", # Hash
|
|
"file$name.txt", # Dollar sign
|
|
"file&name.txt", # Ampersand
|
|
"file(1).txt", # Parentheses
|
|
"file[1].txt", # Brackets
|
|
]
|
|
|
|
for path in special_char_paths:
|
|
self.validator.errors = []
|
|
result = self.validator.validate_file_path(path)
|
|
# Some special characters might be allowed
|
|
assert isinstance(result, bool)
|