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_writer.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 
29 #include "dhcp_client/dhcp_options.h"
30 
31 using shill::ByteString;
32 namespace dhcp_client {
33 
34 namespace {
35 const uint8_t kFakeOptionCode1 = 3;
36 const uint8_t kFakeOptionCode2 = 45;
37 const uint8_t kFakeOptionCode3 = 251;
38 }  // namespace
39 
40 
41 class DHCPOptionsWriterTest : public testing::Test {
42  protected:
43   DHCPOptionsWriter* options_writer_;
44 };
45 
TEST_F(DHCPOptionsWriterTest,WriteUInt8)46 TEST_F(DHCPOptionsWriterTest, WriteUInt8) {
47   const uint8_t kFakeUInt8Option = 0x22;
48   const uint8_t kFakeUInt8OptionResult[] = {
49       kFakeOptionCode1,
50       sizeof(uint8_t),
51       0x22};
52 
53   ByteString option;
54   options_writer_ = DHCPOptionsWriter::GetInstance();
55   int length = options_writer_->WriteUInt8Option(&option,
56                                                  kFakeOptionCode1,
57                                                  kFakeUInt8Option);
58   EXPECT_NE(-1, length);
59   EXPECT_EQ(0, std::memcmp(option.GetConstData(),
60                            kFakeUInt8OptionResult,
61                            length));
62 }
63 
TEST_F(DHCPOptionsWriterTest,WriteUInt16)64 TEST_F(DHCPOptionsWriterTest, WriteUInt16) {
65   const uint16_t kFakeUInt16Option = 0x1516;
66   const uint8_t kFakeUInt16OptionResult[] = {
67       kFakeOptionCode2,
68       sizeof(uint16_t),
69       // Use the network byte order.
70       0x15, 0x16};
71 
72   ByteString option;
73   options_writer_ = DHCPOptionsWriter::GetInstance();
74   int length = options_writer_->WriteUInt16Option(&option,
75                                                   kFakeOptionCode2,
76                                                   kFakeUInt16Option);
77   EXPECT_NE(-1, length);
78   EXPECT_EQ(0, std::memcmp(option.GetConstData(),
79                            kFakeUInt16OptionResult,
80                            length));
81 }
82 
TEST_F(DHCPOptionsWriterTest,WriteUInt32)83 TEST_F(DHCPOptionsWriterTest, WriteUInt32) {
84   const uint32_t kFakeUInt32Option = 0x32a0bf01;
85   const uint8_t kFakeUInt32OptionResult[] = {
86       kFakeOptionCode3,
87       sizeof(uint32_t),
88       // Use the network byte order.
89       0x32, 0xa0, 0xbf, 0x01};
90 
91   ByteString option;
92   options_writer_ = DHCPOptionsWriter::GetInstance();
93   int length = options_writer_->WriteUInt32Option(&option,
94                                                   kFakeOptionCode3,
95                                                   kFakeUInt32Option);
96   EXPECT_NE(-1, length);
97   EXPECT_EQ(0, std::memcmp(option.GetConstData(),
98                            kFakeUInt32OptionResult,
99                            length));
100 }
101 
TEST_F(DHCPOptionsWriterTest,WriteUInt8List)102 TEST_F(DHCPOptionsWriterTest, WriteUInt8List) {
103   const std::vector<uint8_t> kFakeUInt8ListOption =
104       {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
105   const uint8_t kFakeUInt8ListOptionResult[] = {
106       kFakeOptionCode1,
107       static_cast<uint8_t>(kFakeUInt8ListOption.size()),
108       0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
109 
110   ByteString option;
111   options_writer_ = DHCPOptionsWriter::GetInstance();
112   int length = options_writer_->WriteUInt8ListOption(&option,
113                                                      kFakeOptionCode1,
114                                                      kFakeUInt8ListOption);
115   EXPECT_NE(-1, length);
116   EXPECT_EQ(0, std::memcmp(option.GetConstData(),
117                            kFakeUInt8ListOptionResult,
118                            length));
119 }
120 
TEST_F(DHCPOptionsWriterTest,WriteUInt16List)121 TEST_F(DHCPOptionsWriterTest, WriteUInt16List) {
122   const std::vector<uint16_t> kFakeUInt16ListOption =
123       {0xb1a2, 0x0264, 0xdc03, 0x92c4, 0xa500, 0x0010};
124   const uint8_t kFakeUInt16ListOptionResult[] = {
125       kFakeOptionCode2,
126       static_cast<uint8_t>(sizeof(uint16_t) * kFakeUInt16ListOption.size()),
127       // Use the network byte order.
128       0xb1, 0xa2, 0x02, 0x64, 0xdc, 0x03, 0x92, 0xc4, 0xa5, 0x00, 0x00, 0x10};
129 
130   ByteString option;
131   options_writer_ = DHCPOptionsWriter::GetInstance();
132   int length = options_writer_->WriteUInt16ListOption(&option,
133                                                       kFakeOptionCode2,
134                                                       kFakeUInt16ListOption);
135   EXPECT_NE(-1, length);
136   EXPECT_EQ(0, std::memcmp(option.GetConstData(),
137                            kFakeUInt16ListOptionResult,
138                            length));
139 }
140 
TEST_F(DHCPOptionsWriterTest,WriteUInt32List)141 TEST_F(DHCPOptionsWriterTest, WriteUInt32List) {
142   const std::vector<uint32_t> kFakeUInt32ListOption =
143       {0x03a64301, 0x03f52614, 0x7c5d9eff, 0x0138b26e};
144   const uint8_t kFakeUInt32ListOptionResult[] = {
145       kFakeOptionCode3,
146       static_cast<uint8_t>(sizeof(uint32_t) * kFakeUInt32ListOption.size()),
147       // Use the network byte order.
148       0x03, 0xa6, 0x43, 0x01, 0x03, 0xf5, 0x26, 0x14,
149       0x7c, 0x5d, 0x9e, 0xff, 0x01, 0x38, 0xb2, 0x6e};
150 
151   ByteString option;
152   options_writer_ = DHCPOptionsWriter::GetInstance();
153   int length = options_writer_->WriteUInt32ListOption(&option,
154                                                       kFakeOptionCode3,
155                                                       kFakeUInt32ListOption);
156   EXPECT_NE(-1, length);
157   EXPECT_EQ(0, std::memcmp(option.GetConstData(),
158                            kFakeUInt32ListOptionResult,
159                            length));
160 }
161 
TEST_F(DHCPOptionsWriterTest,WriteUInt32PairList)162 TEST_F(DHCPOptionsWriterTest, WriteUInt32PairList) {
163   const std::vector<std::pair<uint32_t, uint32_t>> kFakeUInt32PairListOption =
164       {{0x03b576a1, 0xfa070054}, {0x650c3d22, 0x1397e5bb}};
165   const uint8_t kFakeUInt32PairListOptionResult[] = {
166       kFakeOptionCode1,
167       static_cast<uint8_t>
168           (sizeof(uint32_t) * 2 * kFakeUInt32PairListOption.size()),
169       // Use the network byte order.
170       0x03, 0xb5, 0x76, 0xa1, 0xfa, 0x07, 0x00, 0x54,
171       0x65, 0x0c, 0x3d, 0x22, 0x13, 0x97, 0xe5, 0xbb};
172 
173   ByteString option;
174   options_writer_ = DHCPOptionsWriter::GetInstance();
175   int length =
176       options_writer_->WriteUInt32PairListOption(&option,
177                                                  kFakeOptionCode1,
178                                                  kFakeUInt32PairListOption);
179   EXPECT_NE(-1, length);
180   EXPECT_EQ(0, std::memcmp(option.GetConstData(),
181                            kFakeUInt32PairListOptionResult,
182                            length));
183 }
184 
TEST_F(DHCPOptionsWriterTest,WriteString)185 TEST_F(DHCPOptionsWriterTest, WriteString) {
186   const std::string kFakeStringOption = "fakestring";
187   const uint8_t kFakeStringOptionResult[] = {
188       kFakeOptionCode1,
189       static_cast<uint8_t>(kFakeStringOption.size()),
190       'f', 'a', 'k', 'e', 's', 't', 'r', 'i', 'n', 'g'};
191 
192   ByteString option;
193   options_writer_ = DHCPOptionsWriter::GetInstance();
194   int length = options_writer_->WriteStringOption(&option,
195                                                   kFakeOptionCode1,
196                                                   kFakeStringOption);
197   EXPECT_NE(-1, length);
198   EXPECT_EQ(0, std::memcmp(option.GetConstData(),
199                            kFakeStringOptionResult,
200                            length));
201 }
202 
203 
TEST_F(DHCPOptionsWriterTest,WriteBoolTrue)204 TEST_F(DHCPOptionsWriterTest, WriteBoolTrue) {
205   const uint8_t kFakeBoolOptionTrue = true;
206   const uint8_t kFakeBoolOptionResultTrue[] = {
207     kFakeOptionCode1,
208     sizeof(uint8_t),
209     0x01};
210 
211   ByteString option;
212   options_writer_ = DHCPOptionsWriter::GetInstance();
213   int length = options_writer_->WriteBoolOption(&option,
214                                                 kFakeOptionCode1,
215                                                 kFakeBoolOptionTrue);
216   EXPECT_NE(-1, length);
217   EXPECT_EQ(0, std::memcmp(option.GetConstData(),
218                            kFakeBoolOptionResultTrue,
219                            length));
220 }
221 
TEST_F(DHCPOptionsWriterTest,WriteBoolFalse)222 TEST_F(DHCPOptionsWriterTest, WriteBoolFalse) {
223   const uint8_t kFakeBoolOptionFalse = false;
224   const uint8_t kFakeBoolOptionResultFalse[] = {
225       kFakeOptionCode2,
226       sizeof(uint8_t),
227       0x00};
228 
229   ByteString option;
230   options_writer_ = DHCPOptionsWriter::GetInstance();
231   int length = options_writer_->WriteBoolOption(&option,
232                                                 kFakeOptionCode2,
233                                                 kFakeBoolOptionFalse);
234   EXPECT_NE(-1, length);
235   EXPECT_EQ(0, std::memcmp(option.GetConstData(),
236                            kFakeBoolOptionResultFalse,
237                            length));
238 }
239 
TEST_F(DHCPOptionsWriterTest,WriteByteArray)240 TEST_F(DHCPOptionsWriterTest, WriteByteArray) {
241   const ByteString kFakeByteArrayOption =
242       ByteString({0x06, 0x05, 0x04, 0x03, 0x02, 0x01});
243   const uint8_t kFakeByteArrayOptionResult[] = {
244       kFakeOptionCode1,
245       static_cast<uint8_t>(kFakeByteArrayOption.GetLength()),
246       0x06, 0x05, 0x04, 0x03, 0x02, 0x01};
247 
248   ByteString option;
249   options_writer_ = DHCPOptionsWriter::GetInstance();
250   int length = options_writer_->WriteByteArrayOption(&option,
251                                                      kFakeOptionCode1,
252                                                      kFakeByteArrayOption);
253   EXPECT_NE(-1, length);
254   EXPECT_EQ(0, std::memcmp(option.GetConstData(),
255                            kFakeByteArrayOptionResult,
256                            length));
257 }
258 
TEST_F(DHCPOptionsWriterTest,WriteEndTag)259 TEST_F(DHCPOptionsWriterTest, WriteEndTag) {
260   const std::string kFakeStringOption = "fakestring1";
261   const uint8_t kFakeStringOptionResult[] = {
262       kFakeOptionCode1,
263       static_cast<uint8_t>(kFakeStringOption.size()),
264       'f', 'a', 'k', 'e', 's', 't', 'r', 'i', 'n', 'g', '1'};
265 
266   ByteString option;
267   options_writer_ = DHCPOptionsWriter::GetInstance();
268   int length = options_writer_->WriteStringOption(&option,
269                                                   kFakeOptionCode1,
270                                                   kFakeStringOption);
271   EXPECT_NE(-1, length);
272   EXPECT_NE(-1, options_writer_->WriteEndTag(&option));
273   EXPECT_EQ(0, std::memcmp(option.GetConstData(),
274                            kFakeStringOptionResult,
275                            length));
276   EXPECT_EQ(kDHCPOptionEnd, *(option.GetConstData() + length));
277 }
278 
279 }  // namespace dhcp_client
280