From e491cc5cbcfbcb184f9c9bedf360662bc1f8ac57 Mon Sep 17 00:00:00 2001 From: Bel LaPointe Date: Fri, 24 Mar 2023 11:46:55 -0600 Subject: [PATCH] refresher input --- src/device/input/input_test.go | 1 + src/device/input/refresh.go | 46 ++++++++++++++++++++++++++++++++ src/device/input/refresh_test.go | 44 ++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 src/device/input/refresh.go create mode 100644 src/device/input/refresh_test.go diff --git a/src/device/input/input_test.go b/src/device/input/input_test.go index 484c464..eff0e2f 100644 --- a/src/device/input/input_test.go +++ b/src/device/input/input_test.go @@ -7,4 +7,5 @@ func TestInput(t *testing.T) { var _ Input = Keyboard{} var _ Input = &Buffered{} var _ Input = Remap{} + var _ Input = &Refresh{} } diff --git a/src/device/input/refresh.go b/src/device/input/refresh.go new file mode 100644 index 0000000..cb28eeb --- /dev/null +++ b/src/device/input/refresh.go @@ -0,0 +1,46 @@ +package input + +import ( + "context" + "log" + "os" + "os/signal" +) + +type Refresh struct { + can context.CancelFunc + input Input +} + +func NewRefreshCh(sig os.Signal) <-chan os.Signal { + c := make(chan os.Signal, 1) + signal.Notify(c, sig) + return c +} + +func NewRefresh(newInput func() Input, ch <-chan os.Signal) *Refresh { + ctx, can := context.WithCancel(context.Background()) + result := &Refresh{ + can: can, + input: newInput(), + } + go func() { + select { + case <-ctx.Done(): + return + case sig := <-ch: + log.Println("refreshing for", sig) + result.input = newInput() + } + }() + return result +} + +func (r *Refresh) Read() []Button { + return r.input.Read() +} + +func (r *Refresh) Close() { + r.can() + r.input.Close() +} diff --git a/src/device/input/refresh_test.go b/src/device/input/refresh_test.go new file mode 100644 index 0000000..57f7558 --- /dev/null +++ b/src/device/input/refresh_test.go @@ -0,0 +1,44 @@ +package input + +import ( + "os" + "syscall" + "testing" + "time" +) + +func TestRefresh(t *testing.T) { + b := byte('a') + generator := func() Input { + b += byte(1) + return NewRandom(func() byte { return b }) + } + ch := make(chan os.Signal, 1) + defer close(ch) + refresh := NewRefresh(generator, ch) + defer refresh.Close() + + assertIts := func(t *testing.T, b byte) { + for i := 0; i < 10; i++ { + some := false + for j, button := range refresh.Read() { + some = true + if button.Char != b { + t.Error(i, j, b, button) + } + } + if !some { + t.Error("empty read") + } + } + } + + t.Run("called once on init", func(t *testing.T) { + assertIts(t, byte('b')) + }) + ch <- syscall.SIGUSR1 + time.Sleep(time.Millisecond * 450) + t.Run("called once on signal", func(t *testing.T) { + assertIts(t, byte('c')) + }) +}