Skip to content
Snippets Groups Projects
logger.go 3.15 KiB
// Copyright 2018 Orus.io. All rights reserved.

package fullenv

import (
	"fmt"
	"os"
	"strings"
	"testing"
)

// GetTestLogger returns a new BusLogger for the passed testing.T
func GetTestLogger(t testing.TB) *TestLogger {
	return &TestLogger{t, nil, os.Getenv("XBUS_TEST_LOG_TO_STDOUT") != ""}
}

// MatchMessage is a function that match a log message
type MatchMessage func(string) bool

// ExpectedError is the definition of an expected error
type ExpectedError struct {
	MatchMessage MatchMessage
	Name         string
}

// ExpectsEqual returns a ExpectedError matching a message exactly
func ExpectsEqual(value string) ExpectedError {
	return ExpectedError{
		MatchMessage: func(text string) bool { return text == value },
		Name:         value,
	}
}

// ExpectsContains returns a ExpectedError matching a partial message
func ExpectsContains(value string) ExpectedError {
	return ExpectedError{
		Name: value,
		MatchMessage: func(text string) bool {
			return strings.Contains(text, value)
		},
	}
}

// TestLogger is a BusLogger for tests
type TestLogger struct {
	t              testing.TB
	expectedErrors []ExpectedError
	printToStdout  bool
}

// ExpectsError anticipate an error and make it non-fatal to the test
func (m *TestLogger) ExpectsError(expectedError interface{}) {
	if eE, ok := expectedError.(ExpectedError); ok {
		m.expectedErrors = append(m.expectedErrors, eE)
	} else if strValue, ok := expectedError.(string); ok {
		m.expectedErrors = append(
			m.expectedErrors,
			ExpectsEqual(strValue),
		)
	} else {
		panic("Invalid type for expectedError. Expected a MatchMessage function " +
			"or a string")
	}
}

// Noticef passes the message to T.Logf
func (m TestLogger) Noticef(format string, v ...interface{}) {
	if m.printToStdout {
		fmt.Printf("[INF] "+format+"\n", v...)
	}
	m.t.Logf("[INF] "+format, v...)
}

// Fatalf passes the message to T.Fatalf
func (m TestLogger) Fatalf(format string, v ...interface{}) {
	if m.printToStdout {
		fmt.Printf("[FTL] "+format+"\n", v...)
	}
	m.t.Fatalf("[FTL] "+format, v...)
}

// Errorf passes the message to T.Errorf
func (m *TestLogger) Errorf(format string, v ...interface{}) {
	for i, expectedError := range m.expectedErrors {
		if expectedError.MatchMessage(fmt.Sprintf(format, v...)) {
			if m.printToStdout {
				fmt.Printf("[ERR] (expected) "+format+"\n", v...)
			}
			m.t.Logf("[ERR] (expected) "+format, v...)
			m.expectedErrors = append(m.expectedErrors[:i], m.expectedErrors[i+1:]...)
			return
		}
	}
	m.t.Fatalf("[ERR] (unexpected) "+format, v...)
}

// Debugf passes the message to T.Logf
func (m TestLogger) Debugf(format string, v ...interface{}) {
	if m.printToStdout {
		fmt.Printf("[DBG] "+format+"\n", v...)
	}
	m.t.Logf("[DBG] "+format, v...)
}

// Tracef passes the message to T.Logf
func (m TestLogger) Tracef(format string, v ...interface{}) {
	if m.printToStdout {
		fmt.Printf("[TRC] "+format+"\n", v...)
	}
	m.t.Logf("[TRC] "+format, v...)
}

// VerifyExpectations enforce error expectations
func (m TestLogger) VerifyExpectations() {
	for _, eE := range m.expectedErrors {
		if m.printToStdout {
			fmt.Printf("Expected error not received: %s\n", eE.Name)
		}
		m.t.Errorf("Expected error not received: %s", eE.Name)
	}
}