Skip to content

Commit 74cac72

Browse files
committed
Add more tests for IFileTree::glob and fix issues.
1 parent e4c526c commit 74cac72

File tree

2 files changed

+228
-51
lines changed

2 files changed

+228
-51
lines changed

src/ifiletree.cpp

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -212,27 +212,25 @@ namespace
212212
ifiletree_glob_impl(std::shared_ptr<const FileTreeEntry> entry,
213213
std::span<std::pair<QString, QRegularExpression>> const& patterns)
214214
{
215+
if (patterns.size() == 0) {
216+
co_return;
217+
}
218+
215219
if (patterns[0].first == "**") {
216220
//
217-
if (patterns.size() == 1) {
218-
if (entry->isDir()) {
221+
if (patterns.size() != 1) {
222+
co_yield std::ranges::elements_of(
223+
ifiletree_glob_impl(entry, patterns.subspan(1)));
224+
}
219225

226+
if (entry->isDir()) {
227+
if (patterns.size() == 1) {
220228
co_yield entry;
221-
222-
// if we have more patterns, we need to go deeper
223-
for (const auto& child : *entry->astree()) {
224-
co_yield std::ranges::elements_of(ifiletree_glob_impl(child, patterns));
225-
}
226229
}
227-
} else {
228-
co_yield std::ranges::elements_of(
229-
ifiletree_glob_impl(entry, patterns.subspan(1)));
230230

231-
if (entry->isDir()) {
232-
for (const auto& child : *entry->astree()) {
233-
const auto subPatterns = child->isDir() ? patterns : patterns.subspan(1);
234-
co_yield std::ranges::elements_of(ifiletree_glob_impl(child, subPatterns));
235-
}
231+
for (const auto& child : *entry->astree()) {
232+
const auto subPatterns = child->isDir() ? patterns : patterns.subspan(1);
233+
co_yield std::ranges::elements_of(ifiletree_glob_impl(child, subPatterns));
236234
}
237235
}
238236

@@ -242,6 +240,11 @@ namespace
242240
co_yield entry;
243241

244242
} else if (entry->isDir()) {
243+
244+
if (patterns.size() == 2 && patterns[1].first == "**") {
245+
co_yield entry;
246+
}
247+
245248
// if we have more patterns, we need to go deeper
246249
for (const auto& child : *entry->astree()) {
247250
co_yield std::ranges::elements_of(
@@ -257,14 +260,14 @@ namespace
257260
// replace \\ by /
258261
pattern = pattern.trimmed().replace("\\", "/");
259262

263+
// reduce **/** to ** when possible
264+
pattern = pattern.replace(QRegularExpression("(\\*\\*/)*\\*\\*"), "**");
265+
260266
// handle special case
261267
if (pattern == "**") {
262268
co_yield tree;
263269
}
264270

265-
// reduce **/** to ** when possible
266-
pattern = pattern.replace(QRegularExpression("(\\*\\*/)*\\*\\*"), "**");
267-
268271
// split pattern into blocks
269272
std::vector<std::pair<QString, QRegularExpression>> patterns;
270273
for (const auto& part : pattern.split("/")) {

tests/test_ifiletree.cpp

Lines changed: 207 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -921,46 +921,220 @@ TEST(IFileTreeTest, TreeGlobOperations)
921921
{
922922
using entrySet = std::unordered_set<std::shared_ptr<const FileTreeEntry>>;
923923

924-
auto fileTree = FileListTree::makeTree({{"a/", true},
925-
{"a/g.t", false},
926-
{"b", true},
927-
{"b/u", false},
928-
{"b/v", false},
929-
{"c.x", false},
930-
{"d.y", false},
931-
{"e/q/c.t", false},
932-
{"e/q/m.x", false},
933-
{"e/q/p", true}});
924+
{
925+
auto fileTree = FileListTree::makeTree({{"a/", true},
926+
{"a/g.t", false},
927+
{"b", true},
928+
{"b/u", false},
929+
{"b/v", false},
930+
{"c.x", false},
931+
{"d.y", false},
932+
{"e/q/c.t", false},
933+
{"e/q/m.x", false},
934+
{"e/q/p", true}});
934935

935-
auto map = createMapping(fileTree);
936+
auto map = createMapping(fileTree);
936937

937-
entrySet entries, expected;
938+
entrySet entries, expected;
938939

939-
entries = fileTree->glob("*") | std::ranges::to<std::unordered_set>();
940-
expected = {map["a"], map["b"], map["c.x"], map["d.y"], map["e"]};
941-
EXPECT_EQ(entries, expected);
940+
entries = fileTree->glob("*") | std::ranges::to<std::unordered_set>();
941+
expected = {map["a"], map["b"], map["c.x"], map["d.y"], map["e"]};
942+
EXPECT_EQ(entries, expected);
942943

943-
entries = fileTree->glob("**") | std::ranges::to<std::unordered_set>();
944-
expected = {fileTree, map["a"], map["b"], map["e"], map["e/q"], map["e/q/p"]};
945-
EXPECT_EQ(entries, expected);
944+
entries = fileTree->glob("**") | std::ranges::to<std::unordered_set>();
945+
expected = {fileTree, map["a"], map["b"], map["e"], map["e/q"], map["e/q/p"]};
946+
EXPECT_EQ(entries, expected);
946947

947-
entries = fileTree->glob("*.x") | std::ranges::to<std::unordered_set>();
948-
expected = {map["c.x"]};
949-
EXPECT_EQ(entries, expected);
948+
entries = fileTree->glob("*.x") | std::ranges::to<std::unordered_set>();
949+
expected = {map["c.x"]};
950+
EXPECT_EQ(entries, expected);
950951

951-
entries = fileTree->glob("**/*.x") | std::ranges::to<std::unordered_set>();
952-
expected = {map["c.x"], map["e/q/m.x"]};
953-
EXPECT_EQ(entries, expected);
952+
entries = fileTree->glob("**/*.x") | std::ranges::to<std::unordered_set>();
953+
expected = {map["c.x"], map["e/q/m.x"]};
954+
EXPECT_EQ(entries, expected);
954955

955-
entries = fileTree->glob("*.t") | std::ranges::to<std::unordered_set>();
956-
expected = {};
957-
EXPECT_EQ(entries, expected);
956+
entries = fileTree->glob("*.t") | std::ranges::to<std::unordered_set>();
957+
expected = {};
958+
EXPECT_EQ(entries, expected);
958959

959-
entries = fileTree->glob("**/*.t") | std::ranges::to<std::unordered_set>();
960-
expected = {map["a/g.t"], map["e/q/c.t"]};
961-
EXPECT_EQ(entries, expected);
960+
entries = fileTree->glob("**/*.t") | std::ranges::to<std::unordered_set>();
961+
expected = {map["a/g.t"], map["e/q/c.t"]};
962+
EXPECT_EQ(entries, expected);
962963

963-
entries = fileTree->glob("a/*") | std::ranges::to<std::unordered_set>();
964-
expected = {map["a/g.t"]};
965-
EXPECT_EQ(entries, expected);
964+
entries = fileTree->glob("a/*") | std::ranges::to<std::unordered_set>();
965+
expected = {map["a/g.t"]};
966+
EXPECT_EQ(entries, expected);
967+
}
968+
969+
{
970+
auto fileTree = FileListTree::makeTree({{"aq.js", false},
971+
{"bb", true},
972+
{"cm.tx", false},
973+
{"dp.js", false},
974+
{"ev", false},
975+
{"go.ya", false},
976+
{"gw.md", false},
977+
{"hh", false},
978+
{"hl", true},
979+
{"in", true},
980+
{"mz", true},
981+
{"sc", true},
982+
{"bb/ce.cp", false},
983+
{"bb/cm.tx", false},
984+
{"bb/gw", true},
985+
{"bb/iw.cp", false},
986+
{"bb/js", true},
987+
{"bb/px.cp", false},
988+
{"hl/ds.in", false},
989+
{"in/nu", true},
990+
{"mz/tu.js", false},
991+
{"sc/cm.tx", false},
992+
{"sc/cw.ts", false},
993+
{"sc/cz.rc", false},
994+
{"sc/dr.cp", false},
995+
{"sc/hh.cp", false},
996+
{"sc/kn.ui", false},
997+
{"sc/lr.cp", false},
998+
{"sc/nd.o", false},
999+
{"sc/nv.o", false},
1000+
{"sc/rv.ui", false},
1001+
{"sc/tv.h", false},
1002+
{"bb/gw/cp.qm", false},
1003+
{"bb/gw/hq.qm", false},
1004+
{"bb/gw/pu.ts", false},
1005+
{"bb/gw/tu.ts", false},
1006+
{"bb/js/cm.tx", false},
1007+
{"bb/js/co.cp", false},
1008+
{"in/nu/el.h", false},
1009+
{"in/nu/fj.h", false},
1010+
{"in/nu/lw", true},
1011+
{"in/nu/xx", true},
1012+
{"in/nu/lw/cp.h", false},
1013+
{"in/nu/lw/go.h", false},
1014+
{"in/nu/xx/ap.h", false},
1015+
{"in/nu/xx/qz.h", false}});
1016+
1017+
auto map = createMapping(fileTree);
1018+
1019+
entrySet entries, expected;
1020+
1021+
entries = fileTree->glob("*.h") | std::ranges::to<std::unordered_set>();
1022+
expected = {};
1023+
EXPECT_EQ(entries, expected);
1024+
1025+
entries = fileTree->glob("*") | std::ranges::to<std::unordered_set>();
1026+
expected = {map.at("aq.js"), map.at("bb"), map.at("cm.tx"), map.at("dp.js"),
1027+
map.at("ev"), map.at("go.ya"), map.at("gw.md"), map.at("hh"),
1028+
map.at("hl"), map.at("in"), map.at("mz"), map.at("sc")};
1029+
EXPECT_EQ(entries, expected);
1030+
1031+
entries = fileTree->glob("*/*") | std::ranges::to<std::unordered_set>();
1032+
expected = {
1033+
map.at("bb/ce.cp"), map.at("bb/cm.tx"), map.at("bb/gw"), map.at("bb/iw.cp"),
1034+
map.at("bb/js"), map.at("bb/px.cp"), map.at("hl/ds.in"), map.at("in/nu"),
1035+
map.at("mz/tu.js"), map.at("sc/cm.tx"), map.at("sc/cw.ts"), map.at("sc/cz.rc"),
1036+
map.at("sc/dr.cp"), map.at("sc/hh.cp"), map.at("sc/kn.ui"), map.at("sc/lr.cp"),
1037+
map.at("sc/nd.o"), map.at("sc/nv.o"), map.at("sc/rv.ui"), map.at("sc/tv.h")};
1038+
EXPECT_EQ(entries, expected);
1039+
1040+
entries = fileTree->glob("*/*/*") | std::ranges::to<std::unordered_set>();
1041+
expected = {map.at("bb/gw/cp.qm"), map.at("bb/gw/hq.qm"), map.at("bb/gw/pu.ts"),
1042+
map.at("bb/gw/tu.ts"), map.at("bb/js/cm.tx"), map.at("bb/js/co.cp"),
1043+
map.at("in/nu/el.h"), map.at("in/nu/fj.h"), map.at("in/nu/lw"),
1044+
map.at("in/nu/xx")};
1045+
EXPECT_EQ(entries, expected);
1046+
1047+
entries = fileTree->glob("**") | std::ranges::to<std::unordered_set>();
1048+
expected = {fileTree, map.at("bb"), map.at("bb/gw"), map.at("bb/js"),
1049+
map.at("hl"), map.at("in"), map.at("in/nu"), map.at("in/nu/lw"),
1050+
map.at("in/nu/xx"), map.at("mz"), map.at("sc")};
1051+
EXPECT_EQ(entries, expected);
1052+
1053+
entries = fileTree->glob("**/*") | std::ranges::to<std::unordered_set>();
1054+
expected = {map.at("aq.js"),
1055+
map.at("bb"),
1056+
map.at("cm.tx"),
1057+
map.at("dp.js"),
1058+
map.at("ev"),
1059+
map.at("go.ya"),
1060+
map.at("gw.md"),
1061+
map.at("hh"),
1062+
map.at("hl"),
1063+
map.at("in"),
1064+
map.at("mz"),
1065+
map.at("sc"),
1066+
map.at("bb/ce.cp"),
1067+
map.at("bb/cm.tx"),
1068+
map.at("bb/gw"),
1069+
map.at("bb/iw.cp"),
1070+
map.at("bb/js"),
1071+
map.at("bb/px.cp"),
1072+
map.at("bb/gw/cp.qm"),
1073+
map.at("bb/gw/hq.qm"),
1074+
map.at("bb/gw/pu.ts"),
1075+
map.at("bb/gw/tu.ts"),
1076+
map.at("bb/js/cm.tx"),
1077+
map.at("bb/js/co.cp"),
1078+
map.at("hl/ds.in"),
1079+
map.at("in/nu"),
1080+
map.at("in/nu/el.h"),
1081+
map.at("in/nu/fj.h"),
1082+
map.at("in/nu/lw"),
1083+
map.at("in/nu/xx"),
1084+
map.at("in/nu/lw/cp.h"),
1085+
map.at("in/nu/lw/go.h"),
1086+
map.at("in/nu/xx/ap.h"),
1087+
map.at("in/nu/xx/qz.h"),
1088+
map.at("mz/tu.js"),
1089+
map.at("sc/cm.tx"),
1090+
map.at("sc/cw.ts"),
1091+
map.at("sc/cz.rc"),
1092+
map.at("sc/dr.cp"),
1093+
map.at("sc/hh.cp"),
1094+
map.at("sc/kn.ui"),
1095+
map.at("sc/lr.cp"),
1096+
map.at("sc/nd.o"),
1097+
map.at("sc/nv.o"),
1098+
map.at("sc/rv.ui"),
1099+
map.at("sc/tv.h")};
1100+
EXPECT_EQ(entries, expected);
1101+
1102+
entries = fileTree->glob("**/cm.tx") | std::ranges::to<std::unordered_set>();
1103+
expected = {map.at("cm.tx"), map.at("bb/cm.tx"), map.at("bb/js/cm.tx"),
1104+
map.at("sc/cm.tx")};
1105+
EXPECT_EQ(entries, expected);
1106+
1107+
entries = fileTree->glob("**/sc/**/cm.tx") | std::ranges::to<std::unordered_set>();
1108+
expected = {map.at("sc/cm.tx")};
1109+
EXPECT_EQ(entries, expected);
1110+
1111+
entries = fileTree->glob("**/sc") | std::ranges::to<std::unordered_set>();
1112+
expected = {map.at("sc")};
1113+
EXPECT_EQ(entries, expected);
1114+
1115+
entries = fileTree->glob("in/**") | std::ranges::to<std::unordered_set>();
1116+
expected = {map.at("in"), map.at("in/nu"), map.at("in/nu/lw"), map.at("in/nu/xx")};
1117+
EXPECT_EQ(entries, expected);
1118+
1119+
entries = fileTree->glob("in/**/**") | std::ranges::to<std::unordered_set>();
1120+
expected = {map.at("in"), map.at("in/nu"), map.at("in/nu/lw"), map.at("in/nu/xx")};
1121+
EXPECT_EQ(entries, expected);
1122+
1123+
entries = fileTree->glob("in/*/*") | std::ranges::to<std::unordered_set>();
1124+
expected = {map.at("in/nu/el.h"), map.at("in/nu/fj.h"), map.at("in/nu/lw"),
1125+
map.at("in/nu/xx")};
1126+
EXPECT_EQ(entries, expected);
1127+
1128+
entries = fileTree->glob("in/*/*.h") | std::ranges::to<std::unordered_set>();
1129+
expected = {map.at("in/nu/el.h"), map.at("in/nu/fj.h")};
1130+
EXPECT_EQ(entries, expected);
1131+
1132+
entries = fileTree->glob("sc/**/*.cp") | std::ranges::to<std::unordered_set>();
1133+
expected = {map.at("sc/dr.cp"), map.at("sc/hh.cp"), map.at("sc/lr.cp")};
1134+
EXPECT_EQ(entries, expected);
1135+
1136+
entries = fileTree->glob("sc/**/n*.o") | std::ranges::to<std::unordered_set>();
1137+
expected = {map.at("sc/nd.o"), map.at("sc/nv.o")};
1138+
EXPECT_EQ(entries, expected);
1139+
}
9661140
}

0 commit comments

Comments
 (0)