@@ -177,6 +177,7 @@ class CleanInteTest : public testing::Test {
177177 for (const auto & file_path : cleaned_paths) {
178178 file_names.insert (PathUtil::GetName (file_path));
179179 }
180+ EXPECT_EQ (file_names, expected_names);
180181 return file_names == expected_names;
181182 }
182183
@@ -929,19 +930,33 @@ TEST_F(CleanInteTest, TestOrphanFilesCleanWithIOException) {
929930 OrphanFilesCleaner::Create (std::move (clean_context)));
930931
931932 io_hook->Reset (i, IOHook::Mode::RETURN_ERROR );
932- auto clean_result = cleaner->Clean ();
933+ auto clean_result = cleaner->Clean (); // first clean
933934 io_hook->Clear ();
934935 if (HitIOHook (clean_result.status (), i)) {
935936 scanned_all_io_hook = false ;
936- clean_result = cleaner->Clean ();
937+ clean_result = cleaner->Clean (); // second clean
937938 }
938939 ASSERT_OK (clean_result);
939- ASSERT_TRUE (CheckEqual (clean_result.value (), {" data-orphan2.orc" , " manifest-orphan" ,
940- " .manifest-orphan.uuid.tmp" }));
941- // because clean is quietly delete, if touch IO exception in Delete(), Clean() will
942- // return OK, but files may not be deleted, so need to call Clean() again.
943- // If the next call Clean() return empty, it means all files are deleted.
944- clean_result = cleaner->Clean ();
940+
941+ std::set<std::string> expected_orphans = {" data-orphan2.orc" , " manifest-orphan" ,
942+ " .manifest-orphan.uuid.tmp" };
943+ // In the first clean, IO errors may already have been triggered in
944+ // TryBestListingDirs or MinimalTryBestListingDirs. Those errors are handled quietly,
945+ // which means the cleaner may build an incomplete view of the full file set.
946+ // As a result, the subsequent delete phase may only run on part of the expected orphan
947+ // files. So here we only require the cleaned result to be a subset of
948+ // expected_orphans instead of an exact match.
949+ std::set<std::string> cleaned_file_names;
950+ for (const auto & file_path : clean_result.value ()) {
951+ cleaned_file_names.insert (PathUtil::GetName (file_path));
952+ }
953+ ASSERT_TRUE (std::includes (expected_orphans.begin (), expected_orphans.end (),
954+ cleaned_file_names.begin (), cleaned_file_names.end ()));
955+ // because clean is quietly delete, if touch IO exception in Delete() in the first
956+ // clean, Clean() will return OK, but files may not be deleted, so need to call Clean()
957+ // again. If the third call Clean() return empty, it means all files are deleted and
958+ // already scanned all io hooks.
959+ clean_result = cleaner->Clean (); // third clean
945960 ASSERT_OK (clean_result);
946961 if (!clean_result.value ().empty ()) {
947962 scanned_all_io_hook = false ;
0 commit comments