brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.9 KiB · 8279049 Raw
211 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 11// <filesystem>12 13// class path14 15// int compare(path const&) const noexcept;16// int compare(string_type const&) const;17// int compare(value_type const*) const;18//19// bool operator==(path const&, path const&) noexcept;20// bool operator!=(path const&, path const&) noexcept;21// bool operator< (path const&, path const&) noexcept;22// bool operator<=(path const&, path const&) noexcept;23// bool operator> (path const&, path const&) noexcept;24// bool operator>=(path const&, path const&) noexcept;25// strong_ordering operator<=>(path const&, path const&) noexcept;26//27// size_t hash_value(path const&) noexcept;28// template<> struct hash<filesystem::path>;29 30#include <filesystem>31#include <cassert>32#include <string>33#include <type_traits>34#include <vector>35 36#include "assert_macros.h"37#include "count_new.h"38#include "test_comparisons.h"39#include "test_iterators.h"40#include "test_macros.h"41namespace fs = std::filesystem;42 43struct PathCompareTest {44  const char* LHS;45  const char* RHS;46  int expect;47};48 49#define LONGA                                                                                                          \50  "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" \51  "AAAAAAAA"52#define LONGB                                                                                                          \53  "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" \54  "BBBBBBBB"55#define LONGC                                                                                                          \56  "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" \57  "CCCCCCCC"58#define LONGD                                                                                                          \59  "DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD" \60  "DDDDDDDD"61const PathCompareTest CompareTestCases[] = {62    {"", "", 0},63    {"a", "", 1},64    {"", "a", -1},65    {"a/b/c", "a/b/c", 0},66    {"b/a/c", "a/b/c", 1},67    {"a/b/c", "b/a/c", -1},68    {"a/b", "a/b/c", -1},69    {"a/b/c", "a/b", 1},70    {"a/b/", "a/b/.", -1},71    {"a/b/", "a/b", 1},72    {"a/b//////", "a/b/////.", -1},73    {"a/.././b", "a///..//.////b", 0},74    {"//foo//bar///baz////", "//foo/bar/baz/", 0}, // duplicate separators75    {"///foo/bar", "/foo/bar", 0},                 // "///" is not a root directory76    {"/foo/bar/", "/foo/bar", 1},                  // trailing separator77    {"foo", "/foo", -1}, // if !this->has_root_directory() and p.has_root_directory(), a value less than 0.78    {"/foo", "foo", 1},  //  if this->has_root_directory() and !p.has_root_directory(), a value greater than 0.79#ifdef _WIN3280    {"C:/a", "C:\\a", 0},81#else82    {"C:/a", "C:\\a", -1},83#endif84    {("//" LONGA "////" LONGB "/" LONGC "///" LONGD), ("//" LONGA "/" LONGB "/" LONGC "/" LONGD), 0},85    {(LONGA "/" LONGB "/" LONGC), (LONGA "/" LONGB "/" LONGB), 1}86 87};88#undef LONGA89#undef LONGB90#undef LONGC91#undef LONGD92 93static inline int normalize_ret(int ret) { return ret < 0 ? -1 : (ret > 0 ? 1 : 0); }94 95void test_compare_basic() {96  using namespace fs;97  for (auto const& TC : CompareTestCases) {98    const path p1(TC.LHS);99    const path p2(TC.RHS);100    std::string RHS(TC.RHS);101    const path::string_type R(RHS.begin(), RHS.end());102    const std::basic_string_view<path::value_type> RV(R);103    const path::value_type* Ptr = R.c_str();104    const int E                 = TC.expect;105    {                           // compare(...) functions106      DisableAllocationGuard g; // none of these operations should allocate107 108      // check runtime results109      int ret1 = normalize_ret(p1.compare(p2));110      int ret2 = normalize_ret(p1.compare(R));111      int ret3 = normalize_ret(p1.compare(Ptr));112      int ret4 = normalize_ret(p1.compare(RV));113 114      g.release();115      assert(ret1 == ret2);116      assert(ret1 == ret3);117      assert(ret1 == ret4);118      assert(ret1 == E);119 120      // check signatures121      ASSERT_NOEXCEPT(p1.compare(p2));122    }123    {                           // comparison operators124      DisableAllocationGuard g; // none of these operations should allocate125 126      // check signatures127      AssertComparisonsAreNoexcept<path>();128      AssertComparisonsReturnBool<path>();129#if TEST_STD_VER > 17130      AssertOrderAreNoexcept<path>();131      AssertOrderReturn<std::strong_ordering, path>();132#endif133 134      // check comparison results135      assert(testComparisons(p1, p2, /*isEqual*/ E == 0, /*isLess*/ E < 0));136#if TEST_STD_VER > 17137      assert(testOrder(p1, p2, E <=> 0));138#endif139    }140    { // check hash values141      auto h1 = hash_value(p1);142      auto h2 = hash_value(p2);143      assert((h1 == h2) == (p1 == p2));144      // check signature145      ASSERT_SAME_TYPE(std::size_t, decltype(hash_value(p1)));146      ASSERT_NOEXCEPT(hash_value(p1));147    }148    { // check std::hash149      auto h1 = std::hash<fs::path>()(p1);150      auto h2 = std::hash<fs::path>()(p2);151      assert((h1 == h2) == (p1 == p2));152      // check signature153      ASSERT_SAME_TYPE(std::size_t, decltype(std::hash<fs::path>()(p1)));154      ASSERT_NOEXCEPT(std::hash<fs::path>()(p1));155    }156  }157}158 159int CompareElements(std::vector<std::string> const& LHS, std::vector<std::string> const& RHS) {160  bool IsLess = std::lexicographical_compare(LHS.begin(), LHS.end(), RHS.begin(), RHS.end());161  if (IsLess)162    return -1;163 164  bool IsGreater = std::lexicographical_compare(RHS.begin(), RHS.end(), LHS.begin(), LHS.end());165  if (IsGreater)166    return 1;167 168  return 0;169}170 171void test_compare_elements() {172  struct {173    std::vector<std::string> LHSElements;174    std::vector<std::string> RHSElements;175    int Expect;176  } TestCases[] = {177      {{"a"}, {"a"}, 0},178      {{"a"}, {"b"}, -1},179      {{"b"}, {"a"}, 1},180      {{"a", "b", "c"}, {"a", "b", "c"}, 0},181      {{"a", "b", "c"}, {"a", "b", "d"}, -1},182      {{"a", "b", "d"}, {"a", "b", "c"}, 1},183      {{"a", "b"}, {"a", "b", "c"}, -1},184      {{"a", "b", "c"}, {"a", "b"}, 1},185 186  };187 188  auto BuildPath = [](std::vector<std::string> const& Elems) {189    fs::path p;190    for (auto& E : Elems)191      p /= E;192    return p;193  };194 195  for (auto& TC : TestCases) {196    fs::path LHS        = BuildPath(TC.LHSElements);197    fs::path RHS        = BuildPath(TC.RHSElements);198    const int ExpectCmp = CompareElements(TC.LHSElements, TC.RHSElements);199    assert(ExpectCmp == TC.Expect);200    const int GotCmp = normalize_ret(LHS.compare(RHS));201    assert(GotCmp == TC.Expect);202  }203}204 205int main(int, char**) {206  test_compare_basic();207  test_compare_elements();208 209  return 0;210}211