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 
31 using base::IntToString;
32 using std::string;
33 using std::vector;
34 using testing::_;
35 using testing::DoAll;
36 using testing::Return;
37 using testing::SetArgumentPointee;
38 using testing::StrictMock;
39 using testing::Test;
40 
41 namespace shill {
42 
43 namespace {
44 
45 const char kAddress[] = "10.0.0.1";
46 const char kGateway[] = "10.0.0.254";
47 const int32_t kMtu = 512;
48 const char kNameServer0[] = "10.0.1.253";
49 const char kNameServer1[] = "10.0.1.252";
50 const char kNameServers[] = "10.0.1.253,10.0.1.252";
51 const char kPeerAddress[] = "10.0.0.2";
52 const int32_t kPrefixLen = 24;
53 
54 }  // namespace
55 
56 class StaticIpParametersTest : public Test {
57  public:
StaticIpParametersTest()58   StaticIpParametersTest() {}
59 
ExpectEmptyIPConfig()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.
VersionedAddress(const string & address,int version)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   }
ExpectPopulatedIPConfigWithVersion(int version)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   }
ExpectPopulatedIPConfig()89   void ExpectPopulatedIPConfig() { ExpectPopulatedIPConfigWithVersion(0); }
ExpectPropertiesWithVersion(PropertyStore * store,const string & property_prefix,int version)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   }
ExpectProperties(PropertyStore * store,const string & property_prefix)122   void ExpectProperties(PropertyStore* store, const string& property_prefix) {
123     ExpectPropertiesWithVersion(store, property_prefix, 0);
124   }
PopulateIPConfig()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   }
SetStaticPropertiesWithVersion(PropertyStore * store,int version)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   }
SetStaticProperties(PropertyStore * store)153   void SetStaticProperties(PropertyStore* store) {
154     SetStaticPropertiesWithVersion(store, 0);
155   }
SetStaticDictPropertiesWithVersion(PropertyStore * store,int version)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 
TEST_F(StaticIpParametersTest,InitState)177 TEST_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 
TEST_F(StaticIpParametersTest,ApplyEmptyParameters)186 TEST_F(StaticIpParametersTest, ApplyEmptyParameters) {
187   PopulateIPConfig();
188   static_params_.ApplyTo(&ipconfig_props_);
189   ExpectPopulatedIPConfig();
190 }
191 
TEST_F(StaticIpParametersTest,ControlInterface)192 TEST_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 
TEST_F(StaticIpParametersTest,Profile)239 TEST_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 
TEST_F(StaticIpParametersTest,SavedParameters)275 TEST_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 
TEST_F(StaticIpParametersTest,SavedParametersDict)320 TEST_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