1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/common/important_file_writer.h"
6
7#include "base/compiler_specific.h"
8#include "base/file_path.h"
9#include "base/file_util.h"
10#include "base/logging.h"
11#include "base/memory/scoped_temp_dir.h"
12#include "base/message_loop.h"
13#include "base/threading/thread.h"
14#include "base/time.h"
15#include "testing/gtest/include/gtest/gtest.h"
16
17namespace {
18
19std::string GetFileContent(const FilePath& path) {
20  std::string content;
21  if (!file_util::ReadFileToString(path, &content)) {
22    NOTREACHED();
23  }
24  return content;
25}
26
27class DataSerializer : public ImportantFileWriter::DataSerializer {
28 public:
29  explicit DataSerializer(const std::string& data) : data_(data) {
30  }
31
32  virtual bool SerializeData(std::string* output) {
33    output->assign(data_);
34    return true;
35  }
36
37 private:
38  const std::string data_;
39};
40
41}  // namespace
42
43class ImportantFileWriterTest : public testing::Test {
44 public:
45  ImportantFileWriterTest() { }
46  virtual void SetUp() {
47    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
48    file_ = temp_dir_.path().AppendASCII("test-file");
49  }
50
51 protected:
52  FilePath file_;
53  MessageLoop loop_;
54
55 private:
56  ScopedTempDir temp_dir_;
57};
58
59TEST_F(ImportantFileWriterTest, Basic) {
60  ImportantFileWriter writer(file_,
61                             base::MessageLoopProxy::CreateForCurrentThread());
62  EXPECT_FALSE(file_util::PathExists(writer.path()));
63  writer.WriteNow("foo");
64  loop_.RunAllPending();
65
66  ASSERT_TRUE(file_util::PathExists(writer.path()));
67  EXPECT_EQ("foo", GetFileContent(writer.path()));
68}
69
70TEST_F(ImportantFileWriterTest, ScheduleWrite) {
71  ImportantFileWriter writer(file_,
72                             base::MessageLoopProxy::CreateForCurrentThread());
73  writer.set_commit_interval(base::TimeDelta::FromMilliseconds(25));
74  EXPECT_FALSE(writer.HasPendingWrite());
75  DataSerializer serializer("foo");
76  writer.ScheduleWrite(&serializer);
77  EXPECT_TRUE(writer.HasPendingWrite());
78  MessageLoop::current()->PostDelayedTask(FROM_HERE,
79                                          new MessageLoop::QuitTask(), 100);
80  MessageLoop::current()->Run();
81  EXPECT_FALSE(writer.HasPendingWrite());
82  ASSERT_TRUE(file_util::PathExists(writer.path()));
83  EXPECT_EQ("foo", GetFileContent(writer.path()));
84}
85
86TEST_F(ImportantFileWriterTest, DoScheduledWrite) {
87  ImportantFileWriter writer(file_,
88                             base::MessageLoopProxy::CreateForCurrentThread());
89  EXPECT_FALSE(writer.HasPendingWrite());
90  DataSerializer serializer("foo");
91  writer.ScheduleWrite(&serializer);
92  EXPECT_TRUE(writer.HasPendingWrite());
93  writer.DoScheduledWrite();
94  MessageLoop::current()->PostDelayedTask(FROM_HERE,
95                                          new MessageLoop::QuitTask(), 100);
96  MessageLoop::current()->Run();
97  EXPECT_FALSE(writer.HasPendingWrite());
98  ASSERT_TRUE(file_util::PathExists(writer.path()));
99  EXPECT_EQ("foo", GetFileContent(writer.path()));
100}
101
102TEST_F(ImportantFileWriterTest, BatchingWrites) {
103  ImportantFileWriter writer(file_,
104                             base::MessageLoopProxy::CreateForCurrentThread());
105  writer.set_commit_interval(base::TimeDelta::FromMilliseconds(25));
106  DataSerializer foo("foo"), bar("bar"), baz("baz");
107  writer.ScheduleWrite(&foo);
108  writer.ScheduleWrite(&bar);
109  writer.ScheduleWrite(&baz);
110  MessageLoop::current()->PostDelayedTask(FROM_HERE,
111                                          new MessageLoop::QuitTask(), 100);
112  MessageLoop::current()->Run();
113  ASSERT_TRUE(file_util::PathExists(writer.path()));
114  EXPECT_EQ("baz", GetFileContent(writer.path()));
115}
116