summaryrefslogtreecommitdiff
path: root/utils/optional_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/optional_test.cpp')
-rw-r--r--utils/optional_test.cpp285
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);
+}