github.com/ssgreg/logf@v1.4.1/appender_test.go (about)

     1  package logf
     2  
     3  import (
     4  	"encoding/base64"
     5  	"errors"
     6  	"os"
     7  	"syscall"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  )
    12  
    13  func TestDiscardAppender(t *testing.T) {
    14  	a := NewDiscardAppender()
    15  
    16  	assert.NoError(t, a.Append(Entry{}))
    17  	assert.NoError(t, a.Flush())
    18  	assert.NoError(t, a.Sync())
    19  }
    20  
    21  type testWriterNoSync struct {
    22  	writeData []byte
    23  }
    24  
    25  func (w *testWriterNoSync) Write(p []byte) (n int, err error) {
    26  	if len(p) == 0 {
    27  		panic("TestBuffer.Writer buffer can't be empty!")
    28  	}
    29  	w.writeData = p
    30  
    31  	return 0, nil
    32  }
    33  
    34  type testWriter struct {
    35  	writeData   []byte
    36  	syncCounter int
    37  
    38  	e error
    39  }
    40  
    41  func (w *testWriter) Write(p []byte) (n int, err error) {
    42  	if len(p) == 0 {
    43  		panic("TestBuffer.Writer buffer can't be empty!")
    44  	}
    45  	w.writeData = p
    46  
    47  	return 0, nil
    48  }
    49  
    50  func (w *testWriter) Sync() error {
    51  	w.syncCounter++
    52  
    53  	return w.e
    54  }
    55  
    56  func checkWriterData(t *testing.T, w *testWriter, writeData string, syncCounter int) {
    57  	assert.Equal(t, writeData, string(w.writeData))
    58  	assert.Equal(t, syncCounter, w.syncCounter)
    59  
    60  	w.syncCounter = 0
    61  	w.writeData = nil
    62  }
    63  
    64  type failingEncoder struct {
    65  	e error
    66  }
    67  
    68  func (e *failingEncoder) Encode(*Buffer, Entry) error {
    69  	return e.e
    70  }
    71  
    72  type failingWriter struct {
    73  	e error
    74  }
    75  
    76  func (w *failingWriter) Write(p []byte) (n int, err error) {
    77  	return 0, w.e
    78  }
    79  
    80  func (w *failingWriter) Sync() error {
    81  	return w.e
    82  }
    83  
    84  func TestWriteAppenderErrors(t *testing.T) {
    85  	goldenErr := errors.New("test error")
    86  
    87  	w := testWriter{}
    88  	a := NewWriteAppender(&w, &failingEncoder{goldenErr})
    89  	// Sync should be called once in constructor to check sync possibility.
    90  	checkWriterData(t, &w, "", 1)
    91  
    92  	assert.EqualError(t, a.Append(Entry{}), goldenErr.Error())
    93  	checkWriterData(t, &w, "", 0)
    94  
    95  	a = NewWriteAppender(&failingWriter{goldenErr}, NewJSONEncoder.Default())
    96  	assert.NoError(t, a.Append(Entry{}))
    97  	assert.EqualError(t, a.Flush(), goldenErr.Error())
    98  	assert.EqualError(t, a.Sync(), goldenErr.Error())
    99  }
   100  
   101  func TestWriteAppenderNoSync(t *testing.T) {
   102  	w := testWriterNoSync{}
   103  
   104  	a := NewWriteAppender(&w, NewJSONEncoder.Default())
   105  	assert.NoError(t, a.Sync())
   106  }
   107  
   108  func TestWriteAppenderInvalidSync(t *testing.T) {
   109  	// Check for EINVAL - a known error if Writer is bound to a
   110  	// special File (e.g., a pipe or socket) which does not support
   111  	// synchronization.
   112  
   113  	w := testWriter{e: &os.PathError{Err: syscall.EINVAL}}
   114  
   115  	a := NewWriteAppender(&w, NewJSONEncoder.Default())
   116  	// Sync should be called once in constructor to check sync possibility.
   117  	checkWriterData(t, &w, "", 1)
   118  
   119  	assert.NoError(t, a.Sync())
   120  	// Sync is ignoring now.
   121  	checkWriterData(t, &w, "", 0)
   122  }
   123  
   124  func TestWriteAppender(t *testing.T) {
   125  	w := testWriter{}
   126  
   127  	a := NewWriteAppender(&w, NewJSONEncoder.Default())
   128  	// Sync should be called once in constructor to check sync possibility.
   129  	checkWriterData(t, &w, "", 1)
   130  
   131  	assert.NoError(t, a.Sync())
   132  	// Expected no buffer because of no data and one sync call.
   133  	checkWriterData(t, &w, "", 1)
   134  
   135  	// Test Append auto flush.
   136  
   137  	bigEntry := Entry{
   138  		Text: base64.StdEncoding.EncodeToString(make([]byte, PageSize)),
   139  	}
   140  
   141  	assert.NoError(t, a.Append(bigEntry))
   142  	// Passed entry is enough to force Appender to call Flush automatically.
   143  	// Expected specified buffer and no sync calls.
   144  	checkWriterData(t, &w, `{"level":"error","ts":"0001-01-01T00:00:00Z","msg":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="}`+"\n", 0)
   145  
   146  	// Test Flush.
   147  
   148  	assert.NoError(t, a.Append(Entry{}))
   149  	// Passed entry size less than Appender buffer size. So no buffer is
   150  	// expected and no sync calls.
   151  	checkWriterData(t, &w, "", 0)
   152  
   153  	assert.NoError(t, a.Flush())
   154  	// Flush forced Appender to commit it's buffer. Expected specified
   155  	// buffer and no sync calls.
   156  	checkWriterData(t, &w, `{"level":"error","ts":"0001-01-01T00:00:00Z","msg":""}`+"\n", 0)
   157  
   158  	assert.NoError(t, a.Flush())
   159  	// Second flush should do nothing.
   160  	checkWriterData(t, &w, "", 0)
   161  
   162  	// Test Sync.
   163  
   164  	assert.NoError(t, a.Append(Entry{}))
   165  	// Passed entry size less than Appender buffer size. So no buffer is
   166  	// expected and no sync calls.
   167  	checkWriterData(t, &w, "", 0)
   168  
   169  	assert.NoError(t, a.Flush())
   170  	assert.NoError(t, a.Sync())
   171  	// Sync forced Appender to commit it's buffer. Expected specified
   172  	// buffer and one sync call.
   173  	checkWriterData(t, &w, `{"level":"error","ts":"0001-01-01T00:00:00Z","msg":""}`+"\n", 1)
   174  }