etcd/pkg/wait/wait.go
Anthony Romano 384cc76299 pkg/testutil: make Recorder an interface
Provides two implementations of Recorder-- one that is non-blocking
like the original version and one that provides a blocking channel
to avoid busy waiting or racing in tests when no other synchronization
is available.
2016-01-05 09:39:18 -08:00

96 lines
2.1 KiB
Go

// Copyright 2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package wait provides utility functions for polling, listening using Go
// channel.
package wait
import (
"sync"
"github.com/coreos/etcd/pkg/testutil"
)
type Wait interface {
Register(id uint64) <-chan interface{}
Trigger(id uint64, x interface{})
}
type List struct {
l sync.Mutex
m map[uint64]chan interface{}
}
func New() *List {
return &List{m: make(map[uint64]chan interface{})}
}
func (w *List) Register(id uint64) <-chan interface{} {
w.l.Lock()
defer w.l.Unlock()
ch := w.m[id]
if ch == nil {
ch = make(chan interface{}, 1)
w.m[id] = ch
}
return ch
}
func (w *List) Trigger(id uint64, x interface{}) {
w.l.Lock()
ch := w.m[id]
delete(w.m, id)
w.l.Unlock()
if ch != nil {
ch <- x
close(ch)
}
}
type WaitRecorder struct {
Wait
testutil.Recorder
}
type waitRecorder struct {
testutil.RecorderBuffered
}
func NewRecorder() *WaitRecorder {
wr := &waitRecorder{}
return &WaitRecorder{Wait: wr, Recorder: wr}
}
func NewNop() Wait { return NewRecorder() }
func (w *waitRecorder) Register(id uint64) <-chan interface{} {
w.Record(testutil.Action{Name: "Register"})
return nil
}
func (w *waitRecorder) Trigger(id uint64, x interface{}) {
w.Record(testutil.Action{Name: "Trigger"})
}
type waitWithResponse struct {
ch <-chan interface{}
}
func NewWithResponse(ch <-chan interface{}) Wait {
return &waitWithResponse{ch: ch}
}
func (w *waitWithResponse) Register(id uint64) <-chan interface{} {
return w.ch
}
func (w *waitWithResponse) Trigger(id uint64, x interface{}) {}