github.com/karrick/gorill@v1.10.3/nltr_test.go (about)

     1  package gorill
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"io/ioutil"
     8  	"os"
     9  	"testing"
    10  )
    11  
    12  // newTestReader returns a LineTerminatedReader that reads from a testReader
    13  // configured to return the specified tuples when read from.
    14  func newTestReader(tuples []tuple) *LineTerminatedReader {
    15  	return &LineTerminatedReader{R: &testReader{tuples: tuples}}
    16  }
    17  
    18  func ExampleNewLineTerminatedReader() {
    19  	r := &LineTerminatedReader{R: bytes.NewReader([]byte("123\n456"))}
    20  	buf, err := ioutil.ReadAll(r)
    21  	if err != nil {
    22  		fmt.Fprintf(os.Stderr, "%s\n", err)
    23  		os.Exit(1)
    24  	}
    25  	if got, want := len(buf), 8; got != want {
    26  		fmt.Fprintf(os.Stderr, "GOT: %v; WANT: %v\n", got, want)
    27  		os.Exit(1)
    28  	}
    29  	fmt.Printf("%q\n", buf[len(buf)-1])
    30  	// Output: '\n'
    31  }
    32  
    33  func TestNLTR(t *testing.T) {
    34  	buf := make([]byte, 64)
    35  
    36  	t.Run("compliance", func(t *testing.T) {
    37  		// Ensures compliance with guidelines set forth in io.Reader
    38  		// documentation, copied below:
    39  
    40  		// When Read encounters an error or end-of-file condition after
    41  		// successfully reading n > 0 bytes, it returns the number of bytes
    42  		// read.  It may return the (non-nil) error from the same call or return
    43  		// the error (and n == 0) from a subsequent call.  An instance of this
    44  		// general case is that a Reader returning a non-zero number of bytes at
    45  		// the end of the input stream may return either err == EOF or err ==
    46  		// nil.  The next Read should return 0, EOF.
    47  		t.Run("error during read", func(t *testing.T) {
    48  			r := newTestReader([]tuple{
    49  				tuple{"some data", io.ErrUnexpectedEOF},
    50  			})
    51  
    52  			n, err := r.Read(buf)
    53  			ensureError(t, err, "unexpected EOF")
    54  			ensureBuffer(t, buf, n, "some data")
    55  		})
    56  
    57  		// Implementations of Read are discouraged from returning a zero byte
    58  		// count with a nil error, except when len(p) == 0.
    59  		t.Run("final read has no room", func(t *testing.T) {
    60  			buf := make([]byte, 5)
    61  
    62  			r := newTestReader([]tuple{
    63  				tuple{"12345", io.EOF},
    64  			})
    65  
    66  			n, err := r.Read(buf)
    67  			ensureError(t, err, "")
    68  			ensureBuffer(t, buf, n, "12345")
    69  
    70  			n, err = r.Read(nil)
    71  			ensureError(t, err, "")
    72  			ensureBuffer(t, buf, n, "")
    73  		})
    74  	})
    75  
    76  	t.Run("functional", func(t *testing.T) {
    77  		t.Run("empty", func(t *testing.T) {
    78  			t.Run("with newline", func(t *testing.T) {
    79  				r := newTestReader([]tuple{
    80  					tuple{"\n", io.EOF},
    81  				})
    82  
    83  				n, err := r.Read(buf)
    84  				ensureError(t, err, "EOF")
    85  				ensureBuffer(t, buf, n, "\n")
    86  			})
    87  
    88  			t.Run("sans newline", func(t *testing.T) {
    89  				r := newTestReader([]tuple{
    90  					tuple{"", io.EOF},
    91  				})
    92  
    93  				n, err := r.Read(buf)
    94  				ensureError(t, err, "EOF")
    95  				ensureBuffer(t, buf, n, "\n")
    96  			})
    97  		})
    98  
    99  		t.Run("one line", func(t *testing.T) {
   100  			t.Run("with newline", func(t *testing.T) {
   101  				t.Run("source returns EOF after final data", func(t *testing.T) {
   102  					r := newTestReader([]tuple{
   103  						tuple{"one\n", nil},
   104  						tuple{"", io.EOF},
   105  					})
   106  
   107  					n, err := r.Read(buf)
   108  					ensureError(t, err, "")
   109  					ensureBuffer(t, buf, n, "one\n")
   110  
   111  					n, err = r.Read(buf)
   112  					ensureError(t, err, "EOF")
   113  					ensureBuffer(t, buf, n, "")
   114  				})
   115  
   116  				t.Run("source returns EOF with final data", func(t *testing.T) {
   117  					r := newTestReader([]tuple{
   118  						tuple{"one\n", io.EOF},
   119  					})
   120  
   121  					n, err := r.Read(buf)
   122  					ensureError(t, err, "EOF")
   123  					ensureBuffer(t, buf, n, "one\n")
   124  				})
   125  			})
   126  
   127  			t.Run("sans newline", func(t *testing.T) {
   128  				t.Run("source returns EOF after final data", func(t *testing.T) {
   129  					r := newTestReader([]tuple{
   130  						tuple{"one", nil},
   131  						tuple{"", io.EOF},
   132  					})
   133  
   134  					n, err := r.Read(buf)
   135  					ensureError(t, err, "")
   136  					ensureBuffer(t, buf, n, "one")
   137  
   138  					n, err = r.Read(buf)
   139  					ensureError(t, err, "EOF")
   140  					ensureBuffer(t, buf, n, "\n")
   141  				})
   142  
   143  				t.Run("source returns EOF with final data", func(t *testing.T) {
   144  					r := newTestReader([]tuple{
   145  						tuple{"one", io.EOF},
   146  					})
   147  
   148  					n, err := r.Read(buf)
   149  					ensureError(t, err, "EOF")
   150  					ensureBuffer(t, buf, n, "one\n")
   151  				})
   152  			})
   153  		})
   154  
   155  		t.Run("two lines", func(t *testing.T) {
   156  			t.Run("with newline", func(t *testing.T) {
   157  				t.Run("source returns EOF after final data", func(t *testing.T) {
   158  					r := newTestReader([]tuple{
   159  						tuple{"one\ntwo\n", nil},
   160  						tuple{"", io.EOF},
   161  					})
   162  
   163  					n, err := r.Read(buf)
   164  					ensureError(t, err, "")
   165  					ensureBuffer(t, buf, n, "one\ntwo\n")
   166  
   167  					n, err = r.Read(buf)
   168  					ensureError(t, err, "EOF")
   169  					ensureBuffer(t, buf, n, "")
   170  				})
   171  
   172  				t.Run("source returns EOF with final data", func(t *testing.T) {
   173  					r := newTestReader([]tuple{
   174  						tuple{"one\ntwo\n", io.EOF},
   175  					})
   176  
   177  					n, err := r.Read(buf)
   178  					ensureError(t, err, "EOF")
   179  					ensureBuffer(t, buf, n, "one\ntwo\n")
   180  				})
   181  			})
   182  
   183  			t.Run("sans newline", func(t *testing.T) {
   184  				t.Run("source returns EOF after final data", func(t *testing.T) {
   185  					r := newTestReader([]tuple{
   186  						tuple{"1234\n1234", nil},
   187  						tuple{"", io.EOF},
   188  					})
   189  
   190  					n, err := r.Read(buf)
   191  					ensureError(t, err, "")
   192  					ensureBuffer(t, buf, n, "1234\n1234")
   193  
   194  					n, err = r.Read(buf)
   195  					ensureError(t, err, "EOF")
   196  					ensureBuffer(t, buf, n, "\n")
   197  				})
   198  
   199  				t.Run("source returns EOF with final data", func(t *testing.T) {
   200  					t.Run("enough room in buf", func(t *testing.T) {
   201  						r := newTestReader([]tuple{
   202  							tuple{"1234\n1234", io.EOF},
   203  						})
   204  
   205  						n, err := r.Read(buf)
   206  						ensureError(t, err, "EOF")
   207  						ensureBuffer(t, buf, n, "1234\n1234\n")
   208  					})
   209  					t.Run("not enough room in buf", func(t *testing.T) {
   210  						buf := make([]byte, 5)
   211  
   212  						r := newTestReader([]tuple{
   213  							tuple{"12345", io.EOF},
   214  						})
   215  
   216  						n, err := r.Read(buf)
   217  						ensureError(t, err, "")
   218  						ensureBuffer(t, buf, n, "12345")
   219  
   220  						n, err = r.Read(buf)
   221  						ensureError(t, err, "EOF")
   222  						ensureBuffer(t, buf, n, "\n")
   223  					})
   224  				})
   225  			})
   226  		})
   227  	})
   228  }