1 /* 2 * libjingle 3 * Copyright 2004--2011, Google Inc. 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, 9 * this 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 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "talk/base/fileutils.h" 29 #include "talk/base/gunit.h" 30 #include "talk/base/logging.h" 31 #include "talk/base/pathutils.h" 32 #include "talk/base/stream.h" 33 #include "talk/base/thread.h" 34 35 namespace talk_base { 36 37 // Test basic logging operation. We should get the INFO log but not the VERBOSE. 38 // We should restore the correct global state at the end. 39 TEST(LogTest, SingleStream) { 40 int sev = LogMessage::GetLogToStream(NULL); 41 42 std::string str; 43 StringStream stream(str); 44 LogMessage::AddLogToStream(&stream, LS_INFO); 45 EXPECT_EQ(LS_INFO, LogMessage::GetLogToStream(&stream)); 46 47 LOG(LS_INFO) << "INFO"; 48 LOG(LS_VERBOSE) << "VERBOSE"; 49 EXPECT_NE(std::string::npos, str.find("INFO")); 50 EXPECT_EQ(std::string::npos, str.find("VERBOSE")); 51 52 LogMessage::RemoveLogToStream(&stream); 53 EXPECT_EQ(LogMessage::NO_LOGGING, LogMessage::GetLogToStream(&stream)); 54 55 EXPECT_EQ(sev, LogMessage::GetLogToStream(NULL)); 56 } 57 58 // Test using multiple log streams. The INFO stream should get the INFO message, 59 // the VERBOSE stream should get the INFO and the VERBOSE. 60 // We should restore the correct global state at the end. 61 TEST(LogTest, MultipleStreams) { 62 int sev = LogMessage::GetLogToStream(NULL); 63 64 std::string str1, str2; 65 StringStream stream1(str1), stream2(str2); 66 LogMessage::AddLogToStream(&stream1, LS_INFO); 67 LogMessage::AddLogToStream(&stream2, LS_VERBOSE); 68 EXPECT_EQ(LS_INFO, LogMessage::GetLogToStream(&stream1)); 69 EXPECT_EQ(LS_VERBOSE, LogMessage::GetLogToStream(&stream2)); 70 71 LOG(LS_INFO) << "INFO"; 72 LOG(LS_VERBOSE) << "VERBOSE"; 73 74 EXPECT_NE(std::string::npos, str1.find("INFO")); 75 EXPECT_EQ(std::string::npos, str1.find("VERBOSE")); 76 EXPECT_NE(std::string::npos, str2.find("INFO")); 77 EXPECT_NE(std::string::npos, str2.find("VERBOSE")); 78 79 LogMessage::RemoveLogToStream(&stream2); 80 LogMessage::RemoveLogToStream(&stream1); 81 EXPECT_EQ(LogMessage::NO_LOGGING, LogMessage::GetLogToStream(&stream2)); 82 EXPECT_EQ(LogMessage::NO_LOGGING, LogMessage::GetLogToStream(&stream1)); 83 84 EXPECT_EQ(sev, LogMessage::GetLogToStream(NULL)); 85 } 86 87 // Ensure we don't crash when adding/removing streams while threads are going. 88 // We should restore the correct global state at the end. 89 class LogThread : public Thread { 90 void Run() { 91 // LS_SENSITIVE to avoid cluttering up any real logging going on 92 LOG(LS_SENSITIVE) << "LOG"; 93 } 94 }; 95 96 TEST(LogTest, MultipleThreads) { 97 int sev = LogMessage::GetLogToStream(NULL); 98 99 LogThread thread1, thread2, thread3; 100 thread1.Start(); 101 thread2.Start(); 102 thread3.Start(); 103 104 NullStream stream1, stream2, stream3; 105 for (int i = 0; i < 1000; ++i) { 106 LogMessage::AddLogToStream(&stream1, LS_INFO); 107 LogMessage::AddLogToStream(&stream2, LS_VERBOSE); 108 LogMessage::AddLogToStream(&stream3, LS_SENSITIVE); 109 LogMessage::RemoveLogToStream(&stream1); 110 LogMessage::RemoveLogToStream(&stream2); 111 LogMessage::RemoveLogToStream(&stream3); 112 } 113 114 EXPECT_EQ(sev, LogMessage::GetLogToStream(NULL)); 115 } 116 117 118 TEST(LogTest, WallClockStartTime) { 119 uint32 time = LogMessage::WallClockStartTime(); 120 // Expect the time to be in a sensible range, e.g. > 2012-01-01. 121 EXPECT_GT(time, 1325376000u); 122 } 123 124 // Test the time required to write 1000 80-character logs to an unbuffered file. 125 TEST(LogTest, Perf) { 126 Pathname path; 127 EXPECT_TRUE(Filesystem::GetTemporaryFolder(path, true, NULL)); 128 path.SetPathname(Filesystem::TempFilename(path, "ut")); 129 130 FileStream stream; 131 EXPECT_TRUE(stream.Open(path.pathname(), "wb", NULL)); 132 stream.DisableBuffering(); 133 LogMessage::AddLogToStream(&stream, LS_SENSITIVE); 134 135 uint32 start = Time(), finish; 136 std::string message('X', 80); 137 for (int i = 0; i < 1000; ++i) { 138 LOG(LS_SENSITIVE) << message; 139 } 140 finish = Time(); 141 142 LogMessage::RemoveLogToStream(&stream); 143 stream.Close(); 144 Filesystem::DeleteFile(path); 145 146 LOG(LS_INFO) << "Average log time: " << TimeDiff(finish, start) << " us"; 147 } 148 149 } // namespace talk_base 150