github.com/braveheart12/just@v0.8.7/testutils/recorder.go (about) 1 /* 2 * Copyright 2019 Insolar Technologies 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package testutils 18 19 import ( 20 "bufio" 21 "fmt" 22 "io" 23 "strings" 24 "sync" 25 ) 26 27 type synclist struct { 28 sync.Mutex 29 items []string 30 } 31 32 func (l *synclist) add(name string) { 33 l.Lock() 34 l.items = append(l.items, name) 35 l.Unlock() 36 } 37 38 // Recorder records input data line by line in underline list. 39 type Recorder struct { 40 list *synclist 41 } 42 43 // NewRecoder produces new Recorder instance. 44 func NewRecoder() *Recorder { 45 return &Recorder{ 46 list: &synclist{}, 47 } 48 } 49 50 // Write implements io.Write interface 51 func (rec *Recorder) Write(p []byte) (int, error) { 52 pr, pw := io.Pipe() 53 s := bufio.NewScanner(pr) 54 55 ch := make(chan struct{}) 56 go func() { 57 for s.Scan() { 58 rec.Add(s.Text()) 59 } 60 close(ch) 61 }() 62 63 n, err := pw.Write(p) 64 if err != nil { 65 <-ch 66 // defer pw.Close() ? 67 return n, err 68 } 69 err = pw.Close() 70 <-ch 71 return n, err 72 } 73 74 // Add appends string to Recorder. 75 func (rec *Recorder) Add(s string) { 76 rec.list.add(s) 77 } 78 79 // String stringifies recorder content. 80 func (rec *Recorder) String() string { 81 if len(rec.list.items) == 0 { 82 return "" 83 } 84 s := []string{"Steps:"} 85 for n, step := range rec.list.items { 86 s = append(s, fmt.Sprintf("%v:%v", n, step)) 87 } 88 return strings.Join(s, ", ") 89 } 90 91 // StringMultiline stringifies recorder content in multiple lines. 92 func (rec *Recorder) StringMultiline() string { 93 if len(rec.list.items) == 0 { 94 return "" 95 } 96 s := []string{"Steps:"} 97 for n, step := range rec.list.items { 98 s = append(s, fmt.Sprintf(" %v: %v", n, step)) 99 } 100 return strings.Join(s, "\n") 101 } 102 103 // Items returns Recorder's underlying array. 104 func (rec *Recorder) Items() []string { 105 return rec.list.items 106 }