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