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