1//
2// Copyright (C) 2012 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 "shill/static_ip_parameters.h"
18
19#include <base/strings/string_number_conversions.h>
20#if defined(__ANDROID__)
21#include <dbus/service_constants.h>
22#else
23#include <chromeos/dbus/service_constants.h>
24#endif  // __ANDROID__
25#include <gtest/gtest.h>
26
27#include "shill/ipconfig.h"
28#include "shill/mock_store.h"
29#include "shill/property_store.h"
30
31using base::IntToString;
32using std::string;
33using std::vector;
34using testing::_;
35using testing::DoAll;
36using testing::Return;
37using testing::SetArgumentPointee;
38using testing::StrictMock;
39using testing::Test;
40
41namespace shill {
42
43namespace {
44
45const char kAddress[] = "10.0.0.1";
46const char kGateway[] = "10.0.0.254";
47const int32_t kMtu = 512;
48const char kNameServer0[] = "10.0.1.253";
49const char kNameServer1[] = "10.0.1.252";
50const char kNameServers[] = "10.0.1.253,10.0.1.252";
51const char kPeerAddress[] = "10.0.0.2";
52const int32_t kPrefixLen = 24;
53
54}  // namespace
55
56class StaticIpParametersTest : public Test {
57 public:
58  StaticIpParametersTest() {}
59
60  void ExpectEmptyIPConfig() {
61    EXPECT_TRUE(ipconfig_props_.address.empty());
62    EXPECT_TRUE(ipconfig_props_.gateway.empty());
63    EXPECT_EQ(IPConfig::kUndefinedMTU, ipconfig_props_.mtu);
64    EXPECT_TRUE(ipconfig_props_.dns_servers.empty());
65    EXPECT_TRUE(ipconfig_props_.peer_address.empty());
66    EXPECT_FALSE(ipconfig_props_.subnet_prefix);
67  }
68  // Modify an IP address string in some predictable way.  There's no need
69  // for the output string to be valid from a networking perspective.
70  string VersionedAddress(const string& address, int version) {
71    string returned_address = address;
72    CHECK(returned_address.length());
73    returned_address[returned_address.length() - 1] += version;
74    return returned_address;
75  }
76  void ExpectPopulatedIPConfigWithVersion(int version) {
77    EXPECT_EQ(VersionedAddress(kAddress, version), ipconfig_props_.address);
78    EXPECT_EQ(VersionedAddress(kGateway, version), ipconfig_props_.gateway);
79    EXPECT_EQ(kMtu + version, ipconfig_props_.mtu);
80    EXPECT_EQ(2, ipconfig_props_.dns_servers.size());
81    EXPECT_EQ(VersionedAddress(kNameServer0, version),
82              ipconfig_props_.dns_servers[0]);
83    EXPECT_EQ(VersionedAddress(kNameServer1, version),
84              ipconfig_props_.dns_servers[1]);
85    EXPECT_EQ(VersionedAddress(kPeerAddress, version),
86              ipconfig_props_.peer_address);
87    EXPECT_EQ(kPrefixLen + version, ipconfig_props_.subnet_prefix);
88  }
89  void ExpectPopulatedIPConfig() { ExpectPopulatedIPConfigWithVersion(0); }
90  void ExpectPropertiesWithVersion(PropertyStore* store,
91                                        const string& property_prefix,
92                                        int version) {
93    string string_value;
94    Error unused_error;
95    EXPECT_TRUE(store->GetStringProperty(property_prefix + ".Address",
96                                         &string_value,
97                                         &unused_error));
98    EXPECT_EQ(VersionedAddress(kAddress, version), string_value);
99    EXPECT_TRUE(store->GetStringProperty(property_prefix + ".Gateway",
100                                         &string_value,
101                                         &unused_error));
102    EXPECT_EQ(VersionedAddress(kGateway, version), string_value);
103    int32_t int_value;
104    EXPECT_TRUE(store->GetInt32Property(property_prefix + ".Mtu", &int_value,
105                                        &unused_error));
106    EXPECT_EQ(kMtu + version, int_value);
107    EXPECT_TRUE(store->GetStringProperty(property_prefix + ".NameServers",
108                                         &string_value,
109                                         &unused_error));
110    EXPECT_EQ(VersionedAddress(kNameServer0, version) + "," +
111              VersionedAddress(kNameServer1, version),
112              string_value);
113    EXPECT_TRUE(store->GetStringProperty(property_prefix + ".PeerAddress",
114                                         &string_value,
115                                         &unused_error));
116    EXPECT_EQ(VersionedAddress(kPeerAddress, version), string_value);
117    EXPECT_TRUE(store->GetInt32Property(property_prefix + ".Prefixlen",
118                                        &int_value,
119                                        &unused_error));
120    EXPECT_EQ(kPrefixLen + version, int_value);
121  }
122  void ExpectProperties(PropertyStore* store, const string& property_prefix) {
123    ExpectPropertiesWithVersion(store, property_prefix, 0);
124  }
125  void PopulateIPConfig() {
126    ipconfig_props_.address = kAddress;
127    ipconfig_props_.gateway = kGateway;
128    ipconfig_props_.mtu = kMtu;
129    ipconfig_props_.dns_servers.push_back(kNameServer0);
130    ipconfig_props_.dns_servers.push_back(kNameServer1);
131    ipconfig_props_.peer_address = kPeerAddress;
132    ipconfig_props_.subnet_prefix = kPrefixLen;
133  }
134  void SetStaticPropertiesWithVersion(PropertyStore* store, int version) {
135    Error error;
136    store->SetStringProperty(
137        "StaticIP.Address", VersionedAddress(kAddress, version), &error);
138    store->SetStringProperty(
139        "StaticIP.Gateway", VersionedAddress(kGateway, version), &error);
140    store->SetInt32Property(
141        "StaticIP.Mtu", kMtu + version, &error);
142    store->SetStringProperty(
143        "StaticIP.NameServers",
144        VersionedAddress(kNameServer0, version) + "," +
145        VersionedAddress(kNameServer1, version),
146        &error);
147    store->SetStringProperty(
148        "StaticIP.PeerAddress",
149        VersionedAddress(kPeerAddress, version),
150        &error);
151    store->SetInt32Property("StaticIP.Prefixlen", kPrefixLen + version, &error);
152  }
153  void SetStaticProperties(PropertyStore* store) {
154    SetStaticPropertiesWithVersion(store, 0);
155  }
156  void SetStaticDictPropertiesWithVersion(PropertyStore* store, int version) {
157    KeyValueStore args;
158    args.SetString(kAddressProperty, VersionedAddress(kAddress, version));
159    args.SetString(kGatewayProperty, VersionedAddress(kGateway, version));
160    args.SetInt(kMtuProperty, kMtu + version);
161    vector<string> name_servers;
162    name_servers.push_back(VersionedAddress(kNameServer0, version));
163    name_servers.push_back(VersionedAddress(kNameServer1, version));
164    args.SetStrings(kNameServersProperty, name_servers);
165    args.SetString(kPeerAddressProperty,
166                   VersionedAddress(kPeerAddress, version));
167    args.SetInt(kPrefixlenProperty, kPrefixLen + version);
168    Error error;
169    store->SetKeyValueStoreProperty(kStaticIPConfigProperty, args, &error);
170  }
171
172 protected:
173  StaticIPParameters static_params_;
174  IPConfig::Properties ipconfig_props_;
175};
176
177TEST_F(StaticIpParametersTest, InitState) {
178  ExpectEmptyIPConfig();
179
180  // Applying an empty set of parameters on an empty set of properties should
181  // be a no-op.
182  static_params_.ApplyTo(&ipconfig_props_);
183  ExpectEmptyIPConfig();
184}
185
186TEST_F(StaticIpParametersTest, ApplyEmptyParameters) {
187  PopulateIPConfig();
188  static_params_.ApplyTo(&ipconfig_props_);
189  ExpectPopulatedIPConfig();
190}
191
192TEST_F(StaticIpParametersTest, ControlInterface) {
193  PropertyStore store;
194  static_params_.PlumbPropertyStore(&store);
195  SetStaticProperties(&store);
196  static_params_.ApplyTo(&ipconfig_props_);
197  ExpectPopulatedIPConfig();
198
199  EXPECT_TRUE(static_params_.ContainsAddress());
200  Error unused_error;
201  store.ClearProperty("StaticIP.Address", &unused_error);
202  EXPECT_FALSE(static_params_.ContainsAddress());
203  store.ClearProperty("StaticIP.Mtu", &unused_error);
204  IPConfig::Properties props;
205  const string kTestAddress("test_address");
206  props.address = kTestAddress;
207  const int32_t kTestMtu = 256;
208  props.mtu = kTestMtu;
209  static_params_.ApplyTo(&props);
210  EXPECT_EQ(kTestAddress, props.address);
211  EXPECT_EQ(kTestMtu, props.mtu);
212
213  {
214    Error error;
215    EXPECT_FALSE(store.GetStringProperty("StaticIP.Address", nullptr, &error));
216    EXPECT_EQ(Error::kNotFound, error.type());
217  }
218  string string_value;
219  EXPECT_TRUE(store.GetStringProperty("StaticIP.Gateway", &string_value,
220                                      &unused_error));
221  EXPECT_EQ(kGateway, string_value);
222  {
223    Error error;
224    EXPECT_FALSE(store.GetInt32Property("StaticIP.Mtu", nullptr, &error));
225    EXPECT_EQ(Error::kNotFound, error.type());
226  }
227  EXPECT_TRUE(store.GetStringProperty("StaticIP.NameServers", &string_value,
228                                      &unused_error));
229  EXPECT_EQ(kNameServers, string_value);
230  EXPECT_TRUE(store.GetStringProperty("StaticIP.PeerAddress", &string_value,
231                                      &unused_error));
232  EXPECT_EQ(kPeerAddress, string_value);
233  int32_t int_value;
234  EXPECT_TRUE(store.GetInt32Property("StaticIP.Prefixlen", &int_value,
235                                     &unused_error));
236  EXPECT_EQ(kPrefixLen, int_value);
237}
238
239TEST_F(StaticIpParametersTest, Profile) {
240  StrictMock<MockStore> store;
241  const string kID = "storage_id";
242  EXPECT_CALL(store, GetString(kID, "StaticIP.Address", _))
243      .WillOnce(DoAll(SetArgumentPointee<2>(string(kAddress)), Return(true)));
244  EXPECT_CALL(store, GetString(kID, "StaticIP.Gateway", _))
245      .WillOnce(DoAll(SetArgumentPointee<2>(string(kGateway)), Return(true)));
246  EXPECT_CALL(store, GetInt(kID, "StaticIP.Mtu", _))
247      .WillOnce(DoAll(SetArgumentPointee<2>(kMtu), Return(true)));
248  EXPECT_CALL(store, GetString(kID, "StaticIP.NameServers", _))
249      .WillOnce(DoAll(SetArgumentPointee<2>(string(kNameServers)),
250                      Return(true)));
251  EXPECT_CALL(store, GetString(kID, "StaticIP.PeerAddress", _))
252      .WillOnce(DoAll(SetArgumentPointee<2>(string(kPeerAddress)),
253                      Return(true)));
254  EXPECT_CALL(store, GetInt(kID, "StaticIP.Prefixlen", _))
255      .WillOnce(DoAll(SetArgumentPointee<2>(kPrefixLen), Return(true)));
256  static_params_.Load(&store, kID);
257  static_params_.ApplyTo(&ipconfig_props_);
258  ExpectPopulatedIPConfig();
259
260  EXPECT_CALL(store, SetString(kID, "StaticIP.Address", kAddress))
261      .WillOnce(Return(true));
262  EXPECT_CALL(store, SetString(kID, "StaticIP.Gateway", kGateway))
263      .WillOnce(Return(true));
264  EXPECT_CALL(store, SetInt(kID, "StaticIP.Mtu", kMtu))
265      .WillOnce(Return(true));
266  EXPECT_CALL(store, SetString(kID, "StaticIP.NameServers", kNameServers))
267      .WillOnce(Return(true));
268  EXPECT_CALL(store, SetString(kID, "StaticIP.PeerAddress", kPeerAddress))
269      .WillOnce(Return(true));
270  EXPECT_CALL(store, SetInt(kID, "StaticIP.Prefixlen", kPrefixLen))
271      .WillOnce(Return(true));
272  static_params_.Save(&store, kID);
273}
274
275TEST_F(StaticIpParametersTest, SavedParameters) {
276  // Calling RestoreTo() when no parameters are set should not crash or
277  // add any entries.
278  static_params_.RestoreTo(&ipconfig_props_);
279  ExpectEmptyIPConfig();
280
281  PopulateIPConfig();
282  PropertyStore static_params_props;
283  static_params_.PlumbPropertyStore(&static_params_props);
284  SetStaticPropertiesWithVersion(&static_params_props, 1);
285  static_params_.ApplyTo(&ipconfig_props_);
286
287  // The version 0 properties in |ipconfig_props_| are now in SavedIP.*
288  // properties, while the version 1 StaticIP parameters are now in
289  // |ipconfig_props_|.
290  ExpectPropertiesWithVersion(&static_params_props, "SavedIP", 0);
291  ExpectPopulatedIPConfigWithVersion(1);
292
293  // Clear all "StaticIP" parameters.
294  static_params_.args_.Clear();
295
296  // Another ApplyTo() call rotates the version 1 properties in
297  // |ipconfig_props_| over to SavedIP.*.  Since there are no StaticIP
298  // parameters, |ipconfig_props_| should remain populated with version 1
299  // parameters.
300  static_params_.ApplyTo(&ipconfig_props_);
301  ExpectPropertiesWithVersion(&static_params_props, "SavedIP", 1);
302  ExpectPopulatedIPConfigWithVersion(1);
303
304  // Reset |ipconfig_props_| to version 0.
305  PopulateIPConfig();
306
307  // A RestoreTo() call moves the version 1 "SavedIP" parameters into
308  // |ipconfig_props_|.
309  SetStaticPropertiesWithVersion(&static_params_props, 2);
310  static_params_.RestoreTo(&ipconfig_props_);
311  ExpectPopulatedIPConfigWithVersion(1);
312
313  // All "SavedIP" parameters should be cleared.
314  EXPECT_TRUE(static_params_.saved_args_.IsEmpty());
315
316  // Static IP parameters should be unchanged.
317  ExpectPropertiesWithVersion(&static_params_props, "StaticIP", 2);
318}
319
320TEST_F(StaticIpParametersTest, SavedParametersDict) {
321  // Calling RestoreTo() when no parameters are set should not crash or
322  // add any entries.
323  static_params_.RestoreTo(&ipconfig_props_);
324  ExpectEmptyIPConfig();
325
326  PopulateIPConfig();
327  PropertyStore static_params_props;
328  static_params_.PlumbPropertyStore(&static_params_props);
329  SetStaticDictPropertiesWithVersion(&static_params_props, 1);
330  static_params_.ApplyTo(&ipconfig_props_);
331
332  // The version 0 properties in |ipconfig_props_| are now in SavedIP.*
333  // properties, while the version 1 StaticIP parameters are now in
334  // |ipconfig_props_|.
335  ExpectPropertiesWithVersion(&static_params_props, "SavedIP", 0);
336  ExpectPopulatedIPConfigWithVersion(1);
337
338  // Clear all "StaticIP" parameters.
339  static_params_.args_.Clear();
340
341  // Another ApplyTo() call rotates the version 1 properties in
342  // |ipconfig_props_| over to SavedIP.*.  Since there are no StaticIP
343  // parameters, |ipconfig_props_| should remain populated with version 1
344  // parameters.
345  static_params_.ApplyTo(&ipconfig_props_);
346  ExpectPropertiesWithVersion(&static_params_props, "SavedIP", 1);
347  ExpectPopulatedIPConfigWithVersion(1);
348
349  // Reset |ipconfig_props_| to version 0.
350  PopulateIPConfig();
351
352  // A RestoreTo() call moves the version 1 "SavedIP" parameters into
353  // |ipconfig_props_|.
354  SetStaticDictPropertiesWithVersion(&static_params_props, 2);
355  static_params_.RestoreTo(&ipconfig_props_);
356  ExpectPopulatedIPConfigWithVersion(1);
357
358  // All "SavedIP" parameters should be cleared.
359  EXPECT_TRUE(static_params_.saved_args_.IsEmpty());
360
361  // Static IP parameters should be unchanged.
362  ExpectPropertiesWithVersion(&static_params_props, "StaticIP", 2);
363}
364
365}  // namespace shill
366