1// Copyright (c) 2016 Uber Technologies, Inc.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in
11// all copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19// THE SOFTWARE.
20
21package zap
22
23import (
24	"sync"
25	"testing"
26
27	"go.uber.org/zap/zapcore"
28
29	"github.com/stretchr/testify/assert"
30)
31
32func TestLevelEnablerFunc(t *testing.T) {
33	enab := LevelEnablerFunc(func(l zapcore.Level) bool { return l == zapcore.InfoLevel })
34	tests := []struct {
35		level   zapcore.Level
36		enabled bool
37	}{
38		{DebugLevel, false},
39		{InfoLevel, true},
40		{WarnLevel, false},
41		{ErrorLevel, false},
42		{DPanicLevel, false},
43		{PanicLevel, false},
44		{FatalLevel, false},
45	}
46	for _, tt := range tests {
47		assert.Equal(t, tt.enabled, enab.Enabled(tt.level), "Unexpected result applying LevelEnablerFunc to %s", tt.level)
48	}
49}
50
51func TestNewAtomicLevel(t *testing.T) {
52	lvl := NewAtomicLevel()
53	assert.Equal(t, InfoLevel, lvl.Level(), "Unexpected initial level.")
54	lvl.SetLevel(ErrorLevel)
55	assert.Equal(t, ErrorLevel, lvl.Level(), "Unexpected level after SetLevel.")
56	lvl = NewAtomicLevelAt(WarnLevel)
57	assert.Equal(t, WarnLevel, lvl.Level(), "Unexpected level after SetLevel.")
58}
59
60func TestAtomicLevelMutation(t *testing.T) {
61	lvl := NewAtomicLevel()
62	lvl.SetLevel(WarnLevel)
63	// Trigger races for non-atomic level mutations.
64	proceed := make(chan struct{})
65	wg := &sync.WaitGroup{}
66	runConcurrently(10, 100, wg, func() {
67		<-proceed
68		assert.Equal(t, WarnLevel, lvl.Level())
69	})
70	runConcurrently(10, 100, wg, func() {
71		<-proceed
72		lvl.SetLevel(WarnLevel)
73	})
74	close(proceed)
75	wg.Wait()
76}
77
78func TestAtomicLevelText(t *testing.T) {
79	tests := []struct {
80		text   string
81		expect zapcore.Level
82		err    bool
83	}{
84		{"debug", DebugLevel, false},
85		{"info", InfoLevel, false},
86		{"", InfoLevel, false},
87		{"warn", WarnLevel, false},
88		{"error", ErrorLevel, false},
89		{"dpanic", DPanicLevel, false},
90		{"panic", PanicLevel, false},
91		{"fatal", FatalLevel, false},
92		{"foobar", InfoLevel, true},
93	}
94
95	for _, tt := range tests {
96		var lvl AtomicLevel
97		// Test both initial unmarshaling and overwriting existing value.
98		for i := 0; i < 2; i++ {
99			if tt.err {
100				assert.Error(t, lvl.UnmarshalText([]byte(tt.text)), "Expected unmarshaling %q to fail.", tt.text)
101			} else {
102				assert.NoError(t, lvl.UnmarshalText([]byte(tt.text)), "Expected unmarshaling %q to succeed.", tt.text)
103			}
104			assert.Equal(t, tt.expect, lvl.Level(), "Unexpected level after unmarshaling.")
105			lvl.SetLevel(InfoLevel)
106		}
107
108		// Test marshalling
109		if tt.text != "" && !tt.err {
110			lvl.SetLevel(tt.expect)
111			marshaled, err := lvl.MarshalText()
112			assert.NoError(t, err, `Unexpected error marshalling level "%v" to text.`, tt.expect)
113			assert.Equal(t, tt.text, string(marshaled), "Expected marshaled text to match")
114			assert.Equal(t, tt.text, lvl.String(), "Expected Stringer call to match")
115		}
116	}
117}
118