reapack

Package manager for REAPER
Log | Files | Refs | Submodules | README | LICENSE

path.cpp (7642B)


      1 #include "helper.hpp"
      2 
      3 #include <path.hpp>
      4 
      5 using Catch::Matchers::StartsWith;
      6 
      7 static const char *M = "[path]";
      8 
      9 TEST_CASE("compare paths", M) {
     10   const Path a = Path("hello");
     11   const Path b = Path("world");
     12 
     13   REQUIRE_FALSE(a == b);
     14   REQUIRE(a != b);
     15 
     16   REQUIRE(a == a);
     17   REQUIRE_FALSE(a != a);
     18 }
     19 
     20 TEST_CASE("append path segments", M) {
     21   Path path;
     22   REQUIRE(path.empty());
     23   REQUIRE(path.size() == 0);
     24 
     25   path.append(std::string{});
     26   REQUIRE(path.empty());
     27   REQUIRE(path.size() == 0);
     28 
     29   path.append("foo");
     30   REQUIRE_FALSE(path.empty());
     31   REQUIRE(path.size() == 1);
     32 
     33   path.append("bar");
     34   REQUIRE(path.size() == 2);
     35 
     36   path.append("baz");
     37   REQUIRE(path.size() == 3);
     38 }
     39 
     40 TEST_CASE("path dirname", M) {
     41   Path path;
     42   REQUIRE(path.dirname().empty());
     43 
     44   path.append("foo");
     45   REQUIRE(path.dirname().empty());
     46 
     47   path.append("bar");
     48   REQUIRE(path.dirname() == Path("foo"));
     49 
     50   path.append("baz");
     51   REQUIRE(path.dirname() == Path("foo/bar"));
     52 }
     53 
     54 TEST_CASE("path basename", M) {
     55   Path path;
     56   REQUIRE(path.basename().empty());
     57 
     58   path.append("foo");
     59   REQUIRE(path.basename() == "foo");
     60 
     61   path.append("bar");
     62   REQUIRE(path.basename() == "bar");
     63 }
     64 
     65 TEST_CASE("path first segment", M) {
     66   Path path;
     67   REQUIRE(path.front().empty());
     68 
     69   path.append("foo");
     70   REQUIRE(path.front() == "foo");
     71 }
     72 
     73 TEST_CASE("concatenate paths", M) {
     74   const Path a("hello");
     75   const Path b("world");
     76 
     77   Path c;
     78   c.append("hello");
     79   c += "world";
     80 
     81   REQUIRE(a + b == c);
     82   REQUIRE(a + "world" == c);
     83 }
     84 
     85 TEST_CASE("strip trailing/leading slashes", M) {
     86   Path a;
     87   a.append("a/b/");
     88   a.append("/c/d/");
     89   a.append(Path("/e/f/"));
     90 
     91   REQUIRE(a.size() == 6);
     92 #ifndef _WIN32
     93   REQUIRE(a.join() == "a/b/c/d/e/f");
     94 #else
     95   REQUIRE(a.join() == "a\\b\\c\\d\\e\\f");
     96 #endif
     97 }
     98 
     99 TEST_CASE("clear path", M) {
    100   Path a;
    101   a.append("test");
    102   CHECK(a.size() == 1);
    103 
    104   a.clear();
    105   REQUIRE(a.size() == 0);
    106 }
    107 
    108 TEST_CASE("modify path", M) {
    109   Path a;
    110   a.append("hello");
    111 
    112   a[0] = "world";
    113   REQUIRE(a.join() == "world");
    114 }
    115 
    116 TEST_CASE("force unix separator", M) {
    117   Path a;
    118   a.append("hello");
    119   a.append("world");
    120 
    121   REQUIRE(a.join(false) == "hello/world");
    122 }
    123 
    124 TEST_CASE("split input", M) {
    125   SECTION("slash") {
    126     const Path a("hello/world");
    127 
    128     REQUIRE(a.size() == 2);
    129     REQUIRE(a[0] == "hello");
    130     REQUIRE(a[1] == "world");
    131   }
    132 
    133   SECTION("backslash") {
    134     const Path a("hello\\world");
    135 
    136     REQUIRE(a.size() == 2);
    137     REQUIRE(a[0] == "hello");
    138     REQUIRE(a[1] == "world");
    139   }
    140 
    141   SECTION("append") {
    142     Path a;
    143     a.append("hello/world");
    144     REQUIRE(a.size() == 2);
    145 
    146     a += "chunky/bacon";
    147     REQUIRE(a.size() == 4);
    148   }
    149 
    150   SECTION("skip empty parts") {
    151     const Path a("hello//world/");
    152 
    153     REQUIRE(a.size() == 2);
    154     REQUIRE(a[0] == "hello");
    155     REQUIRE(a[1] == "world");
    156   }
    157 }
    158 
    159 TEST_CASE("absolute path", M) {
    160   CHECK_FALSE(Path("a/b").test(Path::Absolute));
    161 
    162 #ifdef _WIN32
    163   const Path a("C:\\Windows\\System32");
    164 #else
    165   const Path a("/usr/bin/zsh");
    166 #endif
    167 
    168   REQUIRE(a.test(Path::Absolute));
    169   CHECK(a.size() == 3);
    170 
    171 #ifdef _WIN32
    172   CHECK(a[0] == "C:");
    173   CHECK(a.join() == "C:\\Windows\\System32");
    174 #else
    175   CHECK(a[0] == "usr");
    176   CHECK(a.join() == "/usr/bin/zsh");
    177 #endif
    178 }
    179 
    180 TEST_CASE("absolute path (root only)", M) {
    181 #ifdef _WIN32
    182   const Path a("C:");
    183 #else
    184   const Path a("/");
    185 #endif
    186 
    187   REQUIRE(a.test(Path::Absolute));
    188 
    189 #ifdef _WIN32
    190   CHECK(a.size() == 1);
    191   CHECK(a[0] == "C:");
    192   CHECK(a.join() == "C:");
    193 #else
    194   CHECK(a.size() == 0);
    195   CHECK(a.join() == "/");
    196 #endif
    197 }
    198 
    199 TEST_CASE("append absolute path to empty path", M) {
    200 #ifdef _WIN32
    201   const Path abs("C:\\Windows\\");
    202 #else
    203   const Path abs("/usr/bin");
    204 #endif
    205 
    206   Path path;
    207   path += abs;
    208 
    209   CHECK(path == abs);
    210   REQUIRE(path.test(Path::Absolute));
    211 }
    212 
    213 TEST_CASE("extended absolute paths", M) {
    214 #ifdef _WIN32
    215   Path abs("C:\\");
    216   abs.append(std::string(245, 'a'));
    217 
    218   CHECK(abs.test(Path::Absolute));
    219   REQUIRE_THAT(abs.join(), StartsWith("\\\\?\\"));
    220 
    221   const Path path(std::string(500, 'a'));
    222   CHECK_FALSE(path.test(Path::Absolute));
    223 #else
    224   Path path("/hello");
    225   path.append(std::string(260, 'a'));
    226 #endif
    227 
    228   REQUIRE_THAT(path.join(), !StartsWith("\\\\?\\"));
    229 }
    230 
    231 #ifdef _WIN32
    232 TEST_CASE("UNC path", M) {
    233   const Path unc("\\\\FOO\\bar");
    234   REQUIRE(unc.test(Path::Absolute));
    235   REQUIRE(unc.test(Path::UNC));
    236   CHECK(unc.size() == 2);
    237 
    238   CHECK(unc[0] == "FOO");
    239   CHECK(unc.join() == "\\\\FOO\\bar");
    240 }
    241 
    242 TEST_CASE("UNC path extended", M) {
    243   Path unc("\\\\FOO");
    244   unc.append(std::string(260, 'a'));
    245 
    246   CHECK(unc.test(Path::Absolute));
    247   CHECK(unc.test(Path::UNC));
    248   REQUIRE_THAT(unc.join(), StartsWith("\\\\?\\UNC\\FOO"));
    249 }
    250 #else
    251 TEST_CASE("compare absolute to relative path (unix)", M) {
    252   REQUIRE(Path("/a/b") != Path("a/b"));
    253 }
    254 
    255 TEST_CASE("top-level unix absolute path (p=2359736)", M) {
    256   Path p("/foo");
    257   REQUIRE(p[0] == "foo");
    258 }
    259 #endif
    260 
    261 TEST_CASE("remove last segment of path", M) {
    262   Path a;
    263   a.append("a");
    264   a.append("b");
    265 
    266   CHECK(a.size() == 2);
    267 
    268   a.removeLast();
    269 
    270   REQUIRE(a.size() == 1);
    271   REQUIRE(a[0] == "a");
    272 
    273   a.removeLast();
    274   REQUIRE(a.empty());
    275 
    276   a.removeLast(); // no crash
    277 }
    278 
    279 TEST_CASE("prepend root path", M) {
    280   const Path path("world");
    281 
    282   REQUIRE(path.prependRoot() == Path("world"));
    283 
    284   {
    285     UseRootPath root(Path("hello"));
    286     (void)root;
    287 
    288     REQUIRE(path.prependRoot() == Path("hello/world"));
    289   }
    290 
    291   REQUIRE(path.prependRoot() == Path("world"));
    292 }
    293 
    294 TEST_CASE("remove root path", M) {
    295   const Path path("hello/world");
    296 
    297   REQUIRE(path.removeRoot() == Path("hello/world"));
    298 
    299   {
    300     UseRootPath root(Path("hello"));
    301     (void)root;
    302 
    303     REQUIRE(path.removeRoot() == Path("world"));
    304   }
    305 
    306   REQUIRE(path.removeRoot() == Path("hello/world"));
    307 }
    308 
    309 TEST_CASE("append with directory traversal enabled", M) {
    310   SECTION("dot")
    311     REQUIRE(Path("a/./b/.") == Path("a/b"));
    312 
    313   SECTION("dotdot")
    314     REQUIRE(Path("a/../b") == Path("b"));
    315 }
    316 
    317 TEST_CASE("append with directory traversal disabled", M) {
    318   Path a;
    319 
    320   SECTION("dot")
    321     a.append("a/./b/.", false);
    322 
    323   SECTION("dotdot")
    324     a.append("a/../b", false);
    325 
    326   REQUIRE(a == Path("a/b"));
    327 }
    328 
    329 TEST_CASE("concatenate with directory traversal", M) {
    330   SECTION("path + string") {
    331     // concatenating a std::string to a path, directory traversal is applied
    332     const Path a = Path("a/b/c") + "../../../d/e/f";
    333     REQUIRE(a == Path("d/e/f"));
    334   }
    335 
    336   SECTION("path + path") {
    337     // here, the directory traversal segments are lost before concatenating
    338     const Path b = Path("a/b/c") + Path("../../../d/e/f");
    339     REQUIRE(b == Path("a/b/c/d/e/f"));
    340   }
    341 }
    342 
    343 TEST_CASE("append full paths", M) {
    344   Path a;
    345   a += Path("a/b");
    346   a.append(Path("c/d"));
    347   a.append(Path("e/f"));
    348 
    349   REQUIRE(a == Path("a/b/c/d/e/f"));
    350 }
    351 
    352 TEST_CASE("temporary path", M) {
    353   TempPath a(Path("hello/world"));
    354 
    355   REQUIRE(a.target() == Path("hello/world"));
    356   REQUIRE(a.temp() == Path("hello/world.part"));
    357 }
    358 
    359 TEST_CASE("path starts with", M) {
    360   const Path ref("a/b");
    361 
    362   REQUIRE(ref.startsWith(ref));
    363   REQUIRE(Path("a/b/c").startsWith(ref));
    364 #ifndef _WIN32
    365   REQUIRE_FALSE(Path("/a/b/c").startsWith(ref));
    366 #endif
    367   REQUIRE_FALSE(Path("0/a/b/c").startsWith(ref));
    368   REQUIRE_FALSE(Path("a").startsWith(ref));
    369 }
    370 
    371 TEST_CASE("remove path segments", M) {
    372   Path path("/a/b/c/d/e");
    373 
    374   SECTION("remove from start") {
    375     path.remove(0, 1);
    376     REQUIRE(path == Path("b/c/d/e"));
    377     REQUIRE_FALSE(path.test(Path::Absolute));
    378   }
    379 
    380   SECTION("remove from middle") {
    381     path.remove(1, 2);
    382     REQUIRE(path == Path("/a/d/e"));
    383 #ifndef _WIN32
    384     REQUIRE(path.test(Path::Absolute));
    385 #endif
    386   }
    387 
    388   SECTION("remove past the end") {
    389     path.remove(4, 2);
    390     path.remove(18, 1);
    391     REQUIRE(path == Path("/a/b/c/d"));
    392   }
    393 }