Index: net/base/directory_lister_unittest.cc |
diff --git a/net/base/directory_lister_unittest.cc b/net/base/directory_lister_unittest.cc |
index 869e4f688b90a589509c180d9625eac7cf314ca8..adc3d5e08d8682def77118c4d4fe68281da007be 100644 |
--- a/net/base/directory_lister_unittest.cc |
+++ b/net/base/directory_lister_unittest.cc |
@@ -4,12 +4,15 @@ |
#include <list> |
#include <utility> |
+#include <vector> |
+#include "base/bind.h" |
#include "base/files/file_path.h" |
#include "base/files/file_util.h" |
#include "base/files/scoped_temp_dir.h" |
#include "base/i18n/file_util_icu.h" |
#include "base/message_loop/message_loop.h" |
+#include "base/run_loop.h" |
#include "base/strings/stringprintf.h" |
#include "net/base/directory_lister.h" |
#include "net/base/net_errors.h" |
@@ -18,29 +21,59 @@ |
namespace net { |
+namespace { |
+ |
+const int kMaxDepth = 3; |
+const int kBranchingFactor = 4; |
+const int kFilesPerDirectory = 5; |
+ |
class ListerDelegate : public DirectoryLister::DirectoryListerDelegate { |
public: |
- ListerDelegate(bool recursive, |
- bool quit_loop_after_each_file) |
- : error_(-1), |
- recursive_(recursive), |
- quit_loop_after_each_file_(quit_loop_after_each_file) { |
+ explicit ListerDelegate(bool recursive) |
+ : cancel_lister_on_list_file_(false), |
+ cancel_lister_on_list_done_(false), |
+ lister_(nullptr), |
+ done_(false), |
+ error_(-1), |
+ recursive_(recursive) { |
+ } |
+ |
+ // When set to true, this signals that the directory list operation should be |
+ // cancelled (And the run loop quit) in the first call to OnListFile. |
+ void set_cancel_lister_on_list_file(bool cancel_lister_on_list_file) { |
+ cancel_lister_on_list_file_ = cancel_lister_on_list_file; |
+ } |
+ |
+ // When set to true, this signals that the directory list operation should be |
+ // cancelled (And the run loop quit) when OnDone is called. |
+ void set_cancel_lister_on_list_done(bool cancel_lister_on_list_done) { |
+ cancel_lister_on_list_done_ = cancel_lister_on_list_done; |
} |
void OnListFile(const DirectoryLister::DirectoryListerData& data) override { |
+ ASSERT_FALSE(done_); |
+ |
file_list_.push_back(data.info); |
paths_.push_back(data.path); |
- if (quit_loop_after_each_file_) |
- base::MessageLoop::current()->Quit(); |
+ if (cancel_lister_on_list_file_) { |
+ lister_->Cancel(); |
+ run_loop.Quit(); |
+ } |
} |
void OnListDone(int error) override { |
+ ASSERT_FALSE(done_); |
+ |
+ done_ = true; |
error_ = error; |
- base::MessageLoop::current()->Quit(); |
if (recursive_) |
CheckRecursiveSort(); |
else |
CheckSort(); |
+ |
+ if (cancel_lister_on_list_done_) |
+ lister_->Cancel(); |
+ run_loop.Quit(); |
} |
void CheckRecursiveSort() { |
@@ -77,25 +110,45 @@ class ListerDelegate : public DirectoryLister::DirectoryListerDelegate { |
} |
} |
+ void Run(DirectoryLister* lister) { |
+ lister_ = lister; |
+ lister_->Start(); |
+ run_loop.Run(); |
+ } |
+ |
int error() const { return error_; } |
int num_files() const { return file_list_.size(); } |
+ bool done() const { return done_; } |
+ |
private: |
+ bool cancel_lister_on_list_file_; |
+ bool cancel_lister_on_list_done_; |
+ |
+ // This is owned by the individual tests, rather than the ListerDelegate. |
+ DirectoryLister* lister_; |
+ |
+ base::RunLoop run_loop; |
+ |
+ bool done_; |
int error_; |
bool recursive_; |
- bool quit_loop_after_each_file_; |
+ |
std::vector<base::FileEnumerator::FileInfo> file_list_; |
std::vector<base::FilePath> paths_; |
}; |
+} // namespace |
+ |
class DirectoryListerTest : public PlatformTest { |
public: |
- void SetUp() override { |
- const int kMaxDepth = 3; |
- const int kBranchingFactor = 4; |
- const int kFilesPerDirectory = 5; |
+ DirectoryListerTest() |
+ : total_created_file_system_objects_in_temp_root_dir_(0), |
+ created_file_system_objects_in_temp_root_dir_(0) { |
+ } |
+ void SetUp() override { |
// Randomly create a directory structure of depth 3 in a temporary root |
// directory. |
std::list<std::pair<base::FilePath, int> > directories; |
@@ -110,12 +163,18 @@ class DirectoryListerTest : public PlatformTest { |
base::File file(file_path, |
base::File::FLAG_CREATE | base::File::FLAG_WRITE); |
ASSERT_TRUE(file.IsValid()); |
+ ++total_created_file_system_objects_in_temp_root_dir_; |
+ if (dir_data.first == temp_root_dir_.path()) |
+ ++created_file_system_objects_in_temp_root_dir_; |
} |
if (dir_data.second < kMaxDepth - 1) { |
for (int i = 0; i < kBranchingFactor; i++) { |
std::string dir_name = base::StringPrintf("child_dir_%d", i); |
base::FilePath dir_path = dir_data.first.AppendASCII(dir_name); |
ASSERT_TRUE(base::CreateDirectory(dir_path)); |
+ ++total_created_file_system_objects_in_temp_root_dir_; |
+ if (dir_data.first == temp_root_dir_.path()) |
+ ++created_file_system_objects_in_temp_root_dir_; |
directories.push_back(std::make_pair(dir_path, dir_data.second + 1)); |
} |
} |
@@ -127,62 +186,125 @@ class DirectoryListerTest : public PlatformTest { |
return temp_root_dir_.path(); |
} |
+ int expected_list_length_recursive() const { |
+ // List should include everything but the top level directory, and does not |
+ // include "..". |
+ return total_created_file_system_objects_in_temp_root_dir_; |
+ } |
+ |
+ int expected_list_length_non_recursive() const { |
+ // List should include everything in the top level directory, and "..". |
+ return created_file_system_objects_in_temp_root_dir_ + 1; |
+ } |
+ |
private: |
+ // Number of files and directories created in SetUp, excluding |
+ // |temp_root_dir_| itself. Includes all nested directories and their files. |
+ int total_created_file_system_objects_in_temp_root_dir_; |
+ // Number of files and directories created directly in |temp_root_dir_|. |
+ int created_file_system_objects_in_temp_root_dir_; |
+ |
base::ScopedTempDir temp_root_dir_; |
}; |
TEST_F(DirectoryListerTest, BigDirTest) { |
- ListerDelegate delegate(false, false); |
+ ListerDelegate delegate(false); |
DirectoryLister lister(root_path(), &delegate); |
- lister.Start(); |
- |
- base::MessageLoop::current()->Run(); |
+ delegate.Run(&lister); |
+ EXPECT_TRUE(delegate.done()); |
EXPECT_EQ(OK, delegate.error()); |
+ EXPECT_EQ(expected_list_length_non_recursive(), delegate.num_files()); |
} |
TEST_F(DirectoryListerTest, BigDirRecursiveTest) { |
- ListerDelegate delegate(true, false); |
- DirectoryLister lister(root_path(), true, DirectoryLister::FULL_PATH, |
- &delegate); |
- lister.Start(); |
- |
- base::MessageLoop::current()->Run(); |
+ ListerDelegate delegate(true); |
+ DirectoryLister lister( |
+ root_path(), true, DirectoryLister::FULL_PATH, &delegate); |
+ delegate.Run(&lister); |
+ EXPECT_TRUE(delegate.done()); |
EXPECT_EQ(OK, delegate.error()); |
+ EXPECT_EQ(expected_list_length_recursive(), delegate.num_files()); |
} |
-TEST_F(DirectoryListerTest, CancelTest) { |
- ListerDelegate delegate(false, true); |
- DirectoryLister lister(root_path(), &delegate); |
- lister.Start(); |
+TEST_F(DirectoryListerTest, EmptyDirTest) { |
+ base::ScopedTempDir tempDir; |
+ EXPECT_TRUE(tempDir.CreateUniqueTempDir()); |
- base::MessageLoop::current()->Run(); |
+ ListerDelegate delegate(false); |
+ DirectoryLister lister(tempDir.path(), &delegate); |
+ delegate.Run(&lister); |
- int num_files = delegate.num_files(); |
+ EXPECT_TRUE(delegate.done()); |
+ EXPECT_EQ(OK, delegate.error()); |
+ // Contains only the parent directory (".."). |
+ EXPECT_EQ(1, delegate.num_files()); |
+} |
- lister.Cancel(); |
+// This doesn't really test much, except make sure calling cancel before any |
+// callbacks are invoked doesn't crash. Can't wait for all tasks running on a |
+// worker pool to complete, unfortunately. |
+// TODO(mmenke): See if there's a way to make this fail more reliably on |
+// regression. |
+TEST_F(DirectoryListerTest, BasicCancelTest) { |
+ ListerDelegate delegate(false); |
+ scoped_ptr<DirectoryLister> lister(new DirectoryLister( |
+ root_path(), &delegate)); |
+ lister->Start(); |
+ lister->Cancel(); |
+ base::RunLoop().RunUntilIdle(); |
+ |
+ EXPECT_FALSE(delegate.done()); |
+ EXPECT_EQ(0, delegate.num_files()); |
+} |
- base::MessageLoop::current()->RunUntilIdle(); |
+TEST_F(DirectoryListerTest, CancelOnListFileTest) { |
+ ListerDelegate delegate(false); |
+ DirectoryLister lister(root_path(), &delegate); |
+ delegate.set_cancel_lister_on_list_file(true); |
+ delegate.Run(&lister); |
- EXPECT_EQ(num_files, delegate.num_files()); |
+ EXPECT_FALSE(delegate.done()); |
+ EXPECT_EQ(1, delegate.num_files()); |
} |
-TEST_F(DirectoryListerTest, EmptyDirTest) { |
+TEST_F(DirectoryListerTest, CancelOnListDoneTest) { |
+ ListerDelegate delegate(false); |
+ DirectoryLister lister(root_path(), &delegate); |
+ delegate.set_cancel_lister_on_list_done(true); |
+ delegate.Run(&lister); |
+ |
+ EXPECT_TRUE(delegate.done()); |
+ EXPECT_EQ(OK, delegate.error()); |
+ EXPECT_EQ(expected_list_length_non_recursive(), delegate.num_files()); |
+} |
+ |
+TEST_F(DirectoryListerTest, CancelOnLastElementTest) { |
base::ScopedTempDir tempDir; |
EXPECT_TRUE(tempDir.CreateUniqueTempDir()); |
- bool kRecursive = false; |
- bool kQuitLoopAfterEachFile = false; |
- ListerDelegate delegate(kRecursive, kQuitLoopAfterEachFile); |
+ ListerDelegate delegate(false); |
DirectoryLister lister(tempDir.path(), &delegate); |
- lister.Start(); |
- |
- base::MessageLoop::current()->Run(); |
+ delegate.set_cancel_lister_on_list_file(true); |
+ delegate.Run(&lister); |
- // Contains only the parent directory ("..") |
+ EXPECT_FALSE(delegate.done()); |
+ // Contains only the parent directory (".."). |
EXPECT_EQ(1, delegate.num_files()); |
- EXPECT_EQ(OK, delegate.error()); |
+} |
+ |
+TEST_F(DirectoryListerTest, NoSuchDirTest) { |
+ base::ScopedTempDir tempDir; |
+ EXPECT_TRUE(tempDir.CreateUniqueTempDir()); |
+ |
+ ListerDelegate delegate(false); |
+ DirectoryLister lister( |
+ tempDir.path().AppendASCII("this_path_does_not_exist"), &delegate); |
+ delegate.Run(&lister); |
+ |
+ EXPECT_EQ(ERR_FILE_NOT_FOUND, delegate.error()); |
+ EXPECT_EQ(0, delegate.num_files()); |
} |
} // namespace net |