| OLD | NEW |
| (Empty) |
| 1 // Copyright 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/media/webrtc_log_uploader.h" | |
| 6 | |
| 7 #include <stddef.h> | |
| 8 | |
| 9 #include <string> | |
| 10 #include <utility> | |
| 11 | |
| 12 #include "base/files/file.h" | |
| 13 #include "base/files/file_path.h" | |
| 14 #include "base/files/file_util.h" | |
| 15 #include "base/files/scoped_temp_dir.h" | |
| 16 #include "base/logging.h" | |
| 17 #include "base/memory/ptr_util.h" | |
| 18 #include "base/run_loop.h" | |
| 19 #include "base/strings/string_number_conversions.h" | |
| 20 #include "base/strings/string_split.h" | |
| 21 #include "base/time/time.h" | |
| 22 #include "chrome/test/base/testing_profile.h" | |
| 23 #include "content/public/test/test_browser_thread_bundle.h" | |
| 24 #include "testing/gtest/include/gtest/gtest.h" | |
| 25 | |
| 26 const char kTestTime[] = "time"; | |
| 27 const char kTestReportId[] = "report-id"; | |
| 28 const char kTestLocalId[] = "local-id"; | |
| 29 | |
| 30 class WebRtcLogUploaderTest : public testing::Test { | |
| 31 public: | |
| 32 WebRtcLogUploaderTest() {} | |
| 33 | |
| 34 bool VerifyNumberOfLines(int expected_lines) { | |
| 35 std::vector<std::string> lines = GetLinesFromListFile(); | |
| 36 EXPECT_EQ(expected_lines, static_cast<int>(lines.size())); | |
| 37 return expected_lines == static_cast<int>(lines.size()); | |
| 38 } | |
| 39 | |
| 40 bool VerifyLastLineHasAllInfo() { | |
| 41 std::string last_line = GetLastLineFromListFile(); | |
| 42 if (last_line.empty()) | |
| 43 return false; | |
| 44 std::vector<std::string> line_parts = base::SplitString( | |
| 45 last_line, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | |
| 46 EXPECT_EQ(4u, line_parts.size()); | |
| 47 if (4u != line_parts.size()) | |
| 48 return false; | |
| 49 // The times (indices 0 and 3) is the time when the info was written to the | |
| 50 // file which we don't know, so just verify that it's not empty. | |
| 51 EXPECT_FALSE(line_parts[0].empty()); | |
| 52 EXPECT_STREQ(kTestReportId, line_parts[1].c_str()); | |
| 53 EXPECT_STREQ(kTestLocalId, line_parts[2].c_str()); | |
| 54 EXPECT_FALSE(line_parts[3].empty()); | |
| 55 return true; | |
| 56 } | |
| 57 | |
| 58 // Verify that the last line contains the correct info for a local storage. | |
| 59 bool VerifyLastLineHasLocalStorageInfoOnly() { | |
| 60 std::string last_line = GetLastLineFromListFile(); | |
| 61 if (last_line.empty()) | |
| 62 return false; | |
| 63 std::vector<std::string> line_parts = base::SplitString( | |
| 64 last_line, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | |
| 65 EXPECT_EQ(4u, line_parts.size()); | |
| 66 if (4u != line_parts.size()) | |
| 67 return false; | |
| 68 EXPECT_TRUE(line_parts[0].empty()); | |
| 69 EXPECT_TRUE(line_parts[1].empty()); | |
| 70 EXPECT_STREQ(kTestLocalId, line_parts[2].c_str()); | |
| 71 EXPECT_FALSE(line_parts[3].empty()); | |
| 72 return true; | |
| 73 } | |
| 74 | |
| 75 // Verify that the last line contains the correct info for an upload. | |
| 76 bool VerifyLastLineHasUploadInfoOnly() { | |
| 77 std::string last_line = GetLastLineFromListFile(); | |
| 78 if (last_line.empty()) | |
| 79 return false; | |
| 80 std::vector<std::string> line_parts = base::SplitString( | |
| 81 last_line, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | |
| 82 EXPECT_EQ(4u, line_parts.size()); | |
| 83 if (4u != line_parts.size()) | |
| 84 return false; | |
| 85 EXPECT_FALSE(line_parts[0].empty()); | |
| 86 EXPECT_STREQ(kTestReportId, line_parts[1].c_str()); | |
| 87 EXPECT_TRUE(line_parts[2].empty()); | |
| 88 EXPECT_FALSE(line_parts[3].empty()); | |
| 89 return true; | |
| 90 } | |
| 91 | |
| 92 bool AddLinesToTestFile(int number_of_lines) { | |
| 93 base::File test_list_file(test_list_path_, | |
| 94 base::File::FLAG_OPEN | base::File::FLAG_APPEND); | |
| 95 EXPECT_TRUE(test_list_file.IsValid()); | |
| 96 if (!test_list_file.IsValid()) | |
| 97 return false; | |
| 98 | |
| 99 for (int i = 0; i < number_of_lines; ++i) { | |
| 100 EXPECT_EQ(static_cast<int>(sizeof(kTestTime)) - 1, | |
| 101 test_list_file.WriteAtCurrentPos(kTestTime, | |
| 102 sizeof(kTestTime) - 1)); | |
| 103 EXPECT_EQ(1, test_list_file.WriteAtCurrentPos(",", 1)); | |
| 104 EXPECT_EQ(static_cast<int>(sizeof(kTestReportId)) - 1, | |
| 105 test_list_file.WriteAtCurrentPos(kTestReportId, | |
| 106 sizeof(kTestReportId) - 1)); | |
| 107 EXPECT_EQ(1, test_list_file.WriteAtCurrentPos(",", 1)); | |
| 108 EXPECT_EQ(static_cast<int>(sizeof(kTestLocalId)) - 1, | |
| 109 test_list_file.WriteAtCurrentPos(kTestLocalId, | |
| 110 sizeof(kTestLocalId) - 1)); | |
| 111 EXPECT_EQ(1, test_list_file.WriteAtCurrentPos(",", 1)); | |
| 112 EXPECT_EQ(static_cast<int>(sizeof(kTestTime)) - 1, | |
| 113 test_list_file.WriteAtCurrentPos(kTestTime, | |
| 114 sizeof(kTestTime) - 1)); | |
| 115 EXPECT_EQ(1, test_list_file.WriteAtCurrentPos("\n", 1)); | |
| 116 } | |
| 117 return true; | |
| 118 } | |
| 119 | |
| 120 std::vector<std::string> GetLinesFromListFile() { | |
| 121 std::string contents; | |
| 122 int read = base::ReadFileToString(test_list_path_, &contents); | |
| 123 EXPECT_GT(read, 0); | |
| 124 if (read == 0) | |
| 125 return std::vector<std::string>(); | |
| 126 // Since every line should end with '\n', the last line should be empty. So | |
| 127 // we expect at least two lines including the final empty. Remove the empty | |
| 128 // line before returning. | |
| 129 std::vector<std::string> lines = base::SplitString( | |
| 130 contents, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | |
| 131 EXPECT_GT(lines.size(), 1u); | |
| 132 if (lines.size() < 2) | |
| 133 return std::vector<std::string>(); | |
| 134 EXPECT_TRUE(lines.back().empty()); | |
| 135 if (!lines.back().empty()) | |
| 136 return std::vector<std::string>(); | |
| 137 lines.pop_back(); | |
| 138 return lines; | |
| 139 } | |
| 140 | |
| 141 std::string GetLastLineFromListFile() { | |
| 142 std::vector<std::string> lines = GetLinesFromListFile(); | |
| 143 EXPECT_GT(lines.size(), 0u); | |
| 144 if (lines.empty()) | |
| 145 return std::string(); | |
| 146 return lines[lines.size() - 1]; | |
| 147 } | |
| 148 | |
| 149 void VerifyRtpDumpInMultipart(const std::string& post_data, | |
| 150 const std::string& dump_name, | |
| 151 const std::string& dump_content) { | |
| 152 std::vector<std::string> lines; | |
| 153 base::SplitStringUsingSubstr(post_data, "\r\n", &lines); | |
| 154 | |
| 155 std::string name_line = "Content-Disposition: form-data; name=\""; | |
| 156 name_line.append(dump_name); | |
| 157 name_line.append("\""); | |
| 158 name_line.append("; filename=\""); | |
| 159 name_line.append(dump_name); | |
| 160 name_line.append(".gz\""); | |
| 161 | |
| 162 size_t i = 0; | |
| 163 for (; i < lines.size(); ++i) { | |
| 164 if (lines[i] == name_line) | |
| 165 break; | |
| 166 } | |
| 167 | |
| 168 // The RTP dump takes 4 lines: content-disposition, content-type, empty | |
| 169 // line, dump content. | |
| 170 EXPECT_LT(i, lines.size() - 3); | |
| 171 | |
| 172 EXPECT_EQ("Content-Type: application/gzip", lines[i + 1]); | |
| 173 EXPECT_EQ("", lines[i + 2]); | |
| 174 EXPECT_EQ(dump_content, lines[i + 3]); | |
| 175 } | |
| 176 | |
| 177 void FlushIOThread() { | |
| 178 base::RunLoop run_loop; | |
| 179 content::BrowserThread::PostTask( | |
| 180 content::BrowserThread::IO, FROM_HERE, run_loop.QuitClosure()); | |
| 181 run_loop.Run(); | |
| 182 } | |
| 183 | |
| 184 content::TestBrowserThreadBundle thread_bundle_; | |
| 185 base::FilePath test_list_path_; | |
| 186 }; | |
| 187 | |
| 188 TEST_F(WebRtcLogUploaderTest, AddLocallyStoredLogInfoToUploadListFile) { | |
| 189 // Get a temporary filename. We don't want the file to exist to begin with | |
| 190 // since that's the normal use case, hence the delete. | |
| 191 ASSERT_TRUE(base::CreateTemporaryFile(&test_list_path_)); | |
| 192 EXPECT_TRUE(base::DeleteFile(test_list_path_, false)); | |
| 193 std::unique_ptr<WebRtcLogUploader> webrtc_log_uploader( | |
| 194 new WebRtcLogUploader()); | |
| 195 | |
| 196 webrtc_log_uploader->AddLocallyStoredLogInfoToUploadListFile(test_list_path_, | |
| 197 kTestLocalId); | |
| 198 webrtc_log_uploader->AddLocallyStoredLogInfoToUploadListFile(test_list_path_, | |
| 199 kTestLocalId); | |
| 200 ASSERT_TRUE(VerifyNumberOfLines(2)); | |
| 201 ASSERT_TRUE(VerifyLastLineHasLocalStorageInfoOnly()); | |
| 202 | |
| 203 const int expected_line_limit = 50; | |
| 204 ASSERT_TRUE(AddLinesToTestFile(expected_line_limit - 2)); | |
| 205 ASSERT_TRUE(VerifyNumberOfLines(expected_line_limit)); | |
| 206 ASSERT_TRUE(VerifyLastLineHasAllInfo()); | |
| 207 | |
| 208 webrtc_log_uploader->AddLocallyStoredLogInfoToUploadListFile(test_list_path_, | |
| 209 kTestLocalId); | |
| 210 ASSERT_TRUE(VerifyNumberOfLines(expected_line_limit)); | |
| 211 ASSERT_TRUE(VerifyLastLineHasLocalStorageInfoOnly()); | |
| 212 | |
| 213 ASSERT_TRUE(AddLinesToTestFile(10)); | |
| 214 ASSERT_TRUE(VerifyNumberOfLines(60)); | |
| 215 ASSERT_TRUE(VerifyLastLineHasAllInfo()); | |
| 216 | |
| 217 webrtc_log_uploader->AddLocallyStoredLogInfoToUploadListFile(test_list_path_, | |
| 218 kTestLocalId); | |
| 219 ASSERT_TRUE(VerifyNumberOfLines(expected_line_limit)); | |
| 220 ASSERT_TRUE(VerifyLastLineHasLocalStorageInfoOnly()); | |
| 221 | |
| 222 webrtc_log_uploader->StartShutdown(); | |
| 223 FlushIOThread(); | |
| 224 } | |
| 225 | |
| 226 TEST_F(WebRtcLogUploaderTest, AddUploadedLogInfoToUploadListFile) { | |
| 227 // Get a temporary filename. We don't want the file to exist to begin with | |
| 228 // since that's the normal use case, hence the delete. | |
| 229 ASSERT_TRUE(base::CreateTemporaryFile(&test_list_path_)); | |
| 230 EXPECT_TRUE(base::DeleteFile(test_list_path_, false)); | |
| 231 std::unique_ptr<WebRtcLogUploader> webrtc_log_uploader( | |
| 232 new WebRtcLogUploader()); | |
| 233 | |
| 234 webrtc_log_uploader->AddLocallyStoredLogInfoToUploadListFile(test_list_path_, | |
| 235 kTestLocalId); | |
| 236 ASSERT_TRUE(VerifyNumberOfLines(1)); | |
| 237 ASSERT_TRUE(VerifyLastLineHasLocalStorageInfoOnly()); | |
| 238 | |
| 239 webrtc_log_uploader->AddUploadedLogInfoToUploadListFile( | |
| 240 test_list_path_, kTestLocalId, kTestReportId); | |
| 241 ASSERT_TRUE(VerifyNumberOfLines(1)); | |
| 242 ASSERT_TRUE(VerifyLastLineHasAllInfo()); | |
| 243 | |
| 244 // Use a local ID that should not be found in the list. | |
| 245 webrtc_log_uploader->AddUploadedLogInfoToUploadListFile( | |
| 246 test_list_path_, "dummy id", kTestReportId); | |
| 247 ASSERT_TRUE(VerifyNumberOfLines(2)); | |
| 248 ASSERT_TRUE(VerifyLastLineHasUploadInfoOnly()); | |
| 249 | |
| 250 webrtc_log_uploader->StartShutdown(); | |
| 251 FlushIOThread(); | |
| 252 } | |
| 253 | |
| 254 TEST_F(WebRtcLogUploaderTest, AddRtpDumpsToPostedData) { | |
| 255 base::ScopedTempDir temp_dir; | |
| 256 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | |
| 257 | |
| 258 std::unique_ptr<WebRtcLogUploader> webrtc_log_uploader( | |
| 259 new WebRtcLogUploader()); | |
| 260 | |
| 261 std::string post_data; | |
| 262 webrtc_log_uploader->OverrideUploadWithBufferForTesting(&post_data); | |
| 263 | |
| 264 // Create the fake dump files. | |
| 265 const base::FilePath incoming_dump = temp_dir.path().AppendASCII("recv"); | |
| 266 const base::FilePath outgoing_dump = temp_dir.path().AppendASCII("send"); | |
| 267 const std::string incoming_dump_content = "dummy incoming"; | |
| 268 const std::string outgoing_dump_content = "dummy outgoing"; | |
| 269 | |
| 270 base::WriteFile(incoming_dump, | |
| 271 &incoming_dump_content[0], | |
| 272 incoming_dump_content.size()); | |
| 273 base::WriteFile(outgoing_dump, | |
| 274 &outgoing_dump_content[0], | |
| 275 outgoing_dump_content.size()); | |
| 276 | |
| 277 WebRtcLogUploadDoneData upload_done_data; | |
| 278 upload_done_data.log_path = temp_dir.path().AppendASCII("log"); | |
| 279 | |
| 280 std::unique_ptr<Profile> profile(new TestingProfile()); | |
| 281 scoped_refptr<WebRtcLoggingHandlerHost> host(new WebRtcLoggingHandlerHost( | |
| 282 -1, profile.get(), webrtc_log_uploader.get())); | |
| 283 | |
| 284 upload_done_data.incoming_rtp_dump = incoming_dump; | |
| 285 upload_done_data.outgoing_rtp_dump = outgoing_dump; | |
| 286 upload_done_data.host = host.get(); | |
| 287 | |
| 288 std::unique_ptr<WebRtcLogBuffer> log(new WebRtcLogBuffer()); | |
| 289 log->SetComplete(); | |
| 290 webrtc_log_uploader->LoggingStoppedDoUpload( | |
| 291 std::move(log), base::WrapUnique(new MetaDataMap()), upload_done_data); | |
| 292 | |
| 293 VerifyRtpDumpInMultipart(post_data, "rtpdump_recv", incoming_dump_content); | |
| 294 VerifyRtpDumpInMultipart(post_data, "rtpdump_send", outgoing_dump_content); | |
| 295 | |
| 296 webrtc_log_uploader->StartShutdown(); | |
| 297 FlushIOThread(); | |
| 298 } | |
| OLD | NEW |