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 }