| // |
| // 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_parser.h> |
| |
| #include <netinet/in.h> |
| |
| #include <memory> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include <gtest/gtest.h> |
| #include <shill/net/byte_string.h> |
| |
| using shill::ByteString; |
| |
| namespace { |
| const uint8_t kFakeUInt8Option[] = {0x02}; |
| const uint8_t kFakeUInt8OptionLength = 1; |
| const uint8_t kFakeUInt16Option[] = {0x2a, 0x01}; |
| const uint8_t kFakeUInt16OptionLength = 2; |
| const uint8_t kFakeUInt32Option[] = {0x01, 0x02, 0x00, 0xfa}; |
| const uint8_t kFakeUInt32OptionLength = 4; |
| const uint8_t kFakeUInt8ListOption[] = |
| {0x01, 0x02, 0x00, 0xfa, 0x23, 0xae, 0x1f, 0x00}; |
| const uint8_t kFakeUInt8ListOptionLength = 8; |
| |
| const uint8_t kFakeUInt16ListOption[] = |
| {0xaa, 0x26, 0x4b, 0x00, 0xff, 0xc2, 0xcf, 0x0d, 0xe0, 0x01}; |
| const uint8_t kFakeUInt16ListOptionLength = 10; |
| |
| const uint8_t kFakeUInt32ListOption[] = {0x01, 0x02, 0x00, 0xfa, |
| 0x23, 0xae, 0x1f, 0x00, |
| 0x0c, 0x53, 0x33, 0x10, |
| 0x47, 0x80, 0xb3, 0xff}; |
| const uint8_t kFakeUInt32ListOptionLength = 16; |
| |
| const uint8_t kFakeUInt32PairListOption[] = {0x21, 0xa0, 0xeb, 0x73, |
| 0x01, 0x00, 0x1f, 0x10, |
| 0xc9, 0x22, 0x3a, 0x37, |
| 0xff, 0x00, 0xbe, 0xd0}; |
| const uint8_t kFakeUInt32PairListOptionLength = 16; |
| |
| const unsigned char kFakeStringOption[] = |
| {'f', 'a', 'k', 'e', 's', 't', 'r', 'i', 'n', 'g'}; |
| const uint8_t kFakeStringOptionLength = 10; |
| |
| const unsigned char kFakeByteArrayOption[] = |
| {'f', 'a', 'k', 'e', 'b', 'y', 't', 'e', 'a', 'r', 'r', 'a', 'y'}; |
| |
| const uint8_t kFakeBoolOptionEnable[] = {0x01}; |
| const uint8_t kFakeBoolOptionDisable[] = {0x00}; |
| const uint8_t kFakeBoolOptionLength = 1; |
| } // namespace |
| |
| namespace dhcp_client { |
| |
| class ParserTest : public testing::Test { |
| protected: |
| std::unique_ptr<DHCPOptionsParser> parser_; |
| }; |
| |
| TEST_F(ParserTest, ParseUInt8) { |
| parser_.reset(new UInt8Parser()); |
| uint8_t value; |
| EXPECT_TRUE(parser_->GetOption(kFakeUInt8Option, |
| kFakeUInt8OptionLength, |
| &value)); |
| EXPECT_EQ(*kFakeUInt8Option, value); |
| } |
| |
| TEST_F(ParserTest, ParseUInt16) { |
| parser_.reset(new UInt16Parser()); |
| uint16_t value; |
| uint16_t target_value = |
| *reinterpret_cast<const uint16_t*>(kFakeUInt16Option); |
| target_value = ntohs(target_value); |
| EXPECT_TRUE(parser_->GetOption(kFakeUInt16Option, |
| kFakeUInt16OptionLength, |
| &value)); |
| EXPECT_EQ(target_value, value); |
| } |
| |
| TEST_F(ParserTest, ParseUInt32) { |
| parser_.reset(new UInt32Parser()); |
| uint32_t value; |
| uint32_t target_value = |
| *reinterpret_cast<const uint32_t*>(kFakeUInt32Option); |
| target_value = ntohl(target_value); |
| EXPECT_TRUE(parser_->GetOption(kFakeUInt32Option, |
| kFakeUInt32OptionLength, |
| &value)); |
| EXPECT_EQ(target_value, value); |
| } |
| |
| TEST_F(ParserTest, ParseUInt8List) { |
| parser_.reset(new UInt8ListParser()); |
| std::vector<uint8_t> value; |
| std::vector<uint8_t> target_value; |
| uint8_t length = kFakeUInt8ListOptionLength; |
| const uint8_t* uint8_list = |
| reinterpret_cast<const uint8_t*>(kFakeUInt8ListOption); |
| target_value = std::vector<uint8_t>(uint8_list, uint8_list + length); |
| EXPECT_TRUE(parser_->GetOption(kFakeUInt8ListOption, |
| kFakeUInt8ListOptionLength, |
| &value)); |
| EXPECT_EQ(target_value, value); |
| } |
| |
| TEST_F(ParserTest, ParseUInt16List) { |
| parser_.reset(new UInt16ListParser()); |
| std::vector<uint16_t> value; |
| std::vector<uint16_t> target_value; |
| std::vector<uint16_t> target_value_net_order; |
| int length = kFakeUInt16ListOptionLength / sizeof(uint16_t); |
| const uint16_t* uint16_list = |
| reinterpret_cast<const uint16_t*>(kFakeUInt16ListOption); |
| target_value_net_order = |
| std::vector<uint16_t>(uint16_list, uint16_list + length); |
| for (uint16_t element : target_value_net_order) { |
| target_value.push_back(ntohs(element)); |
| } |
| EXPECT_TRUE(parser_->GetOption(kFakeUInt16ListOption, |
| kFakeUInt16ListOptionLength, |
| &value)); |
| EXPECT_EQ(target_value, value); |
| } |
| |
| TEST_F(ParserTest, ParseUInt32List) { |
| parser_.reset(new UInt32ListParser()); |
| std::vector<uint32_t> value; |
| std::vector<uint32_t> target_value; |
| std::vector<uint32_t> target_value_net_order; |
| int length = kFakeUInt32ListOptionLength / sizeof(uint32_t); |
| const uint32_t* uint32_list = |
| reinterpret_cast<const uint32_t*>(kFakeUInt32ListOption); |
| target_value_net_order = |
| std::vector<uint32_t>(uint32_list, uint32_list + length); |
| for (uint32_t element : target_value_net_order) { |
| target_value.push_back(ntohl(element)); |
| } |
| EXPECT_TRUE(parser_->GetOption(kFakeUInt32ListOption, |
| kFakeUInt32ListOptionLength, |
| &value)); |
| EXPECT_EQ(target_value, value); |
| } |
| |
| TEST_F(ParserTest, ParseUInt32PairList) { |
| parser_.reset(new UInt32PairListParser()); |
| int length = kFakeUInt32PairListOptionLength / (2 * sizeof(uint32_t)); |
| const uint32_t* uint32_array = |
| reinterpret_cast<const uint32_t*>(kFakeUInt32PairListOption); |
| std::vector<uint32_t> uint32_vector = |
| std::vector<uint32_t>(uint32_array, uint32_array + length * 2); |
| std::vector<std::pair<uint32_t, uint32_t>> target_value; |
| for (int i = 0; i < length; i++) { |
| target_value.push_back( |
| std::pair<uint32_t, uint32_t>(ntohl(uint32_vector[2 * i]), |
| ntohl(uint32_vector[2 * i + 1]))); |
| } |
| std::vector<std::pair<uint32_t, uint32_t>> value; |
| EXPECT_TRUE(parser_->GetOption(kFakeUInt32PairListOption, |
| kFakeUInt32PairListOptionLength, |
| &value)); |
| EXPECT_EQ(target_value, value); |
| } |
| |
| TEST_F(ParserTest, ParseBoolEnable) { |
| parser_.reset(new BoolParser()); |
| bool value; |
| EXPECT_TRUE(parser_->GetOption(kFakeBoolOptionEnable, |
| kFakeBoolOptionLength, |
| &value)); |
| EXPECT_TRUE(value); |
| } |
| |
| TEST_F(ParserTest, ParseBoolDisable) { |
| parser_.reset(new BoolParser()); |
| bool value; |
| EXPECT_TRUE(parser_->GetOption(kFakeBoolOptionDisable, |
| kFakeBoolOptionLength, |
| &value)); |
| EXPECT_FALSE(value); |
| } |
| |
| TEST_F(ParserTest, ParseString) { |
| parser_.reset(new StringParser()); |
| std::string value; |
| std::string target_value; |
| target_value.assign(reinterpret_cast<const char*>(kFakeStringOption), |
| kFakeStringOptionLength); |
| EXPECT_TRUE(parser_->GetOption(kFakeStringOption, |
| kFakeStringOptionLength, |
| &value)); |
| EXPECT_EQ(target_value, value); |
| } |
| |
| TEST_F(ParserTest, ParseByteArray) { |
| parser_.reset(new ByteArrayParser()); |
| ByteString value; |
| ByteString target_value(reinterpret_cast<const char*>(kFakeByteArrayOption), |
| sizeof(kFakeByteArrayOption)); |
| EXPECT_TRUE(parser_->GetOption(kFakeByteArrayOption, |
| sizeof(kFakeByteArrayOption), |
| &value)); |
| EXPECT_TRUE(target_value.Equals(value)); |
| } |
| |
| } // namespace dhcp_client |