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 }