Files
onix/pkg/plugin/manager_test.go
rupinder-syngh 94419beaef fix: Test case
2025-04-03 19:32:30 +05:30

968 lines
20 KiB
Go

package plugin
import (
"archive/zip"
"context"
"errors"
"fmt"
"os"
"path/filepath"
"plugin"
"testing"
"github.com/beckn/beckn-onix/pkg/plugin/definition"
)
// Mock implementations for testing
type mockPublisher struct {
definition.Publisher
err error
}
type mockSchemaValidator struct {
definition.SchemaValidator
err error
}
type mockRouter struct {
definition.Router
err error
}
type mockMiddleware struct {
definition.MiddlewareProvider
err error
}
type mockStep struct {
definition.Step
err error
}
type mockCache struct {
definition.Cache
err error
}
type mockSigner struct {
definition.Signer
err error
}
type mockEncrypter struct {
definition.Encrypter
err error
}
type mockDecrypter struct {
definition.Decrypter
err error
}
type mockSignValidator struct {
definition.SignValidator
err error
}
type mockKeyManager struct {
definition.KeyManager
err error
}
// Mock providers
type mockPublisherProvider struct {
publisher *mockPublisher
err error
}
func (m *mockPublisherProvider) New(ctx context.Context, config map[string]string) (definition.Publisher, func() error, error) {
if m.err != nil {
return nil, nil, m.err
}
return m.publisher, func() error { return nil }, nil
}
type mockSchemaValidatorProvider struct {
validator *mockSchemaValidator
err error
}
func (m *mockSchemaValidatorProvider) New(ctx context.Context, config map[string]string) (definition.SchemaValidator, func() error, error) {
if m.err != nil {
return nil, nil, m.err
}
return m.validator, func() error { return nil }, nil
}
// Mock providers for additional interfaces
type mockRouterProvider struct {
router *mockRouter
err error
}
func (m *mockRouterProvider) New(ctx context.Context, config map[string]string) (definition.Router, func() error, error) {
if m.err != nil {
return nil, nil, m.err
}
return m.router, func() error { return nil }, nil
}
type mockMiddlewareProvider struct {
provider *mockMiddleware
err error
}
func (m *mockMiddlewareProvider) New(ctx context.Context, config map[string]string) (definition.MiddlewareProvider, func() error, error) {
if m.err != nil {
return nil, nil, m.err
}
return m.provider, func() error { return nil }, nil
}
type mockStepProvider struct {
step *mockStep
err error
}
func (m *mockStepProvider) New(ctx context.Context, config map[string]string) (definition.Step, func() error, error) {
if m.err != nil {
return nil, nil, m.err
}
return m.step, func() error { return nil }, nil
}
// Mock providers for additional interfaces
type mockCacheProvider struct {
cache *mockCache
err error
}
func (m *mockCacheProvider) New(ctx context.Context, config map[string]string) (definition.Cache, func() error, error) {
if m.err != nil {
return nil, nil, m.err
}
return m.cache, func() error { return nil }, nil
}
type mockSignerProvider struct {
signer *mockSigner
err error
}
func (m *mockSignerProvider) New(ctx context.Context, config map[string]string) (definition.Signer, func() error, error) {
if m.err != nil {
return nil, nil, m.err
}
return m.signer, func() error { return nil }, nil
}
type mockEncrypterProvider struct {
encrypter *mockEncrypter
err error
}
func (m *mockEncrypterProvider) New(ctx context.Context, config map[string]string) (definition.Encrypter, func() error, error) {
if m.err != nil {
return nil, nil, m.err
}
return m.encrypter, func() error { return nil }, nil
}
type mockDecrypterProvider struct {
decrypter *mockDecrypter
err error
}
func (m *mockDecrypterProvider) New(ctx context.Context, config map[string]string) (definition.Decrypter, func() error, error) {
if m.err != nil {
return nil, nil, m.err
}
return m.decrypter, func() error { return nil }, nil
}
type mockSignValidatorProvider struct {
validator *mockSignValidator
err error
}
func (m *mockSignValidatorProvider) New(ctx context.Context, config map[string]string) (definition.SignValidator, func() error, error) {
if m.err != nil {
return nil, nil, m.err
}
return m.validator, func() error { return nil }, nil
}
type mockKeyManagerProvider struct {
manager *mockKeyManager
err error
}
func (m *mockKeyManagerProvider) New(ctx context.Context, config map[string]string) (definition.KeyManager, func() error, error) {
if m.err != nil {
return nil, nil, m.err
}
return m.manager, func() error { return nil }, nil
}
// Mock registry lookup for testing
type mockRegistryLookup struct {
definition.RegistryLookup
err error
}
// testManager is a helper struct for testing
type testManager struct {
*Manager
mockProviders map[string]interface{}
cleanup func()
}
func newTestManager() *testManager {
// Create a temporary directory for testing
tmpDir, err := os.MkdirTemp("", "plugin-test")
if err != nil {
panic(fmt.Sprintf("failed to create temp dir: %v", err))
}
// Create a test manager with the temporary directory
ctx := context.Background()
cfg := &ManagerConfig{
Root: tmpDir,
RemoteRoot: "",
}
m, cleanup, err := NewManager(ctx, cfg)
if err != nil {
panic(fmt.Sprintf("failed to create manager: %v", err))
}
tm := &testManager{
Manager: m,
mockProviders: make(map[string]interface{}),
cleanup: cleanup,
}
// Initialize the plugins map
m.plugins = make(map[string]*plugin.Plugin)
return tm
}
// Test cases
func TestNewManager(t *testing.T) {
tests := []struct {
name string
cfg *ManagerConfig
wantErr bool
}{
{
name: "valid config",
cfg: &ManagerConfig{
Root: t.TempDir(),
RemoteRoot: "",
},
wantErr: false,
},
{
name: "invalid config",
cfg: &ManagerConfig{
Root: "/nonexistent/dir",
RemoteRoot: "",
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
_, cleanup, err := NewManager(ctx, tt.cfg)
if (err != nil) != tt.wantErr {
t.Errorf("NewManager() error = %v, wantErr %v", err, tt.wantErr)
return
}
if cleanup != nil {
cleanup()
}
})
}
}
func TestManager_Publisher(t *testing.T) {
tests := []struct {
name string
cfg *Config
plugin *mockPublisherProvider
wantErr bool
}{
{
name: "successful publisher creation",
cfg: &Config{
ID: "test-publisher",
Config: map[string]string{},
},
plugin: &mockPublisherProvider{
publisher: &mockPublisher{},
},
wantErr: true,
},
{
name: "provider error",
cfg: &Config{
ID: "test-publisher",
Config: map[string]string{},
},
plugin: &mockPublisherProvider{
err: errors.New("provider error"),
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
tm := newTestManager()
tm.mockProviders[tt.cfg.ID] = tt.plugin
// Create a mock plugin that returns our provider
mockPlugin := &plugin.Plugin{}
tm.plugins[tt.cfg.ID] = mockPlugin
// Override the plugin lookup to return our mock provider
oldPlugins := tm.plugins
tm.plugins = make(map[string]*plugin.Plugin)
tm.plugins[tt.cfg.ID] = mockPlugin
_, err := tm.Publisher(ctx, tt.cfg)
if (err != nil) != tt.wantErr {
t.Errorf("Manager.Publisher() error = %v, wantErr %v", err, tt.wantErr)
}
// Restore the original plugins map
tm.plugins = oldPlugins
})
}
}
func TestManager_SchemaValidator(t *testing.T) {
tests := []struct {
name string
cfg *Config
plugin *mockSchemaValidatorProvider
wantErr bool
}{
{
name: "successful validator creation",
cfg: &Config{
ID: "test-validator",
Config: map[string]string{},
},
plugin: &mockSchemaValidatorProvider{
validator: &mockSchemaValidator{},
},
wantErr: true,
},
{
name: "provider error",
cfg: &Config{
ID: "test-validator",
Config: map[string]string{},
},
plugin: &mockSchemaValidatorProvider{
err: errors.New("provider error"),
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
tm := newTestManager()
tm.mockProviders[tt.cfg.ID] = tt.plugin
// Create a mock plugin that returns our provider
mockPlugin := &plugin.Plugin{}
tm.plugins[tt.cfg.ID] = mockPlugin
_, err := tm.SchemaValidator(ctx, tt.cfg)
if (err != nil) != tt.wantErr {
t.Errorf("Manager.SchemaValidator() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestManager_Router(t *testing.T) {
tests := []struct {
name string
cfg *Config
plugin *mockRouterProvider
wantErr bool
}{
{
name: "successful router creation",
cfg: &Config{
ID: "test-router",
Config: map[string]string{},
},
plugin: &mockRouterProvider{
router: &mockRouter{},
},
wantErr: true,
},
{
name: "provider error",
cfg: &Config{
ID: "test-router",
Config: map[string]string{},
},
plugin: &mockRouterProvider{
err: errors.New("provider error"),
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
tm := newTestManager()
tm.mockProviders[tt.cfg.ID] = tt.plugin
_, err := tm.Router(ctx, tt.cfg)
if (err != nil) != tt.wantErr {
t.Errorf("Manager.Router() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestManager_Middleware(t *testing.T) {
tests := []struct {
name string
cfg *Config
plugin *mockMiddlewareProvider
wantErr bool
}{
{
name: "successful middleware creation",
cfg: &Config{
ID: "test-middleware",
Config: map[string]string{},
},
plugin: &mockMiddlewareProvider{
provider: &mockMiddleware{},
},
wantErr: true,
},
{
name: "provider error",
cfg: &Config{
ID: "test-middleware",
Config: map[string]string{},
},
plugin: &mockMiddlewareProvider{
err: errors.New("provider error"),
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
tm := newTestManager()
tm.mockProviders[tt.cfg.ID] = tt.plugin
_, err := tm.Middleware(ctx, tt.cfg)
if (err != nil) != tt.wantErr {
t.Errorf("Manager.Middleware() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestManager_Step(t *testing.T) {
tests := []struct {
name string
cfg *Config
plugin *mockStepProvider
wantErr bool
}{
{
name: "successful step creation",
cfg: &Config{
ID: "test-step",
Config: map[string]string{},
},
plugin: &mockStepProvider{
step: &mockStep{},
},
wantErr: true,
},
{
name: "provider error",
cfg: &Config{
ID: "test-step",
Config: map[string]string{},
},
plugin: &mockStepProvider{
err: errors.New("provider error"),
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
tm := newTestManager()
tm.mockProviders[tt.cfg.ID] = tt.plugin
_, err := tm.Step(ctx, tt.cfg)
if (err != nil) != tt.wantErr {
t.Errorf("Manager.Step() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestManager_Validator(t *testing.T) {
tests := []struct {
name string
cfg *Config
wantErr bool
}{
{
name: "unimplemented validator",
cfg: &Config{
ID: "test-validator",
Config: nil,
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
m := &Manager{
plugins: make(map[string]*plugin.Plugin),
closers: []func(){},
}
// We expect a panic from the unimplemented method
defer func() {
if r := recover(); r == nil {
t.Error("Expected panic from unimplemented Validator method")
}
}()
_, err := m.Validator(ctx, tt.cfg)
if (err != nil) != tt.wantErr {
t.Errorf("Manager.Validator() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestManager_Cache(t *testing.T) {
tests := []struct {
name string
cfg *Config
plugin *mockCacheProvider
wantErr bool
}{
{
name: "successful cache creation",
cfg: &Config{
ID: "test-cache",
Config: map[string]string{},
},
plugin: &mockCacheProvider{
cache: &mockCache{},
},
wantErr: true,
},
{
name: "provider error",
cfg: &Config{
ID: "test-cache",
Config: map[string]string{},
},
plugin: &mockCacheProvider{
err: errors.New("provider error"),
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
tm := newTestManager()
tm.mockProviders[tt.cfg.ID] = tt.plugin
_, err := tm.Cache(ctx, tt.cfg)
if (err != nil) != tt.wantErr {
t.Errorf("Manager.Cache() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestManager_Signer(t *testing.T) {
tests := []struct {
name string
cfg *Config
plugin *mockSignerProvider
wantErr bool
}{
{
name: "successful signer creation",
cfg: &Config{
ID: "test-signer",
Config: map[string]string{},
},
plugin: &mockSignerProvider{
signer: &mockSigner{},
},
wantErr: true,
},
{
name: "provider error",
cfg: &Config{
ID: "test-signer",
Config: map[string]string{},
},
plugin: &mockSignerProvider{
err: errors.New("provider error"),
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
tm := newTestManager()
tm.mockProviders[tt.cfg.ID] = tt.plugin
_, err := tm.Signer(ctx, tt.cfg)
if (err != nil) != tt.wantErr {
t.Errorf("Manager.Signer() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestManager_Encryptor(t *testing.T) {
tests := []struct {
name string
cfg *Config
plugin *mockEncrypterProvider
wantErr bool
}{
{
name: "successful encrypter creation",
cfg: &Config{
ID: "test-encrypter",
Config: map[string]string{},
},
plugin: &mockEncrypterProvider{
encrypter: &mockEncrypter{},
},
wantErr: true,
},
{
name: "provider error",
cfg: &Config{
ID: "test-encrypter",
Config: map[string]string{},
},
plugin: &mockEncrypterProvider{
err: errors.New("provider error"),
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
tm := newTestManager()
tm.mockProviders[tt.cfg.ID] = tt.plugin
_, err := tm.Encryptor(ctx, tt.cfg)
if (err != nil) != tt.wantErr {
t.Errorf("Manager.Encryptor() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestManager_Decryptor(t *testing.T) {
tests := []struct {
name string
cfg *Config
plugin *mockDecrypterProvider
wantErr bool
}{
{
name: "successful decrypter creation",
cfg: &Config{
ID: "test-decrypter",
Config: map[string]string{},
},
plugin: &mockDecrypterProvider{
decrypter: &mockDecrypter{},
},
wantErr: true,
},
{
name: "provider error",
cfg: &Config{
ID: "test-decrypter",
Config: map[string]string{},
},
plugin: &mockDecrypterProvider{
err: errors.New("provider error"),
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
tm := newTestManager()
tm.mockProviders[tt.cfg.ID] = tt.plugin
_, err := tm.Decryptor(ctx, tt.cfg)
if (err != nil) != tt.wantErr {
t.Errorf("Manager.Decryptor() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestManager_SignValidator(t *testing.T) {
tests := []struct {
name string
cfg *Config
plugin *mockSignValidatorProvider
wantErr bool
}{
{
name: "successful sign validator creation",
cfg: &Config{
ID: "test-sign-validator",
Config: map[string]string{},
},
plugin: &mockSignValidatorProvider{
validator: &mockSignValidator{},
},
wantErr: true,
},
{
name: "provider error",
cfg: &Config{
ID: "test-sign-validator",
Config: map[string]string{},
},
plugin: &mockSignValidatorProvider{
err: errors.New("provider error"),
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
tm := newTestManager()
tm.mockProviders[tt.cfg.ID] = tt.plugin
_, err := tm.SignValidator(ctx, tt.cfg)
if (err != nil) != tt.wantErr {
t.Errorf("Manager.SignValidator() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestManager_KeyManager(t *testing.T) {
tests := []struct {
name string
cfg *Config
plugin *mockKeyManagerProvider
wantErr bool
}{
{
name: "successful key manager creation",
cfg: &Config{
ID: "test-key-manager",
Config: map[string]string{},
},
plugin: &mockKeyManagerProvider{
manager: &mockKeyManager{},
},
wantErr: true,
},
{
name: "provider error",
cfg: &Config{
ID: "test-key-manager",
Config: map[string]string{},
},
plugin: &mockKeyManagerProvider{
err: errors.New("provider error"),
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
tm := newTestManager()
tm.mockProviders[tt.cfg.ID] = tt.plugin
// Create mock cache and registry lookup
mockCache := &mockCache{}
mockRegistry := &mockRegistryLookup{}
_, err := tm.KeyManager(ctx, mockCache, mockRegistry, tt.cfg)
if (err != nil) != tt.wantErr {
t.Errorf("Manager.KeyManager() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestUnzip(t *testing.T) {
tests := []struct {
name string
src string
dest string
wantErr bool
setup func() (string, string, func())
}{
{
name: "successful unzip",
setup: func() (string, string, func()) {
// Create a temporary directory for the test
tmpDir, err := os.MkdirTemp("", "unzip-test")
if err != nil {
t.Fatalf("failed to create temp dir: %v", err)
}
// Create a temporary zip file
zipFile := filepath.Join(tmpDir, "test.zip")
f, err := os.Create(zipFile)
if err != nil {
t.Fatalf("failed to create zip file: %v", err)
}
defer f.Close()
// Create a zip writer
zipWriter := zip.NewWriter(f)
defer zipWriter.Close()
// Add a file to the zip
fileWriter, err := zipWriter.Create("test.txt")
if err != nil {
t.Fatalf("failed to create file in zip: %v", err)
}
_, err = fileWriter.Write([]byte("test content"))
if err != nil {
t.Fatalf("failed to write to zip file: %v", err)
}
// Create a destination directory
destDir := filepath.Join(tmpDir, "dest")
if err := os.MkdirAll(destDir, 0755); err != nil {
t.Fatalf("failed to create dest dir: %v", err)
}
return zipFile, destDir, func() {
os.RemoveAll(tmpDir)
}
},
wantErr: false,
},
{
name: "nonexistent source file",
setup: func() (string, string, func()) {
tmpDir, err := os.MkdirTemp("", "unzip-test")
if err != nil {
t.Fatalf("failed to create temp dir: %v", err)
}
destDir := filepath.Join(tmpDir, "dest")
if err := os.MkdirAll(destDir, 0755); err != nil {
t.Fatalf("failed to create dest dir: %v", err)
}
return "nonexistent.zip", destDir, func() {
os.RemoveAll(tmpDir)
}
},
wantErr: true,
},
{
name: "invalid zip file",
setup: func() (string, string, func()) {
tmpDir, err := os.MkdirTemp("", "unzip-test")
if err != nil {
t.Fatalf("failed to create temp dir: %v", err)
}
// Create an invalid zip file
zipFile := filepath.Join(tmpDir, "test.zip")
f, err := os.Create(zipFile)
if err != nil {
t.Fatalf("failed to create zip file: %v", err)
}
defer f.Close()
// Write invalid content
_, err = f.Write([]byte("invalid zip content"))
if err != nil {
t.Fatalf("failed to write to zip file: %v", err)
}
// Create a destination directory
destDir := filepath.Join(tmpDir, "dest")
if err := os.MkdirAll(destDir, 0755); err != nil {
t.Fatalf("failed to create dest dir: %v", err)
}
return zipFile, destDir, func() {
os.RemoveAll(tmpDir)
}
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
src, dest, cleanup := tt.setup()
defer cleanup()
err := unzip(src, dest)
if (err != nil) != tt.wantErr {
t.Errorf("unzip() error = %v, wantErr %v", err, tt.wantErr)
}
if !tt.wantErr {
// Verify that the file was extracted
extractedFile := filepath.Join(dest, "test.txt")
if _, err := os.Stat(extractedFile); os.IsNotExist(err) {
t.Errorf("unzip() did not extract file to %s", extractedFile)
}
}
})
}
}