refresh neither leaks wraps, allows 2 of the same at once, nor closes raws

master
bel 2023-03-25 10:50:39 -06:00
parent 97cc3ae151
commit ae1e32391c
18 changed files with 94 additions and 64 deletions

View File

@ -9,6 +9,7 @@ import (
type Parser interface { type Parser interface {
Read() []Button Read() []Button
Close() Close()
CloseWrap() raw.Raw
} }
func New(ctx context.Context, src raw.Raw) Parser { func New(ctx context.Context, src raw.Raw) Parser {

View File

@ -23,6 +23,8 @@ func NewPlaintext(src raw.Raw) Plaintext {
func (p Plaintext) Close() { p.src.Close() } func (p Plaintext) Close() { p.src.Close() }
func (p Plaintext) CloseWrap() raw.Raw { return p.src }
func (p Plaintext) Read() []Button { func (p Plaintext) Read() []Button {
b := p.src.Read() b := p.src.Read()
buttons := make([]Button, 0, len(b)) buttons := make([]Button, 0, len(b))

View File

@ -22,8 +22,6 @@ func TestPlaintext(t *testing.T) {
type constSrc string type constSrc string
func (c constSrc) Refresh() {}
func (c constSrc) Close() {} func (c constSrc) Close() {}
func (c constSrc) Read() []byte { func (c constSrc) Read() []byte {

View File

@ -52,6 +52,11 @@ func NewV01(ctx context.Context, src raw.Raw) V01 {
} }
} }
func (v01 V01) CloseWrap() raw.Raw {
v01.can()
return v01.src
}
func (v01 V01) Close() { func (v01 V01) Close() {
v01.can() v01.can()
v01.src.Close() v01.src.Close()

View File

@ -15,7 +15,6 @@ type Input interface {
func New(ctx context.Context) Input { func New(ctx context.Context) Input {
src := raw.New(ctx) src := raw.New(ctx)
return wrap.New(ctx, func() button.Parser { return wrap.New(ctx, func() button.Parser {
src.Refresh()
return button.New(ctx, src) return button.New(ctx, src)
}) })
} }

View File

@ -3,6 +3,7 @@ package input_test
import ( import (
"context" "context"
"mayhem-party/src/device/input" "mayhem-party/src/device/input"
"mayhem-party/src/device/input/wrap"
"os" "os"
"path" "path"
"testing" "testing"
@ -30,10 +31,10 @@ func TestNewRemapped(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
os.Setenv("WRAP_REMAP_FILE", remap) wrap.FlagRemapFile = remap
os.Setenv("RAW_RANDOM_WEIGHT_FILE", rand) os.Setenv("RAW_RANDOM_WEIGHT_FILE", rand)
t.Cleanup(func() { t.Cleanup(func() {
os.Unsetenv("WRAP_REMAP_FILE") wrap.FlagRemapFile = ""
os.Unsetenv("RAW_RANDOM_WEIGHT_FILE") os.Unsetenv("RAW_RANDOM_WEIGHT_FILE")
}) })
@ -50,9 +51,9 @@ func TestNewRemapped(t *testing.T) {
} }
func TestNewBuffered(t *testing.T) { func TestNewBuffered(t *testing.T) {
os.Setenv("WRAP_BUFFERED", "true") wrap.FlagBuffered = true
t.Cleanup(func() { t.Cleanup(func() {
os.Unsetenv("WRAP_BUFFERED") wrap.FlagBuffered = false
}) })
r := input.New(context.Background()) r := input.New(context.Background())

View File

@ -31,9 +31,6 @@ func NewKeyboard() Keyboard {
return Keyboard{} return Keyboard{}
} }
func (kb Keyboard) Refresh() {
}
func (kb Keyboard) Close() { func (kb Keyboard) Close() {
switch runtime.GOOS { switch runtime.GOOS {
case "linux": case "linux":

View File

@ -22,9 +22,6 @@ func NewRandom(generator func() byte) *Random {
return &Random{generator: generator} return &Random{generator: generator}
} }
func (r *Random) Refresh() {
}
func (r *Random) Close() { func (r *Random) Close() {
} }

View File

@ -9,7 +9,6 @@ import (
type Raw interface { type Raw interface {
Read() []byte Read() []byte
Close() Close()
Refresh()
} }
func New(ctx context.Context) Raw { func New(ctx context.Context) Raw {

View File

@ -55,9 +55,6 @@ func (udp UDP) Read() []byte {
} }
} }
func (udp UDP) Refresh() {
}
func (udp UDP) Close() { func (udp UDP) Close() {
udp.conn.Close() udp.conn.Close()
} }

View File

@ -3,6 +3,7 @@ package wrap
import ( import (
"context" "context"
"mayhem-party/src/device/input/button" "mayhem-party/src/device/input/button"
"mayhem-party/src/device/input/raw"
"os" "os"
"sync" "sync"
"time" "time"
@ -57,6 +58,11 @@ func (b *Buffered) listen() {
} }
} }
func (b *Buffered) CloseWrap() raw.Raw {
b.can()
return b.input.CloseWrap()
}
func (b *Buffered) Close() { func (b *Buffered) Close() {
b.input.Close() b.input.Close()
b.can() b.can()

View File

@ -1,24 +0,0 @@
package wrap
import (
"mayhem-party/src/device/input/button"
"mayhem-party/src/device/input/raw"
)
type Protocol struct {
src raw.Raw
}
func NewProtocol(src raw.Raw) Protocol {
return Protocol{
src: src,
}
}
func (p Protocol) Close() {
p.src.Close()
}
func (p Protocol) Read() []button.Button {
panic(nil)
}

View File

@ -4,13 +4,14 @@ import (
"context" "context"
"log" "log"
"mayhem-party/src/device/input/button" "mayhem-party/src/device/input/button"
"mayhem-party/src/device/input/raw"
"os" "os"
"os/signal" "os/signal"
"syscall" "syscall"
) )
var ( var (
ChanSigUsr1 = func() chan os.Signal { chSigUsr1 = func() chan os.Signal {
c := make(chan os.Signal, 1) c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGUSR1) signal.Notify(c, syscall.SIGUSR1)
return c return c
@ -22,12 +23,12 @@ type Refresh struct {
input Wrap input Wrap
} }
func NewRefresh(newWrap func() Wrap) *Refresh { func NewRefresh(ctx context.Context, newWrap func() Wrap) *Refresh {
return NewRefreshWith(newWrap, ChanSigUsr1) return NewRefreshWith(ctx, newWrap, chSigUsr1)
} }
func NewRefreshWith(newWrap func() Wrap, ch <-chan os.Signal) *Refresh { func NewRefreshWith(ctx context.Context, newWrap func() Wrap, ch <-chan os.Signal) *Refresh {
ctx, can := context.WithCancel(context.Background()) ctx, can := context.WithCancel(ctx)
result := &Refresh{ result := &Refresh{
can: can, can: can,
input: newWrap(), input: newWrap(),
@ -40,16 +41,19 @@ func NewRefreshWith(newWrap func() Wrap, ch <-chan os.Signal) *Refresh {
return return
case sig := <-ch: case sig := <-ch:
log.Println("refreshing for", sig) log.Println("refreshing for", sig)
newInput := newWrap() result.input.CloseWrap()
oldInput := result.input result.input = newWrap()
result.input = newInput
oldInput.Close()
} }
} }
}() }()
return result return result
} }
func (r *Refresh) CloseWrap() raw.Raw {
r.can()
return r.input.CloseWrap()
}
func (r *Refresh) Read() []button.Button { func (r *Refresh) Read() []button.Button {
return r.input.Read() return r.input.Read()
} }

View File

@ -1,6 +1,8 @@
package wrap package wrap
import ( import (
"context"
"mayhem-party/src/device/input/button"
"os" "os"
"syscall" "syscall"
"testing" "testing"
@ -15,7 +17,7 @@ func TestRefresh(t *testing.T) {
} }
ch := make(chan os.Signal, 1) ch := make(chan os.Signal, 1)
defer close(ch) defer close(ch)
refresh := NewRefreshWith(generator, ch) refresh := NewRefreshWith(context.Background(), generator, ch)
defer refresh.Close() defer refresh.Close()
assertIts := func(t *testing.T, b byte) { assertIts := func(t *testing.T, b byte) {
@ -42,3 +44,51 @@ func TestRefresh(t *testing.T) {
assertIts(t, byte('c')) assertIts(t, byte('c'))
}) })
} }
func TestRefreshDoesntCloseSources(t *testing.T) {
src := &telemetrySrc{}
newParsers := 0
newParser := func() Wrap {
newParsers += 1
return button.NewPlaintext(src)
}
ctx, can := context.WithCancel(context.Background())
defer can()
refresh := NewRefresh(ctx, newParser)
if newParsers != 1 {
t.Error(newParsers)
}
for i := 0; i < 5; i++ {
refresh.Read()
}
if want := (telemetrySrc{reads: 5}); *src != want {
t.Errorf("%+v", *src)
} else if newParsers != 1 {
t.Error(newParsers)
}
for i := 0; i < 5; i++ {
chSigUsr1 <- syscall.SIGINT
}
time.Sleep(time.Millisecond * 250)
if want := (telemetrySrc{reads: 5}); *src != want {
t.Errorf("want %+v, got %+v", want, *src)
} else if newParsers != 6 {
t.Error(newParsers)
}
}
type telemetrySrc struct {
closes int
reads int
}
func (src *telemetrySrc) Close() {
src.closes += 1
}
func (src *telemetrySrc) Read() []byte {
src.reads += 1
return []byte("foo")
}

View File

@ -2,6 +2,7 @@ package wrap
import ( import (
"mayhem-party/src/device/input/button" "mayhem-party/src/device/input/button"
"mayhem-party/src/device/input/raw"
"os" "os"
"github.com/go-yaml/yaml" "github.com/go-yaml/yaml"
@ -38,6 +39,10 @@ func NewRemap(input Wrap, m map[byte]byte) Remap {
} }
} }
func (re Remap) CloseWrap() raw.Raw {
return re.input.CloseWrap()
}
func (re Remap) Close() { func (re Remap) Close() {
re.input.Close() re.input.Close()
} }

View File

@ -3,6 +3,7 @@ package wrap
import ( import (
"context" "context"
"mayhem-party/src/device/input/button" "mayhem-party/src/device/input/button"
"mayhem-party/src/device/input/raw"
"os" "os"
) )
@ -15,6 +16,7 @@ var (
type Wrap interface { type Wrap interface {
Read() []button.Button Read() []button.Button
Close() Close()
CloseWrap() raw.Raw
} }
func New(ctx context.Context, srcFunc func() button.Parser) Wrap { func New(ctx context.Context, srcFunc func() button.Parser) Wrap {
@ -36,7 +38,7 @@ func New(ctx context.Context, srcFunc func() button.Parser) Wrap {
if FlagRefreshOnSigUsr1 { if FlagRefreshOnSigUsr1 {
oldMaker := maker oldMaker := maker
maker = func() Wrap { maker = func() Wrap {
return NewRefresh(oldMaker) return NewRefresh(ctx, oldMaker)
} }
} }
return maker() return maker()

View File

@ -1,10 +0,0 @@
package wrap_test
import (
"mayhem-party/src/device/input/wrap"
"testing"
)
func TestNewRefreshing(t *testing.T) {
wrap.FlagBuffered = true
}

View File

@ -2,6 +2,7 @@ package wrap
import ( import (
"mayhem-party/src/device/input/button" "mayhem-party/src/device/input/button"
"mayhem-party/src/device/input/raw"
"testing" "testing"
) )
@ -10,12 +11,12 @@ func TestWrap(t *testing.T) {
var _ Wrap = &Refresh{} var _ Wrap = &Refresh{}
var _ Wrap = &Buffered{} var _ Wrap = &Buffered{}
var _ Wrap = &Remap{} var _ Wrap = &Remap{}
var _ Wrap = Protocol{}
} }
type dummyParser button.Button type dummyParser button.Button
func (d dummyParser) Close() {} func (d dummyParser) CloseWrap() raw.Raw { return nil }
func (d dummyParser) Close() {}
func (d dummyParser) Read() []button.Button { func (d dummyParser) Read() []button.Button {
return []button.Button{button.Button(d)} return []button.Button{button.Button(d)}
} }