github.com/r8d8/go-ethereum@v5.5.2+incompatible/logger/mlog_file_test.go (about) 1 package logger 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io/ioutil" 8 "os" 9 "strings" 10 "testing" 11 "time" 12 13 "github.com/ethereumproject/go-ethereum/common" 14 ) 15 16 var mlogExample1T = &MLogT{ 17 Description: `Struct for testing mlog structs.`, 18 Receiver: "TESTER", 19 Verb: "TESTING", 20 Subject: "MLOG", 21 Details: []MLogDetailT{ 22 {"FROM", "UDP_ADDRESS", "STRING"}, 23 {"FROM", "ID", "STRING"}, 24 {"NEIGHBORS", "BYTES_TRANSFERRED", "INT"}, 25 }, 26 } 27 28 var mlogExample2T = &MLogT{ 29 Description: `Yet another struct for testing mlog structs.`, 30 Receiver: "TESTER", 31 Verb: "TESTING", 32 Subject: "MLOG", 33 Details: []MLogDetailT{ 34 {"FROM", "UDP_ADDRESS", "STRING"}, 35 {"FROM", "ID", "STRING"}, 36 {"NEIGHBORS", "BYTES_TRANSFERRED", "INT"}, 37 }, 38 } 39 40 func BenchmarkSetDetailValues(b *testing.B) { 41 vals := []interface{}{"hello", "kitty", 42} 42 for i := 0; i < b.N; i++ { 43 mlogExample1T.AssignDetails(vals...) 44 } 45 } 46 47 func TestEnabling(t *testing.T) { 48 SetMlogEnabled(false) 49 if MlogEnabled() != false { 50 t.Error("expected: false, got: true") 51 } 52 53 SetMlogEnabled(true) 54 if MlogEnabled() != true { 55 t.Error("expected: true, got: false") 56 } 57 } 58 59 func TestRegisterAvailable(t *testing.T) { 60 MLogRegisterAvailable("example1", []*MLogT{mlogExample1T}) 61 62 avail := GetMLogRegistryAvailable() 63 if len(avail) != 1 { 64 t.Errorf("expected: 1, got: %d", len(avail)) 65 } 66 if _, ok := avail["example1"]; !ok { 67 t.Error("expected key 'example1' not found") 68 } 69 if l := len(avail["example1"]); l != 1 { 70 t.Errorf("expected: 1, got: %d", l) 71 } 72 73 MLogRegisterAvailable("example1", []*MLogT{mlogExample2T}) 74 avail = GetMLogRegistryAvailable() 75 if len(avail) != 1 { 76 t.Errorf("expected: 1, got: %d", len(avail)) 77 } 78 if _, ok := avail["example1"]; !ok { 79 t.Error("expected key 'example1' not found") 80 } 81 if l := len(avail["example1"]); l != 1 { 82 t.Errorf("expected: 1, got: %d", l) 83 } 84 85 MLogRegisterAvailable("example1", []*MLogT{mlogExample1T, mlogExample2T}) 86 avail = GetMLogRegistryAvailable() 87 if len(avail) != 1 { 88 t.Errorf("expected: 1, got: %d", len(avail)) 89 } 90 if _, ok := avail["example1"]; !ok { 91 t.Error("expected key 'example1' not found") 92 } 93 if l := len(avail["example1"]); l != 2 { 94 t.Errorf("expected: 2, got: %d", l) 95 } 96 97 MLogRegisterAvailable("example2", []*MLogT{mlogExample2T}) 98 avail = GetMLogRegistryAvailable() 99 if len(avail) != 2 { 100 t.Errorf("expected: 2, got: %d", len(avail)) 101 } 102 if _, ok := avail["example1"]; !ok { 103 t.Error("expected key 'example1' not found") 104 } 105 if l := len(avail["example1"]); l != 2 { 106 t.Errorf("expected: 2, got: %d", l) 107 } 108 if _, ok := avail["example2"]; !ok { 109 t.Error("expected key 'example1' not found") 110 } 111 if l := len(avail["example2"]); l != 1 { 112 t.Errorf("expected: 1, got: %d", l) 113 } 114 } 115 116 func TestRegisterFromContext(t *testing.T) { 117 setupRegister() 118 119 err := MLogRegisterComponentsFromContext("example1") 120 if err != nil { 121 t.Errorf("unexpected error: %v", err) 122 } 123 124 active := GetMLogRegistryActive() 125 if l := len(active); l != 1 { 126 t.Errorf("expected: 1, got: %d", l) 127 } 128 if _, ok := active["example1"]; !ok { 129 t.Error("expected key 'example1' not found") 130 } 131 } 132 133 func TestRegisterFromContextMany(t *testing.T) { 134 setupRegister() 135 136 err := MLogRegisterComponentsFromContext("example3,example2") 137 if err != nil { 138 t.Errorf("unexpected error: %v", err) 139 } 140 141 active := GetMLogRegistryActive() 142 if l := len(active); l != 2 { 143 t.Errorf("expected: 2, got: %d", l) 144 } 145 if _, ok := active["example2"]; !ok { 146 t.Error("expected key 'example2' not found") 147 } 148 if _, ok := active["example3"]; !ok { 149 t.Error("expected key 'example3' not found") 150 } 151 } 152 153 func TestRegisterFromNegativeContext(t *testing.T) { 154 setupRegister() 155 156 err := MLogRegisterComponentsFromContext("!example2") 157 if err != nil { 158 t.Errorf("unexpected error: %v", err) 159 } 160 161 active := GetMLogRegistryActive() 162 if l := len(active); l != 2 { 163 t.Errorf("expected: 2, got: %d", l) 164 } 165 if _, ok := active["example1"]; !ok { 166 t.Error("expected key 'example1' not found") 167 } 168 if _, ok := active["example3"]; !ok { 169 t.Error("expected key 'example3' not found") 170 } 171 } 172 173 func TestRegisterFromNegativeContextMany(t *testing.T) { 174 setupRegister() 175 176 err := MLogRegisterComponentsFromContext("!example2,example1") 177 if err != nil { 178 t.Errorf("unexpected error: %v", err) 179 } 180 181 active := GetMLogRegistryActive() 182 if l := len(active); l != 1 { 183 t.Errorf("expected: 1, got: %d", l) 184 } 185 if _, ok := active["example3"]; !ok { 186 t.Error("expected key 'example3' not found") 187 } 188 } 189 190 func TestRegisterFromWrongContext(t *testing.T) { 191 setupRegister() 192 193 err := MLogRegisterComponentsFromContext("wrongOne") 194 if err == nil { 195 t.Error("expected error, got nil") 196 } 197 198 err = MLogRegisterComponentsFromContext("example1,wrongOne") 199 if err == nil { 200 t.Error("expected error, got nil") 201 } 202 } 203 204 func setupRegister() { 205 MLogRegisterAvailable("example1", []*MLogT{mlogExample1T, mlogExample2T}) 206 MLogRegisterAvailable("example2", []*MLogT{mlogExample1T, mlogExample2T}) 207 MLogRegisterAvailable("example3", []*MLogT{mlogExample1T, mlogExample2T}) 208 209 // clean the global state 210 MLogRegisterComponentsFromContext("!example1,example2,example3") 211 } 212 213 func TestAssignDetails(t *testing.T) { 214 addr := "sampleAddress" 215 id := "sampleId" 216 bytes := 123 217 mlogExample1T.AssignDetails(addr, id, bytes) 218 219 if mlogExample1T.Details[0].Value != addr { 220 t.Errorf("expected: '%s', got: '%s'", addr, mlogExample1T.Details[0].Value) 221 } 222 if mlogExample1T.Details[1].Value != id { 223 t.Errorf("expected: '%s', got: '%s'", id, mlogExample1T.Details[1].Value) 224 } 225 if mlogExample1T.Details[2].Value != bytes { 226 t.Errorf("expected: %d, got: %d", bytes, mlogExample1T.Details[2].Value) 227 } 228 229 // assign again... 230 addr2 := "anotherAddress" 231 id2 := "anotherId" 232 bytes2 := 321 233 mlogExample1T.AssignDetails(addr2, id2, bytes2) 234 235 if mlogExample1T.Details[0].Value != addr2 { 236 t.Errorf("expected: '%s', got: '%s'", addr2, mlogExample1T.Details[0].Value) 237 } 238 if mlogExample1T.Details[1].Value != id2 { 239 t.Errorf("expected: '%s', got: '%s'", id2, mlogExample1T.Details[1].Value) 240 } 241 if mlogExample1T.Details[2].Value != bytes2 { 242 t.Errorf("expected: %d, got: %d", bytes2, mlogExample1T.Details[2].Value) 243 } 244 } 245 246 func TestSend(t *testing.T) { 247 Reset() 248 // Set up a log sys with a local buffer instead of file 249 var b = new(bytes.Buffer) 250 sys := NewMLogSystem(b, 0, LogLevel(1), false) 251 AddLogSystem(sys) 252 253 testLogger := MLogRegisterAvailable("example1", []*MLogT{mlogExample1T, mlogExample2T}) 254 MLogRegisterActive("example1") 255 256 addr := "sampleAddress" 257 id := "sampleId" 258 numBytesSent := 123 259 mlogExample1T.AssignDetails(addr, id, numBytesSent) 260 261 formats := []string{"plain", "kv", "json"} 262 263 for _, format := range formats { 264 SetMLogFormatFromString(format) 265 mlogExample1T.Send(testLogger) 266 267 Flush() // wait for messages to be delivered 268 269 if format == "plain" || format == "kv" { 270 var wantString string 271 if format == "plain" { 272 wantString = mlogExample1T.FormatPlain() 273 } else if format == "kv" { 274 wantString = mlogExample1T.FormatKV() 275 } 276 277 // basic sanity check for our expectations 278 if len(wantString) < 10 || !strings.Contains(wantString, common.SessionID) { 279 t.Fatalf("wantstring: got: %v, want: %v", wantString, "something sane") 280 } 281 282 if !strings.Contains(b.String(), wantString) { 283 t.Errorf("got: %v, want: %v", b.String(), wantString) 284 } else { 285 t.Logf("%s ok: %s", format, b.String()) 286 } 287 288 b.Reset() 289 continue 290 } 291 292 // handle JSON differently, since we can show that values are OK as well as valid JSON format 293 // 294 // for decoding the JSON line for got/want comparison 295 type arbitraryJSON map[string]interface{} 296 arb := arbitraryJSON{} 297 298 if err := json.Unmarshal(b.Bytes(), &arb); err != nil { 299 t.Fatal(err) 300 } 301 302 wantMap := make(map[string]interface{}) 303 304 wantMap["component"] = string(testLogger) 305 wantMap["session"] = common.SessionID 306 307 // eg. "event":"tester.testing.mlog" 308 wantMap["event"] = strings.Join([]string{ 309 strings.ToLower(mlogExample1T.Receiver), 310 strings.ToLower(mlogExample1T.Verb), 311 strings.ToLower(mlogExample1T.Subject), 312 }, ".") 313 314 // eg. "from.udp_address":"sampleAddress" 315 for _, v := range mlogExample1T.Details { 316 wantMap[strings.Join( 317 []string{ 318 strings.ToLower(v.Owner), 319 strings.ToLower(v.Key), 320 }, ".")] = v.Value 321 } 322 323 var hasError bool 324 for k, v := range wantMap { 325 // fmtStringer comparison because 123 != 123... 326 if arb[k] != v && fmt.Sprintf("%v", arb[k]) != fmt.Sprintf("%v", v) { 327 hasError = true 328 t.Errorf("arb[k] != v, arb[k] = %v, v = %v", arb[k], v) 329 t.Errorf("got: %v, want: %v", b.String(), wantMap) 330 } 331 } 332 333 if !hasError { 334 t.Logf("%s ok: %s", format, b.String()) 335 } 336 337 b.Reset() 338 } 339 } 340 341 func TestFormats(t *testing.T) { 342 formats := []struct { 343 name string 344 valid bool 345 }{ 346 {"plain", true}, 347 {"kv", true}, 348 {"json", true}, 349 {"invalid", false}, 350 } 351 352 for _, format := range formats { 353 t.Run(format.name, func(t *testing.T) { 354 err := SetMLogFormatFromString(format.name) 355 if format.valid { 356 if err != nil { 357 t.Error("unexpected error") 358 } 359 if fmt := GetMLogFormat().String(); fmt != format.name { 360 t.Errorf("expected: '%s', got: '%s'", format.name, fmt) 361 } 362 } else { 363 if err == nil { 364 t.Error("expected error, got nil") 365 } 366 } 367 }) 368 } 369 } 370 371 func TestInit(t *testing.T) { 372 now := time.Now() 373 374 dir, err := ioutil.TempDir("", "mlog_test") 375 if err != nil { 376 t.Errorf("cannot create temp dir: %v", err) 377 } 378 defer os.RemoveAll(dir) // clean up 379 380 SetMLogDir(dir) 381 _, filename, err := CreateMLogFile(now) 382 if err != nil { 383 t.Errorf("unexpected error: %v", err) 384 } 385 if len(filename) == 0 { 386 t.Errorf("expected non-empty filename") 387 } 388 if !strings.HasPrefix(filename, dir) { 389 t.Errorf("file created in wrong directory, expected: %s, got: %s", dir, filename) 390 } 391 } 392 393 func TestDocumentation(t *testing.T) { 394 // reset structure to force valid type information and give some esoteric names 395 mlogExample1T.Details = []MLogDetailT{ 396 {"FROM616", "UDP_ADDRESS911", "STRING"}, 397 {"FROM666", "RANDOMIZED_ID", "STRING"}, 398 {"NEIGHBORS", "BYTES_TRANSFERRED", "INT"}, 399 } 400 logger := MLogRegisterAvailable("example1", []*MLogT{mlogExample1T}) 401 402 docs := mlogExample1T.FormatDocumentation(logger) 403 if len(docs) == 0 { 404 t.Error("documentation is empty!") 405 } 406 if !strings.Contains(docs, mlogExample1T.Subject) { 407 t.Error("missing information about subject") 408 } 409 if !strings.Contains(docs, mlogExample1T.Receiver) { 410 t.Error("missing information about receiver") 411 } 412 if !strings.Contains(docs, mlogExample1T.Verb) { 413 t.Error("missing information about verb") 414 } 415 ldocs := strings.ToLower(docs) 416 for _, detail := range mlogExample1T.Details { 417 if !strings.Contains(ldocs, strings.ToLower(detail.Owner)) { 418 t.Error("missing information about detail owner") 419 } 420 if !strings.Contains(ldocs, strings.ToLower(detail.Key)) { 421 t.Error("missing information about detail key") 422 } 423 } 424 }