1 //  path_test program  -----------------------------------------------------------------//
2 
3 //  Copyright Beman Dawes 2002, 2008
4 //  Copyright Vladimir Prus 2002
5 
6 //  Use, modification, and distribution is subject to the Boost Software
7 //  License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8 //  http://www.boost.org/LICENSE_1_0.txt)
9 
10 //  See library home page at http://www.boost.org/libs/filesystem
11 
12 //  basic_path's stem(), extension(), and replace_extension() tests are based
13 //  on basename(), extension(), and change_extension() tests from the original
14 //  convenience_test.cpp by Vladimir Prus.
15 
16 //--------------------------------------------------------------------------------------//
17 //                                                                                      //
18 //                                     Caution                                          //
19 //                                                                                      //
20 //  The class path relational operators (==, !=, <, etc.) on Windows treat slash and    //
21 //  backslash as equal. Thus any tests on Windows where the difference between slash    //
22 //  and backslash is significant should compare strings rather than paths.              //
23 //                                                                                      //
24 //  BOOST_TEST(path == path)                     // '\\' and '/' are equal              //
25 //  BOOST_TEST(path == convertable to string)    // '\\' and '/' are equal              //
26 //  PATH_TEST_EQ(path, path)                     // '\\' and '/' are equal              //
27 //                                                                                      //
28 //  BOOST_TEST(path.string() == path.string())   // '\\' and '/' are not equal          //
29 //  BOOST_TEST(path.string() ==                                                         //
30 //               convertable to string)          // '\\' and '/' are not equal          //
31 //  PATH_TEST_EQ(path.string(),                                                         //
32 //                convertable to string)         // '\\' and '/' are not equal          //
33 //                                                                                      //
34 //  The last of these is often what is needed, so the PATH_TEST_EQ macro is provided.   //
35 //  It converts its first argument to a path, and then performs a .string() on it,      //
36 //  eliminating much boilerplate .string() or even path(...).string() code.             //
37 //                                                                                      //
38 //  PATH_TEST_EQ(path, convertable to string)    // '\\' and '/' are not equal          //
39 //                                                                                      //
40 //--------------------------------------------------------------------------------------//
41 
42 #include <boost/config/warning_disable.hpp>
43 
44 //  See deprecated_test for tests of deprecated features
45 #ifndef BOOST_FILESYSTEM_NO_DEPRECATED
46 #  define BOOST_FILESYSTEM_NO_DEPRECATED
47 #endif
48 #ifndef BOOST_SYSTEM_NO_DEPRECATED
49 #  define BOOST_SYSTEM_NO_DEPRECATED
50 #endif
51 
52 #include <boost/filesystem/operations.hpp>
53 
54 #include <boost/config.hpp>
55 # if defined( BOOST_NO_STD_WSTRING )
56 #   error Configuration not supported: Boost.Filesystem V3 and later requires std::wstring support
57 # endif
58 
59 #include <boost/utility.hpp>
60 #include <iostream>
61 #include <sstream>
62 #include <string>
63 #include <vector>
64 #include <cstring>
65 #include <cassert>
66 #include <boost/detail/lightweight_test.hpp>
67 #include <boost/detail/lightweight_main.hpp>
68 
69 namespace fs = boost::filesystem;
70 using boost::filesystem::path;
71 using boost::next;
72 using boost::prior;
73 
74 #ifdef BOOST_WINDOWS_API
75 # define BOOST_DIR_SEP "\\"
76 #else
77 # define BOOST_DIR_SEP "/"
78 #endif
79 
80 #define PATH_TEST_EQ(a, b) check(a, b, __FILE__, __LINE__)
81 
82 namespace
83 {
84   std::string platform(BOOST_PLATFORM);
85 
check(const fs::path & source,const std::string & expected,const char * file,int line)86   void check(const fs::path & source,
87               const std::string & expected, const char* file, int line)
88   {
89     if (source.string() == expected)
90       return;
91 
92     std::cout << file
93               << '(' << line << "): source: \"" << source.string()
94               << "\" != expected: \"" << expected
95               << "\"" << std::endl;
96 
97     ++::boost::detail::test_errors();
98   }
99 
100   path p1("fe/fi/fo/fum");
101   path p2(p1);
102   path p3;
103   path p4("foobar");
104   path p5;
105 
106   //  exception_tests  -----------------------------------------------------------------//
107 
exception_tests()108   void exception_tests()
109   {
110     std::cout << "exception_tests..." << std::endl;
111     const std::string str_1("string-1");
112     boost::system::error_code ec(12345, boost::system::system_category());
113     try { throw fs::filesystem_error(str_1, ec); }
114     catch (const fs::filesystem_error & ex)
115     {
116       //std::cout << ex.what() << "*" << std::endl;
117       //BOOST_TEST(std::strcmp(ex.what(),
118       //  "string-1: Unknown error") == 0);
119       BOOST_TEST(ex.code() == ec);
120     }
121 
122     try { throw fs::filesystem_error(str_1, "p1", "p2", ec); }
123     catch (const fs::filesystem_error & ex)
124     {
125       //std::cout << ex.what() << "*" << std::endl;
126       //BOOST_TEST(std::strcmp(ex.what(),
127       //  "string-1: Unknown error: \"p1\", \"p2\"") == 0);
128       BOOST_TEST(ex.code() == ec);
129       BOOST_TEST(ex.path1() == "p1");
130       BOOST_TEST(ex.path2() == "p2");
131     }
132   }
133 
134   //  overload_tests  ------------------------------------------------------------------//
135 
136   // These verify various overloads don't cause compiler errors
137   // They pre-date operations_unit_test.cpp
138 
overload_tests()139   void overload_tests()
140   {
141     std::cout << "overload_tests..." << std::endl;
142 
143     fs::exists(p1);
144     fs::exists("foo");
145     fs::exists(std::string("foo"));
146 
147     fs::exists(p1 / path("foo"));
148     fs::exists(p1 / "foo");
149     fs::exists(p1 / std::string("foo"));
150 
151     fs::exists("foo" / p1);
152     fs::exists(std::string("foo") / p1);
153 
154     p4 /= path("foo");
155     p4 /= "foo";
156     p4 /= std::string("foo");
157   }
158 
159   //  iterator_tests  ------------------------------------------------------------------//
160 
iterator_tests()161   void iterator_tests()
162   {
163     std::cout << "iterator_tests..." << std::endl;
164 
165     path itr_ck = "";
166     path::const_iterator itr = itr_ck.begin();
167     BOOST_TEST(itr == itr_ck.end());
168 
169     itr_ck = "/";
170     itr = itr_ck.begin();
171     BOOST_TEST(itr->string() == "/");
172     BOOST_TEST(++itr == itr_ck.end());
173     BOOST_TEST((--itr)->string() == "/");
174 
175     itr_ck = "foo";
176     BOOST_TEST(*itr_ck.begin() == std::string("foo"));
177     BOOST_TEST(boost::next(itr_ck.begin()) == itr_ck.end());
178     BOOST_TEST(*boost::prior(itr_ck.end()) == std::string("foo"));
179     BOOST_TEST(boost::prior(itr_ck.end()) == itr_ck.begin());
180 
181     itr_ck = path("/foo");
182     BOOST_TEST((itr_ck.begin())->string() == "/");
183     BOOST_TEST(*boost::next(itr_ck.begin()) == std::string("foo"));
184     BOOST_TEST(boost::next(boost::next(itr_ck.begin())) == itr_ck.end());
185     BOOST_TEST(boost::next(itr_ck.begin()) == boost::prior(itr_ck.end()));
186     BOOST_TEST(*boost::prior(itr_ck.end()) == std::string("foo"));
187     BOOST_TEST(*boost::prior(boost::prior(itr_ck.end())) == std::string("/"));
188     BOOST_TEST(boost::prior(boost::prior(itr_ck.end())) == itr_ck.begin());
189 
190     itr_ck = "/foo/bar";
191     itr = itr_ck.begin();
192     BOOST_TEST(itr->string() == "/");
193     BOOST_TEST(*++itr == std::string("foo"));
194     BOOST_TEST(*++itr == std::string("bar"));
195     BOOST_TEST(++itr == itr_ck.end());
196     PATH_TEST_EQ(*--itr, "bar");
197     PATH_TEST_EQ(*--itr, "foo");
198     PATH_TEST_EQ(*--itr, "/");
199 
200     itr_ck = "../f"; // previously failed due to short name bug
201     itr = itr_ck.begin();
202     PATH_TEST_EQ(itr->string(), "..");
203     PATH_TEST_EQ(*++itr, "f");
204     BOOST_TEST(++itr == itr_ck.end());
205     PATH_TEST_EQ(*--itr, "f");
206     PATH_TEST_EQ(*--itr, "..");
207 
208     // POSIX says treat "/foo/bar/" as "/foo/bar/."
209     itr_ck = "/foo/bar/";
210     itr = itr_ck.begin();
211     PATH_TEST_EQ(itr->string(), "/");
212     PATH_TEST_EQ(*++itr, "foo");
213     BOOST_TEST(itr != itr_ck.end());
214     PATH_TEST_EQ(*++itr, "bar");
215     BOOST_TEST(itr != itr_ck.end());
216     PATH_TEST_EQ(*++itr, ".");
217     BOOST_TEST(itr != itr_ck.end());  // verify the . isn't also seen as end()
218     BOOST_TEST(++itr == itr_ck.end());
219     PATH_TEST_EQ(*--itr, ".");
220     PATH_TEST_EQ(*--itr, "bar");
221     PATH_TEST_EQ(*--itr, "foo");
222     PATH_TEST_EQ(*--itr, "/");
223 
224     // POSIX says treat "/f/b/" as "/f/b/."
225     itr_ck = "/f/b/";
226     itr = itr_ck.begin();
227     PATH_TEST_EQ(itr->string(), "/");
228     PATH_TEST_EQ(*++itr, "f");
229     PATH_TEST_EQ(*++itr, "b");
230     PATH_TEST_EQ(*++itr, ".");
231     BOOST_TEST(itr != itr_ck.end());  // verify the . isn't also seen as end()
232     BOOST_TEST(++itr == itr_ck.end());
233     PATH_TEST_EQ(*--itr, ".");
234     PATH_TEST_EQ(*--itr, "b");
235     PATH_TEST_EQ(*--itr, "f");
236     PATH_TEST_EQ(*--itr, "/");
237 
238     // POSIX says treat "a/b/" as "a/b/."
239     // Although similar to the prior test case, this failed the ". isn't end" test due to
240     // a bug while the prior case did not fail.
241     itr_ck = "a/b/";
242     itr = itr_ck.begin();
243     PATH_TEST_EQ(*itr, "a");
244     PATH_TEST_EQ(*++itr, "b");
245     PATH_TEST_EQ(*++itr, ".");
246     BOOST_TEST(itr != itr_ck.end());  // verify the . isn't also seen as end()
247     BOOST_TEST(++itr == itr_ck.end());
248     PATH_TEST_EQ(*--itr, ".");
249     PATH_TEST_EQ(*--itr, "b");
250     PATH_TEST_EQ(*--itr, "a");
251 
252     itr_ck = "//net";
253     itr = itr_ck.begin();
254     // two leading slashes are permitted by POSIX (as implementation defined),
255     // while for Windows it is always well defined (as a network name)
256     PATH_TEST_EQ(itr->string(), "//net");
257     BOOST_TEST(++itr == itr_ck.end());
258     PATH_TEST_EQ(*--itr, "//net");
259 
260     itr_ck = "//net/";
261     itr = itr_ck.begin();
262     PATH_TEST_EQ(itr->string(), "//net");
263     PATH_TEST_EQ(*++itr, "/");
264     BOOST_TEST(++itr == itr_ck.end());
265     PATH_TEST_EQ(*--itr, "/");
266     PATH_TEST_EQ(*--itr, "//net");
267 
268     itr_ck = "//foo///bar///";
269     itr = itr_ck.begin();
270     PATH_TEST_EQ(itr->string(), "//foo");
271     PATH_TEST_EQ(*++itr, "/");
272     PATH_TEST_EQ(*++itr, "bar");
273     PATH_TEST_EQ(*++itr, ".");
274     BOOST_TEST(++itr == itr_ck.end());
275     PATH_TEST_EQ(*--itr, ".");
276     PATH_TEST_EQ(*--itr, "bar");
277     PATH_TEST_EQ(*--itr, "/");
278     PATH_TEST_EQ(*--itr, "//foo");
279 
280     itr_ck = "///foo///bar///";
281     itr = itr_ck.begin();
282     // three or more leading slashes are to be treated as a single slash
283     PATH_TEST_EQ(itr->string(), "/");
284     PATH_TEST_EQ(*++itr, "foo");
285     PATH_TEST_EQ(*++itr, "bar");
286     PATH_TEST_EQ(*++itr, ".");
287     BOOST_TEST(++itr == itr_ck.end());
288     PATH_TEST_EQ(*--itr, ".");
289     PATH_TEST_EQ(*--itr, "bar");
290     PATH_TEST_EQ(*--itr, "foo");
291     PATH_TEST_EQ(*--itr, "/");
292 
293     if (platform == "Windows")
294     {
295       itr_ck = "c:/";
296       itr = itr_ck.begin();
297       PATH_TEST_EQ(itr->string(), "c:");
298       PATH_TEST_EQ(*++itr, std::string("/"));
299       BOOST_TEST(++itr == itr_ck.end());
300       PATH_TEST_EQ(*--itr, "/");
301       PATH_TEST_EQ(*--itr, "c:");
302 
303       itr_ck = "c:\\";
304       itr = itr_ck.begin();
305       PATH_TEST_EQ(itr->string(), "c:");
306       PATH_TEST_EQ(*++itr, "/");  // test that iteration returns generic format
307       BOOST_TEST(++itr == itr_ck.end());
308       PATH_TEST_EQ(*--itr, "/");  // test that iteration returns generic format
309       PATH_TEST_EQ(*--itr, "c:");
310 
311       itr_ck = "c:/foo";
312       itr = itr_ck.begin();
313       BOOST_TEST(*itr == std::string("c:"));
314       BOOST_TEST(*++itr == std::string("/"));
315       BOOST_TEST(*++itr == std::string("foo"));
316       BOOST_TEST(++itr == itr_ck.end());
317       BOOST_TEST(*--itr == std::string("foo"));
318       BOOST_TEST((--itr)->string() == "/");
319       BOOST_TEST(*--itr == std::string("c:"));
320 
321       itr_ck = "c:\\foo";
322       itr = itr_ck.begin();
323       BOOST_TEST(*itr == std::string("c:"));
324       BOOST_TEST(*++itr == std::string("\\"));
325       BOOST_TEST(*++itr == std::string("foo"));
326       BOOST_TEST(++itr == itr_ck.end());
327       BOOST_TEST(*--itr == std::string("foo"));
328       BOOST_TEST(*--itr == std::string("\\"));
329       BOOST_TEST(*--itr == std::string("c:"));
330 
331       itr_ck = "\\\\\\foo\\\\\\bar\\\\\\";
332       itr = itr_ck.begin();
333       // three or more leading slashes are to be treated as a single slash
334       PATH_TEST_EQ(itr->string(), "/");
335       PATH_TEST_EQ(*++itr, "foo");
336       PATH_TEST_EQ(*++itr, "bar");
337       PATH_TEST_EQ(*++itr, ".");
338       BOOST_TEST(++itr == itr_ck.end());
339       PATH_TEST_EQ(*--itr, ".");
340       PATH_TEST_EQ(*--itr, "bar");
341       PATH_TEST_EQ(*--itr, "foo");
342       PATH_TEST_EQ(*--itr, "/");
343 
344       itr_ck = "c:foo";
345       itr = itr_ck.begin();
346       BOOST_TEST(*itr == std::string("c:"));
347       BOOST_TEST(*++itr == std::string("foo"));
348       BOOST_TEST(++itr == itr_ck.end());
349       BOOST_TEST(*--itr == std::string("foo"));
350       BOOST_TEST(*--itr == std::string("c:"));
351 
352       itr_ck = "c:foo/";
353       itr = itr_ck.begin();
354       BOOST_TEST(*itr == std::string("c:"));
355       BOOST_TEST(*++itr == std::string("foo"));
356       BOOST_TEST(*++itr == std::string("."));
357       BOOST_TEST(++itr == itr_ck.end());
358       BOOST_TEST(*--itr == std::string("."));
359       BOOST_TEST(*--itr == std::string("foo"));
360       BOOST_TEST(*--itr == std::string("c:"));
361 
362       itr_ck = path("c:");
363       BOOST_TEST(*itr_ck.begin() == std::string("c:"));
364       BOOST_TEST(next(itr_ck.begin()) == itr_ck.end());
365       BOOST_TEST(prior(itr_ck.end()) == itr_ck.begin());
366       BOOST_TEST(*prior(itr_ck.end()) == std::string("c:"));
367 
368       itr_ck = path("c:/");
369       BOOST_TEST(*itr_ck.begin() == std::string("c:"));
370       BOOST_TEST(*next(itr_ck.begin()) == std::string("/"));
371       BOOST_TEST(next(next(itr_ck.begin())) == itr_ck.end());
372       BOOST_TEST(prior(prior(itr_ck.end())) == itr_ck.begin());
373       BOOST_TEST(*prior(itr_ck.end()) == std::string("/"));
374       BOOST_TEST(*prior(prior(itr_ck.end())) == std::string("c:"));
375 
376       itr_ck = path("c:foo");
377       BOOST_TEST(*itr_ck.begin() == std::string("c:"));
378       BOOST_TEST(*next(itr_ck.begin()) == std::string("foo"));
379       BOOST_TEST(next(next(itr_ck.begin())) == itr_ck.end());
380       BOOST_TEST(prior(prior(itr_ck.end())) == itr_ck.begin());
381       BOOST_TEST(*prior(itr_ck.end()) == std::string("foo"));
382       BOOST_TEST(*prior(prior(itr_ck.end())) == std::string("c:"));
383 
384       itr_ck = path("c:/foo");
385       BOOST_TEST(*itr_ck.begin() == std::string("c:"));
386       BOOST_TEST(*next(itr_ck.begin()) == std::string("/"));
387       BOOST_TEST(*next(next(itr_ck.begin())) == std::string("foo"));
388       BOOST_TEST(next(next(next(itr_ck.begin()))) == itr_ck.end());
389       BOOST_TEST(prior(prior(prior(itr_ck.end()))) == itr_ck.begin());
390       BOOST_TEST(*prior(itr_ck.end()) == std::string("foo"));
391       BOOST_TEST(*prior(prior(itr_ck.end())) == std::string("/"));
392       BOOST_TEST(*prior(prior(prior(itr_ck.end()))) == std::string("c:"));
393 
394       itr_ck = path("//net");
395       BOOST_TEST(*itr_ck.begin() == std::string("//net"));
396       BOOST_TEST(next(itr_ck.begin()) == itr_ck.end());
397       BOOST_TEST(prior(itr_ck.end()) == itr_ck.begin());
398       BOOST_TEST(*prior(itr_ck.end()) == std::string("//net"));
399 
400       itr_ck = path("//net/");
401       PATH_TEST_EQ(itr_ck.begin()->string(), "//net");
402       PATH_TEST_EQ(next(itr_ck.begin())->string(), "/");
403       BOOST_TEST(next(next(itr_ck.begin())) == itr_ck.end());
404       BOOST_TEST(prior(prior(itr_ck.end())) == itr_ck.begin());
405       PATH_TEST_EQ(prior(itr_ck.end())->string(), "/");
406       PATH_TEST_EQ(prior(prior(itr_ck.end()))->string(), "//net");
407 
408       itr_ck = path("//net/foo");
409       BOOST_TEST(*itr_ck.begin() == std::string("//net"));
410       BOOST_TEST(*next(itr_ck.begin()) == std::string("/"));
411       BOOST_TEST(*next(next(itr_ck.begin())) == std::string("foo"));
412       BOOST_TEST(next(next(next(itr_ck.begin()))) == itr_ck.end());
413       BOOST_TEST(prior(prior(prior(itr_ck.end()))) == itr_ck.begin());
414       BOOST_TEST(*prior(itr_ck.end()) == std::string("foo"));
415       BOOST_TEST(*prior(prior(itr_ck.end())) == std::string("/"));
416       BOOST_TEST(*prior(prior(prior(itr_ck.end()))) == std::string("//net"));
417 
418       itr_ck = path("prn:");
419       BOOST_TEST(*itr_ck.begin() == std::string("prn:"));
420       BOOST_TEST(next(itr_ck.begin()) == itr_ck.end());
421       BOOST_TEST(prior(itr_ck.end()) == itr_ck.begin());
422       BOOST_TEST(*prior(itr_ck.end()) == std::string("prn:"));
423     }
424     else
425     {
426       itr_ck = "///";
427       itr = itr_ck.begin();
428       PATH_TEST_EQ(itr->string(),  "/");
429       BOOST_TEST(++itr == itr_ck.end());
430     }
431   }
432 
433   //  non_member_tests  ----------------------------------------------------------------//
434 
non_member_tests()435   void non_member_tests()
436   {
437     std::cout << "non_member_tests..." << std::endl;
438 
439     // test non-member functions, particularly operator overloads
440 
441     path e, e2;
442     std::string es, es2;
443     char ecs[] = "";
444     char ecs2[] = "";
445 
446     char acs[] = "a";
447     std::string as(acs);
448     path a(as);
449 
450     char acs2[] = "a";
451     std::string as2(acs2);
452     path a2(as2);
453 
454     char bcs[] = "b";
455     std::string bs(bcs);
456     path b(bs);
457 
458     // swap
459     a.swap(b);
460     BOOST_TEST(a.string() == "b");
461     BOOST_TEST(b.string() == "a");
462     fs::swap(a, b);
463     BOOST_TEST(a.string() == "a");
464     BOOST_TEST(b.string() == "b");
465 
466     // probe operator /
467     PATH_TEST_EQ(path("") / ".", ".");
468     PATH_TEST_EQ(path("") / "..", "..");
469     if (platform == "Windows")
470     {
471       BOOST_TEST(path("foo\\bar") == "foo/bar");
472       BOOST_TEST((b / a).native() == path("b\\a").native());
473       BOOST_TEST((bs / a).native() == path("b\\a").native());
474       BOOST_TEST((bcs / a).native() == path("b\\a").native());
475       BOOST_TEST((b / as).native() == path("b\\a").native());
476       BOOST_TEST((b / acs).native() == path("b\\a").native());
477       PATH_TEST_EQ(path("a") / "b", "a\\b");
478       PATH_TEST_EQ(path("..") / "", "..");
479       PATH_TEST_EQ(path("foo") / path("bar"), "foo\\bar"); // path arg
480       PATH_TEST_EQ(path("foo") / "bar", "foo\\bar");       // const char* arg
481       PATH_TEST_EQ(path("foo") / path("woo/bar").filename(), "foo\\bar"); // const std::string & arg
482       PATH_TEST_EQ("foo" / path("bar"), "foo\\bar");
483       PATH_TEST_EQ(path("..") / ".." , "..\\..");
484       PATH_TEST_EQ(path("/") / ".." , "/..");
485       PATH_TEST_EQ(path("/..") / ".." , "/..\\..");
486       PATH_TEST_EQ(path("..") / "foo" , "..\\foo");
487       PATH_TEST_EQ(path("foo") / ".." , "foo\\..");
488       PATH_TEST_EQ(path("..") / "f" , "..\\f");
489       PATH_TEST_EQ(path("/..") / "f" , "/..\\f");
490       PATH_TEST_EQ(path("f") / ".." , "f\\..");
491       PATH_TEST_EQ(path("foo") / ".." / ".." , "foo\\..\\..");
492       PATH_TEST_EQ(path("foo") / ".." / ".." / ".." , "foo\\..\\..\\..");
493       PATH_TEST_EQ(path("f") / ".." / "b" , "f\\..\\b");
494       PATH_TEST_EQ(path("foo") / ".." / "bar" , "foo\\..\\bar");
495       PATH_TEST_EQ(path("foo") / "bar" / ".." , "foo\\bar\\..");
496       PATH_TEST_EQ(path("foo") / "bar" / ".." / "..", "foo\\bar\\..\\..");
497       PATH_TEST_EQ(path("foo") / "bar" / ".." / "blah", "foo\\bar\\..\\blah");
498       PATH_TEST_EQ(path("f") / "b" / ".." , "f\\b\\..");
499       PATH_TEST_EQ(path("f") / "b" / ".." / "a", "f\\b\\..\\a");
500       PATH_TEST_EQ(path("foo") / "bar" / "blah" / ".." / "..", "foo\\bar\\blah\\..\\..");
501       PATH_TEST_EQ(path("foo") / "bar" / "blah" / ".." / ".." / "bletch", "foo\\bar\\blah\\..\\..\\bletch");
502 
503       PATH_TEST_EQ(path(".") / "foo", ".\\foo");
504       PATH_TEST_EQ(path(".") / "..", ".\\..");
505       PATH_TEST_EQ(path("foo") / ".", "foo\\.");
506       PATH_TEST_EQ(path("..") / ".", "..\\.");
507       PATH_TEST_EQ(path(".") / ".", ".\\.");
508       PATH_TEST_EQ(path(".") / "." / ".", ".\\.\\.");
509       PATH_TEST_EQ(path(".") / "foo" / ".", ".\\foo\\.");
510       PATH_TEST_EQ(path("foo") / "." / "bar", "foo\\.\\bar");
511       PATH_TEST_EQ(path("foo") / "." / ".", "foo\\.\\.");
512       PATH_TEST_EQ(path("foo") / "." / "..", "foo\\.\\..");
513       PATH_TEST_EQ(path(".") / "." / "..", ".\\.\\..");
514       PATH_TEST_EQ(path(".") / ".." / ".", ".\\..\\.");
515       PATH_TEST_EQ(path("..") / "." / ".", "..\\.\\.");
516     }
517     else  // POSIX
518     {
519       PATH_TEST_EQ(b / a, "b/a");
520       PATH_TEST_EQ(bs / a, "b/a");
521       PATH_TEST_EQ(bcs / a, "b/a");
522       PATH_TEST_EQ(b / as, "b/a");
523       PATH_TEST_EQ(b / acs, "b/a");
524       PATH_TEST_EQ(path("a") / "b", "a/b");
525       PATH_TEST_EQ(path("..") / "", "..");
526       PATH_TEST_EQ(path("") / "..", "..");
527       PATH_TEST_EQ(path("foo") / path("bar"), "foo/bar"); // path arg
528       PATH_TEST_EQ(path("foo") / "bar", "foo/bar");       // const char* arg
529       PATH_TEST_EQ(path("foo") / path("woo/bar").filename(), "foo/bar"); // const std::string & arg
530       PATH_TEST_EQ("foo" / path("bar"), "foo/bar");
531       PATH_TEST_EQ(path("..") / ".." , "../..");
532       PATH_TEST_EQ(path("/") / ".." , "/..");
533       PATH_TEST_EQ(path("/..") / ".." , "/../..");
534       PATH_TEST_EQ(path("..") / "foo" , "../foo");
535       PATH_TEST_EQ(path("foo") / ".." , "foo/..");
536       PATH_TEST_EQ(path("..") / "f" , "../f");
537       PATH_TEST_EQ(path("/..") / "f" , "/../f");
538       PATH_TEST_EQ(path("f") / ".." , "f/..");
539       PATH_TEST_EQ(path("foo") / ".." / ".." , "foo/../..");
540       PATH_TEST_EQ(path("foo") / ".." / ".." / ".." , "foo/../../..");
541       PATH_TEST_EQ(path("f") / ".." / "b" , "f/../b");
542       PATH_TEST_EQ(path("foo") / ".." / "bar" , "foo/../bar");
543       PATH_TEST_EQ(path("foo") / "bar" / ".." , "foo/bar/..");
544       PATH_TEST_EQ(path("foo") / "bar" / ".." / "..", "foo/bar/../..");
545       PATH_TEST_EQ(path("foo") / "bar" / ".." / "blah", "foo/bar/../blah");
546       PATH_TEST_EQ(path("f") / "b" / ".." , "f/b/..");
547       PATH_TEST_EQ(path("f") / "b" / ".." / "a", "f/b/../a");
548       PATH_TEST_EQ(path("foo") / "bar" / "blah" / ".." / "..", "foo/bar/blah/../..");
549       PATH_TEST_EQ(path("foo") / "bar" / "blah" / ".." / ".." / "bletch", "foo/bar/blah/../../bletch");
550 
551       PATH_TEST_EQ(path(".") / "foo", "./foo");
552       PATH_TEST_EQ(path(".") / "..", "./..");
553       PATH_TEST_EQ(path("foo") / ".", "foo/.");
554       PATH_TEST_EQ(path("..") / ".", "../.");
555       PATH_TEST_EQ(path(".") / ".", "./.");
556       PATH_TEST_EQ(path(".") / "." / ".", "././.");
557       PATH_TEST_EQ(path(".") / "foo" / ".", "./foo/.");
558       PATH_TEST_EQ(path("foo") / "." / "bar", "foo/./bar");
559       PATH_TEST_EQ(path("foo") / "." / ".", "foo/./.");
560       PATH_TEST_EQ(path("foo") / "." / "..", "foo/./..");
561       PATH_TEST_EQ(path(".") / "." / "..", "././..");
562       PATH_TEST_EQ(path(".") / ".." / ".", "./../.");
563       PATH_TEST_EQ(path("..") / "." / ".", ".././.");
564     }
565 
566     // probe operator <
567     BOOST_TEST(!(e < e2));
568     BOOST_TEST(!(es < e2));
569     BOOST_TEST(!(ecs < e2));
570     BOOST_TEST(!(e < es2));
571     BOOST_TEST(!(e < ecs2));
572 
573     BOOST_TEST(e < a);
574     BOOST_TEST(es < a);
575     BOOST_TEST(ecs < a);
576     BOOST_TEST(e < as);
577     BOOST_TEST(e < acs);
578 
579     BOOST_TEST(a < b);
580     BOOST_TEST(as < b);
581     BOOST_TEST(acs < b);
582     BOOST_TEST(a < bs);
583     BOOST_TEST(a < bcs);
584 
585     BOOST_TEST(!(a < a2));
586     BOOST_TEST(!(as < a2));
587     BOOST_TEST(!(acs < a2));
588     BOOST_TEST(!(a < as2));
589     BOOST_TEST(!(a < acs2));
590 
591     // make sure basic_path overloads don't conflict with std::string overloads
592 
593     BOOST_TEST(!(as < as));
594     BOOST_TEST(!(as < acs));
595     BOOST_TEST(!(acs < as));
596 
597     // character set reality check before lexicographical tests
598     BOOST_TEST(std::string("a.b") < std::string("a/b"));
599     // verify compare is actually lexicographical
600     BOOST_TEST(path("a/b") < path("a.b"));
601     BOOST_TEST(path("a/b") == path("a///b"));
602     BOOST_TEST(path("a/b/") == path("a/b/."));
603     BOOST_TEST(path("a/b") != path("a/b/"));
604 
605     // make sure the derivative operators also work
606 
607     BOOST_TEST(b > a);
608     BOOST_TEST(b > as);
609     BOOST_TEST(b > acs);
610     BOOST_TEST(bs > a);
611     BOOST_TEST(bcs > a);
612 
613     BOOST_TEST(!(a2 > a));
614     BOOST_TEST(!(a2 > as));
615     BOOST_TEST(!(a2 > acs));
616     BOOST_TEST(!(as2 > a));
617     BOOST_TEST(!(acs2 > a));
618 
619     BOOST_TEST(a <= b);
620     BOOST_TEST(as <= b);
621     BOOST_TEST(acs <= b);
622     BOOST_TEST(a <= bs);
623     BOOST_TEST(a <= bcs);
624 
625     BOOST_TEST(a <= a2);
626     BOOST_TEST(as <= a2);
627     BOOST_TEST(acs <= a2);
628     BOOST_TEST(a <= as2);
629     BOOST_TEST(a <= acs2);
630 
631     BOOST_TEST(b >= a);
632     BOOST_TEST(bs >= a);
633     BOOST_TEST(bcs >= a);
634     BOOST_TEST(b >= as);
635     BOOST_TEST(b >= acs);
636 
637     BOOST_TEST(a2 >= a);
638     BOOST_TEST(as2 >= a);
639     BOOST_TEST(acs2 >= a);
640     BOOST_TEST(a2 >= as);
641     BOOST_TEST(a2 >= acs);
642 
643     //  operator == and != are implemented separately, so test separately
644 
645     path p101("fe/fi/fo/fum");
646     path p102(p101);
647     path p103("fe/fi/fo/fumm");
648     BOOST_TEST(p101.string() != p103.string());
649 
650     // check each overload
651     BOOST_TEST(p101 != p103);
652     BOOST_TEST(p101 != p103.string());
653     BOOST_TEST(p101 != p103.string().c_str());
654     BOOST_TEST(p101.string() != p103);
655     BOOST_TEST(p101.string().c_str() != p103);
656 
657     p103 = p102;
658     BOOST_TEST(p101.string() == p103.string());
659 
660     // check each overload
661     BOOST_TEST(p101 == p103);
662     BOOST_TEST(p101 == p103.string());
663     BOOST_TEST(p101 == p103.string().c_str());
664     BOOST_TEST(p101.string() == p103);
665     BOOST_TEST(p101.string().c_str() == p103);
666 
667     if (platform == "Windows")
668     {
669       std::cout << "Windows relational tests..." << std::endl;
670       path p10 ("c:\\file");
671       path p11 ("c:/file");
672       // check each overload
673       BOOST_TEST(p10.generic_string() == p11.generic_string());
674       BOOST_TEST(p10 == p11);
675       BOOST_TEST(p10 == p11.string());
676       BOOST_TEST(p10 == p11.string().c_str());
677       BOOST_TEST(p10.string() == p11);
678       BOOST_TEST(p10.string().c_str() == p11);
679       BOOST_TEST(p10 == L"c:\\file");
680       BOOST_TEST(p10 == L"c:/file");
681       BOOST_TEST(p11 == L"c:\\file");
682       BOOST_TEST(p11 == L"c:/file");
683       BOOST_TEST(L"c:\\file" == p10);
684       BOOST_TEST(L"c:/file" == p10);
685       BOOST_TEST(L"c:\\file" == p11);
686       BOOST_TEST(L"c:/file" == p11);
687 
688       BOOST_TEST(!(p10.generic_string() != p11.generic_string()));
689       BOOST_TEST(!(p10 != p11));
690       BOOST_TEST(!(p10 != p11.string()));
691       BOOST_TEST(!(p10 != p11.string().c_str()));
692       BOOST_TEST(!(p10.string() != p11));
693       BOOST_TEST(!(p10.string().c_str() != p11));
694       BOOST_TEST(!(p10 != L"c:\\file"));
695       BOOST_TEST(!(p10 != L"c:/file"));
696       BOOST_TEST(!(p11 != L"c:\\file"));
697       BOOST_TEST(!(p11 != L"c:/file"));
698       BOOST_TEST(!(L"c:\\file" != p10));
699       BOOST_TEST(!(L"c:/file" != p10));
700       BOOST_TEST(!(L"c:\\file" != p11));
701       BOOST_TEST(!(L"c:/file" != p11));
702 
703       BOOST_TEST(!(p10.string() < p11.string()));
704       BOOST_TEST(!(p10 < p11));
705       BOOST_TEST(!(p10 < p11.string()));
706       BOOST_TEST(!(p10 < p11.string().c_str()));
707       BOOST_TEST(!(p10.string() < p11));
708       BOOST_TEST(!(p10.string().c_str() < p11));
709       BOOST_TEST(!(p10 < L"c:\\file"));
710       BOOST_TEST(!(p10 < L"c:/file"));
711       BOOST_TEST(!(p11 < L"c:\\file"));
712       BOOST_TEST(!(p11 < L"c:/file"));
713       BOOST_TEST(!(L"c:\\file" < p10));
714       BOOST_TEST(!(L"c:/file" < p10));
715       BOOST_TEST(!(L"c:\\file" < p11));
716       BOOST_TEST(!(L"c:/file" < p11));
717 
718       BOOST_TEST(!(p10.generic_string() > p11.generic_string()));
719       BOOST_TEST(!(p10 > p11));
720       BOOST_TEST(!(p10 > p11.string()));
721       BOOST_TEST(!(p10 > p11.string().c_str()));
722       BOOST_TEST(!(p10.string() > p11));
723       BOOST_TEST(!(p10.string().c_str() > p11));
724       BOOST_TEST(!(p10 > L"c:\\file"));
725       BOOST_TEST(!(p10 > L"c:/file"));
726       BOOST_TEST(!(p11 > L"c:\\file"));
727       BOOST_TEST(!(p11 > L"c:/file"));
728       BOOST_TEST(!(L"c:\\file" > p10));
729       BOOST_TEST(!(L"c:/file" > p10));
730       BOOST_TEST(!(L"c:\\file" > p11));
731       BOOST_TEST(!(L"c:/file" > p11));
732     }
733   }
734 
735   //  query_and_decomposition_tests  ---------------------------------------------------//
736   //
737   //  remove_filename() is also tested here, because its specification depends on
738   //  a decomposition function.
739 
query_and_decomposition_tests()740   void query_and_decomposition_tests()
741   {
742     std::cout << "query_and_decomposition_tests..." << std::endl;
743 
744     // stem() tests not otherwise covered
745     BOOST_TEST(path("b").stem() == "b");
746     BOOST_TEST(path("a/b.txt").stem() == "b");
747     BOOST_TEST(path("a/b.").stem() == "b");
748     BOOST_TEST(path("a.b.c").stem() == "a.b");
749     BOOST_TEST(path("a.b.c.").stem() == "a.b.c");
750 
751     // extension() tests not otherwise covered
752     BOOST_TEST(path("a/b").extension() == "");
753     BOOST_TEST(path("a.b/c").extension() == "");
754     BOOST_TEST(path("a/b.txt").extension() == ".txt");
755     BOOST_TEST(path("a/b.").extension() == ".");
756     BOOST_TEST(path("a.b.c").extension() == ".c");
757     BOOST_TEST(path("a.b.c.").extension() == ".");
758     BOOST_TEST(path("a/").extension() == "");
759 
760     // main q & d test sequence
761     path p;
762     path q;
763 
764     p = q = "";
765     BOOST_TEST(p.relative_path().string() == "");
766     BOOST_TEST(p.parent_path().string() == "");
767     PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
768     BOOST_TEST(p.filename() == "");
769     BOOST_TEST(p.stem() == "");
770     BOOST_TEST(p.extension() == "");
771     BOOST_TEST(p.root_name() == "");
772     BOOST_TEST(p.root_directory() == "");
773     BOOST_TEST(p.root_path().string() == "");
774     BOOST_TEST(!p.has_root_path());
775     BOOST_TEST(!p.has_root_name());
776     BOOST_TEST(!p.has_root_directory());
777     BOOST_TEST(!p.has_relative_path());
778     BOOST_TEST(!p.has_filename());
779     BOOST_TEST(!p.has_stem());
780     BOOST_TEST(!p.has_extension());
781     BOOST_TEST(!p.has_parent_path());
782     BOOST_TEST(!p.is_absolute());
783 
784     p = q = "/";
785     BOOST_TEST(p.relative_path().string() == "");
786     BOOST_TEST(p.parent_path().string() == "");
787     PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
788     BOOST_TEST(p.filename() == "/");
789     BOOST_TEST(p.stem() == "/");
790     BOOST_TEST(p.extension() == "");
791     BOOST_TEST(p.root_name() == "");
792     BOOST_TEST(p.root_directory() == "/");
793     BOOST_TEST(p.root_path().string() == "/");
794     BOOST_TEST(p.has_root_path());
795     BOOST_TEST(!p.has_root_name());
796     BOOST_TEST(p.has_root_directory());
797     BOOST_TEST(!p.has_relative_path());
798     BOOST_TEST(p.has_filename());
799     BOOST_TEST(p.has_stem());
800     BOOST_TEST(!p.has_extension());
801     BOOST_TEST(!p.has_parent_path());
802     if (platform == "POSIX")
803       BOOST_TEST(p.is_absolute());
804     else
805       BOOST_TEST(!p.is_absolute());
806 
807     p = q = "//";
808     PATH_TEST_EQ(p.relative_path().string(), "");
809     PATH_TEST_EQ(p.parent_path().string(), "");
810     PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
811     PATH_TEST_EQ(p.filename(), "//");
812     PATH_TEST_EQ(p.stem(), "//");
813     PATH_TEST_EQ(p.extension(), "");
814     PATH_TEST_EQ(p.root_name(), "//");
815     PATH_TEST_EQ(p.root_directory(), "");
816     PATH_TEST_EQ(p.root_path().string(), "//");
817     BOOST_TEST(p.has_root_path());
818     BOOST_TEST(p.has_root_name());
819     BOOST_TEST(!p.has_root_directory());
820     BOOST_TEST(!p.has_relative_path());
821     BOOST_TEST(p.has_filename());
822     BOOST_TEST(p.has_stem());
823     BOOST_TEST(!p.has_extension());
824     BOOST_TEST(!p.has_parent_path());
825     BOOST_TEST(!p.is_absolute());
826 
827     p = q = "///";
828     PATH_TEST_EQ(p.relative_path().string(), "");
829     PATH_TEST_EQ(p.parent_path().string(), "");
830     PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
831     PATH_TEST_EQ(p.filename(), "/");
832     PATH_TEST_EQ(p.stem(), "/");
833     PATH_TEST_EQ(p.extension(), "");
834     PATH_TEST_EQ(p.root_name(), "");
835     PATH_TEST_EQ(p.root_directory(), "/");
836     PATH_TEST_EQ(p.root_path().string(), "/");
837     BOOST_TEST(p.has_root_path());
838     BOOST_TEST(!p.has_root_name());
839     BOOST_TEST(p.has_root_directory());
840     BOOST_TEST(!p.has_relative_path());
841     BOOST_TEST(p.has_filename());
842     BOOST_TEST(p.has_stem());
843     BOOST_TEST(!p.has_extension());
844     BOOST_TEST(!p.has_parent_path());
845     if (platform == "POSIX")
846       BOOST_TEST(p.is_absolute());
847     else
848       BOOST_TEST(!p.is_absolute());
849 
850     p = q = ".";
851     BOOST_TEST(p.relative_path().string() == ".");
852     BOOST_TEST(p.parent_path().string() == "");
853     PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
854     BOOST_TEST(p.filename() == ".");
855     BOOST_TEST(p.stem() == ".");
856     BOOST_TEST(p.extension() == "");
857     BOOST_TEST(p.root_name() == "");
858     BOOST_TEST(p.root_directory() == "");
859     BOOST_TEST(p.root_path().string() == "");
860     BOOST_TEST(!p.has_root_path());
861     BOOST_TEST(!p.has_root_name());
862     BOOST_TEST(!p.has_root_directory());
863     BOOST_TEST(p.has_relative_path());
864     BOOST_TEST(p.has_filename());
865     BOOST_TEST(p.has_stem());
866     BOOST_TEST(!p.has_extension());
867     BOOST_TEST(!p.has_parent_path());
868     BOOST_TEST(!p.is_absolute());
869 
870     p = q = "..";
871     BOOST_TEST(p.relative_path().string() == "..");
872     BOOST_TEST(p.parent_path().string() == "");
873     PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
874     BOOST_TEST(p.filename() == "..");
875     BOOST_TEST(p.stem() == "..");
876     BOOST_TEST(p.extension() == "");
877     BOOST_TEST(p.root_name() == "");
878     BOOST_TEST(p.root_directory() == "");
879     BOOST_TEST(p.root_path().string() == "");
880     BOOST_TEST(!p.has_root_path());
881     BOOST_TEST(!p.has_root_name());
882     BOOST_TEST(!p.has_root_directory());
883     BOOST_TEST(p.has_relative_path());
884     BOOST_TEST(p.has_filename());
885     BOOST_TEST(p.has_stem());
886     BOOST_TEST(!p.has_extension());
887     BOOST_TEST(!p.has_parent_path());
888     BOOST_TEST(!p.is_absolute());
889 
890     p = q = "foo";
891     BOOST_TEST(p.relative_path().string() == "foo");
892     BOOST_TEST(p.parent_path().string() == "");
893     PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
894     BOOST_TEST(p.filename() == "foo");
895     BOOST_TEST(p.stem() == "foo");
896     BOOST_TEST(p.extension() == "");
897     BOOST_TEST(p.root_name() == "");
898     BOOST_TEST(p.root_directory() == "");
899     BOOST_TEST(p.root_path().string() == "");
900     BOOST_TEST(!p.has_root_path());
901     BOOST_TEST(!p.has_root_name());
902     BOOST_TEST(!p.has_root_directory());
903     BOOST_TEST(p.has_relative_path());
904     BOOST_TEST(p.has_filename());
905     BOOST_TEST(p.has_stem());
906     BOOST_TEST(!p.has_extension());
907     BOOST_TEST(!p.has_parent_path());
908     BOOST_TEST(!p.is_absolute());
909 
910     p = q = "/foo";
911     PATH_TEST_EQ(p.relative_path().string(), "foo");
912     PATH_TEST_EQ(p.parent_path().string(), "/");
913     PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
914     PATH_TEST_EQ(p.filename(), "foo");
915     PATH_TEST_EQ(p.stem(), "foo");
916     PATH_TEST_EQ(p.extension(), "");
917     PATH_TEST_EQ(p.root_name(), "");
918     PATH_TEST_EQ(p.root_directory(), "/");
919     PATH_TEST_EQ(p.root_path().string(), "/");
920     BOOST_TEST(p.has_root_path());
921     BOOST_TEST(!p.has_root_name());
922     BOOST_TEST(p.has_root_directory());
923     BOOST_TEST(p.has_relative_path());
924     BOOST_TEST(p.has_filename());
925     BOOST_TEST(p.has_stem());
926     BOOST_TEST(!p.has_extension());
927     BOOST_TEST(p.has_parent_path());
928     if (platform == "POSIX")
929       BOOST_TEST(p.is_absolute());
930     else
931       BOOST_TEST(!p.is_absolute());
932 
933     p = q = "/foo/";
934     PATH_TEST_EQ(p.relative_path().string(), "foo/");
935     PATH_TEST_EQ(p.parent_path().string(), "/foo");
936     PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
937     PATH_TEST_EQ(p.filename(), ".");
938     PATH_TEST_EQ(p.stem(), ".");
939     PATH_TEST_EQ(p.extension(), "");
940     PATH_TEST_EQ(p.root_name(), "");
941     PATH_TEST_EQ(p.root_directory(), "/");
942     PATH_TEST_EQ(p.root_path().string(), "/");
943     BOOST_TEST(p.has_root_path());
944     BOOST_TEST(!p.has_root_name());
945     BOOST_TEST(p.has_root_directory());
946     BOOST_TEST(p.has_relative_path());
947     BOOST_TEST(p.has_filename());
948     BOOST_TEST(p.has_stem());
949     BOOST_TEST(!p.has_extension());
950     BOOST_TEST(p.has_parent_path());
951     if (platform == "POSIX")
952       BOOST_TEST(p.is_absolute());
953     else
954       BOOST_TEST(!p.is_absolute());
955 
956     p = q = "///foo";
957     PATH_TEST_EQ(p.relative_path().string(), "foo");
958     PATH_TEST_EQ(p.parent_path().string(), "/");
959     PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
960     PATH_TEST_EQ(p.filename(), "foo");
961     PATH_TEST_EQ(p.root_name(), "");
962     PATH_TEST_EQ(p.root_directory(), "/");
963     PATH_TEST_EQ(p.root_path().string(), "/");
964     BOOST_TEST(p.has_root_path());
965     BOOST_TEST(!p.has_root_name());
966     BOOST_TEST(p.has_root_directory());
967     BOOST_TEST(p.has_relative_path());
968     BOOST_TEST(p.has_filename());
969     BOOST_TEST(p.has_parent_path());
970     if (platform == "POSIX")
971       BOOST_TEST(p.is_absolute());
972     else
973       BOOST_TEST(!p.is_absolute());
974 
975     p = q = "foo/bar";
976     BOOST_TEST(p.relative_path().string() == "foo/bar");
977     BOOST_TEST(p.parent_path().string() == "foo");
978     PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
979     BOOST_TEST(p.filename() == "bar");
980     BOOST_TEST(p.stem() == "bar");
981     BOOST_TEST(p.extension() == "");
982     BOOST_TEST(p.root_name() == "");
983     BOOST_TEST(p.root_directory() == "");
984     BOOST_TEST(p.root_path().string() == "");
985     BOOST_TEST(!p.has_root_path());
986     BOOST_TEST(!p.has_root_name());
987     BOOST_TEST(!p.has_root_directory());
988     BOOST_TEST(p.has_relative_path());
989     BOOST_TEST(p.has_filename());
990     BOOST_TEST(p.has_stem());
991     BOOST_TEST(!p.has_extension());
992     BOOST_TEST(p.has_parent_path());
993     BOOST_TEST(!p.is_absolute());
994 
995     p = q = "../foo";
996     BOOST_TEST(p.relative_path().string() == "../foo");
997     BOOST_TEST(p.parent_path().string() == "..");
998     PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
999     BOOST_TEST(p.filename() == "foo");
1000     BOOST_TEST(p.root_name() == "");
1001     BOOST_TEST(p.root_directory() == "");
1002     BOOST_TEST(p.root_path().string() == "");
1003     BOOST_TEST(!p.has_root_path());
1004     BOOST_TEST(!p.has_root_name());
1005     BOOST_TEST(!p.has_root_directory());
1006     BOOST_TEST(p.has_relative_path());
1007     BOOST_TEST(p.has_filename());
1008     BOOST_TEST(p.has_parent_path());
1009     BOOST_TEST(!p.is_absolute());
1010 
1011     p = q = "..///foo";
1012     PATH_TEST_EQ(p.relative_path().string(), "..///foo");
1013     PATH_TEST_EQ(p.parent_path().string(), "..");
1014     PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
1015     PATH_TEST_EQ(p.filename(), "foo");
1016     PATH_TEST_EQ(p.root_name(), "");
1017     PATH_TEST_EQ(p.root_directory(), "");
1018     PATH_TEST_EQ(p.root_path().string(), "");
1019     BOOST_TEST(!p.has_root_path());
1020     BOOST_TEST(!p.has_root_name());
1021     BOOST_TEST(!p.has_root_directory());
1022     BOOST_TEST(p.has_relative_path());
1023     BOOST_TEST(p.has_filename());
1024     BOOST_TEST(p.has_parent_path());
1025     BOOST_TEST(!p.is_absolute());
1026 
1027     p = q = "/foo/bar";
1028     BOOST_TEST(p.relative_path().string() == "foo/bar");
1029     BOOST_TEST(p.parent_path().string() == "/foo");
1030     PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
1031     BOOST_TEST(p.filename() == "bar");
1032     BOOST_TEST(p.root_name() == "");
1033     BOOST_TEST(p.root_directory() == "/");
1034     BOOST_TEST(p.root_path().string() == "/");
1035     BOOST_TEST(p.has_root_path());
1036     BOOST_TEST(!p.has_root_name());
1037     BOOST_TEST(p.has_root_directory());
1038     BOOST_TEST(p.has_relative_path());
1039     BOOST_TEST(p.has_filename());
1040     BOOST_TEST(p.has_parent_path());
1041     if (platform == "POSIX")
1042       BOOST_TEST(p.is_absolute());
1043     else
1044       BOOST_TEST(!p.is_absolute());
1045 
1046     // Both POSIX and Windows allow two leading slashs
1047     // (POSIX meaning is implementation defined)
1048     PATH_TEST_EQ(path("//resource"), "//resource");
1049     PATH_TEST_EQ(path("//resource/"), "//resource/");
1050     PATH_TEST_EQ(path("//resource/foo"), "//resource/foo");
1051 
1052     p = q = path("//net");
1053     PATH_TEST_EQ(p.string(), "//net");
1054     PATH_TEST_EQ(p.relative_path().string(), "");
1055     PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
1056     PATH_TEST_EQ(p.parent_path().string(), "");
1057     PATH_TEST_EQ(p.filename(), "//net");
1058     PATH_TEST_EQ(p.root_name(), "//net");
1059     PATH_TEST_EQ(p.root_directory(), "");
1060     PATH_TEST_EQ(p.root_path().string(), "//net");
1061     BOOST_TEST(p.has_root_path());
1062     BOOST_TEST(p.has_root_name());
1063     BOOST_TEST(!p.has_root_directory());
1064     BOOST_TEST(!p.has_relative_path());
1065     BOOST_TEST(p.has_filename());
1066     BOOST_TEST(!p.has_parent_path());
1067     BOOST_TEST(!p.is_absolute());
1068 
1069     p = q = path("//net/");
1070     BOOST_TEST(p.relative_path().string() == "");
1071     BOOST_TEST(p.parent_path().string() == "//net");
1072     PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
1073     BOOST_TEST(p.filename() == "/");
1074     BOOST_TEST(p.root_name() == "//net");
1075     BOOST_TEST(p.root_directory() == "/");
1076     BOOST_TEST(p.root_path().string() == "//net/");
1077     BOOST_TEST(p.has_root_path());
1078     BOOST_TEST(p.has_root_name());
1079     BOOST_TEST(p.has_root_directory());
1080     BOOST_TEST(!p.has_relative_path());
1081     BOOST_TEST(p.has_filename());
1082     BOOST_TEST(p.has_parent_path());
1083     BOOST_TEST(p.is_absolute());
1084 
1085     p = q = path("//net/foo");
1086     BOOST_TEST(p.relative_path().string() == "foo");
1087     BOOST_TEST(p.parent_path().string() == "//net/");
1088     PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
1089     BOOST_TEST(p.filename() == "foo");
1090     BOOST_TEST(p.root_name() == "//net");
1091     BOOST_TEST(p.root_directory() == "/");
1092     BOOST_TEST(p.root_path().string() == "//net/");
1093     BOOST_TEST(p.has_root_path());
1094     BOOST_TEST(p.has_root_name());
1095     BOOST_TEST(p.has_root_directory());
1096     BOOST_TEST(p.has_relative_path());
1097     BOOST_TEST(p.has_filename());
1098     BOOST_TEST(p.has_parent_path());
1099     BOOST_TEST(p.is_absolute());
1100 
1101     p = q = path("//net///foo");
1102     PATH_TEST_EQ(p.relative_path().string(), "foo");
1103     PATH_TEST_EQ(p.parent_path().string(), "//net/");
1104     PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
1105     PATH_TEST_EQ(p.filename(), "foo");
1106     PATH_TEST_EQ(p.root_name(), "//net");
1107     PATH_TEST_EQ(p.root_directory(), "/");
1108     PATH_TEST_EQ(p.root_path().string(), "//net/");
1109     BOOST_TEST(p.has_root_path());
1110     BOOST_TEST(p.has_root_name());
1111     BOOST_TEST(p.has_root_directory());
1112     BOOST_TEST(p.has_relative_path());
1113     BOOST_TEST(p.has_filename());
1114     BOOST_TEST(p.has_parent_path());
1115     BOOST_TEST(p.is_absolute());
1116 
1117     //  ticket 2739, infinite recursion leading to stack overflow, was caused
1118     //  by failure to handle this case correctly on Windows.
1119     p = path(":");
1120     PATH_TEST_EQ(p.parent_path().string(), "");
1121     PATH_TEST_EQ(p.filename(), ":");
1122     BOOST_TEST(!p.has_parent_path());
1123     BOOST_TEST(p.has_filename());
1124 
1125     //  test some similar cases that both POSIX and Windows should handle identically
1126     p = path("c:");
1127     PATH_TEST_EQ(p.parent_path().string(), "");
1128     PATH_TEST_EQ(p.filename(), "c:");
1129     BOOST_TEST(!p.has_parent_path());
1130     BOOST_TEST(p.has_filename());
1131     p = path("cc:");
1132     PATH_TEST_EQ(p.parent_path().string(), "");
1133     PATH_TEST_EQ(p.filename(), "cc:");
1134     BOOST_TEST(!p.has_parent_path());
1135     BOOST_TEST(p.has_filename());
1136 
1137     //  Windows specific tests
1138     if (platform == "Windows")
1139     {
1140 
1141       //p = q = L"\\\\?\\";
1142       //BOOST_TEST(p.relative_path().string() == "");
1143       //BOOST_TEST(p.parent_path().string() == "");
1144       //PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
1145       //BOOST_TEST(p.filename() == "");
1146       //BOOST_TEST(p.stem() == "");
1147       //BOOST_TEST(p.extension() == "");
1148       //BOOST_TEST(p.root_name() == "");
1149       //BOOST_TEST(p.root_directory() == "");
1150       //BOOST_TEST(p.root_path().string() == "");
1151       //BOOST_TEST(!p.has_root_path());
1152       //BOOST_TEST(!p.has_root_name());
1153       //BOOST_TEST(!p.has_root_directory());
1154       //BOOST_TEST(!p.has_relative_path());
1155       //BOOST_TEST(!p.has_filename());
1156       //BOOST_TEST(!p.has_stem());
1157       //BOOST_TEST(!p.has_extension());
1158       //BOOST_TEST(!p.has_parent_path());
1159       //BOOST_TEST(!p.is_absolute());
1160 
1161       p = q = path("c:");
1162       BOOST_TEST(p.relative_path().string() == "");
1163       BOOST_TEST(p.parent_path().string() == "");
1164       PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
1165       BOOST_TEST(p.filename() == "c:");
1166       BOOST_TEST(p.root_name() == "c:");
1167       BOOST_TEST(p.root_directory() == "");
1168       BOOST_TEST(p.root_path().string() == "c:");
1169       BOOST_TEST(p.has_root_path());
1170       BOOST_TEST(p.has_root_name());
1171       BOOST_TEST(!p.has_root_directory());
1172       BOOST_TEST(!p.has_relative_path());
1173       BOOST_TEST(p.has_filename());
1174       BOOST_TEST(!p.has_parent_path());
1175       BOOST_TEST(!p.is_absolute());
1176 
1177       //p = q = path(L"\\\\?\\c:");
1178       //BOOST_TEST(p.relative_path().string() == "");
1179       //BOOST_TEST(p.parent_path().string() == "");
1180       //PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
1181       //BOOST_TEST(p.filename() == "c:");
1182       //BOOST_TEST(p.root_name() == "c:");
1183       //BOOST_TEST(p.root_directory() == "");
1184       //BOOST_TEST(p.root_path().string() == "c:");
1185       //BOOST_TEST(p.has_root_path());
1186       //BOOST_TEST(p.has_root_name());
1187       //BOOST_TEST(!p.has_root_directory());
1188       //BOOST_TEST(!p.has_relative_path());
1189       //BOOST_TEST(p.has_filename());
1190       //BOOST_TEST(!p.has_parent_path());
1191       //BOOST_TEST(!p.is_absolute());
1192 
1193       p = q = path("c:foo");
1194       BOOST_TEST(p.relative_path().string() == "foo");
1195       BOOST_TEST(p.parent_path().string() == "c:");
1196       PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
1197       BOOST_TEST(p.filename() == "foo");
1198       BOOST_TEST(p.root_name() == "c:");
1199       BOOST_TEST(p.root_directory() == "");
1200       BOOST_TEST(p.root_path().string() == "c:");
1201       BOOST_TEST(p.has_root_path());
1202       BOOST_TEST(p.has_root_name());
1203       BOOST_TEST(!p.has_root_directory());
1204       BOOST_TEST(p.has_relative_path());
1205       BOOST_TEST(p.has_filename());
1206       BOOST_TEST(p.has_parent_path());
1207       BOOST_TEST(!p.is_absolute());
1208 
1209       //p = q = path(L"\\\\?\\c:foo");
1210       //BOOST_TEST(p.relative_path().string() == "foo");
1211       //BOOST_TEST(p.parent_path().string() == "c:");
1212       //PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
1213       //BOOST_TEST(p.filename() == "foo");
1214       //BOOST_TEST(p.root_name() == "c:");
1215       //BOOST_TEST(p.root_directory() == "");
1216       //BOOST_TEST(p.root_path().string() == "c:");
1217       //BOOST_TEST(p.has_root_path());
1218       //BOOST_TEST(p.has_root_name());
1219       //BOOST_TEST(!p.has_root_directory());
1220       //BOOST_TEST(p.has_relative_path());
1221       //BOOST_TEST(p.has_filename());
1222       //BOOST_TEST(p.has_parent_path());
1223       //BOOST_TEST(!p.is_absolute());
1224 
1225       p = q = path("c:/");
1226       BOOST_TEST(p.relative_path().string() == "");
1227       BOOST_TEST(p.parent_path().string() == "c:");
1228       PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
1229       BOOST_TEST(p.filename() == "/");
1230       BOOST_TEST(p.root_name() == "c:");
1231       BOOST_TEST(p.root_directory() == "/");
1232       BOOST_TEST(p.root_path().string() == "c:/");
1233       BOOST_TEST(p.has_root_path());
1234       BOOST_TEST(p.has_root_name());
1235       BOOST_TEST(p.has_root_directory());
1236       BOOST_TEST(!p.has_relative_path());
1237       BOOST_TEST(p.has_filename());
1238       BOOST_TEST(p.has_parent_path());
1239       BOOST_TEST(p.is_absolute());
1240 
1241       p = q = path("c:..");
1242       BOOST_TEST(p.relative_path().string() == "..");
1243       BOOST_TEST(p.parent_path().string() == "c:");
1244       PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
1245       BOOST_TEST(p.filename() == "..");
1246       BOOST_TEST(p.root_name() == "c:");
1247       BOOST_TEST(p.root_directory() == "");
1248       BOOST_TEST(p.root_path().string() == "c:");
1249       BOOST_TEST(p.has_root_path());
1250       BOOST_TEST(p.has_root_name());
1251       BOOST_TEST(!p.has_root_directory());
1252       BOOST_TEST(p.has_relative_path());
1253       BOOST_TEST(p.has_filename());
1254       BOOST_TEST(p.has_parent_path());
1255       BOOST_TEST(!p.is_absolute());
1256 
1257       p = q = path("c:/foo");
1258       PATH_TEST_EQ(p.relative_path().string(), "foo");
1259       PATH_TEST_EQ(p.parent_path().string(), "c:/");
1260       PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
1261       PATH_TEST_EQ(p.filename(), "foo");
1262       PATH_TEST_EQ(p.root_name(), "c:");
1263       PATH_TEST_EQ(p.root_directory(), "/");
1264       PATH_TEST_EQ(p.root_path().string(), "c:/");
1265       BOOST_TEST(p.has_root_path());
1266       BOOST_TEST(p.has_root_name());
1267       BOOST_TEST(p.has_root_directory());
1268       BOOST_TEST(p.has_relative_path());
1269       BOOST_TEST(p.has_filename());
1270       BOOST_TEST(p.has_parent_path());
1271       BOOST_TEST(p.is_absolute());
1272 
1273       p = q = path("c://foo");
1274       PATH_TEST_EQ(p.relative_path().string(), "foo");
1275       PATH_TEST_EQ(p.parent_path().string(), "c:/");
1276       PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
1277       PATH_TEST_EQ(p.filename(), "foo");
1278       PATH_TEST_EQ(p.root_name(), "c:");
1279       PATH_TEST_EQ(p.root_directory(), "/");
1280       PATH_TEST_EQ(p.root_path().string(), "c:/");
1281       BOOST_TEST(p.has_root_path());
1282       BOOST_TEST(p.has_root_name());
1283       BOOST_TEST(p.has_root_directory());
1284       BOOST_TEST(p.has_relative_path());
1285       BOOST_TEST(p.has_filename());
1286       BOOST_TEST(p.has_parent_path());
1287       BOOST_TEST(p.is_absolute());
1288 
1289       p = q = path("c:\\foo\\bar");
1290       PATH_TEST_EQ(p.relative_path().string(), "foo\\bar");
1291       PATH_TEST_EQ(p.parent_path().string(), "c:\\foo");
1292       PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
1293       PATH_TEST_EQ(p.filename(), "bar");
1294       PATH_TEST_EQ(p.root_name(), "c:");
1295       PATH_TEST_EQ(p.root_directory(), "\\");
1296       PATH_TEST_EQ(p.root_path().string(), "c:\\");
1297       BOOST_TEST(p.has_root_path());
1298       BOOST_TEST(p.has_root_name());
1299       BOOST_TEST(p.has_root_directory());
1300       BOOST_TEST(p.has_relative_path());
1301       BOOST_TEST(p.has_filename());
1302       BOOST_TEST(p.has_parent_path());
1303       BOOST_TEST(p.is_absolute());
1304 
1305       p = q = path("prn:");
1306       BOOST_TEST(p.relative_path().string() == "");
1307       BOOST_TEST(p.parent_path().string() == "");
1308       PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
1309       BOOST_TEST(p.filename() == "prn:");
1310       BOOST_TEST(p.root_name() == "prn:");
1311       BOOST_TEST(p.root_directory() == "");
1312       BOOST_TEST(p.root_path().string() == "prn:");
1313       BOOST_TEST(p.has_root_path());
1314       BOOST_TEST(p.has_root_name());
1315       BOOST_TEST(!p.has_root_directory());
1316       BOOST_TEST(!p.has_relative_path());
1317       BOOST_TEST(p.has_filename());
1318       BOOST_TEST(!p.has_parent_path());
1319       BOOST_TEST(!p.is_absolute());
1320 
1321       p = q = path("\\\\net\\\\\\foo");
1322       PATH_TEST_EQ(p.relative_path().string(), "foo");
1323       PATH_TEST_EQ(p.parent_path().string(), "\\\\net\\");
1324       PATH_TEST_EQ(q.remove_filename().string(), p.parent_path().string());
1325       PATH_TEST_EQ(p.filename(), "foo");
1326       PATH_TEST_EQ(p.root_name(), "\\\\net");
1327       PATH_TEST_EQ(p.root_directory(), "\\");
1328       PATH_TEST_EQ(p.root_path().string(), "\\\\net\\");
1329       BOOST_TEST(p.has_root_path());
1330       BOOST_TEST(p.has_root_name());
1331       BOOST_TEST(p.has_root_directory());
1332       BOOST_TEST(p.has_relative_path());
1333       BOOST_TEST(p.has_filename());
1334       BOOST_TEST(p.has_parent_path());
1335       BOOST_TEST(p.is_absolute());
1336     } // Windows
1337 
1338     else
1339     { // POSIX
1340       PATH_TEST_EQ(path("/foo/bar/"), "/foo/bar/");
1341       PATH_TEST_EQ(path("//foo//bar//"), "//foo//bar//");
1342       PATH_TEST_EQ(path("///foo///bar///"), "///foo///bar///");
1343 
1344       p = path("/usr/local/bin:/usr/bin:/bin");
1345       BOOST_TEST(p.string() == "/usr/local/bin:/usr/bin:/bin");
1346     } // POSIX
1347   }
1348 
1349  //  composition_tests  ----------------------------------------------------------------//
1350 
composition_tests()1351   void composition_tests()
1352   {
1353     std::cout << "composition_tests..." << std::endl;
1354 
1355   }
1356 
1357  //  construction_tests  ---------------------------------------------------------------//
1358 
construction_tests()1359   void construction_tests()
1360   {
1361     std::cout << "construction_tests..." << std::endl;
1362 
1363     PATH_TEST_EQ("", "");
1364 
1365     PATH_TEST_EQ("foo", "foo");
1366     PATH_TEST_EQ("f", "f");
1367 
1368     PATH_TEST_EQ("foo/", "foo/");
1369     PATH_TEST_EQ("f/", "f/");
1370     PATH_TEST_EQ("foo/..", "foo/..");
1371     PATH_TEST_EQ("foo/../", "foo/../");
1372     PATH_TEST_EQ("foo/bar/../..", "foo/bar/../..");
1373     PATH_TEST_EQ("foo/bar/../../", "foo/bar/../../");
1374     PATH_TEST_EQ("/", "/");
1375     PATH_TEST_EQ("/f", "/f");
1376 
1377     PATH_TEST_EQ("/foo", "/foo");
1378     PATH_TEST_EQ("/foo/bar/", "/foo/bar/");
1379     PATH_TEST_EQ("//foo//bar//", "//foo//bar//");
1380     PATH_TEST_EQ("///foo///bar///", "///foo///bar///");
1381     PATH_TEST_EQ("\\/foo\\/bar\\/", "\\/foo\\/bar\\/");
1382     PATH_TEST_EQ("\\//foo\\//bar\\//", "\\//foo\\//bar\\//");
1383 
1384     if (platform == "Windows")
1385     {
1386       PATH_TEST_EQ(path("c:") / "foo", "c:foo");
1387       PATH_TEST_EQ(path("c:") / "/foo", "c:/foo");
1388 
1389       PATH_TEST_EQ("\\foo\\bar\\", "\\foo\\bar\\");
1390       PATH_TEST_EQ("\\\\foo\\\\bar\\\\", "\\\\foo\\\\bar\\\\");
1391       PATH_TEST_EQ("\\\\\\foo\\\\\\bar\\\\\\", "\\\\\\foo\\\\\\bar\\\\\\");
1392 
1393       PATH_TEST_EQ("\\", "\\");
1394       PATH_TEST_EQ("\\f", "\\f");
1395       PATH_TEST_EQ("\\foo", "\\foo");
1396       PATH_TEST_EQ("foo\\bar", "foo\\bar");
1397       PATH_TEST_EQ("foo bar", "foo bar");
1398       PATH_TEST_EQ("c:", "c:");
1399       PATH_TEST_EQ("c:/", "c:/");
1400       PATH_TEST_EQ("c:.", "c:.");
1401       PATH_TEST_EQ("c:./foo", "c:./foo");
1402       PATH_TEST_EQ("c:.\\foo", "c:.\\foo");
1403       PATH_TEST_EQ("c:..", "c:..");
1404       PATH_TEST_EQ("c:/.", "c:/.");
1405       PATH_TEST_EQ("c:/..", "c:/..");
1406       PATH_TEST_EQ("c:/../", "c:/../");
1407       PATH_TEST_EQ("c:\\..\\", "c:\\..\\");
1408       PATH_TEST_EQ("c:/../..", "c:/../..");
1409       PATH_TEST_EQ("c:/../foo", "c:/../foo");
1410       PATH_TEST_EQ("c:\\..\\foo", "c:\\..\\foo");
1411       PATH_TEST_EQ("c:../foo", "c:../foo");
1412       PATH_TEST_EQ("c:..\\foo", "c:..\\foo");
1413       PATH_TEST_EQ("c:/../../foo", "c:/../../foo");
1414       PATH_TEST_EQ("c:\\..\\..\\foo", "c:\\..\\..\\foo");
1415       PATH_TEST_EQ("c:foo/..", "c:foo/..");
1416       PATH_TEST_EQ("c:/foo/..", "c:/foo/..");
1417       PATH_TEST_EQ("c:/..foo", "c:/..foo");
1418       PATH_TEST_EQ("c:foo", "c:foo");
1419       PATH_TEST_EQ("c:/foo", "c:/foo");
1420       PATH_TEST_EQ("\\\\netname", "\\\\netname");
1421       PATH_TEST_EQ("\\\\netname\\", "\\\\netname\\");
1422       PATH_TEST_EQ("\\\\netname\\foo", "\\\\netname\\foo");
1423       PATH_TEST_EQ("c:/foo", "c:/foo");
1424       PATH_TEST_EQ("prn:", "prn:");
1425     }
1426     else
1427     {
1428     }
1429 
1430     PATH_TEST_EQ("foo/bar", "foo/bar");
1431     PATH_TEST_EQ("a/b", "a/b");  // probe for length effects
1432     PATH_TEST_EQ("..", "..");
1433     PATH_TEST_EQ("../..", "../..");
1434     PATH_TEST_EQ("/..", "/..");
1435     PATH_TEST_EQ("/../..", "/../..");
1436     PATH_TEST_EQ("../foo", "../foo");
1437     PATH_TEST_EQ("foo/..", "foo/..");
1438     PATH_TEST_EQ("foo/..bar", "foo/..bar");
1439     PATH_TEST_EQ("../f", "../f");
1440     PATH_TEST_EQ("/../f", "/../f");
1441     PATH_TEST_EQ("f/..", "f/..");
1442     PATH_TEST_EQ("foo/../..", "foo/../..");
1443     PATH_TEST_EQ("foo/../../..", "foo/../../..");
1444     PATH_TEST_EQ("foo/../bar", "foo/../bar");
1445     PATH_TEST_EQ("foo/bar/..", "foo/bar/..");
1446     PATH_TEST_EQ("foo/bar/../..", "foo/bar/../..");
1447     PATH_TEST_EQ("foo/bar/../blah", "foo/bar/../blah");
1448     PATH_TEST_EQ("f/../b", "f/../b");
1449     PATH_TEST_EQ("f/b/..", "f/b/..");
1450     PATH_TEST_EQ("f/b/../a", "f/b/../a");
1451     PATH_TEST_EQ("foo/bar/blah/../..", "foo/bar/blah/../..");
1452     PATH_TEST_EQ("foo/bar/blah/../../bletch", "foo/bar/blah/../../bletch");
1453     PATH_TEST_EQ("...", "...");
1454     PATH_TEST_EQ("....", "....");
1455     PATH_TEST_EQ("foo/...", "foo/...");
1456     PATH_TEST_EQ("abc.", "abc.");
1457     PATH_TEST_EQ("abc..", "abc..");
1458     PATH_TEST_EQ("foo/abc.", "foo/abc.");
1459     PATH_TEST_EQ("foo/abc..", "foo/abc..");
1460 
1461     PATH_TEST_EQ(".abc", ".abc");
1462     PATH_TEST_EQ("a.c", "a.c");
1463     PATH_TEST_EQ("..abc", "..abc");
1464     PATH_TEST_EQ("a..c", "a..c");
1465     PATH_TEST_EQ("foo/.abc", "foo/.abc");
1466     PATH_TEST_EQ("foo/a.c", "foo/a.c");
1467     PATH_TEST_EQ("foo/..abc", "foo/..abc");
1468     PATH_TEST_EQ("foo/a..c", "foo/a..c");
1469 
1470     PATH_TEST_EQ(".", ".");
1471     PATH_TEST_EQ("./foo", "./foo");
1472     PATH_TEST_EQ("./..", "./..");
1473     PATH_TEST_EQ("./../foo", "./../foo");
1474     PATH_TEST_EQ("foo/.", "foo/.");
1475     PATH_TEST_EQ("../.", "../.");
1476     PATH_TEST_EQ("./.", "./.");
1477     PATH_TEST_EQ("././.", "././.");
1478     PATH_TEST_EQ("./foo/.", "./foo/.");
1479     PATH_TEST_EQ("foo/./bar", "foo/./bar");
1480     PATH_TEST_EQ("foo/./.", "foo/./.");
1481     PATH_TEST_EQ("foo/./..", "foo/./..");
1482     PATH_TEST_EQ("foo/./../bar", "foo/./../bar");
1483     PATH_TEST_EQ("foo/../.", "foo/../.");
1484     PATH_TEST_EQ("././..", "././..");
1485     PATH_TEST_EQ("./../.", "./../.");
1486     PATH_TEST_EQ(".././.", ".././.");
1487   }
1488 
1489   //  append_tests  --------------------------------------------------------------------//
1490 
append_test_aux(const path & p,const std::string & s,const std::string & expect)1491   void append_test_aux(const path & p, const std::string & s, const std::string & expect)
1492   {
1493     PATH_TEST_EQ((p / path(s)).string(), expect);
1494     PATH_TEST_EQ((p / s.c_str()).string(), expect);
1495     PATH_TEST_EQ((p / s).string(), expect);
1496     path x(p);
1497     x.append(s.begin(), s.end());
1498     PATH_TEST_EQ(x.string(), expect);
1499   }
1500 
append_tests()1501   void append_tests()
1502   {
1503     std::cout << "append_tests..." << std::endl;
1504 
1505     // There are many control paths to be exercised, since empty paths and arguments,
1506     // paths with trailing separators, arguments with leading separators, with or without
1507     // other characters being present, are all separate cases that need to be tested.
1508     // Furthermore, some of the code to be tested is specific to argument categories,
1509     // so that results in further permutations to be tested.
1510 
1511     //// code to generate test cases
1512     ////
1513     //// expected results must be checked by hand
1514     //// "foo\bar" expected result must be edited by hand and moved for Windows/POSIX
1515     ////
1516     //const char* x[]    = { "", "/", "foo", "foo/" };
1517     //const char* y[] = { "", "/", "bar", "/bar" };
1518 
1519     //for (int i = 0; i < sizeof(x)/sizeof(char*); ++i)
1520     //  for (int j = 0; j < sizeof(y)/sizeof(char*); ++j)
1521     //  {
1522     //    std::cout << "\n    PATH_TEST_EQ(path(\"" << x[i] << "\") / \"" << y[j] << "\", \""
1523     //              << path(x[i]) / y[j] << "\");\n";
1524     //    std::cout << "    append_test_aux(\"" << x[i] << "\", \"" << y[j] << "\", \""
1525     //              << path(x[i]) / y[j] << "\");\n";
1526     //  }
1527 
1528     PATH_TEST_EQ(path("") / "", "");
1529     append_test_aux("", "", "");
1530 
1531     PATH_TEST_EQ(path("") / "/", "/");
1532     append_test_aux("", "/", "/");
1533 
1534     PATH_TEST_EQ(path("") / "bar", "bar");
1535     append_test_aux("", "bar", "bar");
1536 
1537     PATH_TEST_EQ(path("") / "/bar", "/bar");
1538     append_test_aux("", "/bar", "/bar");
1539 
1540     PATH_TEST_EQ(path("/") / "", "/");
1541     append_test_aux("/", "", "/");
1542 
1543     PATH_TEST_EQ(path("/") / "/", "//");
1544     append_test_aux("/", "/", "//");
1545 
1546     PATH_TEST_EQ(path("/") / "bar", "/bar");
1547     append_test_aux("/", "bar", "/bar");
1548 
1549     PATH_TEST_EQ(path("/") / "/bar", "//bar");
1550     append_test_aux("/", "/bar", "//bar");
1551 
1552     PATH_TEST_EQ(path("foo") / "", "foo");
1553     append_test_aux("foo", "", "foo");
1554 
1555     PATH_TEST_EQ(path("foo") / "/", "foo/");
1556     append_test_aux("foo", "/", "foo/");
1557 
1558     PATH_TEST_EQ(path("foo") / "/bar", "foo/bar");
1559     append_test_aux("foo", "/bar", "foo/bar");
1560 
1561     PATH_TEST_EQ(path("foo/") / "", "foo/");
1562     append_test_aux("foo/", "", "foo/");
1563 
1564     PATH_TEST_EQ(path("foo/") / "/", "foo//");
1565     append_test_aux("foo/", "/", "foo//");
1566 
1567     PATH_TEST_EQ(path("foo/") / "bar", "foo/bar");
1568     append_test_aux("foo/", "bar", "foo/bar");
1569 
1570 
1571     if (platform == "Windows")
1572     {
1573       PATH_TEST_EQ(path("foo") / "bar", "foo\\bar");
1574       append_test_aux("foo", "bar", "foo\\bar");
1575 
1576       PATH_TEST_EQ(path("foo\\") / "\\bar", "foo\\\\bar");
1577       append_test_aux("foo\\", "\\bar", "foo\\\\bar");
1578 
1579       // hand created test case specific to Windows
1580       PATH_TEST_EQ(path("c:") / "bar", "c:bar");
1581       append_test_aux("c:", "bar", "c:bar");
1582     }
1583     else
1584     {
1585       PATH_TEST_EQ(path("foo") / "bar", "foo/bar");
1586       append_test_aux("foo", "bar", "foo/bar");
1587     }
1588 
1589     // ticket #6819
1590     union
1591     {
1592       char a[1];
1593       char b[3];
1594     } u;
1595 
1596     u.b[0] = 'a';
1597     u.b[1] = 'b';
1598     u.b[2] = '\0';
1599 
1600     path p6819;
1601     p6819 /= u.a;
1602     BOOST_TEST_EQ(p6819, path("ab"));
1603   }
1604 
1605 //  self_assign_and_append_tests  ------------------------------------------------------//
1606 
self_assign_and_append_tests()1607   void self_assign_and_append_tests()
1608   {
1609     std::cout << "self_assign_and_append_tests..." << std::endl;
1610 
1611     path p;
1612 
1613     p = "snafubar";
1614     PATH_TEST_EQ(p = p, "snafubar");
1615 
1616     p = "snafubar";
1617     p = p.c_str();
1618     PATH_TEST_EQ(p, "snafubar");
1619 
1620     p = "snafubar";
1621     p.assign(p.c_str(), path::codecvt());
1622     PATH_TEST_EQ(p, "snafubar");
1623 
1624     p = "snafubar";
1625     PATH_TEST_EQ(p = p.c_str()+5, "bar");
1626 
1627     p = "snafubar";
1628     PATH_TEST_EQ(p.assign(p.c_str() + 5, p.c_str() + 7), "ba");
1629 
1630     p = "snafubar";
1631     p /= p;
1632     PATH_TEST_EQ(p, "snafubar" BOOST_DIR_SEP "snafubar");
1633 
1634     p = "snafubar";
1635     p /= p.c_str();
1636     PATH_TEST_EQ(p, "snafubar" BOOST_DIR_SEP "snafubar");
1637 
1638     p = "snafubar";
1639     p.append(p.c_str(), path::codecvt());
1640     PATH_TEST_EQ(p, "snafubar" BOOST_DIR_SEP "snafubar");
1641 
1642     p = "snafubar";
1643     PATH_TEST_EQ(p.append(p.c_str() + 5, p.c_str() + 7), "snafubar" BOOST_DIR_SEP "ba");
1644   }
1645 
1646 
1647   //  name_function_tests  -------------------------------------------------------------//
1648 
name_function_tests()1649   void name_function_tests()
1650   {
1651     std::cout << "name_function_tests..." << std::endl;
1652 
1653     BOOST_TEST(fs::portable_posix_name(std::string("x")));
1654     BOOST_TEST(fs::windows_name(std::string("x")));
1655     BOOST_TEST(fs::portable_name(std::string("x")));
1656     BOOST_TEST(fs::portable_directory_name(std::string("x")));
1657     BOOST_TEST(fs::portable_file_name(std::string("x")));
1658 
1659     BOOST_TEST(fs::portable_posix_name(std::string(".")));
1660     BOOST_TEST(fs::windows_name(std::string(".")));
1661     BOOST_TEST(fs::portable_name(std::string(".")));
1662     BOOST_TEST(fs::portable_directory_name(std::string(".")));
1663     BOOST_TEST(!fs::portable_file_name(std::string(".")));
1664 
1665     BOOST_TEST(fs::portable_posix_name(std::string("..")));
1666     BOOST_TEST(fs::windows_name(std::string("..")));
1667     BOOST_TEST(fs::portable_name(std::string("..")));
1668     BOOST_TEST(fs::portable_directory_name(std::string("..")));
1669     BOOST_TEST(!fs::portable_file_name(std::string("..")));
1670 
1671     BOOST_TEST(!fs::native(std::string("")));
1672     BOOST_TEST(!fs::portable_posix_name(std::string("")));
1673     BOOST_TEST(!fs::windows_name(std::string("")));
1674     BOOST_TEST(!fs::portable_name(std::string("")));
1675     BOOST_TEST(!fs::portable_directory_name(std::string("")));
1676     BOOST_TEST(!fs::portable_file_name(std::string("")));
1677 
1678     BOOST_TEST(!fs::native(std::string(" ")));
1679     BOOST_TEST(!fs::portable_posix_name(std::string(" ")));
1680     BOOST_TEST(!fs::windows_name(std::string(" ")));
1681     BOOST_TEST(!fs::portable_name(std::string(" ")));
1682     BOOST_TEST(!fs::portable_directory_name(std::string(" ")));
1683     BOOST_TEST(!fs::portable_file_name(std::string(" ")));
1684 
1685     BOOST_TEST(!fs::portable_posix_name(std::string(":")));
1686     BOOST_TEST(!fs::windows_name(std::string(":")));
1687     BOOST_TEST(!fs::portable_name(std::string(":")));
1688     BOOST_TEST(!fs::portable_directory_name(std::string(":")));
1689     BOOST_TEST(!fs::portable_file_name(std::string(":")));
1690 
1691     BOOST_TEST(fs::portable_posix_name(std::string("-")));
1692     BOOST_TEST(fs::windows_name(std::string("-")));
1693     BOOST_TEST(!fs::portable_name(std::string("-")));
1694     BOOST_TEST(!fs::portable_directory_name(std::string("-")));
1695     BOOST_TEST(!fs::portable_file_name(std::string("-")));
1696 
1697     BOOST_TEST(!fs::portable_posix_name(std::string("foo bar")));
1698     BOOST_TEST(fs::windows_name(std::string("foo bar")));
1699     BOOST_TEST(!fs::windows_name(std::string(" bar")));
1700     BOOST_TEST(!fs::windows_name(std::string("foo ")));
1701     BOOST_TEST(!fs::portable_name(std::string("foo bar")));
1702     BOOST_TEST(!fs::portable_directory_name(std::string("foo bar")));
1703     BOOST_TEST(!fs::portable_file_name(std::string("foo bar")));
1704 
1705     BOOST_TEST(fs::portable_posix_name(std::string("foo.bar")));
1706     BOOST_TEST(fs::windows_name(std::string("foo.bar")));
1707     BOOST_TEST(fs::portable_name(std::string("foo.bar")));
1708     BOOST_TEST(!fs::portable_directory_name(std::string("foo.bar")));
1709     BOOST_TEST(fs::portable_file_name(std::string("foo.bar")));
1710 
1711     BOOST_TEST(fs::portable_posix_name(std::string("foo.barf")));
1712     BOOST_TEST(fs::windows_name(std::string("foo.barf")));
1713     BOOST_TEST(fs::portable_name(std::string("foo.barf")));
1714     BOOST_TEST(!fs::portable_directory_name(std::string("foo.barf")));
1715     BOOST_TEST(!fs::portable_file_name(std::string("foo.barf")));
1716 
1717     BOOST_TEST(fs::portable_posix_name(std::string(".foo")));
1718     BOOST_TEST(fs::windows_name(std::string(".foo")));
1719     BOOST_TEST(!fs::portable_name(std::string(".foo")));
1720     BOOST_TEST(!fs::portable_directory_name(std::string(".foo")));
1721     BOOST_TEST(!fs::portable_file_name(std::string(".foo")));
1722 
1723     BOOST_TEST(fs::portable_posix_name(std::string("foo.")));
1724     BOOST_TEST(!fs::windows_name(std::string("foo.")));
1725     BOOST_TEST(!fs::portable_name(std::string("foo.")));
1726     BOOST_TEST(!fs::portable_directory_name(std::string("foo.")));
1727     BOOST_TEST(!fs::portable_file_name(std::string("foo.")));
1728   }
1729 
1730   //  replace_extension_tests  ---------------------------------------------------------//
1731 
replace_extension_tests()1732   void replace_extension_tests()
1733   {
1734     std::cout << "replace_extension_tests..." << std::endl;
1735 
1736     BOOST_TEST(path().replace_extension().empty());
1737     BOOST_TEST(path().replace_extension("a") == ".a");
1738     BOOST_TEST(path().replace_extension("a.") == ".a.");
1739     BOOST_TEST(path().replace_extension(".a") == ".a");
1740     BOOST_TEST(path().replace_extension("a.txt") == ".a.txt");
1741     // see the rationale in html docs for explanation why this works:
1742     BOOST_TEST(path().replace_extension(".txt") == ".txt");
1743 
1744     BOOST_TEST(path("a.txt").replace_extension() == "a");
1745     BOOST_TEST(path("a.txt").replace_extension("") == "a");
1746     BOOST_TEST(path("a.txt").replace_extension(".") == "a.");
1747     BOOST_TEST(path("a.txt").replace_extension(".tex") == "a.tex");
1748     BOOST_TEST(path("a.txt").replace_extension("tex") == "a.tex");
1749     BOOST_TEST(path("a.").replace_extension(".tex") == "a.tex");
1750     BOOST_TEST(path("a.").replace_extension("tex") == "a.tex");
1751     BOOST_TEST(path("a").replace_extension(".txt") == "a.txt");
1752     BOOST_TEST(path("a").replace_extension("txt") == "a.txt");
1753     BOOST_TEST(path("a.b.txt").replace_extension(".tex") == "a.b.tex");
1754     BOOST_TEST(path("a.b.txt").replace_extension("tex") == "a.b.tex");
1755     BOOST_TEST(path("a/b").replace_extension(".c") == "a/b.c");
1756     PATH_TEST_EQ(path("a.txt/b").replace_extension(".c"), "a.txt/b.c"); // ticket 4702
1757     BOOST_TEST(path("foo.txt").replace_extension("exe") == "foo.exe");  // ticket 5118
1758     BOOST_TEST(path("foo.txt").replace_extension(".tar.bz2")
1759                                                     == "foo.tar.bz2");  // ticket 5118
1760   }
1761 
1762   //  make_preferred_tests  ------------------------------------------------------------//
1763 
make_preferred_tests()1764   void make_preferred_tests()
1765   {
1766     std::cout << "make_preferred_tests..." << std::endl;
1767 
1768     if (platform == "Windows")
1769     {
1770       BOOST_TEST(path("//abc\\def/ghi").make_preferred().native()
1771         == path("\\\\abc\\def\\ghi").native());
1772     }
1773     else
1774     {
1775       BOOST_TEST(path("//abc\\def/ghi").make_preferred().native()
1776         == path("//abc\\def/ghi").native());
1777     }
1778   }
1779 
1780 } // unnamed namespace
1781 
1782 static boost::filesystem::path ticket_6737 = "FilePath";  // #6737 reported this crashed
1783                                                           // on VC++ debug mode build
1784 const boost::filesystem::path ticket_6690("test");  // #6690 another V++ static init crash
1785 
1786 //--------------------------------------------------------------------------------------//
1787 //                                                                                      //
1788 //                                     main                                             //
1789 //                                                                                      //
1790 //--------------------------------------------------------------------------------------//
1791 
cpp_main(int,char * [])1792 int cpp_main(int, char*[])
1793 {
1794   // The choice of platform is make at runtime rather than compile-time
1795   // so that compile errors for all platforms will be detected even though
1796   // only the current platform is runtime tested.
1797   platform = (platform == "Win32" || platform == "Win64" || platform == "Cygwin")
1798                ? "Windows"
1799                : "POSIX";
1800   std::cout << "Platform is " << platform << '\n';
1801 
1802   BOOST_TEST(p1.string() != p3.string());
1803   p3 = p2;
1804   BOOST_TEST(p1.string() == p3.string());
1805 
1806   path p04("foobar");
1807   BOOST_TEST(p04.string() == "foobar");
1808   p04 = p04; // self-assignment
1809   BOOST_TEST(p04.string() == "foobar");
1810 
1811   construction_tests();
1812   append_tests();
1813   self_assign_and_append_tests();
1814   overload_tests();
1815   query_and_decomposition_tests();
1816   composition_tests();
1817   iterator_tests();
1818   non_member_tests();
1819   exception_tests();
1820   name_function_tests();
1821   replace_extension_tests();
1822   make_preferred_tests();
1823 
1824   // verify deprecated names still available
1825 
1826 # ifndef BOOST_FILESYSTEM_NO_DEPRECATED
1827 
1828   p1.branch_path();
1829   p1.leaf();
1830   path p_remove_leaf;
1831   p_remove_leaf.remove_leaf();
1832 
1833 # endif
1834 
1835   std::string s1("//:somestring");  // this used to be treated specially
1836 
1837   // check the path member templates
1838   p5.assign(s1.begin(), s1.end());
1839 
1840   PATH_TEST_EQ(p5.string(), "//:somestring");
1841   p5 = s1;
1842   PATH_TEST_EQ(p5.string(), "//:somestring");
1843 
1844   // this code, courtesy of David Whetstone, detects a now fixed bug that
1845   // derefereced the end iterator (assuming debug build with checked itors)
1846   std::vector<char> v1;
1847   p5.assign(v1.begin(), v1.end());
1848   std::string s2(v1.begin(), v1.end());
1849   PATH_TEST_EQ(p5.string(), s2);
1850   p5.assign(s1.begin(), s1.begin() + 1);
1851   PATH_TEST_EQ(p5.string(), "/");
1852 
1853   BOOST_TEST(p1 != p4);
1854   BOOST_TEST(p1.string() == p2.string());
1855   BOOST_TEST(p1.string() == p3.string());
1856   BOOST_TEST(path("foo").filename() == "foo");
1857   BOOST_TEST(path("foo").parent_path().string() == "");
1858   BOOST_TEST(p1.filename() == "fum");
1859   BOOST_TEST(p1.parent_path().string() == "fe/fi/fo");
1860   BOOST_TEST(path("").empty() == true);
1861   BOOST_TEST(path("foo").empty() == false);
1862 
1863   // inserter and extractor tests
1864 # if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // bypass VC++ 7.0 and earlier
1865   std::cout << "\nInserter and extractor test...";
1866   std::stringstream ss;
1867   ss << fs::path("foo/bar") << std::endl;
1868   fs::path round_trip;
1869   ss >> round_trip;
1870   BOOST_TEST(round_trip.string() == "foo/bar");
1871   std::cout << round_trip.string() << "..." << round_trip << " complete\n";
1872 # endif
1873 
1874   return ::boost::report_errors();
1875 }
1876