1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/net/net_log_temp_file.h" 6 7 #include "base/basictypes.h" 8 #include "base/files/file_path.h" 9 #include "base/files/file_util.h" 10 #include "base/message_loop/message_loop.h" 11 #include "base/values.h" 12 #include "build/build_config.h" 13 #include "chrome/browser/net/chrome_net_log.h" 14 #include "content/public/test/test_browser_thread.h" 15 #include "testing/gtest/include/gtest/gtest.h" 16 17 using content::BrowserThread; 18 19 class TestNetLogTempFile : public NetLogTempFile { 20 public: 21 explicit TestNetLogTempFile(ChromeNetLog* chrome_net_log) 22 : NetLogTempFile(chrome_net_log), 23 lie_about_net_export_log_directory_(false), 24 lie_about_file_existence_(false) { 25 } 26 27 // NetLogTempFile implementation: 28 virtual bool GetNetExportLogDirectory(base::FilePath* path) OVERRIDE { 29 if (lie_about_net_export_log_directory_) 30 return false; 31 return NetLogTempFile::GetNetExportLogDirectory(path); 32 } 33 34 virtual bool NetExportLogExists() OVERRIDE { 35 if (lie_about_file_existence_) 36 return false; 37 return NetLogTempFile::NetExportLogExists(); 38 } 39 40 void set_lie_about_net_export_log_directory( 41 bool lie_about_net_export_log_directory) { 42 lie_about_net_export_log_directory_ = lie_about_net_export_log_directory; 43 } 44 45 void set_lie_about_file_existence(bool lie_about_file_existence) { 46 lie_about_file_existence_ = lie_about_file_existence; 47 } 48 49 private: 50 bool lie_about_net_export_log_directory_; 51 bool lie_about_file_existence_; 52 }; 53 54 class NetLogTempFileTest : public ::testing::Test { 55 public: 56 NetLogTempFileTest() 57 : net_log_(new ChromeNetLog), 58 net_log_temp_file_(new TestNetLogTempFile(net_log_.get())), 59 file_user_blocking_thread_(BrowserThread::FILE_USER_BLOCKING, 60 &message_loop_) { 61 } 62 63 // ::testing::Test implementation: 64 virtual void SetUp() OVERRIDE { 65 // Get a temporary file name for unit tests. 66 base::FilePath net_log_dir; 67 ASSERT_TRUE(net_log_temp_file_->GetNetExportLogDirectory(&net_log_dir)); 68 ASSERT_TRUE(base::CreateTemporaryFileInDir(net_log_dir, &net_export_log_)); 69 70 net_log_temp_file_->log_filename_ = net_export_log_.BaseName().value(); 71 72 // CreateTemporaryFileInDir may return a legacy 8.3 file name on windows. 73 // Need to use the original directory name for string comparisons. 74 ASSERT_TRUE(net_log_temp_file_->GetNetExportLog()); 75 net_export_log_ = net_log_temp_file_->log_path_; 76 ASSERT_FALSE(net_export_log_.empty()); 77 } 78 79 virtual void TearDown() OVERRIDE { 80 // Delete the temporary file we have created. 81 ASSERT_TRUE(base::DeleteFile(net_export_log_, false)); 82 } 83 84 std::string GetStateString() const { 85 scoped_ptr<base::DictionaryValue> dict(net_log_temp_file_->GetState()); 86 std::string state; 87 EXPECT_TRUE(dict->GetString("state", &state)); 88 return state; 89 } 90 91 std::string GetLogTypeString() const { 92 scoped_ptr<base::DictionaryValue> dict(net_log_temp_file_->GetState()); 93 std::string log_type; 94 EXPECT_TRUE(dict->GetString("logType", &log_type)); 95 return log_type; 96 } 97 98 // Make sure the export file has been created and is non-empty, as net 99 // constants will always be written to it on creation. 100 void VerifyNetExportLog() { 101 EXPECT_EQ(net_export_log_, net_log_temp_file_->log_path_); 102 EXPECT_TRUE(base::PathExists(net_export_log_)); 103 104 int64 file_size; 105 // base::GetFileSize returns proper file size on open handles. 106 EXPECT_TRUE(base::GetFileSize(net_export_log_, &file_size)); 107 EXPECT_GT(file_size, 0); 108 } 109 110 // Verify state and GetFilePath return correct values if EnsureInit() fails. 111 void VerifyFilePathAndStateAfterEnsureInitFailure() { 112 EXPECT_EQ("UNINITIALIZED", GetStateString()); 113 EXPECT_EQ(NetLogTempFile::STATE_UNINITIALIZED, 114 net_log_temp_file_->state()); 115 116 base::FilePath net_export_file_path; 117 EXPECT_FALSE(net_log_temp_file_->GetFilePath(&net_export_file_path)); 118 } 119 120 // When we lie in NetExportLogExists, make sure state and GetFilePath return 121 // correct values. 122 void VerifyFilePathAndStateAfterEnsureInit() { 123 EXPECT_EQ("NOT_LOGGING", GetStateString()); 124 EXPECT_EQ(NetLogTempFile::STATE_NOT_LOGGING, net_log_temp_file_->state()); 125 EXPECT_EQ("NONE", GetLogTypeString()); 126 EXPECT_EQ(NetLogTempFile::LOG_TYPE_NONE, net_log_temp_file_->log_type()); 127 128 base::FilePath net_export_file_path; 129 EXPECT_FALSE(net_log_temp_file_->GetFilePath(&net_export_file_path)); 130 EXPECT_FALSE(net_log_temp_file_->NetExportLogExists()); 131 } 132 133 // Make sure the export file has been successfully initialized. 134 void VerifyFileAndStateAfterDoStart() { 135 EXPECT_EQ("LOGGING", GetStateString()); 136 EXPECT_EQ(NetLogTempFile::STATE_LOGGING, net_log_temp_file_->state()); 137 EXPECT_EQ("NORMAL", GetLogTypeString()); 138 EXPECT_EQ(NetLogTempFile::LOG_TYPE_NORMAL, net_log_temp_file_->log_type()); 139 140 // Check GetFilePath returns false, if we are still writing to file. 141 base::FilePath net_export_file_path; 142 EXPECT_FALSE(net_log_temp_file_->GetFilePath(&net_export_file_path)); 143 144 VerifyNetExportLog(); 145 EXPECT_EQ(net::NetLog::LOG_ALL_BUT_BYTES, net_log_->GetLogLevel()); 146 } 147 148 // Make sure the export file has been successfully initialized. 149 void VerifyFileAndStateAfterDoStartStripPrivateData() { 150 EXPECT_EQ("LOGGING", GetStateString()); 151 EXPECT_EQ(NetLogTempFile::STATE_LOGGING, net_log_temp_file_->state()); 152 EXPECT_EQ("STRIP_PRIVATE_DATA", GetLogTypeString()); 153 EXPECT_EQ(NetLogTempFile::LOG_TYPE_STRIP_PRIVATE_DATA, 154 net_log_temp_file_->log_type()); 155 156 // Check GetFilePath returns false, if we are still writing to file. 157 base::FilePath net_export_file_path; 158 EXPECT_FALSE(net_log_temp_file_->GetFilePath(&net_export_file_path)); 159 160 VerifyNetExportLog(); 161 EXPECT_EQ(net::NetLog::LOG_STRIP_PRIVATE_DATA, net_log_->GetLogLevel()); 162 } 163 164 // Make sure the export file has been successfully initialized. 165 void VerifyFileAndStateAfterDoStop() { 166 EXPECT_EQ("NOT_LOGGING", GetStateString()); 167 EXPECT_EQ(NetLogTempFile::STATE_NOT_LOGGING, net_log_temp_file_->state()); 168 EXPECT_EQ("NORMAL", GetLogTypeString()); 169 EXPECT_EQ(NetLogTempFile::LOG_TYPE_NORMAL, net_log_temp_file_->log_type()); 170 171 base::FilePath net_export_file_path; 172 EXPECT_TRUE(net_log_temp_file_->GetFilePath(&net_export_file_path)); 173 EXPECT_TRUE(base::PathExists(net_export_file_path)); 174 EXPECT_EQ(net_export_log_, net_export_file_path); 175 176 VerifyNetExportLog(); 177 } 178 179 scoped_ptr<ChromeNetLog> net_log_; 180 // |net_log_temp_file_| is initialized after |net_log_| so that it can stop 181 // obvserving on destruction. 182 scoped_ptr<TestNetLogTempFile> net_log_temp_file_; 183 base::FilePath net_export_log_; 184 185 private: 186 base::MessageLoop message_loop_; 187 content::TestBrowserThread file_user_blocking_thread_; 188 }; 189 190 TEST_F(NetLogTempFileTest, EnsureInitFailure) { 191 net_log_temp_file_->set_lie_about_net_export_log_directory(true); 192 193 EXPECT_FALSE(net_log_temp_file_->EnsureInit()); 194 VerifyFilePathAndStateAfterEnsureInitFailure(); 195 196 net_log_temp_file_->ProcessCommand(NetLogTempFile::DO_START); 197 VerifyFilePathAndStateAfterEnsureInitFailure(); 198 } 199 200 TEST_F(NetLogTempFileTest, EnsureInitAllowStart) { 201 net_log_temp_file_->set_lie_about_file_existence(true); 202 203 EXPECT_TRUE(net_log_temp_file_->EnsureInit()); 204 VerifyFilePathAndStateAfterEnsureInit(); 205 206 // Calling EnsureInit() second time should be a no-op. 207 EXPECT_TRUE(net_log_temp_file_->EnsureInit()); 208 VerifyFilePathAndStateAfterEnsureInit(); 209 } 210 211 TEST_F(NetLogTempFileTest, EnsureInitAllowStartOrSend) { 212 EXPECT_TRUE(net_log_temp_file_->EnsureInit()); 213 214 EXPECT_EQ("NOT_LOGGING", GetStateString()); 215 EXPECT_EQ(NetLogTempFile::STATE_NOT_LOGGING, net_log_temp_file_->state()); 216 EXPECT_EQ("UNKNOWN", GetLogTypeString()); 217 EXPECT_EQ(NetLogTempFile::LOG_TYPE_UNKNOWN, net_log_temp_file_->log_type()); 218 EXPECT_EQ(net_export_log_, net_log_temp_file_->log_path_); 219 EXPECT_TRUE(base::PathExists(net_export_log_)); 220 221 base::FilePath net_export_file_path; 222 EXPECT_TRUE(net_log_temp_file_->GetFilePath(&net_export_file_path)); 223 EXPECT_TRUE(base::PathExists(net_export_file_path)); 224 EXPECT_EQ(net_export_log_, net_export_file_path); 225 226 // GetFilePath should return false if NetExportLogExists() fails. 227 net_log_temp_file_->set_lie_about_file_existence(true); 228 EXPECT_FALSE(net_log_temp_file_->GetFilePath(&net_export_file_path)); 229 } 230 231 TEST_F(NetLogTempFileTest, ProcessCommandDoStartAndStop) { 232 net_log_temp_file_->ProcessCommand(NetLogTempFile::DO_START); 233 VerifyFileAndStateAfterDoStart(); 234 235 // Calling DO_START second time should be a no-op. 236 net_log_temp_file_->ProcessCommand(NetLogTempFile::DO_START); 237 VerifyFileAndStateAfterDoStart(); 238 239 net_log_temp_file_->ProcessCommand(NetLogTempFile::DO_STOP); 240 VerifyFileAndStateAfterDoStop(); 241 242 // Calling DO_STOP second time should be a no-op. 243 net_log_temp_file_->ProcessCommand(NetLogTempFile::DO_STOP); 244 VerifyFileAndStateAfterDoStop(); 245 } 246 247 TEST_F(NetLogTempFileTest, DoStartClearsFile) { 248 // Verify file sizes after two consecutives start/stop are the same (even if 249 // we add some junk data in between). 250 net_log_temp_file_->ProcessCommand(NetLogTempFile::DO_START); 251 VerifyFileAndStateAfterDoStart(); 252 253 int64 start_file_size; 254 EXPECT_TRUE(base::GetFileSize(net_export_log_, &start_file_size)); 255 256 net_log_temp_file_->ProcessCommand(NetLogTempFile::DO_STOP); 257 VerifyFileAndStateAfterDoStop(); 258 259 int64 stop_file_size; 260 EXPECT_TRUE(base::GetFileSize(net_export_log_, &stop_file_size)); 261 EXPECT_GE(stop_file_size, start_file_size); 262 263 // Add some junk at the end of the file. 264 std::string junk_data("Hello"); 265 EXPECT_GT(base::AppendToFile( 266 net_export_log_, junk_data.c_str(), junk_data.size()), 0); 267 268 int64 junk_file_size; 269 EXPECT_TRUE(base::GetFileSize(net_export_log_, &junk_file_size)); 270 EXPECT_GT(junk_file_size, stop_file_size); 271 272 // Execute DO_START/DO_STOP commands and make sure the file is back to the 273 // size before addition of junk data. 274 net_log_temp_file_->ProcessCommand(NetLogTempFile::DO_START); 275 VerifyFileAndStateAfterDoStart(); 276 277 int64 new_start_file_size; 278 EXPECT_TRUE(base::GetFileSize(net_export_log_, &new_start_file_size)); 279 EXPECT_EQ(new_start_file_size, start_file_size); 280 281 net_log_temp_file_->ProcessCommand(NetLogTempFile::DO_STOP); 282 VerifyFileAndStateAfterDoStop(); 283 284 int64 new_stop_file_size; 285 EXPECT_TRUE(base::GetFileSize(net_export_log_, &new_stop_file_size)); 286 EXPECT_EQ(new_stop_file_size, stop_file_size); 287 } 288 289 TEST_F(NetLogTempFileTest, CheckAddEvent) { 290 // Add an event to |net_log_| and then test to make sure that, after we stop 291 // logging, the file is larger than the file created without that event. 292 net_log_temp_file_->ProcessCommand(NetLogTempFile::DO_START); 293 VerifyFileAndStateAfterDoStart(); 294 295 // Get file size without the event. 296 net_log_temp_file_->ProcessCommand(NetLogTempFile::DO_STOP); 297 VerifyFileAndStateAfterDoStop(); 298 299 int64 stop_file_size; 300 EXPECT_TRUE(base::GetFileSize(net_export_log_, &stop_file_size)); 301 302 // Perform DO_START and add an Event and then DO_STOP and then compare 303 // file sizes. 304 net_log_temp_file_->ProcessCommand(NetLogTempFile::DO_START); 305 VerifyFileAndStateAfterDoStart(); 306 307 // Log an event. 308 net_log_->AddGlobalEntry(net::NetLog::TYPE_CANCELLED); 309 310 net_log_temp_file_->ProcessCommand(NetLogTempFile::DO_STOP); 311 VerifyFileAndStateAfterDoStop(); 312 313 int64 new_stop_file_size; 314 EXPECT_TRUE(base::GetFileSize(net_export_log_, &new_stop_file_size)); 315 EXPECT_GE(new_stop_file_size, stop_file_size); 316 } 317