github.com/yandex/pandora@v0.5.32/core/plugin/constructor_test.go (about)

     1  package plugin
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"reflect"
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/require"
    11  )
    12  
    13  func Test_PluginConstructor_ExpectationsFailed(t *testing.T) {
    14  	tests := []struct {
    15  		name      string
    16  		newPlugin any
    17  	}{
    18  		{"not func", errors.New("that is not constructor")},
    19  		{"not implements", func() struct{} { panic("") }},
    20  		{"too many args", func(_, _ ptestConfig) ptestPlugin { panic("") }},
    21  		{"too many return valued", func() (_ ptestPlugin, _, _ error) { panic("") }},
    22  		{"second return value is not error", func() (_, _ ptestPlugin) { panic("") }},
    23  	}
    24  	for _, tt := range tests {
    25  		t.Run(tt.name, func(t *testing.T) {
    26  			defer recoverExpectationFail(t)
    27  			newPluginConstructor(ptestType(), tt.newPlugin)
    28  		})
    29  	}
    30  }
    31  
    32  func Test_PluginConstructor_NewPlugin(t *testing.T) {
    33  	newPlugin := func(newPlugin interface{}, maybeConf []reflect.Value) (interface{}, error) {
    34  		testee := newPluginConstructor(ptestType(), newPlugin)
    35  		return testee.NewPlugin(maybeConf)
    36  	}
    37  
    38  	t.Run("", func(t *testing.T) {
    39  		plugin, err := newPlugin(ptestNew, nil)
    40  		assert.NoError(t, err)
    41  		ptestExpectConfigValue(t, plugin, ptestInitValue)
    42  	})
    43  
    44  	t.Run("more that plugin", func(t *testing.T) {
    45  		plugin, err := newPlugin(ptestNewMoreThan, nil)
    46  		assert.NoError(t, err)
    47  		ptestExpectConfigValue(t, plugin, ptestInitValue)
    48  	})
    49  
    50  	t.Run("config", func(t *testing.T) {
    51  		plugin, err := newPlugin(ptestNewConf, confToMaybe(ptestDefaultConf()))
    52  		assert.NoError(t, err)
    53  		ptestExpectConfigValue(t, plugin, ptestDefaultValue)
    54  	})
    55  
    56  	t.Run("failed", func(t *testing.T) {
    57  		plugin, err := newPlugin(ptestNewErrFailing, nil)
    58  		assert.ErrorIs(t, err, ptestCreateFailedErr)
    59  		assert.Nil(t, plugin)
    60  	})
    61  
    62  }
    63  
    64  func Test_PluginConstructor_NewFactory(t *testing.T) {
    65  	newFactoryOK := func(newPlugin interface{}, factoryType reflect.Type, getMaybeConf func() ([]reflect.Value, error)) interface{} {
    66  		testee := newPluginConstructor(ptestType(), newPlugin)
    67  		factory, err := testee.NewFactory(factoryType, getMaybeConf)
    68  		require.NoError(t, err)
    69  		return factory
    70  	}
    71  
    72  	t.Run("same type - no wrap", func(t *testing.T) {
    73  		factory := newFactoryOK(ptestNew, ptestNewType(), nil)
    74  		expectSameFunc(t, factory, ptestNew)
    75  	})
    76  
    77  	t.Run(" new impl", func(t *testing.T) {
    78  		factory := newFactoryOK(ptestNewImpl, ptestNewType(), nil)
    79  		f, ok := factory.(func() ptestPlugin)
    80  		assert.True(t, ok)
    81  		plugin := f()
    82  		ptestExpectConfigValue(t, plugin, ptestInitValue)
    83  	})
    84  
    85  	t.Run("more than", func(t *testing.T) {
    86  		factory := newFactoryOK(ptestNewMoreThan, ptestNewType(), nil)
    87  		f, ok := factory.(func() ptestPlugin)
    88  		assert.True(t, ok)
    89  		plugin := f()
    90  		ptestExpectConfigValue(t, plugin, ptestInitValue)
    91  	})
    92  
    93  	t.Run("add err", func(t *testing.T) {
    94  		factory := newFactoryOK(ptestNew, ptestNewErrType(), nil)
    95  		f, ok := factory.(func() (ptestPlugin, error))
    96  		assert.True(t, ok)
    97  		plugin, err := f()
    98  		assert.NoError(t, err)
    99  		ptestExpectConfigValue(t, plugin, ptestInitValue)
   100  	})
   101  
   102  	t.Run("trim nil err", func(t *testing.T) {
   103  		factory := newFactoryOK(ptestNewErr, ptestNewType(), nil)
   104  		f, ok := factory.(func() ptestPlugin)
   105  		assert.True(t, ok)
   106  		plugin := f()
   107  		ptestExpectConfigValue(t, plugin, ptestInitValue)
   108  	})
   109  
   110  	t.Run("config", func(t *testing.T) {
   111  		factory := newFactoryOK(ptestNewConf, ptestNewType(), confToGetMaybe(ptestDefaultConf()))
   112  		f, ok := factory.(func() ptestPlugin)
   113  		assert.True(t, ok)
   114  		plugin := f()
   115  		ptestExpectConfigValue(t, plugin, ptestDefaultValue)
   116  	})
   117  
   118  	t.Run("new factory, get config failed", func(t *testing.T) {
   119  		factory := newFactoryOK(ptestNewConf, ptestNewErrType(), errToGetMaybe(ptestConfigurationFailedErr))
   120  		f, ok := factory.(func() (ptestPlugin, error))
   121  		assert.True(t, ok)
   122  		plugin, err := f()
   123  		assert.ErrorIs(t, err, ptestConfigurationFailedErr)
   124  		assert.Nil(t, plugin)
   125  	})
   126  
   127  	t.Run("no err, get config failed, throw panic", func(t *testing.T) {
   128  		factory := newFactoryOK(ptestNewConf, ptestNewType(), errToGetMaybe(ptestConfigurationFailedErr))
   129  		f, ok := factory.(func() ptestPlugin)
   130  		assert.True(t, ok)
   131  		func() {
   132  			defer func() {
   133  				r := recover()
   134  				assert.Equal(t, ptestConfigurationFailedErr, r)
   135  			}()
   136  			f()
   137  		}()
   138  	})
   139  
   140  	t.Run("panic on trim non nil err", func(t *testing.T) {
   141  		factory := newFactoryOK(ptestNewErrFailing, ptestNewType(), nil)
   142  		f, ok := factory.(func() ptestPlugin)
   143  		assert.True(t, ok)
   144  		func() {
   145  			defer func() {
   146  				r := recover()
   147  				assert.Equal(t, ptestCreateFailedErr, r)
   148  			}()
   149  			f()
   150  		}()
   151  	})
   152  
   153  }
   154  
   155  func TestFactoryConstructorExpectationsFailed(t *testing.T) {
   156  	tests := []struct {
   157  		name      string
   158  		newPlugin any
   159  	}{
   160  		{"not func", errors.New("that is not constructor")},
   161  		{"returned not func", func() error { panic("") }},
   162  		{"too many args", func(_, _ ptestConfig) func() ptestPlugin { panic("") }},
   163  		{"too many return valued", func() (func() ptestPlugin, error, error) { panic("") }},
   164  		{"second return value is not error", func() (func() ptestPlugin, ptestPlugin) { panic("") }},
   165  		{"factory accepts conf", func() func(config ptestConfig) ptestPlugin { panic("") }},
   166  		{"not implements", func() func() struct{} { panic("") }},
   167  		{"factory too many args", func() func(_, _ ptestConfig) ptestPlugin { panic("") }},
   168  		{"factory too many return valued", func() func() (_ ptestPlugin, _, _ error) { panic("") }},
   169  		{"factory second return value is not error", func() func() (_, _ ptestPlugin) { panic("") }},
   170  	}
   171  	for _, tt := range tests {
   172  		t.Run(tt.name, func(t *testing.T) {
   173  			defer recoverExpectationFail(t)
   174  			newFactoryConstructor(ptestType(), tt.newPlugin)
   175  		})
   176  	}
   177  }
   178  
   179  func TestFactoryConstructorNewPlugin(t *testing.T) {
   180  	newPlugin := func(newFactory interface{}, maybeConf []reflect.Value) (interface{}, error) {
   181  		testee := newFactoryConstructor(ptestType(), newFactory)
   182  		return testee.NewPlugin(maybeConf)
   183  	}
   184  
   185  	t.Run("", func(t *testing.T) {
   186  		plugin, err := newPlugin(ptestNewFactory, nil)
   187  		assert.NoError(t, err)
   188  		ptestExpectConfigValue(t, plugin, ptestInitValue)
   189  	})
   190  
   191  	t.Run("impl", func(t *testing.T) {
   192  		plugin, err := newPlugin(ptestNewFactoryImpl, nil)
   193  		assert.NoError(t, err)
   194  		ptestExpectConfigValue(t, plugin, ptestInitValue)
   195  	})
   196  
   197  	t.Run("impl more than", func(t *testing.T) {
   198  		plugin, err := newPlugin(ptestNewFactoryMoreThan, nil)
   199  		assert.NoError(t, err)
   200  		ptestExpectConfigValue(t, plugin, ptestInitValue)
   201  	})
   202  
   203  	t.Run("config", func(t *testing.T) {
   204  		plugin, err := newPlugin(ptestNewFactoryConf, confToMaybe(ptestDefaultConf()))
   205  		assert.NoError(t, err)
   206  		ptestExpectConfigValue(t, plugin, ptestDefaultValue)
   207  	})
   208  
   209  	t.Run("failed", func(t *testing.T) {
   210  		plugin, err := newPlugin(ptestNewFactoryErrFailing, nil)
   211  		assert.ErrorIs(t, err, ptestCreateFailedErr)
   212  		assert.Nil(t, plugin)
   213  	})
   214  
   215  	t.Run("factory failed", func(t *testing.T) {
   216  		plugin, err := newPlugin(ptestNewFactoryFactoryErrFailing, nil)
   217  		assert.ErrorIs(t, err, ptestCreateFailedErr)
   218  		assert.Nil(t, plugin)
   219  	})
   220  }
   221  
   222  func TestFactoryConstructorNewFactory(t *testing.T) {
   223  	newFactory := func(newFactory interface{}, factoryType reflect.Type, getMaybeConf func() ([]reflect.Value, error)) (interface{}, error) {
   224  		testee := newFactoryConstructor(ptestType(), newFactory)
   225  		return testee.NewFactory(factoryType, getMaybeConf)
   226  	}
   227  	newFactoryOK := func(newF interface{}, factoryType reflect.Type, getMaybeConf func() ([]reflect.Value, error)) interface{} {
   228  		factory, err := newFactory(newF, factoryType, getMaybeConf)
   229  		require.NoError(t, err)
   230  		return factory
   231  	}
   232  
   233  	t.Run("no err, same type - no wrap", func(t *testing.T) {
   234  		factory := newFactoryOK(ptestNewFactory, ptestNewType(), nil)
   235  		expectSameFunc(t, factory, ptestNew)
   236  	})
   237  
   238  	t.Run("has err, same type - no wrap", func(t *testing.T) {
   239  		factory := newFactoryOK(ptestNewFactoryFactoryErr, ptestNewErrType(), nil)
   240  		expectSameFunc(t, factory, ptestNewErr)
   241  	})
   242  
   243  	t.Run("from new impl", func(t *testing.T) {
   244  		factory := newFactoryOK(ptestNewFactoryImpl, ptestNewType(), nil)
   245  		f, ok := factory.(func() ptestPlugin)
   246  		assert.True(t, ok)
   247  		plugin := f()
   248  		ptestExpectConfigValue(t, plugin, ptestInitValue)
   249  	})
   250  
   251  	t.Run("from new impl", func(t *testing.T) {
   252  		factory := newFactoryOK(ptestNewFactoryMoreThan, ptestNewType(), nil)
   253  		f, ok := factory.(func() ptestPlugin)
   254  		assert.True(t, ok)
   255  		plugin := f()
   256  		ptestExpectConfigValue(t, plugin, ptestInitValue)
   257  	})
   258  
   259  	t.Run("add err", func(t *testing.T) {
   260  		factory := newFactoryOK(ptestNewFactory, ptestNewErrType(), nil)
   261  		f, ok := factory.(func() (ptestPlugin, error))
   262  		assert.True(t, ok)
   263  		plugin, err := f()
   264  		assert.NoError(t, err)
   265  		ptestExpectConfigValue(t, plugin, ptestInitValue)
   266  	})
   267  
   268  	t.Run("factory construction not failed", func(t *testing.T) {
   269  		factory := newFactoryOK(ptestNewFactoryErr, ptestNewType(), nil)
   270  		f, ok := factory.(func() ptestPlugin)
   271  		assert.True(t, ok)
   272  		plugin := f()
   273  		ptestExpectConfigValue(t, plugin, ptestInitValue)
   274  	})
   275  
   276  	t.Run("trim nil err", func(t *testing.T) {
   277  		factory := newFactoryOK(ptestNewFactoryFactoryErr, ptestNewType(), nil)
   278  		f, ok := factory.(func() ptestPlugin)
   279  		assert.True(t, ok)
   280  		plugin := f()
   281  		ptestExpectConfigValue(t, plugin, ptestInitValue)
   282  	})
   283  
   284  	t.Run("config", func(t *testing.T) {
   285  		factory := newFactoryOK(ptestNewFactoryConf, ptestNewType(), confToGetMaybe(ptestDefaultConf()))
   286  		f, ok := factory.(func() ptestPlugin)
   287  		assert.True(t, ok)
   288  		plugin := f()
   289  		ptestExpectConfigValue(t, plugin, ptestDefaultValue)
   290  	})
   291  
   292  	t.Run("get config failed", func(t *testing.T) {
   293  		factory, err := newFactory(ptestNewFactoryConf, ptestNewErrType(), errToGetMaybe(ptestConfigurationFailedErr))
   294  		assert.Error(t, err, ptestConfigurationFailedErr)
   295  		assert.Nil(t, factory)
   296  	})
   297  
   298  	t.Run("factory create failed", func(t *testing.T) {
   299  		factory, err := newFactory(ptestNewFactoryErrFailing, ptestNewErrType(), nil)
   300  		assert.ErrorIs(t, err, ptestCreateFailedErr)
   301  		assert.Nil(t, factory)
   302  	})
   303  
   304  	t.Run("plugin create failed", func(t *testing.T) {
   305  		factory := newFactoryOK(ptestNewFactoryFactoryErrFailing, ptestNewErrType(), nil)
   306  		f, ok := factory.(func() (ptestPlugin, error))
   307  		assert.True(t, ok)
   308  		plugin, err := f()
   309  		assert.ErrorIs(t, err, ptestCreateFailedErr)
   310  		assert.Nil(t, plugin)
   311  	})
   312  
   313  	t.Run("panic on trim non nil err", func(t *testing.T) {
   314  		factory := newFactoryOK(ptestNewFactoryFactoryErrFailing, ptestNewType(), nil)
   315  		f, ok := factory.(func() ptestPlugin)
   316  		assert.True(t, ok)
   317  		func() {
   318  			defer func() {
   319  				r := recover()
   320  				assert.Equal(t, ptestCreateFailedErr, r)
   321  			}()
   322  			f()
   323  		}()
   324  	})
   325  
   326  }
   327  
   328  func confToMaybe(conf interface{}) []reflect.Value {
   329  	if conf != nil {
   330  		return []reflect.Value{reflect.ValueOf(conf)}
   331  	}
   332  	return nil
   333  }
   334  
   335  func confToGetMaybe(conf interface{}) func() ([]reflect.Value, error) {
   336  	return func() ([]reflect.Value, error) {
   337  		return confToMaybe(conf), nil
   338  	}
   339  }
   340  
   341  func errToGetMaybe(err error) func() ([]reflect.Value, error) {
   342  	return func() ([]reflect.Value, error) {
   343  		return nil, err
   344  	}
   345  }
   346  
   347  func expectSameFunc(t *testing.T, f1, f2 interface{}) {
   348  	s1 := fmt.Sprint(f1)
   349  	s2 := fmt.Sprint(f2)
   350  	assert.Equal(t, s1, s2)
   351  }