tests, more docs

This commit is contained in:
Pavel 2024-06-14 17:42:42 +03:00
parent d233fd4cf1
commit 983dbe7229
11 changed files with 367 additions and 7 deletions

View File

@ -10,7 +10,7 @@ import (
) )
func TestAPIClientAdapter(t *testing.T) { func TestAPIClientAdapter(t *testing.T) {
log := newJSONBufferedLogger() log := newJSONBufferedLogger(nil)
client := retailcrm.New("https://example.com", "test_key").WithLogger(APIClientAdapter(log.Logger())) client := retailcrm.New("https://example.com", "test_key").WithLogger(APIClientAdapter(log.Logger()))
client.Debug = true client.Debug = true

155
core/logger/attrs_test.go Normal file
View File

@ -0,0 +1,155 @@
package logger
import (
"bytes"
"errors"
"fmt"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"io"
"net/http"
"testing"
)
func TestErr(t *testing.T) {
var cases = []struct {
source interface{}
expected string
}{
{
source: nil,
expected: "<nil>",
},
{
source: errors.New("untimely error"),
expected: "untimely error",
},
}
for _, c := range cases {
val := Err(c.source)
assert.Equal(t, c.expected, func() string {
if val.String != "" {
return val.String
}
if val.Interface != nil {
return fmt.Sprintf("%s", val.Interface)
}
return ""
}())
assert.Equal(t, ErrorAttr, val.Key)
}
}
func TestHandler(t *testing.T) {
val := Handler("handlerName")
assert.Equal(t, HandlerAttr, val.Key)
assert.Equal(t, "handlerName", val.String)
}
func TestHTTPStatusCode(t *testing.T) {
val := HTTPStatusCode(http.StatusOK)
assert.Equal(t, HTTPStatusAttr, val.Key)
assert.Equal(t, http.StatusOK, int(val.Integer))
}
func TestHTTPStatusName(t *testing.T) {
val := HTTPStatusName(http.StatusOK)
assert.Equal(t, HTTPStatusNameAttr, val.Key)
assert.Equal(t, http.StatusText(http.StatusOK), val.String)
}
func TestBody(t *testing.T) {
var cases = []struct {
input interface{}
result interface{}
}{
{
input: "",
result: nil,
},
{
input: nil,
result: nil,
},
{
input: "ooga booga",
result: "ooga booga",
},
{
input: `{"success":true}`,
result: map[string]interface{}{"success": true},
},
{
input: []byte{},
result: nil,
},
{
input: nil,
result: nil,
},
{
input: []byte("ooga booga"),
result: "ooga booga",
},
{
input: []byte(`{"success":true}`),
result: map[string]interface{}{"success": true},
},
{
input: newReaderMock(func(p []byte) (n int, err error) {
return 0, io.EOF
}),
result: nil,
},
{
input: newReaderMockData([]byte{}),
result: nil,
},
{
input: newReaderMockData([]byte("ooga booga")),
result: "ooga booga",
},
{
input: newReaderMockData([]byte(`{"success":true}`)),
result: map[string]interface{}{"success": true},
},
}
for _, c := range cases {
val := Body(c.input)
assert.Equal(t, BodyAttr, val.Key)
switch assertion := c.result.(type) {
case string:
assert.Equal(t, assertion, val.String)
case int:
assert.Equal(t, assertion, int(val.Integer))
default:
assert.Equal(t, c.result, val.Interface)
}
}
}
type readerMock struct {
mock.Mock
}
func newReaderMock(cb func(p []byte) (n int, err error)) io.Reader {
r := &readerMock{}
r.On("Read", mock.Anything).Return(cb)
return r
}
func newReaderMockData(data []byte) io.Reader {
return newReaderMock(bytes.NewReader(data).Read)
}
func (m *readerMock) Read(p []byte) (n int, err error) {
args := m.Called(p)
out := args.Get(0)
if cb, ok := out.(func(p []byte) (n int, err error)); ok {
return cb(p)
}
return args.Int(0), args.Error(1)
}

View File

@ -29,8 +29,10 @@ type jSONRecordScanner struct {
buf *bufferLogger buf *bufferLogger
} }
func newJSONBufferedLogger() *jSONRecordScanner { func newJSONBufferedLogger(buf *bufferLogger) *jSONRecordScanner {
buf := newBufferLogger() if buf == nil {
buf = newBufferLogger()
}
return &jSONRecordScanner{scan: bufio.NewScanner(buf), buf: buf} return &jSONRecordScanner{scan: bufio.NewScanner(buf), buf: buf}
} }

View File

@ -0,0 +1,89 @@
package logger
import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"go.uber.org/zap"
"testing"
)
type TestDefaultSuite struct {
suite.Suite
}
func TestDefault(t *testing.T) {
suite.Run(t, new(TestDefaultSuite))
}
func (s *TestDefaultSuite) TestNewDefault_OK() {
jsonLog := NewDefault("json", false)
consoleLog := NewDefault("console", true)
s.Assert().NotNil(jsonLog)
s.Assert().NotNil(consoleLog)
}
func (s *TestDefaultSuite) TestNewDefault_Panic() {
s.Assert().PanicsWithValue("unknown logger format: rar", func() {
NewDefault("rar", false)
})
}
func (s *TestDefaultSuite) TestWith() {
log := newBufferLogger()
log.With(zap.String(HandlerAttr, "Handler")).Info("test")
items, err := newJSONBufferedLogger(log).ScanAll()
s.Require().NoError(err)
s.Require().Len(items, 1)
s.Assert().Equal("Handler", items[0].Handler)
}
func (s *TestDefaultSuite) TestWithLazy() {
log := newBufferLogger()
log.WithLazy(zap.String(HandlerAttr, "Handler")).Info("test")
items, err := newJSONBufferedLogger(log).ScanAll()
s.Require().NoError(err)
s.Require().Len(items, 1)
s.Assert().Equal("Handler", items[0].Handler)
}
func (s *TestDefaultSuite) TestForHandler() {
log := newBufferLogger()
log.ForHandler("Handler").Info("test")
items, err := newJSONBufferedLogger(log).ScanAll()
s.Require().NoError(err)
s.Require().Len(items, 1)
s.Assert().Equal("Handler", items[0].Handler)
}
func (s *TestDefaultSuite) TestForConnection() {
log := newBufferLogger()
log.ForConnection("connection").Info("test")
items, err := newJSONBufferedLogger(log).ScanAll()
s.Require().NoError(err)
s.Require().Len(items, 1)
s.Assert().Equal("connection", items[0].Connection)
}
func (s *TestDefaultSuite) TestForAccount() {
log := newBufferLogger()
log.ForAccount("account").Info("test")
items, err := newJSONBufferedLogger(log).ScanAll()
s.Require().NoError(err)
s.Require().Len(items, 1)
s.Assert().Equal("account", items[0].Account)
}
func TestAnyZapFields(t *testing.T) {
fields := AnyZapFields([]interface{}{zap.String("k0", "v0"), "ooga", "booga"})
require.Len(t, fields, 3)
assert.Equal(t, zap.String("k0", "v0"), fields[0])
assert.Equal(t, zap.String("arg1", "ooga"), fields[1])
assert.Equal(t, zap.String("arg2", "booga"), fields[2])
}

37
core/logger/gin_test.go Normal file
View File

@ -0,0 +1,37 @@
package logger
import (
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"net/http"
"net/http/httptest"
"testing"
)
func TestGinMiddleware(t *testing.T) {
log := newBufferLogger()
rr := httptest.NewRecorder()
r := gin.New()
r.Use(GinMiddleware(log))
r.GET("/mine", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{})
})
r.ServeHTTP(rr, httptest.NewRequest(http.MethodGet, "/mine", nil))
require.Equal(t, http.StatusOK, rr.Code)
items, err := newJSONBufferedLogger(log).ScanAll()
require.NoError(t, err)
require.Len(t, items, 1)
require.NotEmpty(t, items[0].Context)
assert.NotEmpty(t, items[0].Context["startTime"])
assert.NotEmpty(t, items[0].Context["endTime"])
assert.True(t, func() bool {
_, ok := items[0].Context["latency"]
return ok
}())
assert.NotEmpty(t, items[0].Context["remoteAddress"])
assert.NotEmpty(t, items[0].Context[HTTPMethodAttr])
assert.NotEmpty(t, items[0].Context["path"])
assert.NotEmpty(t, items[0].Context["bodySize"])
}

View File

@ -11,7 +11,7 @@ import (
func TestMGTransportClientAdapter(t *testing.T) { func TestMGTransportClientAdapter(t *testing.T) {
httpClient := &http.Client{} httpClient := &http.Client{}
log := newJSONBufferedLogger() log := newJSONBufferedLogger(nil)
client := v1.NewWithClient("https://mg.dev", "test_token", httpClient). client := v1.NewWithClient("https://mg.dev", "test_token", httpClient).
WithLogger(MGTransportClientAdapter(log.Logger())) WithLogger(MGTransportClientAdapter(log.Logger()))
client.Debug = true client.Debug = true

18
core/logger/pool_test.go Normal file
View File

@ -0,0 +1,18 @@
package logger
import (
"github.com/stretchr/testify/assert"
"testing"
)
func TestPool(t *testing.T) {
p := NewPool[*uint8](func() *uint8 {
item := uint8(22)
return &item
})
val := p.Get()
assert.Equal(t, uint8(22), *val)
assert.Equal(t, uint8(22), *p.Get())
p.Put(val)
}

View File

@ -0,0 +1,24 @@
package logger
import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"testing"
)
func TestWriterAdapter(t *testing.T) {
log := newBufferLogger()
adapter := WriterAdapter(log, zap.InfoLevel)
msg := []byte("hello world")
total, err := adapter.Write(msg)
require.NoError(t, err)
require.Equal(t, total, len(msg))
items, err := newJSONBufferedLogger(log).ScanAll()
require.NoError(t, err)
require.Len(t, items, 1)
assert.Equal(t, "hello world", items[0].Message)
assert.Equal(t, "INFO", items[0].LevelName)
}

View File

@ -13,10 +13,10 @@ type zabbixCollectorAdapter struct {
func (a *zabbixCollectorAdapter) Errorf(format string, args ...interface{}) { func (a *zabbixCollectorAdapter) Errorf(format string, args ...interface{}) {
baseMsg := "cannot send metrics to Zabbix" baseMsg := "cannot send metrics to Zabbix"
switch format { switch format {
case "cannot send metrics to Zabbix: %v":
baseMsg = "cannot stop collector"
fallthrough
case "cannot stop collector: %s": case "cannot stop collector: %s":
baseMsg = "cannot stop Zabbix collector"
fallthrough
case "cannot send metrics to Zabbix: %v":
var err interface{} var err interface{}
if len(args) > 0 { if len(args) > 0 {
err = args[0] err = args[0]

View File

@ -0,0 +1,25 @@
package logger
import (
"errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"testing"
)
func TestZabbixCollectorAdapter(t *testing.T) {
log := newBufferLogger()
adapter := ZabbixCollectorAdapter(log)
adapter.Errorf("highly unexpected error: %s", "unexpected error")
adapter.Errorf("cannot stop collector: %s", "app error")
adapter.Errorf("cannot send metrics to Zabbix: %v", errors.New("send error"))
items, err := newJSONBufferedLogger(log).ScanAll()
require.NoError(t, err)
require.Len(t, items, 3)
assert.Equal(t, "highly unexpected error: unexpected error", items[0].Message)
assert.Equal(t, "cannot stop Zabbix collector", items[1].Message)
assert.Equal(t, "app error", items[1].Context[ErrorAttr])
assert.Equal(t, "cannot send metrics to Zabbix", items[2].Message)
assert.Equal(t, "send error", items[2].Context[ErrorAttr])
}

View File

@ -26,6 +26,16 @@ type BufferedLogger interface {
} }
// BufferLogger is an implementation of the BufferedLogger. // BufferLogger is an implementation of the BufferedLogger.
//
// BufferLogger can be used in tests to match specific log messages. It uses JSON by default (hardcoded for now).
// It implements fmt.Stringer and provides an adapter to the underlying buffer, which means it can also return
// Bytes(), can be used like io.Reader and can be cleaned using Reset() method.
//
// Usage:
//
// log := NewBufferedLogger()
// // Some other code that works with logger.
// fmt.Println(log.String())
type BufferLogger struct { type BufferLogger struct {
logger.Default logger.Default
buf LockableBuffer buf LockableBuffer