summaryrefslogtreecommitdiffstats
path: root/util/folder/iterator_ut.cpp
diff options
context:
space:
mode:
authorDevtools Arcadia <[email protected]>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <[email protected]>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/folder/iterator_ut.cpp
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/folder/iterator_ut.cpp')
-rw-r--r--util/folder/iterator_ut.cpp227
1 files changed, 227 insertions, 0 deletions
diff --git a/util/folder/iterator_ut.cpp b/util/folder/iterator_ut.cpp
new file mode 100644
index 00000000000..936becd139b
--- /dev/null
+++ b/util/folder/iterator_ut.cpp
@@ -0,0 +1,227 @@
+#include "dirut.h"
+#include "iterator.h"
+
+#include <library/cpp/testing/unittest/registar.h>
+
+#include <util/system/fs.h>
+#include <util/system/file.h>
+#include <util/generic/hash.h>
+#include <util/generic/algorithm.h>
+#include <util/random/mersenne.h>
+
+static TString JoinWithNewline(const TVector<TString>& strings) {
+ TStringStream ss;
+ for (const auto& string : strings) {
+ ss << string << "\n";
+ }
+ return ss.Str();
+}
+
+class TDirIteratorTest: public TTestBase {
+ UNIT_TEST_SUITE(TDirIteratorTest);
+ UNIT_TEST(TestIt)
+ UNIT_TEST(TestError)
+ UNIT_TEST(TestLocal)
+ UNIT_TEST(TestSkip)
+ UNIT_TEST(TestSort)
+ UNIT_TEST_SUITE_END();
+
+private:
+ class TDirHier {
+ public:
+ struct TPath {
+ TString Path;
+ int Type;
+ };
+
+ inline void AddFile(const TString& path) {
+ Add(path, 0);
+ }
+
+ inline void AddDir(const TString& path) {
+ Add(path, 1);
+ }
+
+ inline void Add(const TString& path, int type) {
+ const TPath p = {
+ path, type};
+
+ Add(p);
+ }
+
+ inline void Add(const TPath& path) {
+ switch (path.Type) {
+ case 0:
+ TFile(path.Path, CreateAlways | RdWr);
+ break;
+
+ case 1:
+ MakeDirIfNotExist(path.Path.data());
+ break;
+
+ case 2:
+ ythrow yexception() << "unknown path type";
+ }
+
+ Paths_.push_back(path);
+ Srch_[path.Path] = path;
+ }
+
+ inline int Type(const TString& path) {
+ THashMap<TString, TPath>::const_iterator it = Srch_.find(path);
+
+ UNIT_ASSERT(it != Srch_.end());
+
+ return it->second.Type;
+ }
+
+ inline bool Have(const TString& path, int type) {
+ return Type(path) == type;
+ }
+
+ inline ~TDirHier() {
+ for (size_t i = 0; i < Paths_.size(); ++i) {
+ NFs::Remove(Paths_[Paths_.size() - i - 1].Path);
+ }
+ }
+
+ private:
+ TVector<TPath> Paths_;
+ THashMap<TString, TPath> Srch_;
+ };
+
+ inline void TestLocal() {
+ TString dirname("." LOCSLASH_S);
+ TDirIterator d(dirname, FTS_NOCHDIR);
+ for (auto it = d.begin(); it != d.end(); ++it) {
+ }
+ }
+
+ inline void TestIt() {
+ TDirHier hier;
+
+ const TString dir = "tmpdir";
+ const TDirHier::TPath path = {dir, 1};
+
+ hier.Add(path);
+
+ for (size_t i = 0; i < 10; ++i) {
+ const TString dir1 = dir + LOCSLASH_C + ToString(i);
+ const TDirHier::TPath path1 = {dir1, 1};
+
+ hier.Add(path1);
+
+ for (size_t j = 0; j < 10; ++j) {
+ const TString subdir2 = ToString(j);
+ const TString dir2 = dir1 + LOCSLASH_C + subdir2;
+ const TDirHier::TPath path2 = {dir2, 1};
+
+ hier.Add(path2);
+
+ for (size_t k = 0; k < 3; ++k) {
+ const TString file = dir2 + LOCSLASH_C + "file" + ToString(k);
+ const TDirHier::TPath fpath = {file, 0};
+
+ hier.Add(fpath);
+ }
+ }
+ }
+
+ TDirIterator d(dir);
+
+ for (auto it = d.begin(); it != d.end(); ++it) {
+ UNIT_ASSERT(hier.Have(it->fts_path, it->fts_info != FTS_F));
+ }
+ }
+
+ inline void TestSkip() {
+ TDirHier hier;
+
+ const TString dir = "tmpdir";
+ const TDirHier::TPath path = {dir, 1};
+
+ hier.Add(path);
+ hier.AddDir(dir + LOCSLASH_C + "dir1");
+ hier.AddDir(dir + LOCSLASH_C + "dir1" + LOCSLASH_C + "dir2");
+ //
+ // Without skip
+ //
+ {
+ TDirIterator di(dir);
+
+ UNIT_ASSERT(di.Next());
+ UNIT_ASSERT_EQUAL(TStringBuf(di.Next()->fts_name), "dir1");
+ UNIT_ASSERT_EQUAL(TStringBuf(di.Next()->fts_name), "dir2");
+ UNIT_ASSERT_EQUAL(TStringBuf(di.Next()->fts_name), "dir2");
+ UNIT_ASSERT_EQUAL(TStringBuf(di.Next()->fts_name), "dir1");
+ UNIT_ASSERT(di.Next());
+ UNIT_ASSERT_EQUAL(di.Next(), nullptr);
+ }
+ //
+ // With skip
+ //
+ {
+ TDirIterator di(dir);
+
+ UNIT_ASSERT(di.Next());
+ auto ent = di.Next();
+ UNIT_ASSERT_EQUAL(TStringBuf(ent->fts_name), "dir1");
+ di.Skip(ent);
+ UNIT_ASSERT_EQUAL(TStringBuf(di.Next()->fts_name), "dir1");
+ UNIT_ASSERT(di.Next());
+ UNIT_ASSERT_EQUAL(di.Next(), nullptr);
+ }
+ }
+
+ inline void TestSort() {
+ TDirHier dh;
+ const TString dir("tmpdir");
+
+ //prepare fs
+ {
+ TMersenne<ui32> rnd;
+ const TString prefixes[] = {
+ "a", "b", "xxx", "111", ""};
+
+ dh.AddDir(dir);
+
+ for (size_t i = 0; i < 100; ++i) {
+ const TString fname = dir + LOCSLASH_C + prefixes[i % Y_ARRAY_SIZE(prefixes)] + ToString(rnd.GenRand());
+
+ dh.AddFile(fname);
+ }
+ }
+
+ TVector<TString> fnames;
+
+ {
+ TDirIterator d(dir, TDirIterator::TOptions().SetSortByName());
+
+ for (auto it = d.begin(); it != d.end(); ++it) {
+ if (it->fts_info == FTS_F) {
+ fnames.push_back(it->fts_name);
+ }
+ }
+ }
+
+ TVector<TString> sorted(fnames);
+ Sort(sorted.begin(), sorted.end());
+
+ UNIT_ASSERT_VALUES_EQUAL(JoinWithNewline(fnames), JoinWithNewline(sorted));
+ }
+
+ inline void TestError() {
+ try {
+ TDirIterator d("./notexistingfilename");
+
+ UNIT_ASSERT(false);
+ } catch (const TDirIterator::TError&) {
+ } catch (...) {
+ UNIT_ASSERT(false);
+ }
+
+ UNIT_ASSERT(true);
+ }
+};
+
+UNIT_TEST_SUITE_REGISTRATION(TDirIteratorTest);