1// Copyright 2013 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/browser/chromeos/drive/file_system/truncate_operation.h"
6
7#include "base/files/file_path.h"
8#include "base/files/file_util.h"
9#include "base/task_runner_util.h"
10#include "chrome/browser/chromeos/drive/drive.pb.h"
11#include "chrome/browser/chromeos/drive/fake_free_disk_space_getter.h"
12#include "chrome/browser/chromeos/drive/file_system/operation_test_base.h"
13#include "content/public/test/test_utils.h"
14#include "testing/gtest/include/gtest/gtest.h"
15
16namespace drive {
17namespace file_system {
18
19class TruncateOperationTest : public OperationTestBase {
20 protected:
21  virtual void SetUp() OVERRIDE {
22    OperationTestBase::SetUp();
23
24    operation_.reset(new TruncateOperation(
25        blocking_task_runner(), delegate(), scheduler(),
26        metadata(), cache(), temp_dir()));
27  }
28
29  scoped_ptr<TruncateOperation> operation_;
30};
31
32TEST_F(TruncateOperationTest, Truncate) {
33  base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
34  ResourceEntry src_entry;
35  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
36  const int64 file_size = src_entry.file_info().size();
37
38  // Make sure the file has at least 2 bytes.
39  ASSERT_GE(file_size, 2);
40
41  FileError error = FILE_ERROR_FAILED;
42  operation_->Truncate(
43      file_in_root,
44      1,  // Truncate to 1 byte.
45      google_apis::test_util::CreateCopyResultCallback(&error));
46  content::RunAllBlockingPoolTasksUntilIdle();
47  EXPECT_EQ(FILE_ERROR_OK, error);
48
49  base::FilePath local_path;
50  error = FILE_ERROR_FAILED;
51  base::PostTaskAndReplyWithResult(
52      blocking_task_runner(),
53      FROM_HERE,
54      base::Bind(&internal::FileCache::GetFile,
55                 base::Unretained(cache()),
56                 GetLocalId(file_in_root), &local_path),
57      google_apis::test_util::CreateCopyResultCallback(&error));
58  content::RunAllBlockingPoolTasksUntilIdle();
59  ASSERT_EQ(FILE_ERROR_OK, error);
60
61  // The local file should be truncated.
62  int64 local_file_size = 0;
63  base::GetFileSize(local_path, &local_file_size);
64  EXPECT_EQ(1, local_file_size);
65}
66
67TEST_F(TruncateOperationTest, NegativeSize) {
68  base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
69  ResourceEntry src_entry;
70  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
71  const int64 file_size = src_entry.file_info().size();
72
73  // Make sure the file has at least 2 bytes.
74  ASSERT_GE(file_size, 2);
75
76  FileError error = FILE_ERROR_FAILED;
77  operation_->Truncate(
78      file_in_root,
79      -1,  // Truncate to "-1" byte.
80      google_apis::test_util::CreateCopyResultCallback(&error));
81  content::RunAllBlockingPoolTasksUntilIdle();
82  EXPECT_EQ(FILE_ERROR_INVALID_OPERATION, error);
83}
84
85TEST_F(TruncateOperationTest, HostedDocument) {
86  base::FilePath file_in_root(FILE_PATH_LITERAL(
87      "drive/root/Document 1 excludeDir-test.gdoc"));
88
89  FileError error = FILE_ERROR_FAILED;
90  operation_->Truncate(
91      file_in_root,
92      1,  // Truncate to 1 byte.
93      google_apis::test_util::CreateCopyResultCallback(&error));
94  content::RunAllBlockingPoolTasksUntilIdle();
95  EXPECT_EQ(FILE_ERROR_INVALID_OPERATION, error);
96}
97
98TEST_F(TruncateOperationTest, Extend) {
99  base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
100  ResourceEntry src_entry;
101  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
102  const int64 file_size = src_entry.file_info().size();
103
104  FileError error = FILE_ERROR_FAILED;
105  operation_->Truncate(
106      file_in_root,
107      file_size + 10,  // Extend to 10 bytes.
108      google_apis::test_util::CreateCopyResultCallback(&error));
109  content::RunAllBlockingPoolTasksUntilIdle();
110  EXPECT_EQ(FILE_ERROR_OK, error);
111
112  base::FilePath local_path;
113  error = FILE_ERROR_FAILED;
114  base::PostTaskAndReplyWithResult(
115      blocking_task_runner(),
116      FROM_HERE,
117      base::Bind(&internal::FileCache::GetFile,
118                 base::Unretained(cache()),
119                 GetLocalId(file_in_root), &local_path),
120      google_apis::test_util::CreateCopyResultCallback(&error));
121  content::RunAllBlockingPoolTasksUntilIdle();
122  ASSERT_EQ(FILE_ERROR_OK, error);
123
124  // The local file should be truncated.
125  std::string content;
126  ASSERT_TRUE(base::ReadFileToString(local_path, &content));
127
128  EXPECT_EQ(file_size + 10, static_cast<int64>(content.size()));
129  // All trailing 10 bytes should be '\0'.
130  EXPECT_EQ(std::string(10, '\0'), content.substr(file_size));
131}
132
133}  // namespace file_system
134}  // namespace drive
135