-/*
- * cuReTraverser.cpp
- *
- * License: Public domain
- * Do what you want.
- * No warranties and disclaimer of any damages.
- * The latest sources: https://github.com/republib
- */
-
-#include "base/rebase.hpp"
-#include "os/reos.hpp"
-
-static const char* s_empty[] = { NULL };
-// count of seconds from 1.1.1970 until 1.1.1980:
-const int tenYear = (365 * 10 + 2) * 24 * 3600;
-
-class TestReDirTools : public ReTestUnit {
-public:
- TestReDirTools() : ReTestUnit("ReDirTools", __FILE__){
- m_base = testDir();
- ReDirectory::deleteTree(m_base.str());
- m_base.append("dirtool");
- _mkdir(m_base.str(), ALLPERMS);
- m_base.append(OS_SEPARATOR, -1);
- run();
- ReDirectory::deleteTree(m_base.str(), true);
- }
-private:
- ReByteBuffer m_base;
- ReByteBuffer m_buffer;
-private:
- const char* makeDir(const char* relPath){
- m_buffer = m_base;
- m_buffer.append(relPath);
- m_buffer.replaceAll("/", 1, OS_SEPARATOR, -1);
- _mkdir(m_buffer.str(), ALLPERMS);
- struct stat info;
- if (stat(m_buffer.str(), &info) != 0){
- logF(true, "cannot create dir %s", m_buffer.str());
- }
- return m_buffer.str();
- }
- void makeFile(const char* relPath){
- ReByteBuffer path(m_base);
- path.append(relPath);
- path.replaceAll("/", 1, OS_SEPARATOR, -1);
- createFile(path.str(), relPath);
- struct stat info;
- if (stat(path.str(), &info) != 0){
- logF(true, "cannot create file %s", path.str());
- }
- }
- void initTree(){
- makeFile("1.txt");
- makeDir("dir1");
- makeDir("dir2");
- makeDir("dir1/dir1_1");
- makeDir("dir1/dir1_2");
- makeDir("dir1/dir1_2/dir1_2_1");
- makeDir("dir1/cache");
- makeFile("dir1/dir1_2/dir1_2_1/x1.txt");
- makeFile("dir1/dir1_2/dir1_2_1/x2.txt");
- makeFile("dir2/2.x");
- makeFile("dir1/cache/cache.txt");
- }
- void run(){
- initTree();
-
- testBatch();
-
- testToolStatistic();
- testBasic();
- testDirOptions();
- checkSetFilterFromProgramArgs();
- testDirStatistic();
- testCopyFile();
- testList();
- testToolSync();
- testBatch();
- }
- void testList(){
- const char* argv[] = { "list", m_base.str(), NULL };
- ReDirList().run(2, argv);
- }
- int secOfFileTime(ReFileTime_t data){
-#if defined __linux__
- return data.tv_sec;
-#elif defined __WIN32__
- return (int) ReDirStatus_t::filetimeToTime(&data);
-#endif
- }
- void testCopyFile(){
-#if defined __linux__
- ReByteBuffer src(m_base);
- src.append("dir1/dir1_2/dir1_2_1/x1.txt");
- ReByteBuffer trg(testDir());
- trg.append("copy_x1.txt");
- ReByteBuffer buffer;
- buffer.ensureSize(5);
- ReDirSync::copyFile(src.str(), NULL, trg.str(), buffer,
- ReLogger::globalLogger());
- checkFileEqu(src.str(), trg.str());
-#else
- log(false, "testCopyFile not implemented");
-#endif
- }
-
- void checkRelDate(ReFileTime_t absTime, int relTime){
- int diffNow = int(time(NULL) - secOfFileTime(absTime));
- int diff = diffNow + relTime;
- if (diff < 0)
- diff = - diff;
- checkT(diff < 2);
- }
- void testDirOptions(){
- class MyOptions : public ReDirOptions{
- public:
- MyOptions() : ReDirOptions(s_empty, s_empty) {}
- public:
- int count() { return m_countCompoundUsage; }
- const char** usage() { return m_compoundUsage; }
- };
- static const char* usage1[] = { "line1", "line2", NULL };
- static const char* usage2[] = { "x1", "x2", "x3", NULL };
- MyOptions opts;
- opts.initCompoundUsage(sizeof usage1 + sizeof usage2);
- opts.addCompoundUsage(usage1);
- opts.addCompoundUsage(usage2);
- checkEqu(7, opts.count());
- checkEqu("line1", opts.usage()[0]);
- checkEqu("line2", opts.usage()[1]);
- checkEqu("x1", opts.usage()[2]);
- checkEqu("x2", opts.usage()[3]);
- checkEqu("x3", opts.usage()[4]);
-
- // local time: +3600
- const int DIFF = 3600;
- checkEqu(tenYear + 24*60*60 - DIFF, secOfFileTime(opts.checkDate("1980.01.02")));
- checkEqu(tenYear + 24*60*60+3600-DIFF, secOfFileTime(opts.checkDate("1980.01.02/1")));
- checkEqu(tenYear + 24*60*60 + 2*3600 + 33*60 - DIFF, secOfFileTime(opts.checkDate("1980.01.02/02:33")));
- checkRelDate(opts.checkDate("now-3m"), 3*60);
- checkRelDate(opts.checkDate("now-7h"), 7*60*60);
- checkRelDate(opts.checkDate("now-5d"), 5*24*60*60);
-
- checkEqu(125ll, opts.checkSize("125"));
- checkEqu(125ll, opts.checkSize("125b"));
- checkEqu(3000ll, opts.checkSize("3k"));
- checkEqu(3*1024ll, opts.checkSize("3K"));
- checkEqu(4*1000*1000ll, opts.checkSize("4m"));
- checkEqu(4*1024*1024ll, opts.checkSize("4M"));
- checkEqu(5*1000*1000*1000ll, opts.checkSize("5g"));
- checkEqu(5*1024*1024*1024ll, opts.checkSize("5G"));
-
- }
- void checkSetFilterFromProgramArgs(){
- ReDirOptions opts(s_empty, s_empty);
- opts.addStandardFilterOptions();
- const char* argv[] = { "x", "-y1980.01.02", "-o1980.01.03",
- "-D5", "-d1", "-z1k", "-Z2M", "-p;*;-*~"
- };
- ReDirEntryFilter_t filter;
- opts.programArgsChangeable().init(sizeof argv / sizeof argv[0], argv);
- opts.setFilterFromProgramArgs(filter);
- // local time: +3600
- const int DIFF = 3600;
- checkEqu(tenYear + 1*24*3600 - DIFF, secOfFileTime(filter.m_maxAge));
- checkEqu(tenYear + 2*24*3600 - DIFF, secOfFileTime(filter.m_minAge));
- checkEqu(5, (int) filter.m_maxDepth);
- checkEqu(1, (int) filter.m_minDepth);
- checkEqu(1000ll, filter.m_minSize);
- checkEqu(2*1024*1024ll, filter.m_maxSize);
- checkNN(filter.m_nodePatterns);
- checkEqu(";*;-*~", filter.m_nodePatterns->patternString());
- }
- void checkOneFile(const char* node, const char* parent, const ReHashList& hash){
- ReByteBuffer path, expected;
- checkT(hash.get(ReByteBuffer(node), path));
- expected.set(parent, -1);
- if (! expected.endsWith(OS_SEPARATOR))
- expected.append(OS_SEPARATOR);
- if (! path.endsWith(expected.str(), -1))
- checkT(false);
- }
- void testBasic(){
- ReTraverser traverser(m_base.str());
- RePatternList patterns;
- // exclude */cache/*
- ReByteBuffer buffer(";*;-cache");
- patterns.set(buffer.str());
- traverser.setDirPattern(&patterns);
- int level = 0;
- ReDirStatus_t* entry;
- ReHashList hash;
- while( (entry = traverser.rawNextFile(level)) != NULL){
- hash.put(ReByteBuffer(entry->node(), -1), entry->m_path);
- logF(false, "%d: %-12s %2d %s",
- level, entry->node(),
- int(entry->fileSize()),
- entry->m_path.str());
- }
- checkOneFile("x1.txt", "dir1_2_1", hash);
- checkOneFile("x2.txt", "dir1_2_1", hash);
- checkOneFile("dir1_2_1", "dir1_2", hash);
- checkOneFile("dir1_1", "dir1", hash);
- checkOneFile("dir1_2", "dir1", hash);
- checkF(hash.get("cache.txt", buffer));
- }
- void testDirStatistic(){
- ReDirStatistic stat;
- const ReStringList& list = stat.calculate(m_base.str(), 1);
- ReByteBuffer buffer;
- ReByteBuffer expected;
- log(false, list.join("\n", buffer).str());
- checkEqu(3u, list.count());
- // "1 t:\temp\winfried\2\retestunit\dir1\n"
- buffer.set(list.strOf(0), list.strLengthOf(0));
- checkT(buffer.startsWith("1\t"));
- expected.set(m_base.str(), m_base.length()).append("dir1", -1)
- .append(OS_SEPARATOR);
- // .append(OS_SEPARATOR, -1)
- checkT(buffer.endsWith(expected.str()));
-
- buffer.setLength(0);
- const ReStringList& list2 = stat.calculate(m_base.str(), 1, formatWithSizeFilesAndDirs);
- log(false, list2.join("\n", buffer).str());
-
- buffer.set(list.strOf(0), list.strLengthOf(0));
- checkT(buffer.startsWith(" 0.000074 MB 3 4\t"));
- expected.set(m_base.str(), m_base.length()).append("dir1", -1)
- .append(OS_SEPARATOR);
- checkT(buffer.endsWith(expected.str()));
-
- buffer.set(list.strOf(1), list.strLengthOf(1));
- checkT(buffer.startsWith(" 0.000008 MB 1 0\t"));
- expected.set(m_base.str(), m_base.length()).append("dir2", -1)
- .append(OS_SEPARATOR);
- checkT(buffer.endsWith(expected.str()));
-
- buffer.set(list.strOf(2), list.strLengthOf(2));
- checkT(buffer.startsWith(" 0.000087 MB 5 6\t"));
- expected.set(m_base.str(), m_base.length());
- }
- /**
- * Tests a file with a given context.
- *
- * @param filename name of the file to test
- * @param content expected content: each line must contain a '*',
- * separating the start of line and the end of line
- */
- void checkFile(ReByteBuffer& filename, const char* content){
- ReStringList current;
- current.readFromFile(filename.str());
- ReStringList expected;
- expected.split(content, '\n');
- checkEqu(expected.count(), current.count());
- ReByteBuffer line;
- ReStringList cols;
- for (size_t ix = 0; ix < current.count(); ix++){
- line.setLength(0).append(current.strOf(ix), -1);
-#if defined __WIN32__
- line.replaceAll(OS_SEPARATOR, 1, "/", 1);
-#endif
- cols.split(expected.strOf(ix), '*');
- if (! line.startsWith(cols.strOf(0)))
- checkEqu(cols.strOf(0), line.str());
- const char* col2 = cols.strOf(1);
- if (! line.endsWith(col2)){
- checkEqu(col2, line.str());
- }
- }
- }
- void testTouch(){
- ReByteBuffer nameCurrent;
- buildFilename("current", nameCurrent);
- ReByteBuffer optOutput("--output-file=");
- optOutput.append(nameCurrent);
- ReDirTools tools;
- const char* argv[] = { "dt", "touch", "-P;*;-cache", "-tr", "-p;*.txt",
- "-m2015.03.28/10:21:31", optOutput.str(), m_base.str(), NULL };
- tools.main(8, (char**) argv);
-
- checkFile(nameCurrent,
- "2015.03.28 10:21:31 *dirtool/1.txt\n"
- "2015.03.28 10:21:31 *dirtool/dir1/dir1_2/dir1_2_1/x1.txt\n"
- "2015.03.28 10:21:31 *dirtool/dir1/dir1_2/dir1_2_1/x2.txt\n"
- "=== filtered: 3 file(s) 0.000059 MByte 0 dirs(s) */sec\n"
- "=== total: 4 file(s) 0.000067 MByte 6 dirs(s) * sec");
-
- const char* argv2[] = { "dt", "list", "-P;*;-cache", "-tr", "-p;*.txt", "-h",
- optOutput.str(), m_base.str(), NULL };
- tools.main(8, (char**) argv2);
-
- checkFile(nameCurrent,
- " 0.000005 2015.03.28 10:21:31 *dirtool/1.txt\n"
- " 0.000027 2015.03.28 10:21:31 *dirtool/dir1/dir1_2/dir1_2_1/x1.txt\n"
- " 0.000027 2015.03.28 10:21:31 *dirtool/dir1/dir1_2/dir1_2_1/x2.txt\n"
- "=== filtered: 3 file(s) 0.000059 MByte 0 dirs(s) */sec\n"
- "=== total: 4 file(s) 0.000067 MByte 6 dirs(s) * sec");
-
- }
- void testBatch(){
- ReByteBuffer nameCurrent;
- buildFilename("current", nameCurrent);
- ReByteBuffer optOutput("--output-file=");
- optOutput.append(nameCurrent);
- ReDirTools tools;
- const char* argv[] = { "dt", "batch", "-P;*;-cache", "-td", "-cmyscript",
- optOutput.str(), m_base.str(), NULL };
- tools.main(7, (char**) argv);
- ReByteBuffer content("#! /bin/sh*\n"
- "myscript '*dirtool/dir1'\n"
- "myscript '*dirtool/dir2'\n"
- "myscript '*dirtool/dir1/dir1_1'\n"
- "myscript '*dirtool/dir1/dir1_2'\n"
- "myscript '*dirtool/dir1/cache'\n"
- "myscript '*dirtool/dir1/dir1_2/dir1_2_1'\n"
- "# === filtered: 0 file(s) 0.000000 MByte 6 dirs(s) */sec\n"
- "# === total: 4 file(s) 0.000067 MByte 6 dirs(s) * sec");
-#if defined __WIN32__
- content.replaceAll("'", 1, "\"", 1);
-#endif
- checkFile(nameCurrent, content.str());
- }
- void testToolStatistic(){
- ReDirTools tools;
- const char* argv[] = { "dt", "stat", "-P;*;-cache", m_base.str(), "2" };
- tools.main(5, (char**) argv);
- }
- void testToolSync(){
- ReDirTools tools;
- ReByteBuffer source(m_base);
- source.append("dir1");
- ReByteBuffer target(makeDir("synctest"));
- const char* argv[] = { "dt", "sync", "-P;*;-cache", "-p;*.txt",
- source.str(), target.str() };
- tools.main(6, (char**) argv);
- }
-};
-extern void testReDirTools(void);
-
-void testReDirTools(void){
- TestReDirTools unit;
-}
+/*\r
+ * cuReTraverser.cpp\r
+ *\r
+ * License: Public domain\r
+ * Do what you want.\r
+ * No warranties and disclaimer of any damages.\r
+ * The latest sources: https://github.com/republib\r
+ */\r
+\r
+#include "base/rebase.hpp"\r
+#include "os/reos.hpp"\r
+\r
+static const char* s_empty[] = { NULL };\r
+// count of seconds from 1.1.1970 until 1.1.1980:\r
+const int tenYear = (365 * 10 + 2) * 24 * 3600;\r
+\r
+class TestReDirTools : public ReTestUnit {\r
+public:\r
+ TestReDirTools() : ReTestUnit("ReDirTools", __FILE__){\r
+ m_base = testDir();\r
+ ReDirectory::deleteTree(m_base.str());\r
+ m_base.append("dirtool");\r
+ _mkdir(m_base.str(), ALLPERMS);\r
+ m_base.append(OS_SEPARATOR, -1);\r
+ run();\r
+ ReDirectory::deleteTree(m_base.str(), true);\r
+ }\r
+private:\r
+ ReByteBuffer m_base;\r
+ ReByteBuffer m_buffer;\r
+private:\r
+ const char* makeDir(const char* relPath){\r
+ m_buffer = m_base;\r
+ m_buffer.append(relPath);\r
+ m_buffer.replaceAll("/", 1, OS_SEPARATOR, -1);\r
+ _mkdir(m_buffer.str(), ALLPERMS);\r
+ struct stat info;\r
+ if (stat(m_buffer.str(), &info) != 0){\r
+ logF(true, "cannot create dir %s", m_buffer.str());\r
+ }\r
+ return m_buffer.str();\r
+ }\r
+ void makeFile(const char* relPath){\r
+ ReByteBuffer path(m_base);\r
+ path.append(relPath);\r
+ path.replaceAll("/", 1, OS_SEPARATOR, -1);\r
+ createFile(path.str(), relPath);\r
+ struct stat info;\r
+ if (stat(path.str(), &info) != 0){\r
+ logF(true, "cannot create file %s", path.str());\r
+ }\r
+ }\r
+ void initTree(){\r
+ makeFile("1.txt");\r
+ makeDir("dir1");\r
+ makeDir("dir2");\r
+ makeDir("dir1/cache");\r
+ makeDir("dir1/dir1_1");\r
+ makeDir("dir1/dir1_2");\r
+ makeDir("dir1/dir1_2/dir1_2_1");\r
+ makeFile("dir1/dir1_2/dir1_2_1/x1.txt");\r
+ makeFile("dir1/dir1_2/dir1_2_1/x2.txt");\r
+ makeFile("dir2/2.x");\r
+ makeFile("dir1/cache/cache.txt");\r
+ }\r
+ void run(){\r
+ initTree();\r
+\r
+ testBatch();\r
+\r
+ testToolStatistic();\r
+ testBasic();\r
+ testDirOptions();\r
+ checkSetFilterFromProgramArgs();\r
+ testDirStatistic();\r
+ testCopyFile();\r
+ testList();\r
+ testToolSync();\r
+ testBatch();\r
+ }\r
+ void testList(){\r
+ const char* argv[] = { "list", m_base.str(), NULL };\r
+ ReDirList().run(2, argv);\r
+ }\r
+ int secOfFileTime(ReFileTime_t data){\r
+#if defined __linux__\r
+ return data.tv_sec;\r
+#elif defined __WIN32__\r
+ return (int) ReDirStatus_t::filetimeToTime(&data);\r
+#endif\r
+ }\r
+ void testCopyFile(){\r
+#if defined __linux__\r
+ ReByteBuffer src(m_base);\r
+ src.append("dir1/dir1_2/dir1_2_1/x1.txt");\r
+ ReByteBuffer trg(testDir());\r
+ trg.append("copy_x1.txt");\r
+ ReByteBuffer buffer;\r
+ buffer.ensureSize(5);\r
+ ReDirSync::copyFile(src.str(), NULL, trg.str(), buffer,\r
+ ReLogger::globalLogger());\r
+ checkFileEqu(src.str(), trg.str());\r
+#else\r
+ log(false, "testCopyFile not implemented");\r
+#endif\r
+ }\r
+\r
+ void checkRelDate(ReFileTime_t absTime, int relTime){\r
+ int diffNow = int(time(NULL) - secOfFileTime(absTime));\r
+ int diff = diffNow * relTime < 0 ? diffNow + relTime : diffNow - relTime;\r
+ if (diff < 0)\r
+ diff = - diff;\r
+ checkT(diff < 2);\r
+ }\r
+ void testDirOptions(){\r
+ class MyOptions : public ReDirOptions{\r
+ public:\r
+ MyOptions() : ReDirOptions(s_empty, s_empty) {}\r
+ public:\r
+ int count() { return m_countCompoundUsage; }\r
+ const char** usage() { return m_compoundUsage; }\r
+ };\r
+ static const char* usage1[] = { "line1", "line2", NULL };\r
+ static const char* usage2[] = { "x1", "x2", "x3", NULL };\r
+ MyOptions opts;\r
+ opts.initCompoundUsage(sizeof usage1 + sizeof usage2);\r
+ opts.addCompoundUsage(usage1);\r
+ opts.addCompoundUsage(usage2);\r
+ checkEqu(7, opts.count());\r
+ checkEqu("line1", opts.usage()[0]);\r
+ checkEqu("line2", opts.usage()[1]);\r
+ checkEqu("x1", opts.usage()[2]);\r
+ checkEqu("x2", opts.usage()[3]);\r
+ checkEqu("x3", opts.usage()[4]);\r
+\r
+ // local time: +3600\r
+ const int DIFF = 3600;\r
+ checkEqu(tenYear + 24*60*60 - DIFF, secOfFileTime(opts.checkDate("1980.01.02")));\r
+ checkEqu(tenYear + 24*60*60+3600-DIFF, secOfFileTime(opts.checkDate("1980.01.02/1")));\r
+ checkEqu(tenYear + 24*60*60 + 2*3600 + 33*60 - DIFF, secOfFileTime(opts.checkDate("1980.01.02/02:33")));\r
+ checkRelDate(opts.checkDate("now-3m"), 3*60);\r
+ checkRelDate(opts.checkDate("now-7h"), 7*60*60);\r
+ checkRelDate(opts.checkDate("now-5d"), 5*24*60*60);\r
+\r
+ checkEqu(125ll, opts.checkSize("125"));\r
+ checkEqu(125ll, opts.checkSize("125b"));\r
+ checkEqu(3000ll, opts.checkSize("3k"));\r
+ checkEqu(3*1024ll, opts.checkSize("3K"));\r
+ checkEqu(4*1000*1000ll, opts.checkSize("4m"));\r
+ checkEqu(4*1024*1024ll, opts.checkSize("4M"));\r
+ checkEqu(5*1000*1000*1000ll, opts.checkSize("5g"));\r
+ checkEqu(5*1024*1024*1024ll, opts.checkSize("5G"));\r
+\r
+ }\r
+ void checkSetFilterFromProgramArgs(){\r
+ ReDirOptions opts(s_empty, s_empty);\r
+ opts.addStandardFilterOptions();\r
+ const char* argv[] = { "x", "-y1980.01.02", "-o1980.01.03",\r
+ "-D5", "-d1", "-z1k", "-Z2M", "-p;*;-*~"\r
+ };\r
+ ReDirEntryFilter_t filter;\r
+ opts.programArgsChangeable().init(sizeof argv / sizeof argv[0], argv);\r
+ opts.setFilterFromProgramArgs(filter);\r
+ // local time: +3600\r
+ const int DIFF = 3600;\r
+ checkEqu(tenYear + 1*24*3600 - DIFF, secOfFileTime(filter.m_maxAge));\r
+ checkEqu(tenYear + 2*24*3600 - DIFF, secOfFileTime(filter.m_minAge));\r
+ checkEqu(5, (int) filter.m_maxDepth);\r
+ checkEqu(1, (int) filter.m_minDepth);\r
+ checkEqu(1000ll, filter.m_minSize);\r
+ checkEqu(2*1024*1024ll, filter.m_maxSize);\r
+ checkNN(filter.m_nodePatterns);\r
+ checkEqu(";*;-*~", filter.m_nodePatterns->patternString());\r
+ }\r
+ void checkOneFile(const char* node, const char* parent, const ReHashList& hash){\r
+ ReByteBuffer path, expected;\r
+ checkT(hash.get(ReByteBuffer(node), path));\r
+ expected.set(parent, -1);\r
+ if (! expected.endsWith(OS_SEPARATOR))\r
+ expected.append(OS_SEPARATOR);\r
+ if (! path.endsWith(expected.str(), -1))\r
+ checkT(false); \r
+ }\r
+ void testBasic(){\r
+ ReTraverser traverser(m_base.str());\r
+ RePatternList patterns;\r
+ // exclude */cache/*\r
+ ReByteBuffer buffer(";*;-cache");\r
+ patterns.set(buffer.str());\r
+ traverser.setDirPattern(&patterns);\r
+ int level = 0;\r
+ ReDirStatus_t* entry;\r
+ ReHashList hash;\r
+ while( (entry = traverser.rawNextFile(level)) != NULL){\r
+ hash.put(ReByteBuffer(entry->node(), -1), entry->m_path);\r
+ logF(false, "%d: %-12s %2d %s",\r
+ level, entry->node(),\r
+ int(entry->fileSize()),\r
+ entry->m_path.str());\r
+ }\r
+ checkOneFile("x1.txt", "dir1_2_1", hash);\r
+ checkOneFile("x2.txt", "dir1_2_1", hash);\r
+ checkOneFile("dir1_2_1", "dir1_2", hash);\r
+ checkOneFile("dir1_1", "dir1", hash);\r
+ checkOneFile("dir1_2", "dir1", hash);\r
+ checkF(hash.get("cache.txt", buffer));\r
+ }\r
+ void testDirStatistic(){\r
+ ReDirStatistic stat;\r
+ const ReStringList& list = stat.calculate(m_base.str(), 1);\r
+ ReByteBuffer buffer;\r
+ ReByteBuffer expected;\r
+ log(false, list.join("\n", buffer).str());\r
+ checkEqu(3u, list.count());\r
+ // "1 t:\temp\winfried\2\retestunit\dir1\n"\r
+ buffer.set(list.strOf(0), list.strLengthOf(0));\r
+ checkT(buffer.startsWith("1\t"));\r
+ expected.set(m_base.str(), m_base.length()).append("dir1", -1)\r
+ .append(OS_SEPARATOR);\r
+ // .append(OS_SEPARATOR, -1)\r
+ checkT(buffer.endsWith(expected.str()));\r
+ \r
+ buffer.setLength(0);\r
+ const ReStringList& list2 = stat.calculate(m_base.str(), 1, formatWithSizeFilesAndDirs);\r
+ log(false, list2.join("\n", buffer).str());\r
+ \r
+ buffer.set(list.strOf(0), list.strLengthOf(0));\r
+ checkT(buffer.startsWith(" 0.000074 MB 3 4\t"));\r
+ expected.set(m_base.str(), m_base.length()).append("dir1", -1)\r
+ .append(OS_SEPARATOR);\r
+ checkT(buffer.endsWith(expected.str()));\r
+\r
+ buffer.set(list.strOf(1), list.strLengthOf(1));\r
+ checkT(buffer.startsWith(" 0.000008 MB 1 0\t"));\r
+ expected.set(m_base.str(), m_base.length()).append("dir2", -1)\r
+ .append(OS_SEPARATOR);\r
+ checkT(buffer.endsWith(expected.str()));\r
+\r
+ buffer.set(list.strOf(2), list.strLengthOf(2));\r
+ checkT(buffer.startsWith(" 0.000087 MB 5 6\t"));\r
+ expected.set(m_base.str(), m_base.length());\r
+ }\r
+ /**\r
+ * Tests a file with a given context.\r
+ *\r
+ * @param filename name of the file to test\r
+ * @param content expected content: each line must contain a '*',\r
+ * separating the start of line and the end of line\r
+ */\r
+ void checkFile(ReByteBuffer& filename, const char* content){\r
+ ReStringList current;\r
+ current.readFromFile(filename.str());\r
+ ReStringList expected;\r
+ expected.split(content, '\n');\r
+ checkEqu(expected.count(), current.count());\r
+ ReByteBuffer line;\r
+ ReStringList cols;\r
+ for (size_t ix = 0; ix < current.count(); ix++){\r
+ line.setLength(0).append(current.strOf(ix), -1);\r
+#if defined __WIN32__\r
+ line.replaceAll("/", 1, OS_SEPARATOR, 1);\r
+#endif\r
+ cols.split(expected.strOf(ix), '*');\r
+ const char* col1 = cols.strOf(0);\r
+ if (! line.startsWith(col1))\r
+ checkEqu(col1, line.str());\r
+ const char* col2 = cols.strOf(1);\r
+ if (! line.endsWith(col2)){\r
+ checkEqu(col2, line.str());\r
+ }\r
+ }\r
+ }\r
+ void testTouch(){\r
+ ReByteBuffer nameCurrent;\r
+ buildFilename("current", nameCurrent);\r
+ ReByteBuffer optOutput("--output-file=");\r
+ optOutput.append(nameCurrent);\r
+ ReDirTools tools;\r
+ const char* argv[] = { "dt", "touch", "-P;*;-cache", "-tr", "-p;*.txt",\r
+ "-m2015.03.28/10:21:31", optOutput.str(), m_base.str(), NULL };\r
+ tools.main(8, (char**) argv);\r
+\r
+ checkFile(nameCurrent,\r
+ "2015.03.28 10:21:31 *dirtool/1.txt\n"\r
+ "2015.03.28 10:21:31 *dirtool/dir1/dir1_2/dir1_2_1/x1.txt\n"\r
+ "2015.03.28 10:21:31 *dirtool/dir1/dir1_2/dir1_2_1/x2.txt\n"\r
+ "=== filtered: 3 file(s) 0.000059 MByte 0 dirs(s) */sec\n"\r
+ "=== total: 4 file(s) 0.000067 MByte 6 dirs(s) * sec");\r
+\r
+ const char* argv2[] = { "dt", "list", "-P;*;-cache", "-tr", "-p;*.txt", "-h",\r
+ optOutput.str(), m_base.str(), NULL };\r
+ tools.main(8, (char**) argv2);\r
+\r
+ checkFile(nameCurrent,\r
+ " 0.000005 2015.03.28 10:21:31 *dirtool/1.txt\n"\r
+ " 0.000027 2015.03.28 10:21:31 *dirtool/dir1/dir1_2/dir1_2_1/x1.txt\n"\r
+ " 0.000027 2015.03.28 10:21:31 *dirtool/dir1/dir1_2/dir1_2_1/x2.txt\n"\r
+ "=== filtered: 3 file(s) 0.000059 MByte 0 dirs(s) */sec\n"\r
+ "=== total: 4 file(s) 0.000067 MByte 6 dirs(s) * sec");\r
+\r
+ }\r
+ void testBatch(){\r
+ ReByteBuffer nameCurrent;\r
+ buildFilename("current", nameCurrent);\r
+ ReByteBuffer optOutput("--output-file=");\r
+ optOutput.append(nameCurrent);\r
+ ReDirTools tools;\r
+ const char* argv[] = { "dt", "batch", "-P;*;-cache", "-td", "-cmyscript",\r
+ optOutput.str(), m_base.str(), NULL };\r
+ tools.main(7, (char**) argv);\r
+#if defined __linux__\r
+ static const char* content = "#! /bin/sh*\n"\r
+ "myscript '*dirtool/dir1'\n"\r
+ "myscript '*dirtool/dir2'\n"\r
+ "myscript '*dirtool/dir1/dir1_1'\n"\r
+ "myscript '*dirtool/dir1/dir1_2'\n"\r
+ "myscript '*dirtool/dir1/cache'\n"\r
+ "myscript '*dirtool/dir1/dir1_2/dir1_2_1'\n"\r
+ "# === filtered: 0 file(s) 0.000000 MByte 6 dirs(s) */sec\n"\r
+ "# === total: 4 file(s) 0.000067 MByte 6 dirs(s) * sec";\r
+#elif defined __WIN32__\r
+ static const char* content = "rem this batch is created by*dirtool\n"\r
+ "call myscript *dirtool\\dir1\"\n"\r
+ "call myscript *dirtool\\dir2\"\n"\r
+ "call myscript *dirtool\\dir1\\cache\"\n"\r
+ "call myscript *dirtool\\dir1\\dir1_1\"\n"\r
+ "call myscript *dirtool\\dir1\\dir1_2\"\n"\r
+ "call myscript *dirtool\\dir1\\dir1_2\\dir1_2_1\"\n"\r
+ "rem === filtered: 0 file(s) 0.000000 MByte 6 dirs(s) *sec\n"\r
+ "rem === total: 4 file(s) 0.000067 MByte 6 dirs(s) * sec";\r
+#endif\r
+ checkFile(nameCurrent, content);\r
+ }\r
+ void testToolStatistic(){\r
+ ReDirTools tools;\r
+ const char* argv[] = { "dt", "stat", "-P;*;-cache", m_base.str(), "2" };\r
+ tools.main(5, (char**) argv);\r
+ }\r
+ void testToolSync(){\r
+ ReDirTools tools;\r
+ ReByteBuffer source(m_base);\r
+ source.append("dir1");\r
+ ReByteBuffer target(testDir());\r
+ target.ensureLastChar(OS_SEPARATOR_CHAR);\r
+ target.append("synctest", -1);\r
+ _mkdir(target.str(), ALLPERMS);\r
+ const char* argv[] = { "dt", "sync", "-P;*;-cache", "-p;*.txt",\r
+ source.str(), target.str() };\r
+ tools.main(6, (char**) argv);\r
+ }\r
+};\r
+extern void testReDirTools(void);\r
+\r
+void testReDirTools(void){\r
+ TestReDirTools unit;\r
+}\r