Eventer, tests, gitlab CI, etc.
This commit is contained in:
10
eventer/errors.go
Normal file
10
eventer/errors.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package eventer
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
EventNotFoundError = errors.New("event not found")
|
||||
)
|
125
eventer/eventer_test.go
Normal file
125
eventer/eventer_test.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package eventer
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"testing"
|
||||
|
||||
// other
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestEventerInitializationAndShutdown(t *testing.T) {
|
||||
Initialize()
|
||||
require.NotNil(t, events)
|
||||
|
||||
Shutdown()
|
||||
require.Nil(t, events)
|
||||
require.False(t, eventsInitialized)
|
||||
}
|
||||
|
||||
func TestEventerAddEventHandler(t *testing.T) {
|
||||
Initialize()
|
||||
require.NotNil(t, events)
|
||||
|
||||
handler := &EventHandler{
|
||||
Command: "TEST",
|
||||
Handler: func(data interface{}) interface{} {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
AddEventHandler(handler)
|
||||
|
||||
hndl, exists := events[handler.Command]
|
||||
require.Len(t, events, 1)
|
||||
require.True(t, exists)
|
||||
require.Equal(t, handler, hndl)
|
||||
|
||||
Shutdown()
|
||||
require.Nil(t, events)
|
||||
require.False(t, eventsInitialized)
|
||||
}
|
||||
|
||||
func TestEventerAddEventHandlerAfterInitializationCompleted(t *testing.T) {
|
||||
Initialize()
|
||||
require.NotNil(t, events)
|
||||
InitializeCompleted()
|
||||
|
||||
handler := &EventHandler{
|
||||
Command: "TEST",
|
||||
Handler: func(data interface{}) interface{} {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
AddEventHandler(handler)
|
||||
|
||||
hndl, exists := events[handler.Command]
|
||||
require.Len(t, events, 0)
|
||||
require.False(t, exists)
|
||||
require.Nil(t, hndl)
|
||||
|
||||
Shutdown()
|
||||
require.Nil(t, events)
|
||||
require.False(t, eventsInitialized)
|
||||
}
|
||||
|
||||
func TestEventerLaunchExistingEvent(t *testing.T) {
|
||||
Initialize()
|
||||
require.NotNil(t, events)
|
||||
|
||||
handler := &EventHandler{
|
||||
Command: "TEST",
|
||||
Handler: func(data interface{}) interface{} {
|
||||
return true
|
||||
},
|
||||
}
|
||||
AddEventHandler(handler)
|
||||
|
||||
hndl, exists := events[handler.Command]
|
||||
require.Len(t, events, 1)
|
||||
require.True(t, exists)
|
||||
require.Equal(t, handler, hndl)
|
||||
|
||||
data, err := LaunchEvent(handler.Command, nil)
|
||||
if err != nil {
|
||||
t.Fatal("Test event launch failed:", err.Error())
|
||||
}
|
||||
|
||||
switch data.(type) {
|
||||
case bool:
|
||||
break
|
||||
default:
|
||||
t.Fatalf("Test event returned unacceptable data type: %T", data)
|
||||
}
|
||||
|
||||
Shutdown()
|
||||
require.Nil(t, events)
|
||||
require.False(t, eventsInitialized)
|
||||
}
|
||||
|
||||
func TestEventerLaunchNotExistingEvent(t *testing.T) {
|
||||
Initialize()
|
||||
require.NotNil(t, events)
|
||||
|
||||
handler := &EventHandler{
|
||||
Command: "TEST",
|
||||
Handler: func(data interface{}) interface{} {
|
||||
return true
|
||||
},
|
||||
}
|
||||
AddEventHandler(handler)
|
||||
|
||||
hndl, exists := events[handler.Command]
|
||||
require.Len(t, events, 1)
|
||||
require.True(t, exists)
|
||||
require.Equal(t, handler, hndl)
|
||||
|
||||
data, err := LaunchEvent(handler.Command+"notexisting", nil)
|
||||
if err == nil {
|
||||
t.Fatal("LaunchEvent() returned empty error!")
|
||||
}
|
||||
require.Nil(t, data)
|
||||
|
||||
Shutdown()
|
||||
require.Nil(t, events)
|
||||
require.False(t, eventsInitialized)
|
||||
}
|
64
eventer/exported.go
Normal file
64
eventer/exported.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package eventer
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"log"
|
||||
)
|
||||
|
||||
var (
|
||||
// List of known event handler.
|
||||
// Format:
|
||||
// - commands/CMDNAME - base handler for command. This what
|
||||
// networker will execute on any new command. Case-insensitive.
|
||||
// - internals/CMDNAME - all other internal things like database
|
||||
// access.
|
||||
// This map will not be changed after gonewsd initialization is
|
||||
// complete.
|
||||
events map[string]*EventHandler
|
||||
// Flag that indicates that we have completed events mapping
|
||||
// initialization.
|
||||
// RWMutex can be here, but we also need to write to log if we have
|
||||
// completed initialization.
|
||||
eventsInitialized bool
|
||||
)
|
||||
|
||||
// Initialize initializes package.
|
||||
func Initialize() {
|
||||
log.Println("Initializing event handler...")
|
||||
|
||||
events = make(map[string]*EventHandler)
|
||||
}
|
||||
|
||||
// InitializeCompleted sets eventsInitialized bool to true to avoid
|
||||
// all further events mapping changes.
|
||||
func InitializeCompleted() {
|
||||
eventsInitialized = true
|
||||
log.Println("Events initialization completed")
|
||||
}
|
||||
|
||||
// AddEventHandler adds event handler to a list of known handlers.
|
||||
func AddEventHandler(event *EventHandler) {
|
||||
if !eventsInitialized {
|
||||
events[event.Command] = event
|
||||
} else {
|
||||
log.Println("Can't add event '" + event.Command + "' to a list of known events - events mapping initialization already completed, no more changes allowed.")
|
||||
}
|
||||
}
|
||||
|
||||
// LaunchEvent launches desired event in synchronous manner.
|
||||
func LaunchEvent(eventName string, data interface{}) (interface{}, error) {
|
||||
handler, exists := events[eventName]
|
||||
if !exists {
|
||||
return nil, EventNotFoundError
|
||||
}
|
||||
|
||||
returnedData := handler.Handler(data)
|
||||
return returnedData, nil
|
||||
}
|
||||
|
||||
// Shutdown just nullifies eventer map.
|
||||
// Useful for testing and, maybe, reload.
|
||||
func Shutdown() {
|
||||
events = nil
|
||||
eventsInitialized = false
|
||||
}
|
10
eventer/handler.go
Normal file
10
eventer/handler.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package eventer
|
||||
|
||||
// EventHandler represents generic event handler.
|
||||
type EventHandler struct {
|
||||
// Command is a command name we will use for event registering,
|
||||
// showing help, etc.
|
||||
Command string
|
||||
// Handler if a function that will handle this command.
|
||||
Handler func(data interface{}) interface{}
|
||||
}
|
Reference in New Issue
Block a user