1//
2// Copyright (C) 2015 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include <dhcp_client/dhcp_options_parser.h>
18
19#include <netinet/in.h>
20
21#include <memory>
22#include <string>
23#include <utility>
24#include <vector>
25
26#include <gtest/gtest.h>
27#include <shill/net/byte_string.h>
28
29using shill::ByteString;
30
31namespace {
32const uint8_t kFakeUInt8Option[] = {0x02};
33const uint8_t kFakeUInt8OptionLength = 1;
34const uint8_t kFakeUInt16Option[] = {0x2a, 0x01};
35const uint8_t kFakeUInt16OptionLength = 2;
36const uint8_t kFakeUInt32Option[] = {0x01, 0x02, 0x00, 0xfa};
37const uint8_t kFakeUInt32OptionLength = 4;
38const uint8_t kFakeUInt8ListOption[] =
39    {0x01, 0x02, 0x00, 0xfa, 0x23, 0xae, 0x1f, 0x00};
40const uint8_t kFakeUInt8ListOptionLength = 8;
41
42const uint8_t kFakeUInt16ListOption[] =
43    {0xaa, 0x26, 0x4b, 0x00, 0xff, 0xc2, 0xcf, 0x0d, 0xe0, 0x01};
44const uint8_t kFakeUInt16ListOptionLength = 10;
45
46const uint8_t kFakeUInt32ListOption[] = {0x01, 0x02, 0x00, 0xfa,
47                                         0x23, 0xae, 0x1f, 0x00,
48                                         0x0c, 0x53, 0x33, 0x10,
49                                         0x47, 0x80, 0xb3, 0xff};
50const uint8_t kFakeUInt32ListOptionLength = 16;
51
52const uint8_t kFakeUInt32PairListOption[] = {0x21, 0xa0, 0xeb, 0x73,
53                                             0x01, 0x00, 0x1f, 0x10,
54                                             0xc9, 0x22, 0x3a, 0x37,
55                                             0xff, 0x00, 0xbe, 0xd0};
56const uint8_t kFakeUInt32PairListOptionLength = 16;
57
58const unsigned char kFakeStringOption[] =
59    {'f', 'a', 'k', 'e', 's', 't', 'r', 'i', 'n', 'g'};
60const uint8_t kFakeStringOptionLength = 10;
61
62const unsigned char kFakeByteArrayOption[] =
63    {'f', 'a', 'k', 'e', 'b', 'y', 't', 'e', 'a', 'r', 'r', 'a', 'y'};
64
65const uint8_t kFakeBoolOptionEnable[] = {0x01};
66const uint8_t kFakeBoolOptionDisable[] = {0x00};
67const uint8_t kFakeBoolOptionLength = 1;
68}  // namespace
69
70namespace dhcp_client {
71
72class ParserTest : public testing::Test {
73 protected:
74  std::unique_ptr<DHCPOptionsParser> parser_;
75};
76
77TEST_F(ParserTest, ParseUInt8) {
78  parser_.reset(new UInt8Parser());
79  uint8_t value;
80  EXPECT_TRUE(parser_->GetOption(kFakeUInt8Option,
81                                 kFakeUInt8OptionLength,
82                                 &value));
83  EXPECT_EQ(*kFakeUInt8Option, value);
84}
85
86TEST_F(ParserTest, ParseUInt16) {
87  parser_.reset(new UInt16Parser());
88  uint16_t value;
89  uint16_t target_value =
90      *reinterpret_cast<const uint16_t*>(kFakeUInt16Option);
91  target_value = ntohs(target_value);
92  EXPECT_TRUE(parser_->GetOption(kFakeUInt16Option,
93                                 kFakeUInt16OptionLength,
94                                 &value));
95  EXPECT_EQ(target_value, value);
96}
97
98TEST_F(ParserTest, ParseUInt32) {
99  parser_.reset(new UInt32Parser());
100  uint32_t value;
101  uint32_t target_value =
102      *reinterpret_cast<const uint32_t*>(kFakeUInt32Option);
103  target_value = ntohl(target_value);
104  EXPECT_TRUE(parser_->GetOption(kFakeUInt32Option,
105                                 kFakeUInt32OptionLength,
106                                 &value));
107  EXPECT_EQ(target_value, value);
108}
109
110TEST_F(ParserTest, ParseUInt8List) {
111  parser_.reset(new UInt8ListParser());
112  std::vector<uint8_t> value;
113  std::vector<uint8_t> target_value;
114  uint8_t length = kFakeUInt8ListOptionLength;
115  const uint8_t* uint8_list =
116      reinterpret_cast<const uint8_t*>(kFakeUInt8ListOption);
117  target_value = std::vector<uint8_t>(uint8_list, uint8_list + length);
118  EXPECT_TRUE(parser_->GetOption(kFakeUInt8ListOption,
119                                 kFakeUInt8ListOptionLength,
120                                 &value));
121  EXPECT_EQ(target_value, value);
122}
123
124TEST_F(ParserTest, ParseUInt16List) {
125  parser_.reset(new UInt16ListParser());
126  std::vector<uint16_t> value;
127  std::vector<uint16_t> target_value;
128  std::vector<uint16_t> target_value_net_order;
129  int length = kFakeUInt16ListOptionLength / sizeof(uint16_t);
130  const uint16_t* uint16_list =
131      reinterpret_cast<const uint16_t*>(kFakeUInt16ListOption);
132  target_value_net_order =
133      std::vector<uint16_t>(uint16_list, uint16_list + length);
134  for (uint16_t element : target_value_net_order) {
135    target_value.push_back(ntohs(element));
136  }
137  EXPECT_TRUE(parser_->GetOption(kFakeUInt16ListOption,
138                                 kFakeUInt16ListOptionLength,
139                                 &value));
140  EXPECT_EQ(target_value, value);
141}
142
143TEST_F(ParserTest, ParseUInt32List) {
144  parser_.reset(new UInt32ListParser());
145  std::vector<uint32_t> value;
146  std::vector<uint32_t> target_value;
147  std::vector<uint32_t> target_value_net_order;
148  int length = kFakeUInt32ListOptionLength / sizeof(uint32_t);
149  const uint32_t* uint32_list =
150      reinterpret_cast<const uint32_t*>(kFakeUInt32ListOption);
151  target_value_net_order =
152      std::vector<uint32_t>(uint32_list, uint32_list + length);
153  for (uint32_t element : target_value_net_order) {
154    target_value.push_back(ntohl(element));
155  }
156  EXPECT_TRUE(parser_->GetOption(kFakeUInt32ListOption,
157                                 kFakeUInt32ListOptionLength,
158                                 &value));
159  EXPECT_EQ(target_value, value);
160}
161
162TEST_F(ParserTest, ParseUInt32PairList) {
163  parser_.reset(new UInt32PairListParser());
164  int length = kFakeUInt32PairListOptionLength / (2 * sizeof(uint32_t));
165  const uint32_t* uint32_array =
166      reinterpret_cast<const uint32_t*>(kFakeUInt32PairListOption);
167  std::vector<uint32_t> uint32_vector =
168      std::vector<uint32_t>(uint32_array, uint32_array + length * 2);
169  std::vector<std::pair<uint32_t, uint32_t>> target_value;
170  for (int i = 0; i < length; i++) {
171    target_value.push_back(
172        std::pair<uint32_t, uint32_t>(ntohl(uint32_vector[2 * i]),
173                                      ntohl(uint32_vector[2 * i + 1])));
174  }
175  std::vector<std::pair<uint32_t, uint32_t>> value;
176  EXPECT_TRUE(parser_->GetOption(kFakeUInt32PairListOption,
177                                 kFakeUInt32PairListOptionLength,
178                                 &value));
179  EXPECT_EQ(target_value, value);
180}
181
182TEST_F(ParserTest, ParseBoolEnable) {
183  parser_.reset(new BoolParser());
184  bool value;
185  EXPECT_TRUE(parser_->GetOption(kFakeBoolOptionEnable,
186                                 kFakeBoolOptionLength,
187                                 &value));
188  EXPECT_TRUE(value);
189}
190
191TEST_F(ParserTest, ParseBoolDisable) {
192  parser_.reset(new BoolParser());
193  bool value;
194  EXPECT_TRUE(parser_->GetOption(kFakeBoolOptionDisable,
195                                 kFakeBoolOptionLength,
196                                 &value));
197  EXPECT_FALSE(value);
198}
199
200TEST_F(ParserTest, ParseString) {
201  parser_.reset(new StringParser());
202  std::string value;
203  std::string target_value;
204  target_value.assign(reinterpret_cast<const char*>(kFakeStringOption),
205                      kFakeStringOptionLength);
206  EXPECT_TRUE(parser_->GetOption(kFakeStringOption,
207                                 kFakeStringOptionLength,
208                                 &value));
209  EXPECT_EQ(target_value, value);
210}
211
212TEST_F(ParserTest, ParseByteArray) {
213  parser_.reset(new ByteArrayParser());
214  ByteString value;
215  ByteString target_value(reinterpret_cast<const char*>(kFakeByteArrayOption),
216                          sizeof(kFakeByteArrayOption));
217  EXPECT_TRUE(parser_->GetOption(kFakeByteArrayOption,
218                                 sizeof(kFakeByteArrayOption),
219                                 &value));
220  EXPECT_TRUE(target_value.Equals(value));
221}
222
223}  // namespace dhcp_client
224