github.com/haraldrudell/parl@v0.4.176/plog/log-instance_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 plog
     7  
     8  import (
     9  	"fmt"
    10  	"strings"
    11  	"sync"
    12  	"testing"
    13  
    14  	"github.com/haraldrudell/parl/perrors"
    15  	"github.com/haraldrudell/parl/pruntime"
    16  )
    17  
    18  func TestLogLogI(t *testing.T) {
    19  
    20  	// the code location in printouts is code location Short:
    21  	// parl.TestLogLogI-log-instance_test.go:22
    22  	// it has a line number that  mocksLogI removes
    23  	if false {
    24  		t.Logf("Short: %q", pruntime.NewCodeLocation(0).Short())
    25  		t.FailNow()
    26  	}
    27  
    28  	text1, textNewline, expectedLocation, _, writer, lg := mocksLogI()
    29  	// expectedLocation:
    30  	// parl.TestLogLogI-log-instance_test.go
    31  	if false {
    32  		t.Logf("mocksLogI Short: %q", expectedLocation)
    33  		t.FailNow()
    34  	}
    35  	var actualSlice []string
    36  	var actual string
    37  
    38  	// Log
    39  	lg.Log(text1)
    40  	actualSlice = writer.getData()
    41  	if len(actualSlice) != 1 || actualSlice[0] != textNewline {
    42  		t.Logf("len actual: %d", len(actualSlice))
    43  		t.Logf(".Log failed: expected: %q actual: %s", textNewline, quoteSliceLogI(actualSlice))
    44  		t.Fail()
    45  	}
    46  
    47  	// Log with Location
    48  	lg.SetDebug(true)
    49  	lg.Log(text1 + "\n")
    50  	actualSlice = writer.getData()
    51  	if len(actualSlice) != 1 {
    52  		t.Logf("Log SetDebug: invocations not 1: %d", len(actualSlice))
    53  	} else {
    54  		actual = actualSlice[0]
    55  	}
    56  	if !strings.HasPrefix(actual, text1) {
    57  		t.Logf("Log SetDebug: no text1 prefix: %q", actual)
    58  		t.Fail()
    59  	}
    60  	if !strings.Contains(actual, expectedLocation) {
    61  		t.Logf("Log SetDebug: no location: actual:\n%q expected:\n%q", actual, expectedLocation)
    62  		t.Fail()
    63  	}
    64  	if strings.Index(actual, "\n") != len(actual)-1 {
    65  		t.Logf("Log SetDebug: newline not at end: actual: %q expected: %q", actual, expectedLocation)
    66  		t.Fail()
    67  	}
    68  }
    69  
    70  func TestInfoLogI(t *testing.T) {
    71  	text1, textNewline, _, _, writer, lg := mocksLogI()
    72  	var actualSlice []string
    73  
    74  	// Info
    75  	lg.Info(text1)
    76  	actualSlice = writer.getData()
    77  	if len(actualSlice) != 1 || actualSlice[0] != textNewline {
    78  		t.Logf(".Log failed: expected: %q actual: %+v", textNewline, quoteSliceLogI(actualSlice))
    79  		t.Fail()
    80  	}
    81  	if lg.IsSilent() {
    82  		t.Logf("SetSilent default true")
    83  		t.Fail()
    84  	}
    85  
    86  	// SetSilent
    87  	lg.SetSilent(true)
    88  	if !lg.IsSilent() {
    89  		t.Logf("SetSilent ineffective")
    90  		t.Fail()
    91  	}
    92  	lg.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 TestDebugLogI(t *testing.T) {
   101  	text1, textNewline, expectedLocation, _, writer, lg := mocksLogI()
   102  	var actualSlice []string
   103  	var actual string
   104  
   105  	// Debug off
   106  	if lg.IsThisDebug() {
   107  		t.Logf("IsThisDebug default true")
   108  		t.Fail()
   109  	}
   110  	lg.Debug(text1)
   111  	actualSlice = writer.getData()
   112  	if len(actualSlice) != 0 {
   113  		t.Logf("Debug prints as default")
   114  		t.Fail()
   115  	}
   116  
   117  	// Debug on
   118  	lg.SetDebug(true)
   119  	if !lg.IsThisDebug() {
   120  		t.Logf("IsThisDebug ineffective")
   121  		t.Fail()
   122  	}
   123  	lg.Debug(textNewline)
   124  	actualSlice = writer.getData()
   125  	if len(actualSlice) != 1 {
   126  		t.Logf("Log SetDebug: invocations not 1: %d", len(actualSlice))
   127  		t.FailNow()
   128  	}
   129  	actual = actualSlice[0]
   130  	if !strings.HasPrefix(actual, text1) {
   131  		t.Logf("Log SetDebug: no text1 prefix: %q", actual)
   132  		t.Fail()
   133  	}
   134  	if !strings.Contains(actual, expectedLocation) {
   135  		t.Logf("Log SetDebug: no location: actual: %q expected: %q", actual, expectedLocation)
   136  		t.Fail()
   137  	}
   138  }
   139  
   140  func TestRegexpLogI(t *testing.T) {
   141  
   142  	// What is matched against the regexp is FuncName:
   143  	// github.com/haraldrudell/parl.TestRegexpLogI
   144  	// fully qualified package name and function name
   145  	if false {
   146  		t.Logf("FuncName: %q", pruntime.NewCodeLocation(0).FuncName)
   147  		t.FailNow()
   148  	}
   149  
   150  	text1, textNewline, expectedLocation, regexpLocation, writer, lg := mocksLogI()
   151  	var actualSlice []string
   152  	var actual string
   153  
   154  	nonMatchingRegexp := "aaa"
   155  	matchingRegexp := regexpLocation
   156  
   157  	// string that regExp is matched against: "github.com/haraldrudell/parl.TestRegexpLogI"
   158  	//t.Logf("string that regExp is matched against: %q", error116.NewCodeLocation(0).FuncName)
   159  
   160  	// matching regexp
   161  	if err := lg.SetRegexp(matchingRegexp); err != nil {
   162  		t.Logf("SetRegexp failed: input: %q err: %+v", matchingRegexp, err)
   163  		t.Fail()
   164  	}
   165  	lg.Debug(textNewline)
   166  	actualSlice = writer.getData()
   167  	if len(actualSlice) != 1 {
   168  		var r = lg.infoRegexp.Load()
   169  		t.Logf("matching regexp did not print 1: %d regexp input:\n%q compiled:\n%+v",
   170  			len(actualSlice),
   171  			matchingRegexp,
   172  			r)
   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, regexpLocation)
   188  		t.Fail()
   189  	}
   190  
   191  	// non-matching regexp
   192  	if err := lg.SetRegexp(nonMatchingRegexp); err != nil {
   193  		panic(err)
   194  	}
   195  	lg.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 mockWriterLogI struct {
   204  	lock sync.Mutex
   205  	buf  []string
   206  }
   207  
   208  func (w *mockWriterLogI) 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 *mockWriterLogI) 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 quoteSliceLogI(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 mocksLogI() (text1, textNewline, expectedLocation, regexpLocation string, writer *mockWriterLogI, lg *LogInstance) {
   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 = &mockWriterLogI{}
   247  	lg = NewLog(writer)
   248  	return
   249  }