293 lines
7.6 KiB
Go
293 lines
7.6 KiB
Go
package plugins
|
|||
|
|
|
||
|
|
import (
|
||
|
|
"os"
|
||
|
|
"path/filepath"
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"github.com/stretchr/testify/assert"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestNewPluginLoader(t *testing.T) {
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, "/tmp/plugins")
|
||
|
|
|
||
|
|
assert.NotNil(t, loader)
|
||
|
|
assert.Equal(t, registry, loader.registry)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestRegisterLoadedPlugin(t *testing.T) {
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, "/tmp/plugins")
|
||
|
|
|
||
|
|
plugin := &MockPlugin{name: "test-plugin", version: "1.0.0"}
|
||
|
|
err := loader.RegisterLoadedPlugin(plugin, "test-author", nil)
|
||
|
|
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.True(t, loader.IsPluginLoaded("test-plugin"))
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestUnloadPlugin(t *testing.T) {
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, "/tmp/plugins")
|
||
|
|
|
||
|
|
plugin := &MockPlugin{name: "test-plugin", version: "1.0.0"}
|
||
|
|
loader.RegisterLoadedPlugin(plugin, "test-author", nil)
|
||
|
|
|
||
|
|
assert.True(t, loader.IsPluginLoaded("test-plugin"))
|
||
|
|
|
||
|
|
err := loader.UnloadPlugin("test-plugin")
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.False(t, loader.IsPluginLoaded("test-plugin"))
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestUnloadPluginNotFound(t *testing.T) {
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, "/tmp/plugins")
|
||
|
|
|
||
|
|
err := loader.UnloadPlugin("nonexistent")
|
||
|
|
assert.Error(t, err)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestReloadPlugin(t *testing.T) {
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, "/tmp/plugins")
|
||
|
|
|
||
|
|
plugin := &MockPlugin{name: "test-plugin", version: "1.0.0"}
|
||
|
|
loader.RegisterLoadedPlugin(plugin, "test-author", nil)
|
||
|
|
|
||
|
|
_, _ = loader.GetLoadTime("test-plugin")
|
||
|
|
|
||
|
|
err := loader.ReloadPlugin("test-plugin")
|
||
|
|
assert.NoError(t, err)
|
||
|
|
|
||
|
|
loadedPlugins := loader.GetLoadedPlugins()
|
||
|
|
assert.Equal(t, 1, loadedPlugins["test-plugin"].ReloadCount)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestReloadPluginNotFound(t *testing.T) {
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, "/tmp/plugins")
|
||
|
|
|
||
|
|
err := loader.ReloadPlugin("nonexistent")
|
||
|
|
assert.Error(t, err)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestGetLoadedPlugins(t *testing.T) {
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, "/tmp/plugins")
|
||
|
|
|
||
|
|
for i := 0; i < 3; i++ {
|
||
|
|
plugin := &MockPlugin{
|
||
|
|
name: string(rune(48 + i)) + "-plugin",
|
||
|
|
version: "1.0.0",
|
||
|
|
}
|
||
|
|
loader.RegisterLoadedPlugin(plugin, "author", nil)
|
||
|
|
}
|
||
|
|
|
||
|
|
loaded := loader.GetLoadedPlugins()
|
||
|
|
assert.Equal(t, 3, len(loaded))
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestGetLoadTime(t *testing.T) {
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, "/tmp/plugins")
|
||
|
|
|
||
|
|
plugin := &MockPlugin{name: "test-plugin", version: "1.0.0"}
|
||
|
|
loader.RegisterLoadedPlugin(plugin, "author", nil)
|
||
|
|
|
||
|
|
loadTime, exists := loader.GetLoadTime("test-plugin")
|
||
|
|
assert.True(t, exists)
|
||
|
|
assert.NotZero(t, loadTime)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestIsPluginLoaded(t *testing.T) {
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, "/tmp/plugins")
|
||
|
|
|
||
|
|
assert.False(t, loader.IsPluginLoaded("test-plugin"))
|
||
|
|
|
||
|
|
plugin := &MockPlugin{name: "test-plugin", version: "1.0.0"}
|
||
|
|
loader.RegisterLoadedPlugin(plugin, "author", nil)
|
||
|
|
|
||
|
|
assert.True(t, loader.IsPluginLoaded("test-plugin"))
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestLoaderExecutePlugin(t *testing.T) {
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, "/tmp/plugins")
|
||
|
|
|
||
|
|
plugin := &MockPlugin{name: "test-plugin", version: "1.0.0"}
|
||
|
|
loader.RegisterLoadedPlugin(plugin, "author", nil)
|
||
|
|
|
||
|
|
output, err := loader.ExecutePlugin("test-plugin", map[string]interface{}{})
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.NotNil(t, output)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestLoaderExecutePluginNotLoaded(t *testing.T) {
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, "/tmp/plugins")
|
||
|
|
|
||
|
|
_, err := loader.ExecutePlugin("nonexistent", map[string]interface{}{})
|
||
|
|
assert.Error(t, err)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestGetPluginStats(t *testing.T) {
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, "/tmp/plugins")
|
||
|
|
|
||
|
|
plugin := &MockPlugin{name: "test-plugin", version: "1.0.0"}
|
||
|
|
loader.RegisterLoadedPlugin(plugin, "author", nil)
|
||
|
|
|
||
|
|
stats, err := loader.GetPluginStats("test-plugin")
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.NotNil(t, stats)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestGetPluginStatsNotLoaded(t *testing.T) {
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, "/tmp/plugins")
|
||
|
|
|
||
|
|
_, err := loader.GetPluginStats("nonexistent")
|
||
|
|
assert.Error(t, err)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestClose(t *testing.T) {
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, "/tmp/plugins")
|
||
|
|
|
||
|
|
for i := 0; i < 3; i++ {
|
||
|
|
plugin := &MockPlugin{
|
||
|
|
name: string(rune(48+i)) + "-plugin",
|
||
|
|
version: "1.0.0",
|
||
|
|
}
|
||
|
|
loader.RegisterLoadedPlugin(plugin, "author", nil)
|
||
|
|
}
|
||
|
|
|
||
|
|
assert.Equal(t, 3, len(loader.GetLoadedPlugins()))
|
||
|
|
|
||
|
|
err := loader.Close()
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.Equal(t, 0, len(loader.GetLoadedPlugins()))
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestGetPluginRegistry(t *testing.T) {
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, "/tmp/plugins")
|
||
|
|
|
||
|
|
retrieved := loader.GetPluginRegistry()
|
||
|
|
assert.Equal(t, registry, retrieved)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestLoadPlugin(t *testing.T) {
|
||
|
|
tmpDir := t.TempDir()
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, tmpDir)
|
||
|
|
|
||
|
|
// For now, test with plugin:// URL (no file loading needed)
|
||
|
|
err := loader.LoadPlugin("plugin://test-plugin")
|
||
|
|
assert.NoError(t, err)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestLoadPluginDirectory(t *testing.T) {
|
||
|
|
tmpDir := t.TempDir()
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, tmpDir)
|
||
|
|
|
||
|
|
// Create some mock config files
|
||
|
|
configContent := `{
|
||
|
|
"name": "test-plugin",
|
||
|
|
"version": "1.0.0",
|
||
|
|
"author": "test-author",
|
||
|
|
"path": "test-plugin"
|
||
|
|
}`
|
||
|
|
|
||
|
|
configFile := filepath.Join(tmpDir, "test-plugin.json")
|
||
|
|
os.WriteFile(configFile, []byte(configContent), 0644)
|
||
|
|
|
||
|
|
// Load from directory (won't actually load plugins without more setup)
|
||
|
|
err := loader.LoadPluginDirectory(tmpDir)
|
||
|
|
assert.NoError(t, err)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestLoadPluginDirectoryNotFound(t *testing.T) {
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, "/tmp/plugins")
|
||
|
|
|
||
|
|
err := loader.LoadPluginDirectory("/nonexistent/directory")
|
||
|
|
assert.Error(t, err)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestGetFailedLoads(t *testing.T) {
|
||
|
|
tmpDir := t.TempDir()
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, tmpDir)
|
||
|
|
|
||
|
|
// Try to load from nonexistent file
|
||
|
|
loader.LoadPlugin(filepath.Join(tmpDir, "nonexistent.json"))
|
||
|
|
|
||
|
|
failed := loader.GetFailedLoads()
|
||
|
|
assert.Greater(t, len(failed), 0)
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestMultiplePluginLifecycle(t *testing.T) {
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, "/tmp/plugins")
|
||
|
|
|
||
|
|
// Load plugins
|
||
|
|
for i := 0; i < 5; i++ {
|
||
|
|
plugin := &MockPlugin{
|
||
|
|
name: string(rune(48+i)) + "-plugin",
|
||
|
|
version: "1.0.0",
|
||
|
|
}
|
||
|
|
err := loader.RegisterLoadedPlugin(plugin, "author", nil)
|
||
|
|
assert.NoError(t, err)
|
||
|
|
}
|
||
|
|
|
||
|
|
assert.Equal(t, 5, len(loader.GetLoadedPlugins()))
|
||
|
|
|
||
|
|
// Execute plugins
|
||
|
|
for i := 0; i < 5; i++ {
|
||
|
|
name := string(rune(48+i)) + "-plugin"
|
||
|
|
output, err := loader.ExecutePlugin(name, map[string]interface{}{})
|
||
|
|
assert.NoError(t, err)
|
||
|
|
assert.NotNil(t, output)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Unload plugins
|
||
|
|
for i := 0; i < 5; i++ {
|
||
|
|
name := string(rune(48+i)) + "-plugin"
|
||
|
|
err := loader.UnloadPlugin(name)
|
||
|
|
assert.NoError(t, err)
|
||
|
|
}
|
||
|
|
|
||
|
|
assert.Equal(t, 0, len(loader.GetLoadedPlugins()))
|
||
|
|
}
|
||
|
|
|
||
|
|
func BenchmarkRegisterLoadedPlugin(b *testing.B) {
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, "/tmp/plugins")
|
||
|
|
|
||
|
|
for i := 0; i < b.N; i++ {
|
||
|
|
plugin := &MockPlugin{
|
||
|
|
name: string(rune(48+i%100)) + "-plugin",
|
||
|
|
version: "1.0.0",
|
||
|
|
}
|
||
|
|
loader.RegisterLoadedPlugin(plugin, "author", nil)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func BenchmarkExecuteLoadedPlugin(b *testing.B) {
|
||
|
|
registry := NewPluginRegistry()
|
||
|
|
loader := NewPluginLoader(registry, "/tmp/plugins")
|
||
|
|
|
||
|
|
plugin := &MockPlugin{name: "test-plugin", version: "1.0.0"}
|
||
|
|
loader.RegisterLoadedPlugin(plugin, "author", nil)
|
||
|
|
|
||
|
|
b.ResetTimer()
|
||
|
|
for i := 0; i < b.N; i++ {
|
||
|
|
loader.ExecutePlugin("test-plugin", map[string]interface{}{})
|
||
|
|
}
|
||
|
|
}
|