1 // Copyright 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <gmock/gmock.h>
16 
17 #include "host-common/logging.h"
18 
19 #include <thread>
20 
21 #include "aemu/base/testing/TestUtils.h"
22 
23 namespace {
24 
25 using ::testing::EndsWith;
26 using ::testing::HasSubstr;
27 using ::testing::Not;
28 using ::testing::StartsWith;
29 using ::testing::internal::CaptureStderr;
30 using ::testing::internal::CaptureStdout;
31 using ::testing::internal::GetCapturedStderr;
32 using ::testing::internal::GetCapturedStdout;
33 
34 // Returns the microseconds since the Unix epoch for Sep 13, 2020 12:26:40.123456 in the machine's
35 // local timezone.
defaultTimestamp()36 int64_t defaultTimestamp() {
37     std::tm time = {};
38     time.tm_year = 2020 - 1900;
39     time.tm_mon = 9 - 1;  // month starts at 0
40     time.tm_mday = 13;
41     time.tm_hour = 12;
42     time.tm_min = 26;
43     time.tm_sec = 40;
44     time.tm_isdst = -1;  // let mktime determine whether DST is in effect
45     int64_t timestamp_s = mktime(&time);
46     EXPECT_GT(timestamp_s, 0) << "mktime() failed";
47     return timestamp_s * 1000000 + 123456;
48 }
49 
TEST(Logging,ERRMacroNoArguments)50 TEST(Logging, ERRMacroNoArguments) {
51     CaptureStderr();
52     ERR("Hello world.");
53     std::string log = GetCapturedStderr();
54     EXPECT_THAT(log, StartsWith("E"));
55     EXPECT_THAT(log, EndsWith("] Hello world.\n"));
56 }
57 
TEST(Logging,ERRMacroWithArguments)58 TEST(Logging, ERRMacroWithArguments) {
59     CaptureStderr();
60     ERR("hello %s %d", "world", 1);
61     std::string log = GetCapturedStderr();
62     EXPECT_THAT(log, StartsWith("E"));
63     EXPECT_THAT(log, EndsWith("] hello world 1\n"));
64 }
65 
TEST(Logging,INFOMacroNoArguments)66 TEST(Logging, INFOMacroNoArguments) {
67     CaptureStderr();
68     INFO("Hello world.");
69     std::string log = GetCapturedStderr();
70     EXPECT_THAT(log, StartsWith("I"));
71     EXPECT_THAT(log, EndsWith("] Hello world.\n"));
72 }
73 
TEST(Logging,INFOMacroWithArguments)74 TEST(Logging, INFOMacroWithArguments) {
75     CaptureStderr();
76     INFO("hello %s %d", "world", 1);
77     std::string log = GetCapturedStderr();
78     EXPECT_THAT(log, StartsWith("I"));
79     EXPECT_THAT(log, EndsWith("] hello world 1\n"));
80 }
81 
TEST(Logging,FormatsPrefixCorrectly)82 TEST(Logging, FormatsPrefixCorrectly) {
83     CaptureStderr();
84     INFO("foo");
85     std::string log = GetCapturedStderr();
86     EXPECT_THAT(
87         log, MatchesStdRegex(
88                  R"re(I\d{4} \d{2}:\d{2}:\d{2}\.\d{6} +\w+ logging_unittest.cpp:\d+\] foo\n)re"));
89 }
90 
TEST(Logging,OutputsTimestamp)91 TEST(Logging, OutputsTimestamp) {
92     CaptureStdout();
93     OutputLog(stdout, 'I', "", 0, defaultTimestamp(), "");
94     std::string log = GetCapturedStdout();
95     EXPECT_THAT(log, StartsWith("I0913 12:26:40.123456"));
96 }
97 
98 #if defined(_WIN32)
TEST(Logging,FileHasBasenameOnlyWithBackwardsSlashes)99 TEST(Logging, FileHasBasenameOnlyWithBackwardsSlashes) {
100     CaptureStdout();
101     OutputLog(stdout, ' ', R"(c:\foo\bar\file_name)", 123, 0, "");
102     std::string log = GetCapturedStdout();
103     EXPECT_THAT(log, HasSubstr(" file_name:123"));
104     EXPECT_THAT(log, Not(HasSubstr("bar")));
105 }
106 #endif
107 
TEST(Logging,FileHasBasenameOnlyWithForwardSlashes)108 TEST(Logging, FileHasBasenameOnlyWithForwardSlashes) {
109     CaptureStdout();
110     OutputLog(stdout, ' ', "/foo/bar/file_name", 123, 0, "");
111     std::string log = GetCapturedStdout();
112     EXPECT_THAT(log, HasSubstr(" file_name:123"));
113     EXPECT_THAT(log, Not(HasSubstr("bar")));
114 }
115 
TEST(Logging,OutputsDifferentThreadIdsOnDifferentThreads)116 TEST(Logging, OutputsDifferentThreadIdsOnDifferentThreads) {
117     CaptureStderr();
118     INFO("hello");
119     std::string log1 = GetCapturedStderr();
120 
121     CaptureStderr();
122     std::thread([]() { INFO("from thread"); }).join();
123     std::string log2 = GetCapturedStderr();
124 
125     std::string tid1 = log1.substr(21, 9);
126     std::string tid2 = log2.substr(21, 9);
127     EXPECT_THAT(tid1, MatchesStdRegex(R"( +\w+ )"));
128     EXPECT_THAT(tid2, MatchesStdRegex(R"( +\w+ )"));
129     EXPECT_NE(tid1, tid2);
130 }
131 
132 }  // namespace
133