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