Remove CircularFileStream / replace it with CallSessionFileRotatingStream.
BUG=4838, 4839
Review URL: https://codereview.webrtc.org/1245143005
Cr-Commit-Position: refs/heads/master@{#9628}
diff --git a/talk/app/webrtc/objc/RTCFileLogger.mm b/talk/app/webrtc/objc/RTCFileLogger.mm
index b474d7a..3080ebc 100644
--- a/talk/app/webrtc/objc/RTCFileLogger.mm
+++ b/talk/app/webrtc/objc/RTCFileLogger.mm
@@ -28,45 +28,19 @@
#import "RTCFileLogger.h"
#include "webrtc/base/checks.h"
+#include "webrtc/base/filerotatingstream.h"
#include "webrtc/base/logging.h"
+#include "webrtc/base/logsinks.h"
#include "webrtc/base/scoped_ptr.h"
-#include "webrtc/base/stream.h"
-NSString *const kDefaultLogFileName = @"webrtc.log";
+NSString *const kDefaultLogDirName = @"webrtc_logs";
NSUInteger const kDefaultMaxFileSize = 10 * 1024 * 1024; // 10MB.
-namespace rtc {
-
-class CircularFileStreamLogSink : public LogSink {
- public:
- // Creates a log sink that writes to the given stream. This log sink takes
- // ownership of |stream|.
- CircularFileStreamLogSink(CircularFileStream *stream) {
- DCHECK(stream);
- _stream.reset(stream);
- }
-
- ~CircularFileStreamLogSink() override {}
-
- void OnLogMessage(const std::string &message) override {
- if (_stream) {
- _stream->WriteAll(message.data(), message.size(), nullptr, nullptr);
- }
- }
-
- CircularFileStream *GetStream() { return _stream.get(); }
-
- private:
- scoped_ptr<CircularFileStream> _stream;
-};
-
-} // namespace rtc
-
@implementation RTCFileLogger {
BOOL _hasStarted;
- NSString *_filePath;
+ NSString *_dirPath;
NSUInteger _maxFileSize;
- rtc::scoped_ptr<rtc::CircularFileStreamLogSink> _logSink;
+ rtc::scoped_ptr<rtc::CallSessionFileRotatingLogSink> _logSink;
}
@synthesize severity = _severity;
@@ -75,18 +49,34 @@
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirPath = [paths firstObject];
- NSString *defaultFilePath =
- [documentsDirPath stringByAppendingPathComponent:kDefaultLogFileName];
- return [self initWithFilePath:defaultFilePath
- maxFileSize:kDefaultMaxFileSize];
+ NSString *defaultDirPath =
+ [documentsDirPath stringByAppendingPathComponent:kDefaultLogDirName];
+ return [self initWithDirPath:defaultDirPath
+ maxFileSize:kDefaultMaxFileSize];
}
-- (instancetype)initWithFilePath:(NSString *)filePath
- maxFileSize:(NSUInteger)maxFileSize {
- NSParameterAssert(filePath.length);
+- (instancetype)initWithDirPath:(NSString *)dirPath
+ maxFileSize:(NSUInteger)maxFileSize {
+ NSParameterAssert(dirPath.length);
NSParameterAssert(maxFileSize);
if (self = [super init]) {
- _filePath = filePath;
+ BOOL isDir = NO;
+ NSFileManager *fileManager = [NSFileManager defaultManager];
+ if ([fileManager fileExistsAtPath:dirPath isDirectory:&isDir]) {
+ if (!isDir) {
+ // Bail if something already exists there.
+ return nil;
+ }
+ } else {
+ if (![fileManager createDirectoryAtPath:dirPath
+ withIntermediateDirectories:NO
+ attributes:nil
+ error:nil]) {
+ // Bail if we failed to create a directory.
+ return nil;
+ }
+ }
+ _dirPath = dirPath;
_maxFileSize = maxFileSize;
_severity = kRTCFileLoggerSeverityInfo;
}
@@ -101,19 +91,14 @@
if (_hasStarted) {
return;
}
- rtc::scoped_ptr<rtc::CircularFileStream> stream;
- stream.reset(new rtc::CircularFileStream(_maxFileSize));
- _logSink.reset(new rtc::CircularFileStreamLogSink(stream.release()));
- int error = 0;
- if (!_logSink->GetStream()->Open(_filePath.UTF8String, "wb", &error)) {
- LOG(LS_ERROR) << "Failed to open log file at path: "
- << _filePath.UTF8String
- << " Error: "
- << error;
+ _logSink.reset(new rtc::CallSessionFileRotatingLogSink(_dirPath.UTF8String,
+ _maxFileSize));
+ if (!_logSink->Init()) {
+ LOG(LS_ERROR) << "Failed to open log files at path: "
+ << _dirPath.UTF8String;
_logSink.reset();
return;
}
- // TODO(tkchin): Log thead info on iOS, currently this doesn't do anything.
rtc::LogMessage::LogThreads(true);
rtc::LogMessage::LogTimestamps(true);
rtc::LogMessage::AddLogToStream(_logSink.get(), [self rtcSeverity]);
@@ -127,93 +112,35 @@
DCHECK(_logSink);
rtc::LogMessage::RemoveLogToStream(_logSink.get());
_hasStarted = NO;
-
- // Read the ordered version of the log.
- NSData *logData = [self reorderedLogData];
- NSError *error = nil;
- // Write the ordered version back to disk.
- if (![logData writeToFile:_filePath
- options:NSDataWritingAtomic
- error:&error]) {
- LOG(LS_ERROR) << "Failed to rewrite log to disk at path: "
- << _filePath.UTF8String;
- if (error) {
- LOG(LS_ERROR) << "Error: " << error.localizedDescription.UTF8String;
- }
- } else {
- // If we succeeded in writing to disk we don't need to hold on to the
- // stream anymore.
- _logSink.reset();
- }
+ _logSink.reset();
}
- (NSData *)logData {
if (_hasStarted) {
return nil;
}
- if (!_logSink.get()) {
- // If there isn't a previously used stream just return contents of file.
- return [[self class] contentsOfFileAtPath:_filePath];
+ NSMutableData* logData = [NSMutableData data];
+ rtc::scoped_ptr<rtc::CallSessionFileRotatingStream> stream(
+ new rtc::CallSessionFileRotatingStream(_dirPath.UTF8String));
+ if (!stream->Open()) {
+ return logData;
}
- return [self reorderedLogData];
+ size_t bufferSize = 0;
+ if (!stream->GetSize(&bufferSize) || bufferSize == 0) {
+ return logData;
+ }
+ size_t read = 0;
+ // Allocate memory using malloc so we can pass it direcly to NSData without
+ // copying.
+ rtc::scoped_ptr<uint8_t[]> buffer(static_cast<uint8_t*>(malloc(bufferSize)));
+ stream->ReadAll(buffer.get(), bufferSize, &read, nullptr);
+ logData = [[NSMutableData alloc] initWithBytesNoCopy:buffer.release()
+ length:read];
+ return logData;
}
#pragma mark - Private
-+ (NSData *)contentsOfFileAtPath:(NSString *)path {
- NSError *error = nil;
- NSData *contents = [NSData dataWithContentsOfFile:path
- options:0
- error:&error];
- if (error) {
- LOG(LS_ERROR) << "Failed to read contents of file at path: "
- << path.UTF8String
- << " Error: "
- << error.localizedDescription.UTF8String;
- return nil;
- }
- return contents;
-}
-
-- (NSData *)reorderedLogData {
- if (_hasStarted || !_logSink.get()) {
- return nil;
- }
- // We have a stream we used for writing in memory and we're not writing. The
- // stream has a pointer to where the log boundary is so it can reorder the
- // log correctly. We just need to reopen the file in read mode.
- int error = 0;
- rtc::CircularFileStream *stream = _logSink->GetStream();
- if (!stream->Open(_filePath.UTF8String, "r", &error)) {
- LOG(LS_ERROR) << "Failed to open log file at path: "
- << _filePath.UTF8String
- << " Error: "
- << error;
- return nil;
- }
- size_t logSize = 0;
- size_t bytesRead = 0;
- error = 0;
- if (!stream->GetSize(&logSize)) {
- LOG(LS_ERROR) << "Failed to get log file size.";
- return nil;
- }
- // Allocate memory using malloc so we can pass it direcly to NSData without
- // copying.
- rtc::scoped_ptr<uint8_t[]> buffer(static_cast<uint8_t*>(malloc(logSize)));
- if (stream->ReadAll(buffer.get(), logSize, &bytesRead, &error)
- != rtc::SR_SUCCESS) {
- LOG(LS_ERROR) << "Failed to read log file at path: "
- << _filePath.UTF8String
- << " Error: "
- << error;
- }
- DCHECK_LE(bytesRead, logSize);
- // NSData takes ownership of the bytes and frees it on dealloc.
- return [NSData dataWithBytesNoCopy:buffer.release()
- length:bytesRead];
-}
-
- (rtc::LoggingSeverity)rtcSeverity {
switch (_severity) {
case kRTCFileLoggerSeverityVerbose:
diff --git a/talk/app/webrtc/objc/public/RTCFileLogger.h b/talk/app/webrtc/objc/public/RTCFileLogger.h
index 5c311b7..3900cb6 100644
--- a/talk/app/webrtc/objc/public/RTCFileLogger.h
+++ b/talk/app/webrtc/objc/public/RTCFileLogger.h
@@ -49,24 +49,22 @@
// The severity level to capture. The default is kRTCFileLoggerSeverityInfo.
@property(nonatomic, assign) RTCFileLoggerSeverity severity;
-// Default constructor provides default settings for file path and file size.
+// Default constructor provides default settings for dir path and file size.
- (instancetype)init;
-- (instancetype)initWithFilePath:(NSString *)filePath
- maxFileSize:(NSUInteger)maxFileSize
+- (instancetype)initWithDirPath:(NSString *)dirPath
+ maxFileSize:(NSUInteger)maxFileSize
NS_DESIGNATED_INITIALIZER;
-// Starts writing WebRTC logs to file if not already started. Overwrites any
-// existing file.
+// Starts writing WebRTC logs to disk if not already started. Overwrites any
+// existing file(s).
- (void)start;
-// Stops writing WebRTC logs to file. Rewrites the log file as required to
-// reorder logs because logs may be disordered due to use of
-// rtc::CircularFileStream. This method is also called on dealloc.
+// Stops writing WebRTC logs to disk. This method is also called on dealloc.
- (void)stop;
-// Returns the current contents of the log file. Returns nil if start has been
-// called without a stop, or if there is no data.
+// Returns the current contents of the logs, or nil if start has been called
+// without a stop.
- (NSData *)logData;
@end
diff --git a/webrtc/base/filerotatingstream.cc b/webrtc/base/filerotatingstream.cc
index 3fd60ac..f2a6def 100644
--- a/webrtc/base/filerotatingstream.cc
+++ b/webrtc/base/filerotatingstream.cc
@@ -177,6 +177,26 @@
return file_stream_->Flush();
}
+bool FileRotatingStream::GetSize(size_t* size) const {
+ if (mode_ != kRead) {
+ // Not possible to get accurate size on disk when writing because of
+ // potential buffering.
+ return false;
+ }
+ DCHECK(size);
+ *size = 0;
+ size_t total_size = 0;
+ for (auto file_name : file_names_) {
+ Pathname pathname(file_name);
+ size_t file_size = 0;
+ if (Filesystem::GetFileSize(file_name, &file_size)) {
+ total_size += file_size;
+ }
+ }
+ *size = total_size;
+ return true;
+}
+
void FileRotatingStream::Close() {
CloseCurrentFile();
}
diff --git a/webrtc/base/filerotatingstream.h b/webrtc/base/filerotatingstream.h
index 7f6bc50..f3de14e 100644
--- a/webrtc/base/filerotatingstream.h
+++ b/webrtc/base/filerotatingstream.h
@@ -50,6 +50,8 @@
size_t* written,
int* error) override;
bool Flush() override;
+ // Returns the total file size currently used on disk.
+ bool GetSize(size_t* size) const override;
void Close() override;
// Opens the appropriate file(s). Call this before using the stream.
diff --git a/webrtc/base/filerotatingstream_unittest.cc b/webrtc/base/filerotatingstream_unittest.cc
index 084c612..09438f8 100644
--- a/webrtc/base/filerotatingstream_unittest.cc
+++ b/webrtc/base/filerotatingstream_unittest.cc
@@ -60,11 +60,15 @@
scoped_ptr<FileRotatingStream> stream;
stream.reset(new FileRotatingStream(dir_path, file_prefix));
ASSERT_TRUE(stream->Open());
+ size_t read = 0;
+ size_t stream_size = 0;
+ EXPECT_TRUE(stream->GetSize(&stream_size));
scoped_ptr<uint8_t[]> buffer(new uint8_t[expected_length]);
EXPECT_EQ(SR_SUCCESS,
- stream->ReadAll(buffer.get(), expected_length, nullptr, nullptr));
+ stream->ReadAll(buffer.get(), expected_length, &read, nullptr));
EXPECT_EQ(0, memcmp(expected_contents, buffer.get(), expected_length));
EXPECT_EQ(SR_EOS, stream->ReadAll(buffer.get(), 1, nullptr, nullptr));
+ EXPECT_EQ(stream_size, read);
}
void VerifyFileContents(const char* expected_contents,
@@ -214,11 +218,15 @@
scoped_ptr<CallSessionFileRotatingStream> stream(
new CallSessionFileRotatingStream(dir_path));
ASSERT_TRUE(stream->Open());
+ size_t read = 0;
+ size_t stream_size = 0;
+ EXPECT_TRUE(stream->GetSize(&stream_size));
scoped_ptr<uint8_t[]> buffer(new uint8_t[expected_length]);
EXPECT_EQ(SR_SUCCESS,
- stream->ReadAll(buffer.get(), expected_length, nullptr, nullptr));
+ stream->ReadAll(buffer.get(), expected_length, &read, nullptr));
EXPECT_EQ(0, memcmp(expected_contents, buffer.get(), expected_length));
EXPECT_EQ(SR_EOS, stream->ReadAll(buffer.get(), 1, nullptr, nullptr));
+ EXPECT_EQ(stream_size, read);
}
scoped_ptr<CallSessionFileRotatingStream> stream_;
diff --git a/webrtc/base/logsinks.cc b/webrtc/base/logsinks.cc
index e202a81..4968339 100644
--- a/webrtc/base/logsinks.cc
+++ b/webrtc/base/logsinks.cc
@@ -10,8 +10,11 @@
#include "webrtc/base/logsinks.h"
+#include <iostream>
#include <string>
+#include "webrtc/base/checks.h"
+
namespace rtc {
FileRotatingLogSink::FileRotatingLogSink(const std::string& log_dir_path,
@@ -26,14 +29,15 @@
FileRotatingLogSink::FileRotatingLogSink(FileRotatingStream* stream)
: stream_(stream) {
+ DCHECK(stream);
}
FileRotatingLogSink::~FileRotatingLogSink() {
}
void FileRotatingLogSink::OnLogMessage(const std::string& message) {
- if (!stream_ || stream_->GetState() != SS_OPEN) {
- LOG(LS_WARNING) << "Init() must be called before adding this sink.";
+ if (stream_->GetState() != SS_OPEN) {
+ std::cerr << "Init() must be called before adding this sink." << std::endl;
return;
}
stream_->WriteAll(message.c_str(), message.size(), nullptr, nullptr);
@@ -43,6 +47,10 @@
return stream_->Open();
}
+bool FileRotatingLogSink::DisableBuffering() {
+ return stream_->DisableBuffering();
+}
+
CallSessionFileRotatingLogSink::CallSessionFileRotatingLogSink(
const std::string& log_dir_path,
size_t max_total_log_size)
diff --git a/webrtc/base/logsinks.h b/webrtc/base/logsinks.h
index f86bdd0..849e1dc 100644
--- a/webrtc/base/logsinks.h
+++ b/webrtc/base/logsinks.h
@@ -39,6 +39,9 @@
// Deletes any existing files in the directory and creates a new log file.
virtual bool Init();
+ // Disables buffering on the underlying stream.
+ bool DisableBuffering();
+
protected:
explicit FileRotatingLogSink(FileRotatingStream* stream);
@@ -57,8 +60,6 @@
~CallSessionFileRotatingLogSink() override;
private:
- scoped_ptr<CallSessionFileRotatingStream> stream_;
-
DISALLOW_COPY_AND_ASSIGN(CallSessionFileRotatingLogSink);
};
diff --git a/webrtc/base/stream.cc b/webrtc/base/stream.cc
index 3e3afa0..e22c3d8 100644
--- a/webrtc/base/stream.cc
+++ b/webrtc/base/stream.cc
@@ -517,113 +517,6 @@
fclose(file_);
}
-CircularFileStream::CircularFileStream(size_t max_size)
- : max_write_size_(max_size),
- position_(0),
- marked_position_(max_size / 2),
- last_write_position_(0),
- read_segment_(READ_LATEST),
- read_segment_available_(0) {
-}
-
-bool CircularFileStream::Open(const std::string& filename,
- const char* mode,
- int* error) {
- if (!FileStream::Open(filename.c_str(), mode, error))
- return false;
-
- if (strchr(mode, "r") != NULL) { // Opened in read mode.
- // Check if the buffer has been overwritten and determine how to read the
- // log in time sequence.
- size_t file_size;
- GetSize(&file_size);
- if (file_size == position_) {
- // The buffer has not been overwritten yet. Read 0 .. file_size
- read_segment_ = READ_LATEST;
- read_segment_available_ = file_size;
- } else {
- // The buffer has been over written. There are three segments: The first
- // one is 0 .. marked_position_, which is the marked earliest log. The
- // second one is position_ .. file_size, which is the middle log. The
- // last one is marked_position_ .. position_, which is the latest log.
- read_segment_ = READ_MARKED;
- read_segment_available_ = marked_position_;
- last_write_position_ = position_;
- }
-
- // Read from the beginning.
- position_ = 0;
- SetPosition(position_);
- }
-
- return true;
-}
-
-StreamResult CircularFileStream::Read(void* buffer,
- size_t buffer_len,
- size_t* read,
- int* error) {
- if (read_segment_available_ == 0) {
- size_t file_size;
- switch (read_segment_) {
- case READ_MARKED: // Finished READ_MARKED and start READ_MIDDLE.
- read_segment_ = READ_MIDDLE;
- position_ = last_write_position_;
- SetPosition(position_);
- GetSize(&file_size);
- read_segment_available_ = file_size - position_;
- break;
-
- case READ_MIDDLE: // Finished READ_MIDDLE and start READ_LATEST.
- read_segment_ = READ_LATEST;
- position_ = marked_position_;
- SetPosition(position_);
- read_segment_available_ = last_write_position_ - position_;
- break;
-
- default: // Finished READ_LATEST and return EOS.
- return rtc::SR_EOS;
- }
- }
-
- size_t local_read;
- if (!read)
- read = &local_read;
-
- size_t to_read = std::min(buffer_len, read_segment_available_);
- rtc::StreamResult result =
- rtc::FileStream::Read(buffer, to_read, read, error);
- if (result == rtc::SR_SUCCESS) {
- read_segment_available_ -= *read;
- position_ += *read;
- }
- return result;
-}
-
-StreamResult CircularFileStream::Write(const void* data,
- size_t data_len,
- size_t* written,
- int* error) {
- if (position_ >= max_write_size_) {
- ASSERT(position_ == max_write_size_);
- position_ = marked_position_;
- SetPosition(position_);
- }
-
- size_t local_written;
- if (!written)
- written = &local_written;
-
- size_t to_eof = max_write_size_ - position_;
- size_t to_write = std::min(data_len, to_eof);
- rtc::StreamResult result =
- rtc::FileStream::Write(data, to_write, written, error);
- if (result == rtc::SR_SUCCESS) {
- position_ += *written;
- }
- return result;
-}
-
///////////////////////////////////////////////////////////////////////////////
// MemoryStream
///////////////////////////////////////////////////////////////////////////////
diff --git a/webrtc/base/stream.h b/webrtc/base/stream.h
index f67c704..b331766 100644
--- a/webrtc/base/stream.h
+++ b/webrtc/base/stream.h
@@ -418,39 +418,6 @@
DISALLOW_COPY_AND_ASSIGN(FileStream);
};
-// A stream that caps the output at a certain size, dropping content from the
-// middle of the logical stream and maintaining equal parts of the start/end of
-// the logical stream.
-class CircularFileStream : public FileStream {
- public:
- explicit CircularFileStream(size_t max_size);
-
- bool Open(const std::string& filename, const char* mode, int* error) override;
- StreamResult Read(void* buffer,
- size_t buffer_len,
- size_t* read,
- int* error) override;
- StreamResult Write(const void* data,
- size_t data_len,
- size_t* written,
- int* error) override;
-
- private:
- enum ReadSegment {
- READ_MARKED, // Read 0 .. marked_position_
- READ_MIDDLE, // Read position_ .. file_size
- READ_LATEST, // Read marked_position_ .. position_ if the buffer was
- // overwritten or 0 .. position_ otherwise.
- };
-
- size_t max_write_size_;
- size_t position_;
- size_t marked_position_;
- size_t last_write_position_;
- ReadSegment read_segment_;
- size_t read_segment_available_;
-};
-
///////////////////////////////////////////////////////////////////////////////
// MemoryStream is a simple implementation of a StreamInterface over in-memory
// data. Data is read and written at the current seek position. Reads return
diff --git a/webrtc/base/stream_unittest.cc b/webrtc/base/stream_unittest.cc
index 4d5066a..4172a97 100644
--- a/webrtc/base/stream_unittest.cc
+++ b/webrtc/base/stream_unittest.cc
@@ -372,162 +372,4 @@
EXPECT_EQ(SR_BLOCK, buf.ReadOffset(out, 10, 16, NULL));
}
-class CircularFileStreamTest : public ::testing::Test {
- protected:
- static size_t const kMaxSize = 12;
-
- CircularFileStreamTest() : is_open_(false), stream_(kMaxSize) {
- Pathname temp_dir;
- if (Filesystem::GetAppTempFolder(&temp_dir)) {
- logfile_name_ =
- Filesystem::TempFilename(temp_dir, "CircularFileStreamTest");
- }
- }
-
- virtual void SetUp() {
- int error = -1;
- is_open_ = stream_.Open(logfile_name_, "wb", &error);
- }
-
- virtual void TearDown() {
- if (!Filesystem::IsAbsent(logfile_name_)) {
- Filesystem::DeleteFile(logfile_name_);
- }
- }
-
- bool is_open_;
- CircularFileStream stream_;
- std::string logfile_name_;
-};
-
-TEST_F(CircularFileStreamTest, ReadWriteWithinCapacity) {
- EXPECT_TRUE(is_open_);
- // Write contents.
- const uint8_t bytes[] = {1, 2, 3, 4, 5, 6};
- size_t written = 0;
- int error = 0;
- EXPECT_EQ(SR_SUCCESS, stream_.Write(bytes, sizeof(bytes), &written, &error));
- EXPECT_EQ(0, error);
- EXPECT_EQ(written, sizeof(bytes));
- stream_.Close();
-
- // Check file contents.
- uint8_t content_bytes[sizeof(bytes)] = {};
- scoped_ptr<FileStream> content_stream(
- Filesystem::OpenFile(logfile_name_, "r"));
- size_t num_content_bytes_read = 0;
- EXPECT_TRUE(content_stream);
- error = 0;
- EXPECT_EQ(SR_SUCCESS,
- content_stream->Read(content_bytes, sizeof(content_bytes),
- &num_content_bytes_read, &error));
- EXPECT_EQ(sizeof(content_bytes), num_content_bytes_read);
- ASSERT_EQ(sizeof(content_bytes), sizeof(bytes));
- EXPECT_EQ(0, memcmp(content_bytes, bytes, sizeof(content_bytes)));
-
- // Check read result.
- error = 0;
- size_t file_size = 0;
- EXPECT_TRUE(stream_.Open(logfile_name_, "r", &error));
- EXPECT_TRUE(stream_.GetSize(&file_size));
- EXPECT_EQ(0, error);
- EXPECT_EQ(sizeof(bytes), file_size);
- scoped_ptr<uint8_t[]> read_bytes(new uint8_t[file_size]);
- size_t num_read_bytes = 0;
- error = 0;
- EXPECT_EQ(SR_SUCCESS, stream_.ReadAll(read_bytes.get(), file_size,
- &num_read_bytes, &error));
- EXPECT_EQ(sizeof(bytes), num_read_bytes);
- EXPECT_EQ(0, memcmp(bytes, read_bytes.get(), file_size));
-}
-
-TEST_F(CircularFileStreamTest, ReadWriteAtCapacity) {
- EXPECT_TRUE(is_open_);
- // Write contents.
- const uint8_t bytes[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
- size_t written = 0;
- int error = 0;
- EXPECT_EQ(SR_SUCCESS, stream_.Write(bytes, sizeof(bytes), &written, &error));
- EXPECT_EQ(0, error);
- EXPECT_EQ(written, sizeof(bytes));
- stream_.Close();
-
- // Check file contents.
- uint8_t content_bytes[sizeof(bytes)] = {};
- scoped_ptr<FileStream> content_stream(
- Filesystem::OpenFile(logfile_name_, "r"));
- size_t num_content_bytes_read = 0;
- EXPECT_TRUE(content_stream);
- error = 0;
- EXPECT_EQ(SR_SUCCESS,
- content_stream->Read(content_bytes, sizeof(content_bytes),
- &num_content_bytes_read, &error));
- EXPECT_EQ(sizeof(content_bytes), num_content_bytes_read);
- ASSERT_EQ(sizeof(content_bytes), sizeof(bytes));
- EXPECT_EQ(0, memcmp(content_bytes, bytes, sizeof(content_bytes)));
-
- // Check read result.
- error = 0;
- size_t file_size = 0;
- EXPECT_TRUE(stream_.Open(logfile_name_, "r", &error));
- EXPECT_TRUE(stream_.GetSize(&file_size));
- EXPECT_EQ(0, error);
- EXPECT_EQ(sizeof(bytes), file_size);
- scoped_ptr<uint8_t[]> read_bytes(new uint8_t[file_size]);
- size_t num_read_bytes = 0;
- error = 0;
- EXPECT_EQ(SR_SUCCESS, stream_.ReadAll(read_bytes.get(), file_size,
- &num_read_bytes, &error));
- EXPECT_EQ(sizeof(bytes), num_read_bytes);
- EXPECT_EQ(0, memcmp(bytes, read_bytes.get(), file_size));
-}
-
-TEST_F(CircularFileStreamTest, ReadWriteOverCapacity) {
- EXPECT_TRUE(is_open_);
- // Write contents.
- const uint8_t bytes[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
- size_t written = 0;
- int error = 0;
- EXPECT_EQ(SR_SUCCESS,
- stream_.WriteAll(bytes, sizeof(bytes), &written, &error));
- EXPECT_EQ(0, error);
- EXPECT_EQ(written, sizeof(bytes));
- stream_.Close();
-
- // Check file contents.
- uint8_t content_bytes[kMaxSize] = {};
- scoped_ptr<FileStream> content_stream(
- Filesystem::OpenFile(logfile_name_, "r"));
- size_t num_content_bytes_read = 0;
- EXPECT_TRUE(content_stream);
- error = 0;
- EXPECT_EQ(SR_SUCCESS,
- content_stream->Read(content_bytes, sizeof(content_bytes),
- &num_content_bytes_read, &error));
- EXPECT_EQ(sizeof(content_bytes), num_content_bytes_read);
- const uint8_t expected_content_bytes[] = {
- 1, 2, 3, 4, 5, 6, 13, 14, 15, 10, 11, 12};
- ASSERT_EQ(sizeof(content_bytes), sizeof(expected_content_bytes));
- EXPECT_EQ(
- 0, memcmp(expected_content_bytes, content_bytes, sizeof(content_bytes)));
-
- // Check read result.
- error = 0;
- size_t file_size = 0;
- EXPECT_TRUE(stream_.Open(logfile_name_, "r", &error));
- EXPECT_TRUE(stream_.GetSize(&file_size));
- EXPECT_EQ(0, error);
- EXPECT_EQ(sizeof(content_bytes), file_size);
- scoped_ptr<uint8_t[]> read_bytes(new uint8_t[file_size]);
- size_t num_read_bytes = 0;
- error = 0;
- EXPECT_EQ(SR_SUCCESS, stream_.ReadAll(read_bytes.get(), file_size,
- &num_read_bytes, &error));
-
- const uint8_t expected_read_bytes[] = {
- 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 14, 15};
- EXPECT_EQ(sizeof(expected_read_bytes), num_read_bytes);
- EXPECT_EQ(0, memcmp(expected_read_bytes, read_bytes.get(), file_size));
-}
-
} // namespace rtc