1 /* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 #include "tensorflow/c/experimental/filesystem/modular_filesystem.h"
16 
17 #include <memory>
18 #include <random>
19 #include <string>
20 
21 #include "tensorflow/core/lib/io/path.h"
22 #include "tensorflow/core/platform/env.h"
23 #include "tensorflow/core/platform/stacktrace_handler.h"
24 #include "tensorflow/core/platform/test.h"
25 #include "tensorflow/core/util/command_line_flags.h"
26 
27 #if defined(PLATFORM_WINDOWS)
28 // Make mkdir resolve to _mkdir to create the test temporary directory.
29 #include <direct.h>
30 #define mkdir(name, mode) _mkdir(name)
31 
32 // Windows defines the following macros to convert foo to fooA or fooW,
33 // depending on the type of the string argument. We don't use these macros, so
34 // undefine them here.
35 #undef CopyFile
36 #undef DeleteFile
37 #undef TranslateName
38 #endif  // defined(PLATFORM_WINDOWS)
39 
40 // The tests defined here test the compliance of filesystems with the API
41 // defined by `filesystem_interface.h`.
42 //
43 // As some filesystems require special setup, these tests are run manually.
44 //
45 // Each filesystem implementation can be provided by DSOs, so we provide the
46 // `--dsos` flag to specify a list of shared objects to be loaded in order.
47 // If the flag is not used, no shared objects are loaded.
48 //
49 // Every filesystem provides support for accessing URIs of form
50 // `[<scheme>://]<path>` where `<scheme>` is optional (if missing, we are
51 // accessing local paths). This test suite tests exactly one scheme for each
52 // invocation. By default, we are testing all schemes available but this can be
53 // restricted by using `--schemes` to specify a set of schemes to test.
54 //
55 // Example invocation:
56 //  bazel test //tensorflow/c/experimental/filesystem:modular_filesystem_test \\
57 //  --test_arg=--dso=/path/to/one.so --test_arg=--dso=/path/to/another.so \\
58 //  --test_arg=--scheme= --test_arg=--scheme=file
59 //
60 // Note that to test the local filesystem we use an empty value.
61 
62 namespace tensorflow {
63 namespace {
64 
65 using ::tensorflow::error::Code;
66 
67 // As we need to test multiple URI schemes we need a parameterized test.
68 // Furthermore, since each test creates and deletes files, we will use the same
69 // fixture to create new directories in `SetUp`. Each directory will reside in
70 // `::testing::TempDir()`, will use a RNG component and the test name. This
71 // ensures that two consecutive runs are unlikely to clash.
72 class ModularFileSystemTest : public ::testing::TestWithParam<std::string> {
73  public:
74   // Initializes `root_dir_` to a unique value made of `::testing::TempDir()`, a
75   // static random value unique for all the tests in one invocation, and the
76   // current test name.
77   //
78   // Since the test name contains `/` (due to parameters), this function
79   // replaces `/` with `_`.
80   //
81   // We trade in one extra initialization for readability.
ModularFileSystemTest()82   ModularFileSystemTest() {
83     const std::string test_name = tensorflow::str_util::StringReplace(
84         ::testing::UnitTest::GetInstance()->current_test_info()->name(), "/",
85         "_", /*replace_all=*/true);
86     if (!cloud_path_.empty()) {
87       // We have to join path for non-local filesystem manually to make sure
88       // that this test will run on Windows since `tensorflow::io::JoinPath`
89       // behaves differently on Windows. `tmp_dir` should be something like
90       // `path/to/tmp/dir/`. After joining path, we will have
91       // /path/to/tmp/dir/tf_fs_rng_name/`
92       root_dir_ = tensorflow::strings::StrCat(
93           "/", tmp_dir_,
94           tensorflow::strings::StrCat("tf_fs_", rng_val_, "_", test_name), "/");
95     } else {
96       root_dir_ = tensorflow::io::JoinPath(
97           tmp_dir_,
98           tensorflow::strings::StrCat("tf_fs_", rng_val_, "_", test_name));
99     }
100     if (!GetParam().empty()) {
101       root_dir_ = tensorflow::strings::StrCat(GetParam(), "://", cloud_path_,
102                                               root_dir_);
103     }
104     env_ = Env::Default();
105   }
106 
SetUp()107   void SetUp() override {
108     FileSystem* fs = nullptr;
109     Status s = env_->GetFileSystemForFile(root_dir_, &fs);
110     if (fs == nullptr || !s.ok())
111       GTEST_SKIP() << "No filesystem registered: " << s;
112 
113     s = fs->CreateDir(root_dir_);
114     if (!s.ok()) {
115       GTEST_SKIP() << "Cannot create working directory: " << s;
116     }
117   }
118 
119   // Converts path reference to URI reference.
120   //
121   // If URI scheme is empty, URI reference is `path` relative to current test
122   // root directory. Otherwise, we need to add the `<scheme>://` in front of
123   // this path.
124   //
125   // Note that some filesystem might require a different approach here, for
126   // example they might require the root directory path to be in a special
127   // format, etc. When we get there, we might decide to move this class to
128   // `modular_filesystem_test.h` and extend the instantiation to also take as
129   // argument an implementation for this method/a subclass factory (see
130   // https://github.com/google/googletest/blob/master/googletest/docs/advanced.md#creating-value-parameterized-abstract-tests)
GetURIForPath(StringPiece path)131   std::string GetURIForPath(StringPiece path) {
132     const std::string translated_name =
133         tensorflow::io::JoinPath(root_dir_, path);
134     // We have already checked `GetParam().empty()` in
135     // `ModularFileSystemTest()`. root_dir_ should contain `GetParam() + "://"`
136     // if it isn't empty.
137     return translated_name;
138   }
139 
140   // Converts absolute paths to paths relative to root_dir_.
GetRelativePath(StringPiece absolute_path)141   StringPiece GetRelativePath(StringPiece absolute_path) {
142     return tensorflow::str_util::StripPrefix(absolute_path, root_dir_);
143   }
144 
145   // Initializes the randomness used to ensure test isolation.
InitializeTestRNG()146   static void InitializeTestRNG() {
147     std::random_device rd;
148     std::mt19937 gen(rd());
149     std::uniform_int_distribution<> distribution;
150     rng_val_ = distribution(gen);
151   }
152 
SetCloudPath(const std::string & cloud_path)153   static void SetCloudPath(const std::string& cloud_path) {
154     cloud_path_ = cloud_path;
155     if (cloud_path_.back() == '/') cloud_path_.pop_back();
156   }
157 
SetTmpDir(const std::string & tmp_dir)158   static void SetTmpDir(const std::string& tmp_dir) {
159     tmp_dir_ = tmp_dir.empty() ? ::testing::TempDir() : tmp_dir;
160   }
161 
162  protected:
163   Env* env_;
164 
165  private:
166   std::string root_dir_;
167   static int rng_val_;
168   static std::string cloud_path_;
169   static std::string tmp_dir_;
170 };
171 
172 int ModularFileSystemTest::rng_val_;
173 std::string ModularFileSystemTest::cloud_path_;
174 std::string ModularFileSystemTest::tmp_dir_;
175 
176 // As some of the implementations might be missing, the tests should still pass
177 // if the returned `Status` signals the unimplemented state.
UnimplementedOrReturnsCode(Status actual_status,Code expected_code)178 bool UnimplementedOrReturnsCode(Status actual_status, Code expected_code) {
179   Code actual_code = actual_status.code();
180   return (actual_code == Code::UNIMPLEMENTED) || (actual_code == expected_code);
181 }
182 
TEST_P(ModularFileSystemTest,TestTranslateName)183 TEST_P(ModularFileSystemTest, TestTranslateName) {
184   const std::string generic_path = GetURIForPath("some_path");
185   FileSystem* fs = nullptr;
186   Status s = env_->GetFileSystemForFile(generic_path, &fs);
187   if (fs == nullptr || !s.ok())
188     GTEST_SKIP() << "No filesystem registered: " << s;
189 
190   // First, test some interesting corner cases concerning empty URIs
191   if (GetParam().empty()) {
192     EXPECT_EQ(fs->TranslateName(""), "");
193     EXPECT_EQ(fs->TranslateName("/"), "/");
194     EXPECT_EQ(fs->TranslateName("//"), "/");
195     // Empty scheme also allows relative paths
196     EXPECT_EQ(fs->TranslateName("a_file"), "a_file");
197     EXPECT_EQ(fs->TranslateName("a_dir/.."), ".");
198   } else {
199     EXPECT_EQ(fs->TranslateName(tensorflow::strings::StrCat(GetParam(), "://")),
200               "/");
201     EXPECT_EQ(
202         fs->TranslateName(tensorflow::strings::StrCat(GetParam(), ":///")),
203         "/");
204     EXPECT_EQ(
205         fs->TranslateName(tensorflow::strings::StrCat(GetParam(), ":////")),
206         "/");
207   }
208 
209   // Now test several paths/URIs
210   EXPECT_EQ(GetRelativePath(fs->TranslateName(GetURIForPath("a_file"))),
211             "/a_file");
212   EXPECT_EQ(GetRelativePath(fs->TranslateName(GetURIForPath("a_dir/a_file"))),
213             "/a_dir/a_file");
214   EXPECT_EQ(GetRelativePath(fs->TranslateName(GetURIForPath("./a_file"))),
215             "/a_file");
216   EXPECT_EQ(GetRelativePath(fs->TranslateName(
217                 GetURIForPath("a/convoluted/../path/./to/.//.///a/file"))),
218             "/a/path/to/a/file");
219 }
220 
TEST_P(ModularFileSystemTest,TestCreateFile)221 TEST_P(ModularFileSystemTest, TestCreateFile) {
222   const std::string filepath = GetURIForPath("a_file");
223   std::unique_ptr<WritableFile> new_file;
224   Status status = env_->NewWritableFile(filepath, &new_file);
225   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
226 }
227 
TEST_P(ModularFileSystemTest,TestCreateFileNonExisting)228 TEST_P(ModularFileSystemTest, TestCreateFileNonExisting) {
229   const std::string filepath = GetURIForPath("dir_not_found/a_file");
230   std::unique_ptr<WritableFile> new_file;
231   Status status = env_->NewWritableFile(filepath, &new_file);
232   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::NOT_FOUND);
233 }
234 
TEST_P(ModularFileSystemTest,TestCreateFileExistingDir)235 TEST_P(ModularFileSystemTest, TestCreateFileExistingDir) {
236   const std::string filepath = GetURIForPath("a_file");
237   Status status = env_->CreateDir(filepath);
238   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
239 
240   std::unique_ptr<WritableFile> new_file;
241   status = env_->NewWritableFile(filepath, &new_file);
242   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
243 }
244 
TEST_P(ModularFileSystemTest,TestCreateFilePathIsInvalid)245 TEST_P(ModularFileSystemTest, TestCreateFilePathIsInvalid) {
246   const std::string filepath = GetURIForPath("a_file");
247   std::unique_ptr<WritableFile> file;
248   Status status = env_->NewWritableFile(filepath, &file);
249   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
250 
251   const std::string new_path = GetURIForPath("a_file/a_file");
252   std::unique_ptr<WritableFile> new_file;
253   status = env_->NewWritableFile(new_path, &new_file);
254   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
255 }
256 
TEST_P(ModularFileSystemTest,TestAppendFile)257 TEST_P(ModularFileSystemTest, TestAppendFile) {
258   const std::string filepath = GetURIForPath("a_file");
259   std::unique_ptr<WritableFile> new_file;
260   Status status = env_->NewAppendableFile(filepath, &new_file);
261   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
262 }
263 
TEST_P(ModularFileSystemTest,TestAppendFileNonExisting)264 TEST_P(ModularFileSystemTest, TestAppendFileNonExisting) {
265   const std::string filepath = GetURIForPath("dir_not_found/a_file");
266   std::unique_ptr<WritableFile> new_file;
267   Status status = env_->NewAppendableFile(filepath, &new_file);
268   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::NOT_FOUND);
269 }
270 
TEST_P(ModularFileSystemTest,TestAppendFileExistingDir)271 TEST_P(ModularFileSystemTest, TestAppendFileExistingDir) {
272   const std::string filepath = GetURIForPath("a_file");
273   Status status = env_->CreateDir(filepath);
274   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
275 
276   std::unique_ptr<WritableFile> new_file;
277   status = env_->NewAppendableFile(filepath, &new_file);
278   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
279 }
280 
TEST_P(ModularFileSystemTest,TestCreateThenAppendFile)281 TEST_P(ModularFileSystemTest, TestCreateThenAppendFile) {
282   const std::string filepath = GetURIForPath("a_file");
283   std::unique_ptr<WritableFile> new_file;
284   Status status = env_->NewWritableFile(filepath, &new_file);
285   if (!status.ok())
286     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
287 
288   std::unique_ptr<WritableFile> same_file;
289   status = env_->NewAppendableFile(filepath, &same_file);
290   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
291 }
292 
TEST_P(ModularFileSystemTest,TestAppendFilePathIsInvalid)293 TEST_P(ModularFileSystemTest, TestAppendFilePathIsInvalid) {
294   const std::string filepath = GetURIForPath("a_file");
295   std::unique_ptr<WritableFile> file;
296   Status status = env_->NewWritableFile(filepath, &file);
297   if (!status.ok())
298     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
299 
300   const std::string new_path = GetURIForPath("a_file/a_file");
301   std::unique_ptr<WritableFile> same_file;
302   status = env_->NewAppendableFile(new_path, &same_file);
303   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
304 }
305 
TEST_P(ModularFileSystemTest,TestReadFile)306 TEST_P(ModularFileSystemTest, TestReadFile) {
307   const std::string filepath = GetURIForPath("a_file");
308   std::unique_ptr<RandomAccessFile> new_file;
309   Status status = env_->NewRandomAccessFile(filepath, &new_file);
310   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::NOT_FOUND);
311 }
312 
TEST_P(ModularFileSystemTest,TestReadFileNonExisting)313 TEST_P(ModularFileSystemTest, TestReadFileNonExisting) {
314   const std::string filepath = GetURIForPath("dir_not_found/a_file");
315   std::unique_ptr<RandomAccessFile> new_file;
316   Status status = env_->NewRandomAccessFile(filepath, &new_file);
317   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::NOT_FOUND);
318 }
319 
TEST_P(ModularFileSystemTest,TestReadFileExistingDir)320 TEST_P(ModularFileSystemTest, TestReadFileExistingDir) {
321   const std::string filepath = GetURIForPath("a_file");
322   Status status = env_->CreateDir(filepath);
323   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
324 
325   std::unique_ptr<RandomAccessFile> new_file;
326   status = env_->NewRandomAccessFile(filepath, &new_file);
327   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
328 }
329 
TEST_P(ModularFileSystemTest,TestCreateThenReadFile)330 TEST_P(ModularFileSystemTest, TestCreateThenReadFile) {
331   const std::string filepath = GetURIForPath("a_file");
332   std::unique_ptr<WritableFile> new_file;
333   Status status = env_->NewWritableFile(filepath, &new_file);
334   if (!status.ok())
335     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
336 
337   std::unique_ptr<RandomAccessFile> same_file;
338   status = env_->NewRandomAccessFile(filepath, &same_file);
339   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
340 }
341 
TEST_P(ModularFileSystemTest,TestReadFilePathIsInvalid)342 TEST_P(ModularFileSystemTest, TestReadFilePathIsInvalid) {
343   const std::string filepath = GetURIForPath("a_file");
344   std::unique_ptr<WritableFile> file;
345   Status status = env_->NewWritableFile(filepath, &file);
346   if (!status.ok())
347     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
348 
349   const std::string new_path = GetURIForPath("a_file/a_file");
350   std::unique_ptr<RandomAccessFile> same_file;
351   status = env_->NewRandomAccessFile(new_path, &same_file);
352   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
353 }
354 
TEST_P(ModularFileSystemTest,TestCreateMemoryRegion)355 TEST_P(ModularFileSystemTest, TestCreateMemoryRegion) {
356   const std::string filepath = GetURIForPath("a_file");
357   std::unique_ptr<ReadOnlyMemoryRegion> region;
358   Status status = env_->NewReadOnlyMemoryRegionFromFile(filepath, ®ion);
359   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::NOT_FOUND);
360 }
361 
TEST_P(ModularFileSystemTest,TestCreateMemoryRegionNonExisting)362 TEST_P(ModularFileSystemTest, TestCreateMemoryRegionNonExisting) {
363   const std::string filepath = GetURIForPath("dir_not_found/a_file");
364   std::unique_ptr<ReadOnlyMemoryRegion> region;
365   Status status = env_->NewReadOnlyMemoryRegionFromFile(filepath, ®ion);
366   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::NOT_FOUND);
367 }
368 
TEST_P(ModularFileSystemTest,TestCreateMemoryRegionExistingDir)369 TEST_P(ModularFileSystemTest, TestCreateMemoryRegionExistingDir) {
370   const std::string filepath = GetURIForPath("a_file");
371   Status status = env_->CreateDir(filepath);
372   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
373 
374   std::unique_ptr<ReadOnlyMemoryRegion> new_file;
375   status = env_->NewReadOnlyMemoryRegionFromFile(filepath, &new_file);
376   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
377 }
378 
TEST_P(ModularFileSystemTest,TestCreateMemoryRegionFromEmptyFile)379 TEST_P(ModularFileSystemTest, TestCreateMemoryRegionFromEmptyFile) {
380   const std::string filepath = GetURIForPath("a_file");
381   std::unique_ptr<WritableFile> new_file;
382   Status status = env_->NewWritableFile(filepath, &new_file);
383   if (!status.ok())
384     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
385 
386   std::unique_ptr<ReadOnlyMemoryRegion> region;
387   status = env_->NewReadOnlyMemoryRegionFromFile(filepath, ®ion);
388   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::INVALID_ARGUMENT);
389 }
390 
TEST_P(ModularFileSystemTest,TestCreateMemoryRegionFromFile)391 TEST_P(ModularFileSystemTest, TestCreateMemoryRegionFromFile) {
392   const std::string filepath = GetURIForPath("a_file");
393   std::unique_ptr<WritableFile> new_file;
394   Status status = env_->NewWritableFile(filepath, &new_file);
395   if (!status.ok())
396     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
397 
398   const std::string test_data("asdf");
399   status = new_file->Append(test_data);
400   if (!status.ok()) GTEST_SKIP() << "Append() not supported: " << status;
401   status = new_file->Flush();
402   if (!status.ok()) GTEST_SKIP() << "Flush() not supported: " << status;
403   status = new_file->Close();
404   if (!status.ok()) GTEST_SKIP() << "Close() not supported: " << status;
405 
406   std::unique_ptr<ReadOnlyMemoryRegion> region;
407   status = env_->NewReadOnlyMemoryRegionFromFile(filepath, ®ion);
408   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
409   if (!status.ok())
410     GTEST_SKIP() << "NewReadOnlyMemoryRegionFromFile() not supported: "
411                  << status;
412   EXPECT_EQ(region->length(), test_data.size());
413   EXPECT_STREQ(reinterpret_cast<const char*>(region->data()),
414                test_data.c_str());
415 }
416 
TEST_P(ModularFileSystemTest,TestCreateMemoryRegionFromFilePathIsInvalid)417 TEST_P(ModularFileSystemTest, TestCreateMemoryRegionFromFilePathIsInvalid) {
418   const std::string filepath = GetURIForPath("a_file");
419   std::unique_ptr<WritableFile> file;
420   Status status = env_->NewWritableFile(filepath, &file);
421   if (!status.ok())
422     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
423 
424   std::string new_path = GetURIForPath("a_file/a_file");
425   std::unique_ptr<ReadOnlyMemoryRegion> region;
426   status = env_->NewReadOnlyMemoryRegionFromFile(new_path, ®ion);
427   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
428 }
429 
TEST_P(ModularFileSystemTest,TestCreateDir)430 TEST_P(ModularFileSystemTest, TestCreateDir) {
431   const std::string dirpath = GetURIForPath("a_dir");
432   Status status = env_->CreateDir(dirpath);
433   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
434 }
435 
TEST_P(ModularFileSystemTest,TestCreateDirNoParent)436 TEST_P(ModularFileSystemTest, TestCreateDirNoParent) {
437   const std::string dirpath = GetURIForPath("dir_not_found/a_dir");
438   Status status = env_->CreateDir(dirpath);
439   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::NOT_FOUND);
440 }
441 
TEST_P(ModularFileSystemTest,TestCreateDirWhichIsFile)442 TEST_P(ModularFileSystemTest, TestCreateDirWhichIsFile) {
443   const std::string filepath = GetURIForPath("a_file");
444   std::unique_ptr<WritableFile> new_file;
445   Status status = env_->NewWritableFile(filepath, &new_file);
446   if (!status.ok())
447     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
448 
449   status = env_->CreateDir(filepath);
450   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::ALREADY_EXISTS);
451 }
452 
TEST_P(ModularFileSystemTest,TestCreateDirTwice)453 TEST_P(ModularFileSystemTest, TestCreateDirTwice) {
454   const std::string dirpath = GetURIForPath("a_dir");
455   Status status = env_->CreateDir(dirpath);
456   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
457 
458   status = env_->CreateDir(dirpath);
459   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::ALREADY_EXISTS);
460 }
461 
TEST_P(ModularFileSystemTest,TestCreateDirPathIsInvalid)462 TEST_P(ModularFileSystemTest, TestCreateDirPathIsInvalid) {
463   const std::string filepath = GetURIForPath("a_file");
464   std::unique_ptr<WritableFile> file;
465   Status status = env_->NewWritableFile(filepath, &file);
466   if (!status.ok())
467     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
468 
469   const std::string new_path = GetURIForPath("a_file/a_dir");
470   status = env_->CreateDir(new_path);
471   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
472 }
473 
TEST_P(ModularFileSystemTest,TestRecursivelyCreateDir)474 TEST_P(ModularFileSystemTest, TestRecursivelyCreateDir) {
475   const std::string dirpath = GetURIForPath("a/path/to/a/dir");
476   Status status = env_->RecursivelyCreateDir(dirpath);
477   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
478 }
479 
TEST_P(ModularFileSystemTest,TestRecursivelyCreateDirInATree)480 TEST_P(ModularFileSystemTest, TestRecursivelyCreateDirInATree) {
481   const std::string dirpath = GetURIForPath("a/path/to/a/dir");
482   Status status = env_->RecursivelyCreateDir(dirpath);
483   if (!status.ok())
484     GTEST_SKIP() << "RecursivelyCreateDir() not supported: " << status;
485 
486   const std::string new_dirpath = GetURIForPath("a/path/to/a/another/dir");
487   status = env_->RecursivelyCreateDir(new_dirpath);
488   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
489 }
490 
TEST_P(ModularFileSystemTest,TestRecursivelyCreateDirWhichIsFile)491 TEST_P(ModularFileSystemTest, TestRecursivelyCreateDirWhichIsFile) {
492   const std::string filepath = GetURIForPath("a_file");
493   std::unique_ptr<WritableFile> new_file;
494   Status status = env_->NewWritableFile(filepath, &new_file);
495   if (!status.ok())
496     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
497 
498   status = env_->RecursivelyCreateDir(filepath);
499   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
500 }
501 
TEST_P(ModularFileSystemTest,TestRecursivelyCreateDirTwice)502 TEST_P(ModularFileSystemTest, TestRecursivelyCreateDirTwice) {
503   const std::string dirpath = GetURIForPath("a/path/to/a/dir");
504   Status status = env_->RecursivelyCreateDir(dirpath);
505   if (!status.ok())
506     GTEST_SKIP() << "RecursivelyCreateDir() not supported: " << status;
507 
508   status = env_->RecursivelyCreateDir(dirpath);
509   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
510 }
511 
TEST_P(ModularFileSystemTest,TestRecursivelyCreateDirPathIsInvalid)512 TEST_P(ModularFileSystemTest, TestRecursivelyCreateDirPathIsInvalid) {
513   const std::string filepath = GetURIForPath("a_file");
514   std::unique_ptr<WritableFile> file;
515   Status status = env_->NewWritableFile(filepath, &file);
516   if (!status.ok())
517     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
518 
519   const std::string new_path = GetURIForPath("a_file/a_dir");
520   status = env_->RecursivelyCreateDir(new_path);
521   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
522 }
523 
TEST_P(ModularFileSystemTest,TestRecursivelyCreateDirFromNestedDir)524 TEST_P(ModularFileSystemTest, TestRecursivelyCreateDirFromNestedDir) {
525   const std::string parent_path = GetURIForPath("some/path");
526   Status status = env_->RecursivelyCreateDir(parent_path);
527   if (!status.ok())
528     GTEST_SKIP() << "RecursivelyCreateDir() not supported: " << status;
529 
530   const std::string new_dirpath = GetURIForPath("some/path/that/is/extended");
531   status = env_->RecursivelyCreateDir(new_dirpath);
532   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
533 }
534 
TEST_P(ModularFileSystemTest,TestRecursivelyCreateDirFromNestedFile)535 TEST_P(ModularFileSystemTest, TestRecursivelyCreateDirFromNestedFile) {
536   const std::string parent_path = GetURIForPath("some/path");
537   Status status = env_->RecursivelyCreateDir(parent_path);
538   if (!status.ok())
539     GTEST_SKIP() << "RecursivelyCreateDir() not supported: " << status;
540 
541   const std::string filepath = GetURIForPath("some/path/to_a_file");
542   std::unique_ptr<WritableFile> file;
543   status = env_->NewWritableFile(filepath, &file);
544   if (!status.ok())
545     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
546 
547   const std::string new_dirpath = GetURIForPath("some/path/to_a_file/error");
548   status = env_->RecursivelyCreateDir(new_dirpath);
549   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
550 }
551 
TEST_P(ModularFileSystemTest,TestDeleteFile)552 TEST_P(ModularFileSystemTest, TestDeleteFile) {
553   const std::string filepath = GetURIForPath("a_file");
554   std::unique_ptr<WritableFile> new_file;
555   Status status = env_->NewWritableFile(filepath, &new_file);
556   if (!status.ok())
557     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
558 
559   status = env_->DeleteFile(filepath);
560   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
561 }
562 
TEST_P(ModularFileSystemTest,TestDeleteFileFromDirectory)563 TEST_P(ModularFileSystemTest, TestDeleteFileFromDirectory) {
564   const std::string dirpath = GetURIForPath("a_dir");
565   Status status = env_->CreateDir(dirpath);
566   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
567 
568   const std::string filepath = GetURIForPath("a_dir/a_file");
569   std::unique_ptr<WritableFile> new_file;
570   status = env_->NewWritableFile(filepath, &new_file);
571   if (!status.ok())
572     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
573 
574   status = env_->DeleteFile(filepath);
575   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
576 }
577 
TEST_P(ModularFileSystemTest,TestDeleteFileDoesNotExist)578 TEST_P(ModularFileSystemTest, TestDeleteFileDoesNotExist) {
579   const std::string filepath = GetURIForPath("a_file");
580   Status status = env_->DeleteFile(filepath);
581   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::NOT_FOUND);
582 }
583 
TEST_P(ModularFileSystemTest,TestDeleteFileWhichIsDirectory)584 TEST_P(ModularFileSystemTest, TestDeleteFileWhichIsDirectory) {
585   const std::string dirpath = GetURIForPath("a_dir");
586   Status status = env_->CreateDir(dirpath);
587   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
588 
589   status = env_->DeleteFile(dirpath);
590   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
591 }
592 
TEST_P(ModularFileSystemTest,TestDeleteFilePathIsInvalid)593 TEST_P(ModularFileSystemTest, TestDeleteFilePathIsInvalid) {
594   const std::string filepath = GetURIForPath("a_file");
595   std::unique_ptr<WritableFile> file;
596   Status status = env_->NewWritableFile(filepath, &file);
597   if (!status.ok())
598     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
599 
600   const std::string new_path = GetURIForPath("a_file/a_new_file");
601   status = env_->DeleteFile(new_path);
602   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
603 }
604 
TEST_P(ModularFileSystemTest,TestDeleteDirectory)605 TEST_P(ModularFileSystemTest, TestDeleteDirectory) {
606   const std::string dirpath = GetURIForPath("a_dir");
607   Status status = env_->CreateDir(dirpath);
608   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
609 
610   status = env_->DeleteDir(dirpath);
611   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
612 }
613 
TEST_P(ModularFileSystemTest,TestDeleteDirectoryFromDirectory)614 TEST_P(ModularFileSystemTest, TestDeleteDirectoryFromDirectory) {
615   const std::string dirpath = GetURIForPath("a_dir");
616   Status status = env_->CreateDir(dirpath);
617   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
618 
619   const std::string target_path = GetURIForPath("a_dir/another_dir");
620   EXPECT_EQ(env_->CreateDir(target_path).code(), Code::OK);
621 
622   status = env_->DeleteDir(target_path);
623   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
624 }
625 
TEST_P(ModularFileSystemTest,TestDeleteDirectoryDoesNotExist)626 TEST_P(ModularFileSystemTest, TestDeleteDirectoryDoesNotExist) {
627   const std::string dirpath = GetURIForPath("a_dir");
628   Status status = env_->DeleteDir(dirpath);
629   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::NOT_FOUND);
630 }
631 
TEST_P(ModularFileSystemTest,TestDeleteDirectoryNotEmpty)632 TEST_P(ModularFileSystemTest, TestDeleteDirectoryNotEmpty) {
633   const std::string dirpath = GetURIForPath("a_dir");
634   Status status = env_->CreateDir(dirpath);
635   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
636 
637   const std::string filepath = GetURIForPath("a_dir/a_file");
638   std::unique_ptr<WritableFile> new_file;
639   status = env_->NewWritableFile(filepath, &new_file);
640   if (!status.ok())
641     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
642 
643   status = env_->DeleteDir(dirpath);
644   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
645 }
646 
TEST_P(ModularFileSystemTest,TestDeleteDirectoryWhichIsFile)647 TEST_P(ModularFileSystemTest, TestDeleteDirectoryWhichIsFile) {
648   const std::string filepath = GetURIForPath("a_file");
649   std::unique_ptr<WritableFile> new_file;
650   Status status = env_->NewWritableFile(filepath, &new_file);
651   if (!status.ok())
652     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
653 
654   status = env_->DeleteDir(filepath);
655   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
656 }
657 
TEST_P(ModularFileSystemTest,TestDeleteDirectoryPathIsInvalid)658 TEST_P(ModularFileSystemTest, TestDeleteDirectoryPathIsInvalid) {
659   const std::string filepath = GetURIForPath("a_file");
660   std::unique_ptr<WritableFile> file;
661   Status status = env_->NewWritableFile(filepath, &file);
662   if (!status.ok())
663     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
664 
665   const std::string new_path = GetURIForPath("a_file/a_dir");
666   status = env_->DeleteDir(new_path);
667   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
668 }
669 
TEST_P(ModularFileSystemTest,TestDeleteRecursivelyEmpty)670 TEST_P(ModularFileSystemTest, TestDeleteRecursivelyEmpty) {
671   const std::string dirpath = GetURIForPath("a_dir");
672   Status status = env_->CreateDir(dirpath);
673   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
674 
675   int64_t undeleted_files = 0;
676   int64_t undeleted_dirs = 0;
677   status = env_->DeleteRecursively(dirpath, &undeleted_files, &undeleted_dirs);
678   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
679   EXPECT_EQ(undeleted_files, 0);
680   EXPECT_EQ(undeleted_dirs, 0);
681 }
682 
TEST_P(ModularFileSystemTest,TestDeleteRecursivelyNotEmpty)683 TEST_P(ModularFileSystemTest, TestDeleteRecursivelyNotEmpty) {
684   const std::string dirpath = GetURIForPath("a_dir");
685   Status status = env_->CreateDir(dirpath);
686   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
687 
688   const std::string some_path = GetURIForPath("a_dir/another_dir");
689   status = env_->CreateDir(some_path);
690   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
691 
692   const std::string another_path = GetURIForPath("a_dir/yet_another_dir");
693   status = env_->CreateDir(another_path);
694   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
695 
696   const std::string filepath = GetURIForPath("a_dir/a_file");
697   std::unique_ptr<WritableFile> new_file;
698   status = env_->NewWritableFile(filepath, &new_file);
699   if (!status.ok())
700     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
701 
702   int64_t undeleted_files = 0;
703   int64_t undeleted_dirs = 0;
704   status = env_->DeleteRecursively(dirpath, &undeleted_files, &undeleted_dirs);
705   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
706   EXPECT_EQ(undeleted_files, 0);
707   EXPECT_EQ(undeleted_dirs, 0);
708 }
709 
TEST_P(ModularFileSystemTest,TestDeleteRecursivelyDoesNotExist)710 TEST_P(ModularFileSystemTest, TestDeleteRecursivelyDoesNotExist) {
711   const std::string dirpath = GetURIForPath("a_dir");
712 
713   int64_t undeleted_files = 0;
714   int64_t undeleted_dirs = 0;
715   Status status =
716       env_->DeleteRecursively(dirpath, &undeleted_files, &undeleted_dirs);
717   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::NOT_FOUND);
718   EXPECT_EQ(undeleted_files, 0);
719   EXPECT_EQ(undeleted_dirs, 1);
720 }
721 
TEST_P(ModularFileSystemTest,TestDeleteRecursivelyAFile)722 TEST_P(ModularFileSystemTest, TestDeleteRecursivelyAFile) {
723   const std::string filepath = GetURIForPath("a_file");
724   std::unique_ptr<WritableFile> new_file;
725   Status status = env_->NewWritableFile(filepath, &new_file);
726   if (!status.ok())
727     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
728 
729   int64_t undeleted_files = 0;
730   int64_t undeleted_dirs = 0;
731   status = env_->DeleteRecursively(filepath, &undeleted_files, &undeleted_dirs);
732   EXPECT_EQ(undeleted_files, 0);
733   EXPECT_EQ(undeleted_dirs, 0);
734 }
735 
TEST_P(ModularFileSystemTest,TestDeleteRecursivelyPathIsInvalid)736 TEST_P(ModularFileSystemTest, TestDeleteRecursivelyPathIsInvalid) {
737   const std::string filepath = GetURIForPath("a_file");
738   std::unique_ptr<WritableFile> file;
739   Status status = env_->NewWritableFile(filepath, &file);
740   if (!status.ok())
741     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
742 
743   const std::string new_path = GetURIForPath("a_file/a_dir");
744   int64_t undeleted_files, undeleted_dirs;
745   status = env_->DeleteRecursively(new_path, &undeleted_files, &undeleted_dirs);
746   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
747 }
748 
TEST_P(ModularFileSystemTest,TestDeleteRecursivelyANestedDir)749 TEST_P(ModularFileSystemTest, TestDeleteRecursivelyANestedDir) {
750   const std::string parent_path = GetURIForPath("parent/path");
751   Status status = env_->RecursivelyCreateDir(parent_path);
752   if (!status.ok())
753     GTEST_SKIP() << "RecursivelyCreateDir() not supported: " << status;
754 
755   const std::string new_dirpath = GetURIForPath("parent/path/that/is/extended");
756   status = env_->RecursivelyCreateDir(new_dirpath);
757   if (!status.ok())
758     GTEST_SKIP() << "RecursivelyCreateDir() not supported: " << status;
759 
760   const std::string path = GetURIForPath("parent/path/that");
761   int64_t undeleted_files = 0;
762   int64_t undeleted_dirs = 0;
763   status = env_->DeleteRecursively(path, &undeleted_files, &undeleted_dirs);
764   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
765   EXPECT_EQ(undeleted_files, 0);
766   EXPECT_EQ(undeleted_dirs, 0);
767 
768   // Parent directory must still exist
769   status = env_->FileExists(parent_path);
770   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
771 }
772 
TEST_P(ModularFileSystemTest,TestDeleteRecursivelyANestedFile)773 TEST_P(ModularFileSystemTest, TestDeleteRecursivelyANestedFile) {
774   const std::string parent_path = GetURIForPath("some/path");
775   Status status = env_->RecursivelyCreateDir(parent_path);
776   if (!status.ok())
777     GTEST_SKIP() << "RecursivelyCreateDir() not supported: " << status;
778 
779   const std::string filepath = GetURIForPath("some/path/to_a_file");
780   std::unique_ptr<WritableFile> file;
781   status = env_->NewWritableFile(filepath, &file);
782   if (!status.ok())
783     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
784 
785   int64_t undeleted_files = 0;
786   int64_t undeleted_dirs = 0;
787   status = env_->DeleteRecursively(filepath, &undeleted_files, &undeleted_dirs);
788   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
789   EXPECT_EQ(undeleted_files, 0);
790   EXPECT_EQ(undeleted_dirs, 0);
791 
792   // Parent directory must still exist
793   status = env_->FileExists(parent_path);
794   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
795 }
796 
TEST_P(ModularFileSystemTest,TestRenameFile)797 TEST_P(ModularFileSystemTest, TestRenameFile) {
798   const std::string filepath = GetURIForPath("a_file");
799   std::unique_ptr<WritableFile> new_file;
800   Status status = env_->NewWritableFile(filepath, &new_file);
801   if (!status.ok())
802     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
803 
804   const std::string new_filepath = GetURIForPath("a_new_file");
805   status = env_->RenameFile(filepath, new_filepath);
806   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
807   if (!status.ok()) GTEST_SKIP() << "RenameFile() not supported: " << status;
808 
809   status = env_->FileExists(filepath);
810   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::NOT_FOUND);
811   status = env_->FileExists(new_filepath);
812   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
813 }
814 
TEST_P(ModularFileSystemTest,TestRenameFileOverwrite)815 TEST_P(ModularFileSystemTest, TestRenameFileOverwrite) {
816   const std::string filepath = GetURIForPath("a_file");
817   std::unique_ptr<WritableFile> file;
818   Status status = env_->NewWritableFile(filepath, &file);
819   if (!status.ok())
820     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
821 
822   const std::string new_filepath = GetURIForPath("a_new_file");
823   std::unique_ptr<WritableFile> new_file;
824   status = env_->NewWritableFile(filepath, &new_file);
825   if (!status.ok())
826     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
827 
828   status = env_->RenameFile(filepath, new_filepath);
829   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
830   if (!status.ok()) GTEST_SKIP() << "RenameFile() not supported: " << status;
831 
832   status = env_->FileExists(filepath);
833   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::NOT_FOUND);
834   status = env_->FileExists(new_filepath);
835   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
836 }
837 
TEST_P(ModularFileSystemTest,TestRenameFileSourceNotFound)838 TEST_P(ModularFileSystemTest, TestRenameFileSourceNotFound) {
839   const std::string filepath = GetURIForPath("a_file");
840   const std::string new_filepath = GetURIForPath("a_new_file");
841   Status status = env_->RenameFile(filepath, new_filepath);
842   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::NOT_FOUND);
843 }
844 
TEST_P(ModularFileSystemTest,TestRenameFileDestinationParentNotFound)845 TEST_P(ModularFileSystemTest, TestRenameFileDestinationParentNotFound) {
846   const std::string filepath = GetURIForPath("a_file");
847   std::unique_ptr<WritableFile> file;
848   Status status = env_->NewWritableFile(filepath, &file);
849   if (!status.ok())
850     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
851 
852   const std::string new_filepath = GetURIForPath("a_dir/a_file");
853   status = env_->RenameFile(filepath, new_filepath);
854   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::NOT_FOUND);
855 }
856 
TEST_P(ModularFileSystemTest,TestRenameFileSourceIsDirectory)857 TEST_P(ModularFileSystemTest, TestRenameFileSourceIsDirectory) {
858   const std::string dirpath = GetURIForPath("a_dir");
859   Status status = env_->CreateDir(dirpath);
860   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
861 
862   const std::string new_filepath = GetURIForPath("a_new_file");
863   status = env_->RenameFile(dirpath, new_filepath);
864   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
865 }
866 
TEST_P(ModularFileSystemTest,TestRenameFileTargetIsDirectory)867 TEST_P(ModularFileSystemTest, TestRenameFileTargetIsDirectory) {
868   const std::string filepath = GetURIForPath("a_file");
869   std::unique_ptr<WritableFile> new_file;
870   Status status = env_->NewWritableFile(filepath, &new_file);
871   if (!status.ok())
872     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
873 
874   const std::string dirpath = GetURIForPath("a_dir");
875   status = env_->CreateDir(dirpath);
876   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
877 
878   status = env_->RenameFile(filepath, dirpath);
879   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
880 }
881 
TEST_P(ModularFileSystemTest,TestRenameFileSourcePathIsInvalid)882 TEST_P(ModularFileSystemTest, TestRenameFileSourcePathIsInvalid) {
883   const std::string filepath = GetURIForPath("a_file");
884   std::unique_ptr<WritableFile> file;
885   Status status = env_->NewWritableFile(filepath, &file);
886   if (!status.ok())
887     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
888 
889   const std::string old_filepath = GetURIForPath("a_file/x");
890   const std::string new_filepath = GetURIForPath("a_new_file");
891   status = env_->RenameFile(old_filepath, new_filepath);
892   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
893 }
894 
TEST_P(ModularFileSystemTest,TestRenameFileTargetPathIsInvalid)895 TEST_P(ModularFileSystemTest, TestRenameFileTargetPathIsInvalid) {
896   const std::string old_filepath = GetURIForPath("a_file");
897   std::unique_ptr<WritableFile> old_file;
898   Status status = env_->NewWritableFile(old_filepath, &old_file);
899   if (!status.ok())
900     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
901 
902   const std::string filepath = GetURIForPath("a_file");
903   std::unique_ptr<WritableFile> file;
904   status = env_->NewWritableFile(filepath, &file);
905   if (!status.ok())
906     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
907 
908   const std::string new_filepath = GetURIForPath("a_file/a_new_file");
909   status = env_->RenameFile(old_filepath, new_filepath);
910   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
911 }
912 
TEST_P(ModularFileSystemTest,TestRenameFileCompareContents)913 TEST_P(ModularFileSystemTest, TestRenameFileCompareContents) {
914   const std::string filepath = GetURIForPath("a_file");
915   std::unique_ptr<WritableFile> file;
916   Status status = env_->NewWritableFile(filepath, &file);
917   if (!status.ok())
918     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
919 
920   const std::string test_data("asdf");
921   status = file->Append(test_data);
922   if (!status.ok()) GTEST_SKIP() << "Append() not supported: " << status;
923   status = file->Flush();
924   if (!status.ok()) GTEST_SKIP() << "Flush() not supported: " << status;
925   status = file->Close();
926   if (!status.ok()) GTEST_SKIP() << "Close() not supported: " << status;
927 
928   const std::string new_filepath = GetURIForPath("a_new_file");
929   status = env_->RenameFile(filepath, new_filepath);
930   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
931   if (!status.ok()) GTEST_SKIP() << "RenameFile() not supported: " << status;
932 
933   uint64 size;
934   status = env_->GetFileSize(new_filepath, &size);
935   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
936   if (!status.ok()) GTEST_SKIP() << "GetFileSize() not supported: " << status;
937   EXPECT_EQ(size, test_data.size());
938 }
939 
TEST_P(ModularFileSystemTest,TestCopyFile)940 TEST_P(ModularFileSystemTest, TestCopyFile) {
941   const std::string filepath = GetURIForPath("a_file");
942   std::unique_ptr<WritableFile> new_file;
943   Status status = env_->NewWritableFile(filepath, &new_file);
944   if (!status.ok())
945     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
946 
947   const std::string new_filepath = GetURIForPath("a_new_file");
948   status = env_->CopyFile(filepath, new_filepath);
949   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
950   if (!status.ok()) GTEST_SKIP() << "CopyFile() not supported: " << status;
951 
952   status = env_->FileExists(filepath);
953   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
954   status = env_->FileExists(new_filepath);
955   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
956 }
957 
TEST_P(ModularFileSystemTest,TestCopyFileOverwrite)958 TEST_P(ModularFileSystemTest, TestCopyFileOverwrite) {
959   const std::string filepath = GetURIForPath("a_file");
960   std::unique_ptr<WritableFile> file;
961   Status status = env_->NewWritableFile(filepath, &file);
962   if (!status.ok())
963     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
964 
965   const std::string new_filepath = GetURIForPath("a_new_file");
966   std::unique_ptr<WritableFile> new_file;
967   status = env_->NewWritableFile(filepath, &new_file);
968   if (!status.ok())
969     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
970 
971   status = env_->CopyFile(filepath, new_filepath);
972   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
973   if (!status.ok()) GTEST_SKIP() << "CopyFile() not supported: " << status;
974 
975   status = env_->FileExists(filepath);
976   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
977   status = env_->FileExists(new_filepath);
978   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
979 }
980 
TEST_P(ModularFileSystemTest,TestCopyFileSourceNotFound)981 TEST_P(ModularFileSystemTest, TestCopyFileSourceNotFound) {
982   const std::string filepath = GetURIForPath("a_file");
983   const std::string new_filepath = GetURIForPath("a_new_file");
984   Status status = env_->CopyFile(filepath, new_filepath);
985   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::NOT_FOUND);
986 }
987 
TEST_P(ModularFileSystemTest,TestCopyFileSourceIsDirectory)988 TEST_P(ModularFileSystemTest, TestCopyFileSourceIsDirectory) {
989   const std::string dirpath = GetURIForPath("a_dir");
990   Status status = env_->CreateDir(dirpath);
991   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
992 
993   const std::string new_filepath = GetURIForPath("a_new_file");
994   status = env_->CopyFile(dirpath, new_filepath);
995   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
996 }
997 
TEST_P(ModularFileSystemTest,TestCopyFileTargetIsDirectory)998 TEST_P(ModularFileSystemTest, TestCopyFileTargetIsDirectory) {
999   const std::string filepath = GetURIForPath("a_file");
1000   std::unique_ptr<WritableFile> new_file;
1001   Status status = env_->NewWritableFile(filepath, &new_file);
1002   if (!status.ok())
1003     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1004 
1005   const std::string dirpath = GetURIForPath("a_dir");
1006   status = env_->CreateDir(dirpath);
1007   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
1008 
1009   status = env_->CopyFile(filepath, dirpath);
1010   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
1011 }
1012 
TEST_P(ModularFileSystemTest,TestCopyFileSourcePathIsInvalid)1013 TEST_P(ModularFileSystemTest, TestCopyFileSourcePathIsInvalid) {
1014   const std::string filepath = GetURIForPath("a_file");
1015   std::unique_ptr<WritableFile> file;
1016   Status status = env_->NewWritableFile(filepath, &file);
1017   if (!status.ok())
1018     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1019 
1020   const std::string old_filepath = GetURIForPath("a_file/x");
1021   const std::string new_filepath = GetURIForPath("a_new_file");
1022   status = env_->CopyFile(old_filepath, new_filepath);
1023   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
1024 }
1025 
TEST_P(ModularFileSystemTest,TestCopyFileTargetPathIsInvalid)1026 TEST_P(ModularFileSystemTest, TestCopyFileTargetPathIsInvalid) {
1027   const std::string old_filepath = GetURIForPath("a_file");
1028   std::unique_ptr<WritableFile> old_file;
1029   Status status = env_->NewWritableFile(old_filepath, &old_file);
1030   if (!status.ok())
1031     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1032 
1033   const std::string filepath = GetURIForPath("a_file");
1034   std::unique_ptr<WritableFile> file;
1035   status = env_->NewWritableFile(filepath, &file);
1036   if (!status.ok())
1037     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1038 
1039   const std::string new_filepath = GetURIForPath("a_file/a_new_file");
1040   status = env_->CopyFile(old_filepath, new_filepath);
1041   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
1042 }
1043 
TEST_P(ModularFileSystemTest,TestCopyFileCompareContents)1044 TEST_P(ModularFileSystemTest, TestCopyFileCompareContents) {
1045   const std::string filepath = GetURIForPath("a_file");
1046   std::unique_ptr<WritableFile> file;
1047   Status status = env_->NewWritableFile(filepath, &file);
1048   if (!status.ok())
1049     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1050 
1051   const std::string test_data("asdf");
1052   status = file->Append(test_data);
1053   if (!status.ok()) GTEST_SKIP() << "Append() not supported: " << status;
1054   status = file->Flush();
1055   if (!status.ok()) GTEST_SKIP() << "Flush() not supported: " << status;
1056   status = file->Close();
1057   if (!status.ok()) GTEST_SKIP() << "Close() not supported: " << status;
1058 
1059   const std::string new_filepath = GetURIForPath("a_new_file");
1060   status = env_->CopyFile(filepath, new_filepath);
1061   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1062   if (!status.ok()) GTEST_SKIP() << "RenameFile() not supported: " << status;
1063 
1064   uint64 size;
1065   status = env_->GetFileSize(filepath, &size);
1066   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1067   if (!status.ok()) GTEST_SKIP() << "GetFileSize() not supported: " << status;
1068   EXPECT_EQ(size, test_data.size());
1069 
1070   status = env_->GetFileSize(new_filepath, &size);
1071   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1072   if (!status.ok()) GTEST_SKIP() << "GetFileSize() not supported: " << status;
1073   EXPECT_EQ(size, test_data.size());
1074 }
1075 
TEST_P(ModularFileSystemTest,TestFileExists)1076 TEST_P(ModularFileSystemTest, TestFileExists) {
1077   const std::string filepath = GetURIForPath("a_file");
1078   std::unique_ptr<WritableFile> file;
1079   Status status = env_->NewWritableFile(filepath, &file);
1080   if (!status.ok())
1081     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1082 
1083   status = env_->FileExists(filepath);
1084   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1085 }
1086 
TEST_P(ModularFileSystemTest,TestFileExistsButIsDirectory)1087 TEST_P(ModularFileSystemTest, TestFileExistsButIsDirectory) {
1088   const std::string filepath = GetURIForPath("a_file");
1089   Status status = env_->CreateDir(filepath);
1090   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
1091 
1092   status = env_->FileExists(filepath);
1093   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1094 }
1095 
TEST_P(ModularFileSystemTest,TestFileExistsNotFound)1096 TEST_P(ModularFileSystemTest, TestFileExistsNotFound) {
1097   const std::string filepath = GetURIForPath("a_file");
1098   Status status = env_->FileExists(filepath);
1099   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::NOT_FOUND);
1100 }
1101 
TEST_P(ModularFileSystemTest,TestFileExistsPathIsInvalid)1102 TEST_P(ModularFileSystemTest, TestFileExistsPathIsInvalid) {
1103   const std::string filepath = GetURIForPath("a_file");
1104   std::unique_ptr<WritableFile> file;
1105   Status status = env_->NewWritableFile(filepath, &file);
1106   if (!status.ok())
1107     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1108 
1109   const std::string target_path = GetURIForPath("a_file/a_new_file");
1110   status = env_->FileExists(target_path);
1111   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
1112 }
1113 
TEST_P(ModularFileSystemTest,TestFilesExist)1114 TEST_P(ModularFileSystemTest, TestFilesExist) {
1115   const std::vector<std::string> filenames = {GetURIForPath("a"),
1116                                               GetURIForPath("b")};
1117   for (const auto& filename : filenames) {
1118     std::unique_ptr<WritableFile> file;
1119     Status status = env_->NewWritableFile(filename, &file);
1120     if (!status.ok())
1121       GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1122   }
1123 
1124   EXPECT_TRUE(env_->FilesExist(filenames, /*status=*/nullptr));
1125 
1126   std::vector<Status> statuses;
1127   EXPECT_TRUE(env_->FilesExist(filenames, &statuses));
1128   EXPECT_EQ(statuses.size(), filenames.size());
1129   for (const auto& status : statuses)
1130     EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1131 }
1132 
TEST_P(ModularFileSystemTest,TestFilesExistAllFailureModes)1133 TEST_P(ModularFileSystemTest, TestFilesExistAllFailureModes) {
1134   // if reordering these, make sure to reorder checks at the end
1135   const std::vector<std::string> filenames = {
1136       GetURIForPath("a_dir"),
1137       GetURIForPath("a_file"),
1138       GetURIForPath("a_file/a_new_file"),
1139       GetURIForPath("file_not_found"),
1140   };
1141 
1142   Status status = env_->CreateDir(filenames[0]);
1143   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
1144 
1145   std::unique_ptr<WritableFile> file;
1146   status = env_->NewWritableFile(filenames[1], &file);
1147   if (!status.ok())
1148     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1149 
1150   std::vector<Status> statuses;
1151   EXPECT_FALSE(env_->FilesExist(filenames, &statuses));
1152   EXPECT_EQ(statuses.size(), filenames.size());
1153   EXPECT_PRED2(UnimplementedOrReturnsCode, statuses[0], Code::OK);
1154   EXPECT_PRED2(UnimplementedOrReturnsCode, statuses[1], Code::OK);
1155   EXPECT_PRED2(UnimplementedOrReturnsCode, statuses[2],
1156                Code::FAILED_PRECONDITION);
1157   EXPECT_PRED2(UnimplementedOrReturnsCode, statuses[3], Code::NOT_FOUND);
1158 }
1159 
TEST_P(ModularFileSystemTest,TestFilesExistsNoFiles)1160 TEST_P(ModularFileSystemTest, TestFilesExistsNoFiles) {
1161   const std::vector<std::string> filenames = {};
1162   EXPECT_TRUE(env_->FilesExist(filenames, /*status=*/nullptr));
1163 
1164   std::vector<Status> statuses;
1165   EXPECT_TRUE(env_->FilesExist(filenames, &statuses));
1166   EXPECT_TRUE(statuses.empty());
1167 }
1168 
TEST_P(ModularFileSystemTest,TestStatEmptyFile)1169 TEST_P(ModularFileSystemTest, TestStatEmptyFile) {
1170   const std::string filepath = GetURIForPath("a_file");
1171   std::unique_ptr<WritableFile> file;
1172   Status status = env_->NewWritableFile(filepath, &file);
1173   if (!status.ok())
1174     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1175 
1176   FileStatistics stat;
1177   status = env_->Stat(filepath, &stat);
1178   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1179   if (!status.ok()) GTEST_SKIP() << "Stat() not supported: " << status;
1180   EXPECT_FALSE(stat.is_directory);
1181   EXPECT_EQ(stat.length, 0);
1182 }
1183 
TEST_P(ModularFileSystemTest,TestStatNonEmptyFile)1184 TEST_P(ModularFileSystemTest, TestStatNonEmptyFile) {
1185   const std::string filepath = GetURIForPath("a_file");
1186   std::unique_ptr<WritableFile> file;
1187   Status status = env_->NewWritableFile(filepath, &file);
1188   if (!status.ok())
1189     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1190 
1191   const std::string test_data("asdf");
1192   status = file->Append(test_data);
1193   if (!status.ok()) GTEST_SKIP() << "Append() not supported: " << status;
1194   status = file->Flush();
1195   if (!status.ok()) GTEST_SKIP() << "Flush() not supported: " << status;
1196   status = file->Close();
1197   if (!status.ok()) GTEST_SKIP() << "Close() not supported: " << status;
1198 
1199   FileStatistics stat;
1200   status = env_->Stat(filepath, &stat);
1201   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1202   if (!status.ok()) GTEST_SKIP() << "Stat() not supported: " << status;
1203   EXPECT_FALSE(stat.is_directory);
1204   EXPECT_EQ(stat.length, test_data.size());
1205 }
1206 
TEST_P(ModularFileSystemTest,TestStatDirectory)1207 TEST_P(ModularFileSystemTest, TestStatDirectory) {
1208   const std::string dirpath = GetURIForPath("a_dir");
1209   Status status = env_->CreateDir(dirpath);
1210   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
1211 
1212   FileStatistics stat;
1213   status = env_->Stat(dirpath, &stat);
1214   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1215   if (!status.ok()) GTEST_SKIP() << "Stat() not supported: " << status;
1216   EXPECT_TRUE(stat.is_directory);
1217 }
1218 
TEST_P(ModularFileSystemTest,TestStatNotFound)1219 TEST_P(ModularFileSystemTest, TestStatNotFound) {
1220   const std::string dirpath = GetURIForPath("a_dir");
1221   FileStatistics stat;
1222   Status status = env_->Stat(dirpath, &stat);
1223   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::NOT_FOUND);
1224 }
1225 
TEST_P(ModularFileSystemTest,TestStatPathIsInvalid)1226 TEST_P(ModularFileSystemTest, TestStatPathIsInvalid) {
1227   const std::string filepath = GetURIForPath("a_file");
1228   std::unique_ptr<WritableFile> file;
1229   Status status = env_->NewWritableFile(filepath, &file);
1230   if (!status.ok())
1231     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1232 
1233   const std::string target_path = GetURIForPath("a_file/a_new_file");
1234   FileStatistics stat;
1235   status = env_->Stat(target_path, &stat);
1236   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
1237 }
1238 
TEST_P(ModularFileSystemTest,TestIsDirectory)1239 TEST_P(ModularFileSystemTest, TestIsDirectory) {
1240   const std::string dirpath = GetURIForPath("a_dir");
1241   Status status = env_->CreateDir(dirpath);
1242   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
1243 
1244   status = env_->IsDirectory(dirpath);
1245   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1246 }
1247 
TEST_P(ModularFileSystemTest,TestIsDirectoryFile)1248 TEST_P(ModularFileSystemTest, TestIsDirectoryFile) {
1249   const std::string filepath = GetURIForPath("a_file");
1250   std::unique_ptr<WritableFile> file;
1251   Status status = env_->NewWritableFile(filepath, &file);
1252   if (!status.ok())
1253     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1254 
1255   status = env_->IsDirectory(filepath);
1256   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
1257 }
1258 
TEST_P(ModularFileSystemTest,TestIsDirectoryNotFound)1259 TEST_P(ModularFileSystemTest, TestIsDirectoryNotFound) {
1260   const std::string dirpath = GetURIForPath("a_dir");
1261   Status status = env_->IsDirectory(dirpath);
1262   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::NOT_FOUND);
1263 }
1264 
TEST_P(ModularFileSystemTest,TestIsDirectoryPathIsInvalid)1265 TEST_P(ModularFileSystemTest, TestIsDirectoryPathIsInvalid) {
1266   const std::string filepath = GetURIForPath("a_file");
1267   std::unique_ptr<WritableFile> file;
1268   Status status = env_->NewWritableFile(filepath, &file);
1269   if (!status.ok())
1270     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1271 
1272   const std::string target_path = GetURIForPath("a_file/a_new_file");
1273   status = env_->IsDirectory(target_path);
1274   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
1275 }
1276 
TEST_P(ModularFileSystemTest,TestGetFileSizeEmptyFile)1277 TEST_P(ModularFileSystemTest, TestGetFileSizeEmptyFile) {
1278   const std::string filepath = GetURIForPath("a_file");
1279   std::unique_ptr<WritableFile> file;
1280   Status status = env_->NewWritableFile(filepath, &file);
1281   if (!status.ok())
1282     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1283 
1284   uint64 size;
1285   status = env_->GetFileSize(filepath, &size);
1286   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1287   if (!status.ok()) GTEST_SKIP() << "GetFileSize() not supported: " << status;
1288   EXPECT_EQ(size, 0);
1289 }
1290 
TEST_P(ModularFileSystemTest,TestGetFileSizeNonEmptyFile)1291 TEST_P(ModularFileSystemTest, TestGetFileSizeNonEmptyFile) {
1292   const std::string filepath = GetURIForPath("a_file");
1293   std::unique_ptr<WritableFile> file;
1294   Status status = env_->NewWritableFile(filepath, &file);
1295   if (!status.ok())
1296     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1297 
1298   const std::string test_data("asdf");
1299   status = file->Append(test_data);
1300   if (!status.ok()) GTEST_SKIP() << "Append() not supported: " << status;
1301   status = file->Flush();
1302   if (!status.ok()) GTEST_SKIP() << "Flush() not supported: " << status;
1303   status = file->Close();
1304   if (!status.ok()) GTEST_SKIP() << "Close() not supported: " << status;
1305 
1306   uint64 size;
1307   status = env_->GetFileSize(filepath, &size);
1308   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1309   if (!status.ok()) GTEST_SKIP() << "GetFileSize() not supported: " << status;
1310   EXPECT_EQ(size, test_data.size());
1311 }
1312 
TEST_P(ModularFileSystemTest,TestGetFileSizeDirectory)1313 TEST_P(ModularFileSystemTest, TestGetFileSizeDirectory) {
1314   const std::string dirpath = GetURIForPath("a_dir");
1315   Status status = env_->CreateDir(dirpath);
1316   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
1317 
1318   uint64 size;
1319   status = env_->GetFileSize(dirpath, &size);
1320   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
1321 }
1322 
TEST_P(ModularFileSystemTest,TestGetFileSizeNotFound)1323 TEST_P(ModularFileSystemTest, TestGetFileSizeNotFound) {
1324   const std::string filepath = GetURIForPath("a_dir");
1325   uint64 size;
1326   Status status = env_->GetFileSize(filepath, &size);
1327   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::NOT_FOUND);
1328 }
1329 
TEST_P(ModularFileSystemTest,TestGetFileSizePathIsInvalid)1330 TEST_P(ModularFileSystemTest, TestGetFileSizePathIsInvalid) {
1331   const std::string filepath = GetURIForPath("a_file");
1332   std::unique_ptr<WritableFile> file;
1333   Status status = env_->NewWritableFile(filepath, &file);
1334   if (!status.ok())
1335     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1336 
1337   const std::string target_path = GetURIForPath("a_file/a_new_file");
1338   uint64 size;
1339   status = env_->GetFileSize(target_path, &size);
1340   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
1341 }
1342 
TEST_P(ModularFileSystemTest,TestGetChildren)1343 TEST_P(ModularFileSystemTest, TestGetChildren) {
1344   const std::string dirpath = GetURIForPath("dir");
1345   Status status = env_->CreateDir(dirpath);
1346   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
1347 
1348   // If updating, make sure to update expected_children below.
1349   const std::vector<std::string> filenames = {
1350       GetURIForPath("dir/a_file"),
1351       GetURIForPath("dir/another_file"),
1352   };
1353   for (const auto& filename : filenames) {
1354     std::unique_ptr<WritableFile> file;
1355     status = env_->NewWritableFile(filename, &file);
1356     if (!status.ok())
1357       GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1358   }
1359 
1360   // If updating, make sure to update expected_children below.
1361   const std::vector<std::string> dirnames = {
1362       GetURIForPath("dir/a_dir"),
1363       GetURIForPath("dir/another_dir"),
1364   };
1365   for (const auto& dirname : dirnames) {
1366     status = env_->CreateDir(dirname);
1367     if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
1368   }
1369 
1370   std::vector<std::string> children;
1371   status = env_->GetChildren(dirpath, &children);
1372   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1373   if (!status.ok()) GTEST_SKIP() << "GetChildren() not supported: " << status;
1374 
1375   // All entries must show up in the vector.
1376   // Must contain only the last name in filenames and dirnames.
1377   const std::vector<std::string> expected_children = {"a_file", "another_file",
1378                                                       "a_dir", "another_dir"};
1379   EXPECT_EQ(children.size(), filenames.size() + dirnames.size());
1380   for (const auto& child : expected_children)
1381     EXPECT_NE(std::find(children.begin(), children.end(), child),
1382               children.end());
1383 }
1384 
TEST_P(ModularFileSystemTest,TestGetChildrenEmpty)1385 TEST_P(ModularFileSystemTest, TestGetChildrenEmpty) {
1386   const std::string dirpath = GetURIForPath("dir");
1387   Status status = env_->CreateDir(dirpath);
1388   if (!status.ok()) GTEST_SKIP() << "CreateDir() not supported: " << status;
1389 
1390   std::vector<std::string> children;
1391   status = env_->GetChildren(dirpath, &children);
1392   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1393   EXPECT_EQ(children.size(), 0);
1394 }
1395 
TEST_P(ModularFileSystemTest,TestGetChildrenOfFile)1396 TEST_P(ModularFileSystemTest, TestGetChildrenOfFile) {
1397   const std::string filepath = GetURIForPath("a_file");
1398   std::unique_ptr<WritableFile> file;
1399   Status status = env_->NewWritableFile(filepath, &file);
1400   if (!status.ok())
1401     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1402 
1403   std::vector<std::string> children;
1404   status = env_->GetChildren(filepath, &children);
1405   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
1406 }
1407 
TEST_P(ModularFileSystemTest,TestGetChildrenPathNotFound)1408 TEST_P(ModularFileSystemTest, TestGetChildrenPathNotFound) {
1409   const std::string target_path = GetURIForPath("a_dir");
1410   std::vector<std::string> children;
1411   Status status = env_->GetChildren(target_path, &children);
1412   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::NOT_FOUND);
1413 }
1414 
TEST_P(ModularFileSystemTest,TestGetChildrenPathIsInvalid)1415 TEST_P(ModularFileSystemTest, TestGetChildrenPathIsInvalid) {
1416   const std::string filepath = GetURIForPath("a_file");
1417   std::unique_ptr<WritableFile> file;
1418   Status status = env_->NewWritableFile(filepath, &file);
1419   if (!status.ok())
1420     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1421 
1422   const std::string target_path = GetURIForPath("a_file/a_new_dir");
1423   std::vector<std::string> children;
1424   status = env_->GetChildren(target_path, &children);
1425   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::FAILED_PRECONDITION);
1426 }
1427 
TEST_P(ModularFileSystemTest,TestGetMatchingPaths)1428 TEST_P(ModularFileSystemTest, TestGetMatchingPaths) {
1429   const std::vector<std::string> matching_filenames = {
1430       GetURIForPath("a_file"),
1431       GetURIForPath("another_file"),
1432   };
1433   const std::vector<std::string> other_filenames = {
1434       GetURIForPath("some_file"),
1435       GetURIForPath("yet_another_file"),
1436   };
1437 
1438   for (const auto& filename : matching_filenames) {
1439     std::unique_ptr<WritableFile> file;
1440     Status status = env_->NewWritableFile(filename, &file);
1441     if (!status.ok())
1442       GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1443   }
1444 
1445   for (const auto& filename : other_filenames) {
1446     std::unique_ptr<WritableFile> file;
1447     Status status = env_->NewWritableFile(filename, &file);
1448     if (!status.ok())
1449       GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1450   }
1451 
1452   std::vector<std::string> results;
1453   Status status = env_->GetMatchingPaths(GetURIForPath("/a*"), &results);
1454   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1455   if (!status.ok())
1456     GTEST_SKIP() << "GetMatchingPaths() not supported: " << status;
1457   EXPECT_EQ(results.size(), matching_filenames.size());
1458   for (const auto& match : matching_filenames)
1459     EXPECT_NE(std::find(results.begin(), results.end(), match), results.end());
1460 }
1461 
TEST_P(ModularFileSystemTest,TestGetMatchingPathsEmptyFileSystem)1462 TEST_P(ModularFileSystemTest, TestGetMatchingPathsEmptyFileSystem) {
1463   std::vector<std::string> results;
1464   Status status = env_->GetMatchingPaths(GetURIForPath("a*"), &results);
1465   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1466   EXPECT_EQ(results.size(), 0);
1467 }
1468 
TEST_P(ModularFileSystemTest,TestGetMatchingPathsEmptyPattern)1469 TEST_P(ModularFileSystemTest, TestGetMatchingPathsEmptyPattern) {
1470   const std::vector<std::string> filenames = {
1471       GetURIForPath("a_file"),
1472       GetURIForPath("another_file"),
1473       GetURIForPath("some_file"),
1474       GetURIForPath("yet_another_file"),
1475   };
1476 
1477   for (const auto& filename : filenames) {
1478     std::unique_ptr<WritableFile> file;
1479     Status status = env_->NewWritableFile(filename, &file);
1480     if (!status.ok())
1481       GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1482   }
1483 
1484   std::vector<std::string> results;
1485   Status status = env_->GetMatchingPaths(GetURIForPath(""), &results);
1486   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1487   if (!status.ok())
1488     GTEST_SKIP() << "GetMatchingPaths() not supported: " << status;
1489   EXPECT_EQ(results.size(), 1);
1490   EXPECT_NE(std::find(results.begin(), results.end(), GetURIForPath("")),
1491             results.end());
1492 }
1493 
TEST_P(ModularFileSystemTest,TestGetMatchingPathsLiteralMatch)1494 TEST_P(ModularFileSystemTest, TestGetMatchingPathsLiteralMatch) {
1495   const std::vector<std::string> filenames = {
1496       GetURIForPath("a_file"),
1497       GetURIForPath("another_file"),
1498       GetURIForPath("some_file"),
1499       GetURIForPath("yet_another_file"),
1500   };
1501 
1502   for (const auto& filename : filenames) {
1503     std::unique_ptr<WritableFile> file;
1504     Status status = env_->NewWritableFile(filename, &file);
1505     if (!status.ok())
1506       GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1507   }
1508 
1509   std::vector<std::string> results;
1510   Status status = env_->GetMatchingPaths(filenames[0], &results);
1511   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1512   if (!status.ok())
1513     GTEST_SKIP() << "GetMatchingPaths() not supported: " << status;
1514   EXPECT_EQ(results.size(), 1);
1515   EXPECT_NE(std::find(results.begin(), results.end(), filenames[0]),
1516             results.end());
1517 }
1518 
TEST_P(ModularFileSystemTest,TestGetMatchingPathsNoMatch)1519 TEST_P(ModularFileSystemTest, TestGetMatchingPathsNoMatch) {
1520   const std::vector<std::string> filenames = {
1521       GetURIForPath("a_file"),
1522       GetURIForPath("another_file"),
1523       GetURIForPath("some_file"),
1524       GetURIForPath("yet_another_file"),
1525   };
1526 
1527   for (const auto& filename : filenames) {
1528     std::unique_ptr<WritableFile> file;
1529     Status status = env_->NewWritableFile(filename, &file);
1530     if (!status.ok())
1531       GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1532   }
1533 
1534   std::vector<std::string> results;
1535   Status status = env_->GetMatchingPaths(GetURIForPath("x?y*"), &results);
1536   if (!status.ok())
1537     GTEST_SKIP() << "GetMatchingPaths() not supported: " << status;
1538   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1539   EXPECT_EQ(results.size(), 0);
1540 }
1541 
TEST_P(ModularFileSystemTest,TestAppendAndTell)1542 TEST_P(ModularFileSystemTest, TestAppendAndTell) {
1543   const std::string filename = GetURIForPath("a_file");
1544   std::unique_ptr<WritableFile> file;
1545   Status status = env_->NewWritableFile(filename, &file);
1546   if (!status.ok())
1547     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1548 
1549   int64_t position;
1550   status = file->Tell(&position);
1551   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1552   if (!status.ok()) GTEST_SKIP() << "Tell() not supported: " << status;
1553   EXPECT_EQ(position, 0);
1554 
1555   const std::string test_data("asdf");
1556   status = file->Append(test_data);
1557   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1558   if (!status.ok()) GTEST_SKIP() << "Append() not supported: " << status;
1559 
1560   status = file->Tell(&position);
1561   EXPECT_EQ(status.code(), Code::OK);
1562   EXPECT_EQ(position, test_data.size());
1563 }
1564 
TEST_P(ModularFileSystemTest,TestClose)1565 TEST_P(ModularFileSystemTest, TestClose) {
1566   const std::string filename = GetURIForPath("a_file");
1567   std::unique_ptr<WritableFile> file;
1568   Status status = env_->NewWritableFile(filename, &file);
1569   if (!status.ok())
1570     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1571 
1572   status = file->Close();
1573   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1574   if (!status.ok()) GTEST_SKIP() << "Close() not supported: " << status;
1575 }
1576 
TEST_P(ModularFileSystemTest,TestRoundTrip)1577 TEST_P(ModularFileSystemTest, TestRoundTrip) {
1578   const std::string filepath = GetURIForPath("a_file");
1579   std::unique_ptr<WritableFile> file;
1580   Status status = env_->NewWritableFile(filepath, &file);
1581   if (!status.ok())
1582     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1583 
1584   const std::string test_data("asdf");
1585   status = file->Append(test_data);
1586   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1587   if (!status.ok()) GTEST_SKIP() << "Append() not supported: " << status;
1588 
1589   status = file->Flush();
1590   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1591   if (!status.ok()) GTEST_SKIP() << "Flush() not supported: " << status;
1592 
1593   status = file->Close();
1594   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1595   if (!status.ok()) GTEST_SKIP() << "Close() not supported: " << status;
1596 
1597   std::unique_ptr<RandomAccessFile> read_file;
1598   status = env_->NewRandomAccessFile(filepath, &read_file);
1599   if (!status.ok())
1600     GTEST_SKIP() << "NewRandomAccessFile() not supported: " << status;
1601 
1602   char scratch[64 /* big enough to accommodate test_data */] = {0};
1603   StringPiece result;
1604   status = read_file->Read(0, test_data.size(), &result, scratch);
1605   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1606   EXPECT_EQ(test_data, result);
1607 }
1608 
TEST_P(ModularFileSystemTest,TestRoundTripWithAppendableFile)1609 TEST_P(ModularFileSystemTest, TestRoundTripWithAppendableFile) {
1610   const std::string filepath = GetURIForPath("a_file");
1611   std::unique_ptr<WritableFile> file;
1612   Status status = env_->NewWritableFile(filepath, &file);
1613   if (!status.ok())
1614     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1615 
1616   const std::string test_data("asdf");
1617   status = file->Append(test_data);
1618   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1619   if (!status.ok()) GTEST_SKIP() << "Append() not supported: " << status;
1620 
1621   status = file->Flush();
1622   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1623   if (!status.ok()) GTEST_SKIP() << "Flush() not supported: " << status;
1624 
1625   status = file->Close();
1626   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1627   if (!status.ok()) GTEST_SKIP() << "Close() not supported: " << status;
1628 
1629   std::unique_ptr<WritableFile> same_file;
1630   status = env_->NewAppendableFile(filepath, &same_file);
1631   if (!status.ok())
1632     GTEST_SKIP() << "NewAppendableFile() not supported: " << status;
1633 
1634   const std::string more_test_data("qwer");
1635   EXPECT_EQ(same_file->Append(more_test_data).code(), Code::OK);
1636   EXPECT_EQ(same_file->Flush().code(), Code::OK);
1637   EXPECT_EQ(same_file->Close().code(), Code::OK);
1638 
1639   std::unique_ptr<RandomAccessFile> read_file;
1640   status = env_->NewRandomAccessFile(filepath, &read_file);
1641   if (!status.ok())
1642     GTEST_SKIP() << "NewRandomAccessFile() not supported: " << status;
1643 
1644   char scratch[64 /* big enough for test_data and more_test_data */] = {0};
1645   StringPiece result;
1646   status = read_file->Read(0, test_data.size() + more_test_data.size(), &result,
1647                            scratch);
1648   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1649   EXPECT_EQ(test_data + more_test_data, result);
1650   EXPECT_EQ(
1651       read_file->Read(test_data.size(), more_test_data.size(), &result, scratch)
1652           .code(),
1653       Code::OK);
1654   EXPECT_EQ(more_test_data, result);
1655 }
1656 
TEST_P(ModularFileSystemTest,TestReadOutOfRange)1657 TEST_P(ModularFileSystemTest, TestReadOutOfRange) {
1658   const std::string filepath = GetURIForPath("a_file");
1659   std::unique_ptr<WritableFile> file;
1660   Status status = env_->NewWritableFile(filepath, &file);
1661   if (!status.ok())
1662     GTEST_SKIP() << "NewWritableFile() not supported: " << status;
1663 
1664   const std::string test_data("asdf");
1665   status = file->Append(test_data);
1666   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1667   if (!status.ok()) GTEST_SKIP() << "Append() not supported: " << status;
1668 
1669   status = file->Flush();
1670   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1671   if (!status.ok()) GTEST_SKIP() << "Flush() not supported: " << status;
1672 
1673   status = file->Close();
1674   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OK);
1675   if (!status.ok()) GTEST_SKIP() << "Close() not supported: " << status;
1676 
1677   std::unique_ptr<RandomAccessFile> read_file;
1678   status = env_->NewRandomAccessFile(filepath, &read_file);
1679   if (!status.ok())
1680     GTEST_SKIP() << "NewRandomAccessFile() not supported: " << status;
1681 
1682   char scratch[64 /* must be bigger than test_data */] = {0};
1683   StringPiece result;
1684   // read at least 1 byte more than test_data
1685   status = read_file->Read(0, test_data.size() + 1, &result, scratch);
1686   EXPECT_PRED2(UnimplementedOrReturnsCode, status, Code::OUT_OF_RANGE);
1687 }
1688 
1689 // The URI schemes that need to be tested are provided by the user via flags
1690 // (or, if none is supplied, all existing schemes are used). As a scheme can
1691 // become available after a shared object with a filesystem implementation is
1692 // loaded, we can only check for availability after all arguments have been
1693 // parsed.
1694 //
1695 // Furthermore, as `INSTANTIATE_TEST_SUITE_P` needs to be at global level and we
1696 // don't want to have a `std::vector<std::string>` at global level, we use a
1697 // static pointer to such a vector: we construct it via `SchemeVector()` below
1698 // and when tests are instantiated we process it using `GetSchemes()`.
SchemeVector()1699 static std::vector<std::string>* SchemeVector() {
1700   static std::vector<std::string>* schemes = new std::vector<std::string>;
1701   return schemes;
1702 }
1703 
1704 // `INSTANTIATE_TEST_SUITE_P` is called once for every `TEST_P`. However, we
1705 // only want to analyze the user provided schemes and those that are registered
1706 // only once. Hence, this function keeping another static pointer to a vector
1707 // which contains only the schemes under test.
1708 //
1709 // Without this additional step, when there are schemes available but the user
1710 // only requests schemes that don't exist, first instantiation of the test would
1711 // filter out all the user provided schemes (as they are not registered) but
1712 // subsequent instantiations would return all registered schemes (since the
1713 // vector with the user provided schemes is cleared).
GetSchemesFromUserOrEnv()1714 static std::vector<std::string>* GetSchemesFromUserOrEnv() {
1715   std::vector<std::string>* all_schemes = new std::vector<std::string>;
1716   tensorflow::Status status =
1717       tensorflow::Env::Default()->GetRegisteredFileSystemSchemes(all_schemes);
1718 
1719   if (status.ok()) {
1720     std::vector<std::string>* user_schemes = SchemeVector();
1721     if (!user_schemes->empty()) {
1722       auto is_requested_scheme = [user_schemes](const auto& scheme) {
1723         return std::find(user_schemes->begin(), user_schemes->end(), scheme) ==
1724                user_schemes->end();
1725       };
1726       auto end = std::remove_if(all_schemes->begin(), all_schemes->end(),
1727                                 is_requested_scheme);
1728       all_schemes->erase(end, all_schemes->end());
1729     }
1730   }
1731 
1732   return all_schemes;
1733 }
1734 
GetSchemes()1735 static std::vector<std::string> GetSchemes() {
1736   static std::vector<std::string>* schemes = GetSchemesFromUserOrEnv();
1737   return *schemes;
1738 }
1739 
1740 INSTANTIATE_TEST_SUITE_P(ModularFileSystem, ModularFileSystemTest,
1741                          ::testing::ValuesIn(GetSchemes()));
1742 
1743 // Loads a shared object implementing filesystem functionality.
LoadDSO(const std::string & dso)1744 static bool LoadDSO(const std::string& dso) {
1745   tensorflow::Status status = RegisterFilesystemPlugin(dso);
1746   if (!status.ok())
1747     VLOG(0) << "Filesystems from '" << dso
1748             << "' could not be registered: " << status;
1749   return status.ok();
1750 }
1751 
1752 // Tests whether a URI scheme results in a filesystem that is supported.
1753 //
1754 // As we need these URI schemes to instantiate the test suite when
1755 // `testing::InitGoogleTest` gets called, here we just store them to an
1756 // internal scheme registry. See `URISchemeRegister` above.
GetURIScheme(const std::string & scheme)1757 static bool GetURIScheme(const std::string& scheme) {
1758   tensorflow::SchemeVector()->push_back(scheme);
1759   return true;
1760 }
1761 
1762 // This function is used for cloud filesystem
1763 // `S3` and `GCS` require the `root_dir_` to have bucket name
1764 // `HDFS` requires the `root_dir` to have namenode
1765 // `root_dir_ = scheme + "://" cloud_path_ + root_dir_`
SetCloudPath(const std::string & cloud_path_)1766 static bool SetCloudPath(const std::string& cloud_path_) {
1767   ModularFileSystemTest::SetCloudPath(cloud_path_);
1768   return true;
1769 }
1770 
SetTmpDir(const std::string & tmp_dir_)1771 static bool SetTmpDir(const std::string& tmp_dir_) {
1772   ModularFileSystemTest::SetTmpDir(tmp_dir_);
1773   return true;
1774 }
1775 
1776 }  // namespace
1777 }  // namespace tensorflow
1778 
1779 // Due to the usages of flags for this manual test, we need a special `main` to
1780 // ensure our flags are parsed properly as `testing::InitGoogleTest` silently
1781 // ignores other flags. Furthermore, we need this to ensure that the DSO is
1782 // loaded exactly once, if provided.
main(int argc,char ** argv)1783 GTEST_API_ int main(int argc, char** argv) {
1784   const std::vector<tensorflow::Flag> flag_list = {
1785       tensorflow::Flag("dso", tensorflow::LoadDSO, "",
1786                        "Path to shared object to load"),
1787       tensorflow::Flag("scheme", tensorflow::GetURIScheme, "",
1788                        "URI scheme to test"),
1789       tensorflow::Flag("cloud_path", tensorflow::SetCloudPath, "",
1790                        "Path for cloud filesystem (namenode for hdfs, "
1791                        "bucketname for s3/gcs)"),
1792       tensorflow::Flag("tmp_dir", tensorflow::SetTmpDir, "",
1793                        "Temporary directory to store test data.")};
1794   if (!tensorflow::Flags::Parse(&argc, argv, flag_list)) {
1795     std::cout << tensorflow::Flags::Usage(argv[0], flag_list);
1796     return -1;
1797   }
1798 
1799   tensorflow::testing::InstallStacktraceHandler();
1800   tensorflow::ModularFileSystemTest::InitializeTestRNG();
1801   testing::InitGoogleTest(&argc, argv);
1802   return RUN_ALL_TESTS();
1803 }
1804