f42735dcff4eaaaa5763d76cb50a36317c7d087b
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WebCore / Logging.cpp
1 /*
2  * Copyright (C) 2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WTFStringUtilities.h"
28 #include <pal/Logger.h>
29 #include <wtf/Assertions.h>
30 #include <wtf/MainThread.h>
31
32 #define LOG_CHANNEL_PREFIX Test
33
34 using namespace PAL;
35 using namespace WTF;
36
37 const char* logTestingSubsystem = "com.webkit.testing";
38
39 DEFINE_LOG_CHANNEL(Channel1, logTestingSubsystem);
40 DEFINE_LOG_CHANNEL(Channel2, logTestingSubsystem);
41 DEFINE_LOG_CHANNEL(Channel3, logTestingSubsystem);
42 DEFINE_LOG_CHANNEL(Channel4, logTestingSubsystem);
43
44 static WTFLogChannel* testLogChannels[] = {
45     &TestChannel1,
46     &TestChannel2,
47     &TestChannel3,
48     &TestChannel4,
49 };
50 static const size_t logChannelCount = sizeof(testLogChannels) / sizeof(testLogChannels[0]);
51
52 // Define the following to enable all tests. Disabled by default because replacing stderr with a
53 // non-blocking pipe fails on some of the bots.
54 #define TEST_OUTPUT 0
55
56 namespace TestWebKitAPI {
57
58 class LoggingTest : public testing::Test {
59 public:
60     void SetUp() final
61     {
62         WTF::initializeMainThread();
63
64         // Replace stderr with a non-blocking pipe that we can read from.
65         pipe(m_descriptors);
66         fcntl(m_descriptors[0], F_SETFL, fcntl(m_descriptors[0], F_GETFL, 0) | O_NONBLOCK);
67         dup2(m_descriptors[1], STDERR_FILENO);
68         close(m_descriptors[1]);
69
70         m_stderr = fdopen(m_descriptors[0], "r");
71
72         WTFInitializeLogChannelStatesFromString(testLogChannels, logChannelCount, "all");
73         WTFSetLogChannelLevel(&TestChannel1, WTFLogLevelError);
74         WTFSetLogChannelLevel(&TestChannel2, WTFLogLevelError);
75         WTFSetLogChannelLevel(&TestChannel3, WTFLogLevelError);
76         WTFSetLogChannelLevel(&TestChannel4, WTFLogLevelError);
77     }
78
79     void TearDown() override
80     {
81         close(m_descriptors[0]);
82         fclose(m_stderr);
83     }
84
85     String output()
86     {
87         char buffer[1024];
88         StringBuilder result;
89         char* line;
90
91         while ((line = fgets(buffer, sizeof(buffer), m_stderr)))
92             result.append(line);
93
94         return result.toString();
95     }
96
97 private:
98     int m_descriptors[2];
99     FILE* m_stderr;
100 };
101
102 TEST_F(LoggingTest, Initialization)
103 {
104     EXPECT_EQ(TestChannel1.state, WTFLogChannelOn);
105     EXPECT_EQ(TestChannel2.state, WTFLogChannelOn);
106     EXPECT_EQ(TestChannel3.state, WTFLogChannelOn);
107     EXPECT_EQ(TestChannel4.state, WTFLogChannelOn);
108
109     EXPECT_EQ(TestChannel1.level, WTFLogLevelError);
110     EXPECT_EQ(TestChannel2.level, WTFLogLevelError);
111     EXPECT_EQ(TestChannel3.level, WTFLogLevelError);
112     EXPECT_EQ(TestChannel4.level, WTFLogLevelError);
113
114     TestChannel1.state = WTFLogChannelOff;
115     WTFInitializeLogChannelStatesFromString(testLogChannels, logChannelCount, "Channel1");
116     EXPECT_EQ(TestChannel1.level, WTFLogLevelError);
117     EXPECT_EQ(TestChannel1.state, WTFLogChannelOn);
118
119     TestChannel1.state = WTFLogChannelOff;
120     WTFInitializeLogChannelStatesFromString(testLogChannels, logChannelCount, "Channel1=foo");
121     EXPECT_EQ(TestChannel1.level, WTFLogLevelError);
122 #if TEST_OUTPUT
123     EXPECT_TRUE(output().contains("Unknown logging level: foo", false));
124 #endif
125
126     WTFInitializeLogChannelStatesFromString(testLogChannels, logChannelCount, "Channel1=warning");
127     EXPECT_EQ(TestChannel1.level, WTFLogLevelWarning);
128     EXPECT_EQ(TestChannel2.level, WTFLogLevelError);
129     EXPECT_EQ(TestChannel3.level, WTFLogLevelError);
130     EXPECT_EQ(TestChannel4.level, WTFLogLevelError);
131
132     WTFInitializeLogChannelStatesFromString(testLogChannels, logChannelCount, "Channel4=   debug, Channel3 = info,Channel2=notice");
133     EXPECT_EQ(TestChannel1.level, WTFLogLevelWarning);
134     EXPECT_EQ(TestChannel2.level, WTFLogLevelNotice);
135     EXPECT_EQ(TestChannel3.level, WTFLogLevelInfo);
136     EXPECT_EQ(TestChannel4.level, WTFLogLevelDebug);
137
138     WTFInitializeLogChannelStatesFromString(testLogChannels, logChannelCount, "-all");
139     EXPECT_EQ(TestChannel1.state, WTFLogChannelOff);
140     EXPECT_EQ(TestChannel2.state, WTFLogChannelOff);
141     EXPECT_EQ(TestChannel3.state, WTFLogChannelOff);
142     EXPECT_EQ(TestChannel4.state, WTFLogChannelOff);
143
144     WTFInitializeLogChannelStatesFromString(testLogChannels, logChannelCount, "all");
145     EXPECT_EQ(TestChannel1.state, WTFLogChannelOn);
146     EXPECT_EQ(TestChannel2.state, WTFLogChannelOn);
147     EXPECT_EQ(TestChannel3.state, WTFLogChannelOn);
148     EXPECT_EQ(TestChannel4.state, WTFLogChannelOn);
149 }
150
151 TEST_F(LoggingTest, WTFWillLogWithLevel)
152 {
153     EXPECT_EQ(TestChannel1.state, WTFLogChannelOn);
154     EXPECT_EQ(TestChannel2.state, WTFLogChannelOn);
155     EXPECT_EQ(TestChannel3.state, WTFLogChannelOn);
156     EXPECT_EQ(TestChannel4.state, WTFLogChannelOn);
157
158     EXPECT_EQ(TestChannel1.level, WTFLogLevelError);
159     EXPECT_EQ(TestChannel2.level, WTFLogLevelError);
160     EXPECT_EQ(TestChannel3.level, WTFLogLevelError);
161     EXPECT_EQ(TestChannel4.level, WTFLogLevelError);
162
163     EXPECT_TRUE(WTFWillLogWithLevel(&TestChannel1, WTFLogLevelError));
164     EXPECT_TRUE(WTFWillLogWithLevel(&TestChannel2, WTFLogLevelError));
165     EXPECT_TRUE(WTFWillLogWithLevel(&TestChannel3, WTFLogLevelError));
166     EXPECT_TRUE(WTFWillLogWithLevel(&TestChannel4, WTFLogLevelError));
167
168     EXPECT_FALSE(WTFWillLogWithLevel(&TestChannel1, WTFLogLevelInfo));
169     EXPECT_FALSE(WTFWillLogWithLevel(&TestChannel2, WTFLogLevelInfo));
170     EXPECT_FALSE(WTFWillLogWithLevel(&TestChannel3, WTFLogLevelInfo));
171     EXPECT_FALSE(WTFWillLogWithLevel(&TestChannel4, WTFLogLevelInfo));
172
173     TestChannel1.state = WTFLogChannelOff;
174     EXPECT_FALSE(WTFWillLogWithLevel(&TestChannel1, WTFLogLevelError));
175     EXPECT_FALSE(WTFWillLogWithLevel(&TestChannel1, WTFLogLevelInfo));
176
177     TestChannel1.state = WTFLogChannelOn;
178     EXPECT_TRUE(WTFWillLogWithLevel(&TestChannel1, WTFLogLevelError));
179     EXPECT_FALSE(WTFWillLogWithLevel(&TestChannel1, WTFLogLevelInfo));
180
181     TestChannel1.level = WTFLogLevelInfo;
182     EXPECT_TRUE(WTFWillLogWithLevel(&TestChannel1, WTFLogLevelError));
183     EXPECT_TRUE(WTFWillLogWithLevel(&TestChannel1, WTFLogLevelInfo));
184 }
185
186 #if TEST_OUTPUT
187 TEST_F(LoggingTest, LOG)
188 {
189     LOG(Channel1, "Log message.");
190     EXPECT_TRUE(output().contains("Log Message.", false));
191 }
192
193 TEST_F(LoggingTest, LOG_WITH_LEVEL)
194 {
195     LOG_WITH_LEVEL(Channel1, WTFLogLevelError, "Go and boil your bottoms, you sons of a silly person.");
196     EXPECT_TRUE(output().contains("sons of a silly person.", false));
197
198     LOG_WITH_LEVEL(Channel1, WTFLogLevelWarning, "You don't frighten us, English pig dogs.");
199     EXPECT_EQ(0u, output().length());
200
201     WTFSetLogChannelLevel(&TestChannel1, WTFLogLevelInfo);
202     LOG_WITH_LEVEL(Channel1, WTFLogLevelWarning, "I'm French. Why do you think I have this outrageous accent, you silly king?");
203     EXPECT_TRUE(output().contains("outrageous accent", false));
204
205     LOG_WITH_LEVEL(Channel1, WTFLogLevelDebug, "You don't frighten us with your silly knees-bent running around advancing behavior!");
206     EXPECT_EQ(0u, output().length());
207
208     WTFSetLogChannelLevel(&TestChannel1, WTFLogLevelDebug);
209     LOG_WITH_LEVEL(Channel1, WTFLogLevelDebug, "Go and tell your master that we have been charged by God with a sacred quest.");
210     EXPECT_TRUE(output().contains("sacred quest", false));
211 }
212
213 TEST_F(LoggingTest, RELEASE_LOG)
214 {
215     RELEASE_LOG(Channel1, "Log message.");
216     EXPECT_TRUE(output().contains("Log Message.", false));
217 }
218
219 TEST_F(LoggingTest, RELEASE_LOG_IF)
220 {
221     bool enabled = true;
222     RELEASE_LOG_IF(enabled, Channel1, "Your mother was a hamster,");
223     EXPECT_TRUE(output().contains("hamster,", false));
224
225     enabled = false;
226     RELEASE_LOG_IF(enabled, Channel1, "and your father smelt of elderberries ...");
227     EXPECT_EQ(0u, output().length());
228 }
229
230 TEST_F(LoggingTest, RELEASE_LOG_WITH_LEVEL)
231 {
232     RELEASE_LOG_WITH_LEVEL(Channel1, WTFLogLevelError, "You don't frighten us, English pig dogs.");
233     EXPECT_TRUE(output().contains("pig dogs.", false));
234
235     RELEASE_LOG_WITH_LEVEL(Channel1, WTFLogLevelWarning, "Go and boil your bottoms, you sons of a silly person.");
236     EXPECT_EQ(0u, output().length());
237
238     WTFSetLogChannelLevel(&TestChannel1, WTFLogLevelInfo);
239     RELEASE_LOG_WITH_LEVEL(Channel1, WTFLogLevelWarning, "I'm French. Why do you think I have this outrageous accent, you silly king?");
240     EXPECT_TRUE(output().contains("outrageous accent", false));
241
242     RELEASE_LOG_WITH_LEVEL(Channel1, WTFLogLevelDebug, "You don't frighten us with your silly knees-bent running around advancing behavior!");
243     EXPECT_EQ(0u, output().length());
244
245     WTFSetLogChannelLevel(&TestChannel1, WTFLogLevelDebug);
246     RELEASE_LOG_WITH_LEVEL(Channel1, WTFLogLevelDebug, "Go and tell your master that we have been charged by God with a sacred quest.");
247     EXPECT_TRUE(output().contains("sacred quest", false));
248 }
249
250 TEST_F(LoggingTest, RELEASE_LOG_WITH_LEVEL_IF)
251 {
252     bool enabled = true;
253     RELEASE_LOG_WITH_LEVEL_IF(enabled, Channel1, WTFLogLevelError, "Is there someone else up there that we can talk to?");
254     EXPECT_TRUE(output().contains("someone else", false));
255
256     RELEASE_LOG_WITH_LEVEL_IF(enabled, Channel1, WTFLogLevelDebug, "No, now go away");
257     EXPECT_EQ(0u, output().length());
258
259     enabled = false;
260     RELEASE_LOG_WITH_LEVEL_IF(enabled, Channel1, WTFLogLevelWarning, "or I shall taunt you a second time! %i", 12);
261     EXPECT_EQ(0u, output().length());
262 }
263
264 TEST_F(LoggingTest, Logger)
265 {
266     Ref<Logger> logger = Logger::create(this);
267     EXPECT_TRUE(logger->enabled());
268
269     WTFSetLogChannelLevel(&TestChannel1, WTFLogLevelError);
270     logger->error(TestChannel1, "You're using coconuts!");
271     EXPECT_TRUE(output().contains("You're using coconuts!", false));
272     logger->warning(TestChannel1, "You're using coconuts!");
273     EXPECT_EQ(0u, output().length());
274     logger->notice(TestChannel1, "You're using coconuts!");
275     EXPECT_EQ(0u, output().length());
276     logger->info(TestChannel1, "You're using coconuts!");
277     EXPECT_EQ(0u, output().length());
278     logger->debug(TestChannel1, "You're using coconuts!");
279     EXPECT_EQ(0u, output().length());
280
281     logger->error(TestChannel1, Logger::MethodAndPointer("LoggingTest::Logger", this) , ": test output");
282     EXPECT_TRUE(output().contains("LoggingTest::Logger(", false));
283
284     logger->error(TestChannel1, "What is ", 1, " + " , 12.5F, "?");
285     EXPECT_TRUE(output().contains("What is 1 + 12.5?", false));
286
287     logger->error(TestChannel1, "What, ", "ridden on a horse?");
288     EXPECT_TRUE(output().contains("What, ridden on a horse?", false));
289
290     logger->setEnabled(this, false);
291     EXPECT_FALSE(logger->enabled());
292     logger->error(TestChannel1, "You've got two empty halves of coconuts");
293     EXPECT_EQ(0u, output().length());
294
295     logger->setEnabled(this, true);
296     EXPECT_TRUE(logger->enabled());
297     logger->error(TestChannel1, "You've got ", 2, " empty halves of ", "coconuts!");
298     EXPECT_TRUE(output().contains("You've got 2 empty halves of coconuts!", false));
299
300     WTFSetLogChannelLevel(&TestChannel1, WTFLogLevelError);
301     logger->logAlways(TestChannel1, "I shall taunt you a second time!");
302     EXPECT_TRUE(output().contains("I shall taunt you a second time!", false));
303
304     logger->setEnabled(this, false);
305     EXPECT_FALSE(logger->enabled());
306     logger->logAlways(TestChannel1, "You've got two empty halves of coconuts");
307     EXPECT_EQ(0u, output().length());
308 }
309 #endif
310
311 } // namespace TestWebKitAPI