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  }