Skip to content

Commit 6b7fc3a

Browse files
committed
settings: fix panic in SetOnChange for max setting
1 parent e3b4544 commit 6b7fc3a

File tree

2 files changed

+62
-2
lines changed

2 files changed

+62
-2
lines changed

pkg/settings/setting.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ func (sv *Values) Opaque() interface{} {
8282

8383
func (sv *Values) settingChanged(slotIdx int) {
8484
sv.changeMu.Lock()
85-
funcs := sv.changeMu.onChange[slotIdx]
85+
funcs := sv.changeMu.onChange[slotIdx-1]
8686
sv.changeMu.Unlock()
8787
for _, fn := range funcs {
8888
fn()
@@ -113,7 +113,7 @@ func (sv *Values) setGeneric(slotIdx int, newVal interface{}) {
113113
// goroutine which handles all settings updates.
114114
func (sv *Values) setOnChange(slotIdx int, fn func()) {
115115
sv.changeMu.Lock()
116-
sv.changeMu.onChange[slotIdx] = append(sv.changeMu.onChange[slotIdx], fn)
116+
sv.changeMu.onChange[slotIdx-1] = append(sv.changeMu.onChange[slotIdx-1], fn)
117117
sv.changeMu.Unlock()
118118
}
119119

pkg/settings/settings_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import (
2323
"github.com/pkg/errors"
2424
)
2525

26+
const maxSettings = 128
27+
2628
type dummy struct {
2729
msg1 string
2830
growsbyone string
@@ -612,3 +614,61 @@ func TestHide(t *testing.T) {
612614
t.Errorf("expected 'sekretz' to be hidden")
613615
}
614616
}
617+
618+
func TestOnChangeWithMaxSettings(t *testing.T) {
619+
// Register maxSettings settings to ensure that no errors occur.
620+
maxName, err := batchRegisterSettings(t, t.Name(), maxSettings-1-len(settings.Keys()))
621+
if err != nil {
622+
t.Errorf("expected no error to register 128 settings, but get error : %s", err)
623+
}
624+
625+
// Change the max slotIdx setting to ensure that no errors occur.
626+
sv := &settings.Values{}
627+
sv.Init(settings.TestOpaque)
628+
var changes int
629+
intSetting, ok := settings.Lookup(maxName)
630+
if !ok {
631+
t.Errorf("expected lookup of %s to succeed", maxName)
632+
}
633+
intSetting.SetOnChange(sv, func() { changes++ })
634+
635+
u := settings.NewUpdater(sv)
636+
if err := u.Set(maxName, settings.EncodeInt(9), "i"); err != nil {
637+
t.Fatal(err)
638+
}
639+
640+
if changes != 1 {
641+
t.Errorf("expected the max slot setting changed")
642+
}
643+
}
644+
645+
func TestMaxSettingsPanics(t *testing.T) {
646+
// Register too many settings which will cause a panic which is caught and converted to an error.
647+
_, err := batchRegisterSettings(t, t.Name(), maxSettings-len(settings.Keys()))
648+
expectedErr := "too many settings; increase maxSettings"
649+
if err == nil || err.Error() != expectedErr {
650+
t.Errorf("expected error %v, but got %v", expectedErr, err)
651+
}
652+
}
653+
654+
func batchRegisterSettings(t *testing.T, keyPrefix string, count int) (name string, err error) {
655+
defer func() {
656+
// Catch panic and convert it to an error.
657+
if r := recover(); r != nil {
658+
// Check exactly what the panic was and create error.
659+
switch x := r.(type) {
660+
case string:
661+
err = errors.New(x)
662+
case error:
663+
err = x
664+
default:
665+
err = errors.Errorf("unknown panic: %v", x)
666+
}
667+
}
668+
}()
669+
for i := 0; i < count; i++ {
670+
name = fmt.Sprintf("%s_%3d", keyPrefix, i)
671+
settings.RegisterValidatedIntSetting(name, "desc", 0, nil)
672+
}
673+
return name, err
674+
}

0 commit comments

Comments
 (0)