mirror of
https://github.com/danielmiessler/Fabric.git
synced 2026-02-13 23:45:08 -05:00
added tests for extension manager, registration and execution.
This commit is contained in:
360
plugins/template/extension_executor_test.go
Normal file
360
plugins/template/extension_executor_test.go
Normal file
@@ -0,0 +1,360 @@
|
||||
package template
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestExtensionExecutor(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp("", "fabric-ext-executor-*")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
// Create test script that has both stdout and file output modes
|
||||
testScript := filepath.Join(tmpDir, "test-script.sh")
|
||||
scriptContent := `#!/bin/bash
|
||||
case "$1" in
|
||||
"stdout")
|
||||
echo "Hello, $2!"
|
||||
;;
|
||||
"file")
|
||||
echo "Hello, $2!" > "$3"
|
||||
echo "$3" # Print the filename for path_from_stdout
|
||||
;;
|
||||
*)
|
||||
echo "Unknown command" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac`
|
||||
|
||||
if err := os.WriteFile(testScript, []byte(scriptContent), 0755); err != nil {
|
||||
t.Fatalf("Failed to create test script: %v", err)
|
||||
}
|
||||
|
||||
// Create registry and register our test extensions
|
||||
registry := NewExtensionRegistry(tmpDir)
|
||||
executor := NewExtensionExecutor(registry)
|
||||
|
||||
// Test stdout-based extension
|
||||
t.Run("StdoutExecution", func(t *testing.T) {
|
||||
configPath := filepath.Join(tmpDir, "stdout-extension.yaml")
|
||||
configContent := `name: stdout-test
|
||||
executable: ` + testScript + `
|
||||
type: executable
|
||||
timeout: 30s
|
||||
operations:
|
||||
greet:
|
||||
cmd_template: "{{executable}} stdout {{1}}"
|
||||
config:
|
||||
output:
|
||||
method: stdout`
|
||||
|
||||
if err := os.WriteFile(configPath, []byte(configContent), 0644); err != nil {
|
||||
t.Fatalf("Failed to create config: %v", err)
|
||||
}
|
||||
|
||||
if err := registry.Register(configPath); err != nil {
|
||||
t.Fatalf("Failed to register extension: %v", err)
|
||||
}
|
||||
|
||||
output, err := executor.Execute("stdout-test", "greet", "World")
|
||||
if err != nil {
|
||||
t.Errorf("Failed to execute: %v", err)
|
||||
}
|
||||
|
||||
expected := "Hello, World!\n"
|
||||
if output != expected {
|
||||
t.Errorf("Expected output %q, got %q", expected, output)
|
||||
}
|
||||
})
|
||||
|
||||
// Test file-based extension
|
||||
t.Run("FileExecution", func(t *testing.T) {
|
||||
configPath := filepath.Join(tmpDir, "file-extension.yaml")
|
||||
configContent := `name: file-test
|
||||
executable: ` + testScript + `
|
||||
type: executable
|
||||
timeout: 30s
|
||||
operations:
|
||||
greet:
|
||||
cmd_template: "{{executable}} file {{1}} {{2}}"
|
||||
config:
|
||||
output:
|
||||
method: file
|
||||
file_config:
|
||||
cleanup: true
|
||||
path_from_stdout: true`
|
||||
|
||||
if err := os.WriteFile(configPath, []byte(configContent), 0644); err != nil {
|
||||
t.Fatalf("Failed to create config: %v", err)
|
||||
}
|
||||
|
||||
if err := registry.Register(configPath); err != nil {
|
||||
t.Fatalf("Failed to register extension: %v", err)
|
||||
}
|
||||
|
||||
output, err := executor.Execute("file-test", "greet", "World|/tmp/test.txt")
|
||||
if err != nil {
|
||||
t.Errorf("Failed to execute: %v", err)
|
||||
}
|
||||
|
||||
expected := "Hello, World!\n"
|
||||
if output != expected {
|
||||
t.Errorf("Expected output %q, got %q", expected, output)
|
||||
}
|
||||
})
|
||||
|
||||
// Test execution errors
|
||||
t.Run("ExecutionErrors", func(t *testing.T) {
|
||||
// Test with non-existent extension
|
||||
_, err := executor.Execute("nonexistent", "test", "value")
|
||||
if err == nil {
|
||||
t.Error("Expected error executing non-existent extension, got nil")
|
||||
}
|
||||
|
||||
// Test with invalid command that should exit non-zero
|
||||
configPath := filepath.Join(tmpDir, "error-extension.yaml")
|
||||
configContent := `name: error-test
|
||||
executable: ` + testScript + `
|
||||
type: executable
|
||||
timeout: 30s
|
||||
operations:
|
||||
invalid:
|
||||
cmd_template: "{{executable}} invalid {{1}}"
|
||||
config:
|
||||
output:
|
||||
method: stdout`
|
||||
|
||||
if err := os.WriteFile(configPath, []byte(configContent), 0644); err != nil {
|
||||
t.Fatalf("Failed to create config: %v", err)
|
||||
}
|
||||
|
||||
if err := registry.Register(configPath); err != nil {
|
||||
t.Fatalf("Failed to register extension: %v", err)
|
||||
}
|
||||
|
||||
_, err = executor.Execute("error-test", "invalid", "test")
|
||||
if err == nil {
|
||||
t.Error("Expected error from invalid command, got nil")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "Unknown command") {
|
||||
t.Errorf("Expected 'Unknown command' in error, got: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestFixedFileExtensionExecutor(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp("", "fabric-ext-executor-fixed-*")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
// Create test script
|
||||
testScript := filepath.Join(tmpDir, "test-script.sh")
|
||||
scriptContent := `#!/bin/bash
|
||||
case "$1" in
|
||||
"write")
|
||||
echo "Hello, $2!" > "$3"
|
||||
;;
|
||||
"append")
|
||||
echo "Hello, $2!" >> "$3"
|
||||
;;
|
||||
"large")
|
||||
for i in {1..1000}; do
|
||||
echo "Line $i" >> "$3"
|
||||
done
|
||||
;;
|
||||
"error")
|
||||
echo "Error message" >&2
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
echo "Unknown command" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac`
|
||||
|
||||
if err := os.WriteFile(testScript, []byte(scriptContent), 0755); err != nil {
|
||||
t.Fatalf("Failed to create test script: %v", err)
|
||||
}
|
||||
|
||||
registry := NewExtensionRegistry(tmpDir)
|
||||
executor := NewExtensionExecutor(registry)
|
||||
|
||||
// Helper function to create and register extension
|
||||
createExtension := func(name, opName, cmdTemplate string, config map[string]interface{}) error {
|
||||
configPath := filepath.Join(tmpDir, name+".yaml")
|
||||
configContent := `name: ` + name + `
|
||||
executable: ` + testScript + `
|
||||
type: executable
|
||||
timeout: 30s
|
||||
operations:
|
||||
` + opName + `:
|
||||
cmd_template: "` + cmdTemplate + `"
|
||||
config:
|
||||
output:
|
||||
method: file
|
||||
file_config:`
|
||||
|
||||
// Add config options
|
||||
for k, v := range config {
|
||||
configContent += "\n " + k + ": " + strings.TrimSpace(v.(string))
|
||||
}
|
||||
|
||||
if err := os.WriteFile(configPath, []byte(configContent), 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return registry.Register(configPath)
|
||||
}
|
||||
|
||||
// Test basic fixed file output
|
||||
t.Run("BasicFixedFile", func(t *testing.T) {
|
||||
outputFile := filepath.Join(tmpDir, "output.txt")
|
||||
config := map[string]interface{}{
|
||||
"output_file": `"output.txt"`,
|
||||
"work_dir": `"` + tmpDir + `"`,
|
||||
"cleanup": "true",
|
||||
}
|
||||
|
||||
err := createExtension("basic-test", "write",
|
||||
"{{executable}} write {{1}} "+outputFile, config)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create extension: %v", err)
|
||||
}
|
||||
|
||||
output, err := executor.Execute("basic-test", "write", "World")
|
||||
if err != nil {
|
||||
t.Errorf("Failed to execute: %v", err)
|
||||
}
|
||||
|
||||
expected := "Hello, World!\n"
|
||||
if output != expected {
|
||||
t.Errorf("Expected output %q, got %q", expected, output)
|
||||
}
|
||||
})
|
||||
|
||||
// Test no work_dir specified
|
||||
t.Run("NoWorkDir", func(t *testing.T) {
|
||||
config := map[string]interface{}{
|
||||
"output_file": `"direct-output.txt"`,
|
||||
"cleanup": "true",
|
||||
}
|
||||
|
||||
err := createExtension("no-workdir-test", "write",
|
||||
"{{executable}} write {{1}} direct-output.txt", config)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create extension: %v", err)
|
||||
}
|
||||
|
||||
_, err = executor.Execute("no-workdir-test", "write", "World")
|
||||
if err != nil {
|
||||
t.Errorf("Failed to execute: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
// Test cleanup behavior
|
||||
t.Run("CleanupBehavior", func(t *testing.T) {
|
||||
outputFile := filepath.Join(tmpDir, "cleanup-test.txt")
|
||||
|
||||
// Test with cleanup enabled
|
||||
config := map[string]interface{}{
|
||||
"output_file": `"cleanup-test.txt"`,
|
||||
"work_dir": `"` + tmpDir + `"`,
|
||||
"cleanup": "true",
|
||||
}
|
||||
|
||||
err := createExtension("cleanup-test", "write",
|
||||
"{{executable}} write {{1}} "+outputFile, config)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create extension: %v", err)
|
||||
}
|
||||
|
||||
_, err = executor.Execute("cleanup-test", "write", "World")
|
||||
if err != nil {
|
||||
t.Errorf("Failed to execute: %v", err)
|
||||
}
|
||||
|
||||
// File should be deleted after execution
|
||||
if _, err := os.Stat(outputFile); !os.IsNotExist(err) {
|
||||
t.Error("Expected output file to be cleaned up")
|
||||
}
|
||||
|
||||
// Test with cleanup disabled
|
||||
config["cleanup"] = "false"
|
||||
err = createExtension("no-cleanup-test", "write",
|
||||
"{{executable}} write {{1}} "+outputFile, config)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create extension: %v", err)
|
||||
}
|
||||
|
||||
_, err = executor.Execute("no-cleanup-test", "write", "World")
|
||||
if err != nil {
|
||||
t.Errorf("Failed to execute: %v", err)
|
||||
}
|
||||
|
||||
// File should remain after execution
|
||||
if _, err := os.Stat(outputFile); os.IsNotExist(err) {
|
||||
t.Error("Expected output file to remain")
|
||||
}
|
||||
})
|
||||
|
||||
// Test error cases
|
||||
t.Run("ErrorCases", func(t *testing.T) {
|
||||
outputFile := filepath.Join(tmpDir, "error-test.txt")
|
||||
config := map[string]interface{}{
|
||||
"output_file": `"error-test.txt"`,
|
||||
"work_dir": `"` + tmpDir + `"`,
|
||||
"cleanup": "true",
|
||||
}
|
||||
|
||||
// Test command error
|
||||
err := createExtension("error-test", "error",
|
||||
"{{executable}} error {{1}} "+outputFile, config)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create extension: %v", err)
|
||||
}
|
||||
|
||||
_, err = executor.Execute("error-test", "error", "World")
|
||||
if err == nil {
|
||||
t.Error("Expected error from failing command, got nil")
|
||||
}
|
||||
|
||||
// Test invalid work_dir
|
||||
config["work_dir"] = `"/nonexistent/directory"`
|
||||
err = createExtension("invalid-dir-test", "write",
|
||||
"{{executable}} write {{1}} output.txt", config)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create extension: %v", err)
|
||||
}
|
||||
|
||||
_, err = executor.Execute("invalid-dir-test", "write", "World")
|
||||
if err == nil {
|
||||
t.Error("Expected error from invalid work_dir, got nil")
|
||||
}
|
||||
})
|
||||
|
||||
// Test with missing output_file
|
||||
t.Run("MissingOutputFile", func(t *testing.T) {
|
||||
config := map[string]interface{}{
|
||||
"work_dir": `"` + tmpDir + `"`,
|
||||
"cleanup": "true",
|
||||
}
|
||||
|
||||
err := createExtension("missing-output-test", "write",
|
||||
"{{executable}} write {{1}} output.txt", config)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create extension: %v", err)
|
||||
}
|
||||
|
||||
_, err = executor.Execute("missing-output-test", "write", "World")
|
||||
if err == nil {
|
||||
t.Error("Expected error from missing output_file, got nil")
|
||||
}
|
||||
})
|
||||
}
|
||||
184
plugins/template/extension_manager_test.go
Normal file
184
plugins/template/extension_manager_test.go
Normal file
@@ -0,0 +1,184 @@
|
||||
package template
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestExtensionManager is the main test suite for ExtensionManager
|
||||
func TestExtensionManager(t *testing.T) {
|
||||
// Create temporary directory for tests
|
||||
tmpDir, err := os.MkdirTemp("", "fabric-ext-test-*")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
// Create test extension config
|
||||
testConfig := filepath.Join(tmpDir, "test-extension.yaml")
|
||||
testScript := filepath.Join(tmpDir, "test-script.sh")
|
||||
|
||||
// Create test script
|
||||
scriptContent := `#!/bin/bash
|
||||
if [ "$1" = "echo" ]; then
|
||||
echo "Hello, $2!"
|
||||
fi`
|
||||
|
||||
err = os.WriteFile(testScript, []byte(scriptContent), 0755)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create test script: %v", err)
|
||||
}
|
||||
|
||||
// Create test config
|
||||
configContent := `name: test-extension
|
||||
executable: ` + testScript + `
|
||||
type: executable
|
||||
timeout: 30s
|
||||
description: "Test extension"
|
||||
version: "1.0.0"
|
||||
operations:
|
||||
echo:
|
||||
cmd_template: "{{executable}} echo {{1}}"
|
||||
`
|
||||
|
||||
err = os.WriteFile(testConfig, []byte(configContent), 0644)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create test config: %v", err)
|
||||
}
|
||||
|
||||
// Initialize manager
|
||||
manager := NewExtensionManager(tmpDir)
|
||||
|
||||
// Test cases
|
||||
t.Run("RegisterExtension", func(t *testing.T) {
|
||||
err := manager.RegisterExtension(testConfig)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to register extension: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ListExtensions", func(t *testing.T) {
|
||||
err := manager.ListExtensions()
|
||||
if err != nil {
|
||||
t.Errorf("Failed to list extensions: %v", err)
|
||||
}
|
||||
// Note: Output validation would require capturing stdout
|
||||
})
|
||||
|
||||
t.Run("ProcessExtension", func(t *testing.T) {
|
||||
output, err := manager.ProcessExtension("test-extension", "echo", "World")
|
||||
if err != nil {
|
||||
t.Errorf("Failed to process extension: %v", err)
|
||||
}
|
||||
expected := "Hello, World!\n"
|
||||
if output != expected {
|
||||
t.Errorf("Expected output %q, got %q", expected, output)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("RemoveExtension", func(t *testing.T) {
|
||||
err := manager.RemoveExtension("test-extension")
|
||||
if err != nil {
|
||||
t.Errorf("Failed to remove extension: %v", err)
|
||||
}
|
||||
|
||||
// Verify extension is removed by trying to process it
|
||||
_, err = manager.ProcessExtension("test-extension", "echo", "World")
|
||||
if err == nil {
|
||||
t.Error("Expected error processing removed extension, got nil")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// TestExtensionManagerErrors tests error cases
|
||||
func TestExtensionManagerErrors(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp("", "fabric-ext-test-errors-*")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
manager := NewExtensionManager(tmpDir)
|
||||
|
||||
t.Run("RegisterNonexistentConfig", func(t *testing.T) {
|
||||
err := manager.RegisterExtension("/nonexistent/config.yaml")
|
||||
if err == nil {
|
||||
t.Error("Expected error registering nonexistent config, got nil")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ProcessNonexistentExtension", func(t *testing.T) {
|
||||
_, err := manager.ProcessExtension("nonexistent", "echo", "test")
|
||||
if err == nil {
|
||||
t.Error("Expected error processing nonexistent extension, got nil")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("RemoveNonexistentExtension", func(t *testing.T) {
|
||||
err := manager.RemoveExtension("nonexistent")
|
||||
if err == nil {
|
||||
t.Error("Expected error removing nonexistent extension, got nil")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// TestExtensionManagerWithInvalidConfig tests handling of invalid configurations
|
||||
func TestExtensionManagerWithInvalidConfig(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp("", "fabric-ext-test-invalid-*")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
invalidConfig := filepath.Join(tmpDir, "invalid-extension.yaml")
|
||||
|
||||
// Test cases with different invalid configurations
|
||||
testCases := []struct {
|
||||
name string
|
||||
config string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "MissingExecutable",
|
||||
config: `name: invalid-extension
|
||||
type: executable
|
||||
timeout: 30s`,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "InvalidTimeout",
|
||||
config: `name: invalid-extension
|
||||
executable: /bin/echo
|
||||
type: executable
|
||||
timeout: invalid`,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "EmptyName",
|
||||
config: `name: ""
|
||||
executable: /bin/echo
|
||||
type: executable
|
||||
timeout: 30s`,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
manager := NewExtensionManager(tmpDir)
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := os.WriteFile(invalidConfig, []byte(tc.config), 0644)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create invalid config file: %v", err)
|
||||
}
|
||||
|
||||
err = manager.RegisterExtension(invalidConfig)
|
||||
if tc.wantErr && err == nil {
|
||||
t.Error("Expected error registering invalid config, got nil")
|
||||
} else if !tc.wantErr && err != nil {
|
||||
t.Errorf("Unexpected error registering config: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
// Add this import
|
||||
@@ -103,6 +104,8 @@ func (r *ExtensionRegistry) ensureConfigDir() error {
|
||||
return os.MkdirAll(extDir, 0755)
|
||||
}
|
||||
|
||||
// Update the Register method in extension_registry.go
|
||||
|
||||
func (r *ExtensionRegistry) Register(configPath string) error {
|
||||
// Read and parse the extension definition to verify it
|
||||
data, err := os.ReadFile(configPath)
|
||||
@@ -115,6 +118,11 @@ func (r *ExtensionRegistry) Register(configPath string) error {
|
||||
return fmt.Errorf("failed to parse config file: %w", err)
|
||||
}
|
||||
|
||||
// Add validation
|
||||
if err := r.validateExtensionDefinition(&ext); err != nil {
|
||||
return fmt.Errorf("invalid extension configuration: %w", err)
|
||||
}
|
||||
|
||||
// Verify executable exists
|
||||
if _, err := os.Stat(ext.Executable); err != nil {
|
||||
return fmt.Errorf("executable not found: %w", err)
|
||||
@@ -143,6 +151,39 @@ func (r *ExtensionRegistry) Register(configPath string) error {
|
||||
return r.saveRegistry()
|
||||
}
|
||||
|
||||
func (r *ExtensionRegistry) validateExtensionDefinition(ext *ExtensionDefinition) error {
|
||||
// Validate required fields
|
||||
if ext.Name == "" {
|
||||
return fmt.Errorf("extension name is required")
|
||||
}
|
||||
if ext.Executable == "" {
|
||||
return fmt.Errorf("executable path is required")
|
||||
}
|
||||
if ext.Type == "" {
|
||||
return fmt.Errorf("extension type is required")
|
||||
}
|
||||
|
||||
// Validate timeout format
|
||||
if ext.Timeout != "" {
|
||||
if _, err := time.ParseDuration(ext.Timeout); err != nil {
|
||||
return fmt.Errorf("invalid timeout format: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Validate operations
|
||||
if len(ext.Operations) == 0 {
|
||||
return fmt.Errorf("at least one operation must be defined")
|
||||
}
|
||||
for name, op := range ext.Operations {
|
||||
if op.CmdTemplate == "" {
|
||||
return fmt.Errorf("command template is required for operation %s", name)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
func (r *ExtensionRegistry) Remove(name string) error {
|
||||
if _, exists := r.registry.Extensions[name]; !exists {
|
||||
return fmt.Errorf("extension %s not found", name)
|
||||
|
||||
75
plugins/template/extension_registry_test.go
Normal file
75
plugins/template/extension_registry_test.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package template
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRegistryPersistence(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp("", "fabric-ext-registry-persist-*")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create temp directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
// Create test executable
|
||||
execPath := filepath.Join(tmpDir, "test-exec.sh")
|
||||
execContent := []byte("#!/bin/bash\necho \"test\"")
|
||||
err = os.WriteFile(execPath, execContent, 0755)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create test executable: %v", err)
|
||||
}
|
||||
|
||||
// Create valid config
|
||||
configContent := `name: test-extension
|
||||
executable: ` + execPath + `
|
||||
type: executable
|
||||
timeout: 30s
|
||||
operations:
|
||||
test:
|
||||
cmd_template: "{{executable}} {{operation}}"`
|
||||
|
||||
configPath := filepath.Join(tmpDir, "test-extension.yaml")
|
||||
err = os.WriteFile(configPath, []byte(configContent), 0644)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create test config: %v", err)
|
||||
}
|
||||
|
||||
// Test registry persistence
|
||||
t.Run("SaveAndReload", func(t *testing.T) {
|
||||
// Create and populate first registry
|
||||
registry1 := NewExtensionRegistry(tmpDir)
|
||||
err := registry1.Register(configPath)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to register extension: %v", err)
|
||||
}
|
||||
|
||||
// Create new registry instance and verify it loads the saved state
|
||||
registry2 := NewExtensionRegistry(tmpDir)
|
||||
ext, err := registry2.GetExtension("test-extension")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to get extension from reloaded registry: %v", err)
|
||||
}
|
||||
if ext.Name != "test-extension" {
|
||||
t.Errorf("Expected extension name 'test-extension', got %q", ext.Name)
|
||||
}
|
||||
})
|
||||
|
||||
// Test hash verification
|
||||
t.Run("HashVerification", func(t *testing.T) {
|
||||
registry := NewExtensionRegistry(tmpDir)
|
||||
|
||||
// Modify executable after registration
|
||||
modifiedExecContent := []byte("#!/bin/bash\necho \"modified\"")
|
||||
err := os.WriteFile(execPath, modifiedExecContent, 0755)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to modify executable: %v", err)
|
||||
}
|
||||
|
||||
_, err = registry.GetExtension("test-extension")
|
||||
if err == nil {
|
||||
t.Error("Expected error when executable modified, got nil")
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user