// Copyright (c) 2012 - Cloud Instruments Co., Ltd. // // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package seelog import ( "fmt" "strings" "testing" "time" ) const ( TestFuncName = "TestFormats" ) type formatTest struct { formatString string input string inputLogLevel LogLevel expectedOutput string errorExpected bool } var formatTests = []formatTest{ {"test", "abcdef", TraceLvl, "test", false}, {"", "abcdef", TraceLvl, "", false}, {"%Level", "", TraceLvl, "Trace", false}, {"%Level", "", DebugLvl, "Debug", false}, {"%Level", "", InfoLvl, "Info", false}, {"%Level", "", WarnLvl, "Warn", false}, {"%Level", "", ErrorLvl, "Error", false}, {"%Level", "", CriticalLvl, "Critical", false}, {"[%Level]", "", TraceLvl, "[Trace]", false}, {"[%Level]", "abc", DebugLvl, "[Debug]", false}, {"%LevelLevel", "", InfoLvl, "InfoLevel", false}, {"[%Level][%Level]", "", WarnLvl, "[Warn][Warn]", false}, {"[%Level]X[%Level]", "", ErrorLvl, "[Error]X[Error]", false}, {"%Levelll", "", CriticalLvl, "Criticalll", false}, {"%Lvl", "", TraceLvl, "", true}, {"%%Level", "", DebugLvl, "%Level", false}, {"%Level%", "", InfoLvl, "", true}, {"%sevel", "", WarnLvl, "", true}, {"Level", "", ErrorLvl, "Level", false}, {"%LevelLevel", "", CriticalLvl, "CriticalLevel", false}, {"%Lev", "", TraceLvl, "Trc", false}, {"%Lev", "", DebugLvl, "Dbg", false}, {"%Lev", "", InfoLvl, "Inf", false}, {"%Lev", "", WarnLvl, "Wrn", false}, {"%Lev", "", ErrorLvl, "Err", false}, {"%Lev", "", CriticalLvl, "Crt", false}, {"[%Lev]", "", TraceLvl, "[Trc]", false}, {"[%Lev]", "abc", DebugLvl, "[Dbg]", false}, {"%LevLevel", "", InfoLvl, "InfLevel", false}, {"[%Level][%Lev]", "", WarnLvl, "[Warn][Wrn]", false}, {"[%Lev]X[%Lev]", "", ErrorLvl, "[Err]X[Err]", false}, {"%Levll", "", CriticalLvl, "Crtll", false}, {"%LEVEL", "", TraceLvl, "TRACE", false}, {"%LEVEL", "", DebugLvl, "DEBUG", false}, {"%LEVEL", "", InfoLvl, "INFO", false}, {"%LEVEL", "", WarnLvl, "WARN", false}, {"%LEVEL", "", ErrorLvl, "ERROR", false}, {"%LEVEL", "", CriticalLvl, "CRITICAL", false}, {"[%LEVEL]", "", TraceLvl, "[TRACE]", false}, {"[%LEVEL]", "abc", DebugLvl, "[DEBUG]", false}, {"%LEVELLEVEL", "", InfoLvl, "INFOLEVEL", false}, {"[%LEVEL][%LEVEL]", "", WarnLvl, "[WARN][WARN]", false}, {"[%LEVEL]X[%Level]", "", ErrorLvl, "[ERROR]X[Error]", false}, {"%LEVELLL", "", CriticalLvl, "CRITICALLL", false}, {"%LEV", "", TraceLvl, "TRC", false}, {"%LEV", "", DebugLvl, "DBG", false}, {"%LEV", "", InfoLvl, "INF", false}, {"%LEV", "", WarnLvl, "WRN", false}, {"%LEV", "", ErrorLvl, "ERR", false}, {"%LEV", "", CriticalLvl, "CRT", false}, {"[%LEV]", "", TraceLvl, "[TRC]", false}, {"[%LEV]", "abc", DebugLvl, "[DBG]", false}, {"%LEVLEVEL", "", InfoLvl, "INFLEVEL", false}, {"[%LEVEL][%LEV]", "", WarnLvl, "[WARN][WRN]", false}, {"[%LEV]X[%LEV]", "", ErrorLvl, "[ERR]X[ERR]", false}, {"%LEVLL", "", CriticalLvl, "CRTLL", false}, {"%l", "", TraceLvl, "t", false}, {"%l", "", DebugLvl, "d", false}, {"%l", "", InfoLvl, "i", false}, {"%l", "", WarnLvl, "w", false}, {"%l", "", ErrorLvl, "e", false}, {"%l", "", CriticalLvl, "c", false}, {"[%l]", "", TraceLvl, "[t]", false}, {"[%l]", "abc", DebugLvl, "[d]", false}, {"%Level%Msg", "", TraceLvl, "Trace", false}, {"%Level%Msg", "A", DebugLvl, "DebugA", false}, {"%Level%Msg", "", InfoLvl, "Info", false}, {"%Level%Msg", "test", WarnLvl, "Warntest", false}, {"%Level%Msg", " ", ErrorLvl, "Error ", false}, {"%Level%Msg", "", CriticalLvl, "Critical", false}, {"[%Level]", "", TraceLvl, "[Trace]", false}, {"[%Level]", "abc", DebugLvl, "[Debug]", false}, {"%Level%MsgLevel", "A", InfoLvl, "InfoALevel", false}, {"[%Level]%Msg[%Level]", "test", WarnLvl, "[Warn]test[Warn]", false}, {"[%Level]%MsgX[%Level]", "test", ErrorLvl, "[Error]testX[Error]", false}, {"%Levell%Msgl", "Test", CriticalLvl, "CriticallTestl", false}, {"%Lev%Msg%LEVEL%LEV%l%Msg", "Test", InfoLvl, "InfTestINFOINFiTest", false}, {"%n", "", CriticalLvl, "\n", false}, {"%t", "", CriticalLvl, "\t", false}, } func TestFormats(t *testing.T) { context, conErr := currentContext() if conErr != nil { t.Fatal("Cannot get current context:" + conErr.Error()) return } for _, test := range formatTests { form, err := newFormatter(test.formatString) if (err != nil) != test.errorExpected { t.Errorf("input: %s \nInput LL: %s\n* Expected error:%t Got error: %t\n", test.input, test.inputLogLevel, test.errorExpected, (err != nil)) if err != nil { t.Logf("%s\n", err.Error()) } continue } else if err != nil { continue } msg := form.Format(test.input, test.inputLogLevel, context) if err == nil && msg != test.expectedOutput { t.Errorf("format: %s \nInput: %s \nInput LL: %s\n* Expected: %s \n* Got: %s\n", test.formatString, test.input, test.inputLogLevel, test.expectedOutput, msg) } } } func TestDateFormat(t *testing.T) { _, err := newFormatter("%Date") if err != nil { t.Error("Unexpected error: " + err.Error()) } } func TestDateParameterizedFormat(t *testing.T) { testFormat := "Mon Jan 02 2006 15:04:05" preciseForamt := "Mon Jan 02 2006 15:04:05.000" context, conErr := currentContext() if conErr != nil { t.Fatal("Cannot get current context:" + conErr.Error()) return } form, err := newFormatter("%Date(" + preciseForamt + ")") if err != nil { t.Error("Unexpected error: " + err.Error()) } dateBefore := time.Now().Format(testFormat) msg := form.Format("", TraceLvl, context) dateAfter := time.Now().Format(testFormat) if !strings.HasPrefix(msg, dateBefore) && !strings.HasPrefix(msg, dateAfter) { t.Errorf("incorrect message: %v. Expected %v or %v", msg, dateBefore, dateAfter) } _, err = newFormatter("%Date(" + preciseForamt) if err == nil { t.Error("Expected error for invalid format") } } func createTestFormatter(format string) FormatterFunc { return func(message string, level LogLevel, context LogContextInterface) interface{} { return "TEST " + context.Func() + " TEST" } } func TestCustomFormatterRegistration(t *testing.T) { err := RegisterCustomFormatter("Level", createTestFormatter) if err == nil { t.Errorf("expected an error when trying to register a custom formatter with a reserved alias") } err = RegisterCustomFormatter("EscM", createTestFormatter) if err == nil { t.Errorf("expected an error when trying to register a custom formatter with a reserved parameterized alias") } err = RegisterCustomFormatter("TEST", createTestFormatter) if err != nil { t.Fatalf("Registering custom formatter: unexpected error: %s", err) } err = RegisterCustomFormatter("TEST", createTestFormatter) if err == nil { t.Errorf("expected an error when trying to register a custom formatter with duplicate name") } context, conErr := currentContext() if conErr != nil { t.Fatal("Cannot get current context:" + conErr.Error()) return } form, err := newFormatter("%Msg %TEST 123") if err != nil { t.Fatalf("%s\n", err.Error()) } expected := fmt.Sprintf("test TEST %sTestCustomFormatterRegistration TEST 123", commonPrefix) msg := form.Format("test", DebugLvl, context) if msg != expected { t.Fatalf("Custom formatter: invalid output. Expected: '%s'. Got: '%s'", expected, msg) } }