dhcp client: add class DHCPOptionWriter
Add class DHCPOptionsWriter for writing dhcp options.
Also add the corresponding unittests.
while there, change the variable name from 'option_number'
to 'option_code' for better readability.
Bug: 25642025
TEST=compile and unittests
Change-Id: I6410651d32525760405df427b38c961ce106293f
diff --git a/dhcp_client.gyp b/dhcp_client.gyp
index 447a3f0..474c029 100644
--- a/dhcp_client.gyp
+++ b/dhcp_client.gyp
@@ -60,6 +60,7 @@
'device_info.cc',
'dhcp_message.cc',
'dhcp_options_parser.cc',
+ 'dhcp_options_writer.cc',
'dhcpv4.cc',
'message_loop_event_dispatcher.cc',
'manager.cc',
@@ -87,6 +88,7 @@
'device_info_unittest.cc',
'dhcp_message_unittest.cc',
'dhcp_options_parser_unittest.cc',
+ 'dhcp_options_writer_unittest.cc',
'testrunner.cc',
],
},
diff --git a/dhcp_message.cc b/dhcp_message.cc
index 20100c8..cfb9433 100644
--- a/dhcp_message.cc
+++ b/dhcp_message.cc
@@ -27,6 +27,8 @@
#include <base/logging.h>
+#include "dhcp_client/dhcp_options.h"
+
using shill::ByteString;
namespace dhcp_client {
@@ -35,23 +37,12 @@
const int kClientHardwareAddressLength = 16;
const int kServerNameLength = 64;
const int kBootFileLength = 128;
-const int kDHCPOptionLength = 312;
const uint32_t kMagicCookie = 0x63825363;
const size_t kDHCPMessageMaxLength = 548;
const size_t kDHCPMessageMinLength = 236;
const uint8_t kDHCPMessageBootRequest = 1;
const uint8_t kDHCPMessageBootReply = 2;
-// Constants for DHCP options.
-const uint8_t kDHCPOptionPad = 0;
-const uint8_t kDHCPOptionDNSServer = 6;
-const uint8_t kDHCPOptionLeaseTime = 51;
-const uint8_t kDHCPOptionMessageType = 53;
-const uint8_t kDHCPOptionServerIdentifier = 54;
-const uint8_t kDHCPOptionRenewalTime = 58;
-const uint8_t kDHCPOptionRebindingTime = 59;
-const uint8_t kDHCPOptionEnd = 255;
-
// Follow the naming in rfc2131 for this struct.
struct __attribute__((__packed__)) RawDHCPMessage {
uint8_t op;
@@ -150,11 +141,11 @@
const uint8_t* end_ptr = options + options_length;
std::set<uint8_t> options_set;
while (ptr < end_ptr) {
- uint8_t option_number = *ptr++;
- int option_number_int = static_cast<int>(option_number);
- if (option_number == kDHCPOptionPad) {
+ uint8_t option_code = *ptr++;
+ int option_code_int = static_cast<int>(option_code);
+ if (option_code == kDHCPOptionPad) {
continue;
- } else if (option_number == kDHCPOptionEnd) {
+ } else if (option_code == kDHCPOptionEnd) {
// We reach the end of the option field.
// A DHCP message must have option 53: DHCP Message Type.
if (options_set.find(kDHCPOptionMessageType) == options_set.end()) {
@@ -165,29 +156,29 @@
}
if (ptr >= end_ptr) {
LOG(ERROR) << "Failed to decode dhcp options, no option length field"
- "for option: " << option_number_int;
+ "for option: " << option_code_int;
return false;
}
uint8_t option_length = *ptr++;
if (ptr + option_length >= end_ptr) {
LOG(ERROR) << "Failed to decode dhcp options, invalid option length field"
- "for option: " << option_number_int;
+ "for option: " << option_code_int;
return false;
}
- if (options_set.find(option_number) != options_set.end()) {
- LOG(ERROR) << "Found repeated DHCP option: " << option_number_int;
+ if (options_set.find(option_code) != options_set.end()) {
+ LOG(ERROR) << "Found repeated DHCP option: " << option_code_int;
return false;
}
// Here we find a valid DHCP option.
- auto it = options_map_.find(option_number);
+ auto it = options_map_.find(option_code);
if (it != options_map_.end()) {
ParserContext* context = &(it->second);
if (!context->parser->GetOption(ptr, option_length, context->output)) {
return false;
}
- options_set.insert(option_number);
+ options_set.insert(option_code);
} else {
- DLOG(INFO) << "Ignore DHCP option: " << option_number_int;
+ DLOG(INFO) << "Ignore DHCP option: " << option_code_int;
}
// Move to next tag.
ptr += option_length;
diff --git a/dhcp_message.h b/dhcp_message.h
index f8d2634..acd5db8 100644
--- a/dhcp_message.h
+++ b/dhcp_message.h
@@ -23,10 +23,10 @@
#include <vector>
#include <base/macros.h>
-
-#include <dhcp_client/dhcp_options_parser.h>
#include <shill/net/byte_string.h>
+#include "dhcp_client/dhcp_options_parser.h"
+
namespace dhcp_client {
static const uint8_t kDHCPMessageTypeDiscover = 1;
diff --git a/dhcp_message_unittest.cc b/dhcp_message_unittest.cc
index 4a7f163..2b9b9c8 100644
--- a/dhcp_message_unittest.cc
+++ b/dhcp_message_unittest.cc
@@ -14,7 +14,7 @@
// limitations under the License.
//
-#include <dhcp_client/dhcp_message.h>
+#include "dhcp_client/dhcp_message.h"
#include <gtest/gtest.h>
diff --git a/dhcp_options.h b/dhcp_options.h
new file mode 100644
index 0000000..48733c7
--- /dev/null
+++ b/dhcp_options.h
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef DHCP_CLIENT_DHCP_OPTIONS_H_
+#define DHCP_CLIENT_DHCP_OPTIONS_H_
+
+namespace dhcp_client {
+// Constants for DHCP options.
+const uint8_t kDHCPOptionPad = 0;
+const uint8_t kDHCPOptionDNSServer = 6;
+const uint8_t kDHCPOptionLeaseTime = 51;
+const uint8_t kDHCPOptionMessageType = 53;
+const uint8_t kDHCPOptionServerIdentifier = 54;
+const uint8_t kDHCPOptionRenewalTime = 58;
+const uint8_t kDHCPOptionRebindingTime = 59;
+const uint8_t kDHCPOptionEnd = 255;
+
+const int kDHCPOptionLength = 312;
+} // namespace dhcp_client
+
+#endif // DHCP_CLIENT_DHCP_OPTIONS_H_
diff --git a/dhcp_options_writer.cc b/dhcp_options_writer.cc
new file mode 100644
index 0000000..e6bea8c
--- /dev/null
+++ b/dhcp_options_writer.cc
@@ -0,0 +1,163 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "dhcp_client/dhcp_options_writer.h"
+
+#include <netinet/in.h>
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <base/logging.h>
+#include <base/macros.h>
+
+#include "dhcp_client/dhcp_options.h"
+
+namespace {
+base::LazyInstance<dhcp_client::DHCPOptionsWriter> g_dhcp_options_writer
+ = LAZY_INSTANCE_INITIALIZER;
+} // namespace
+
+namespace dhcp_client {
+
+DHCPOptionsWriter* DHCPOptionsWriter::GetInstance() {
+ return g_dhcp_options_writer.Pointer();
+}
+
+int DHCPOptionsWriter::WriteUInt8Option(uint8_t* buffer,
+ uint8_t option_code,
+ uint8_t value) {
+ *buffer++ = option_code;
+ *buffer++ = sizeof(uint8_t);
+ *buffer++ = value;
+ return sizeof(uint8_t) + 2;
+}
+
+int DHCPOptionsWriter::WriteUInt16Option(uint8_t* buffer,
+ uint8_t option_code,
+ uint16_t value) {
+ *buffer++ = option_code;
+ *buffer++ = sizeof(uint16_t);
+ *reinterpret_cast<uint16_t*>(buffer) = htons(value);
+ buffer += sizeof(uint16_t);
+ return sizeof(uint16_t) + 2;
+}
+
+int DHCPOptionsWriter::WriteUInt32Option(uint8_t* buffer,
+ uint8_t option_code,
+ uint32_t value) {
+ *buffer++ = option_code;
+ *buffer++ = sizeof(uint32_t);
+ *reinterpret_cast<uint32_t*>(buffer) = htonl(value);
+ buffer += sizeof(uint32_t);
+ return sizeof(uint32_t) + 2;
+}
+
+int DHCPOptionsWriter::WriteUInt8ListOption(uint8_t* buffer,
+ uint8_t option_code,
+ const std::vector<uint8_t>& value) {
+ *buffer++ = option_code;
+ *buffer++ = value.size() * sizeof(uint8_t);
+ for (uint8_t element : value) {
+ *buffer++ = element;
+ }
+ return value.size() * sizeof(uint8_t) + 2;
+}
+
+int DHCPOptionsWriter::WriteUInt16ListOption(uint8_t* buffer,
+ uint8_t option_code,
+ const std::vector<uint16_t>& value) {
+ if (value.size() == 0) {
+ LOG(ERROR) << "Faild to write option: " << static_cast<int>(option_code)
+ << ", because value size cannot be 0";
+ return -1;
+ }
+ *buffer++ = option_code;
+ *buffer++ = value.size() * sizeof(uint16_t);
+ for (uint16_t element : value) {
+ *reinterpret_cast<uint16_t*>(buffer) = htons(element);
+ buffer += sizeof(uint16_t);
+ }
+ return value.size() * sizeof(uint16_t) + 2;
+}
+
+int DHCPOptionsWriter::WriteUInt32ListOption(uint8_t* buffer,
+ uint8_t option_code,
+ const std::vector<uint32_t>& value) {
+ if (value.size() == 0) {
+ LOG(ERROR) << "Faild to write option: " << static_cast<int>(option_code)
+ << ", because value size cannot be 0";
+ return -1;
+ }
+ *buffer++ = option_code;
+ *buffer++ = value.size() * sizeof(uint32_t);
+ for (uint32_t element : value) {
+ *reinterpret_cast<uint32_t*>(buffer) = htonl(element);
+ buffer += sizeof(uint32_t);
+ }
+ return value.size() * sizeof(uint32_t) + 2;
+}
+
+int DHCPOptionsWriter::WriteUInt32PairListOption(uint8_t* buffer,
+ uint8_t option_code,
+ const std::vector<std::pair<uint32_t, uint32_t>>& value) {
+ if (value.size() == 0) {
+ LOG(ERROR) << "Faild to write option: " << static_cast<int>(option_code)
+ << ", because value size cannot be 0";
+ return -1;
+ }
+ *buffer++ = option_code;
+ *buffer++ = value.size() * 2 * sizeof(uint32_t);
+ for (auto element : value) {
+ *reinterpret_cast<uint32_t*>(buffer) = htonl(element.first);
+ buffer += sizeof(uint32_t);
+ *reinterpret_cast<uint32_t*>(buffer) = htonl(element.second);
+ buffer += sizeof(uint32_t);
+ }
+ return value.size() * sizeof(uint32_t) * 2 + 2;
+}
+
+int DHCPOptionsWriter::WriteBoolOption(uint8_t* buffer,
+ uint8_t option_code,
+ const bool value) {
+ *buffer++ = option_code;
+ *buffer++ = sizeof(uint8_t);
+ *buffer++ = value ? 1 : 0;
+ return sizeof(uint8_t) + 2;
+}
+
+int DHCPOptionsWriter::WriteStringOption(uint8_t* buffer,
+ uint8_t option_code,
+ const std::string& value) {
+ if (value.size() == 0) {
+ LOG(ERROR) << "Faild to write option: " << static_cast<int>(option_code)
+ << ", because value size cannot be 0";
+ return -1;
+ }
+ *buffer++ = option_code;
+ *buffer++ = value.size() * sizeof(uint8_t);
+ for (unsigned int i = 0; i < value.size(); i++) {
+ *buffer++ = static_cast<uint8_t>(value[i]);
+ }
+ return value.size() * sizeof(uint8_t) + 2;
+}
+
+void DHCPOptionsWriter::WriteEndTag(uint8_t* buffer) {
+ *buffer = kDHCPOptionEnd;
+}
+
+} // namespace dhcp_client
diff --git a/dhcp_options_writer.h b/dhcp_options_writer.h
new file mode 100644
index 0000000..21ed7ab
--- /dev/null
+++ b/dhcp_options_writer.h
@@ -0,0 +1,69 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef DHCP_CLIENT_OPTION_WRITER_H_
+#define DHCP_CLIENT_OPTION_WRITER_H_
+
+#include <cstdint>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <base/lazy_instance.h>
+
+namespace dhcp_client {
+
+class DHCPOptionsWriter {
+ public:
+ ~DHCPOptionsWriter() {}
+ static DHCPOptionsWriter* GetInstance();
+ int WriteUInt8Option(uint8_t* buffer, uint8_t option_code, uint8_t value);
+ int WriteUInt16Option(uint8_t* buffer,
+ uint8_t option_code,
+ uint16_t value);
+ int WriteUInt32Option(uint8_t* buffer,
+ uint8_t option_code,
+ uint32_t value);
+ int WriteUInt8ListOption(uint8_t* buffer,
+ uint8_t option_code,
+ const std::vector<uint8_t>& value);
+ int WriteUInt16ListOption(uint8_t* buffer,
+ uint8_t option_code,
+ const std::vector<uint16_t>& value);
+ int WriteUInt32ListOption(uint8_t* buffer,
+ uint8_t option_code,
+ const std::vector<uint32_t>& value);
+ int WriteUInt32PairListOption(uint8_t* buffer,
+ uint8_t option_code,
+ const std::vector<std::pair<uint32_t, uint32_t>>& value);
+ int WriteBoolOption(uint8_t* buffer,
+ uint8_t option_code,
+ const bool value);
+ int WriteStringOption(uint8_t* buffer,
+ uint8_t option_code,
+ const std::string& value);
+ void WriteEndTag(uint8_t* buffer);
+
+ protected:
+ DHCPOptionsWriter() {}
+
+ private:
+ friend struct base::DefaultLazyInstanceTraits<DHCPOptionsWriter>;
+};
+
+} // namespace dhcp_client
+
+#endif // DHCP_CLIENT_OPTION_WRITER_H_
diff --git a/dhcp_options_writer_unittest.cc b/dhcp_options_writer_unittest.cc
new file mode 100644
index 0000000..b9b18e5
--- /dev/null
+++ b/dhcp_options_writer_unittest.cc
@@ -0,0 +1,231 @@
+//
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <dhcp_client/dhcp_options_writer.h>
+
+#include <netinet/in.h>
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "dhcp_client/dhcp_options.h"
+
+namespace dhcp_client {
+
+namespace {
+const uint8_t kFakeOptionCode1 = 3;
+const uint8_t kFakeOptionCode2 = 45;
+const uint8_t kFakeOptionCode3 = 251;
+
+const uint8_t kFakeUInt8Option = 0x22;
+const uint8_t kFakeUInt8OptionResult[] = {
+ kFakeOptionCode1,
+ sizeof(uint8_t),
+ 0x22};
+
+const uint16_t kFakeUInt16Option = 0x1516;
+const uint8_t kFakeUInt16OptionResult[] = {
+ kFakeOptionCode2,
+ sizeof(uint16_t),
+ // Use the network byte order.
+ 0x15, 0x16};
+
+const uint32_t kFakeUInt32Option = 0x32a0bf01;
+const uint8_t kFakeUInt32OptionResult[] = {
+ kFakeOptionCode3,
+ sizeof(uint32_t),
+ // Use the network byte order.
+ 0x32, 0xa0, 0xbf, 0x01};
+
+const std::vector<uint8_t> kFakeUInt8ListOption =
+ {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
+const uint8_t kFakeUInt8ListOptionResult[] = {
+ kFakeOptionCode1,
+ static_cast<uint8_t>(kFakeUInt8ListOption.size()),
+ // Use the network byte order.
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
+
+const std::vector<uint16_t> kFakeUInt16ListOption =
+ {0xb1a2, 0x0264, 0xdc03, 0x92c4, 0xa500, 0x0010};
+const uint8_t kFakeUInt16ListOptionResult[] = {
+ kFakeOptionCode2,
+ static_cast<uint8_t>(sizeof(uint16_t) * kFakeUInt16ListOption.size()),
+ // Use the network byte order.
+ 0xb1, 0xa2, 0x02, 0x64, 0xdc, 0x03, 0x92, 0xc4, 0xa5, 0x00, 0x00, 0x10};
+
+const std::vector<uint32_t> kFakeUInt32ListOption =
+ {0x03a64301, 0x03f52614, 0x7c5d9eff, 0x0138b26e};
+const uint8_t kFakeUInt32ListOptionResult[] = {
+ kFakeOptionCode3,
+ static_cast<uint8_t>(sizeof(uint32_t) * kFakeUInt32ListOption.size()),
+ // Use the network byte order.
+ 0x03, 0xa6, 0x43, 0x01, 0x03, 0xf5, 0x26, 0x14,
+ 0x7c, 0x5d, 0x9e, 0xff, 0x01, 0x38, 0xb2, 0x6e};
+
+const std::vector<std::pair<uint32_t, uint32_t>> kFakeUInt32PairListOption =
+ {{0x03b576a1, 0xfa070054}, {0x650c3d22, 0x1397e5bb}};
+const uint8_t kFakeUInt32PairListOptionResult[] = {
+ kFakeOptionCode1,
+ static_cast<uint8_t>
+ (sizeof(uint32_t) * 2 * kFakeUInt32PairListOption.size()),
+ // Use the network byte order.
+ 0x03, 0xb5, 0x76, 0xa1, 0xfa, 0x07, 0x00, 0x54,
+ 0x65, 0x0c, 0x3d, 0x22, 0x13, 0x97, 0xe5, 0xbb};
+
+const std::string kFakeStringOption = "fakestring";
+const uint8_t kFakeStringOptionResult[] = {
+ kFakeOptionCode1,
+ static_cast<uint8_t>(kFakeStringOption.size()),
+ 'f', 'a', 'k', 'e', 's', 't', 'r', 'i', 'n', 'g'};
+
+const uint8_t kFakeBoolOptionTrue = true;
+const uint8_t kFakeBoolOptionResultTrue[] = {
+ kFakeOptionCode1,
+ sizeof(uint8_t),
+ 0x01};
+
+const uint8_t kFakeBoolOptionFalse = false;
+const uint8_t kFakeBoolOptionResultFalse[] = {
+ kFakeOptionCode2,
+ sizeof(uint8_t),
+ 0x00};
+} // namespace
+
+
+class DHCPOptionsWriterTest : public testing::Test {
+ protected:
+ DHCPOptionsWriter* options_writer_;
+};
+
+TEST_F(DHCPOptionsWriterTest, WriteUInt8) {
+ uint8_t option[kDHCPOptionLength];
+ options_writer_ = DHCPOptionsWriter::GetInstance();
+ int length = options_writer_->WriteUInt8Option(option,
+ kFakeOptionCode1,
+ kFakeUInt8Option);
+ EXPECT_NE(-1, length);
+ EXPECT_EQ(0, std::memcmp(option, kFakeUInt8OptionResult, length));
+}
+
+TEST_F(DHCPOptionsWriterTest, WriteUInt16) {
+ uint8_t option[kDHCPOptionLength];
+ options_writer_ = DHCPOptionsWriter::GetInstance();
+ int length = options_writer_->WriteUInt16Option(option,
+ kFakeOptionCode2,
+ kFakeUInt16Option);
+ EXPECT_NE(-1, length);
+ EXPECT_EQ(0, std::memcmp(option, kFakeUInt16OptionResult, length));
+}
+
+TEST_F(DHCPOptionsWriterTest, WriteUInt32) {
+ uint8_t option[kDHCPOptionLength];
+ options_writer_ = DHCPOptionsWriter::GetInstance();
+ int length = options_writer_->WriteUInt32Option(option,
+ kFakeOptionCode3,
+ kFakeUInt32Option);
+ EXPECT_NE(-1, length);
+ EXPECT_EQ(0, std::memcmp(option, kFakeUInt32OptionResult, length));
+}
+
+TEST_F(DHCPOptionsWriterTest, WriteUInt8List) {
+ uint8_t option[kDHCPOptionLength];
+ options_writer_ = DHCPOptionsWriter::GetInstance();
+ int length = options_writer_->WriteUInt8ListOption(option,
+ kFakeOptionCode1,
+ kFakeUInt8ListOption);
+ EXPECT_NE(-1, length);
+ EXPECT_EQ(0, std::memcmp(option, kFakeUInt8ListOptionResult, length));
+}
+
+TEST_F(DHCPOptionsWriterTest, WriteUInt16List) {
+ uint8_t option[kDHCPOptionLength];
+ options_writer_ = DHCPOptionsWriter::GetInstance();
+ int length = options_writer_->WriteUInt16ListOption(option,
+ kFakeOptionCode2,
+ kFakeUInt16ListOption);
+ EXPECT_NE(-1, length);
+ EXPECT_EQ(0, std::memcmp(option, kFakeUInt16ListOptionResult, length));
+}
+
+TEST_F(DHCPOptionsWriterTest, WriteUInt32List) {
+ uint8_t option[kDHCPOptionLength];
+ options_writer_ = DHCPOptionsWriter::GetInstance();
+ int length = options_writer_->WriteUInt32ListOption(option,
+ kFakeOptionCode3,
+ kFakeUInt32ListOption);
+ EXPECT_NE(-1, length);
+ EXPECT_EQ(0, std::memcmp(option, kFakeUInt32ListOptionResult, length));
+}
+
+TEST_F(DHCPOptionsWriterTest, WriteUInt32PairList) {
+ uint8_t option[kDHCPOptionLength];
+ options_writer_ = DHCPOptionsWriter::GetInstance();
+ int length =
+ options_writer_->WriteUInt32PairListOption(option,
+ kFakeOptionCode1,
+ kFakeUInt32PairListOption);
+ EXPECT_NE(-1, length);
+ EXPECT_EQ(0, std::memcmp(option, kFakeUInt32PairListOptionResult, length));
+}
+
+TEST_F(DHCPOptionsWriterTest, WriteString) {
+ uint8_t option[kDHCPOptionLength];
+ options_writer_ = DHCPOptionsWriter::GetInstance();
+ int length = options_writer_->WriteStringOption(option,
+ kFakeOptionCode1,
+ kFakeStringOption);
+ EXPECT_NE(-1, length);
+ EXPECT_EQ(0, std::memcmp(option, kFakeStringOptionResult, length));
+}
+
+
+TEST_F(DHCPOptionsWriterTest, WriteBoolTrue) {
+ uint8_t option[kDHCPOptionLength];
+ options_writer_ = DHCPOptionsWriter::GetInstance();
+ int length = options_writer_->WriteBoolOption(option,
+ kFakeOptionCode1,
+ kFakeBoolOptionTrue);
+ EXPECT_NE(-1, length);
+ EXPECT_EQ(0, std::memcmp(option, kFakeBoolOptionResultTrue, length));
+}
+
+TEST_F(DHCPOptionsWriterTest, WriteBoolFalse) {
+ uint8_t option[kDHCPOptionLength];
+ options_writer_ = DHCPOptionsWriter::GetInstance();
+ int length = options_writer_->WriteBoolOption(option,
+ kFakeOptionCode2,
+ kFakeBoolOptionFalse);
+ EXPECT_NE(-1, length);
+ EXPECT_EQ(0, std::memcmp(option, kFakeBoolOptionResultFalse, length));
+}
+
+TEST_F(DHCPOptionsWriterTest, WriteEndTag) {
+ uint8_t option[kDHCPOptionLength];
+ options_writer_ = DHCPOptionsWriter::GetInstance();
+ int length = options_writer_->WriteStringOption(option,
+ kFakeOptionCode1,
+ kFakeStringOption);
+ EXPECT_NE(-1, length);
+ options_writer_->WriteEndTag(option + length);
+ EXPECT_EQ(0, std::memcmp(option, kFakeStringOptionResult, length));
+ EXPECT_EQ(kDHCPOptionEnd, *(option + length));
+}
+
+} // namespace dhcp_client