github.com/haraldrudell/parl@v0.4.176/log_test.go (about)

     1  /*
     2  © 2020–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package parl
     7  
     8  import (
     9  	"fmt"
    10  	"strings"
    11  	"sync"
    12  	"testing"
    13  
    14  	"github.com/haraldrudell/parl/perrors"
    15  	"github.com/haraldrudell/parl/plog"
    16  	"github.com/haraldrudell/parl/pruntime"
    17  )
    18  
    19  func TestLogLog(t *testing.T) {
    20  	// reset of static loggings logInstance object
    21  	defer func(stderrLogger0 *plog.LogInstance) {
    22  		stderrLogger = stderrLogger0
    23  	}(stderrLogger)
    24  	defer SetDebug(false)
    25  
    26  	text1, textNewline, expectedLocation, _, writer, _ := mocksLogStat()
    27  	stderrLogger = plog.NewLogFrames(writer, 1)
    28  
    29  	var actualSlice []string
    30  	var actual string
    31  
    32  	// Log
    33  	Log(text1)
    34  	actualSlice = writer.getData()
    35  	if len(actualSlice) != 1 || actualSlice[0] != textNewline {
    36  		t.Logf(".Log failed: expected: %q actual: %s", textNewline, quoteSliceLogStat(actualSlice))
    37  		t.Fail()
    38  	}
    39  
    40  	// Log with Location
    41  	SetDebug(true)
    42  	Log(text1 + "\n")
    43  	actualSlice = writer.getData()
    44  	if len(actualSlice) != 1 {
    45  		t.Logf("Log SetDebug: invocations not 1: %d", len(actualSlice))
    46  	} else {
    47  		actual = actualSlice[0]
    48  	}
    49  	if !strings.HasPrefix(actual, text1) {
    50  		t.Logf("Log SetDebug: no text1 prefix: %q", actual)
    51  		t.Fail()
    52  	}
    53  	if !strings.Contains(actual, expectedLocation) {
    54  		t.Logf("Log SetDebug: no location: actual: %q expected: %q", actual, expectedLocation)
    55  		t.Fail()
    56  	}
    57  	if strings.Index(actual, "\n") != len(actual)-1 {
    58  		t.Logf("Log SetDebug: newline not at end: actual: %q expected: %q", actual, expectedLocation)
    59  		t.Fail()
    60  	}
    61  }
    62  
    63  func TestInfoLog(t *testing.T) {
    64  	defer func(stderrLogger0 *plog.LogInstance) {
    65  		stderrLogger = stderrLogger0
    66  	}(stderrLogger)
    67  	defer SetSilent(false)
    68  
    69  	text1, textNewline, _, _, writer, _ := mocksLogStat()
    70  	stderrLogger = plog.NewLogFrames(writer, 1)
    71  
    72  	var actualSlice []string
    73  
    74  	// Info
    75  	Info(text1)
    76  	actualSlice = writer.getData()
    77  	if len(actualSlice) != 1 || actualSlice[0] != textNewline {
    78  		t.Logf(".Log failed: expected:\n%q actual:\n%+v", textNewline, quoteSliceLogStat(actualSlice))
    79  		t.Fail()
    80  	}
    81  	if IsSilent() {
    82  		t.Logf("SetSilent default true")
    83  		t.Fail()
    84  	}
    85  
    86  	// SetSilent
    87  	SetSilent(true)
    88  	if !IsSilent() {
    89  		t.Logf("SetSilent ineffective")
    90  		t.Fail()
    91  	}
    92  	Info(text1)
    93  	actualSlice = writer.getData()
    94  	if len(actualSlice) != 0 {
    95  		t.Logf("SetSilent true: Info still prints")
    96  		t.Fail()
    97  	}
    98  }
    99  
   100  func TestDebugLog(t *testing.T) {
   101  	defer func(stderrLogger0 *plog.LogInstance) {
   102  		stderrLogger = stderrLogger0
   103  	}(stderrLogger)
   104  	defer SetDebug(false)
   105  
   106  	text1, textNewline, expectedLocation, _, writer, _ := mocksLogStat()
   107  	stderrLogger = plog.NewLogFrames(writer, 1)
   108  
   109  	var actualSlice []string
   110  	var actual string
   111  
   112  	// Debug off
   113  	if IsThisDebug() {
   114  		t.Logf("IsThisDebug default true")
   115  		t.Fail()
   116  	}
   117  	Debug(text1)
   118  	actualSlice = writer.getData()
   119  	if len(actualSlice) != 0 {
   120  		t.Logf("Debug prints as default")
   121  		t.Fail()
   122  	}
   123  
   124  	// Debug on
   125  	SetDebug(true)
   126  	if !IsThisDebug() {
   127  		t.Logf("IsThisDebug ineffective")
   128  		t.Fail()
   129  	}
   130  	Debug(textNewline)
   131  	actualSlice = writer.getData()
   132  	if len(actualSlice) != 1 {
   133  		t.Logf("Log SetDebug: invocations not 1: %d", len(actualSlice))
   134  		t.FailNow()
   135  	}
   136  	actual = actualSlice[0]
   137  	if !strings.HasPrefix(actual, text1) {
   138  		t.Logf("Log SetDebug: no text1 prefix: %q", actual)
   139  		t.Fail()
   140  	}
   141  	if !strings.Contains(actual, expectedLocation) {
   142  		t.Logf("Log SetDebug: no location: actual: %q expected: %q", actual, expectedLocation)
   143  		t.Fail()
   144  	}
   145  }
   146  
   147  func TestRegexpLog(t *testing.T) {
   148  	defer func(stderrLogger0 *plog.LogInstance) {
   149  		stderrLogger = stderrLogger0
   150  	}(stderrLogger)
   151  	defer SetRegexp("")
   152  
   153  	text1, textNewline, expectedLocation, regexpLocation, writer, _ := mocksLogStat()
   154  	stderrLogger = plog.NewLogFrames(writer, 1)
   155  
   156  	matchingRegexp := regexpLocation
   157  	nonMatchingRegexp := "aaa"
   158  
   159  	var actualSlice []string
   160  	var actual string
   161  
   162  	// matching regexp
   163  	if err := SetRegexp(matchingRegexp); err != nil {
   164  		t.Logf("SetRegexp failed: input: %q err: %+v", matchingRegexp, err)
   165  		t.Fail()
   166  	}
   167  	Debug(textNewline)
   168  	actualSlice = writer.getData()
   169  	if len(actualSlice) != 1 {
   170  		t.Logf("matching regexp did not print 1: %d regexp input:\n%q",
   171  			len(actualSlice),
   172  			matchingRegexp)
   173  		t.Fail()
   174  	}
   175  	actual = actualSlice[0]
   176  	if !strings.HasPrefix(actual, text1) {
   177  		t.Logf("matching regexp: missing prefix: %q text: %q", text1, actual)
   178  		t.Fail()
   179  	}
   180  	if !strings.Contains(actual, expectedLocation) {
   181  		t.Logf("matching regexp: no location: actual:\n%q expected:\n%q",
   182  			actual,
   183  			expectedLocation)
   184  		t.Fail()
   185  	}
   186  	if strings.Index(actual, "\n") != len(actual)-1 {
   187  		t.Logf("matching regexp: newline not at end: actual: %q expected: %q", actual, expectedLocation)
   188  		t.Fail()
   189  	}
   190  
   191  	// non-matching regexp
   192  	if err := SetRegexp(nonMatchingRegexp); err != nil {
   193  		panic(err)
   194  	}
   195  	Debug(text1)
   196  	actualSlice = writer.getData()
   197  	if len(actualSlice) > 0 {
   198  		t.Logf("non-matching regexp did print: %d", len(actualSlice))
   199  		t.Fail()
   200  	}
   201  }
   202  
   203  type mockWriterLogStat struct {
   204  	lock sync.Mutex
   205  	buf  []string
   206  }
   207  
   208  func (w *mockWriterLogStat) Write(p []byte) (n int, err error) {
   209  	n = len(p)
   210  	w.lock.Lock()
   211  	defer w.lock.Unlock()
   212  	w.buf = append(w.buf, string(p))
   213  	return
   214  }
   215  
   216  func (w *mockWriterLogStat) getData() (sList []string) {
   217  	w.lock.Lock()
   218  	defer w.lock.Unlock()
   219  	sList = w.buf
   220  	w.buf = nil
   221  	return
   222  }
   223  
   224  func quoteSliceLogStat(sList []string) (s string) {
   225  	var s2 []string
   226  	for _, sx := range sList {
   227  		s2 = append(s2, fmt.Sprintf("%q", sx))
   228  	}
   229  	return strings.Join(s2, "\x20")
   230  }
   231  
   232  func mocksLogStat() (text1, textNewline, expectedLocation, regexpLocation string, writer *mockWriterLogStat, mockOutput func(n int, s string) (err error)) {
   233  	text1 = "abc"
   234  	textNewline = text1 + "\n"
   235  
   236  	// location text for this file
   237  	location := pruntime.NewCodeLocation(1)
   238  	expectedLocation = location.Short()
   239  	// remove line number since this changes
   240  	if index := strings.Index(expectedLocation, ":"); index == -1 {
   241  		panic(perrors.Errorf("error116.NewCodeLocation failed: %q", expectedLocation))
   242  	} else {
   243  		expectedLocation = expectedLocation[0:index]
   244  	}
   245  	regexpLocation = location.FuncName
   246  	writer = &mockWriterLogStat{}
   247  	mockOutput = func(n int, s string) (err error) {
   248  		_ = n
   249  		if !strings.HasSuffix(s, "\n") {
   250  			s += "\n"
   251  		}
   252  		_, err = writer.Write([]byte(s))
   253  		return
   254  	}
   255  	return
   256  }
   257  
   258  func TestIsThisDebugN(t *testing.T) {
   259  	SetDebug(false)
   260  
   261  	// matching Regexp should…
   262  	SetRegexp("TestIsThisDebugN")
   263  	if !IsThisDebug() {
   264  		t.Error("IsThisDebug false")
   265  	}
   266  	if !IsThisDebugN(0) {
   267  		t.Error("IsThisDebugN(0) false")
   268  	}
   269  	if IsThisDebugN(1) {
   270  		t.Error("IsThisDebugN(1) true")
   271  	}
   272  
   273  	// no debug should…
   274  	SetRegexp("")
   275  	if IsThisDebug() {
   276  		t.Error("IsThisDebug true")
   277  	}
   278  	if IsThisDebugN(0) {
   279  		t.Error("IsThisDebugN(0) true")
   280  	}
   281  	if IsThisDebugN(1) {
   282  		t.Error("IsThisDebugN(1) true")
   283  	}
   284  }