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