Add tests for main package, manager, and various components

- Introduced unit tests for the main package to ensure compilation.
- Added tests for the manager, including validation of upload sessions and handling of Blender binary paths.
- Implemented tests for job token generation and validation, ensuring security and integrity.
- Created tests for configuration management and database schema to verify functionality.
- Added tests for logger and runner components to enhance overall test coverage and reliability.
This commit is contained in:
2026-03-14 22:20:03 -05:00
parent 16d6a95058
commit a3defe5cf6
45 changed files with 1717 additions and 52 deletions

View File

@@ -19,6 +19,9 @@ import (
"jiggablend/pkg/types"
)
var runMetadataCommand = executils.RunCommand
var resolveMetadataBlenderPath = resolveBlenderBinaryPath
// handleGetJobMetadata retrieves metadata for a job
func (s *Manager) handleGetJobMetadata(w http.ResponseWriter, r *http.Request) {
userID, err := getUserID(r)
@@ -141,16 +144,24 @@ func (s *Manager) extractMetadataFromContext(jobID int64) (*types.BlendMetadata,
return nil, fmt.Errorf("failed to create extraction script: %w", err)
}
// Make blend file path relative to tmpDir to avoid path resolution issues
blendFileRel, err := filepath.Rel(tmpDir, blendFile)
// Use absolute paths to avoid path normalization issues with relative traversal.
blendFileAbs, err := filepath.Abs(blendFile)
if err != nil {
return nil, fmt.Errorf("failed to get relative path for blend file: %w", err)
return nil, fmt.Errorf("failed to get absolute path for blend file: %w", err)
}
scriptPathAbs, err := filepath.Abs(scriptPath)
if err != nil {
return nil, fmt.Errorf("failed to get absolute path for extraction script: %w", err)
}
// Execute Blender with Python script using executils
result, err := executils.RunCommand(
"blender",
[]string{"-b", blendFileRel, "--python", "extract_metadata.py"},
blenderBinary, err := resolveMetadataBlenderPath("blender")
if err != nil {
return nil, err
}
result, err := runMetadataCommand(
blenderBinary,
[]string{"-b", blendFileAbs, "--python", scriptPathAbs},
tmpDir,
nil, // inherit environment
jobID,
@@ -225,8 +236,17 @@ func (s *Manager) extractTar(tarPath, destDir string) error {
return fmt.Errorf("failed to read tar header: %w", err)
}
// Sanitize path to prevent directory traversal
target := filepath.Join(destDir, header.Name)
// Sanitize path to prevent directory traversal. TAR stores "/" separators, so normalize first.
normalizedHeaderPath := filepath.FromSlash(header.Name)
cleanHeaderPath := filepath.Clean(normalizedHeaderPath)
if cleanHeaderPath == "." {
continue
}
if filepath.IsAbs(cleanHeaderPath) || strings.HasPrefix(cleanHeaderPath, ".."+string(os.PathSeparator)) || cleanHeaderPath == ".." {
log.Printf("ERROR: Invalid file path in TAR - header: %s", header.Name)
return fmt.Errorf("invalid file path in archive: %s", header.Name)
}
target := filepath.Join(destDir, cleanHeaderPath)
// Ensure target is within destDir
cleanTarget := filepath.Clean(target)
@@ -237,14 +257,14 @@ func (s *Manager) extractTar(tarPath, destDir string) error {
}
// Create parent directories
if err := os.MkdirAll(filepath.Dir(target), 0755); err != nil {
if err := os.MkdirAll(filepath.Dir(cleanTarget), 0755); err != nil {
return fmt.Errorf("failed to create directory: %w", err)
}
// Write file
switch header.Typeflag {
case tar.TypeReg:
outFile, err := os.Create(target)
outFile, err := os.Create(cleanTarget)
if err != nil {
return fmt.Errorf("failed to create file: %w", err)
}