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	"path/filepath"
30	"regexp"
31	"strings"
32	"testing"
33)
34
35type customTestReceiverOutput struct {
36	initCalled    bool
37	dataPassed    string
38	messageOutput string
39	levelOutput   LogLevel
40	closed        bool
41	flushed       bool
42}
43type customTestReceiver struct{ co *customTestReceiverOutput }
44
45func (cr *customTestReceiver) ReceiveMessage(message string, level LogLevel, context LogContextInterface) error {
46	cr.co.messageOutput = message
47	cr.co.levelOutput = level
48	return nil
49}
50
51func (cr *customTestReceiver) String() string {
52	return fmt.Sprintf("custom data='%s'", cr.co.dataPassed)
53}
54
55func (cr *customTestReceiver) AfterParse(initArgs CustomReceiverInitArgs) error {
56	cr.co = new(customTestReceiverOutput)
57	cr.co.initCalled = true
58	cr.co.dataPassed = initArgs.XmlCustomAttrs["test"]
59	return nil
60}
61
62func (cr *customTestReceiver) Flush() {
63	cr.co.flushed = true
64}
65
66func (cr *customTestReceiver) Close() error {
67	cr.co.closed = true
68	return nil
69}
70
71var re = regexp.MustCompile(`[^a-zA-Z0-9]+`)
72
73func getTestFileName(testName, postfix string) string {
74	if len(postfix) != 0 {
75		return strings.ToLower(re.ReplaceAllString(testName, "_")) + "_" + postfix + "_test.log"
76	}
77	return strings.ToLower(re.ReplaceAllString(testName, "_")) + "_test.log"
78}
79
80var parserTests []parserTest
81
82type parserTest struct {
83	testName      string
84	config        string
85	expected      *configForParsing //interface{}
86	errorExpected bool
87	parserConfig  *CfgParseParams
88}
89
90func getParserTests() []parserTest {
91	if parserTests == nil {
92		parserTests = make([]parserTest, 0)
93
94		testName := "Simple file output"
95		testLogFileName := getTestFileName(testName, "")
96		testConfig := `
97		<seelog>
98			<outputs>
99				<file path="` + testLogFileName + `"/>
100			</outputs>
101		</seelog>
102		`
103		testExpected := new(configForParsing)
104		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
105		testExpected.Exceptions = nil
106		testfileWriter, _ := NewFileWriter(testLogFileName)
107		testHeadSplitter, _ := NewSplitDispatcher(DefaultFormatter, []interface{}{testfileWriter})
108		testExpected.LogType = asyncLooploggerTypeFromString
109		testExpected.RootDispatcher = testHeadSplitter
110		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
111
112		testName = "Filter dispatcher"
113		testLogFileName = getTestFileName(testName, "")
114		testConfig = `
115		<seelog type="sync">
116			<outputs>
117				<filter levels="debug, info, critical">
118					<file path="` + testLogFileName + `"/>
119				</filter>
120			</outputs>
121		</seelog>
122		`
123		testExpected = new(configForParsing)
124		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
125		testExpected.Exceptions = nil
126		testfileWriter, _ = NewFileWriter(testLogFileName)
127		testFilter, _ := NewFilterDispatcher(DefaultFormatter, []interface{}{testfileWriter}, DebugLvl, InfoLvl, CriticalLvl)
128		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testFilter})
129		testExpected.LogType = syncloggerTypeFromString
130		testExpected.RootDispatcher = testHeadSplitter
131		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
132
133		testName = "Console writer"
134		testConfig = `
135		<seelog type="sync">
136			<outputs>
137				<console />
138			</outputs>
139		</seelog>
140		`
141		testExpected = new(configForParsing)
142		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
143		testExpected.Exceptions = nil
144		testconsoleWriter, _ := NewConsoleWriter()
145		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testconsoleWriter})
146		testExpected.LogType = syncloggerTypeFromString
147		testExpected.RootDispatcher = testHeadSplitter
148		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
149
150		testName = "SMTP writer"
151		testConfig = `
152<seelog>
153	<outputs>
154		<smtp senderaddress="sa" sendername="sn"  hostname="hn" hostport="123" username="un" password="up">
155			<recipient address="ra1"/>
156			<recipient address="ra2"/>
157			<recipient address="ra3"/>
158			<cacertdirpath path="cacdp1"/>
159			<cacertdirpath path="cacdp2"/>
160		</smtp>
161	</outputs>
162</seelog>
163		`
164
165		testExpected = new(configForParsing)
166		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
167		testExpected.Exceptions = nil
168		testSMTPWriter := NewSMTPWriter(
169			"sa",
170			"sn",
171			[]string{"ra1", "ra2", "ra3"},
172			"hn",
173			"123",
174			"un",
175			"up",
176			[]string{"cacdp1", "cacdp2"},
177			DefaultSubjectPhrase,
178			nil,
179		)
180		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testSMTPWriter})
181		testExpected.LogType = asyncLooploggerTypeFromString
182		testExpected.RootDispatcher = testHeadSplitter
183		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
184
185		testName = "SMTP writer custom header and subject configuration"
186		testConfig = `
187<seelog>
188	<outputs>
189		<smtp senderaddress="sa" sendername="sn"  hostname="hn" hostport="123" username="un" password="up" subject="ohlala">
190			<recipient address="ra1"/>
191			<cacertdirpath path="cacdp1"/>
192			<header name="Priority" value="Urgent" />
193			<header name="Importance" value="high" />
194			<header name="Sensitivity" value="Company-Confidential" />
195			<header name="Auto-Submitted" value="auto-generated" />
196		</smtp>
197	</outputs>
198</seelog>
199		`
200		testExpected = new(configForParsing)
201		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
202		testExpected.Exceptions = nil
203		testSMTPWriter = NewSMTPWriter(
204			"sa",
205			"sn",
206			[]string{"ra1"},
207			"hn",
208			"123",
209			"un",
210			"up",
211			[]string{"cacdp1"},
212			"ohlala",
213			[]string{"Priority: Urgent", "Importance: high", "Sensitivity: Company-Confidential", "Auto-Submitted: auto-generated"},
214		)
215		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testSMTPWriter})
216		testExpected.LogType = asyncLooploggerTypeFromString
217		testExpected.RootDispatcher = testHeadSplitter
218		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
219
220		testName = "Default output"
221		testConfig = `
222		<seelog type="sync"/>
223		`
224		testExpected = new(configForParsing)
225		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
226		testExpected.Exceptions = nil
227		testconsoleWriter, _ = NewConsoleWriter()
228		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testconsoleWriter})
229		testExpected.LogType = syncloggerTypeFromString
230		testExpected.RootDispatcher = testHeadSplitter
231		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
232
233		testName = "Asyncloop behavior"
234		testConfig = `
235		<seelog type="asyncloop"/>
236		`
237		testExpected = new(configForParsing)
238		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
239		testExpected.Exceptions = nil
240		testconsoleWriter, _ = NewConsoleWriter()
241		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testconsoleWriter})
242		testExpected.LogType = asyncLooploggerTypeFromString
243		testExpected.RootDispatcher = testHeadSplitter
244		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
245
246		testName = "Asynctimer behavior"
247		testConfig = `
248		<seelog type="asynctimer" asyncinterval="101"/>
249		`
250		testExpected = new(configForParsing)
251		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
252		testExpected.Exceptions = nil
253		testconsoleWriter, _ = NewConsoleWriter()
254		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testconsoleWriter})
255		testExpected.LogType = asyncTimerloggerTypeFromString
256		testExpected.LoggerData = asyncTimerLoggerData{101}
257		testExpected.RootDispatcher = testHeadSplitter
258		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
259
260		testName = "Rolling file writer size"
261		testLogFileName = getTestFileName(testName, "")
262		testConfig = `
263		<seelog type="sync">
264			<outputs>
265				<rollingfile type="size" filename="` + testLogFileName + `" maxsize="100" maxrolls="5" />
266			</outputs>
267		</seelog>
268		`
269		testExpected = new(configForParsing)
270		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
271		testExpected.Exceptions = nil
272		testrollingFileWriter, _ := NewRollingFileWriterSize(testLogFileName, rollingArchiveNone, "", 100, 5, rollingNameModePostfix, false)
273		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testrollingFileWriter})
274		testExpected.LogType = syncloggerTypeFromString
275		testExpected.RootDispatcher = testHeadSplitter
276		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
277
278		testName = "Rolling file writer archive gzip"
279		testLogFileName = getTestFileName(testName, "")
280		testConfig = `
281		<seelog type="sync">
282			<outputs>
283				<rollingfile type="size" filename="` + testLogFileName + `" maxsize="100" maxrolls="5" archivetype="gzip"/>
284			</outputs>
285		</seelog>`
286		testExpected = new(configForParsing)
287		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
288		testExpected.Exceptions = nil
289		testrollingFileWriter, _ = NewRollingFileWriterSize(testLogFileName, rollingArchiveGzip, "log.tar.gz", 100, 5, rollingNameModePostfix, false)
290		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testrollingFileWriter})
291		testExpected.LogType = syncloggerTypeFromString
292		testExpected.RootDispatcher = testHeadSplitter
293		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
294
295		testName = "Rolling file writer archive zip"
296		testLogFileName = getTestFileName(testName, "")
297		testConfig = `
298		<seelog type="sync">
299			<outputs>
300				<rollingfile type="size" filename="` + testLogFileName + `" maxsize="100" maxrolls="5" archivetype="zip"/>
301			</outputs>
302		</seelog>`
303		testExpected = new(configForParsing)
304		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
305		testExpected.Exceptions = nil
306		testrollingFileWriter, _ = NewRollingFileWriterSize(testLogFileName, rollingArchiveZip, "log.zip", 100, 5, rollingNameModePostfix, false)
307		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testrollingFileWriter})
308		testExpected.LogType = syncloggerTypeFromString
309		testExpected.RootDispatcher = testHeadSplitter
310		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
311
312		testName = "Rolling file writer archive zip with specified path"
313		testLogFileName = getTestFileName(testName, "")
314		testConfig = `
315		<seelog type="sync">
316			<outputs>
317				<rollingfile namemode="prefix" type="size" filename="` + testLogFileName + `" maxsize="100" maxrolls="5" archivetype="zip" archivepath="test.zip"/>
318			</outputs>
319		</seelog>`
320		testExpected = new(configForParsing)
321		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
322		testExpected.Exceptions = nil
323		testrollingFileWriter, _ = NewRollingFileWriterSize(testLogFileName, rollingArchiveZip, "test.zip", 100, 5, rollingNameModePrefix, false)
324		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testrollingFileWriter})
325		testExpected.LogType = syncloggerTypeFromString
326		testExpected.RootDispatcher = testHeadSplitter
327		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
328
329		testName = "Rolling file writer archive zip exploded"
330		testLogFileName = getTestFileName(testName, "")
331		testConfig = `
332		<seelog type="sync">
333			<outputs>
334				<rollingfile type="size" filename="` + testLogFileName + `" maxsize="100" maxrolls="5" archivetype="zip" archiveexploded="true"/>
335			</outputs>
336		</seelog>`
337		testExpected = new(configForParsing)
338		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
339		testExpected.Exceptions = nil
340		testrollingFileWriter, _ = NewRollingFileWriterSize(testLogFileName, rollingArchiveZip, "old", 100, 5, rollingNameModePostfix, true)
341		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testrollingFileWriter})
342		testExpected.LogType = syncloggerTypeFromString
343		testExpected.RootDispatcher = testHeadSplitter
344		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
345
346		testName = "Rolling file writer archive zip exploded with specified path"
347		testLogFileName = getTestFileName(testName, "")
348		testConfig = `
349		<seelog type="sync">
350			<outputs>
351				<rollingfile namemode="prefix" type="size" filename="` + testLogFileName + `" maxsize="100" maxrolls="5" archivetype="zip" archiveexploded="true" archivepath="test_old_logs"/>
352			</outputs>
353		</seelog>`
354		testExpected = new(configForParsing)
355		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
356		testExpected.Exceptions = nil
357		testrollingFileWriter, _ = NewRollingFileWriterSize(testLogFileName, rollingArchiveZip, "test_old_logs", 100, 5, rollingNameModePrefix, true)
358		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testrollingFileWriter})
359		testExpected.LogType = syncloggerTypeFromString
360		testExpected.RootDispatcher = testHeadSplitter
361		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
362
363		testName = "Rolling file writer archive none"
364		testLogFileName = getTestFileName(testName, "")
365		testConfig = `
366		<seelog type="sync">
367			<outputs>
368				<rollingfile namemode="postfix" type="size" filename="` + testLogFileName + `" maxsize="100" maxrolls="5" archivetype="none"/>
369			</outputs>
370		</seelog>`
371		testExpected = new(configForParsing)
372		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
373		testExpected.Exceptions = nil
374		testrollingFileWriter, _ = NewRollingFileWriterSize(testLogFileName, rollingArchiveNone, "", 100, 5, rollingNameModePostfix, false)
375		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testrollingFileWriter})
376		testExpected.LogType = syncloggerTypeFromString
377		testExpected.RootDispatcher = testHeadSplitter
378		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
379
380		testName = "Rolling file writer date"
381		testLogFileName = getTestFileName(testName, "")
382		testConfig = `
383		<seelog type="sync">
384			<outputs>
385				<rollingfile type="date" filename="` + testLogFileName + `" datepattern="2006-01-02T15:04:05Z07:00" />
386			</outputs>
387		</seelog>`
388		testExpected = new(configForParsing)
389		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
390		testExpected.Exceptions = nil
391		testrollingFileWriterTime, _ := NewRollingFileWriterTime(testLogFileName, rollingArchiveNone, "", 0, "2006-01-02T15:04:05Z07:00", rollingNameModePostfix, false, false)
392		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testrollingFileWriterTime})
393		testExpected.LogType = syncloggerTypeFromString
394		testExpected.RootDispatcher = testHeadSplitter
395		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
396
397		testName = "Buffered writer"
398		testLogFileName = getTestFileName(testName, "")
399		testConfig = `
400		<seelog type="sync">
401			<outputs>
402				<buffered size="100500" flushperiod="100">
403					<rollingfile type="date" filename="` + testLogFileName + `" datepattern="2006-01-02T15:04:05Z07:00" />
404				</buffered>
405			</outputs>
406		</seelog>`
407		testExpected = new(configForParsing)
408		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
409		testExpected.Exceptions = nil
410		testrollingFileWriterTime, _ = NewRollingFileWriterTime(testLogFileName, rollingArchiveNone, "", 0, "2006-01-02T15:04:05Z07:00", rollingNameModePostfix, false, false)
411		testbufferedWriter, _ := NewBufferedWriter(testrollingFileWriterTime, 100500, 100)
412		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testbufferedWriter})
413		testExpected.LogType = syncloggerTypeFromString
414		testExpected.RootDispatcher = testHeadSplitter
415		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
416
417		testName = "Inner splitter output"
418		testLogFileName1 := getTestFileName(testName, "1")
419		testLogFileName2 := getTestFileName(testName, "2")
420		testLogFileName3 := getTestFileName(testName, "3")
421		testConfig = `
422		<seelog type="sync">
423			<outputs>
424				<file path="` + testLogFileName1 + `"/>
425				<splitter>
426					<file path="` + testLogFileName2 + `"/>
427					<file path="` + testLogFileName3 + `"/>
428				</splitter>
429			</outputs>
430		</seelog>
431		`
432		testExpected = new(configForParsing)
433		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
434		testExpected.Exceptions = nil
435		testfileWriter1, _ := NewFileWriter(testLogFileName2)
436		testfileWriter2, _ := NewFileWriter(testLogFileName3)
437		testInnerSplitter, _ := NewSplitDispatcher(DefaultFormatter, []interface{}{testfileWriter1, testfileWriter2})
438		testfileWriter, _ = NewFileWriter(testLogFileName1)
439		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testfileWriter, testInnerSplitter})
440		testExpected.LogType = syncloggerTypeFromString
441		testExpected.RootDispatcher = testHeadSplitter
442		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
443
444		RegisterReceiver("custom-name-1", &customTestReceiver{})
445
446		testName = "Custom receiver 1"
447		testConfig = `
448		<seelog type="sync">
449			<outputs>
450				<custom name="custom-name-1" data-test="set"/>
451			</outputs>
452		</seelog>
453		`
454		testExpected = new(configForParsing)
455		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
456		testExpected.Exceptions = nil
457		testCustomReceiver, _ := NewCustomReceiverDispatcher(DefaultFormatter, "custom-name-1", CustomReceiverInitArgs{
458			XmlCustomAttrs: map[string]string{
459				"test": "set",
460			},
461		})
462		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testCustomReceiver})
463		testExpected.LogType = syncloggerTypeFromString
464		testExpected.RootDispatcher = testHeadSplitter
465		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
466
467		testName = "Custom receiver 2"
468		testConfig = `
469		<seelog type="sync">
470			<outputs>
471				<custom name="custom-name-2" data-test="set2"/>
472			</outputs>
473		</seelog>
474		`
475		testExpected = new(configForParsing)
476		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
477		testExpected.Exceptions = nil
478		crec := &customTestReceiver{}
479		cargs := CustomReceiverInitArgs{
480			XmlCustomAttrs: map[string]string{
481				"test": "set2",
482			},
483		}
484		crec.AfterParse(cargs)
485		testCustomReceiver2, _ := NewCustomReceiverDispatcherByValue(DefaultFormatter, crec, "custom-name-2", cargs)
486		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testCustomReceiver2})
487		testExpected.LogType = syncloggerTypeFromString
488		testExpected.RootDispatcher = testHeadSplitter
489		fnc := func(initArgs CustomReceiverInitArgs) (CustomReceiver, error) {
490			return &customTestReceiver{}, nil
491		}
492		cfg := CfgParseParams{
493			CustomReceiverProducers: map[string]CustomReceiverProducer{
494				"custom-name-2": CustomReceiverProducer(fnc),
495			},
496		}
497		testExpected.Params = &cfg
498		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, &cfg})
499
500		RegisterReceiver("-", &customTestReceiver{})
501		testName = "Custom receiver 3"
502		testConfig = `
503		<seelog type="sync">
504			<outputs>
505				<custom name="-" data-test="set3"/>
506			</outputs>
507		</seelog>
508		`
509		testExpected = new(configForParsing)
510		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
511		testExpected.Exceptions = nil
512		creccustom := &customTestReceiver{}
513		cargs3 := CustomReceiverInitArgs{
514			XmlCustomAttrs: map[string]string{
515				"test": "set3",
516			},
517		}
518		creccustom.AfterParse(cargs3)
519		testCustomReceiver, _ = NewCustomReceiverDispatcherByValue(DefaultFormatter, creccustom, "-", cargs3)
520		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testCustomReceiver})
521		testExpected.LogType = syncloggerTypeFromString
522		testExpected.RootDispatcher = testHeadSplitter
523		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
524
525		testName = "Custom receivers with formats"
526		testConfig = `
527		<seelog type="sync">
528			<outputs>
529				<custom name="custom-name-1" data-test="set1"/>
530				<custom name="custom-name-1" data-test="set2"/>
531				<custom name="custom-name-1" data-test="set3"/>
532			</outputs>
533		</seelog>
534		`
535		testExpected = new(configForParsing)
536		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
537		testExpected.Exceptions = nil
538		testCustomReceivers := make([]*customReceiverDispatcher, 3)
539		for i := 0; i < 3; i++ {
540			testCustomReceivers[i], _ = NewCustomReceiverDispatcher(DefaultFormatter, "custom-name-1", CustomReceiverInitArgs{
541				XmlCustomAttrs: map[string]string{
542					"test": fmt.Sprintf("set%d", i+1),
543				},
544			})
545		}
546
547		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testCustomReceivers[0], testCustomReceivers[1], testCustomReceivers[2]})
548		testExpected.LogType = syncloggerTypeFromString
549		testExpected.RootDispatcher = testHeadSplitter
550		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
551
552		testName = "Format"
553		testLogFileName = getTestFileName(testName, "")
554		testConfig = `
555		<seelog type="sync">
556			<outputs formatid="dateFormat">
557				<file path="` + testLogFileName + `"/>
558			</outputs>
559			<formats>
560				<format id="dateFormat" format="%Level %Msg %File" />
561			</formats>
562		</seelog>
563		`
564		testExpected = new(configForParsing)
565		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
566		testExpected.Exceptions = nil
567		testfileWriter, _ = NewFileWriter(testLogFileName)
568		testFormat, _ := NewFormatter("%Level %Msg %File")
569		testHeadSplitter, _ = NewSplitDispatcher(testFormat, []interface{}{testfileWriter})
570		testExpected.LogType = syncloggerTypeFromString
571		testExpected.RootDispatcher = testHeadSplitter
572		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
573
574		testName = "Format2"
575		testLogFileName = getTestFileName(testName, "")
576		testLogFileName1 = getTestFileName(testName, "1")
577		testConfig = `
578		<seelog type="sync">
579			<outputs formatid="format1">
580				<file path="` + testLogFileName + `"/>
581				<file formatid="format2" path="` + testLogFileName1 + `"/>
582			</outputs>
583			<formats>
584				<format id="format1" format="%Level %Msg %File" />
585				<format id="format2" format="%l %Msg" />
586			</formats>
587		</seelog>
588		`
589		testExpected = new(configForParsing)
590		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
591		testExpected.Exceptions = nil
592		testfileWriter, _ = NewFileWriter(testLogFileName)
593		testfileWriter1, _ = NewFileWriter(testLogFileName1)
594		testFormat1, _ := NewFormatter("%Level %Msg %File")
595		testFormat2, _ := NewFormatter("%l %Msg")
596		formattedWriter, _ := NewFormattedWriter(testfileWriter1, testFormat2)
597		testHeadSplitter, _ = NewSplitDispatcher(testFormat1, []interface{}{testfileWriter, formattedWriter})
598		testExpected.LogType = syncloggerTypeFromString
599		testExpected.RootDispatcher = testHeadSplitter
600		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
601
602		testName = "Minlevel = warn"
603		testConfig = `<seelog minlevel="warn"/>`
604		testExpected = new(configForParsing)
605		testExpected.Constraints, _ = NewMinMaxConstraints(WarnLvl, CriticalLvl)
606		testExpected.Exceptions = nil
607		testconsoleWriter, _ = NewConsoleWriter()
608		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testconsoleWriter})
609		testExpected.LogType = asyncLooploggerTypeFromString
610		testExpected.RootDispatcher = testHeadSplitter
611		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
612
613		testName = "Maxlevel = trace"
614		testConfig = `<seelog maxlevel="trace"/>`
615		testExpected = new(configForParsing)
616		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, TraceLvl)
617		testExpected.Exceptions = nil
618		testconsoleWriter, _ = NewConsoleWriter()
619		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testconsoleWriter})
620		testExpected.LogType = asyncLooploggerTypeFromString
621		testExpected.RootDispatcher = testHeadSplitter
622		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
623
624		testName = "Level between info and error"
625		testConfig = `<seelog minlevel="info" maxlevel="error"/>`
626		testExpected = new(configForParsing)
627		testExpected.Constraints, _ = NewMinMaxConstraints(InfoLvl, ErrorLvl)
628		testExpected.Exceptions = nil
629		testconsoleWriter, _ = NewConsoleWriter()
630		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testconsoleWriter})
631		testExpected.LogType = asyncLooploggerTypeFromString
632		testExpected.RootDispatcher = testHeadSplitter
633		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
634
635		testName = "Off with minlevel"
636		testConfig = `<seelog minlevel="off"/>`
637		testExpected = new(configForParsing)
638		testExpected.Constraints, _ = NewOffConstraints()
639		testExpected.Exceptions = nil
640		testconsoleWriter, _ = NewConsoleWriter()
641		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testconsoleWriter})
642		testExpected.LogType = asyncLooploggerTypeFromString
643		testExpected.RootDispatcher = testHeadSplitter
644		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
645
646		testName = "Off with levels"
647		testConfig = `<seelog levels="off"/>`
648		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
649
650		testName = "Levels list"
651		testConfig = `<seelog levels="debug, info, critical"/>`
652		testExpected = new(configForParsing)
653		testExpected.Constraints, _ = NewListConstraints([]LogLevel{
654			DebugLvl, InfoLvl, CriticalLvl})
655		testExpected.Exceptions = nil
656		testconsoleWriter, _ = NewConsoleWriter()
657		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testconsoleWriter})
658		testExpected.LogType = asyncLooploggerTypeFromString
659		testExpected.RootDispatcher = testHeadSplitter
660		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
661
662		testName = "Errors #1"
663		testConfig = `<seelog minlevel="debug" minlevel="trace"/>`
664		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
665
666		testName = "Errors #2"
667		testConfig = `<seelog minlevel="error" maxlevel="debug"/>`
668		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
669
670		testName = "Errors #3"
671		testConfig = `<seelog maxlevel="debug" maxlevel="trace"/>`
672		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
673
674		testName = "Errors #4"
675		testConfig = `<seelog maxlevel="off"/>`
676		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
677
678		testName = "Errors #5"
679		testConfig = `<seelog minlevel="off" maxlevel="trace"/>`
680		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
681
682		testName = "Errors #6"
683		testConfig = `<seelog minlevel="warn" maxlevel="error" levels="debug"/>`
684		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
685
686		testName = "Errors #7"
687		testConfig = `<not_seelog/>`
688		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
689
690		testName = "Errors #8"
691		testConfig = `<seelog levels="warn, debug, test"/>`
692		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
693
694		testName = "Errors #9"
695		testConfig = `<seelog levels=""/>`
696		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
697
698		testName = "Errors #10"
699		testConfig = `<seelog levels="off" something="abc"/>`
700		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
701
702		testName = "Errors #11"
703		testConfig = `<seelog><output/></seelog>`
704		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
705
706		testName = "Errors #12"
707		testConfig = `<seelog><outputs/><outputs/></seelog>`
708		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
709
710		testName = "Errors #13"
711		testConfig = `<seelog><exceptions/></seelog>`
712		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
713
714		testName = "Errors #14"
715		testConfig = `<seelog><formats/></seelog>`
716		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
717
718		testName = "Errors #15"
719		testConfig = `<seelog><outputs><splitter/></outputs></seelog>`
720		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
721
722		testName = "Errors #16"
723		testConfig = `<seelog><outputs><filter/></outputs></seelog>`
724		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
725
726		testName = "Errors #17"
727		testLogFileName = getTestFileName(testName, "")
728		testConfig = `<seelog><outputs><file path="` + testLogFileName + `"><something/></file></outputs></seelog>`
729		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
730
731		testName = "Errors #18"
732		testConfig = `<seelog><outputs><buffered size="100500" flushperiod="100"/></outputs></seelog>`
733		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
734
735		testName = "Errors #19"
736		testConfig = `<seelog><outputs></outputs></seelog>`
737		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
738
739		testName = "Exceptions: restricting"
740		testConfig =
741			`
742		<seelog type="sync">
743			<exceptions>
744				<exception funcpattern="Test*" filepattern="someFile.go" minlevel="off"/>
745			</exceptions>
746		</seelog>
747		`
748		testExpected = new(configForParsing)
749		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
750		listConstraint, _ := NewOffConstraints()
751		exception, _ := NewLogLevelException("Test*", "someFile.go", listConstraint)
752		testExpected.Exceptions = []*LogLevelException{exception}
753		testconsoleWriter, _ = NewConsoleWriter()
754		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testconsoleWriter})
755		testExpected.LogType = syncloggerTypeFromString
756		testExpected.RootDispatcher = testHeadSplitter
757		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
758
759		testName = "Exceptions: allowing #1"
760		testConfig =
761			`
762		<seelog type="sync" levels="error">
763			<exceptions>
764				<exception filepattern="testfile.go" minlevel="trace"/>
765			</exceptions>
766		</seelog>
767		`
768		testExpected = new(configForParsing)
769		testExpected.Constraints, _ = NewListConstraints([]LogLevel{ErrorLvl})
770		minMaxConstraint, _ := NewMinMaxConstraints(TraceLvl, CriticalLvl)
771		exception, _ = NewLogLevelException("*", "testfile.go", minMaxConstraint)
772		testExpected.Exceptions = []*LogLevelException{exception}
773		testconsoleWriter, _ = NewConsoleWriter()
774		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testconsoleWriter})
775		testExpected.LogType = syncloggerTypeFromString
776		testExpected.RootDispatcher = testHeadSplitter
777		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
778
779		testName = "Exceptions: allowing #2"
780		testConfig = `
781		<seelog type="sync" levels="off">
782			<exceptions>
783				<exception filepattern="testfile.go" minlevel="warn"/>
784			</exceptions>
785		</seelog>
786		`
787		testExpected = new(configForParsing)
788		testExpected.Constraints, _ = NewOffConstraints()
789		minMaxConstraint, _ = NewMinMaxConstraints(WarnLvl, CriticalLvl)
790		exception, _ = NewLogLevelException("*", "testfile.go", minMaxConstraint)
791		testExpected.Exceptions = []*LogLevelException{exception}
792		testconsoleWriter, _ = NewConsoleWriter()
793		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testconsoleWriter})
794		testExpected.LogType = syncloggerTypeFromString
795		testExpected.RootDispatcher = testHeadSplitter
796		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
797
798		testName = "Predefined formats"
799		formatID := predefinedPrefix + "xml-debug-short"
800		testConfig = `
801		<seelog type="sync">
802			<outputs formatid="` + formatID + `">
803				<console />
804			</outputs>
805		</seelog>`
806		testExpected = new(configForParsing)
807		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
808		testExpected.Exceptions = nil
809		testconsoleWriter, _ = NewConsoleWriter()
810		testFormat, _ = predefinedFormats[formatID]
811		testHeadSplitter, _ = NewSplitDispatcher(testFormat, []interface{}{testconsoleWriter})
812		testExpected.LogType = syncloggerTypeFromString
813		testExpected.RootDispatcher = testHeadSplitter
814		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
815
816		testName = "Predefined formats redefine"
817		testLogFileName = getTestFileName(testName, "")
818		formatID = predefinedPrefix + "xml-debug-short"
819		testConfig = `
820		<seelog type="sync">
821			<outputs formatid="` + formatID + `">
822				<file path="` + testLogFileName + `"/>
823			</outputs>
824			<formats>
825				<format id="` + formatID + `" format="%Level %Msg %File" />
826			</formats>
827		</seelog>`
828		testExpected = new(configForParsing)
829		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
830		testExpected.Exceptions = nil
831		testfileWriter, _ = NewFileWriter(testLogFileName)
832		testFormat, _ = NewFormatter("%Level %Msg %File")
833		testHeadSplitter, _ = NewSplitDispatcher(testFormat, []interface{}{testfileWriter})
834		testExpected.LogType = syncloggerTypeFromString
835		testExpected.RootDispatcher = testHeadSplitter
836		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
837
838		testName = "Conn writer 1"
839		testConfig = `
840		<seelog type="sync">
841			<outputs>
842				<conn net="tcp" addr=":8888" />
843			</outputs>
844		</seelog>`
845		testExpected = new(configForParsing)
846		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
847		testExpected.Exceptions = nil
848		testConnWriter := NewConnWriter("tcp", ":8888", false)
849		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testConnWriter})
850		testExpected.LogType = syncloggerTypeFromString
851		testExpected.RootDispatcher = testHeadSplitter
852		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
853
854		testName = "Conn writer 2"
855		testConfig = `
856		<seelog type="sync">
857			<outputs>
858				<conn net="tcp" addr=":8888" reconnectonmsg="true" />
859			</outputs>
860		</seelog>`
861		testExpected = new(configForParsing)
862		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
863		testExpected.Exceptions = nil
864		testConnWriter = NewConnWriter("tcp", ":8888", true)
865		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{testConnWriter})
866		testExpected.LogType = syncloggerTypeFromString
867		testExpected.RootDispatcher = testHeadSplitter
868		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
869
870		testName = "Errors #11"
871		testConfig = `
872		<seelog type="sync"><exceptions>
873				<exception filepattern="testfile.go" minlevel="trace"/>
874				<exception filepattern="testfile.go" minlevel="warn"/>
875		</exceptions></seelog>`
876		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
877
878		testName = "Errors #12"
879		testConfig = `
880		<seelog type="sync"><exceptions>
881				<exception filepattern="!@+$)!!%&@(^$" minlevel="trace"/>
882		</exceptions></seelog>`
883		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
884
885		testName = "Errors #13"
886		testConfig = `
887		<seelog type="sync"><exceptions>
888				<exception filepattern="*" minlevel="unknown"/>
889		</exceptions></seelog>`
890		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
891
892		testName = "Errors #14"
893		testConfig = `
894		<seelog type="sync" levels=”off”>
895			<exceptions>
896				<exception filepattern="testfile.go" minlevel="off"/>
897			</exceptions>
898		</seelog>
899		`
900		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
901
902		testName = "Errors #15"
903		testConfig = `
904		<seelog type="sync" levels=”trace”>
905			<exceptions>
906				<exception filepattern="testfile.go" levels="trace"/>
907			</exceptions>
908		</seelog>
909		`
910		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
911
912		testName = "Errors #16"
913		testConfig = `
914		<seelog type="sync" minlevel=”trace”>
915			<exceptions>
916				<exception filepattern="testfile.go" minlevel="trace"/>
917			</exceptions>
918		</seelog>
919		`
920		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
921
922		testName = "Errors #17"
923		testConfig = `
924		<seelog type="sync" minlevel=”trace”>
925			<exceptions>
926				<exception filepattern="testfile.go" minlevel="warn"/>
927			</exceptions>
928			<exceptions>
929				<exception filepattern="testfile.go" minlevel="warn"/>
930			</exceptions>
931		</seelog>
932		`
933		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
934
935		testName = "Errors #18"
936		testConfig = `
937		<seelog type="sync" minlevel=”trace”>
938			<exceptions>
939				<exception filepattern="testfile.go"/>
940			</exceptions>
941		</seelog>
942		`
943		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
944
945		testName = "Errors #19"
946		testConfig = `
947		<seelog type="sync" minlevel=”trace”>
948			<exceptions>
949				<exception minlevel="warn"/>
950			</exceptions>
951		</seelog>
952		`
953		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
954
955		testName = "Errors #20"
956		testConfig = `
957		<seelog type="sync" minlevel=”trace”>
958			<exceptions>
959				<exception/>
960			</exceptions>
961		</seelog>
962		`
963		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
964
965		testName = "Errors #21"
966		testConfig = `
967		<seelog>
968			<outputs>
969				<splitter>
970				</splitter>
971			</outputs>
972		</seelog>
973		`
974		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
975
976		testName = "Errors #22"
977		testConfig = `
978		<seelog type="sync">
979			<outputs>
980				<filter levels="debug, info, critical">
981
982				</filter>
983			</outputs>
984		</seelog>
985		`
986		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
987
988		testName = "Errors #23"
989		testConfig = `
990		<seelog type="sync">
991			<outputs>
992				<buffered size="100500" flushperiod="100">
993
994				</buffered>
995			</outputs>
996		</seelog>
997		`
998		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
999
1000		testName = "Errors #24"
1001		testLogFileName = getTestFileName(testName, "")
1002		testConfig = `
1003		<seelog type="sync">
1004			<outputs>
1005				<buffered size="100500" flushperiod="100">
1006					<rollingfile type="date" filename="` + testLogFileName + `" datepattern="2006-01-02T15:04:05Z07:00" formatid="testFormat"/>
1007				</buffered>
1008			</outputs>
1009			<formats>
1010				<format id="testFormat" format="%Level %Msg %File 123" />
1011			</formats>
1012		</seelog>
1013		`
1014		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
1015
1016		testName = "Errors #25"
1017		testLogFileName = getTestFileName(testName, "")
1018		testConfig = `
1019		<seelog type="sync">
1020			<outputs>
1021				<outputs>
1022					<file path="` + testLogFileName + `"/>
1023				</outputs>
1024				<outputs>
1025					<file path="` + testLogFileName + `"/>
1026				</outputs>
1027			</outputs>
1028		</seelog>
1029		`
1030		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
1031
1032		testName = "Errors #26"
1033		testConfig = `
1034		<seelog type="sync">
1035			<outputs>
1036				<conn net="tcp" addr=":8888" reconnectonmsg="true1" />
1037			</outputs>
1038		</seelog>`
1039		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
1040
1041		testName = "Errors #27"
1042		testLogFileName = getTestFileName(testName, "")
1043		testConfig = `
1044		<seelog type="sync">
1045			<outputs>
1046				<rollingfile type="size" filename="` + testLogFileName + `" maxsize="100" maxrolls="5" archivetype="zip" archivepath="" />
1047			</outputs>
1048		</seelog>`
1049		parserTests = append(parserTests, parserTest{testName, testConfig, nil, true, nil})
1050
1051		testName = "Buffered writer same formatid override"
1052		testLogFileName = getTestFileName(testName, "")
1053		testConfig = `
1054		<seelog type="sync">
1055			<outputs>
1056				<buffered size="100500" flushperiod="100" formatid="testFormat">
1057					<rollingfile namemode="prefix" type="date" filename="` + testLogFileName + `" datepattern="2006-01-02T15:04:05Z07:00" formatid="testFormat"/>
1058				</buffered>
1059			</outputs>
1060			<formats>
1061				<format id="testFormat" format="%Level %Msg %File 123" />
1062			</formats>
1063		</seelog>`
1064		testExpected = new(configForParsing)
1065		testExpected.Constraints, _ = NewMinMaxConstraints(TraceLvl, CriticalLvl)
1066		testExpected.Exceptions = nil
1067		testrollingFileWriterTime, _ = NewRollingFileWriterTime(testLogFileName, rollingArchiveNone, "", 0, "2006-01-02T15:04:05Z07:00", rollingNameModePrefix, false, false)
1068		testbufferedWriter, _ = NewBufferedWriter(testrollingFileWriterTime, 100500, 100)
1069		testFormat, _ = NewFormatter("%Level %Msg %File 123")
1070		formattedWriter, _ = NewFormattedWriter(testbufferedWriter, testFormat)
1071		testHeadSplitter, _ = NewSplitDispatcher(DefaultFormatter, []interface{}{formattedWriter})
1072		testExpected.LogType = syncloggerTypeFromString
1073		testExpected.RootDispatcher = testHeadSplitter
1074		parserTests = append(parserTests, parserTest{testName, testConfig, testExpected, false, nil})
1075
1076	}
1077
1078	return parserTests
1079}
1080
1081// Temporary solution: compare by string identity. Not the best solution in
1082// terms of performance, but a valid one in terms of comparison, because
1083// every seelog dispatcher/receiver must have a valid String() func
1084// that fully represents its internal parameters.
1085func configsAreEqual(conf1 *configForParsing, conf2 interface{}) bool {
1086	if conf1 == nil {
1087		return conf2 == nil
1088	}
1089	if conf2 == nil {
1090		return conf1 == nil
1091	}
1092
1093	// configForParsing, ok := conf2 //.(*configForParsing)
1094	// if !ok {
1095	// 	return false
1096	// }
1097
1098	return fmt.Sprintf("%v", conf1) == fmt.Sprintf("%v", conf2) //configForParsing)
1099}
1100
1101func testLogFileFilter(fn string) bool {
1102	return ".log" == filepath.Ext(fn)
1103}
1104
1105func cleanupAfterCfgTest(t *testing.T) {
1106	toDel, err := getDirFilePaths(".", testLogFileFilter, true)
1107	if nil != err {
1108		t.Fatal("Cannot list files in test directory!")
1109	}
1110
1111	for _, p := range toDel {
1112		err = tryRemoveFile(p)
1113		if nil != err {
1114			t.Errorf("cannot remove file %s in test directory: %s", p, err.Error())
1115		}
1116	}
1117}
1118
1119func parseTest(test parserTest, t *testing.T) {
1120	conf, err := configFromReaderWithConfig(strings.NewReader(test.config), test.parserConfig)
1121	if /*err != nil &&*/ conf != nil && conf.RootDispatcher != nil {
1122		defer func() {
1123			if err = conf.RootDispatcher.Close(); err != nil {
1124				t.Errorf("\n----ERROR while closing root dispatcher in %s test: %s", test.testName, err)
1125			}
1126		}()
1127	}
1128
1129	if (err != nil) != test.errorExpected {
1130		t.Errorf("\n----ERROR in %s:\nConfig: %s\n* Expected error:%t. Got error: %t\n",
1131			test.testName, test.config, test.errorExpected, (err != nil))
1132		if err != nil {
1133			t.Logf("%s\n", err.Error())
1134		}
1135		return
1136	}
1137
1138	if err == nil && !configsAreEqual(conf, test.expected) {
1139		t.Errorf("\n----ERROR in %s:\nConfig: %s\n* Expected: %v. \n* Got: %v\n",
1140			test.testName, test.config, test.expected, conf)
1141	}
1142}
1143
1144func TestParser(t *testing.T) {
1145	defer cleanupAfterCfgTest(t)
1146
1147	for _, test := range getParserTests() {
1148		parseTest(test, t)
1149	}
1150}
1151