Files
gibidify/cli/processor_simple_test.go
Ismo Vuorinen 3f65b813bd feat: update go to 1.25, add permissions and envs (#49)
* chore(ci): update go to 1.25, add permissions and envs
* fix(ci): update pr-lint.yml
* chore: update go, fix linting
* fix: tests and linting
* fix(lint): lint fixes, renovate should now pass
* fix: updates, security upgrades
* chore: workflow updates, lint
* fix: more lint, checkmake, and other fixes
* fix: more lint, convert scripts to POSIX compliant
* fix: simplify codeql workflow
* tests: increase test coverage, fix found issues
* fix(lint): editorconfig checking, add to linters
* fix(lint): shellcheck, add to linters
* fix(lint): apply cr comment suggestions
* fix(ci): remove step-security/harden-runner
* fix(lint): remove duplication, apply cr fixes
* fix(ci): tests in CI/CD pipeline
* chore(lint): deduplication of strings
* fix(lint): apply cr comment suggestions
* fix(ci): actionlint
* fix(lint): apply cr comment suggestions
* chore: lint, add deps management
2025-10-10 12:14:42 +03:00

266 lines
5.6 KiB
Go

package cli
import (
"context"
"os"
"path/filepath"
"sync"
"testing"
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/ivuorinen/gibidify/fileproc"
)
func TestProcessorSimple(t *testing.T) {
t.Run("NewProcessor", func(t *testing.T) {
flags := &Flags{
SourceDir: "/tmp/test",
Destination: "output.md",
Format: "markdown",
Concurrency: 2,
NoColors: true,
NoProgress: true,
Verbose: false,
}
p := NewProcessor(flags)
assert.NotNil(t, p)
assert.Equal(t, flags, p.flags)
assert.NotNil(t, p.ui)
assert.NotNil(t, p.backpressure)
assert.NotNil(t, p.resourceMonitor)
assert.False(t, p.ui.enableColors)
assert.False(t, p.ui.enableProgress)
})
t.Run("ConfigureFileTypes", func(t *testing.T) {
p := &Processor{
flags: &Flags{},
ui: NewUIManager(),
}
// Should not panic or error
err := p.configureFileTypes()
assert.NoError(t, err)
assert.NotNil(t, p)
})
t.Run("CreateOutputFile", func(t *testing.T) {
// Create temp file path
tempDir := t.TempDir()
outputPath := filepath.Join(tempDir, "output.txt")
p := &Processor{
flags: &Flags{
Destination: outputPath,
},
ui: NewUIManager(),
}
file, err := p.createOutputFile()
assert.NoError(t, err)
assert.NotNil(t, file)
// Clean up
err = file.Close()
require.NoError(t, err)
err = os.Remove(outputPath)
require.NoError(t, err)
})
t.Run("ValidateFileCollection", func(t *testing.T) {
p := &Processor{
ui: NewUIManager(),
}
// Empty collection should be valid (just checks limits)
err := p.validateFileCollection([]string{})
assert.NoError(t, err)
// Small collection should be valid
err = p.validateFileCollection([]string{
testFilePath1,
testFilePath2,
})
assert.NoError(t, err)
})
t.Run("CollectFiles_EmptyDir", func(t *testing.T) {
tempDir := t.TempDir()
p := &Processor{
flags: &Flags{
SourceDir: tempDir,
},
ui: NewUIManager(),
}
files, err := p.collectFiles()
assert.NoError(t, err)
assert.Empty(t, files)
})
t.Run("CollectFiles_WithFiles", func(t *testing.T) {
tempDir := t.TempDir()
// Create test files
require.NoError(t, os.WriteFile(filepath.Join(tempDir, "test1.go"), []byte("package main"), 0o600))
require.NoError(t, os.WriteFile(filepath.Join(tempDir, "test2.go"), []byte("package test"), 0o600))
// Set config so no files are ignored, and restore after test
origIgnoreDirs := viper.Get("ignoreDirectories")
origFileSizeLimit := viper.Get("fileSizeLimit")
viper.Set("ignoreDirectories", []string{})
viper.Set("fileSizeLimit", 1024*1024*10) // 10MB
t.Cleanup(func() {
viper.Set("ignoreDirectories", origIgnoreDirs)
viper.Set("fileSizeLimit", origFileSizeLimit)
})
p := &Processor{
flags: &Flags{
SourceDir: tempDir,
},
ui: NewUIManager(),
}
files, err := p.collectFiles()
assert.NoError(t, err)
assert.Len(t, files, 2)
})
t.Run("SendFiles", func(t *testing.T) {
p := &Processor{
backpressure: fileproc.NewBackpressureManager(),
ui: NewUIManager(),
}
ctx := context.Background()
fileCh := make(chan string, 3)
files := []string{
testFilePath1,
testFilePath2,
}
var wg sync.WaitGroup
wg.Add(1)
// Send files in a goroutine since it might block
go func() {
defer wg.Done()
err := p.sendFiles(ctx, files, fileCh)
assert.NoError(t, err)
}()
// Read all files from channel
var received []string
for i := 0; i < len(files); i++ {
file := <-fileCh
received = append(received, file)
}
assert.Equal(t, len(files), len(received))
// Wait for sendFiles goroutine to finish (and close fileCh)
wg.Wait()
// Now channel should be closed
_, ok := <-fileCh
assert.False(t, ok, "channel should be closed")
})
t.Run("WaitForCompletion", func(t *testing.T) {
p := &Processor{
ui: NewUIManager(),
}
writeCh := make(chan fileproc.WriteRequest)
writerDone := make(chan struct{})
// Simulate writer finishing
go func() {
<-writeCh // Wait for close
close(writerDone)
}()
var wg sync.WaitGroup
// Start and finish immediately
wg.Add(1)
wg.Done()
// Should complete without hanging
p.waitForCompletion(&wg, writeCh, writerDone)
assert.NotNil(t, p)
})
t.Run("LogFinalStats", func(t *testing.T) {
p := &Processor{
flags: &Flags{
Verbose: true,
},
ui: NewUIManager(),
resourceMonitor: fileproc.NewResourceMonitor(),
backpressure: fileproc.NewBackpressureManager(),
}
// Should not panic
p.logFinalStats()
assert.NotNil(t, p)
})
}
// Test error handling scenarios
func TestProcessorErrors(t *testing.T) {
t.Run("CreateOutputFile_InvalidPath", func(t *testing.T) {
p := &Processor{
flags: &Flags{
Destination: "/root/cannot-write-here.txt",
},
ui: NewUIManager(),
}
file, err := p.createOutputFile()
assert.Error(t, err)
assert.Nil(t, file)
})
t.Run("CollectFiles_NonExistentDir", func(t *testing.T) {
p := &Processor{
flags: &Flags{
SourceDir: "/non/existent/path",
},
ui: NewUIManager(),
}
files, err := p.collectFiles()
assert.Error(t, err)
assert.Nil(t, files)
})
t.Run("SendFiles_WithCancellation", func(t *testing.T) {
p := &Processor{
backpressure: fileproc.NewBackpressureManager(),
ui: NewUIManager(),
}
ctx, cancel := context.WithCancel(context.Background())
fileCh := make(chan string) // Unbuffered to force blocking
files := []string{
testFilePath1,
testFilePath2,
"/test/file3.go",
}
// Cancel immediately
cancel()
err := p.sendFiles(ctx, files, fileCh)
assert.Error(t, err)
assert.Equal(t, context.Canceled, err)
})
}