1 #include <iostream>
2 #include <platform/dirutils.h>
3 #include <cstdlib>
4 #include <list>
5 #include <string>
6 #include <cerrno>
7 #include <cstring>
8 #include <sys/stat.h>
9 #include <sys/types.h>
10 #include <stdio.h>
11 
12 #ifdef WIN32
13 #include <windows.h>
14 #include <direct.h>
CreateDirectory(const std::string &dir)15 static bool CreateDirectory(const std::string &dir) {
16     if (_mkdir(dir.c_str()) != 0) {
17         return false;
18     }
19     return true;
20 }
21 
22 #define PATH_SEPARATOR "\\"
23 
24 #else
CreateDirectory(const std::string &dir)25 static bool CreateDirectory(const std::string &dir) {
26    if (mkdir(dir.c_str(), S_IXUSR | S_IWUSR | S_IRUSR) != 0) {
27       return false;
28    }
29    return true;
30 }
31 
32 #define PATH_SEPARATOR "/"
33 
34 #endif
35 
36 #undef NDEBUG
37 #include <cassert>
38 
39 int exit_value = EXIT_SUCCESS;
40 
expect(const std::string &exp, const std::string &val)41 static void expect(const std::string &exp, const std::string &val) {
42    if (exp != val) {
43       std::cerr << "Expected " << exp << " got [" << val << "]" << std::endl;
44       exit_value = EXIT_FAILURE;
45    }
46 }
47 
expect(size_t size, const std::vector<std::string> &vec)48 static void expect(size_t size, const std::vector<std::string> &vec) {
49    if (vec.size() != size) {
50       std::cerr << "Expected vector of " << size
51                 << " elements got [" << vec.size() << "]" << std::endl;
52       exit_value = EXIT_FAILURE;
53    }
54 }
55 
contains(const std::string &val, const std::vector<std::string> &vec)56 static void contains(const std::string &val, const std::vector<std::string> &vec) {
57    std::vector<std::string>::const_iterator ii;
58    for (ii = vec.begin(); ii != vec.end(); ++ii) {
59       if (val == *ii) {
60          return ;
61       }
62    }
63 
64    std::cerr << "Expected vector to contain [" << val << "]" << std::endl;
65    for (ii = vec.begin(); ii != vec.end(); ++ii) {
66       std::cerr << "  -> " << *ii << std::endl;
67    }
68    std::cerr << std::endl;
69    exit_value = EXIT_FAILURE;
70 }
71 
72 static std::list<std::string> vfs;
73 
exists(const std::string &path)74 static bool exists(const std::string &path) {
75    struct stat st;
76    return stat(path.c_str(), &st) == 0;
77 }
78 
testDirname(void)79 static void testDirname(void) {
80    // Check the simple case
81    expect("foo", CouchbaseDirectoryUtilities::dirname("foo\\bar"));
82    expect("foo", CouchbaseDirectoryUtilities::dirname("foo/bar"));
83 
84    // Make sure that we remove double an empty chunk
85    expect("foo", CouchbaseDirectoryUtilities::dirname("foo\\\\bar"));
86    expect("foo", CouchbaseDirectoryUtilities::dirname("foo//bar"));
87 
88    // Make sure that we handle the case without a directory
89    expect(".", CouchbaseDirectoryUtilities::dirname("bar"));
90    expect(".", CouchbaseDirectoryUtilities::dirname(""));
91 
92    // Absolute directories
93    expect("\\", CouchbaseDirectoryUtilities::dirname("\\bar"));
94    expect("\\", CouchbaseDirectoryUtilities::dirname("\\\\bar"));
95    expect("/", CouchbaseDirectoryUtilities::dirname("/bar"));
96    expect("/", CouchbaseDirectoryUtilities::dirname("//bar"));
97 
98    // Test that we work with multiple directories
99    expect("1/2/3/4/5", CouchbaseDirectoryUtilities::dirname("1/2/3/4/5/6"));
100    expect("1\\2\\3\\4\\5", CouchbaseDirectoryUtilities::dirname("1\\2\\3\\4\\5\\6"));
101    expect("1/2\\4/5", CouchbaseDirectoryUtilities::dirname("1/2\\4/5\\6"));
102 }
103 
testBasename(void)104 static void testBasename(void) {
105    expect("bar", CouchbaseDirectoryUtilities::basename("foo\\bar"));
106    expect("bar", CouchbaseDirectoryUtilities::basename("foo/bar"));
107    expect("bar", CouchbaseDirectoryUtilities::basename("foo\\\\bar"));
108    expect("bar", CouchbaseDirectoryUtilities::basename("foo//bar"));
109    expect("bar", CouchbaseDirectoryUtilities::basename("bar"));
110    expect("", CouchbaseDirectoryUtilities::basename(""));
111    expect("bar", CouchbaseDirectoryUtilities::basename("\\bar"));
112    expect("bar", CouchbaseDirectoryUtilities::basename("\\\\bar"));
113    expect("bar", CouchbaseDirectoryUtilities::basename("/bar"));
114    expect("bar", CouchbaseDirectoryUtilities::basename("//bar"));
115    expect("6", CouchbaseDirectoryUtilities::basename("1/2/3/4/5/6"));
116    expect("6", CouchbaseDirectoryUtilities::basename("1\\2\\3\\4\\5\\6"));
117    expect("6", CouchbaseDirectoryUtilities::basename("1/2\\4/5\\6"));
118 }
119 
testFindFilesWithPrefix(void)120 static void testFindFilesWithPrefix(void) {
121    using namespace CouchbaseDirectoryUtilities;
122 
123    std::vector<std::string> vec = findFilesWithPrefix("fs");
124    expect(1, vec);
125    contains("." PATH_SEPARATOR "fs", vec);
126 
127    vec = findFilesWithPrefix("fs", "d");
128    expect(3, vec);
129    contains("fs" PATH_SEPARATOR "d1", vec);
130    contains("fs" PATH_SEPARATOR "d2", vec);
131    contains("fs" PATH_SEPARATOR "d3", vec);
132    vec = findFilesWithPrefix("fs", "1");
133    expect(1, vec);
134    contains("fs" PATH_SEPARATOR "1", vec);
135 
136    vec = findFilesWithPrefix("fs", "");
137    expect(vfs.size() - 1, vec);
138 
139 }
140 
testFindFilesContaining(void)141 static void testFindFilesContaining(void) {
142    using namespace CouchbaseDirectoryUtilities;
143    std::vector<std::string> vec = findFilesContaining("fs", "");
144    expect(vfs.size() - 1, vec);
145 
146    vec = findFilesContaining("fs", "2");
147    expect(7, vec);
148    contains("fs" PATH_SEPARATOR "d2", vec);
149    contains("fs" PATH_SEPARATOR "e2", vec);
150    contains("fs" PATH_SEPARATOR "f2c", vec);
151    contains("fs" PATH_SEPARATOR "g2", vec);
152    contains("fs" PATH_SEPARATOR "2", vec);
153    contains("fs" PATH_SEPARATOR "2c", vec);
154    contains("fs" PATH_SEPARATOR "2d", vec);
155 }
156 
testRemove(void)157 static void testRemove(void) {
158    fclose(fopen("test-file", "w"));
159    if (!CouchbaseDirectoryUtilities::rmrf("test-file")) {
160       std::cerr << "expected to delete existing file" << std::endl;
161    }
162    if (CouchbaseDirectoryUtilities::rmrf("test-file")) {
163       std::cerr << "Didn't expected to delete non-existing file" << std::endl;
164    }
165 
166    if (!CouchbaseDirectoryUtilities::rmrf("fs")) {
167       std::cerr << "Expected to nuke the entire fs directory recursively" << std::endl;
168    }
169 }
170 
main(int argc, char **argv)171 int main(int argc, char **argv)
172 {
173    testDirname();
174    testBasename();
175 
176 
177    vfs.push_back("fs");
178    vfs.push_back("fs/d1");
179    vfs.push_back("fs/d2");
180    vfs.push_back("fs/e2");
181    vfs.push_back("fs/f2c");
182    vfs.push_back("fs/g2");
183    vfs.push_back("fs/d3");
184    vfs.push_back("fs/1");
185    vfs.push_back("fs/2");
186    vfs.push_back("fs/2c");
187    vfs.push_back("fs/2d");
188    vfs.push_back("fs/3");
189 
190    std::list<std::string>::iterator ii;
191    for (ii = vfs.begin(); ii != vfs.end(); ++ii) {
192       if (!CreateDirectory(*ii)) {
193          if (!exists(*ii)) {
194             std::cerr << "Fatal: failed to setup test directory: "
195                       << *ii << std::endl;
196             exit(EXIT_FAILURE);
197          }
198       }
199    }
200 
201    testFindFilesWithPrefix();
202    testFindFilesContaining();
203    testRemove();
204 
205    return exit_value;
206 }
207