package hotkeys import ( "fmt" "path/filepath" "sync" "testing" ) func TestSetBindingFileConcurrentUpdatesPreserveEveryBinding(t *testing.T) { path := filepath.Join(t.TempDir(), "input.conf") const updates = 24 start := make(chan struct{}) errs := make(chan error, updates) var wg sync.WaitGroup for i := 1; i <= updates; i++ { wg.Add(1) go func(i int) { defer wg.Done() <-start key := fmt.Sprintf("F%d", i) if _, err := SetBindingFile(path, key, fmt.Sprintf("seek %d", i), "", false); err != nil { errs <- err } }(i) } close(start) wg.Wait() close(errs) for err := range errs { t.Fatal(err) } conf, err := ReadInputConf(path) if err != nil { t.Fatal(err) } for i := 1; i <= updates; i++ { key := fmt.Sprintf("F%d", i) binding := FindBinding(conf, key) if binding == nil { t.Errorf("binding %s was lost", key) continue } if want := fmt.Sprintf("seek %d", i); binding.Command != want { t.Errorf("binding %s = %q, want %q", key, binding.Command, want) } } } func TestSetBindingFileConflictDoesNotOverwrite(t *testing.T) { path := filepath.Join(t.TempDir(), "input.conf") if _, err := SetBindingFile(path, "SPACE", "cycle pause", "", false); err != nil { t.Fatal(err) } existing, err := SetBindingFile(path, "SPACE", "cycle mute", "", false) if err != ErrBindingConflict { t.Fatalf("SetBindingFile conflict error = %v, want %v", err, ErrBindingConflict) } if existing == nil || existing.Command != "cycle pause" { t.Fatalf("existing binding = %#v, want cycle pause", existing) } conf, err := ReadInputConf(path) if err != nil { t.Fatal(err) } if got := FindBinding(conf, "SPACE"); got == nil || got.Command != "cycle pause" { t.Fatalf("conflict changed binding: %#v", got) } }