package cli import ( "bytes" "fmt" "io" "sync" ) // NewMockUi returns a fully initialized MockUi instance // which is safe for concurrent use. func NewMockUi() *MockUi { m := new(MockUi) m.once.Do(m.init) return m } // MockUi is a mock UI that is used for tests and is exported publicly // for use in external tests if needed as well. Do not instantite this // directly since the buffers will be initialized on the first write. If // there is no write then you will get a nil panic. Please use the // NewMockUi() constructor function instead. You can fix your code with // // sed -i -e 's/new(cli.MockUi)/cli.NewMockUi()/g' *_test.go type MockUi struct { InputReader io.Reader ErrorWriter *syncBuffer OutputWriter *syncBuffer once sync.Once } func (u *MockUi) Ask(query string) (string, error) { u.once.Do(u.init) var result string fmt.Fprint(u.OutputWriter, query) if _, err := fmt.Fscanln(u.InputReader, &result); err != nil { return "", err } return result, nil } func (u *MockUi) AskSecret(query string) (string, error) { return u.Ask(query) } func (u *MockUi) Error(message string) { u.once.Do(u.init) fmt.Fprint(u.ErrorWriter, message) fmt.Fprint(u.ErrorWriter, "\n") } func (u *MockUi) Info(message string) { u.Output(message) } func (u *MockUi) Output(message string) { u.once.Do(u.init) fmt.Fprint(u.OutputWriter, message) fmt.Fprint(u.OutputWriter, "\n") } func (u *MockUi) Warn(message string) { u.once.Do(u.init) fmt.Fprint(u.ErrorWriter, message) fmt.Fprint(u.ErrorWriter, "\n") } func (u *MockUi) init() { u.ErrorWriter = new(syncBuffer) u.OutputWriter = new(syncBuffer) } type syncBuffer struct { sync.RWMutex b bytes.Buffer } func (b *syncBuffer) Write(data []byte) (int, error) { b.Lock() defer b.Unlock() return b.b.Write(data) } func (b *syncBuffer) Read(data []byte) (int, error) { b.RLock() defer b.RUnlock() return b.b.Read(data) } func (b *syncBuffer) Reset() { b.Lock() b.b.Reset() b.Unlock() } func (b *syncBuffer) String() string { return string(b.Bytes()) } func (b *syncBuffer) Bytes() []byte { b.RLock() data := b.b.Bytes() b.RUnlock() return data }