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