brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.2 KiB · ef00a3f Raw
174 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++1410// UNSUPPORTED: no-filesystem11 12// <filesystem>13 14// path proximate(const path& p, error_code &ec)15// path proximate(const path& p, const path& base = current_path())16// path proximate(const path& p, const path& base, error_code& ec);17 18#include <filesystem>19#include <cassert>20 21#include "assert_macros.h"22#include "concat_macros.h"23#include "test_macros.h"24#include "count_new.h"25#include "filesystem_test_helper.h"26#include "../../class.path/path_helper.h"27namespace fs = std::filesystem;28 29static int count_path_elems(const fs::path& p) {30  int count = 0;31  for (auto&& elem : p) {32    if (elem != p.root_name() && elem != "/" && elem != "")33      ++count;34  }35  return count;36}37 38static void signature_test() {39  using fs::path;40  const path p;41  ((void)p);42  std::error_code ec;43  ((void)ec);44  ASSERT_NOT_NOEXCEPT(proximate(p));45  ASSERT_NOT_NOEXCEPT(proximate(p, p));46  ASSERT_NOT_NOEXCEPT(proximate(p, ec));47  ASSERT_NOT_NOEXCEPT(proximate(p, p, ec));48}49 50static void basic_test() {51  using fs::path;52  const path cwd        = fs::current_path();53  const path parent_cwd = cwd.parent_path();54  const path curdir     = cwd.filename();55  assert(!cwd.native().empty());56  int cwd_depth = count_path_elems(cwd);57  path dot_dot_to_root;58  for (int i = 0; i < cwd_depth; ++i)59    dot_dot_to_root /= "..";60  path relative_cwd = cwd.native().substr(cwd.root_path().native().size());61  // clang-format off62  struct {63    fs::path input;64    fs::path base;65    fs::path expect;66  } TestCases[] = {67      {"", "", "."},68      {cwd, "a", ".."},69      {parent_cwd, "a", "../.."},70      {"a", cwd, "a"},71      {"a", parent_cwd, curdir / "a"},72      {"/", "a", dot_dot_to_root / ".."},73      {"/", "a/b", dot_dot_to_root / "../.."},74      {"/", "a/b/", dot_dot_to_root / "../.."},75      {"a", "/", relative_cwd / "a"},76      {"a/b", "/", relative_cwd / "a/b"},77      {"a", "/net", ".." / relative_cwd / "a"},78#ifdef _WIN3279      {"//foo/", "//foo", "//foo/"},80      {"//foo", "//foo/", "//foo"},81#else82      {"//foo/", "//foo", "."},83      {"//foo", "//foo/", "."},84#endif85      {"//foo", "//foo", "."},86      {"//foo/", "//foo/", "."},87#ifdef _WIN3288      {"//foo", "a", "//foo"},89      {"//foo/a", "//bar", "//foo/a"},90      {"//foo/a", "//bar/", "//foo/a"},91      {"//foo/a", "b", "//foo/a"},92      {"//foo/a", "/b", "//foo/a"},93      {"//foo/a", "//bar/b", "//foo/a"},94      // Using X: instead of C: to avoid influence from the CWD being under C:95      {"X:/a", "X:/b", "../a"},96      {"X:/a", "X:b", "X:/a"},97      {"X:/a", "Y:/a", "X:/a"},98      {"X:/a", "Y:/b", "X:/a"},99      {"X:/a", "Y:b", "X:/a"},100      {"X:a", "X:/b", "X:a"},101      {"X:a", "X:b", "../a"},102      {"X:a", "Y:/a", "X:a"},103      {"X:a", "Y:/b", "X:a"},104      {"X:a", "Y:b", "X:a"},105#else106      {"//foo", "a", dot_dot_to_root / "../foo"},107      {"//foo/a", "//bar", "../foo/a"},108      {"//foo/a", "//bar/", "../foo/a"},109      {"//foo/a", "b", dot_dot_to_root / "../foo/a"},110      {"//foo/a", "/b", "../foo/a"},111      {"//foo/a", "//bar/b", "../../foo/a"},112      {"X:/a", "X:/b", "../a"},113      {"X:/a", "X:b", "../X:/a"},114      {"X:/a", "Y:/a", "../../X:/a"},115      {"X:/a", "Y:/b", "../../X:/a"},116      {"X:/a", "Y:b", "../X:/a"},117      {"X:a", "X:/b", "../../X:a"},118      {"X:a", "X:b", "../X:a"},119      {"X:a", "Y:/a", "../../X:a"},120      {"X:a", "Y:/b", "../../X:a"},121      {"X:a", "Y:b", "../X:a"},122#endif123      {"a", "a", "."},124      {"a/b", "a/b", "."},125      {"a/b/c/", "a/b/c/", "."},126      {"//foo/a/b", "//foo/a/b", "."},127      {"/a/d", "/a/b/c", "../../d"},128      {"/a/b/c", "/a/d", "../b/c"},129      {"a/b/c", "a", "b/c"},130      {"a/b/c", "a/b/c/x/y", "../.."},131      {"a/b/c", "a/b/c", "."},132      {"a/b", "c/d", "../../a/b"}133  };134  // clang-format on135  for (auto& TC : TestCases) {136    std::error_code ec    = GetTestEC();137    fs::path p            = TC.input;138    const fs::path output = fs::proximate(p, TC.base, ec);139    fs::path expect       = TC.expect;140    expect.make_preferred();141    TEST_REQUIRE(!ec,142                 TEST_WRITE_CONCATENATED(143                     "Input: ", TC.input.string(), "\nBase: ", TC.base.string(), "\nExpected: ", expect.string()));144 145    const path canon_input = fs::weakly_canonical(TC.input);146    const path canon_base  = fs::weakly_canonical(TC.base);147    const path lexically_p = canon_input.lexically_proximate(canon_base);148    TEST_REQUIRE(149        PathEq(output, expect),150        TEST_WRITE_CONCATENATED(151            "Input: ",152            TC.input.string(),153            "\nBase: ",154            TC.base.string(),155            "\nExpected: ",156            expect.string(),157            "\nOutput: ",158            output.string(),159            "\nLex Prox: ",160            lexically_p.string(),161            "\nCanon Input: ",162            canon_input.string(),163            "\nCanon Base: ",164            canon_base.string()));165  }166}167 168int main(int, char**) {169  signature_test();170  basic_test();171 172  return 0;173}174