blob: 4274215491f8999036aedf03c15ec51040627c5d [file] [log] [blame]
Elad Alon83ccca12017-10-04 13:18:26 +02001/*
2 * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Niels Möllerd8b9ed72019-05-08 13:53:51 +020011#include "api/rtc_event_log_output_file.h"
Danil Chapovalov6e9d8952018-04-09 20:30:51 +020012
Elad Alon83ccca12017-10-04 13:18:26 +020013#include <fstream>
Yves Gerey3e707812018-11-28 16:47:49 +010014#include <iterator>
Elad Alon83ccca12017-10-04 13:18:26 +020015#include <memory>
16#include <string>
17
Danil Chapovalov6e9d8952018-04-09 20:30:51 +020018#include "rtc_base/checks.h"
Elad Alon83ccca12017-10-04 13:18:26 +020019#include "test/gtest.h"
Steve Anton10542f22019-01-11 09:11:00 -080020#include "test/testsupport/file_utils.h"
Elad Alon83ccca12017-10-04 13:18:26 +020021
22namespace webrtc {
23
24class RtcEventLogOutputFileTest : public ::testing::Test {
25 public:
26 RtcEventLogOutputFileTest() : output_file_name_(GetOutputFilePath()) {
27 // Ensure no leftovers from previous runs, which might not have terminated
28 // in an orderly fashion.
29 remove(output_file_name_.c_str());
30 }
31
32 ~RtcEventLogOutputFileTest() override { remove(output_file_name_.c_str()); }
33
34 protected:
35 std::string GetOutputFilePath() const {
36 auto test_info = ::testing::UnitTest::GetInstance()->current_test_info();
37 return test::OutputPath() + test_info->test_case_name() + test_info->name();
38 }
39
40 std::string GetOutputFileContents() const {
41 std::ifstream file(output_file_name_,
42 std::ios_base::in | std::ios_base::binary);
43 RTC_CHECK(file.is_open());
44 RTC_CHECK(file.good());
45 std::string file_str((std::istreambuf_iterator<char>(file)),
46 std::istreambuf_iterator<char>());
47 return file_str;
48 }
49
50 const std::string output_file_name_;
51};
52
53TEST_F(RtcEventLogOutputFileTest, NonDefectiveOutputsStartOutActive) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +020054 auto output_file = std::make_unique<RtcEventLogOutputFile>(output_file_name_);
Elad Alon83ccca12017-10-04 13:18:26 +020055 EXPECT_TRUE(output_file->IsActive());
56}
57
58TEST_F(RtcEventLogOutputFileTest, DefectiveOutputsStartOutInactive) {
59 const std::string illegal_filename = "/////////";
Mirko Bonadei317a1f02019-09-17 17:06:18 +020060 auto output_file = std::make_unique<RtcEventLogOutputFile>(illegal_filename);
Elad Alon83ccca12017-10-04 13:18:26 +020061 EXPECT_FALSE(output_file->IsActive());
62}
63
64// Sanity over opening a file (by filename) with an unlimited size.
65TEST_F(RtcEventLogOutputFileTest, UnlimitedOutputFile) {
66 const std::string output_str = "one two three";
67
Mirko Bonadei317a1f02019-09-17 17:06:18 +020068 auto output_file = std::make_unique<RtcEventLogOutputFile>(output_file_name_);
Elad Alon83ccca12017-10-04 13:18:26 +020069 output_file->Write(output_str);
70 output_file.reset(); // Closing the file flushes the buffer to disk.
71
72 EXPECT_EQ(GetOutputFileContents(), output_str);
73}
74
75// Do not allow writing more bytes to the file than
76TEST_F(RtcEventLogOutputFileTest, LimitedOutputFileCappedToCapacity) {
77 // Fit two bytes, then the third should be rejected.
78 auto output_file =
Mirko Bonadei317a1f02019-09-17 17:06:18 +020079 std::make_unique<RtcEventLogOutputFile>(output_file_name_, 2);
Elad Alon83ccca12017-10-04 13:18:26 +020080
81 output_file->Write("1");
82 output_file->Write("2");
83 output_file->Write("3");
84 // Unsuccessful writes close the file; no need to delete the output to flush.
85
86 EXPECT_EQ(GetOutputFileContents(), "12");
87}
88
89// Make sure that calls to Write() either write everything to the file, or
90// nothing (short of underlying issues in the module that handles the file,
91// which would be beyond our control).
92TEST_F(RtcEventLogOutputFileTest, DoNotWritePartialLines) {
93 const std::string output_str_1 = "0123456789";
94 const std::string output_str_2 = "abcdefghij";
95
96 // Set a file size limit just shy of fitting the entire second line.
97 const size_t size_limit = output_str_1.length() + output_str_2.length() - 1;
98 auto output_file =
Mirko Bonadei317a1f02019-09-17 17:06:18 +020099 std::make_unique<RtcEventLogOutputFile>(output_file_name_, size_limit);
Elad Alon83ccca12017-10-04 13:18:26 +0200100
101 output_file->Write(output_str_1);
102 output_file->Write(output_str_2);
103 // Unsuccessful writes close the file; no need to delete the output to flush.
104
105 EXPECT_EQ(GetOutputFileContents(), output_str_1);
106}
107
108TEST_F(RtcEventLogOutputFileTest, UnsuccessfulWriteReturnsFalse) {
109 auto output_file =
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200110 std::make_unique<RtcEventLogOutputFile>(output_file_name_, 2);
Elad Alon83ccca12017-10-04 13:18:26 +0200111 EXPECT_FALSE(output_file->Write("abc"));
112}
113
114TEST_F(RtcEventLogOutputFileTest, SuccessfulWriteReturnsTrue) {
115 auto output_file =
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200116 std::make_unique<RtcEventLogOutputFile>(output_file_name_, 3);
Elad Alon83ccca12017-10-04 13:18:26 +0200117 EXPECT_TRUE(output_file->Write("abc"));
118}
119
120// Even if capacity is reached, a successful write leaves the output active.
121TEST_F(RtcEventLogOutputFileTest, FileStillActiveAfterSuccessfulWrite) {
122 auto output_file =
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200123 std::make_unique<RtcEventLogOutputFile>(output_file_name_, 3);
Elad Alon83ccca12017-10-04 13:18:26 +0200124 ASSERT_TRUE(output_file->Write("abc"));
125 EXPECT_TRUE(output_file->IsActive());
126}
127
128// Unsuccessful writes switch the output to inactive, even if capacity has
129// not yet been reached.
130TEST_F(RtcEventLogOutputFileTest, FileInactiveAfterUnsuccessfulWrite) {
131 auto output_file =
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200132 std::make_unique<RtcEventLogOutputFile>(output_file_name_, 2);
Elad Alon83ccca12017-10-04 13:18:26 +0200133 ASSERT_FALSE(output_file->Write("abc"));
134 EXPECT_FALSE(output_file->IsActive());
135}
136
137TEST_F(RtcEventLogOutputFileTest, AllowReasonableFileSizeLimits) {
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200138 auto output_file = std::make_unique<RtcEventLogOutputFile>(
Elad Alon83ccca12017-10-04 13:18:26 +0200139 output_file_name_, RtcEventLogOutputFile::kMaxReasonableFileSize);
140 EXPECT_TRUE(output_file->IsActive());
141}
142
Elad Alon8233bfe2017-10-05 15:27:29 +0200143#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
Tommi909f3a52020-05-18 16:47:56 +0200144class RtcEventLogOutputFileDeathTest : public RtcEventLogOutputFileTest {};
145
146TEST_F(RtcEventLogOutputFileDeathTest, WritingToInactiveFileForbidden) {
Elad Alon8233bfe2017-10-05 15:27:29 +0200147 RtcEventLogOutputFile output_file(output_file_name_, 2);
148 ASSERT_FALSE(output_file.Write("abc"));
149 ASSERT_FALSE(output_file.IsActive());
150 EXPECT_DEATH(output_file.Write("abc"), "");
151}
152
Tommi909f3a52020-05-18 16:47:56 +0200153TEST_F(RtcEventLogOutputFileDeathTest, DisallowUnreasonableFileSizeLimits) {
Elad Alon8233bfe2017-10-05 15:27:29 +0200154 // Keeping in a temporary unique_ptr to make it clearer that the death is
155 // triggered by construction, not destruction.
156 std::unique_ptr<RtcEventLogOutputFile> output_file;
157 auto create_output_file = [&] {
158 const size_t unreasonable_size =
159 RtcEventLogOutputFile::kMaxReasonableFileSize + 1;
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200160 output_file = std::make_unique<RtcEventLogOutputFile>(output_file_name_,
161 unreasonable_size);
Elad Alon8233bfe2017-10-05 15:27:29 +0200162 };
163 EXPECT_DEATH(create_output_file(), "");
164}
Elad Alon8233bfe2017-10-05 15:27:29 +0200165#endif
166
Elad Alon83ccca12017-10-04 13:18:26 +0200167} // namespace webrtc