-// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
Dhcp4Client::Dhcp4Client(const Dhcp4Client::State& state) :
config_(),
- ciaddr_(IOAddress("0.0.0.0")),
+ ciaddr_(),
curr_transid_(0),
dest_addr_("255.255.255.255"),
hwaddr_(generateHWAddr()),
Dhcp4Client::Dhcp4Client(boost::shared_ptr<NakedDhcpv4Srv> srv,
const Dhcp4Client::State& state) :
config_(),
- ciaddr_(IOAddress("0.0.0.0")),
+ ciaddr_(),
curr_transid_(0),
dest_addr_("255.255.255.255"),
fqdn_(),
addRequestedAddress(*requested_addr);
}
// Override the default ciaddr if specified by a test.
- if (ciaddr_.isSpecified()) {
- context_.query_->setCiaddr(ciaddr_.get());
+ if (!ciaddr_.unspecified()) {
+ context_.query_->setCiaddr(ciaddr_);
}
appendExtraOptions();
appendClasses();
context_.query_ = createMsg(DHCPREQUEST);
// Override the default ciaddr if specified by a test.
- if (ciaddr_.isSpecified()) {
- context_.query_->setCiaddr(ciaddr_.get());
+ if (!ciaddr_.unspecified()) {
+ context_.query_->setCiaddr(ciaddr_);
} else if ((state_ == SELECTING) || (state_ == INIT_REBOOT)) {
context_.query_->setCiaddr(IOAddress("0.0.0.0"));
} else {
-// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
/// If this value is "unspecified" the default values will be used
/// by the client. If this value is specified, it will override ciaddr
/// in the client's messages.
- isc::util::OptionalValue<asiolink::IOAddress> ciaddr_;
+ isc::util::Optional<asiolink::IOAddress> ciaddr_;
/// @brief Adds extra option (an option the client will always send)
///
-// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// Configure DHCP server.
configure(DORA_CONFIGS[0], *client.getServer());
// Force ciaddr of Discover message to be non-zero.
- client.ciaddr_.specify(IOAddress("10.0.0.50"));
+ client.ciaddr_ = IOAddress("10.0.0.50");
// Obtain a lease from the server using the 4-way exchange.
ASSERT_NO_THROW(client.doDiscover(boost::shared_ptr<
IOAddress>(new IOAddress("10.0.0.50"))));
// Replace the address held by the client. The client will request
// the assignment of this address but the server has a different
// address for this client.
- client.ciaddr_.specify(IOAddress("192.168.0.30"));
+ client.ciaddr_ = IOAddress("192.168.0.30");
ASSERT_NO_THROW(client.doRequest());
// The client is sending invalid ciaddr so the server should send a NAK.
resp = client.getContext().response_;
-// Copyright (C) 2011-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
<< " already defined on the " << name_ << " interface.");
}
}
- unicasts_.push_back(OptionalValue<IOAddress>(addr, true));
+ unicasts_.push_back(Optional<IOAddress>(addr));
}
bool
void
Iface::addAddress(const isc::asiolink::IOAddress& addr) {
- addrs_.push_back(Address(addr, OptionalValueState(true)));
+ addrs_.push_back(Address(addr));
}
void
for (AddressCollection::iterator addr_it = addrs_.begin();
addr_it != addrs_.end(); ++addr_it) {
if (address == addr_it->get()) {
- addr_it->specify(OptionalValueState(active));
+ addr_it->unspecified(!active);
return;
}
}
Iface::setActive(const bool active) {
for (AddressCollection::iterator addr_it = addrs_.begin();
addr_it != addrs_.end(); ++addr_it) {
- addr_it->specify(OptionalValueState(active));
+ addr_it->unspecified(!active);
}
}
Iface::countActive4() const {
uint16_t count = 0;
BOOST_FOREACH(Address addr, addrs_) {
- if (addr.get().isV4() && addr.isSpecified()) {
+ if (!addr.unspecified() && addr.get().isV4()) {
++count;
}
}
BOOST_FOREACH(Iface::Address addr, iface->getAddresses()) {
// Skip non-IPv4 addresses and those that weren't selected..
- if (!addr.get().isV4() || !addr.isSpecified()) {
+ if (addr.unspecified() || !addr.get().isV4()) {
continue;
}
-// Copyright (C) 2011-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
static const unsigned int MAX_MAC_LEN = 20;
/// @brief Address type.
- typedef util::OptionalValue<asiolink::IOAddress> Address;
+ typedef util::Optional<asiolink::IOAddress> Address;
/// Type that defines list of addresses
typedef std::list<Address> AddressCollection;
/// @brief Returns all addresses available on an interface.
///
- /// The returned addresses are encapsulated in the @c util::OptionalValue
+ /// The returned addresses are encapsulated in the @c util::Optional
/// class to be able to selectively flag some of the addresses as active
/// (when optional value is specified) or inactive (when optional value
/// is specified). If the address is marked as active, the
std::vector<MYSQL_BIND>
createBindForSend(const OptionDescriptor& opt_desc,
const std::string& opt_space,
- const OptionalValue<SubnetID>& subnet_id,
+ const Optional<SubnetID>& subnet_id,
const HostID& host_id) {
// Hold pointer to the option to make sure it remains valid until
bind_[7].length = &client_class_len_;
// dhcp4_subnet_id: INT UNSIGNED NULL
- if (subnet_id.isSpecified()) {
+ if (!subnet_id.unspecified()) {
subnet_id_ = subnet_id;
bind_[8].buffer_type = MYSQL_TYPE_LONG;
bind_[8].buffer = reinterpret_cast<char*>(subnet_id_);
void addOption(const MySqlHostDataSourceImpl::StatementIndex& stindex,
const OptionDescriptor& opt_desc,
const std::string& opt_space,
- const OptionalValue<SubnetID>& subnet_id,
+ const Optional<SubnetID>& subnet_id,
const HostID& host_id);
/// @brief Inserts multiple options into the database.
MySqlHostDataSourceImpl::addOption(const StatementIndex& stindex,
const OptionDescriptor& opt_desc,
const std::string& opt_space,
- const OptionalValue<SubnetID>& subnet_id,
+ const Optional<SubnetID>& subnet_id,
const HostID& id) {
std::vector<MYSQL_BIND> bind =
host_option_exchange_->createBindForSend(opt_desc, opt_space,
if (options && !options->empty()) {
for (OptionContainer::const_iterator opt = options->begin();
opt != options->end(); ++opt) {
- addOption(stindex, *opt, *space, OptionalValue<SubnetID>(),
+ addOption(stindex, *opt, *space, Optional<SubnetID>(),
host_id);
}
}
-// Copyright (C) 2017-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2017-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
return (opt);
}
-OptionalValue<uint32_t>
+Optional<uint32_t>
OptionDataParser::extractCode(ConstElementPtr parent) const {
uint32_t code;
try {
} catch (const std::exception&) {
// The code parameter was not found. Return an unspecified
// value.
- return (OptionalValue<uint32_t>());
+ return (Optional<uint32_t>());
}
if (code == 0) {
}
- return (OptionalValue<uint32_t>(code, OptionalValueState(true)));
+ return (Optional<uint32_t>(code));
}
-OptionalValue<std::string>
+Optional<std::string>
OptionDataParser::extractName(ConstElementPtr parent) const {
std::string name;
try {
name = getString(parent, "name");
} catch (...) {
- return (OptionalValue<std::string>());
+ return (Optional<std::string>());
}
if (name.find(" ") != std::string::npos) {
<< getPosition("name", parent) << ")");
}
- return (OptionalValue<std::string>(name, OptionalValueState(true)));
+ return (Optional<std::string>(name));
}
std::string
return (data);
}
-OptionalValue<bool>
+Optional<bool>
OptionDataParser::extractCSVFormat(ConstElementPtr parent) const {
bool csv_format = true;
try {
csv_format = getBoolean(parent, "csv-format");
} catch (...) {
- return (OptionalValue<bool>(csv_format));
+ return (Optional<bool>());
}
- return (OptionalValue<bool>(csv_format, OptionalValueState(true)));
+ return (Optional<bool>(csv_format));
}
std::string
return (space);
}
-OptionalValue<bool>
+Optional<bool>
OptionDataParser::extractPersistent(ConstElementPtr parent) const {
bool persist = false;
try {
persist = getBoolean(parent, "always-send");
} catch (...) {
- return (OptionalValue<bool>(persist));
+ return (Optional<bool>());
}
- return (OptionalValue<bool>(persist, OptionalValueState(true)));
+ return (Optional<bool>(persist));
}
template<typename SearchKey>
const Option::Universe universe = address_family_ == AF_INET ?
Option::V4 : Option::V6;
- OptionalValue<uint32_t> code_param = extractCode(option_data);
- OptionalValue<std::string> name_param = extractName(option_data);
- OptionalValue<bool> csv_format_param = extractCSVFormat(option_data);
- OptionalValue<bool> persist_param = extractPersistent(option_data);
+ Optional<uint32_t> code_param = extractCode(option_data);
+ Optional<std::string> name_param = extractName(option_data);
+ Optional<bool> csv_format_param = extractCSVFormat(option_data);
+ Optional<bool> persist_param = extractPersistent(option_data);
std::string data_param = extractData(option_data);
std::string space_param = extractSpace(option_data);
ConstElementPtr user_context = option_data->get("user-context");
// Require that option code or option name is specified.
- if (!code_param.isSpecified() && !name_param.isSpecified()) {
+ if (code_param.unspecified() && name_param.unspecified()) {
isc_throw(DhcpConfigError, "option data configuration requires one of"
" 'code' or 'name' parameters to be specified"
<< " (" << option_data->getPosition() << ")");
// Try to find a corresponding option definition using option code or
// option name.
- OptionDefinitionPtr def = code_param.isSpecified() ?
- findOptionDefinition(space_param, code_param) :
- findOptionDefinition(space_param, name_param);
+ OptionDefinitionPtr def = code_param.unspecified() ?
+ findOptionDefinition(space_param, name_param) :
+ findOptionDefinition(space_param, code_param);
// If there is no definition, the user must not explicitly enable the
// use of csv-format.
if (!def) {
// If explicitly requested that the CSV format is to be used,
// the option definition is a must.
- if (csv_format_param.isSpecified() && csv_format_param) {
+ if (!csv_format_param.unspecified() && csv_format_param) {
isc_throw(DhcpConfigError, "definition for the option '"
<< space_param << "." << name_param
<< "' having code '" << code_param
// If there is no option definition and the option code is not specified
// we have no means to find the option code.
- } else if (name_param.isSpecified() && !code_param.isSpecified()) {
+ } else if (!name_param.unspecified() && code_param.unspecified()) {
isc_throw(DhcpConfigError, "definition for the option '"
<< space_param << "." << name_param
<< "' does not exist ("
// If the definition is available and csv-format hasn't been explicitly
// disabled, we will parse the data as comma separated values.
- if (def && (!csv_format_param.isSpecified() || csv_format_param)) {
+ if (def && (csv_format_param.unspecified() || csv_format_param)) {
// If the option data is specified as a string of comma
// separated values then we need to split this string into
// individual values - each value will be used to initialize
binary));
desc.option_ = option;
- desc.persistent_ = persist_param.isSpecified() && persist_param;
+ desc.persistent_ = !persist_param.unspecified() && persist_param;
} else {
// Option name is specified it should match the name in the definition.
- if (name_param.isSpecified() && (def->getName() != name_param.get())) {
+ if (!name_param.unspecified() && (def->getName() != name_param.get())) {
isc_throw(DhcpConfigError, "specified option name '"
<< name_param << "' does not match the "
<< "option definition: '" << space_param
// Option definition has been found so let's use it to create
// an instance of our option.
try {
- bool use_csv = !csv_format_param.isSpecified() || csv_format_param;
+ bool use_csv = csv_format_param.unspecified() || csv_format_param;
OptionPtr option = use_csv ?
def->optionFactory(universe, def->getCode(), data_tokens) :
def->optionFactory(universe, def->getCode(), binary);
desc.option_ = option;
- desc.persistent_ = persist_param.isSpecified() && persist_param;
+ desc.persistent_ = !persist_param.unspecified() && persist_param;
if (use_csv) {
desc.formatted_value_ = data_param;
}
-// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2017-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
///
/// @return Option code, possibly unspecified.
/// @throw DhcpConfigError if option code is invalid.
- util::OptionalValue<uint32_t>
+ util::Optional<uint32_t>
extractCode(data::ConstElementPtr parent) const;
/// @brief Retrieves parsed option name as an optional value.
///
/// @return Option name, possibly unspecified.
/// @throw DhcpConfigError if option name is invalid.
- util::OptionalValue<std::string>
+ util::Optional<std::string>
extractName(data::ConstElementPtr parent) const;
/// @brief Retrieves csv-format parameter as an optional value.
///
/// @return Value of the csv-format parameter, possibly unspecified.
- util::OptionalValue<bool> extractCSVFormat(data::ConstElementPtr parent) const;
+ util::Optional<bool> extractCSVFormat(data::ConstElementPtr parent) const;
/// @brief Retrieves option data as a string.
///
/// @brief Retrieves persistent/always-send parameter as an optional value.
///
/// @return Value of the persistent parameter, possibly unspecified.
- util::OptionalValue<bool> extractPersistent(data::ConstElementPtr parent) const;
+ util::Optional<bool> extractPersistent(data::ConstElementPtr parent) const;
/// @brief Address family: @c AF_INET or @c AF_INET6.
uint16_t address_family_;
-// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2014-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#ifndef OPTIONAL_VALUE_H
-#define OPTIONAL_VALUE_H
+#ifndef OPTIONAL_H
+#define OPTIONAL_H
#include <ostream>
+#include <string>
namespace isc {
namespace util {
-/// @brief Indicate if an @c OptionalValue is is specified or not.
+/// @brief A template representing an optional value.
///
-/// This is a simple wrapper class which holds a boolean value to indicate
-/// if the @c OptionalValue is specified or not. By using this class in the
-/// @c OptionalValue class constructor we avoid the ambiguity when the
-/// @c OptionalValue encapsulates a bool type.
-struct OptionalValueState {
-
- /// @brief Constructor.
- ///
- /// @param specified A boolean value to be assigned.
- OptionalValueState(const bool specified)
- : specified_(specified) {
- }
- /// @brief A bool value encapsulated by this structure.
- bool specified_;
-};
-
-/// @brief Simple class representing an optional value.
-///
-/// This template class encapsulates a value of any type. An additional flag
-/// held by this class indicates if the value is "specified" or "unspecified".
-/// For example, a configuration parser for DHCP server may use this class
-/// to represent the value of the configuration parameter which may appear
-/// in the configuration file, but is not mandatory. The value of the
-/// @c OptionalValue may be initialized to "unspecified" initially. When the
-/// configuration parser finds that the appropriate parameter exists in the
-/// configuration file, the default value can be overridden and the value may
-/// be marked as "specified". If the parameter is not found, the value remains
-/// "unspecified" and the appropriate actions may be taken, e.g. the default
-/// value may be used.
+/// This template class encapsulates an optional value. The default implementation
+/// encapsulates numeric values, but additional specializations are defined
+/// as neccessary to support other types od data.
///
-/// This is a generic class and may be used in all cases when there is a need
-/// for the additional information to be carried along with the value.
-/// Alternative approach is to use a pointer which is only initialized if the
-/// actual value needs to be specified, but this may not be feasible in all
-/// cases.
+/// This class includes a boolean flag which indicates if the encapsulated
+/// value is specified or unspecified. For example, a configuration parser
+/// for the DHCP server may use this class to represent a value of the
+/// configuration parameter which may appear in the configuration file, but
+/// is not mandatory. The value of the @c Optional may be initialized to
+/// "unspecified" initially. When the configuration parser finds that the
+/// particular parameter exists in the configuration file, the default value
+/// can be overriden and the value may be marked as "specified". If the
+/// parameter is not found, the value remains "unspecified" and the appropriate
+/// actions may be taken, e.g. the default value may be used.
///
/// @tparam Type of the encapsulated value.
template<typename T>
-class OptionalValue {
+class Optional {
public:
- /// @brief Default constructor.
+ /// @brief Assigns a new value value and marks it "specified".
///
- /// Note that the type @c T must have a default constructor to use this
- /// constructor.
- OptionalValue()
- : value_(T()), specified_(false) {
+ /// @param other new actual value.
+ Optional<T>& operator=(T other) {
+ default_ = other;
+ unspecified_ = false;
+ return (*this);
}
- /// @brief Constructor
- ///
- /// Creates optional value. The value defaults to "unspecified".
- ///
- /// @param value Default explicit value.
- /// @param state Specifies bool which determines if the value is initially
- /// specified or not (default is false).
- explicit OptionalValue(const T& value, const OptionalValueState& state =
- OptionalValueState(false))
- : value_(value), specified_(state.specified_) {
- }
-
- /// @brief Retrieves the actual value.
- T get() const {
- return (value_);
- }
-
- /// @brief Sets the actual value.
+ /// @brief Type cast operator.
///
- /// @param value New value.
- void set(const T& value) {
- value_ = value;
- }
-
- /// @brief Sets the new value and marks it specified.
+ /// This operator converts the optional value to the actual value being
+ /// encapsulated.
///
- /// @param value New actual value.
- void specify(const T& value) {
- set(value);
- specify(OptionalValueState(true));
+ /// @return Encapsulated value.
+ operator T() const {
+ return (default_);
}
- /// @brief Sets the value to "specified" or "unspecified".
+ /// @brief Default constructor.
///
- /// It does not alter the actual value. It only marks it "specified" or
- /// "unspecified".
- /// @param state determines if a value is specified or not
- void specify(const OptionalValueState& state) {
- specified_ = state.specified_;
+ /// Sets the encapsulated value to 0.
+ Optional()
+ : default_(T(0)), unspecified_(true) {
}
- /// @brief Checks if the value is specified or unspecified.
+ /// @brief Constructor
///
- /// @return true if the value is specified, false otherwise.
- bool isSpecified() const {
- return (specified_);
- }
-
- /// @brief Specifies a new value value and marks it "specified".
+ /// Creates optional value and marks it as "specified".
///
- /// @param value New actual value.
- void operator=(const T& value) {
- specify(value);
+ /// @param value value to be assigned.
+ explicit Optional(T value)
+ : default_(value), unspecified_(false) {
}
- /// @brief Equality operator.
- ///
- /// @param value Actual value to compare to.
- ///
- /// @return true if the value is specified and equals the argument.
- bool operator==(const T& value) const {
- return (specified_ && (value_ == value));
+ /// @brief Retrieves the actual value.
+ T get() const {
+ return (default_);
}
- /// @brief Inequality operator.
+ /// @brief Modifies the flag that indicates whether the value is specified
+ /// or unspecified.
///
- /// @param value Actual value to compare to.
- ///
- /// @return true if the value is unspecified or unequal.
- bool operator!=(const T& value) const {
- return (!operator==(value));
+ /// @param unspecified new value of the flag. If it is @c true, the
+ /// value is marked as unspecified, otherwise it is marked as specified.
+ void unspecified(bool unspecified) {
+ unspecified_ = unspecified;
}
- /// @brief Type cast operator.
- ///
- /// This operator converts the optional value to the actual value being
- /// encapsulated.
+ /// @brief Checks if the value has been specified or unspecified.
///
- /// @return Encapsulated value.
- operator T() const {
- return (value_);
+ /// @return true if the value hasn't been specified, false otherwise.
+ bool unspecified() const {
+ return (unspecified_);
}
-private:
- T value_; ///< Encapsulated value.
- bool specified_; ///< Flag which indicates if the value is specified.
+protected:
+ T default_; ///< Encapsulated value.
+ bool unspecified_; ///< Flag which indicates if the value is specified.
};
+/// @brief Specialization of the default @c Optional constructor for
+/// strings.
+///
+/// It calls default string object constructor.
+template<>
+inline Optional<std::string>::Optional()
+ : default_(), unspecified_(true) {
+}
+
/// @brief Inserts an optional value to a stream.
///
/// This function overloads the global operator<< to behave as in
-/// @c ostream::operator<< but applied to @c OptionalValue objects.
+/// @c ostream::operator<< but applied to @c Optional objects.
///
/// @param os A @c std::ostream object to which the value is inserted.
-/// @param optional_value An @c OptionalValue object to be inserted into
+/// @param optional_value An @c Optional object to be inserted into
/// a stream.
-/// @tparam Type of the value encapsulated by the @c OptionalValue object.
+/// @tparam Type of the value encapsulated by the @c Optional object.
///
/// @return A reference to the stream after insertion.
template<typename T>
std::ostream&
-operator<<(std::ostream& os, const OptionalValue<T>& optional_value) {
+operator<<(std::ostream& os, const Optional<T>& optional_value) {
os << optional_value.get();
return (os);
}
-// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2015-2019 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
using namespace isc::util;
-// This test checks that the constructor sets the values passed as arguments.
-TEST(OptionalValueTest, constructor) {
- // Do not specify the second parameter. The default should be that
- // the value is "unspecified".
- OptionalValue<int> value1(10);
+// This test checks that the constructors work correctly.
+TEST(OptionalTest, constructor) {
+ // Explicitly set a value via constructor. The value becomes
+ // specified.
+ Optional<int> value1(10);
EXPECT_EQ(10, value1.get());
- EXPECT_FALSE(value1.isSpecified());
+ EXPECT_FALSE(value1.unspecified());
- // Use the non-default value for second parameter.
- OptionalValue<int> value2(2, true);
- EXPECT_EQ(2, value2.get());
- EXPECT_TRUE(value2.isSpecified());
+ // Do not set a value in a constructor. The value should be
+ // unspecified.
+ Optional<int> value2;
+ EXPECT_EQ(0, value2.get());
+ EXPECT_TRUE(value2.unspecified());
}
-// This test checks that the OptionalValue::set and OptionalValue::specify
-// set the values as expected.
-TEST(OptionalValueTest, set) {
- OptionalValue<int> value(10);
- ASSERT_EQ(10, value.get());
- ASSERT_FALSE(value.isSpecified());
-
- // Set new value. This should not change the "specified" flag.
- value.set(100);
- ASSERT_EQ(100, value.get());
- ASSERT_FALSE(value.isSpecified());
-
- // Mark value "specified". The value itself should not change.
- value.specify(OptionalValueState(true));
- ASSERT_EQ(100, value.get());
- ASSERT_TRUE(value.isSpecified());
-
- // Once it is "specified", set the new value. It should remain specified.
- value.set(5);
- ASSERT_EQ(5, value.get());
- ASSERT_TRUE(value.isSpecified());
-
- // Mark it "unspecified". The value should remain the same.
- value.specify(OptionalValueState(false));
- ASSERT_EQ(5, value.get());
- ASSERT_FALSE(value.isSpecified());
-}
+TEST(OptionalTest, constructorString) {
+ Optional<std::string> value1("foo");
+ EXPECT_EQ("foo", value1.get());
-// This test checks that the OptionalValue::specify functions may be used
-// to set the new value and to mark value specified.
-TEST(OptionalValueTest, specifyValue) {
- OptionalValue<int> value(10);
- ASSERT_EQ(10, value.get());
- ASSERT_FALSE(value.isSpecified());
-
- // Set the new value and mark it "specified".
- value.specify(123);
- ASSERT_EQ(123, value.get());
- ASSERT_TRUE(value.isSpecified());
-
- // Specify another value. The value should be still "specified".
- value.specify(1000);
- ASSERT_EQ(1000, value.get());
- ASSERT_TRUE(value.isSpecified());
+ Optional<std::string> value2;
+ EXPECT_TRUE(value2.get().empty());
}
// This test checks if the assignment operator assigning an actual
// value to the optional value works as expected.
-TEST(OptionalValueTest, assignValue) {
- OptionalValue<int> value(10);
- ASSERT_EQ(10, value.get());
- ASSERT_FALSE(value.isSpecified());
+TEST(OptionalTest, assignValue) {
+ Optional<int> value(10);
+ EXPECT_EQ(10, value.get());
+ EXPECT_FALSE(value.unspecified());
- // Set the new value and mark it "specified".
+ // Assign a new value.
value = 111;
- ASSERT_EQ(111, value.get());
- ASSERT_TRUE(value.isSpecified());
+ EXPECT_EQ(111, value.get());
+ EXPECT_FALSE(value.unspecified());
- // Specify another value. The value should be still "specified".
+ // Assign another value.
value = 1000;
- ASSERT_EQ(1000, value.get());
- ASSERT_TRUE(value.isSpecified());
+ EXPECT_EQ(1000, value.get());
+ EXPECT_FALSE(value.unspecified());
}
-// This test checks if the equality and inequality operators work
-// correctly for the optional value.
-TEST(OptionalValueTest, equalityOperators) {
- OptionalValue<int> value(10);
- ASSERT_EQ(10, value.get());
- ASSERT_FALSE(value.isSpecified());
-
- EXPECT_FALSE(value == 10);
- EXPECT_TRUE(value != 10);
- EXPECT_FALSE(value == 123);
- EXPECT_TRUE(value != 123);
-
- value.specify(OptionalValueState(true));
-
- EXPECT_TRUE(value == 10);
- EXPECT_FALSE(value != 10);
- EXPECT_FALSE(value == 123);
- EXPECT_TRUE(value != 123);
-
- value = 123;
- EXPECT_TRUE(value == 123);
- EXPECT_FALSE(value != 123);
- EXPECT_FALSE(value == 10);
- EXPECT_TRUE(value != 10);
-
- value.specify(OptionalValueState(false));
-
- EXPECT_FALSE(value == 123);
- EXPECT_TRUE(value != 123);
- EXPECT_FALSE(value == 10);
- EXPECT_TRUE(value != 10);
+// This test checks that it is possible to modify the flag that indicates
+// if the value is specified or unspecified.
+TEST(OptionalTest, modifyUnspecified) {
+ Optional<int> value;
+ EXPECT_TRUE(value.unspecified());
+
+ value.unspecified(false);
+ EXPECT_FALSE(value.unspecified());
+
+ value.unspecified(true);
+ EXPECT_TRUE(value.unspecified());
}
// This test checks if the type case operator returns correct value.
-TEST(OptionalValueTest, typeCastOperator) {
- OptionalValue<int> value(-10, true);
+TEST(OptionalTest, typeCastOperator) {
+ Optional<int> value(-10);
ASSERT_EQ(-10, value.get());
- ASSERT_TRUE(value.isSpecified());
+ ASSERT_FALSE(value.unspecified());
int actual = value;
EXPECT_EQ(-10, actual);