diff --git a/Makefile b/Makefile index 68dd432..037e311 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,10 @@ dbuild: docker build -t gor . dtest: - docker run -v `pwd`:/gopath/src/gor -t -i --env GORACE="halt_on_error=1" gor go test -race -v + docker run -v `pwd`:/gopath/src/gor -t -i --env GORACE="halt_on_error=1" gor go test $(ARGS) -race -v + +dfmt: + docker run -v `pwd`:/gopath/src/gor -t -i gor go fmt dbench: docker run -v `pwd`:/gopath/src/gor -t -i gor go test -v -run NOT_EXISTING -bench HTTP diff --git a/plugins.go b/plugins.go index ed21d42..abc8ea8 100644 --- a/plugins.go +++ b/plugins.go @@ -2,6 +2,7 @@ package main import ( "io" + "reflect" ) type InOutPlugins struct { @@ -9,42 +10,67 @@ type InOutPlugins struct { Outputs []io.Writer } +type ReaderOrWriter interface{} + var Plugins *InOutPlugins = new(InOutPlugins) +// Automatically detects type of plugin and initialize it +// +// See this article if curious about relfect stuff below: http://blog.burntsushi.net/type-parametric-functions-golang +func registerPlugin(constructor interface{}, options ...interface{}) { + vc := reflect.ValueOf(constructor) + + vo := []reflect.Value{} + for _, i := range options { + vo = append(vo, reflect.ValueOf(i)) + } + + // Here we calling our constructor with list of passed options + plugin := vc.Call(vo)[0].Interface() + + if p, ok := plugin.(io.Reader); ok { + Plugins.Inputs = append(Plugins.Inputs, p) + } + + if p, ok := plugin.(io.Writer); ok { + Plugins.Outputs = append(Plugins.Outputs, p) + } +} + func InitPlugins() { for _, options := range Settings.inputDummy { - Plugins.Inputs = append(Plugins.Inputs, NewDummyInput(options)) + registerPlugin(NewDummyInput, options) } for _, options := range Settings.outputDummy { - Plugins.Outputs = append(Plugins.Outputs, NewDummyOutput(options)) + registerPlugin(NewDummyOutput, options) } for _, options := range Settings.inputRAW { - Plugins.Inputs = append(Plugins.Inputs, NewRAWInput(options)) + registerPlugin(NewRAWInput, options) } for _, options := range Settings.inputTCP { - Plugins.Inputs = append(Plugins.Inputs, NewTCPInput(options)) + registerPlugin(NewTCPInput, options) } for _, options := range Settings.outputTCP { - Plugins.Outputs = append(Plugins.Outputs, NewTCPOutput(options)) + registerPlugin(NewTCPOutput, options) } for _, options := range Settings.inputFile { - Plugins.Inputs = append(Plugins.Inputs, NewFileInput(options)) + registerPlugin(NewFileInput, options) } for _, options := range Settings.outputFile { - Plugins.Outputs = append(Plugins.Outputs, NewFileOutput(options)) + registerPlugin(NewFileOutput, options) } for _, options := range Settings.inputHTTP { - Plugins.Inputs = append(Plugins.Inputs, NewHTTPInput(options)) + registerPlugin(NewHTTPInput, options) } for _, options := range Settings.outputHTTP { - Plugins.Outputs = append(Plugins.Outputs, NewHTTPOutput(options, Settings.outputHTTPHeaders, Settings.outputHTTPMethods, Settings.outputHTTPUrlRegexp, Settings.outputHTTPHeaderFilters, Settings.outputHTTPHeaderHashFilters, Settings.outputHTTPElasticSearch, Settings.outputHTTPUrlRewrite)) + registerPlugin(NewHTTPOutput, options, Settings.outputHTTPHeaders, Settings.outputHTTPMethods, Settings.outputHTTPUrlRegexp, Settings.outputHTTPHeaderFilters, Settings.outputHTTPHeaderHashFilters, Settings.outputHTTPElasticSearch, Settings.outputHTTPUrlRewrite) } } diff --git a/plugins_test.go b/plugins_test.go new file mode 100644 index 0000000..9ddfb3a --- /dev/null +++ b/plugins_test.go @@ -0,0 +1,37 @@ +package main + +import ( + "io" + "testing" +) + +func TestPluginsRegistration(t *testing.T) { + Plugins.Inputs = []io.Reader{} + Plugins.Outputs = []io.Writer{} + + Settings.inputDummy = MultiOption{"[]"} + Settings.outputDummy = MultiOption{"[]"} + Settings.inputFile = MultiOption{"/dev/null"} + + InitPlugins() + + if len(Plugins.Inputs) != 2 { + t.Errorf("Should be 2 inputs") + } + + if _, ok := Plugins.Inputs[0].(*DummyInput); !ok { + t.Errorf("First input should be DummyInput") + } + + if _, ok := Plugins.Inputs[1].(*FileInput); !ok { + t.Errorf("Second input should be FileInput") + } + + if len(Plugins.Outputs) != 1 { + t.Errorf("Should be 1 output") + } + + if _, ok := Plugins.Outputs[0].(*DummyOutput); !ok { + t.Errorf("Output should be DummyOutput") + } +}