1// Copyright (c) 2012 - Cloud Instruments Co., Ltd. 2// 3// All rights reserved. 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are met: 7// 8// 1. Redistributions of source code must retain the above copyright notice, this 9// list of conditions and the following disclaimer. 10// 2. Redistributions in binary form must reproduce the above copyright notice, 11// this list of conditions and the following disclaimer in the documentation 12// and/or other materials provided with the distribution. 13// 14// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 25package seelog 26 27import ( 28 "fmt" 29 "strings" 30 "testing" 31 "time" 32) 33 34const ( 35 TestFuncName = "TestFormats" 36) 37 38type formatTest struct { 39 formatString string 40 input string 41 inputLogLevel LogLevel 42 expectedOutput string 43 errorExpected bool 44} 45 46var formatTests = []formatTest{ 47 {"test", "abcdef", TraceLvl, "test", false}, 48 {"", "abcdef", TraceLvl, "", false}, 49 {"%Level", "", TraceLvl, "Trace", false}, 50 {"%Level", "", DebugLvl, "Debug", false}, 51 {"%Level", "", InfoLvl, "Info", false}, 52 {"%Level", "", WarnLvl, "Warn", false}, 53 {"%Level", "", ErrorLvl, "Error", false}, 54 {"%Level", "", CriticalLvl, "Critical", false}, 55 {"[%Level]", "", TraceLvl, "[Trace]", false}, 56 {"[%Level]", "abc", DebugLvl, "[Debug]", false}, 57 {"%LevelLevel", "", InfoLvl, "InfoLevel", false}, 58 {"[%Level][%Level]", "", WarnLvl, "[Warn][Warn]", false}, 59 {"[%Level]X[%Level]", "", ErrorLvl, "[Error]X[Error]", false}, 60 {"%Levelll", "", CriticalLvl, "Criticalll", false}, 61 {"%Lvl", "", TraceLvl, "", true}, 62 {"%%Level", "", DebugLvl, "%Level", false}, 63 {"%Level%", "", InfoLvl, "", true}, 64 {"%sevel", "", WarnLvl, "", true}, 65 {"Level", "", ErrorLvl, "Level", false}, 66 {"%LevelLevel", "", CriticalLvl, "CriticalLevel", false}, 67 {"%Lev", "", TraceLvl, "Trc", false}, 68 {"%Lev", "", DebugLvl, "Dbg", false}, 69 {"%Lev", "", InfoLvl, "Inf", false}, 70 {"%Lev", "", WarnLvl, "Wrn", false}, 71 {"%Lev", "", ErrorLvl, "Err", false}, 72 {"%Lev", "", CriticalLvl, "Crt", false}, 73 {"[%Lev]", "", TraceLvl, "[Trc]", false}, 74 {"[%Lev]", "abc", DebugLvl, "[Dbg]", false}, 75 {"%LevLevel", "", InfoLvl, "InfLevel", false}, 76 {"[%Level][%Lev]", "", WarnLvl, "[Warn][Wrn]", false}, 77 {"[%Lev]X[%Lev]", "", ErrorLvl, "[Err]X[Err]", false}, 78 {"%Levll", "", CriticalLvl, "Crtll", false}, 79 {"%LEVEL", "", TraceLvl, "TRACE", false}, 80 {"%LEVEL", "", DebugLvl, "DEBUG", false}, 81 {"%LEVEL", "", InfoLvl, "INFO", false}, 82 {"%LEVEL", "", WarnLvl, "WARN", false}, 83 {"%LEVEL", "", ErrorLvl, "ERROR", false}, 84 {"%LEVEL", "", CriticalLvl, "CRITICAL", false}, 85 {"[%LEVEL]", "", TraceLvl, "[TRACE]", false}, 86 {"[%LEVEL]", "abc", DebugLvl, "[DEBUG]", false}, 87 {"%LEVELLEVEL", "", InfoLvl, "INFOLEVEL", false}, 88 {"[%LEVEL][%LEVEL]", "", WarnLvl, "[WARN][WARN]", false}, 89 {"[%LEVEL]X[%Level]", "", ErrorLvl, "[ERROR]X[Error]", false}, 90 {"%LEVELLL", "", CriticalLvl, "CRITICALLL", false}, 91 {"%LEV", "", TraceLvl, "TRC", false}, 92 {"%LEV", "", DebugLvl, "DBG", false}, 93 {"%LEV", "", InfoLvl, "INF", false}, 94 {"%LEV", "", WarnLvl, "WRN", false}, 95 {"%LEV", "", ErrorLvl, "ERR", false}, 96 {"%LEV", "", CriticalLvl, "CRT", false}, 97 {"[%LEV]", "", TraceLvl, "[TRC]", false}, 98 {"[%LEV]", "abc", DebugLvl, "[DBG]", false}, 99 {"%LEVLEVEL", "", InfoLvl, "INFLEVEL", false}, 100 {"[%LEVEL][%LEV]", "", WarnLvl, "[WARN][WRN]", false}, 101 {"[%LEV]X[%LEV]", "", ErrorLvl, "[ERR]X[ERR]", false}, 102 {"%LEVLL", "", CriticalLvl, "CRTLL", false}, 103 {"%l", "", TraceLvl, "t", false}, 104 {"%l", "", DebugLvl, "d", false}, 105 {"%l", "", InfoLvl, "i", false}, 106 {"%l", "", WarnLvl, "w", false}, 107 {"%l", "", ErrorLvl, "e", false}, 108 {"%l", "", CriticalLvl, "c", false}, 109 {"[%l]", "", TraceLvl, "[t]", false}, 110 {"[%l]", "abc", DebugLvl, "[d]", false}, 111 {"%Level%Msg", "", TraceLvl, "Trace", false}, 112 {"%Level%Msg", "A", DebugLvl, "DebugA", false}, 113 {"%Level%Msg", "", InfoLvl, "Info", false}, 114 {"%Level%Msg", "test", WarnLvl, "Warntest", false}, 115 {"%Level%Msg", " ", ErrorLvl, "Error ", false}, 116 {"%Level%Msg", "", CriticalLvl, "Critical", false}, 117 {"[%Level]", "", TraceLvl, "[Trace]", false}, 118 {"[%Level]", "abc", DebugLvl, "[Debug]", false}, 119 {"%Level%MsgLevel", "A", InfoLvl, "InfoALevel", false}, 120 {"[%Level]%Msg[%Level]", "test", WarnLvl, "[Warn]test[Warn]", false}, 121 {"[%Level]%MsgX[%Level]", "test", ErrorLvl, "[Error]testX[Error]", false}, 122 {"%Levell%Msgl", "Test", CriticalLvl, "CriticallTestl", false}, 123 {"%Lev%Msg%LEVEL%LEV%l%Msg", "Test", InfoLvl, "InfTestINFOINFiTest", false}, 124 {"%r", "", CriticalLvl, "\r", false}, 125 {"%n", "", CriticalLvl, "\n", false}, 126 {"%t", "", CriticalLvl, "\t", false}, 127} 128 129func TestFormats(t *testing.T) { 130 131 context, conErr := currentContext(nil) 132 if conErr != nil { 133 t.Fatal("Cannot get current context:" + conErr.Error()) 134 return 135 } 136 137 for _, test := range formatTests { 138 139 form, err := NewFormatter(test.formatString) 140 141 if (err != nil) != test.errorExpected { 142 t.Errorf("input: %s \nInput LL: %s\n* Expected error:%t Got error: %t\n", 143 test.input, test.inputLogLevel, test.errorExpected, (err != nil)) 144 if err != nil { 145 t.Logf("%s\n", err.Error()) 146 } 147 continue 148 } else if err != nil { 149 continue 150 } 151 152 msg := form.Format(test.input, test.inputLogLevel, context) 153 154 if err == nil && msg != test.expectedOutput { 155 t.Errorf("format: %s \nInput: %s \nInput LL: %s\n* Expected: %s \n* Got: %s\n", 156 test.formatString, test.input, test.inputLogLevel, test.expectedOutput, msg) 157 } 158 } 159} 160 161func TestDateFormat(t *testing.T) { 162 _, err := NewFormatter("%Date") 163 if err != nil { 164 t.Error("Unexpected error: " + err.Error()) 165 } 166} 167 168func TestDateParameterizedFormat(t *testing.T) { 169 testFormat := "Mon Jan 02 2006 15:04:05" 170 preciseForamt := "Mon Jan 02 2006 15:04:05.000" 171 172 context, conErr := currentContext(nil) 173 if conErr != nil { 174 t.Fatal("Cannot get current context:" + conErr.Error()) 175 return 176 } 177 178 form, err := NewFormatter("%Date(" + preciseForamt + ")") 179 if err != nil { 180 t.Error("Unexpected error: " + err.Error()) 181 } 182 183 dateBefore := time.Now().Format(testFormat) 184 msg := form.Format("", TraceLvl, context) 185 dateAfter := time.Now().Format(testFormat) 186 187 if !strings.HasPrefix(msg, dateBefore) && !strings.HasPrefix(msg, dateAfter) { 188 t.Errorf("incorrect message: %v. Expected %v or %v", msg, dateBefore, dateAfter) 189 } 190 191 _, err = NewFormatter("%Date(" + preciseForamt) 192 if err == nil { 193 t.Error("Expected error for invalid format") 194 } 195} 196 197func createTestFormatter(format string) FormatterFunc { 198 return func(message string, level LogLevel, context LogContextInterface) interface{} { 199 return "TEST " + context.Func() + " TEST" 200 } 201} 202 203func TestCustomFormatterRegistration(t *testing.T) { 204 err := RegisterCustomFormatter("Level", createTestFormatter) 205 if err == nil { 206 t.Errorf("expected an error when trying to register a custom formatter with a reserved alias") 207 } 208 err = RegisterCustomFormatter("EscM", createTestFormatter) 209 if err == nil { 210 t.Errorf("expected an error when trying to register a custom formatter with a reserved parameterized alias") 211 } 212 err = RegisterCustomFormatter("TEST", createTestFormatter) 213 if err != nil { 214 t.Fatalf("Registering custom formatter: unexpected error: %s", err) 215 } 216 err = RegisterCustomFormatter("TEST", createTestFormatter) 217 if err == nil { 218 t.Errorf("expected an error when trying to register a custom formatter with duplicate name") 219 } 220 221 context, conErr := currentContext(nil) 222 if conErr != nil { 223 t.Fatal("Cannot get current context:" + conErr.Error()) 224 return 225 } 226 227 form, err := NewFormatter("%Msg %TEST 123") 228 if err != nil { 229 t.Fatalf("%s\n", err.Error()) 230 } 231 232 expected := fmt.Sprintf("test TEST %sTestCustomFormatterRegistration TEST 123", commonPrefix) 233 msg := form.Format("test", DebugLvl, context) 234 if msg != expected { 235 t.Fatalf("Custom formatter: invalid output. Expected: '%s'. Got: '%s'", expected, msg) 236 } 237} 238