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.
7 #include "base/files/file.h"
8 #include "base/files/file_path.h"
9 #include "base/files/file_util.h"
10 #include "base/files/scoped_temp_dir.h"
11 #include "base/logging.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_split.h"
14 #include "base/time/time.h"
15 #include "chrome/browser/media/webrtc_log_uploader.h"
16 #include "chrome/test/base/testing_profile.h"
17 #include "content/public/test/test_browser_thread_bundle.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 const char kTestTime
[] = "time";
21 const char kTestReportId
[] = "report-id";
22 const char kTestLocalId
[] = "local-id";
24 class WebRtcLogUploaderTest
: public testing::Test
{
26 WebRtcLogUploaderTest() {}
28 bool VerifyNumberOfLines(int expected_lines
) {
29 std::vector
<std::string
> lines
= GetLinesFromListFile();
30 EXPECT_EQ(expected_lines
, static_cast<int>(lines
.size()));
31 return expected_lines
== static_cast<int>(lines
.size());
34 bool VerifyLastLineHasAllInfo() {
35 std::string last_line
= GetLastLineFromListFile();
36 if (last_line
.empty())
38 std::vector
<std::string
> line_parts
;
39 base::SplitString(last_line
, ',', &line_parts
);
40 EXPECT_EQ(3u, line_parts
.size());
41 if (3u != line_parts
.size())
43 // The time (line_parts[0]) is the time when the info was written to the
44 // file which we don't know, so just verify that it's not empty.
45 EXPECT_FALSE(line_parts
[0].empty());
46 EXPECT_STREQ(kTestReportId
, line_parts
[1].c_str());
47 EXPECT_STREQ(kTestLocalId
, line_parts
[2].c_str());
51 bool VerifyLastLineHasLocalIdOnly() {
52 std::string last_line
= GetLastLineFromListFile();
53 if (last_line
.empty())
55 std::vector
<std::string
> line_parts
;
56 base::SplitString(last_line
, ',', &line_parts
);
57 EXPECT_EQ(3u, line_parts
.size());
58 if (3u != line_parts
.size())
60 EXPECT_TRUE(line_parts
[0].empty());
61 EXPECT_TRUE(line_parts
[1].empty());
62 EXPECT_STREQ(kTestLocalId
, line_parts
[2].c_str());
66 bool VerifyLastLineHasUploadTimeAndIdOnly() {
67 std::string last_line
= GetLastLineFromListFile();
68 if (last_line
.empty())
70 std::vector
<std::string
> line_parts
;
71 base::SplitString(last_line
, ',', &line_parts
);
72 EXPECT_EQ(3u, line_parts
.size());
73 if (3u != line_parts
.size())
75 EXPECT_FALSE(line_parts
[0].empty());
76 EXPECT_STREQ(kTestReportId
, line_parts
[1].c_str());
77 EXPECT_TRUE(line_parts
[2].empty());
81 bool AddLinesToTestFile(int number_of_lines
) {
82 base::File
test_list_file(test_list_path_
,
83 base::File::FLAG_OPEN
| base::File::FLAG_APPEND
);
84 EXPECT_TRUE(test_list_file
.IsValid());
85 if (!test_list_file
.IsValid())
88 for (int i
= 0; i
< number_of_lines
; ++i
) {
89 EXPECT_EQ(static_cast<int>(sizeof(kTestTime
)) - 1,
90 test_list_file
.WriteAtCurrentPos(kTestTime
,
91 sizeof(kTestTime
) - 1));
92 EXPECT_EQ(1, test_list_file
.WriteAtCurrentPos(",", 1));
93 EXPECT_EQ(static_cast<int>(sizeof(kTestReportId
)) - 1,
94 test_list_file
.WriteAtCurrentPos(kTestReportId
,
95 sizeof(kTestReportId
) - 1));
96 EXPECT_EQ(1, test_list_file
.WriteAtCurrentPos(",", 1));
97 EXPECT_EQ(static_cast<int>(sizeof(kTestLocalId
)) - 1,
98 test_list_file
.WriteAtCurrentPos(kTestLocalId
,
99 sizeof(kTestLocalId
) - 1));
100 EXPECT_EQ(1, test_list_file
.WriteAtCurrentPos("\n", 1));
105 std::vector
<std::string
> GetLinesFromListFile() {
106 std::string contents
;
107 int read
= base::ReadFileToString(test_list_path_
, &contents
);
110 return std::vector
<std::string
>();
111 // Since every line should end with '\n', the last line should be empty. So
112 // we expect at least two lines including the final empty. Remove the empty
113 // line before returning.
114 std::vector
<std::string
> lines
;
115 base::SplitString(contents
, '\n', &lines
);
116 EXPECT_GT(lines
.size(), 1u);
117 if (lines
.size() < 2)
118 return std::vector
<std::string
>();
119 EXPECT_TRUE(lines
[lines
.size() - 1].empty());
120 if (!lines
[lines
.size() - 1].empty())
121 return std::vector
<std::string
>();
126 std::string
GetLastLineFromListFile() {
127 std::vector
<std::string
> lines
= GetLinesFromListFile();
128 EXPECT_GT(lines
.size(), 0u);
130 return std::string();
131 return lines
[lines
.size() - 1];
134 void VerifyRtpDumpInMultipart(const std::string
& post_data
,
135 const std::string
& dump_name
,
136 const std::string
& dump_content
) {
137 std::vector
<std::string
> lines
;
138 base::SplitStringUsingSubstr(post_data
, "\r\n", &lines
);
140 std::string name_line
= "Content-Disposition: form-data; name=\"";
141 name_line
.append(dump_name
);
142 name_line
.append("\"");
143 name_line
.append("; filename=\"");
144 name_line
.append(dump_name
);
145 name_line
.append(".gz\"");
148 for (; i
< lines
.size(); ++i
) {
149 if (lines
[i
] == name_line
)
153 // The RTP dump takes 4 lines: content-disposition, content-type, empty
154 // line, dump content.
155 EXPECT_LT(i
, lines
.size() - 3);
157 EXPECT_EQ("Content-Type: application/gzip", lines
[i
+ 1]);
158 EXPECT_EQ("", lines
[i
+ 2]);
159 EXPECT_EQ(dump_content
, lines
[i
+ 3]);
162 content::TestBrowserThreadBundle thread_bundle_
;
163 base::FilePath test_list_path_
;
166 TEST_F(WebRtcLogUploaderTest
, AddLocallyStoredLogInfoToUploadListFile
) {
167 // Get a temporary filename. We don't want the file to exist to begin with
168 // since that's the normal use case, hence the delete.
169 ASSERT_TRUE(base::CreateTemporaryFile(&test_list_path_
));
170 EXPECT_TRUE(base::DeleteFile(test_list_path_
, false));
171 scoped_ptr
<WebRtcLogUploader
> webrtc_log_uploader(new WebRtcLogUploader());
173 webrtc_log_uploader
->AddLocallyStoredLogInfoToUploadListFile(test_list_path_
,
175 webrtc_log_uploader
->AddLocallyStoredLogInfoToUploadListFile(test_list_path_
,
177 ASSERT_TRUE(VerifyNumberOfLines(2));
178 ASSERT_TRUE(VerifyLastLineHasLocalIdOnly());
180 const int expected_line_limit
= 50;
181 ASSERT_TRUE(AddLinesToTestFile(expected_line_limit
- 2));
182 ASSERT_TRUE(VerifyNumberOfLines(expected_line_limit
));
183 ASSERT_TRUE(VerifyLastLineHasAllInfo());
185 webrtc_log_uploader
->AddLocallyStoredLogInfoToUploadListFile(test_list_path_
,
187 ASSERT_TRUE(VerifyNumberOfLines(expected_line_limit
));
188 ASSERT_TRUE(VerifyLastLineHasLocalIdOnly());
190 ASSERT_TRUE(AddLinesToTestFile(10));
191 ASSERT_TRUE(VerifyNumberOfLines(60));
192 ASSERT_TRUE(VerifyLastLineHasAllInfo());
194 webrtc_log_uploader
->AddLocallyStoredLogInfoToUploadListFile(test_list_path_
,
196 ASSERT_TRUE(VerifyNumberOfLines(expected_line_limit
));
197 ASSERT_TRUE(VerifyLastLineHasLocalIdOnly());
199 webrtc_log_uploader
->StartShutdown();
202 TEST_F(WebRtcLogUploaderTest
, AddUploadedLogInfoToUploadListFile
) {
203 // Get a temporary filename. We don't want the file to exist to begin with
204 // since that's the normal use case, hence the delete.
205 ASSERT_TRUE(base::CreateTemporaryFile(&test_list_path_
));
206 EXPECT_TRUE(base::DeleteFile(test_list_path_
, false));
207 scoped_ptr
<WebRtcLogUploader
> webrtc_log_uploader(new WebRtcLogUploader());
209 webrtc_log_uploader
->AddLocallyStoredLogInfoToUploadListFile(test_list_path_
,
211 ASSERT_TRUE(VerifyNumberOfLines(1));
212 ASSERT_TRUE(VerifyLastLineHasLocalIdOnly());
214 webrtc_log_uploader
->AddUploadedLogInfoToUploadListFile(
215 test_list_path_
, kTestLocalId
, kTestReportId
);
216 ASSERT_TRUE(VerifyNumberOfLines(1));
217 ASSERT_TRUE(VerifyLastLineHasAllInfo());
219 // Use a local ID that should not be found in the list.
220 webrtc_log_uploader
->AddUploadedLogInfoToUploadListFile(
221 test_list_path_
, "dummy id", kTestReportId
);
222 ASSERT_TRUE(VerifyNumberOfLines(2));
223 ASSERT_TRUE(VerifyLastLineHasUploadTimeAndIdOnly());
225 webrtc_log_uploader
->StartShutdown();
228 TEST_F(WebRtcLogUploaderTest
, AddRtpDumpsToPostedData
) {
229 base::ScopedTempDir temp_dir
;
230 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
232 scoped_ptr
<WebRtcLogUploader
> webrtc_log_uploader(new WebRtcLogUploader());
234 std::string post_data
;
235 webrtc_log_uploader
->OverrideUploadWithBufferForTesting(&post_data
);
237 // Create the fake dump files.
238 const base::FilePath incoming_dump
= temp_dir
.path().AppendASCII("recv");
239 const base::FilePath outgoing_dump
= temp_dir
.path().AppendASCII("send");
240 const std::string incoming_dump_content
= "dummy incoming";
241 const std::string outgoing_dump_content
= "dummy outgoing";
243 base::WriteFile(incoming_dump
,
244 &incoming_dump_content
[0],
245 incoming_dump_content
.size());
246 base::WriteFile(outgoing_dump
,
247 &outgoing_dump_content
[0],
248 outgoing_dump_content
.size());
250 WebRtcLogUploadDoneData upload_done_data
;
251 upload_done_data
.log_path
= temp_dir
.path().AppendASCII("log");
253 scoped_ptr
<Profile
> profile(new TestingProfile());
254 scoped_refptr
<WebRtcLoggingHandlerHost
> host(
255 new WebRtcLoggingHandlerHost(profile
.get()));
257 upload_done_data
.incoming_rtp_dump
= incoming_dump
;
258 upload_done_data
.outgoing_rtp_dump
= outgoing_dump
;
259 upload_done_data
.host
= host
.get();
261 scoped_ptr
<WebRtcLogBuffer
> log(new WebRtcLogBuffer());
263 webrtc_log_uploader
->LoggingStoppedDoUpload(
264 log
.Pass(), make_scoped_ptr(new MetaDataMap()), upload_done_data
);
266 VerifyRtpDumpInMultipart(post_data
, "rtpdump_recv", incoming_dump_content
);
267 VerifyRtpDumpInMultipart(post_data
, "rtpdump_send", outgoing_dump_content
);
269 webrtc_log_uploader
->StartShutdown();