gdb::optional unit tests

I thought I'd add some unit tests to make sure gdb::optional behaved
correctly, and started writing some, but then thought/realized that
libstdc++ already has extensive testing for C++17 std::optional, which
gdb::optional is a subset of, and thought why bother writing something
from scratch.  So I tried copying over a subset of libstdc++'s tests
(that ones that cover the subset supported by gdb::optional), and was
positively surprised that they mostly work OOTB.  This did help shake
out a few bugs from what I was implementing in the previous patch to
gdb::optional.  Still, it's a good chunk of code being copied over, so
if people dislike this copying/duplication, I can drop this patch.

gdb/ChangeLog:
2017-04-18  Pedro Alves  <palves@redhat.com>

	* Makefile.in (SUBDIR_UNITTESTS_SRCS): Add
	unittests/optional-selftests.c.
	(SUBDIR_UNITTESTS_OBS): Add optional-selftests.o.
	* unittests/optional-selftests.c: New file.
	* unittests/optional/assignment/1.cc: New file.
	* unittests/optional/assignment/2.cc: New file.
	* unittests/optional/assignment/3.cc: New file.
	* unittests/optional/assignment/4.cc: New file.
	* unittests/optional/assignment/5.cc: New file.
	* unittests/optional/assignment/6.cc: New file.
	* unittests/optional/assignment/7.cc: New file.
	* unittests/optional/cons/copy.cc: New file.
	* unittests/optional/cons/default.cc: New file.
	* unittests/optional/cons/move.cc: New file.
	* unittests/optional/cons/value.cc: New file.
	* unittests/optional/in_place.cc: New file.
	* unittests/optional/observers/1.cc: New file.
	* unittests/optional/observers/2.cc: New file.
This commit is contained in:
Pedro Alves 2017-04-18 21:39:24 +01:00
parent 22796e972f
commit d35d19584c
17 changed files with 1751 additions and 2 deletions

View File

@ -1,3 +1,24 @@
2017-04-18 Pedro Alves <palves@redhat.com>
* Makefile.in (SUBDIR_UNITTESTS_SRCS): Add
unittests/optional-selftests.c.
(SUBDIR_UNITTESTS_OBS): Add optional-selftests.o.
* unittests/optional-selftests.c: New file.
* unittests/optional/assignment/1.cc: New file.
* unittests/optional/assignment/2.cc: New file.
* unittests/optional/assignment/3.cc: New file.
* unittests/optional/assignment/4.cc: New file.
* unittests/optional/assignment/5.cc: New file.
* unittests/optional/assignment/6.cc: New file.
* unittests/optional/assignment/7.cc: New file.
* unittests/optional/cons/copy.cc: New file.
* unittests/optional/cons/default.cc: New file.
* unittests/optional/cons/move.cc: New file.
* unittests/optional/cons/value.cc: New file.
* unittests/optional/in_place.cc: New file.
* unittests/optional/observers/1.cc: New file.
* unittests/optional/observers/2.cc: New file.
2017-04-18 Pedro Alves <palves@redhat.com>
* common/gdb_optional.h: Include common/traits.h.

View File

@ -526,12 +526,14 @@ SUBDIR_PYTHON_CFLAGS =
SUBDIR_UNITTESTS_SRCS = \
unittests/function-view-selftests.c \
unittests/offset-type-selftests.c \
unittests/ptid-selftests.c
unittests/ptid-selftests.c \
unittests/optional-selftests.c
SUBDIR_UNITTESTS_OBS = \
function-view-selftests.o \
offset-type-selftests.o \
ptid-selftests.o
ptid-selftests.o \
optional-selftests.o
# Opcodes currently live in one of two places. Either they are in the
# opcode library, typically ../opcodes, or they are in a header file

View File

@ -0,0 +1,94 @@
/* Self tests for optional for GDB, the GNU debugger.
Copyright (C) 2017 Free Software Foundation, Inc.
This file is part of GDB.
This program 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 of the License, or
(at your option) any later version.
This program 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 program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "selftest.h"
#include "common/gdb_optional.h"
/* Used by the included .cc files below. Included here because the
included test files are wrapped in a namespace. */
#include <vector>
#include <string>
#include <memory>
/* libstdc++'s testsuite uses VERIFY. */
#define VERIFY SELF_CHECK
/* Used to disable testing features not supported by
gdb::optional. */
#define GDB_OPTIONAL
namespace selftests {
namespace optional {
/* The actual tests live in separate files, which were originally
copied over from libstdc++'s testsuite. To preserve the structure
and help with comparison with the original tests, the file names
have been preserved, and only minimal modification was done to have
them compile against gdb::optional instead of std::optional:
- std::optional->gdb:optional, etc.
- ATTRIBUTE_UNUSED in a few places
- wrap each file in a namespace so they can all be compiled as a
single unit.
- libstdc++'s license and formatting style was preserved.
*/
#include "optional/assignment/1.cc"
#include "optional/assignment/2.cc"
#include "optional/assignment/3.cc"
#include "optional/assignment/4.cc"
#include "optional/assignment/5.cc"
#include "optional/assignment/6.cc"
#include "optional/assignment/7.cc"
#include "optional/cons/copy.cc"
#include "optional/cons/default.cc"
#include "optional/cons/move.cc"
#include "optional/cons/value.cc"
#include "optional/in_place.cc"
#include "optional/observers/1.cc"
#include "optional/observers/2.cc"
static void
run_tests ()
{
assign_1::test ();
assign_2::test ();
assign_3::test ();
assign_4::test ();
assign_5::test ();
assign_6::test ();
assign_7::test ();
cons_copy::test ();
cons_default::test ();
cons_move::test ();
cons_value::test ();
in_place::test ();
observers_1::test ();
observers_2::test ();
}
} /* namespace optional */
} /* namespace selftests */
void
_initialize_optional_selftests ()
{
register_self_test (selftests::optional::run_tests);
}

View File

@ -0,0 +1,195 @@
// Copyright (C) 2013-2017 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/>.
namespace assign_1 {
struct exception {};
int counter = 0;
struct mixin_counter
{
mixin_counter() { ++counter; }
mixin_counter(mixin_counter const&) { ++counter; }
~mixin_counter() { --counter; }
};
struct value_type : private mixin_counter
{
enum state_type
{
zero,
moved_from,
throwing_construction,
throwing_copy,
throwing_copy_assignment,
throwing_move,
throwing_move_assignment,
threw,
};
value_type() = default;
explicit value_type(state_type state_)
: state(state_)
{
throw_if(throwing_construction);
}
value_type(value_type const& other)
: state(other.state)
{
throw_if(throwing_copy);
}
value_type&
operator=(value_type const& other)
{
state = other.state;
throw_if(throwing_copy_assignment);
return *this;
}
value_type(value_type&& other)
: state(other.state)
{
other.state = moved_from;
throw_if(throwing_move);
}
value_type&
operator=(value_type&& other)
{
state = other.state;
other.state = moved_from;
throw_if(throwing_move_assignment);
return *this;
}
void throw_if(state_type match)
{
if(state == match)
{
state = threw;
throw exception {};
}
}
state_type state = zero;
};
void test()
{
using O = gdb::optional<value_type>;
using S = value_type::state_type;
auto const make = [](S s = S::zero) { return O { gdb::in_place, s }; };
enum outcome_type { nothrow, caught, bad_catch };
// Check copy/move assignment for disengaged optional
// From disengaged optional
{
O o;
VERIFY( !o );
O p;
o = p;
VERIFY( !o );
VERIFY( !p );
}
{
O o;
VERIFY( !o );
O p;
o = std::move(p);
VERIFY( !o );
VERIFY( !p );
}
#ifndef GDB_OPTIONAL
{
O o;
VERIFY( !o );
o = {};
VERIFY( !o );
}
#endif
// From engaged optional
{
O o;
VERIFY( !o );
O p = make(S::throwing_copy_assignment);
o = p;
VERIFY( o && o->state == S::throwing_copy_assignment );
VERIFY( p && p->state == S::throwing_copy_assignment );
}
{
O o;
VERIFY( !o );
O p = make(S::throwing_move_assignment);
o = std::move(p);
VERIFY( o && o->state == S::throwing_move_assignment );
VERIFY( p && p->state == S::moved_from );
}
{
outcome_type outcome {};
O o;
VERIFY( !o );
O p = make(S::throwing_copy);
try
{
o = p;
}
catch(exception const&)
{ outcome = caught; }
catch(...)
{ outcome = bad_catch; }
VERIFY( outcome == caught );
VERIFY( !o );
VERIFY( p && p->state == S::throwing_copy );
}
{
outcome_type outcome {};
O o;
VERIFY( !o );
O p = make(S::throwing_move);
try
{
o = std::move(p);
}
catch(exception const&)
{ outcome = caught; }
catch(...)
{ outcome = bad_catch; }
VERIFY( outcome == caught );
VERIFY( !o );
VERIFY( p && p->state == S::moved_from );
}
VERIFY( counter == 0 );
}
} // namespace assign_1

View File

@ -0,0 +1,193 @@
// Copyright (C) 2013-2017 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/>.
namespace assign_2 {
struct exception {};
int counter = 0;
struct mixin_counter
{
mixin_counter() { ++counter; }
mixin_counter(mixin_counter const&) { ++counter; }
~mixin_counter() { --counter; }
};
struct value_type : private mixin_counter
{
enum state_type
{
zero,
moved_from,
throwing_construction,
throwing_copy,
throwing_copy_assignment,
throwing_move,
throwing_move_assignment,
threw,
};
value_type() = default;
explicit value_type(state_type state_)
: state(state_)
{
throw_if(throwing_construction);
}
value_type(value_type const& other)
: state(other.state)
{
throw_if(throwing_copy);
}
value_type&
operator=(value_type const& other)
{
state = other.state;
throw_if(throwing_copy_assignment);
return *this;
}
value_type(value_type&& other)
: state(other.state)
{
other.state = moved_from;
throw_if(throwing_move);
}
value_type&
operator=(value_type&& other)
{
state = other.state;
other.state = moved_from;
throw_if(throwing_move_assignment);
return *this;
}
void throw_if(state_type match)
{
if(state == match)
{
state = threw;
throw exception {};
}
}
state_type state = zero;
};
void test()
{
using O = gdb::optional<value_type>;
using S = value_type::state_type;
auto const make = [](S s = S::zero) { return O { gdb::in_place, s }; };
enum outcome_type { nothrow, caught, bad_catch };
// Check copy/move assignment for engaged optional
// From disengaged optional
{
O o = make(S::zero);
VERIFY( o );
O p;
o = p;
VERIFY( !o );
VERIFY( !p );
}
{
O o = make(S::zero);
VERIFY( o );
O p;
o = std::move(p);
VERIFY( !o );
VERIFY( !p );
}
#ifndef GDB_OPTIONAL
{
O o = make(S::zero);
VERIFY( o );
o = {};
VERIFY( !o );
}
#endif
// From engaged optional
{
O o = make(S::zero);
VERIFY( o );
O p = make(S::throwing_copy);
o = p;
VERIFY( o && o->state == S::throwing_copy);
VERIFY( p && p->state == S::throwing_copy);
}
{
O o = make(S::zero);
VERIFY( o );
O p = make(S::throwing_move);
o = std::move(p);
VERIFY( o && o->state == S::throwing_move);
VERIFY( p && p->state == S::moved_from);
}
{
ATTRIBUTE_UNUSED outcome_type outcome {};
O o = make(S::zero);
VERIFY( o );
O p = make(S::throwing_copy_assignment);
try
{
o = p;
}
catch(exception const&)
{ outcome = caught; }
catch(...)
{ outcome = bad_catch; }
VERIFY( o && o->state == S::threw);
VERIFY( p && p->state == S::throwing_copy_assignment);
}
{
ATTRIBUTE_UNUSED outcome_type outcome {};
O o = make(S::zero);
VERIFY( o );
O p = make(S::throwing_move_assignment);
try
{
o = std::move(p);
}
catch(exception const&)
{ outcome = caught; }
catch(...)
{ outcome = bad_catch; }
VERIFY( o && o->state == S::threw);
VERIFY( p && p->state == S::moved_from);
}
VERIFY( counter == 0 );
}
} // namespace assign_2

View File

@ -0,0 +1,156 @@
// Copyright (C) 2013-2017 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/>.
namespace assign_3 {
struct exception {};
int counter = 0;
struct mixin_counter
{
mixin_counter() { ++counter; }
mixin_counter(mixin_counter const&) { ++counter; }
~mixin_counter() { --counter; }
};
struct value_type : private mixin_counter
{
enum state_type
{
zero,
moved_from,
throwing_construction,
throwing_copy,
throwing_copy_assignment,
throwing_move,
throwing_move_assignment,
threw,
};
value_type() = default;
explicit value_type(state_type state_)
: state(state_)
{
throw_if(throwing_construction);
}
value_type(value_type const& other)
: state(other.state)
{
throw_if(throwing_copy);
}
value_type&
operator=(value_type const& other)
{
state = other.state;
throw_if(throwing_copy_assignment);
return *this;
}
value_type(value_type&& other)
: state(other.state)
{
other.state = moved_from;
throw_if(throwing_move);
}
value_type&
operator=(value_type&& other)
{
state = other.state;
other.state = moved_from;
throw_if(throwing_move_assignment);
return *this;
}
void throw_if(state_type match)
{
if(state == match)
{
state = threw;
throw exception {};
}
}
state_type state = zero;
};
void test()
{
using O = gdb::optional<value_type>;
using S = value_type::state_type;
auto const make = [](S s = S::zero) { return value_type { s }; };
enum outcome_type { nothrow, caught, bad_catch };
// Check value assignment for disengaged optional
{
O o;
value_type v = make(S::throwing_copy_assignment);
o = v;
VERIFY( o && o->state == S::throwing_copy_assignment );
}
{
O o;
value_type v = make(S::throwing_move_assignment);
o = std::move(v);
VERIFY( o && o->state == S::throwing_move_assignment );
}
{
ATTRIBUTE_UNUSED outcome_type outcome {};
O o;
value_type v = make(S::throwing_copy);
try
{
o = v;
}
catch(exception const&)
{ outcome = caught; }
catch(...)
{ outcome = bad_catch; }
VERIFY( !o );
}
{
ATTRIBUTE_UNUSED outcome_type outcome {};
O o;
value_type v = make(S::throwing_move);
try
{
o = std::move(v);
}
catch(exception const&)
{ outcome = caught; }
catch(...)
{ outcome = bad_catch; }
VERIFY( !o );
}
VERIFY( counter == 0 );
}
} // namespace assign_3

View File

@ -0,0 +1,156 @@
// Copyright (C) 2013-2017 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/>.
namespace assign_4 {
struct exception {};
int counter = 0;
struct mixin_counter
{
mixin_counter() { ++counter; }
mixin_counter(mixin_counter const&) { ++counter; }
~mixin_counter() { --counter; }
};
struct value_type : private mixin_counter
{
enum state_type
{
zero,
moved_from,
throwing_construction,
throwing_copy,
throwing_copy_assignment,
throwing_move,
throwing_move_assignment,
threw,
};
value_type() = default;
explicit value_type(state_type state_)
: state(state_)
{
throw_if(throwing_construction);
}
value_type(value_type const& other)
: state(other.state)
{
throw_if(throwing_copy);
}
value_type&
operator=(value_type const& other)
{
state = other.state;
throw_if(throwing_copy_assignment);
return *this;
}
value_type(value_type&& other)
: state(other.state)
{
other.state = moved_from;
throw_if(throwing_move);
}
value_type&
operator=(value_type&& other)
{
state = other.state;
other.state = moved_from;
throw_if(throwing_move_assignment);
return *this;
}
void throw_if(state_type match)
{
if(state == match)
{
state = threw;
throw exception {};
}
}
state_type state = zero;
};
void test()
{
using O = gdb::optional<value_type>;
using S = value_type::state_type;
auto const make = [](S s = S::zero) { return value_type { s }; };
enum outcome_type { nothrow, caught, bad_catch };
// Check value assignment for engaged optional
{
O o = make();
value_type v = make(S::throwing_copy);
o = v;
VERIFY( o && o->state == S::throwing_copy);
}
{
O o = make();
value_type v = make(S::throwing_move);
o = std::move(v);
VERIFY( o && o->state == S::throwing_move);
}
{
ATTRIBUTE_UNUSED outcome_type outcome {};
O o = make();
value_type v = make(S::throwing_copy_assignment);
try
{
o = v;
}
catch(exception const&)
{ outcome = caught; }
catch(...)
{ outcome = bad_catch; }
VERIFY( o && o->state == S::threw );
}
{
ATTRIBUTE_UNUSED outcome_type outcome {};
O o = make();
value_type v = make(S::throwing_move_assignment);
try
{
o = std::move(v);
}
catch(exception const&)
{ outcome = caught; }
catch(...)
{ outcome = bad_catch; }
VERIFY( o && o->state == S::threw );
}
VERIFY( counter == 0 );
}
} // namespace assign_4

View File

@ -0,0 +1,80 @@
// Copyright (C) 2013-2017 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/>.
namespace assign_5 {
int counter = 0;
struct mixin_counter
{
mixin_counter() { ++counter; }
mixin_counter(mixin_counter const&) { ++counter; }
~mixin_counter() { --counter; }
};
struct value_type : private mixin_counter { };
void test()
{
using O = gdb::optional<value_type>;
// Check std::nullopt_t and 'default' (= {}) assignment
#ifndef GDB_OPTIONAL
{
O o;
o = std::nullopt;
VERIFY( !o );
}
#endif
#ifndef GDB_OPTIONAL
{
O o { gdb::in_place };
o = std::nullopt;
VERIFY( !o );
}
#endif
#ifndef GDB_OPTIONAL
{
O o;
o = {};
VERIFY( !o );
}
#endif
#ifndef GDB_OPTIONAL
{
O o { gdb::in_place };
o = {};
VERIFY( !o );
}
#endif
{
gdb::optional<std::vector<int>> ovi{{1, 2, 3}};
VERIFY(ovi->size() == 3);
VERIFY((*ovi)[0] == 1 && (*ovi)[1] == 2 && (*ovi)[2] == 3);
ovi = {4, 5, 6, 7};
VERIFY(ovi->size() == 4);
VERIFY((*ovi)[0] == 4 && (*ovi)[1] == 5 &&
(*ovi)[2] == 6 && (*ovi)[3] == 7);
}
VERIFY( counter == 0 );
}
} // namespace assign_5

View File

@ -0,0 +1,90 @@
// Copyright (C) 2013-2017 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/>.
namespace assign_6 {
int counter = 0;
struct mixin_counter
{
mixin_counter() { ++counter; }
mixin_counter(mixin_counter const&) { ++counter; }
~mixin_counter() { --counter; }
};
struct value_type : private mixin_counter
{
value_type() = default;
value_type(int) : state(1) { }
value_type(std::initializer_list<char>, const char*) : state(2) { }
int state = 0;
};
void test()
{
using O = gdb::optional<value_type>;
// Check emplace
{
O o;
o.emplace();
VERIFY( o && o->state == 0 );
}
{
O o { gdb::in_place, 0 };
o.emplace();
VERIFY( o && o->state == 0 );
}
{
O o;
o.emplace(0);
VERIFY( o && o->state == 1 );
}
{
O o { gdb::in_place };
o.emplace(0);
VERIFY( o && o->state == 1 );
}
#ifndef GDB_OPTIONAL
{
O o;
o.emplace({ 'a' }, "");
VERIFY( o && o->state == 2 );
}
{
O o { gdb::in_place };
o.emplace({ 'a' }, "");
VERIFY( o && o->state == 2 );
}
#endif
{
O o;
VERIFY(&o.emplace(0) == &*o);
#ifndef GDB_OPTIONAL
VERIFY(&o.emplace({ 'a' }, "") == &*o);
#endif
}
static_assert( !std::is_constructible<O, std::initializer_list<int>, int>(), "" );
VERIFY( counter == 0 );
}
} // namespace assign_6

View File

@ -0,0 +1,29 @@
// Copyright (C) 2016-2017 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/>.
namespace assign_7 {
void test()
{
gdb::optional<int> o{666};
VERIFY(o && *o == 666);
o.reset();
VERIFY(!o);
static_assert(noexcept(std::declval<gdb::optional<int>>().reset()), "");
}
} // namespace assign_7

View File

@ -0,0 +1,126 @@
// Copyright (C) 2013-2017 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/>.
namespace cons_copy {
struct tracker
{
tracker(int value) : value(value) { ++count; }
~tracker() { --count; }
tracker(tracker const& other) : value(other.value) { ++count; }
tracker(tracker&& other) : value(other.value)
{
other.value = -1;
++count;
}
tracker& operator=(tracker const&) = default;
tracker& operator=(tracker&&) = default;
int value;
static int count;
};
int tracker::count = 0;
struct exception { };
struct throwing_copy
{
throwing_copy() = default;
throwing_copy(throwing_copy const&) { throw exception {}; }
};
void test()
{
// [20.5.4.1] Constructors
{
gdb::optional<long> o;
auto copy = o;
VERIFY( !copy );
VERIFY( !o );
}
{
const long val = 0x1234ABCD;
gdb::optional<long> o { gdb::in_place, val};
auto copy = o;
VERIFY( copy );
VERIFY( *copy == val );
#ifndef GDB_OPTIONAL
VERIFY( o && o == val );
#endif
}
{
gdb::optional<tracker> o;
auto copy = o;
VERIFY( !copy );
VERIFY( tracker::count == 0 );
VERIFY( !o );
}
{
gdb::optional<tracker> o { gdb::in_place, 333 };
auto copy = o;
VERIFY( copy );
VERIFY( copy->value == 333 );
VERIFY( tracker::count == 2 );
VERIFY( o && o->value == 333 );
}
enum outcome { nothrow, caught, bad_catch };
{
outcome result = nothrow;
gdb::optional<throwing_copy> o;
try
{
auto copy = o;
}
catch(exception const&)
{ result = caught; }
catch(...)
{ result = bad_catch; }
VERIFY( result == nothrow );
}
{
outcome result = nothrow;
gdb::optional<throwing_copy> o { gdb::in_place };
try
{
auto copy = o;
}
catch(exception const&)
{ result = caught; }
catch(...)
{ result = bad_catch; }
VERIFY( result == caught );
}
VERIFY( tracker::count == 0 );
}
} // namespace cons_copy

View File

@ -0,0 +1,58 @@
// Copyright (C) 2013-2017 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/>.
namespace cons_default {
struct tracker
{
tracker() { ++count; }
~tracker() { --count; }
tracker(tracker const&) { ++count; }
tracker(tracker&&) { ++count; }
tracker& operator=(tracker const&) = default;
tracker& operator=(tracker&&) = default;
static int count;
};
int tracker::count = 0;
void test()
{
// [20.5.4.1] Constructors
{
gdb::optional<tracker> o;
VERIFY( !o );
}
{
gdb::optional<tracker> o {};
VERIFY( !o );
}
{
gdb::optional<tracker> o = {};
VERIFY( !o );
}
VERIFY( tracker::count == 0 );
}
} // namespace cons_default

View File

@ -0,0 +1,124 @@
// Copyright (C) 2013-2017 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/>.
namespace cons_move {
struct tracker
{
tracker(int value) : value(value) { ++count; }
~tracker() { --count; }
tracker(tracker const& other) : value(other.value) { ++count; }
tracker(tracker&& other) : value(other.value)
{
other.value = -1;
++count;
}
tracker& operator=(tracker const&) = default;
tracker& operator=(tracker&&) = default;
int value;
static int count;
};
int tracker::count = 0;
struct exception { };
struct throwing_move
{
throwing_move() = default;
throwing_move(throwing_move const&) { throw exception {}; }
};
void test()
{
// [20.5.4.1] Constructors
{
gdb::optional<long> o;
auto moved_to = std::move(o);
VERIFY( !moved_to );
VERIFY( !o );
}
{
const long val = 0x1234ABCD;
gdb::optional<long> o { gdb::in_place, val};
auto moved_to = std::move(o);
VERIFY( moved_to );
VERIFY( *moved_to == val );
VERIFY( o && *o == val );
}
{
gdb::optional<tracker> o;
auto moved_to = std::move(o);
VERIFY( !moved_to );
VERIFY( tracker::count == 0 );
VERIFY( !o );
}
{
gdb::optional<tracker> o { gdb::in_place, 333 };
auto moved_to = std::move(o);
VERIFY( moved_to );
VERIFY( moved_to->value == 333 );
VERIFY( tracker::count == 2 );
VERIFY( o && o->value == -1 );
}
enum outcome { nothrow, caught, bad_catch };
{
outcome result = nothrow;
gdb::optional<throwing_move> o;
try
{
auto moved_to = std::move(o);
}
catch(exception const&)
{ result = caught; }
catch(...)
{ result = bad_catch; }
VERIFY( result == nothrow );
}
{
outcome result = nothrow;
gdb::optional<throwing_move> o { gdb::in_place };
try
{
auto moved_to = std::move(o);
}
catch(exception const&)
{ result = caught; }
catch(...)
{ result = bad_catch; }
VERIFY( result == caught );
}
VERIFY( tracker::count == 0 );
}
} // namespace cons_move

View File

@ -0,0 +1,294 @@
// Copyright (C) 2013-2017 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/>.
namespace cons_value {
struct tracker
{
tracker(int value) : value(value) { ++count; }
~tracker() { --count; }
tracker(tracker const& other) : value(other.value) { ++count; }
tracker(tracker&& other) : value(other.value)
{
other.value = -1;
++count;
}
tracker& operator=(tracker const&) = default;
tracker& operator=(tracker&&) = default;
int value;
static int count;
};
int tracker::count = 0;
struct exception { };
struct throwing_construction
{
explicit throwing_construction(bool propagate) : propagate(propagate) { }
throwing_construction(throwing_construction const& other)
: propagate(other.propagate)
{
if(propagate)
throw exception {};
}
bool propagate;
};
void test()
{
// [20.5.4.1] Constructors
{
auto i = 0x1234ABCD;
gdb::optional<long> o { i };
VERIFY( o );
VERIFY( *o == 0x1234ABCD );
VERIFY( i == 0x1234ABCD );
}
{
auto i = 0x1234ABCD;
gdb::optional<long> o = i;
VERIFY( o );
VERIFY( *o == 0x1234ABCD );
VERIFY( i == 0x1234ABCD );
}
{
auto i = 0x1234ABCD;
gdb::optional<long> o = { i };
VERIFY( o );
VERIFY( *o == 0x1234ABCD );
VERIFY( i == 0x1234ABCD );
}
{
auto i = 0x1234ABCD;
gdb::optional<long> o { std::move(i) };
VERIFY( o );
VERIFY( *o == 0x1234ABCD );
VERIFY( i == 0x1234ABCD );
}
{
auto i = 0x1234ABCD;
gdb::optional<long> o = std::move(i);
VERIFY( o );
VERIFY( *o == 0x1234ABCD );
VERIFY( i == 0x1234ABCD );
}
{
auto i = 0x1234ABCD;
gdb::optional<long> o = { std::move(i) };
VERIFY( o );
VERIFY( *o == 0x1234ABCD );
VERIFY( i == 0x1234ABCD );
}
#ifndef GDB_OPTIONAL
{
std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
gdb::optional<std::vector<int>> o { v };
VERIFY( !v.empty() );
VERIFY( o->size() == 6 );
}
#endif
{
std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
gdb::optional<std::vector<int>> o = v;
VERIFY( !v.empty() );
VERIFY( o->size() == 6 );
}
{
std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
gdb::optional<std::vector<int>> o { v };
VERIFY( !v.empty() );
VERIFY( o->size() == 6 );
}
{
std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
gdb::optional<std::vector<int>> o { std::move(v) };
VERIFY( v.empty() );
VERIFY( o->size() == 6 );
}
{
std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
gdb::optional<std::vector<int>> o = std::move(v);
VERIFY( v.empty() );
VERIFY( o->size() == 6 );
}
{
std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
gdb::optional<std::vector<int>> o { std::move(v) };
VERIFY( v.empty() );
VERIFY( o->size() == 6 );
}
{
tracker t { 333 };
gdb::optional<tracker> o = t;
VERIFY( o->value == 333 );
VERIFY( tracker::count == 2 );
VERIFY( t.value == 333 );
}
{
tracker t { 333 };
gdb::optional<tracker> o = std::move(t);
VERIFY( o->value == 333 );
VERIFY( tracker::count == 2 );
VERIFY( t.value == -1 );
}
enum outcome { nothrow, caught, bad_catch };
{
outcome result = nothrow;
throwing_construction t { false };
try
{
gdb::optional<throwing_construction> o { t };
}
catch(exception const&)
{ result = caught; }
catch(...)
{ result = bad_catch; }
VERIFY( result == nothrow );
}
{
outcome result = nothrow;
throwing_construction t { true };
try
{
gdb::optional<throwing_construction> o { t };
}
catch(exception const&)
{ result = caught; }
catch(...)
{ result = bad_catch; }
VERIFY( result == caught );
}
{
outcome result = nothrow;
throwing_construction t { false };
try
{
gdb::optional<throwing_construction> o { std::move(t) };
}
catch(exception const&)
{ result = caught; }
catch(...)
{ result = bad_catch; }
VERIFY( result == nothrow );
}
{
outcome result = nothrow;
throwing_construction t { true };
try
{
gdb::optional<throwing_construction> o { std::move(t) };
}
catch(exception const&)
{ result = caught; }
catch(...)
{ result = bad_catch; }
VERIFY( result == caught );
}
{
#ifndef GDB_OPTIONAL
gdb::optional<std::string> os = "foo";
#endif
struct X
{
explicit X(int) {}
X& operator=(int) {return *this;}
};
#ifndef GDB_OPTIONAL
gdb::optional<X> ox{42};
#endif
gdb::optional<int> oi{42};
#ifndef GDB_OPTIONAL
gdb::optional<X> ox2{oi};
#endif
gdb::optional<std::string> os2;
os2 = "foo";
#ifndef GDB_OPTIONAL
gdb::optional<X> ox3;
ox3 = 42;
gdb::optional<X> ox4;
ox4 = oi;
#endif
}
{
// no converting construction.
#ifndef GDB_OPTIONAL
gdb::optional<int> oi = gdb::optional<short>();
VERIFY(!bool(oi));
gdb::optional<std::string> os = gdb::optional<const char*>();
VERIFY(!bool(os));
#endif
gdb::optional<gdb::optional<int>> ooi = gdb::optional<int>();
VERIFY(bool(ooi));
ooi = gdb::optional<int>();
VERIFY(bool(ooi));
ooi = gdb::optional<int>(42);
VERIFY(bool(ooi));
VERIFY(bool(*ooi));
#ifndef GDB_OPTIONAL
gdb::optional<gdb::optional<int>> ooi2 = gdb::optional<short>();
VERIFY(bool(ooi2));
ooi2 = gdb::optional<short>();
VERIFY(bool(ooi2));
ooi2 = gdb::optional<short>(6);
VERIFY(bool(ooi2));
VERIFY(bool(*ooi2));
gdb::optional<gdb::optional<int>> ooi3 = gdb::optional<int>(42);
VERIFY(bool(ooi3));
VERIFY(bool(*ooi3));
gdb::optional<gdb::optional<int>> ooi4 = gdb::optional<short>(6);
VERIFY(bool(ooi4));
VERIFY(bool(*ooi4));
#endif
}
}
} // namespace cons_value

View File

@ -0,0 +1,65 @@
// Copyright (C) 2013-2017 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/>.
namespace in_place {
void test()
{
// [20.5.5] In-place construction
{
gdb::optional<int> o { gdb::in_place };
VERIFY( o );
VERIFY( *o == int() );
#ifndef GDB_OPTIONAL
static_assert( !std::is_convertible<gdb::in_place_t, gdb::optional<int>>(), "" );
#endif
}
{
gdb::optional<int> o { gdb::in_place, 42 };
VERIFY( o );
VERIFY( *o == 42 );
}
{
gdb::optional<std::vector<int>> o { gdb::in_place, 18, 4 };
VERIFY( o );
VERIFY( o->size() == 18 );
VERIFY( (*o)[17] == 4 );
}
#ifndef GDB_OPTIONAL
{
gdb::optional<std::vector<int>> o { gdb::in_place, { 18, 4 } };
VERIFY( o );
VERIFY( o->size() == 2 );
VERIFY( (*o)[0] == 18 );
}
#endif
#ifndef GDB_OPTIONAL
{
gdb::optional<std::vector<int>> o { gdb::in_place, { 18, 4 }, std::allocator<int> {} };
VERIFY( o );
VERIFY( o->size() == 2 );
VERIFY( (*o)[0] == 18 );
}
#endif
}
} // namespace in_place

View File

@ -0,0 +1,31 @@
// Copyright (C) 2013-2017 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/>.
namespace observers_1 {
struct value_type
{
int i;
};
void test()
{
gdb::optional<value_type> o { value_type { 51 } };
VERIFY( (*o).i == 51 );
}
} // namespace observers_1

View File

@ -0,0 +1,35 @@
// Copyright (C) 2013-2017 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/>.
namespace observers_2 {
struct value_type
{
int i;
};
void* operator&(const value_type&) = delete;
void test()
{
gdb::optional<value_type> o { value_type { 51 } };
VERIFY( o->i == 51 );
VERIFY( o->i == (*o).i );
VERIFY( &o->i == &(*o).i );
}
} // namespace observers_2