Shermans's Notes
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Testing Stdin Stdout

    I needed to test the input and output of a cli program I was writing.

    I needed to capture what was happening in a goroutine safe way so I ended up with the struct below.

    Anywhere that did logging was passed this struct as their io.Writer

    It has a lock as testing with -race complained (rightly) at multiple routines trying to access at once. This would also help ensure that messages were output in full, without interference from other write calls E The only other concern was that as it was a buffered output, you need to call flush before getting a string of the output to compare.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    
    type StdIO struct {  
       in        bytes.Buffer  
       out       bytes.Buffer  
       inReader  *bufio.Reader  
       outWriter *bufio.Writer  
       rMutex    sync.Mutex  
       wMutex    sync.Mutex  
    }  
      
    func (s *StdIO) Flush() {  
       s.wMutex.Lock()  
       defer s.wMutex.Unlock()  
       s.outWriter.Flush()  
    }  
      
    func (s *StdIO) Read(p []byte) (n int, err error) {  
       s.rMutex.Lock()  
       defer s.rMutex.Unlock()  
       return s.inReader.Read(p)  
    }  
      
    func (s *StdIO) Write(p []byte) (n int, err error) {  
       s.wMutex.Lock()  
       defer s.wMutex.Unlock()  
       return s.outWriter.Write(p)  
    }  
      
    func NewStdIO() *StdIO {  
       s := &StdIO{  
          in:  bytes.Buffer{},  
          out: bytes.Buffer{},  
       }  
       s.inReader = bufio.NewReader(&s.in)  
       s.outWriter = bufio.NewWriter(&s.out)  
       return s  
    }