rtc_event_log_output_file_unittest.cc (6264B)
1 /* 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 11 #include "api/rtc_event_log_output_file.h" 12 13 #include <stdio.h> 14 15 #include <cstddef> 16 #include <cstdio> 17 #include <fstream> 18 #include <ios> 19 #include <iterator> 20 #include <memory> 21 #include <string> 22 23 #include "rtc_base/checks.h" 24 #include "test/gtest.h" 25 #include "test/testsupport/file_utils.h" 26 27 namespace webrtc { 28 29 class RtcEventLogOutputFileTest : public ::testing::Test { 30 public: 31 RtcEventLogOutputFileTest() : output_file_name_(GetOutputFilePath()) { 32 // Ensure no leftovers from previous runs, which might not have terminated 33 // in an orderly fashion. 34 remove(output_file_name_.c_str()); 35 } 36 37 ~RtcEventLogOutputFileTest() override { remove(output_file_name_.c_str()); } 38 39 protected: 40 std::string GetOutputFilePath() const { 41 auto test_info = ::testing::UnitTest::GetInstance()->current_test_info(); 42 return test::OutputPathWithRandomDirectory() + test_info->test_case_name() + 43 test_info->name(); 44 } 45 46 std::string GetOutputFileContents() const { 47 std::ifstream file(output_file_name_, 48 std::ios_base::in | std::ios_base::binary); 49 RTC_CHECK(file.is_open()); 50 RTC_CHECK(file.good()); 51 std::string file_str((std::istreambuf_iterator<char>(file)), 52 std::istreambuf_iterator<char>()); 53 return file_str; 54 } 55 56 const std::string output_file_name_; 57 }; 58 59 TEST_F(RtcEventLogOutputFileTest, NonDefectiveOutputsStartOutActive) { 60 auto output_file = std::make_unique<RtcEventLogOutputFile>(output_file_name_); 61 EXPECT_TRUE(output_file->IsActive()); 62 } 63 64 TEST_F(RtcEventLogOutputFileTest, DefectiveOutputsStartOutInactive) { 65 const std::string illegal_filename = "/////////"; 66 auto output_file = std::make_unique<RtcEventLogOutputFile>(illegal_filename); 67 EXPECT_FALSE(output_file->IsActive()); 68 } 69 70 // Sanity over opening a file (by filename) with an unlimited size. 71 TEST_F(RtcEventLogOutputFileTest, UnlimitedOutputFile) { 72 const std::string output_str = "one two three"; 73 74 auto output_file = std::make_unique<RtcEventLogOutputFile>(output_file_name_); 75 output_file->Write(output_str); 76 output_file.reset(); // Closing the file flushes the buffer to disk. 77 78 EXPECT_EQ(GetOutputFileContents(), output_str); 79 } 80 81 // Do not allow writing more bytes to the file than max file size. 82 TEST_F(RtcEventLogOutputFileTest, LimitedOutputFileCappedToCapacity) { 83 // Fit two bytes, then the third should be rejected. 84 auto output_file = 85 std::make_unique<RtcEventLogOutputFile>(output_file_name_, 2); 86 87 output_file->Write("1"); 88 output_file->Write("2"); 89 output_file->Write("3"); 90 // Unsuccessful writes close the file; no need to delete the output to flush. 91 92 EXPECT_EQ(GetOutputFileContents(), "12"); 93 } 94 95 // Make sure that calls to Write() either write everything to the file, or 96 // nothing (short of underlying issues in the module that handles the file, 97 // which would be beyond our control). 98 TEST_F(RtcEventLogOutputFileTest, DoNotWritePartialLines) { 99 const std::string output_str_1 = "0123456789"; 100 const std::string output_str_2 = "abcdefghij"; 101 102 // Set a file size limit just shy of fitting the entire second line. 103 const size_t size_limit = output_str_1.length() + output_str_2.length() - 1; 104 auto output_file = 105 std::make_unique<RtcEventLogOutputFile>(output_file_name_, size_limit); 106 107 output_file->Write(output_str_1); 108 output_file->Write(output_str_2); 109 // Unsuccessful writes close the file; no need to delete the output to flush. 110 111 EXPECT_EQ(GetOutputFileContents(), output_str_1); 112 } 113 114 TEST_F(RtcEventLogOutputFileTest, UnsuccessfulWriteReturnsFalse) { 115 auto output_file = 116 std::make_unique<RtcEventLogOutputFile>(output_file_name_, 2); 117 EXPECT_FALSE(output_file->Write("abc")); 118 } 119 120 TEST_F(RtcEventLogOutputFileTest, SuccessfulWriteReturnsTrue) { 121 auto output_file = 122 std::make_unique<RtcEventLogOutputFile>(output_file_name_, 3); 123 EXPECT_TRUE(output_file->Write("abc")); 124 } 125 126 // Even if capacity is reached, a successful write leaves the output active. 127 TEST_F(RtcEventLogOutputFileTest, FileStillActiveAfterSuccessfulWrite) { 128 auto output_file = 129 std::make_unique<RtcEventLogOutputFile>(output_file_name_, 3); 130 ASSERT_TRUE(output_file->Write("abc")); 131 EXPECT_TRUE(output_file->IsActive()); 132 } 133 134 // Unsuccessful writes switch the output to inactive, even if capacity has 135 // not yet been reached. 136 TEST_F(RtcEventLogOutputFileTest, FileInactiveAfterUnsuccessfulWrite) { 137 auto output_file = 138 std::make_unique<RtcEventLogOutputFile>(output_file_name_, 2); 139 ASSERT_FALSE(output_file->Write("abc")); 140 EXPECT_FALSE(output_file->IsActive()); 141 } 142 143 TEST_F(RtcEventLogOutputFileTest, AllowReasonableFileSizeLimits) { 144 auto output_file = std::make_unique<RtcEventLogOutputFile>( 145 output_file_name_, RtcEventLogOutputFile::kMaxReasonableFileSize); 146 EXPECT_TRUE(output_file->IsActive()); 147 } 148 149 #if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID) 150 class RtcEventLogOutputFileDeathTest : public RtcEventLogOutputFileTest {}; 151 152 TEST_F(RtcEventLogOutputFileDeathTest, WritingToInactiveFileForbidden) { 153 RtcEventLogOutputFile output_file(output_file_name_, 2); 154 ASSERT_FALSE(output_file.Write("abc")); 155 ASSERT_FALSE(output_file.IsActive()); 156 EXPECT_DEATH(output_file.Write("abc"), ""); 157 } 158 159 TEST_F(RtcEventLogOutputFileDeathTest, DisallowUnreasonableFileSizeLimits) { 160 // Keeping in a temporary unique_ptr to make it clearer that the death is 161 // triggered by construction, not destruction. 162 std::unique_ptr<RtcEventLogOutputFile> output_file; 163 auto create_output_file = [&] { 164 const size_t unreasonable_size = 165 RtcEventLogOutputFile::kMaxReasonableFileSize + 1; 166 output_file = std::make_unique<RtcEventLogOutputFile>(output_file_name_, 167 unreasonable_size); 168 }; 169 EXPECT_DEATH(create_output_file(), ""); 170 } 171 #endif 172 173 } // namespace webrtc