blob: bffda0c8643b44e017b5bcdc4f221fb4d9160fca [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
Karl Wiberg918f50c2018-07-05 11:40:33 +020018#include "absl/memory/memory.h"
Danil Chapovalov6e9d8952018-04-09 20:30:51 +020019#include "rtc_base/checks.h"
Elad Alon83ccca12017-10-04 13:18:26 +020020#include "test/gtest.h"
Steve Anton10542f22019-01-11 09:11:00 -080021#include "test/testsupport/file_utils.h"
Elad Alon83ccca12017-10-04 13:18:26 +020022
23namespace webrtc {
24
25class RtcEventLogOutputFileTest : public ::testing::Test {
26 public:
27 RtcEventLogOutputFileTest() : output_file_name_(GetOutputFilePath()) {
28 // Ensure no leftovers from previous runs, which might not have terminated
29 // in an orderly fashion.
30 remove(output_file_name_.c_str());
31 }
32
33 ~RtcEventLogOutputFileTest() override { remove(output_file_name_.c_str()); }
34
35 protected:
36 std::string GetOutputFilePath() const {
37 auto test_info = ::testing::UnitTest::GetInstance()->current_test_info();
38 return test::OutputPath() + test_info->test_case_name() + test_info->name();
39 }
40
41 std::string GetOutputFileContents() const {
42 std::ifstream file(output_file_name_,
43 std::ios_base::in | std::ios_base::binary);
44 RTC_CHECK(file.is_open());
45 RTC_CHECK(file.good());
46 std::string file_str((std::istreambuf_iterator<char>(file)),
47 std::istreambuf_iterator<char>());
48 return file_str;
49 }
50
51 const std::string output_file_name_;
52};
53
54TEST_F(RtcEventLogOutputFileTest, NonDefectiveOutputsStartOutActive) {
Karl Wiberg918f50c2018-07-05 11:40:33 +020055 auto output_file =
56 absl::make_unique<RtcEventLogOutputFile>(output_file_name_);
Elad Alon83ccca12017-10-04 13:18:26 +020057 EXPECT_TRUE(output_file->IsActive());
58}
59
60TEST_F(RtcEventLogOutputFileTest, DefectiveOutputsStartOutInactive) {
61 const std::string illegal_filename = "/////////";
Karl Wiberg918f50c2018-07-05 11:40:33 +020062 auto output_file = absl::make_unique<RtcEventLogOutputFile>(illegal_filename);
Elad Alon83ccca12017-10-04 13:18:26 +020063 EXPECT_FALSE(output_file->IsActive());
64}
65
66// Sanity over opening a file (by filename) with an unlimited size.
67TEST_F(RtcEventLogOutputFileTest, UnlimitedOutputFile) {
68 const std::string output_str = "one two three";
69
Karl Wiberg918f50c2018-07-05 11:40:33 +020070 auto output_file =
71 absl::make_unique<RtcEventLogOutputFile>(output_file_name_);
Elad Alon83ccca12017-10-04 13:18:26 +020072 output_file->Write(output_str);
73 output_file.reset(); // Closing the file flushes the buffer to disk.
74
75 EXPECT_EQ(GetOutputFileContents(), output_str);
76}
77
78// Do not allow writing more bytes to the file than
79TEST_F(RtcEventLogOutputFileTest, LimitedOutputFileCappedToCapacity) {
80 // Fit two bytes, then the third should be rejected.
81 auto output_file =
Karl Wiberg918f50c2018-07-05 11:40:33 +020082 absl::make_unique<RtcEventLogOutputFile>(output_file_name_, 2);
Elad Alon83ccca12017-10-04 13:18:26 +020083
84 output_file->Write("1");
85 output_file->Write("2");
86 output_file->Write("3");
87 // Unsuccessful writes close the file; no need to delete the output to flush.
88
89 EXPECT_EQ(GetOutputFileContents(), "12");
90}
91
92// Make sure that calls to Write() either write everything to the file, or
93// nothing (short of underlying issues in the module that handles the file,
94// which would be beyond our control).
95TEST_F(RtcEventLogOutputFileTest, DoNotWritePartialLines) {
96 const std::string output_str_1 = "0123456789";
97 const std::string output_str_2 = "abcdefghij";
98
99 // Set a file size limit just shy of fitting the entire second line.
100 const size_t size_limit = output_str_1.length() + output_str_2.length() - 1;
101 auto output_file =
Karl Wiberg918f50c2018-07-05 11:40:33 +0200102 absl::make_unique<RtcEventLogOutputFile>(output_file_name_, size_limit);
Elad Alon83ccca12017-10-04 13:18:26 +0200103
104 output_file->Write(output_str_1);
105 output_file->Write(output_str_2);
106 // Unsuccessful writes close the file; no need to delete the output to flush.
107
108 EXPECT_EQ(GetOutputFileContents(), output_str_1);
109}
110
111TEST_F(RtcEventLogOutputFileTest, UnsuccessfulWriteReturnsFalse) {
112 auto output_file =
Karl Wiberg918f50c2018-07-05 11:40:33 +0200113 absl::make_unique<RtcEventLogOutputFile>(output_file_name_, 2);
Elad Alon83ccca12017-10-04 13:18:26 +0200114 EXPECT_FALSE(output_file->Write("abc"));
115}
116
117TEST_F(RtcEventLogOutputFileTest, SuccessfulWriteReturnsTrue) {
118 auto output_file =
Karl Wiberg918f50c2018-07-05 11:40:33 +0200119 absl::make_unique<RtcEventLogOutputFile>(output_file_name_, 3);
Elad Alon83ccca12017-10-04 13:18:26 +0200120 EXPECT_TRUE(output_file->Write("abc"));
121}
122
123// Even if capacity is reached, a successful write leaves the output active.
124TEST_F(RtcEventLogOutputFileTest, FileStillActiveAfterSuccessfulWrite) {
125 auto output_file =
Karl Wiberg918f50c2018-07-05 11:40:33 +0200126 absl::make_unique<RtcEventLogOutputFile>(output_file_name_, 3);
Elad Alon83ccca12017-10-04 13:18:26 +0200127 ASSERT_TRUE(output_file->Write("abc"));
128 EXPECT_TRUE(output_file->IsActive());
129}
130
131// Unsuccessful writes switch the output to inactive, even if capacity has
132// not yet been reached.
133TEST_F(RtcEventLogOutputFileTest, FileInactiveAfterUnsuccessfulWrite) {
134 auto output_file =
Karl Wiberg918f50c2018-07-05 11:40:33 +0200135 absl::make_unique<RtcEventLogOutputFile>(output_file_name_, 2);
Elad Alon83ccca12017-10-04 13:18:26 +0200136 ASSERT_FALSE(output_file->Write("abc"));
137 EXPECT_FALSE(output_file->IsActive());
138}
139
140TEST_F(RtcEventLogOutputFileTest, AllowReasonableFileSizeLimits) {
Karl Wiberg918f50c2018-07-05 11:40:33 +0200141 auto output_file = absl::make_unique<RtcEventLogOutputFile>(
Elad Alon83ccca12017-10-04 13:18:26 +0200142 output_file_name_, RtcEventLogOutputFile::kMaxReasonableFileSize);
143 EXPECT_TRUE(output_file->IsActive());
144}
145
Elad Alon8233bfe2017-10-05 15:27:29 +0200146#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
Elad Alon8233bfe2017-10-05 15:27:29 +0200147TEST_F(RtcEventLogOutputFileTest, WritingToInactiveFileForbidden) {
148 RtcEventLogOutputFile output_file(output_file_name_, 2);
149 ASSERT_FALSE(output_file.Write("abc"));
150 ASSERT_FALSE(output_file.IsActive());
151 EXPECT_DEATH(output_file.Write("abc"), "");
152}
153
154TEST_F(RtcEventLogOutputFileTest, DisallowUnreasonableFileSizeLimits) {
155 // Keeping in a temporary unique_ptr to make it clearer that the death is
156 // triggered by construction, not destruction.
157 std::unique_ptr<RtcEventLogOutputFile> output_file;
158 auto create_output_file = [&] {
159 const size_t unreasonable_size =
160 RtcEventLogOutputFile::kMaxReasonableFileSize + 1;
Karl Wiberg918f50c2018-07-05 11:40:33 +0200161 output_file = absl::make_unique<RtcEventLogOutputFile>(output_file_name_,
162 unreasonable_size);
Elad Alon8233bfe2017-10-05 15:27:29 +0200163 };
164 EXPECT_DEATH(create_output_file(), "");
165}
Elad Alon8233bfe2017-10-05 15:27:29 +0200166#endif
167
Elad Alon83ccca12017-10-04 13:18:26 +0200168} // namespace webrtc