1 // Copyright 2015 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/file_system_provider/scoped_file_opener.h"
6 
7 #include <memory>
8 #include <vector>
9 
10 #include "base/bind.h"
11 #include "base/files/file.h"
12 #include "base/run_loop.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/threading/thread_task_runner_handle.h"
15 #include "chrome/browser/chromeos/file_system_provider/fake_provided_file_system.h"
16 #include "chrome/browser/chromeos/file_system_provider/provided_file_system_info.h"
17 #include "content/public/test/browser_task_environment.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 
20 namespace chromeos {
21 namespace file_system_provider {
22 namespace {
23 
24 class TestingProvidedFileSystem : public FakeProvidedFileSystem {
25  public:
TestingProvidedFileSystem()26   TestingProvidedFileSystem()
27       : FakeProvidedFileSystem(ProvidedFileSystemInfo()) {}
28 
~TestingProvidedFileSystem()29   ~TestingProvidedFileSystem() override {}
30 
OpenFile(const base::FilePath & file_path,OpenFileMode mode,OpenFileCallback callback)31   AbortCallback OpenFile(const base::FilePath& file_path,
32                          OpenFileMode mode,
33                          OpenFileCallback callback) override {
34     open_callback_ = std::move(callback);
35     return base::BindOnce(&TestingProvidedFileSystem::AbortOpen,
36                           base::Unretained(this));
37   }
38 
CloseFile(int file_handle,storage::AsyncFileUtil::StatusCallback callback)39   AbortCallback CloseFile(
40       int file_handle,
41       storage::AsyncFileUtil::StatusCallback callback) override {
42     close_requests_.push_back(file_handle);
43     std::move(callback).Run(base::File::FILE_OK);
44     return AbortCallback();
45   }
46 
has_open_callback() const47   bool has_open_callback() const { return !!open_callback_; }
open_callback()48   OpenFileCallback open_callback() {
49     return base::BindOnce(&TestingProvidedFileSystem::CompleteOpen,
50                           base::Unretained(this));
51   }
close_requests() const52   const std::vector<int> close_requests() const { return close_requests_; }
53 
54  private:
55   OpenFileCallback open_callback_;
56   std::vector<int> close_requests_;
57 
CompleteOpen(int file_handle,base::File::Error result)58   void CompleteOpen(int file_handle, base::File::Error result) {
59     std::move(open_callback_).Run(file_handle, result);
60   }
61 
AbortOpen()62   void AbortOpen() {
63     std::move(open_callback_).Run(0, base::File::FILE_ERROR_ABORT);
64   }
65 };
66 
67 typedef std::vector<std::pair<int, base::File::Error>> OpenLog;
68 
LogOpen(OpenLog * log,int file_handle,base::File::Error result)69 void LogOpen(OpenLog* log, int file_handle, base::File::Error result) {
70   log->push_back(std::make_pair(file_handle, result));
71 }
72 
73 }  // namespace
74 
TEST(ScopedFileOpenerTest,AbortWhileOpening)75 TEST(ScopedFileOpenerTest, AbortWhileOpening) {
76   TestingProvidedFileSystem file_system;
77   content::BrowserTaskEnvironment task_environment;
78   OpenLog log;
79   {
80     ScopedFileOpener file_opener(&file_system, base::FilePath(),
81                                  OPEN_FILE_MODE_READ,
82                                  base::BindOnce(&LogOpen, &log));
83     base::RunLoop().RunUntilIdle();
84     EXPECT_TRUE(file_system.has_open_callback());
85   }
86   ASSERT_EQ(1u, log.size());
87   EXPECT_EQ(0, log[0].first);
88   EXPECT_EQ(base::File::FILE_ERROR_ABORT, log[0].second);
89 
90   base::RunLoop().RunUntilIdle();
91   EXPECT_EQ(0u, file_system.close_requests().size());
92 }
93 
TEST(ScopedFileOpenerTest,CloseAfterOpening)94 TEST(ScopedFileOpenerTest, CloseAfterOpening) {
95   TestingProvidedFileSystem file_system;
96   content::BrowserTaskEnvironment task_environment;
97   OpenLog log;
98   {
99     ScopedFileOpener file_opener(&file_system, base::FilePath(),
100                                  OPEN_FILE_MODE_READ,
101                                  base::BindOnce(&LogOpen, &log));
102     base::RunLoop().RunUntilIdle();
103     ASSERT_TRUE(file_system.has_open_callback());
104     file_system.open_callback().Run(123, base::File::FILE_OK);
105   }
106 
107   ASSERT_EQ(1u, log.size());
108   EXPECT_EQ(123, log[0].first);
109   EXPECT_EQ(base::File::FILE_OK, log[0].second);
110 
111   ASSERT_EQ(1u, file_system.close_requests().size());
112   EXPECT_EQ(123, file_system.close_requests()[0]);
113 }
114 
TEST(ScopedFileOpenerTest,CloseAfterAborting)115 TEST(ScopedFileOpenerTest, CloseAfterAborting) {
116   TestingProvidedFileSystem file_system;
117   content::BrowserTaskEnvironment task_environment;
118   OpenLog log;
119   {
120     ScopedFileOpener file_opener(&file_system, base::FilePath(),
121                                  OPEN_FILE_MODE_READ,
122                                  base::BindOnce(&LogOpen, &log));
123     base::RunLoop().RunUntilIdle();
124     ASSERT_TRUE(file_system.has_open_callback());
125     file_system.open_callback().Run(0, base::File::FILE_ERROR_ABORT);
126   }
127 
128   ASSERT_EQ(1u, log.size());
129   EXPECT_EQ(0, log[0].first);
130   EXPECT_EQ(base::File::FILE_ERROR_ABORT, log[0].second);
131   EXPECT_EQ(0u, file_system.close_requests().size());
132 }
133 
134 }  // namespace file_system_provider
135 }  // namespace chromeos
136