| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ash/fileapi/recent_arc_media_source.h" |
| |
| #include <memory> |
| #include <optional> |
| #include <string> |
| #include <utility> |
| |
| #include "base/functional/bind.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/run_loop.h" |
| #include "base/test/bind.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "base/time/time.h" |
| #include "chrome/browser/ash/arc/arc_util.h" |
| #include "chrome/browser/ash/arc/fileapi/arc_documents_provider_util.h" |
| #include "chrome/browser/ash/arc/fileapi/arc_file_system_mounter.h" |
| #include "chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner.h" |
| #include "chrome/browser/ash/arc/fileapi/arc_media_view_util.h" |
| #include "chrome/browser/ash/fileapi/recent_file.h" |
| #include "chrome/browser/ash/fileapi/recent_source.h" |
| #include "chrome/browser/ash/fileapi/test/recent_file_matcher.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "chromeos/ash/experiences/arc/mojom/file_system.mojom.h" |
| #include "chromeos/ash/experiences/arc/session/arc_bridge_service.h" |
| #include "chromeos/ash/experiences/arc/session/arc_service_manager.h" |
| #include "chromeos/ash/experiences/arc/test/connection_holder_util.h" |
| #include "chromeos/ash/experiences/arc/test/fake_file_system_instance.h" |
| #include "components/keyed_service/content/browser_context_keyed_service_factory.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace ash { |
| namespace { |
| |
| std::unique_ptr<KeyedService> CreateFileSystemOperationRunnerForTesting( |
| content::BrowserContext* context) { |
| return arc::ArcFileSystemOperationRunner::CreateForTesting( |
| context, arc::ArcServiceManager::Get()->arc_bridge_service()); |
| } |
| |
| base::FilePath GetPathForRoot(const std::string& root, |
| const std::string& name) { |
| return arc::GetDocumentsProviderMountPath( |
| arc::kMediaDocumentsProviderAuthority, root) |
| .Append(name); |
| } |
| |
| base::FilePath GetDocumentPath(const std::string& name) { |
| return GetPathForRoot(arc::kDocumentsRootId, name); |
| } |
| |
| base::FilePath GetImagePath(const std::string& name) { |
| return GetPathForRoot(arc::kImagesRootId, name); |
| } |
| |
| base::FilePath GetVideoPath(const std::string& name) { |
| return GetPathForRoot(arc::kVideosRootId, name); |
| } |
| |
| base::Time ModifiedTime(int64_t millis) { |
| return base::Time::FromMillisecondsSinceUnixEpoch(millis); |
| } |
| |
| arc::FakeFileSystemInstance::Document MakeDocument( |
| const std::string& document_id, |
| const std::string& parent_document_id, |
| const std::string& display_name, |
| const std::string& mime_type, |
| const base::Time& last_modified) { |
| return arc::FakeFileSystemInstance::Document( |
| arc::kMediaDocumentsProviderAuthority, // authority |
| document_id, // document_id |
| parent_document_id, // parent_document_id |
| display_name, // display_name |
| mime_type, // mime_type |
| 0, // size |
| last_modified.InMillisecondsSinceUnixEpoch()); // last_modified |
| } |
| |
| } // namespace |
| |
| class RecentArcMediaSourceTest : public testing::Test { |
| public: |
| RecentArcMediaSourceTest() = default; |
| |
| void SetUp() override { |
| arc_service_manager_ = std::make_unique<arc::ArcServiceManager>(); |
| profile_ = std::make_unique<TestingProfile>(); |
| arc_service_manager_->set_browser_context(profile_.get()); |
| runner_ = static_cast<arc::ArcFileSystemOperationRunner*>( |
| arc::ArcFileSystemOperationRunner::GetFactory() |
| ->SetTestingFactoryAndUse( |
| profile_.get(), |
| base::BindRepeating( |
| &CreateFileSystemOperationRunnerForTesting))); |
| |
| // Mount ARC file systems. |
| arc::ArcFileSystemMounter::GetForBrowserContext(profile_.get()); |
| |
| // Add documents to FakeFileSystemInstance. Note that they are not available |
| // until EnableFakeFileSystemInstance() is called. |
| AddDocumentsToFakeFileSystemInstance(); |
| } |
| |
| void TearDown() override { |
| arc_service_manager_->arc_bridge_service()->file_system()->CloseInstance( |
| &fake_file_system_); |
| arc_service_manager_->set_browser_context(nullptr); |
| } |
| |
| protected: |
| void AddDocumentsToFakeFileSystemInstance() { |
| auto images_root_doc = |
| MakeDocument(arc::kImagesRootId, "", "", arc::kAndroidDirectoryMimeType, |
| base::Time::FromMillisecondsSinceUnixEpoch(1)); |
| auto cat_doc = MakeDocument("cat", arc::kImagesRootId, "cat.png", |
| "image/png", ModifiedTime(2)); |
| auto dog_doc = MakeDocument("dog", arc::kImagesRootId, "dog.jpg", |
| "image/jpeg", ModifiedTime(3)); |
| auto fox_doc = MakeDocument("fox", arc::kImagesRootId, "fox.gif", |
| "image/gif", ModifiedTime(4)); |
| auto elk_doc = MakeDocument("elk", arc::kImagesRootId, "elk.tiff", |
| "image/tiff", ModifiedTime(5)); |
| auto audio_root_doc = |
| MakeDocument(arc::kAudioRootId, "", "", arc::kAndroidDirectoryMimeType, |
| ModifiedTime(1)); |
| auto god_doc = MakeDocument("god", arc::kAudioRootId, "god.mp3", |
| "audio/mp3", ModifiedTime(6)); |
| auto videos_root_doc = |
| MakeDocument(arc::kVideosRootId, "", "", arc::kAndroidDirectoryMimeType, |
| ModifiedTime(1)); |
| auto hot_doc = MakeDocument("hot", arc::kVideosRootId, "hot.mp4", |
| "video/mp4", ModifiedTime(7)); |
| auto ink_doc = MakeDocument("ink", arc::kVideosRootId, "ink.webm", |
| "video/webm", ModifiedTime(8)); |
| auto documents_root_doc = |
| MakeDocument(arc::kDocumentsRootId, "", "", |
| arc::kAndroidDirectoryMimeType, ModifiedTime(1)); |
| auto word_doc = MakeDocument("word", arc::kDocumentsRootId, "word.doc", |
| "application/msword", ModifiedTime(9)); |
| auto text_doc = MakeDocument("text", arc::kDocumentsRootId, "text.txt", |
| "text/plain", ModifiedTime(10)); |
| |
| fake_file_system_.AddDocument(images_root_doc); |
| fake_file_system_.AddDocument(cat_doc); |
| fake_file_system_.AddDocument(dog_doc); |
| fake_file_system_.AddDocument(fox_doc); |
| fake_file_system_.AddDocument(audio_root_doc); |
| fake_file_system_.AddDocument(god_doc); |
| fake_file_system_.AddDocument(videos_root_doc); |
| fake_file_system_.AddDocument(hot_doc); |
| fake_file_system_.AddDocument(ink_doc); |
| fake_file_system_.AddDocument(documents_root_doc); |
| fake_file_system_.AddDocument(word_doc); |
| fake_file_system_.AddDocument(text_doc); |
| |
| fake_file_system_.AddRecentDocument(arc::kImagesRootId, images_root_doc); |
| fake_file_system_.AddRecentDocument(arc::kImagesRootId, cat_doc); |
| fake_file_system_.AddRecentDocument(arc::kImagesRootId, dog_doc); |
| fake_file_system_.AddRecentDocument(arc::kImagesRootId, elk_doc); |
| fake_file_system_.AddRecentDocument(arc::kAudioRootId, audio_root_doc); |
| fake_file_system_.AddRecentDocument(arc::kAudioRootId, god_doc); |
| fake_file_system_.AddRecentDocument(arc::kVideosRootId, videos_root_doc); |
| fake_file_system_.AddRecentDocument(arc::kVideosRootId, hot_doc); |
| fake_file_system_.AddRecentDocument(arc::kVideosRootId, ink_doc); |
| fake_file_system_.AddRecentDocument(arc::kDocumentsRootId, |
| documents_root_doc); |
| fake_file_system_.AddRecentDocument(arc::kDocumentsRootId, word_doc); |
| fake_file_system_.AddRecentDocument(arc::kDocumentsRootId, text_doc); |
| } |
| |
| void EnableFakeFileSystemInstance() { |
| arc_service_manager_->arc_bridge_service()->file_system()->SetInstance( |
| &fake_file_system_); |
| arc::WaitForInstanceReady( |
| arc_service_manager_->arc_bridge_service()->file_system()); |
| } |
| |
| // Fetches files matching the given query and specified `file_type` from |
| // the `source_`. If the `root_lag` has value it can be used to cause one |
| // of the roots (documents, images, videos) to experience an artificial lag. |
| // If the lag is specified, it must be greater than 100ms. |
| std::vector<RecentFile> GetRecentFiles( |
| RecentArcMediaSource* source, |
| const std::string& query, |
| RecentSource::FileType file_type = RecentSource::FileType::kAll, |
| std::optional<std::pair<const char*, base::TimeDelta>> root_lag = {}, |
| size_t max_files = 10) { |
| std::vector<RecentFile> files; |
| base::RunLoop run_loop; |
| base::OneShotTimer timer; |
| |
| const int32_t call_id = 0; |
| if (root_lag.has_value()) { |
| auto [root_id, lag] = root_lag.value(); |
| base::TimeDelta stop_delta = lag - base::Milliseconds(100); |
| source->SetLagForTesting(lag); |
| EXPECT_TRUE(stop_delta.is_positive()); |
| timer.Start(FROM_HERE, stop_delta, base::BindLambdaForTesting([&]() { |
| files = source->Stop(call_id); |
| run_loop.Quit(); |
| })); |
| } |
| |
| source->GetRecentFiles( |
| RecentSource::Params( |
| /*file_system_context=*/nullptr, call_id, |
| /*origin=*/GURL(), query, |
| /*max_files=*/max_files, |
| /*cutoff_time=*/base::Time(), |
| /*end_time=*/base::TimeTicks::Max(), |
| /*file_type=*/file_type), |
| base::BindOnce( |
| [](base::RunLoop* run_loop, std::vector<RecentFile>* out_files, |
| std::vector<RecentFile> files) { |
| *out_files = std::move(files); |
| run_loop->Quit(); |
| }, |
| &run_loop, &files)); |
| |
| run_loop.Run(); |
| |
| return files; |
| } |
| |
| void EnableDefer() { runner_->SetShouldDefer(true); } |
| |
| // NOTE: In local run real time was used. However, that causes the test to run |
| // for over 6s. With MOCK_TIME, this is reduced to 3s with no difference to |
| // test outcomes (UmaStats taking the longest). |
| content::BrowserTaskEnvironment task_environment_{ |
| content::BrowserTaskEnvironment::REAL_IO_THREAD, |
| base::test::TaskEnvironment::TimeSource::MOCK_TIME}; |
| arc::FakeFileSystemInstance fake_file_system_; |
| |
| // Use the same initialization/destruction order as |
| // `ChromeBrowserMainPartsAsh`. |
| std::unique_ptr<arc::ArcServiceManager> arc_service_manager_; |
| std::unique_ptr<TestingProfile> profile_; |
| |
| raw_ptr<arc::ArcFileSystemOperationRunner> runner_; |
| }; |
| |
| TEST_F(RecentArcMediaSourceTest, Normal) { |
| EnableFakeFileSystemInstance(); |
| |
| auto doc_source = std::make_unique<RecentArcMediaSource>( |
| profile_.get(), arc::kDocumentsRootId); |
| std::vector<RecentFile> doc_files = GetRecentFiles(doc_source.get(), ""); |
| |
| ASSERT_EQ(2u, doc_files.size()); |
| EXPECT_THAT(doc_files[0], |
| IsRecentFile(GetDocumentPath("text.txt"), ModifiedTime(10))); |
| EXPECT_THAT(doc_files[1], |
| IsRecentFile(GetDocumentPath("word.doc"), ModifiedTime(9))); |
| |
| auto video_source = std::make_unique<RecentArcMediaSource>( |
| profile_.get(), arc::kVideosRootId); |
| std::vector<RecentFile> video_files = GetRecentFiles(video_source.get(), ""); |
| |
| ASSERT_EQ(2u, video_files.size()); |
| EXPECT_THAT(video_files[0], |
| IsRecentFile(GetVideoPath("ink.webm"), ModifiedTime(8))); |
| EXPECT_THAT(video_files[1], |
| IsRecentFile(GetVideoPath("hot.mp4"), ModifiedTime(7))); |
| |
| auto image_source = std::make_unique<RecentArcMediaSource>( |
| profile_.get(), arc::kImagesRootId); |
| std::vector<RecentFile> image_files = GetRecentFiles(image_source.get(), ""); |
| |
| EXPECT_THAT(image_files[0], |
| IsRecentFile(GetImagePath("dog.jpg"), ModifiedTime(3))); |
| EXPECT_THAT(image_files[1], |
| IsRecentFile(GetImagePath("cat.png"), ModifiedTime(2))); |
| |
| doc_files = GetRecentFiles(doc_source.get(), "text"); |
| ASSERT_EQ(1u, doc_files.size()); |
| EXPECT_THAT(doc_files[0], |
| IsRecentFile(GetDocumentPath("text.txt"), ModifiedTime(10))); |
| ASSERT_EQ(0u, GetRecentFiles(video_source.get(), "text").size()); |
| ASSERT_EQ(0u, GetRecentFiles(image_source.get(), "text").size()); |
| } |
| |
| TEST_F(RecentArcMediaSourceTest, ArcNotAvailable) { |
| // By not enabling fake file system instance we make Arc unavailable. |
| auto doc_source = std::make_unique<RecentArcMediaSource>( |
| profile_.get(), arc::kDocumentsRootId); |
| std::vector<RecentFile> files = GetRecentFiles(doc_source.get(), ""); |
| EXPECT_EQ(0u, files.size()); |
| |
| files = GetRecentFiles(doc_source.get(), "hot"); |
| EXPECT_EQ(0u, files.size()); |
| } |
| |
| TEST_F(RecentArcMediaSourceTest, Deferred) { |
| EnableFakeFileSystemInstance(); |
| EnableDefer(); |
| |
| auto doc_source = std::make_unique<RecentArcMediaSource>( |
| profile_.get(), arc::kDocumentsRootId); |
| std::vector<RecentFile> files = GetRecentFiles(doc_source.get(), ""); |
| EXPECT_EQ(0u, files.size()); |
| |
| files = GetRecentFiles(doc_source.get(), "word"); |
| EXPECT_EQ(0u, files.size()); |
| } |
| |
| TEST_F(RecentArcMediaSourceTest, GetAudioFiles) { |
| EnableFakeFileSystemInstance(); |
| |
| auto doc_source = std::make_unique<RecentArcMediaSource>( |
| profile_.get(), arc::kDocumentsRootId); |
| std::vector<RecentFile> files = |
| GetRecentFiles(doc_source.get(), "", RecentSource::FileType::kAudio); |
| // Query for recently-modified audio files should be ignored, since |
| // MediaDocumentsProvider doesn't support queryRecentDocuments for audio. |
| ASSERT_EQ(0u, files.size()); |
| } |
| |
| TEST_F(RecentArcMediaSourceTest, GetImageFiles) { |
| EnableFakeFileSystemInstance(); |
| |
| auto image_source = std::make_unique<RecentArcMediaSource>( |
| profile_.get(), arc::kImagesRootId); |
| std::vector<RecentFile> files = |
| GetRecentFiles(image_source.get(), "", RecentSource::FileType::kImage); |
| |
| ASSERT_EQ(2u, files.size()); |
| EXPECT_THAT(files[0], IsRecentFile(GetImagePath("dog.jpg"), ModifiedTime(3))); |
| EXPECT_THAT(files[1], IsRecentFile(GetImagePath("cat.png"), ModifiedTime(2))); |
| } |
| |
| TEST_F(RecentArcMediaSourceTest, GetVideoFiles) { |
| EnableFakeFileSystemInstance(); |
| |
| auto video_source = std::make_unique<RecentArcMediaSource>( |
| profile_.get(), arc::kVideosRootId); |
| std::vector<RecentFile> files = |
| GetRecentFiles(video_source.get(), "", RecentSource::FileType::kVideo); |
| |
| ASSERT_EQ(2u, files.size()); |
| EXPECT_THAT(files[0], |
| IsRecentFile(GetVideoPath("ink.webm"), ModifiedTime(8))); |
| EXPECT_THAT(files[1], IsRecentFile(GetVideoPath("hot.mp4"), ModifiedTime(7))); |
| } |
| |
| TEST_F(RecentArcMediaSourceTest, GetDocumentFiles) { |
| EnableFakeFileSystemInstance(); |
| |
| auto doc_source = std::make_unique<RecentArcMediaSource>( |
| profile_.get(), arc::kDocumentsRootId); |
| std::vector<RecentFile> files = |
| GetRecentFiles(doc_source.get(), "", RecentSource::FileType::kDocument); |
| |
| ASSERT_EQ(2u, files.size()); |
| EXPECT_THAT(files[0], |
| IsRecentFile(GetDocumentPath("text.txt"), ModifiedTime(10))); |
| EXPECT_THAT(files[1], |
| IsRecentFile(GetDocumentPath("word.doc"), ModifiedTime(9))); |
| |
| files = GetRecentFiles(doc_source.get(), "word", |
| RecentSource::FileType::kDocument); |
| ASSERT_EQ(1u, files.size()); |
| EXPECT_THAT(files[0], |
| IsRecentFile(GetDocumentPath("word.doc"), ModifiedTime(9))); |
| |
| files = GetRecentFiles(doc_source.get(), "no-match", |
| RecentSource::FileType::kDocument); |
| ASSERT_EQ(0u, files.size()); |
| } |
| |
| TEST_F(RecentArcMediaSourceTest, LaggyDocuments) { |
| EnableFakeFileSystemInstance(); |
| // Find all recent files containing 'd' in their name. |
| auto doc_source = std::make_unique<RecentArcMediaSource>( |
| profile_.get(), arc::kDocumentsRootId); |
| std::vector<RecentFile> files_no_lag = GetRecentFiles(doc_source.get(), "d"); |
| ASSERT_EQ(1u, files_no_lag.size()); |
| EXPECT_THAT(files_no_lag[0], |
| IsRecentFile(GetDocumentPath("word.doc"), ModifiedTime(9))); |
| |
| // Now search again; but with an artificial lag for documents. Expect that |
| // word.doc is no longer found. |
| std::vector<RecentFile> files = GetRecentFiles( |
| doc_source.get(), "d", RecentSource::FileType::kAll, |
| std::make_pair(arc::kDocumentsRootId, base::Milliseconds(500))); |
| |
| ASSERT_EQ(0u, files.size()); |
| } |
| |
| TEST_F(RecentArcMediaSourceTest, OverlappingLaggySearches) { |
| EnableFakeFileSystemInstance(); |
| // The number of times laggy, overlapping search is repeated. |
| constexpr int32_t reps = 10; |
| |
| auto doc_source = std::make_unique<RecentArcMediaSource>( |
| profile_.get(), arc::kDocumentsRootId); |
| std::vector<std::vector<RecentFile>> results(reps); |
| std::vector<base::OneShotTimer> timers(reps); |
| |
| // Prepare timers; timers are stopping searches at 250ms + 100ms * call_id. |
| // Whenever a source is stopped, the code just collects its partial results |
| // for later analysis. |
| for (int32_t call_id = 0; call_id < reps; ++call_id) { |
| base::TimeDelta stop_delta = base::Milliseconds(250 + 100 * call_id); |
| base::TimeDelta lag_delta = base::Milliseconds(500 + 100 * call_id); |
| doc_source->SetLagForTesting(lag_delta); |
| timers[call_id].Start( |
| FROM_HERE, stop_delta, |
| base::BindOnce( |
| [](const int32_t my_call_id, std::vector<RecentFile>* out_files, |
| RecentArcMediaSource* source) { |
| *out_files = source->Stop(my_call_id); |
| }, |
| call_id, &results[call_id], doc_source.get())); |
| doc_source->GetRecentFiles(RecentSource::Params( |
| /*file_system_context=*/nullptr, |
| /*call_id=*/call_id, |
| /*origin=*/GURL(), |
| /*query=*/"d", |
| /*max_files=*/10, |
| /*cutoff_time=*/base::Time(), |
| /*end_time=*/base::TimeTicks::Max(), |
| /*file_type=*/RecentSource::FileType::kAll), |
| base::BindOnce( |
| [](std::vector<RecentFile>* out_files, |
| std::vector<RecentFile> files) { |
| *out_files = std::move(files); |
| }, |
| &results[call_id])); |
| } |
| |
| // Last call; wait for the results; these results are not interrupted and take |
| // longer than any of the request requested above. |
| doc_source->SetLagForTesting(base::Milliseconds(500 + 100 * reps)); |
| base::RunLoop run_loop; |
| std::vector<RecentFile> final_result; |
| doc_source->GetRecentFiles( |
| RecentSource::Params( |
| /*file_system_context=*/nullptr, |
| /*call_id=*/reps, |
| /*origin=*/GURL(), |
| /*query=*/"d", |
| /*max_files=*/10, |
| /*cutoff_time=*/base::Time(), |
| /*end_time=*/base::TimeTicks::Max(), |
| /*file_type=*/RecentSource::FileType::kAll), |
| base::BindOnce( |
| [](base::RunLoop* run_loop, std::vector<RecentFile>* out_files, |
| std::vector<RecentFile> files) { |
| *out_files = std::move(files); |
| run_loop->Quit(); |
| }, |
| &run_loop, &final_result)); |
| |
| run_loop.Run(); |
| ASSERT_EQ(1u, final_result.size()); |
| EXPECT_THAT(final_result[0], |
| IsRecentFile(GetDocumentPath("word.doc"), ModifiedTime(9))); |
| for (int32_t call_id = 0; call_id < reps; ++call_id) { |
| ASSERT_EQ(0u, results[call_id].size()); |
| } |
| } |
| |
| TEST_F(RecentArcMediaSourceTest, UmaStats) { |
| EnableFakeFileSystemInstance(); |
| |
| auto doc_source = std::make_unique<RecentArcMediaSource>( |
| profile_.get(), arc::kDocumentsRootId); |
| base::HistogramTester histogram_tester; |
| |
| GetRecentFiles(doc_source.get(), ""); |
| |
| histogram_tester.ExpectTotalCount(RecentArcMediaSource::kLoadHistogramName, |
| 1); |
| } |
| |
| TEST_F(RecentArcMediaSourceTest, UmaStats_Deferred) { |
| EnableFakeFileSystemInstance(); |
| EnableDefer(); |
| |
| auto doc_source = std::make_unique<RecentArcMediaSource>( |
| profile_.get(), arc::kDocumentsRootId); |
| base::HistogramTester histogram_tester; |
| |
| GetRecentFiles(doc_source.get(), ""); |
| |
| histogram_tester.ExpectTotalCount(RecentArcMediaSource::kLoadHistogramName, |
| 0); |
| } |
| |
| TEST_F(RecentArcMediaSourceTest, MaxFiles) { |
| EnableFakeFileSystemInstance(); |
| |
| // Maximum one image can be returned per query, regardless of matched numbers. |
| auto image_source = std::make_unique<RecentArcMediaSource>( |
| profile_.get(), arc::kImagesRootId); |
| std::vector<RecentFile> files = GetRecentFiles( |
| image_source.get(), "", RecentSource::FileType::kImage, {}, 1); |
| |
| ASSERT_EQ(1u, files.size()); |
| EXPECT_THAT(files[0], IsRecentFile(GetImagePath("dog.jpg"), ModifiedTime(3))); |
| } |
| |
| TEST_F(RecentArcMediaSourceTest, CallStopLate) { |
| EnableFakeFileSystemInstance(); |
| |
| // Maximum one image can be returned per query, relardless of matched numbers. |
| auto image_source = std::make_unique<RecentArcMediaSource>( |
| profile_.get(), arc::kImagesRootId); |
| std::vector<RecentFile> files = |
| GetRecentFiles(image_source.get(), "", RecentSource::FileType::kImage); |
| |
| ASSERT_EQ(2u, files.size()); |
| EXPECT_THAT(files[0], IsRecentFile(GetImagePath("dog.jpg"), ModifiedTime(3))); |
| EXPECT_THAT(files[1], IsRecentFile(GetImagePath("cat.png"), ModifiedTime(2))); |
| |
| std::vector<RecentFile> stop_files = image_source->Stop(0); |
| ASSERT_EQ(0u, stop_files.size()); |
| } |
| |
| } // namespace ash |