diff options
Diffstat (limited to 'utils/optional_test.cpp')
-rw-r--r-- | utils/optional_test.cpp | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/utils/optional_test.cpp b/utils/optional_test.cpp new file mode 100644 index 000000000000..debd8949852e --- /dev/null +++ b/utils/optional_test.cpp @@ -0,0 +1,285 @@ +// Copyright 2010 The Kyua Authors. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors +// may be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "utils/optional.ipp" + +#include <iostream> +#include <sstream> + +#include <atf-c++.hpp> + +using utils::none; +using utils::optional; + + +namespace { + + +/// Fake class to capture calls to the new and delete operators. +class test_alloc { +public: + /// Value to disambiguate objects after construction. + int value; + + /// Balance of alive instances of this class in dynamic memory. + static size_t instances; + + /// Constructs a new optional object. + /// + /// \param value_ The value to store in this object for disambiguation. + test_alloc(int value_) : value(value_) + { + } + + /// Allocates a new object and records its existence. + /// + /// \param size The amount of memory to allocate. + /// + /// \return A pointer to the allocated memory. + /// + /// \throw std::bad_alloc If the memory allocation fails. + void* + operator new(size_t size) + { + instances++; + std::cout << "test_alloc::operator new called\n"; + return ::operator new(size); + } + + /// Deallocates an existing object and unrecords its existence. + /// + /// \param mem The pointer to the memory to deallocate. + void + operator delete(void* mem) + { + instances--; + std::cout << "test_alloc::operator delete called\n"; + ::operator delete(mem); + } +}; + + +size_t test_alloc::instances = 0; + + +/// Constructs and returns an optional object. +/// +/// This is used by tests to validate that returning an object from within a +/// function works (i.e. the necessary constructors are available). +/// +/// \tparam Type The type of the object included in the optional wrapper. +/// \param value The value to put inside the optional wrapper. +/// +/// \return The constructed optional object. +template< typename Type > +optional< Type > +return_optional(const Type& value) +{ + return optional< Type >(value); +} + + +} // anonymous namespace + + +ATF_TEST_CASE_WITHOUT_HEAD(ctors__native_type); +ATF_TEST_CASE_BODY(ctors__native_type) +{ + const optional< int > no_args; + ATF_REQUIRE(!no_args); + + const optional< int > with_none(none); + ATF_REQUIRE(!with_none); + + const optional< int > with_arg(3); + ATF_REQUIRE(with_arg); + ATF_REQUIRE_EQ(3, with_arg.get()); + + const optional< int > copy_none(with_none); + ATF_REQUIRE(!copy_none); + + const optional< int > copy_arg(with_arg); + ATF_REQUIRE(copy_arg); + ATF_REQUIRE_EQ(3, copy_arg.get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(ctors__complex_type); +ATF_TEST_CASE_BODY(ctors__complex_type) +{ + const optional< std::string > no_args; + ATF_REQUIRE(!no_args); + + const optional< std::string > with_none(none); + ATF_REQUIRE(!with_none); + + const optional< std::string > with_arg("foo"); + ATF_REQUIRE(with_arg); + ATF_REQUIRE_EQ("foo", with_arg.get()); + + const optional< std::string > copy_none(with_none); + ATF_REQUIRE(!copy_none); + + const optional< std::string > copy_arg(with_arg); + ATF_REQUIRE(copy_arg); + ATF_REQUIRE_EQ("foo", copy_arg.get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(assign); +ATF_TEST_CASE_BODY(assign) +{ + optional< int > from_default; + from_default = optional< int >(); + ATF_REQUIRE(!from_default); + + optional< int > from_none(3); + from_none = none; + ATF_REQUIRE(!from_none); + + optional< int > from_int; + from_int = 6; + ATF_REQUIRE_EQ(6, from_int.get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(return); +ATF_TEST_CASE_BODY(return) +{ + optional< long > from_return(return_optional< long >(123)); + ATF_REQUIRE(from_return); + ATF_REQUIRE_EQ(123, from_return.get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(memory); +ATF_TEST_CASE_BODY(memory) +{ + ATF_REQUIRE_EQ(0, test_alloc::instances); + { + optional< test_alloc > optional1(test_alloc(3)); + ATF_REQUIRE_EQ(1, test_alloc::instances); + ATF_REQUIRE_EQ(3, optional1.get().value); + + { + optional< test_alloc > optional2(optional1); + ATF_REQUIRE_EQ(2, test_alloc::instances); + ATF_REQUIRE_EQ(3, optional2.get().value); + + optional2 = 5; + ATF_REQUIRE_EQ(2, test_alloc::instances); + ATF_REQUIRE_EQ(5, optional2.get().value); + ATF_REQUIRE_EQ(3, optional1.get().value); + } + ATF_REQUIRE_EQ(1, test_alloc::instances); + ATF_REQUIRE_EQ(3, optional1.get().value); + } + ATF_REQUIRE_EQ(0, test_alloc::instances); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(get_default); +ATF_TEST_CASE_BODY(get_default) +{ + const std::string def_value = "hello"; + optional< std::string > optional; + ATF_REQUIRE(&def_value == &optional.get_default(def_value)); + optional = "bye"; + ATF_REQUIRE_EQ("bye", optional.get_default(def_value)); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(make_optional); +ATF_TEST_CASE_BODY(make_optional) +{ + optional< int > opt = utils::make_optional(576); + ATF_REQUIRE(opt); + ATF_REQUIRE_EQ(576, opt.get()); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(operators_eq_and_ne); +ATF_TEST_CASE_BODY(operators_eq_and_ne) +{ + optional< int > opt1, opt2; + + opt1 = none; opt2 = none; + ATF_REQUIRE( opt1 == opt2); + ATF_REQUIRE(!(opt1 != opt2)); + + opt1 = utils::make_optional(5); opt2 = none; + ATF_REQUIRE(!(opt1 == opt2)); + ATF_REQUIRE( opt1 != opt2); + + opt1 = none; opt2 = utils::make_optional(5); + ATF_REQUIRE(!(opt1 == opt2)); + ATF_REQUIRE( opt1 != opt2); + + opt1 = utils::make_optional(5); opt2 = utils::make_optional(5); + ATF_REQUIRE( opt1 == opt2); + ATF_REQUIRE(!(opt1 != opt2)); + + opt1 = utils::make_optional(6); opt2 = utils::make_optional(5); + ATF_REQUIRE(!(opt1 == opt2)); + ATF_REQUIRE( opt1 != opt2); +} + + +ATF_TEST_CASE_WITHOUT_HEAD(output); +ATF_TEST_CASE_BODY(output) +{ + { + std::ostringstream str; + str << optional< int >(none); + ATF_REQUIRE_EQ("none", str.str()); + } + { + std::ostringstream str; + str << optional< int >(5); + ATF_REQUIRE_EQ("5", str.str()); + } + { + std::ostringstream str; + str << optional< std::string >("this is a text"); + ATF_REQUIRE_EQ("this is a text", str.str()); + } +} + + +ATF_INIT_TEST_CASES(tcs) +{ + ATF_ADD_TEST_CASE(tcs, ctors__native_type); + ATF_ADD_TEST_CASE(tcs, ctors__complex_type); + ATF_ADD_TEST_CASE(tcs, assign); + ATF_ADD_TEST_CASE(tcs, return); + ATF_ADD_TEST_CASE(tcs, memory); + ATF_ADD_TEST_CASE(tcs, get_default); + ATF_ADD_TEST_CASE(tcs, make_optional); + ATF_ADD_TEST_CASE(tcs, operators_eq_and_ne); + ATF_ADD_TEST_CASE(tcs, output); +} |