1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "base/logging.h"
18 
19 #include <regex>
20 #include <string>
21 
22 #include "base/file.h"
23 #include "base/stringprintf.h"
24 #include "test_utils.h"
25 
26 #include <gtest/gtest.h>
27 
28 #ifdef __ANDROID__
29 #define HOST_TEST(suite, name) TEST(suite, DISABLED_ ## name)
30 #else
31 #define HOST_TEST(suite, name) TEST(suite, name)
32 #endif
33 
34 class CapturedStderr {
35  public:
CapturedStderr()36   CapturedStderr() : old_stderr_(-1) {
37     init();
38   }
39 
~CapturedStderr()40   ~CapturedStderr() {
41     reset();
42   }
43 
fd() const44   int fd() const {
45     return temp_file_.fd;
46   }
47 
48  private:
init()49   void init() {
50     old_stderr_ = dup(STDERR_FILENO);
51     ASSERT_NE(-1, old_stderr_);
52     ASSERT_NE(-1, dup2(fd(), STDERR_FILENO));
53   }
54 
reset()55   void reset() {
56     ASSERT_NE(-1, dup2(old_stderr_, STDERR_FILENO));
57     ASSERT_EQ(0, close(old_stderr_));
58   }
59 
60   TemporaryFile temp_file_;
61   int old_stderr_;
62 };
63 
TEST(logging,CHECK)64 TEST(logging, CHECK) {
65   ASSERT_DEATH(CHECK(false), "Check failed: false ");
66   CHECK(true);
67 
68   ASSERT_DEATH(CHECK_EQ(0, 1), "Check failed: 0 == 1 ");
69   CHECK_EQ(0, 0);
70 
71   ASSERT_DEATH(CHECK_STREQ("foo", "bar"), R"(Check failed: "foo" == "bar")");
72   CHECK_STREQ("foo", "foo");
73 }
74 
make_log_pattern(android::base::LogSeverity severity,const char * message)75 std::string make_log_pattern(android::base::LogSeverity severity,
76                              const char* message) {
77   static const char* log_characters = "VDIWEF";
78   char log_char = log_characters[severity];
79   return android::base::StringPrintf(
80       "%c[[:space:]]+[[:digit:]]+[[:space:]]+[[:digit:]]+ " __FILE__
81       ":[[:digit:]]+] %s",
82       log_char, message);
83 }
84 
TEST(logging,LOG)85 TEST(logging, LOG) {
86   ASSERT_DEATH(LOG(FATAL) << "foobar", "foobar");
87 
88   {
89     CapturedStderr cap;
90     LOG(WARNING) << "foobar";
91     ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
92 
93     std::string output;
94     android::base::ReadFdToString(cap.fd(), &output);
95 
96     std::regex message_regex(
97         make_log_pattern(android::base::WARNING, "foobar"));
98     ASSERT_TRUE(std::regex_search(output, message_regex));
99   }
100 
101   {
102     CapturedStderr cap;
103     LOG(INFO) << "foobar";
104     ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
105 
106     std::string output;
107     android::base::ReadFdToString(cap.fd(), &output);
108 
109     std::regex message_regex(
110         make_log_pattern(android::base::INFO, "foobar"));
111     ASSERT_TRUE(std::regex_search(output, message_regex));
112   }
113 
114   {
115     CapturedStderr cap;
116     LOG(DEBUG) << "foobar";
117     ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
118 
119     std::string output;
120     android::base::ReadFdToString(cap.fd(), &output);
121     ASSERT_TRUE(output.empty());
122   }
123 
124   {
125     android::base::ScopedLogSeverity severity(android::base::DEBUG);
126     CapturedStderr cap;
127     LOG(DEBUG) << "foobar";
128     ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
129 
130     std::string output;
131     android::base::ReadFdToString(cap.fd(), &output);
132 
133     std::regex message_regex(
134         make_log_pattern(android::base::DEBUG, "foobar"));
135     ASSERT_TRUE(std::regex_search(output, message_regex));
136   }
137 }
138 
TEST(logging,PLOG)139 TEST(logging, PLOG) {
140   {
141     CapturedStderr cap;
142     errno = ENOENT;
143     PLOG(INFO) << "foobar";
144     ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
145 
146     std::string output;
147     android::base::ReadFdToString(cap.fd(), &output);
148 
149     std::regex message_regex(make_log_pattern(
150         android::base::INFO, "foobar: No such file or directory"));
151     ASSERT_TRUE(std::regex_search(output, message_regex));
152   }
153 }
154 
TEST(logging,UNIMPLEMENTED)155 TEST(logging, UNIMPLEMENTED) {
156   {
157     CapturedStderr cap;
158     errno = ENOENT;
159     UNIMPLEMENTED(ERROR);
160     ASSERT_EQ(0, lseek(cap.fd(), SEEK_SET, 0));
161 
162     std::string output;
163     android::base::ReadFdToString(cap.fd(), &output);
164 
165     std::string expected_message =
166         android::base::StringPrintf("%s unimplemented ", __PRETTY_FUNCTION__);
167     std::regex message_regex(
168         make_log_pattern(android::base::ERROR, expected_message.c_str()));
169     ASSERT_TRUE(std::regex_search(output, message_regex));
170   }
171 }
172