From e478250f499385a0299d5182dd40f640aaa1270a Mon Sep 17 00:00:00 2001 From: Volker Schukai <volker.schukai@schukai.com> Date: Mon, 17 Oct 2022 15:54:44 +0200 Subject: [PATCH] feat add HasOnChangeHook and RemoveOnChangeHook --- README.md | 19 +++++++++-- change.go | 28 ++++++++++++++-- change_test.go | 77 +++++++++++++++++++++++++++++++++++++------- http-handler_test.go | 14 +++++--- watch_test.go | 15 ++++++--- 5 files changed, 128 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index f794823..4333b47 100644 --- a/README.md +++ b/README.md @@ -303,6 +303,14 @@ import ( "gitlab.schukai.com/oss/libraries/go/application/configuration" ) +type ChangeEventHandler struct { + callback func(event configuration.ChangeEvent) +} + +func (c *ChangeEventHandler) Handle(event configuration.ChangeEvent) { + c.callback(event) +} + func main() { config := struct { Host string @@ -314,12 +322,17 @@ func main() { closeChan := make(chan bool) - s.OnChange(func(event configuration.ChangeEvent) { + var h configuration.EventHook + h = &ChangeEventHandler{ + callback: func(event configuration.ChangeEvent) { log := event.Changlog - msg := fmt.Sprintf("Change from %s to %s", log[0].From, log[0].To) + msg = fmt.Sprintf("Change from %s to %s", log[0].From, log[0].To) fmt.Println(msg) closeChan <- true - }) + }, + } + + s.OnChange(h) c := s.Config() c.Host = "www.example.com" diff --git a/change.go b/change.go index 18c63d9..f513670 100644 --- a/change.go +++ b/change.go @@ -11,16 +11,40 @@ type ChangeEvent struct { Changlog diff.Changelog } -type EventHook func(event ChangeEvent) +type EventHook interface { + Handle(event ChangeEvent) +} +// OnChange registers a hook that is called when the configuration changes. func (s *Settings[C]) OnChange(hook EventHook) *Settings[C] { s.hooks.change = append(s.hooks.change, hook) return s } +// HasOnChangeHook returns true if there are registered hooks. +func (s *Settings[C]) HasOnChangeHook(hook EventHook) *Settings[C] { + for _, h := range s.hooks.change { + if h == hook { + break + } + } + return s +} + +// RemoveOnChangeHook removes a change hook from the list of hooks. +func (s *Settings[C]) RemoveOnChangeHook(hook EventHook) *Settings[C] { + for i, h := range s.hooks.change { + if h == hook { + s.hooks.change = append(s.hooks.change[:i], s.hooks.change[i+1:]...) + break + } + } + return s +} + func (s *Settings[C]) notifyChangeHooks(changelog diff.Changelog) *Settings[C] { for _, h := range s.hooks.change { - h(ChangeEvent{Changlog: changelog}) + h.Handle(ChangeEvent{Changlog: changelog}) } return s } diff --git a/change_test.go b/change_test.go index 2b8d8ad..7414a81 100644 --- a/change_test.go +++ b/change_test.go @@ -11,6 +11,49 @@ import ( "time" ) +type mockTestEventHandler struct { + EventHook +} + +func (m *mockTestEventHandler) Handle(event ChangeEvent) { + // do nothing + +} + +func TestAddRemoveHook(t *testing.T) { + + config := struct { + Host string + }{ + Host: "localhost", + } + + s := New(config) + + var h EventHook + h = &mockTestEventHandler{} + s.OnChange(h) + + if len(s.hooks.change) != 1 { + t.Error("Expected 1 got ", len(s.hooks.change)) + } + + s.RemoveOnChangeHook(h) + + if len(s.hooks.change) != 0 { + t.Error("Expected 0 got ", len(s.hooks.change)) + } + +} + +type ChangeEventTester struct { + callback func(event ChangeEvent) +} + +func (c *ChangeEventTester) Handle(event ChangeEvent) { + c.callback(event) +} + func TestReadmeExample(t *testing.T) { config := struct { @@ -24,13 +67,19 @@ func TestReadmeExample(t *testing.T) { closeChan := make(chan bool) msg := "" - s.OnChange(func(event ChangeEvent) { - log := event.Changlog - msg = fmt.Sprintf("Change from %s to %s", log[0].From, log[0].To) - // for Readme - //fmt.Println(msg) - closeChan <- true - }) + + var h EventHook + h = &ChangeEventTester{ + callback: func(event ChangeEvent) { + log := event.Changlog + msg = fmt.Sprintf("Change from %s to %s", log[0].From, log[0].To) + // for Readme + //fmt.Println(msg) + closeChan <- true + }, + } + + s.OnChange(h) c := s.Config() c.Host = "www.example.com" @@ -84,10 +133,16 @@ func TestCangeOnChange(t *testing.T) { closeChan := make(chan bool) counter := 0 - s.OnChange(func(event ChangeEvent) { - counter++ - closeChan <- true - }) + + var h EventHook + h = &ChangeEventTester{ + callback: func(event ChangeEvent) { + counter++ + closeChan <- true + }, + } + + s.OnChange(h) c.A = "b" s.SetConfig(c) diff --git a/http-handler_test.go b/http-handler_test.go index 1955070..7f1cdb5 100644 --- a/http-handler_test.go +++ b/http-handler_test.go @@ -271,10 +271,16 @@ func TestConfigurationServePostJson(t *testing.T) { closeChan := make(chan bool) counter := 0 - s.OnChange(func(event ChangeEvent) { - counter++ - closeChan <- true - }) + + var h EventHook + h = &ChangeEventTester{ + callback: func(event ChangeEvent) { + counter++ + closeChan <- true + }, + } + + s.OnChange(h) // We create a ResponseRecorder (which satisfies http.ResponseWriter) to record the response. rr := httptest.NewRecorder() diff --git a/watch_test.go b/watch_test.go index b310b9e..aafb522 100644 --- a/watch_test.go +++ b/watch_test.go @@ -35,11 +35,16 @@ func TestWatch(t *testing.T) { signal := make(chan bool) - c.OnChange(func(event ChangeEvent) { - assert.Equal(t, event.Changlog[0].From, "localhost") - assert.Equal(t, event.Changlog[0].To, "example.org") - signal <- true - }) + var h EventHook + h = &ChangeEventTester{ + callback: func(event ChangeEvent) { + assert.Equal(t, event.Changlog[0].From, "localhost") + assert.Equal(t, event.Changlog[0].To, "example.org") + signal <- true + }, + } + + c.OnChange(h) c.Watch() -- GitLab