16 #include "tensorflow_serving/sources/storage_path/file_system_storage_path_source.h"
23 #include <gmock/gmock.h>
24 #include <gtest/gtest.h>
25 #include "tensorflow/core/lib/core/status_test_util.h"
26 #include "tensorflow/core/lib/core/stringpiece.h"
27 #include "tensorflow/core/lib/io/path.h"
28 #include "tensorflow/core/lib/strings/str_util.h"
29 #include "tensorflow/core/lib/strings/strcat.h"
30 #include "tensorflow/core/lib/strings/stringprintf.h"
31 #include "tensorflow/core/platform/env.h"
32 #include "tensorflow/core/platform/test.h"
33 #include "tensorflow_serving/config/file_system_storage_path_source.pb.h"
34 #include "tensorflow_serving/core/servable_data.h"
35 #include "tensorflow_serving/core/target.h"
36 #include "tensorflow_serving/core/test_util/mock_storage_path_target.h"
37 #include "tensorflow_serving/test_util/test_util.h"
39 using ::testing::AnyOf;
40 using ::testing::ElementsAre;
42 using ::testing::IsEmpty;
43 using ::testing::StrictMock;
45 namespace tensorflow {
56 Status PollFileSystemAndInvokeCallback() {
57 return source_->PollFileSystemAndInvokeCallback();
60 void SetAspiredVersionsCallbackNotifier(std::function<
void()> fn) {
61 source_->SetAspiredVersionsCallbackNotifier(fn);
74 TEST(FileSystemStoragePathSourceTest, NoVersionsAtStartup) {
75 for (
bool base_path_exists : {
false,
true}) {
76 const string base_path = io::JoinPath(
78 strings::StrCat(
"NoVersionsAtStartup",
79 base_path_exists ?
"" :
"_nonexistent_base_path"));
80 if (base_path_exists) {
81 TF_ASSERT_OK(Env::Default()->CreateDir(base_path));
82 TF_ASSERT_OK(Env::Default()->CreateDir(
83 io::JoinPath(base_path,
"non_numerical_child")));
86 for (
bool fail_if_zero_versions_at_startup : {
false,
true}) {
87 auto config = test_util::CreateProto<FileSystemStoragePathSourceConfig>(
88 strings::Printf(
"servables: {"
89 " servable_name: 'test_servable_name' "
92 "fail_if_zero_versions_at_startup: %s "
94 "file_system_poll_wait_seconds: -1 ",
96 fail_if_zero_versions_at_startup ?
"true" :
"false"));
97 std::unique_ptr<FileSystemStoragePathSource> source;
98 bool success = FileSystemStoragePathSource::Create(config, &source).ok();
99 EXPECT_EQ(!fail_if_zero_versions_at_startup, success);
101 std::unique_ptr<test_util::MockStoragePathTarget> target(
102 new StrictMock<test_util::MockStoragePathTarget>);
103 ConnectSourceToTarget(source.get(), target.get());
104 if (base_path_exists) {
107 SetAspiredVersions(Eq(
"test_servable_name"), IsEmpty()));
109 internal::FileSystemStoragePathSourceTestAccess(source.get())
110 .PollFileSystemAndInvokeCallback());
114 internal::FileSystemStoragePathSourceTestAccess(source.get())
115 .PollFileSystemAndInvokeCallback()
123 TEST(FileSystemStoragePathSourceTest, FilesAppearAfterStartup) {
124 const string base_path =
125 io::JoinPath(testing::TmpDir(),
"FilesAppearAfterStartup");
127 auto config = test_util::CreateProto<FileSystemStoragePathSourceConfig>(
128 strings::Printf(
"servables: {"
129 " servable_name: 'test_servable_name' "
132 "fail_if_zero_versions_at_startup: false "
134 "file_system_poll_wait_seconds: -1 ",
136 std::unique_ptr<FileSystemStoragePathSource> source;
137 TF_ASSERT_OK(FileSystemStoragePathSource::Create(config, &source));
138 std::unique_ptr<test_util::MockStoragePathTarget> target(
139 new StrictMock<test_util::MockStoragePathTarget>);
140 ConnectSourceToTarget(source.get(), target.get());
143 EXPECT_FALSE(internal::FileSystemStoragePathSourceTestAccess(source.get())
144 .PollFileSystemAndInvokeCallback()
148 TF_ASSERT_OK(Env::Default()->CreateDir(base_path));
149 TF_ASSERT_OK(Env::Default()->CreateDir(io::JoinPath(base_path,
"3")));
150 EXPECT_CALL(*target, SetAspiredVersions(Eq(
"test_servable_name"),
151 ElementsAre(ServableData<StoragePath>(
152 {
"test_servable_name", 3},
153 io::JoinPath(base_path,
"3")))));
154 TF_ASSERT_OK(internal::FileSystemStoragePathSourceTestAccess(source.get())
155 .PollFileSystemAndInvokeCallback());
158 TEST(FileSystemStoragePathSourceTest, MultipleVersions) {
159 const string base_path = io::JoinPath(testing::TmpDir(),
"MultipleVersions");
160 TF_ASSERT_OK(Env::Default()->CreateDir(base_path));
161 TF_ASSERT_OK(Env::Default()->CreateDir(
162 io::JoinPath(base_path,
"non_numerical_child")));
163 TF_ASSERT_OK(Env::Default()->CreateDir(io::JoinPath(base_path,
"42")));
164 TF_ASSERT_OK(Env::Default()->CreateDir(io::JoinPath(base_path,
"17")));
166 auto config = test_util::CreateProto<FileSystemStoragePathSourceConfig>(
167 strings::Printf(
"servables: {"
168 " servable_name: 'test_servable_name' "
172 "file_system_poll_wait_seconds: -1 ",
174 std::unique_ptr<FileSystemStoragePathSource> source;
175 TF_ASSERT_OK(FileSystemStoragePathSource::Create(config, &source));
176 std::unique_ptr<test_util::MockStoragePathTarget> target(
177 new StrictMock<test_util::MockStoragePathTarget>);
178 ConnectSourceToTarget(source.get(), target.get());
180 EXPECT_CALL(*target, SetAspiredVersions(Eq(
"test_servable_name"),
181 ElementsAre(ServableData<StoragePath>(
182 {
"test_servable_name", 42},
183 io::JoinPath(base_path,
"42")))));
184 TF_ASSERT_OK(internal::FileSystemStoragePathSourceTestAccess(source.get())
185 .PollFileSystemAndInvokeCallback());
188 TEST(FileSystemStoragePathSourceTest, MultipleVersionsAtTheSameTime) {
189 const string base_path =
190 io::JoinPath(testing::TmpDir(),
"MultipleVersionsAtTheSameTime");
191 TF_ASSERT_OK(Env::Default()->CreateDir(base_path));
192 TF_ASSERT_OK(Env::Default()->CreateDir(
193 io::JoinPath(base_path,
"non_numerical_child")));
194 TF_ASSERT_OK(Env::Default()->CreateDir(io::JoinPath(base_path,
"42")));
195 TF_ASSERT_OK(Env::Default()->CreateDir(io::JoinPath(base_path,
"17")));
197 auto config = test_util::CreateProto<FileSystemStoragePathSourceConfig>(
198 strings::Printf(
"servables: { "
199 " servable_version_policy { "
203 " servable_name: 'test_servable_name' "
207 "file_system_poll_wait_seconds: -1 ",
209 std::unique_ptr<FileSystemStoragePathSource> source;
210 TF_ASSERT_OK(FileSystemStoragePathSource::Create(config, &source));
211 std::unique_ptr<test_util::MockStoragePathTarget> target(
212 new StrictMock<test_util::MockStoragePathTarget>);
213 ConnectSourceToTarget(source.get(), target.get());
218 Eq(
"test_servable_name"),
220 ServableData<StoragePath>({
"test_servable_name", 17},
221 io::JoinPath(base_path,
"17")),
222 ServableData<StoragePath>({
"test_servable_name", 42},
223 io::JoinPath(base_path,
"42")))));
225 TF_ASSERT_OK(internal::FileSystemStoragePathSourceTestAccess(source.get())
226 .PollFileSystemAndInvokeCallback());
229 TEST(FileSystemStoragePathSourceTest, NLatestVersions) {
230 const string base_path =
231 io::JoinPath(testing::TmpDir(),
"NLatestVersionsAtTheSameTime");
232 TF_ASSERT_OK(Env::Default()->CreateDir(base_path));
233 for (
const string& version :
234 {
"non_numerical_child",
"42",
"33",
"30",
"21",
"17"}) {
235 TF_ASSERT_OK(Env::Default()->CreateDir(io::JoinPath(base_path, version)));
238 const FileSystemStoragePathSourceConfig config =
239 test_util::CreateProto<FileSystemStoragePathSourceConfig>(
240 strings::Printf(
"servables: { "
241 " servable_version_policy { "
246 " servable_name: 'test_servable_name' "
250 "file_system_poll_wait_seconds: -1 ",
252 std::unique_ptr<FileSystemStoragePathSource> source;
253 TF_ASSERT_OK(FileSystemStoragePathSource::Create(config, &source));
254 std::unique_ptr<test_util::MockStoragePathTarget> target(
255 new StrictMock<test_util::MockStoragePathTarget>);
256 ConnectSourceToTarget(source.get(), target.get());
261 Eq(
"test_servable_name"),
263 ServableData<StoragePath>({
"test_servable_name", 42},
264 io::JoinPath(base_path,
"42")),
265 ServableData<StoragePath>({
"test_servable_name", 33},
266 io::JoinPath(base_path,
"33")),
267 ServableData<StoragePath>({
"test_servable_name", 30},
268 io::JoinPath(base_path,
"30")))));
270 TF_ASSERT_OK(internal::FileSystemStoragePathSourceTestAccess(source.get())
271 .PollFileSystemAndInvokeCallback());
274 TEST(FileSystemStoragePathSourceTest, SpecificVersions) {
275 const string base_path = io::JoinPath(testing::TmpDir(),
"SpecificVersions");
276 TF_ASSERT_OK(Env::Default()->CreateDir(base_path));
277 for (
const string& version :
278 {
"non_numerical_child",
"42",
"33",
"30",
"21",
"17"}) {
279 TF_ASSERT_OK(Env::Default()->CreateDir(io::JoinPath(base_path, version)));
282 const FileSystemStoragePathSourceConfig config =
283 test_util::CreateProto<FileSystemStoragePathSourceConfig>(
284 strings::Printf(
"servables: { "
285 " servable_version_policy { "
291 " servable_name: 'test_servable_name' "
295 "file_system_poll_wait_seconds: -1 ",
297 std::unique_ptr<FileSystemStoragePathSource> source;
298 TF_ASSERT_OK(FileSystemStoragePathSource::Create(config, &source));
299 std::unique_ptr<test_util::MockStoragePathTarget> target(
300 new StrictMock<test_util::MockStoragePathTarget>);
301 ConnectSourceToTarget(source.get(), target.get());
306 Eq(
"test_servable_name"),
308 ServableData<StoragePath>({
"test_servable_name", 17},
309 io::JoinPath(base_path,
"17")),
310 ServableData<StoragePath>({
"test_servable_name", 30},
311 io::JoinPath(base_path,
"30")))));
313 TF_ASSERT_OK(internal::FileSystemStoragePathSourceTestAccess(source.get())
314 .PollFileSystemAndInvokeCallback());
320 TEST(FileSystemStoragePathSourceTest, SpecificVersionsLeadingZeros) {
321 const string base_path =
322 io::JoinPath(testing::TmpDir(),
"SpecificVersionsLeadingZeros");
323 TF_ASSERT_OK(Env::Default()->CreateDir(base_path));
324 for (
const string& version :
325 {
"non_numerical_child",
"42",
"33",
"30",
"21",
"00017"}) {
326 TF_ASSERT_OK(Env::Default()->CreateDir(io::JoinPath(base_path, version)));
329 const FileSystemStoragePathSourceConfig config =
330 test_util::CreateProto<FileSystemStoragePathSourceConfig>(
331 strings::Printf(
"servables: { "
332 " servable_version_policy { "
338 " servable_name: 'test_servable_name' "
342 "file_system_poll_wait_seconds: -1 ",
344 std::unique_ptr<FileSystemStoragePathSource> source;
345 TF_ASSERT_OK(FileSystemStoragePathSource::Create(config, &source));
346 std::unique_ptr<test_util::MockStoragePathTarget> target(
347 new StrictMock<test_util::MockStoragePathTarget>);
348 ConnectSourceToTarget(source.get(), target.get());
353 Eq(
"test_servable_name"),
355 ServableData<StoragePath>({
"test_servable_name", 17},
356 io::JoinPath(base_path,
"00017")),
357 ServableData<StoragePath>({
"test_servable_name", 30},
358 io::JoinPath(base_path,
"30")))));
360 TF_ASSERT_OK(internal::FileSystemStoragePathSourceTestAccess(source.get())
361 .PollFileSystemAndInvokeCallback());
364 TEST(FileSystemStoragePathSourceTest, SpecificVersionsEmpty) {
365 const string base_path =
366 io::JoinPath(testing::TmpDir(),
"SpecificVersionsEmpty");
367 TF_ASSERT_OK(Env::Default()->CreateDir(base_path));
368 for (
const string& version :
369 {
"non_numerical_child",
"42",
"33",
"30",
"21",
"17"}) {
370 TF_ASSERT_OK(Env::Default()->CreateDir(io::JoinPath(base_path, version)));
373 const FileSystemStoragePathSourceConfig config =
374 test_util::CreateProto<FileSystemStoragePathSourceConfig>(
375 strings::Printf(
"servables: { "
376 " servable_version_policy { "
380 " servable_name: 'test_servable_name' "
384 "file_system_poll_wait_seconds: -1 ",
386 std::unique_ptr<FileSystemStoragePathSource> source;
387 TF_ASSERT_OK(FileSystemStoragePathSource::Create(config, &source));
388 std::unique_ptr<test_util::MockStoragePathTarget> target(
389 new StrictMock<test_util::MockStoragePathTarget>);
390 ConnectSourceToTarget(source.get(), target.get());
394 EXPECT_CALL(*target, SetAspiredVersions(Eq(
"test_servable_name"), IsEmpty()));
396 TF_ASSERT_OK(internal::FileSystemStoragePathSourceTestAccess(source.get())
397 .PollFileSystemAndInvokeCallback());
400 TEST(FileSystemStoragePathSourceTest, DefaultVersionPolicy) {
403 const string base_path =
404 io::JoinPath(testing::TmpDir(),
"DefaultVersionPolicy");
405 TF_ASSERT_OK(Env::Default()->CreateDir(base_path));
406 for (
const string& version : {
"non_numerical_child",
"42",
"33",
"30"}) {
407 TF_ASSERT_OK(Env::Default()->CreateDir(io::JoinPath(base_path, version)));
410 const FileSystemStoragePathSourceConfig config =
411 test_util::CreateProto<FileSystemStoragePathSourceConfig>(
412 strings::Printf(
"servables: { "
413 " servable_name: 'test_servable_name' "
417 "file_system_poll_wait_seconds: -1 ",
419 std::unique_ptr<FileSystemStoragePathSource> source;
420 TF_ASSERT_OK(FileSystemStoragePathSource::Create(config, &source));
421 std::unique_ptr<test_util::MockStoragePathTarget> target(
422 new StrictMock<test_util::MockStoragePathTarget>);
423 ConnectSourceToTarget(source.get(), target.get());
425 EXPECT_CALL(*target, SetAspiredVersions(Eq(
"test_servable_name"),
426 ElementsAre(ServableData<StoragePath>(
427 {
"test_servable_name", 42},
428 io::JoinPath(base_path,
"42")))));
430 TF_ASSERT_OK(internal::FileSystemStoragePathSourceTestAccess(source.get())
431 .PollFileSystemAndInvokeCallback());
434 TEST(FileSystemStoragePathSourceTest, DefaultNumLatestVersions) {
437 const string base_path =
438 io::JoinPath(testing::TmpDir(),
"DefaultNumLatestVersions");
439 TF_ASSERT_OK(Env::Default()->CreateDir(base_path));
440 for (
const string& version : {
"non_numerical_child",
"42",
"33",
"30"}) {
441 TF_ASSERT_OK(Env::Default()->CreateDir(io::JoinPath(base_path, version)));
444 const FileSystemStoragePathSourceConfig config =
445 test_util::CreateProto<FileSystemStoragePathSourceConfig>(
446 strings::Printf(
"servables: { "
447 " servable_version_policy { "
451 " servable_name: 'test_servable_name' "
455 "file_system_poll_wait_seconds: -1 ",
457 std::unique_ptr<FileSystemStoragePathSource> source;
458 TF_ASSERT_OK(FileSystemStoragePathSource::Create(config, &source));
459 std::unique_ptr<test_util::MockStoragePathTarget> target(
460 new StrictMock<test_util::MockStoragePathTarget>);
461 ConnectSourceToTarget(source.get(), target.get());
463 EXPECT_CALL(*target, SetAspiredVersions(Eq(
"test_servable_name"),
464 ElementsAre(ServableData<StoragePath>(
465 {
"test_servable_name", 42},
466 io::JoinPath(base_path,
"42")))));
468 TF_ASSERT_OK(internal::FileSystemStoragePathSourceTestAccess(source.get())
469 .PollFileSystemAndInvokeCallback());
472 TEST(FileSystemStoragePathSourceTest, MultipleServables) {
473 FileSystemStoragePathSourceConfig config;
474 config.set_fail_if_zero_versions_at_startup(
false);
475 config.set_file_system_poll_wait_seconds(-1);
478 const string base_path_0 =
479 io::JoinPath(testing::TmpDir(),
"MultipleServables_0");
480 TF_ASSERT_OK(Env::Default()->CreateDir(base_path_0));
481 TF_ASSERT_OK(Env::Default()->CreateDir(io::JoinPath(base_path_0,
"1")));
482 TF_ASSERT_OK(Env::Default()->CreateDir(io::JoinPath(base_path_0,
"3")));
483 auto* servable_0 = config.add_servables();
484 servable_0->set_servable_name(
"servable_0");
485 servable_0->set_base_path(base_path_0);
488 const string base_path_1 =
489 io::JoinPath(testing::TmpDir(),
"MultipleServables_1");
490 TF_ASSERT_OK(Env::Default()->CreateDir(base_path_1));
491 TF_ASSERT_OK(Env::Default()->CreateDir(io::JoinPath(base_path_1,
"42")));
492 auto* servable_1 = config.add_servables();
493 servable_1->set_servable_name(
"servable_1");
494 servable_1->set_base_path(base_path_1);
497 const string base_path_2 =
498 io::JoinPath(testing::TmpDir(),
"MultipleServables_2");
499 TF_ASSERT_OK(Env::Default()->CreateDir(base_path_2));
500 auto* servable_2 = config.add_servables();
501 servable_2->set_servable_name(
"servable_2");
502 servable_2->set_base_path(base_path_2);
505 std::unique_ptr<FileSystemStoragePathSource> source;
506 TF_ASSERT_OK(FileSystemStoragePathSource::Create(config, &source));
507 std::unique_ptr<test_util::MockStoragePathTarget> target(
508 new StrictMock<test_util::MockStoragePathTarget>);
509 ConnectSourceToTarget(source.get(), target.get());
515 ElementsAre(ServableData<StoragePath>(
516 {
"servable_0", 3}, io::JoinPath(base_path_0,
"3")))));
520 ElementsAre(ServableData<StoragePath>(
521 {
"servable_1", 42}, io::JoinPath(base_path_1,
"42")))));
522 EXPECT_CALL(*target, SetAspiredVersions(Eq(
"servable_2"), IsEmpty()));
523 TF_ASSERT_OK(internal::FileSystemStoragePathSourceTestAccess(source.get())
524 .PollFileSystemAndInvokeCallback());
527 TEST(FileSystemStoragePathSourceTest, ChangeSetOfServables) {
528 FileSystemStoragePathSourceConfig config;
529 config.set_fail_if_zero_versions_at_startup(
false);
530 config.set_file_system_poll_wait_seconds(-1);
533 const string base_path_prefix =
534 io::JoinPath(testing::TmpDir(),
"ChangeSetOfServables_");
535 for (
int i = 0; i <= 2; ++i) {
536 const string base_path = strings::StrCat(base_path_prefix, i);
537 TF_ASSERT_OK(Env::Default()->CreateDir(base_path));
538 TF_ASSERT_OK(Env::Default()->CreateDir(io::JoinPath(base_path,
"0")));
542 for (
int i : {0, 1}) {
543 auto* servable = config.add_servables();
544 servable->set_servable_name(strings::StrCat(
"servable_", i));
545 servable->set_base_path(strings::StrCat(base_path_prefix, i));
547 std::unique_ptr<FileSystemStoragePathSource> source;
548 TF_ASSERT_OK(FileSystemStoragePathSource::Create(config, &source));
549 std::unique_ptr<test_util::MockStoragePathTarget> target(
550 new StrictMock<test_util::MockStoragePathTarget>);
551 ConnectSourceToTarget(source.get(), target.get());
552 for (
int i : {0, 1}) {
556 Eq(strings::StrCat(
"servable_", i)),
557 ElementsAre(ServableData<StoragePath>(
558 {strings::StrCat(
"servable_", i), 0},
559 io::JoinPath(strings::StrCat(base_path_prefix, i),
"0")))));
561 TF_ASSERT_OK(internal::FileSystemStoragePathSourceTestAccess(source.get())
562 .PollFileSystemAndInvokeCallback());
565 config.clear_servables();
566 for (
int i : {1, 2}) {
567 auto* servable = config.add_servables();
568 servable->set_servable_name(strings::StrCat(
"servable_", i));
569 servable->set_base_path(strings::StrCat(base_path_prefix, i));
573 EXPECT_CALL(*target, SetAspiredVersions(Eq(
"servable_0"), IsEmpty()));
578 for (
int i : {1, 2}) {
582 Eq(strings::StrCat(
"servable_", i)),
583 ElementsAre(ServableData<StoragePath>(
584 {strings::StrCat(
"servable_", i), 0},
585 io::JoinPath(strings::StrCat(base_path_prefix, i),
"0")))));
587 TF_ASSERT_OK(source->UpdateConfig(config));
588 TF_ASSERT_OK(internal::FileSystemStoragePathSourceTestAccess(source.get())
589 .PollFileSystemAndInvokeCallback());
592 TEST(FileSystemStoragePathSourceTest, ChangeVersionPolicy) {
595 const string base_path_prefix =
596 io::JoinPath(testing::TmpDir(),
"ChangeVersionPolicy_");
597 TF_ASSERT_OK(Env::Default()->CreateDir(base_path_prefix));
598 for (
const string& version : {
"1",
"02",
"3",
"5",
"8",
"13"}) {
600 Env::Default()->CreateDir(io::JoinPath(base_path_prefix, version)));
603 FileSystemStoragePathSourceConfig config =
604 test_util::CreateProto<FileSystemStoragePathSourceConfig>(
605 strings::Printf(
"servables: { "
606 " servable_version_policy { "
611 " servable_name: 'test_servable_name' "
615 "file_system_poll_wait_seconds: -1 ",
616 base_path_prefix.c_str()));
617 std::unique_ptr<FileSystemStoragePathSource> source;
618 TF_ASSERT_OK(FileSystemStoragePathSource::Create(config, &source));
619 std::unique_ptr<test_util::MockStoragePathTarget> target(
620 new StrictMock<test_util::MockStoragePathTarget>);
621 ConnectSourceToTarget(source.get(), target.get());
626 Eq(
"test_servable_name"),
628 ServableData<StoragePath>({
"test_servable_name", 13},
629 io::JoinPath(base_path_prefix,
"13")),
630 ServableData<StoragePath>({
"test_servable_name", 8},
631 io::JoinPath(base_path_prefix,
"8")))));
633 TF_ASSERT_OK(internal::FileSystemStoragePathSourceTestAccess(source.get())
634 .PollFileSystemAndInvokeCallback());
637 config = test_util::CreateProto<FileSystemStoragePathSourceConfig>(
638 strings::Printf(
"servables: { "
639 " servable_version_policy { "
645 " servable_name: 'test_servable_name' "
649 "file_system_poll_wait_seconds: -1 ",
650 base_path_prefix.c_str()));
655 Eq(
"test_servable_name"),
657 ServableData<StoragePath>({
"test_servable_name", 2},
658 io::JoinPath(base_path_prefix,
"02")),
659 ServableData<StoragePath>({
"test_servable_name", 5},
660 io::JoinPath(base_path_prefix,
"5")))));
662 TF_ASSERT_OK(source->UpdateConfig(config));
663 TF_ASSERT_OK(internal::FileSystemStoragePathSourceTestAccess(source.get())
664 .PollFileSystemAndInvokeCallback());
667 TEST(FileSystemStoragePathSourceTest, AttemptToChangePollingPeriod) {
668 FileSystemStoragePathSourceConfig config;
669 config.set_file_system_poll_wait_seconds(1);
670 std::unique_ptr<FileSystemStoragePathSource> source;
671 TF_ASSERT_OK(FileSystemStoragePathSource::Create(config, &source));
672 std::unique_ptr<test_util::MockStoragePathTarget> target(
673 new StrictMock<test_util::MockStoragePathTarget>);
674 ConnectSourceToTarget(source.get(), target.get());
676 FileSystemStoragePathSourceConfig new_config = config;
677 new_config.set_file_system_poll_wait_seconds(5);
678 EXPECT_FALSE(source->UpdateConfig(new_config).ok());
681 TEST(FileSystemStoragePathSourceTest, ParseTimestampedVersion) {
682 static_assert(
static_cast<int32
>(20170111173521LL) == 944751505,
683 "Version overflows if cast to int32.");
684 const string base_path =
685 io::JoinPath(testing::TmpDir(),
"ParseTimestampedVersion");
686 TF_ASSERT_OK(Env::Default()->CreateDir(base_path));
688 Env::Default()->CreateDir(io::JoinPath(base_path,
"20170111173521")));
689 auto config = test_util::CreateProto<FileSystemStoragePathSourceConfig>(
690 strings::Printf(
"servables: { "
691 " servable_version_policy { "
695 " servable_name: 'test_servable_name' "
699 "file_system_poll_wait_seconds: -1 ",
701 std::unique_ptr<FileSystemStoragePathSource> source;
702 TF_ASSERT_OK(FileSystemStoragePathSource::Create(config, &source));
703 std::unique_ptr<test_util::MockStoragePathTarget> target(
704 new StrictMock<test_util::MockStoragePathTarget>);
705 ConnectSourceToTarget(source.get(), target.get());
707 EXPECT_CALL(*target, SetAspiredVersions(
708 Eq(
"test_servable_name"),
709 ElementsAre(ServableData<StoragePath>(
710 {
"test_servable_name", 20170111173521LL},
711 io::JoinPath(base_path,
"20170111173521")))));
713 TF_ASSERT_OK(internal::FileSystemStoragePathSourceTestAccess(source.get())
714 .PollFileSystemAndInvokeCallback());
717 TEST(FileSystemStoragePathSourceTest, ServableVersionDirRenamed) {
719 const string base_path_prefix =
720 io::JoinPath(testing::TmpDir(),
"ServableVersionDirRenamed_");
721 TF_ASSERT_OK(Env::Default()->CreateDir(base_path_prefix));
722 for (
const string& version : {
"1",
"2",
"3",
"5",
"8"}) {
724 Env::Default()->CreateDir(io::JoinPath(base_path_prefix, version)));
727 auto config = test_util::CreateProto<FileSystemStoragePathSourceConfig>(
728 strings::Printf(
"servables: { "
729 " servable_version_policy { "
733 " servable_name: 'test_servable_name' "
737 "file_system_poll_wait_seconds: -1 ",
738 base_path_prefix.c_str()));
739 std::unique_ptr<FileSystemStoragePathSource> source;
740 TF_ASSERT_OK(FileSystemStoragePathSource::Create(config, &source));
741 std::unique_ptr<test_util::MockStoragePathTarget> target(
742 new StrictMock<test_util::MockStoragePathTarget>);
743 ConnectSourceToTarget(source.get(), target.get());
748 Eq(
"test_servable_name"),
750 ServableData<StoragePath>({
"test_servable_name", 1},
751 io::JoinPath(base_path_prefix,
"1")),
752 ServableData<StoragePath>({
"test_servable_name", 2},
753 io::JoinPath(base_path_prefix,
"2")),
754 ServableData<StoragePath>({
"test_servable_name", 3},
755 io::JoinPath(base_path_prefix,
"3")),
756 ServableData<StoragePath>({
"test_servable_name", 5},
757 io::JoinPath(base_path_prefix,
"5")),
758 ServableData<StoragePath>({
"test_servable_name", 8},
759 io::JoinPath(base_path_prefix,
"8")))));
761 TF_ASSERT_OK(internal::FileSystemStoragePathSourceTestAccess(source.get())
762 .PollFileSystemAndInvokeCallback());
767 Env::Default()->RenameFile(io::JoinPath(base_path_prefix,
"2"),
768 io::JoinPath(base_path_prefix,
"2.denied")));
770 Env::Default()->RenameFile(io::JoinPath(base_path_prefix,
"5"),
771 io::JoinPath(base_path_prefix,
"5.denied")));
772 TF_ASSERT_OK(Env::Default()->DeleteDir(io::JoinPath(base_path_prefix,
"8")));
777 Eq(
"test_servable_name"),
779 ServableData<StoragePath>({
"test_servable_name", 1},
780 io::JoinPath(base_path_prefix,
"1")),
781 ServableData<StoragePath>({
"test_servable_name", 3},
782 io::JoinPath(base_path_prefix,
"3")))));
784 TF_ASSERT_OK(source->UpdateConfig(config));
785 TF_ASSERT_OK(internal::FileSystemStoragePathSourceTestAccess(source.get())
786 .PollFileSystemAndInvokeCallback());
789 TEST(FileSystemStoragePathSourceTest, DuplicateVersions) {
790 const string base_path = io::JoinPath(testing::TmpDir(),
"DuplicateVersions");
791 TF_ASSERT_OK(Env::Default()->CreateDir(base_path));
792 TF_ASSERT_OK(Env::Default()->CreateDir(
793 io::JoinPath(base_path,
"non_numerical_child")));
794 for (
const string& version : {
"0001",
"001",
"00001"}) {
795 TF_ASSERT_OK(Env::Default()->CreateDir(io::JoinPath(base_path, version)));
798 auto config = test_util::CreateProto<FileSystemStoragePathSourceConfig>(
799 strings::Printf(
"servables: {"
800 " servable_name: 'test_servable_name' "
804 "file_system_poll_wait_seconds: -1 ",
806 std::unique_ptr<FileSystemStoragePathSource> source;
807 TF_ASSERT_OK(FileSystemStoragePathSource::Create(config, &source));
808 std::unique_ptr<test_util::MockStoragePathTarget> target(
809 new StrictMock<test_util::MockStoragePathTarget>);
810 ConnectSourceToTarget(source.get(), target.get());
815 Eq(
"test_servable_name"),
817 ElementsAre(ServableData<StoragePath>(
818 {
"test_servable_name", 1}, io::JoinPath(base_path,
"001"))),
819 ElementsAre(ServableData<StoragePath>(
820 {
"test_servable_name", 1}, io::JoinPath(base_path,
"0001"))),
821 ElementsAre(ServableData<StoragePath>(
822 {
"test_servable_name", 1},
823 io::JoinPath(base_path,
"00001"))))));
824 TF_ASSERT_OK(internal::FileSystemStoragePathSourceTestAccess(source.get())
825 .PollFileSystemAndInvokeCallback());
828 TEST(FileSystemStoragePathSourceTest, LastVersionNotRemoved) {
829 const string base_path =
830 io::JoinPath(testing::TmpDir(),
"LastVersionNotRemoved");
831 TF_ASSERT_OK(Env::Default()->CreateDir(base_path));
833 for (
bool servable_versions_always_present : {
false,
true}) {
835 Env::Default()->RecursivelyCreateDir(io::JoinPath(base_path,
"42")));
837 auto config = test_util::CreateProto<FileSystemStoragePathSourceConfig>(
838 strings::Printf(
"servables: {"
839 " servable_name: 'test_servable_name' "
842 "servable_versions_always_present: %s "
844 "file_system_poll_wait_seconds: -1 ",
846 servable_versions_always_present ?
"true" :
"false"));
847 std::unique_ptr<FileSystemStoragePathSource> source;
848 TF_ASSERT_OK(FileSystemStoragePathSource::Create(config, &source));
849 std::unique_ptr<test_util::MockStoragePathTarget> target(
850 new StrictMock<test_util::MockStoragePathTarget>);
851 ConnectSourceToTarget(source.get(), target.get());
854 SetAspiredVersions(Eq(
"test_servable_name"),
855 ElementsAre(ServableData<StoragePath>(
856 {
"test_servable_name", 42},
857 io::JoinPath(base_path,
"42")))));
858 TF_ASSERT_OK(internal::FileSystemStoragePathSourceTestAccess(source.get())
859 .PollFileSystemAndInvokeCallback());
861 TF_ASSERT_OK(Env::Default()->DeleteDir(io::JoinPath(base_path,
"42")));
863 if (servable_versions_always_present) {
865 SetAspiredVersions(Eq(
"test_servable_name"), IsEmpty()))
869 SetAspiredVersions(Eq(
"test_servable_name"), IsEmpty()));
872 TF_ASSERT_OK(internal::FileSystemStoragePathSourceTestAccess(source.get())
873 .PollFileSystemAndInvokeCallback());
877 TEST(FileSystemStoragePathSourceTest, PollFilesystemOnlyOnce) {
878 const string base_path = io::JoinPath(testing::TmpDir(),
"OneShot");
879 auto config = test_util::CreateProto<FileSystemStoragePathSourceConfig>(
880 strings::Printf(
"servables: {"
881 " servable_name: 'test_servable_name' "
884 "fail_if_zero_versions_at_startup: false "
886 "file_system_poll_wait_seconds: 0 ",
888 std::unique_ptr<FileSystemStoragePathSource> source;
889 TF_ASSERT_OK(FileSystemStoragePathSource::Create(config, &source));
890 internal::FileSystemStoragePathSourceTestAccess source_test(source.get());
891 std::atomic<int> notify_count(0);
892 source_test.SetAspiredVersionsCallbackNotifier([&]() { notify_count++; });
893 std::unique_ptr<test_util::MockStoragePathTarget> target(
894 new StrictMock<test_util::MockStoragePathTarget>);
896 TF_ASSERT_OK(Env::Default()->CreateDir(base_path));
897 TF_ASSERT_OK(Env::Default()->CreateDir(io::JoinPath(base_path,
"3")));
898 EXPECT_CALL(*target, SetAspiredVersions(Eq(
"test_servable_name"),
899 ElementsAre(ServableData<StoragePath>(
900 {
"test_servable_name", 3},
901 io::JoinPath(base_path,
"3")))));
902 EXPECT_EQ(notify_count.load(), 0);
903 ConnectSourceToTarget(source.get(), target.get());
904 while (notify_count == 0) {
905 Env::Default()->SleepForMicroseconds(1000 );
907 EXPECT_EQ(notify_count.load(), 1);
910 TF_ASSERT_OK(Env::Default()->CreateDir(io::JoinPath(base_path,
"4")));
911 Env::Default()->SleepForMicroseconds(1 * 1000 * 1000 );
912 EXPECT_EQ(notify_count.load(), 1);