Browse Source

[3367] Moved OptionalValue class to the util library.

Marcin Siodelski 10 years ago
parent
commit
a3ee7a211b

+ 2 - 69
src/bin/dhcp4/tests/dhcp4_client.h

@@ -19,6 +19,7 @@
 #include <dhcp/hwaddr.h>
 #include <dhcp/pkt4.h>
 #include <dhcp4/tests/dhcp4_test_utils.h>
+#include <util/optional_value.h>
 #include <boost/noncopyable.hpp>
 #include <boost/shared_ptr.hpp>
 #include <set>
@@ -34,74 +35,6 @@ public:
         isc::Exception(file, line, what) { };
 };
 
-/// @brief Simple class representing an optional value.
-///
-/// This class encapsulates a value of any type. An additional flag held
-/// by this class indicates if the value is specified, i.e. should be used
-/// by the @c Dhcp4Client class. This is used in cases when the caller
-/// needs to override some values used by the client. For example, the
-/// client sets ciaddr according to the RFC2131, depending on the client's
-/// state and using available lease information. However, a test may need
-/// to override the value being used by the client to test some negative
-/// scenarios (e.g. invalid ciaddr). To do this, the test needs to set
-/// the optional value to the desired value and mark it specified. If the
-/// @c Dhcp4Client finds that the value is specified, it will use this
-/// value in the outgoing message. Otherwise, it will disregard the
-/// value and use the defaults.
-///
-/// @tparam Type of the encapsulated value.
-template<typename T>
-class OptionalValue {
-public:
-
-    /// @brief Constructor
-    ///
-    /// Creates optional value. The value defaults to "unspecified".
-    OptionalValue(const T& value)
-        : value_(value),
-          specified_(false) {
-    }
-
-    /// @brief Retrieves the actual value.
-    T get() const {
-        return (value_);
-    }
-
-    /// @brief Sets the actual value.
-    ///
-    /// @param value New value.
-    void set(const T& value) {
-        value_ = value;
-    }
-
-    /// @brief Sets the new value and marks it specified.
-    ///
-    /// @param value New actual value.
-    void specify(const T& value) {
-        set(value);
-        specify(true);
-    }
-
-    /// @brief Sets the value to "specified".
-    ///
-    /// It does not alter the actual value. It only marks it "specified".
-    /// @param specified boolean that determined if a value is specified or not
-    void specify(const bool specified) {
-        specified_ = specified;
-    }
-
-    /// @brief Checks if the value is specified or unspecified.
-    ///
-    /// @return true if the value is specified, false otherwise.
-    bool isSpecified() const {
-        return (specified_);
-    }
-
-private:
-    T value_;         ///< Encapsulated value.
-    bool specified_;  ///< Flag which indicates if the value is specified.
-};
-
 /// @brief DHCPv4 client used for unit testing.
 ///
 /// This class implements a DHCPv4 "client" which interoperates with the
@@ -367,7 +300,7 @@ public:
     /// 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.
-    OptionalValue<asiolink::IOAddress> ciaddr_;
+    isc::util::OptionalValue<asiolink::IOAddress> ciaddr_;
 
 private:
 

+ 1 - 0
src/lib/util/Makefile.am

@@ -30,6 +30,7 @@ libkea_util_la_SOURCES += memory_segment_local.h memory_segment_local.cc
 if USE_SHARED_MEMORY
 libkea_util_la_SOURCES += memory_segment_mapped.h memory_segment_mapped.cc
 endif
+libkea_util_la_SOURCES += optional_value.h
 libkea_util_la_SOURCES += range_utilities.h
 libkea_util_la_SOURCES += signal_set.cc signal_set.h
 libkea_util_la_SOURCES += encode/base16_from_binary.h

+ 102 - 0
src/lib/util/optional_value.h

@@ -0,0 +1,102 @@
+// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef OPTIONAL_VALUE_H
+#define OPTIONAL_VALUE_H
+
+namespace isc {
+namespace util {
+
+/// @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 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.
+///
+/// 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.
+///
+/// @tparam Type of the encapsulated value.
+template<typename T>
+class OptionalValue {
+public:
+
+    /// @brief Constructor
+    ///
+    /// Creates optional value. The value defaults to "unspecified".
+    ///
+    /// @param value Default explicit value.
+    /// @param specified Boolean value which determines if the value is
+    /// initially specified or not (default is false).
+    OptionalValue(const T& value, const bool specified = false)
+        : value_(value),
+          specified_(specified) {
+    }
+
+    /// @brief Retrieves the actual value.
+    T get() const {
+        return (value_);
+    }
+
+    /// @brief Sets the actual value.
+    ///
+    /// @param value New value.
+    void set(const T& value) {
+        value_ = value;
+    }
+
+    /// @brief Sets the new value and marks it specified.
+    ///
+    /// @param value New actual value.
+    void specify(const T& value) {
+        set(value);
+        specify(true);
+    }
+
+    /// @brief Sets the value to "specified" or "unspecified".
+    ///
+    /// It does not alter the actual value. It only marks it "specified" or
+    /// "unspecified".
+    /// @param specified boolean that determined if a value is specified or not
+    void specify(const bool specified) {
+        specified_ = specified;
+    }
+
+    /// @brief Checks if the value is specified or unspecified.
+    ///
+    /// @return true if the value is specified, false otherwise.
+    bool isSpecified() const {
+        return (specified_);
+    }
+
+private:
+    T value_;         ///< Encapsulated value.
+    bool specified_;  ///< Flag which indicates if the value is specified.
+};
+
+} // end of namespace isc::util
+} // end of namespace isc
+
+#endif // OPTIONAL_VALUE_H

+ 1 - 0
src/lib/util/tests/Makefile.am

@@ -40,6 +40,7 @@ run_unittests_SOURCES += memory_segment_mapped_unittest.cc
 endif
 run_unittests_SOURCES += memory_segment_common_unittest.h
 run_unittests_SOURCES += memory_segment_common_unittest.cc
+run_unittests_SOURCES += optional_value_unittest.cc
 run_unittests_SOURCES += qid_gen_unittest.cc
 run_unittests_SOURCES += random_number_generator_unittest.cc
 run_unittests_SOURCES += socketsession_unittest.cc

+ 83 - 0
src/lib/util/tests/optional_value_unittest.cc

@@ -0,0 +1,83 @@
+// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <config.h>
+#include <util/optional_value.h>
+#include <gtest/gtest.h>
+
+namespace {
+
+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);
+    EXPECT_EQ(10, value1.get());
+    EXPECT_FALSE(value1.isSpecified());
+
+    // Use the non-default value for second parameter.
+    OptionalValue<int> value2(2, true);
+    EXPECT_EQ(2, value2.get());
+    EXPECT_TRUE(value2.isSpecified());
+}
+
+// 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(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(false);
+    ASSERT_EQ(5, value.get());
+    ASSERT_FALSE(value.isSpecified());
+}
+
+// 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());
+}
+
+} // end of anonymous namespace