blob: d83976338db9aa6984ad22e60371102b55c99bb3 [file] [log] [blame]
// Copyright (C) 2018-2021 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
#include <filesystem>
#include <testsuite_hooks.h>
using std::filesystem::filesystem_error;
// The COW std::string does not have noexcept copies, because copying a
// "leaked" string can throw (and for fully-dynamic strings, copying the
// empty rep can also throw).
// That's OK, because we know that the std::string in the std::runtime_error
// or std::logic_error base class won't be leaked (and usually won't be empty).
// The is_nothrow_xxx type traits don't know that though, so we can only
// check them for the cxx11 ABI, which uses __cow_string, which has noexcept
// copies.
#if _GLIBCXX_USE_CXX11_ABI
// PR libstdc++/83306
static_assert(std::is_nothrow_copy_constructible_v<filesystem_error>);
static_assert(std::is_nothrow_copy_assignable_v<filesystem_error>);
#endif
void
test01()
{
const char* const str = "error test";
const std::error_code ec = make_error_code(std::errc::is_a_directory);
const filesystem_error e1(str, ec);
auto e2 = e1;
VERIFY( e2.path1().empty() );
VERIFY( e2.path2().empty() );
VERIFY( std::string_view(e2.what()).find(str) != std::string_view::npos );
VERIFY( e2.code() == ec );
const filesystem_error e3(str, "test/path/one", ec);
auto e4 = e3;
VERIFY( e4.path1() == "test/path/one" );
VERIFY( e4.path2().empty() );
VERIFY( std::string_view(e4.what()).find(str) != std::string_view::npos );
VERIFY( e2.code() == ec );
const filesystem_error e5(str, "test/path/one", "/test/path/two", ec);
auto e6 = e5;
VERIFY( e6.path1() == "test/path/one" );
VERIFY( e6.path2() == "/test/path/two" );
VERIFY( std::string_view(e6.what()).find(str) != std::string_view::npos );
VERIFY( e2.code() == ec );
}
void
test02()
{
const char* const str = "error test";
const std::error_code ec = make_error_code(std::errc::is_a_directory);
const filesystem_error e1(str, ec);
filesystem_error e2("", {});
e2 = e1;
VERIFY( e2.path1().empty() );
VERIFY( e2.path2().empty() );
VERIFY( std::string_view(e2.what()).find(str) != std::string_view::npos );
VERIFY( e2.code() == ec );
const filesystem_error e3(str, "test/path/one", ec);
filesystem_error e4("", {});
e4 = e3;
VERIFY( e4.path1() == "test/path/one" );
VERIFY( e4.path2().empty() );
VERIFY( std::string_view(e4.what()).find(str) != std::string_view::npos );
VERIFY( e2.code() == ec );
const filesystem_error e5(str, "test/path/one", "/test/path/two", ec);
filesystem_error e6("", {});
e6 = e5;
VERIFY( e6.path1() == "test/path/one" );
VERIFY( e6.path2() == "/test/path/two" );
VERIFY( std::string_view(e6.what()).find(str) != std::string_view::npos );
VERIFY( e2.code() == ec );
}
void
test03()
{
filesystem_error e("test", std::error_code());
VERIFY( e.path1().empty() );
VERIFY( e.path2().empty() );
auto e2 = std::move(e);
// Observers must still be usable on moved-from object:
VERIFY( e.path1().empty() );
VERIFY( e.path2().empty() );
VERIFY( e.what() != nullptr );
e2 = std::move(e);
VERIFY( e.path1().empty() );
VERIFY( e.path2().empty() );
VERIFY( e.what() != nullptr );
}
int
main()
{
test01();
test02();
test03();
}