blob: e7ab6451b5b1ab49eec8c2f07d6f21537a4463f7 [file] [log] [blame]
Darin Petkova4766822011-07-07 10:42:22 -07001// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Chris Masone7aa5f902011-07-11 11:13:35 -07005#include "shill/profile.h"
6
Chris Masone6791a432011-07-12 13:23:19 -07007#include <string>
8#include <vector>
9
Chris Masone6515aab2011-10-12 16:19:09 -070010#include <base/file_path.h>
Chris Masoneb9c00592011-10-06 13:10:39 -070011#include <base/memory/scoped_ptr.h>
Darin Petkova4766822011-07-07 10:42:22 -070012#include <base/string_util.h>
13#include <gtest/gtest.h>
14
Chris Masone6515aab2011-10-12 16:19:09 -070015#include "shill/glib.h"
16#include "shill/key_file_store.h"
Chris Masone6791a432011-07-12 13:23:19 -070017#include "shill/mock_profile.h"
18#include "shill/mock_service.h"
Chris Masone9d779932011-08-25 16:33:41 -070019#include "shill/mock_store.h"
Chris Masone6791a432011-07-12 13:23:19 -070020#include "shill/property_store_unittest.h"
Chris Masone6515aab2011-10-12 16:19:09 -070021#include "shill/service_under_test.h"
Chris Masone6791a432011-07-12 13:23:19 -070022
23using std::set;
Darin Petkova4766822011-07-07 10:42:22 -070024using std::string;
Chris Masone6791a432011-07-12 13:23:19 -070025using std::vector;
Chris Masone9d779932011-08-25 16:33:41 -070026using testing::_;
Chris Masone6515aab2011-10-12 16:19:09 -070027using testing::Invoke;
Chris Masone6791a432011-07-12 13:23:19 -070028using testing::Return;
Chris Masone9d779932011-08-25 16:33:41 -070029using testing::SetArgumentPointee;
Chris Masone6791a432011-07-12 13:23:19 -070030using testing::StrictMock;
Darin Petkova4766822011-07-07 10:42:22 -070031
32namespace shill {
33
Chris Masone6791a432011-07-12 13:23:19 -070034class ProfileTest : public PropertyStoreTest {
35 public:
Chris Masone6515aab2011-10-12 16:19:09 -070036 ProfileTest() {
37 Profile::Identifier id("rather", "irrelevant");
38 profile_ = new Profile(control_interface(), manager(), id, "", false);
Chris Masone9d779932011-08-25 16:33:41 -070039 }
40
41 MockService *CreateMockService() {
Chris Masone2176a882011-09-14 22:29:15 -070042 return new StrictMock<MockService>(control_interface(),
43 dispatcher(),
Chris Masone9d779932011-08-25 16:33:41 -070044 manager());
Chris Masone6791a432011-07-12 13:23:19 -070045 }
46
Chris Masone6515aab2011-10-12 16:19:09 -070047 virtual void SetUp() {
48 PropertyStoreTest::SetUp();
49 FilePath final_path(storage_path());
50 final_path = final_path.Append("test.profile");
51 scoped_ptr<KeyFileStore> storage(new KeyFileStore(&real_glib_));
52 storage->set_path(final_path);
53 ASSERT_TRUE(storage->Open());
54 profile_->set_storage(storage.release()); // Passes ownership.
55 }
56
Paul Stewart5dc40aa2011-10-28 19:43:43 -070057 bool ProfileInitStorage(const Profile::Identifier &id,
58 Profile::InitStorageOption storage_option,
59 bool save,
60 Error::Type error_type) {
61 Error error;
62 ProfileRefPtr profile(
63 new Profile(control_interface(), manager(), id, storage_path(), false));
64 bool ret = profile->InitStorage(&real_glib_, storage_option, &error);
65 EXPECT_EQ(error_type, error.type());
66 if (ret && save) {
67 EXPECT_TRUE(profile->Save());
68 }
69 return ret;
70 }
71
Chris Masone6791a432011-07-12 13:23:19 -070072 protected:
Chris Masone6515aab2011-10-12 16:19:09 -070073 GLib real_glib_;
74 ProfileRefPtr profile_;
Darin Petkova4766822011-07-07 10:42:22 -070075};
76
77TEST_F(ProfileTest, IsValidIdentifierToken) {
78 EXPECT_FALSE(Profile::IsValidIdentifierToken(""));
79 EXPECT_FALSE(Profile::IsValidIdentifierToken(" "));
80 EXPECT_FALSE(Profile::IsValidIdentifierToken("-"));
81 EXPECT_FALSE(Profile::IsValidIdentifierToken("~"));
82 EXPECT_FALSE(Profile::IsValidIdentifierToken("_"));
83 EXPECT_TRUE(Profile::IsValidIdentifierToken("a"));
84 EXPECT_TRUE(Profile::IsValidIdentifierToken("ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
85 EXPECT_TRUE(Profile::IsValidIdentifierToken("abcdefghijklmnopqrstuvwxyz"));
86 EXPECT_TRUE(Profile::IsValidIdentifierToken("0123456789"));
87}
88
89TEST_F(ProfileTest, ParseIdentifier) {
90 Profile::Identifier identifier;
91 EXPECT_FALSE(Profile::ParseIdentifier("", &identifier));
92 EXPECT_FALSE(Profile::ParseIdentifier("~", &identifier));
93 EXPECT_FALSE(Profile::ParseIdentifier("~foo", &identifier));
94 EXPECT_FALSE(Profile::ParseIdentifier("~/", &identifier));
95 EXPECT_FALSE(Profile::ParseIdentifier("~bar/", &identifier));
96 EXPECT_FALSE(Profile::ParseIdentifier("~/zoo", &identifier));
97 EXPECT_FALSE(Profile::ParseIdentifier("~./moo", &identifier));
98 EXPECT_FALSE(Profile::ParseIdentifier("~valid/?", &identifier));
99 EXPECT_FALSE(Profile::ParseIdentifier("~no//no", &identifier));
100 EXPECT_FALSE(Profile::ParseIdentifier("~no~no", &identifier));
101
102 static const char kUser[] = "user";
103 static const char kIdentifier[] = "identifier";
104 EXPECT_TRUE(Profile::ParseIdentifier(
105 base::StringPrintf("~%s/%s", kUser, kIdentifier),
106 &identifier));
107 EXPECT_EQ(kUser, identifier.user);
108 EXPECT_EQ(kIdentifier, identifier.identifier);
109
110 EXPECT_FALSE(Profile::ParseIdentifier("!", &identifier));
111 EXPECT_FALSE(Profile::ParseIdentifier("/nope", &identifier));
112
113 static const char kIdentifier2[] = "something";
114 EXPECT_TRUE(Profile::ParseIdentifier(kIdentifier2, &identifier));
115 EXPECT_EQ("", identifier.user);
116 EXPECT_EQ(kIdentifier2, identifier.identifier);
117}
118
Chris Masone7df0c672011-07-15 10:24:54 -0700119TEST_F(ProfileTest, GetFriendlyName) {
Darin Petkova4766822011-07-07 10:42:22 -0700120 static const char kUser[] = "theUser";
121 static const char kIdentifier[] = "theIdentifier";
Chris Masone6515aab2011-10-12 16:19:09 -0700122 Profile::Identifier id(kIdentifier);
Chris Masone7df0c672011-07-15 10:24:54 -0700123 ProfileRefPtr profile(
Chris Masone2176a882011-09-14 22:29:15 -0700124 new Profile(control_interface(), manager(), id, "", false));
Chris Masone7df0c672011-07-15 10:24:54 -0700125 EXPECT_EQ(kIdentifier, profile->GetFriendlyName());
126 id.user = kUser;
Chris Masone2176a882011-09-14 22:29:15 -0700127 profile = new Profile(control_interface(), manager(), id, "", false);
Chris Masone7df0c672011-07-15 10:24:54 -0700128 EXPECT_EQ(string(kUser) + "/" + kIdentifier, profile->GetFriendlyName());
Darin Petkova4766822011-07-07 10:42:22 -0700129}
130
131TEST_F(ProfileTest, GetStoragePath) {
132 static const char kUser[] = "chronos";
133 static const char kIdentifier[] = "someprofile";
Chris Masone2ae797d2011-08-23 20:41:00 -0700134 static const char kFormat[] = "/a/place/for/%s";
Darin Petkova4766822011-07-07 10:42:22 -0700135 FilePath path;
Chris Masone6515aab2011-10-12 16:19:09 -0700136 Profile::Identifier id(kIdentifier);
Chris Masone2ae797d2011-08-23 20:41:00 -0700137 ProfileRefPtr profile(
Chris Masone2176a882011-09-14 22:29:15 -0700138 new Profile(control_interface(), manager(), id, "", false));
Chris Masone2ae797d2011-08-23 20:41:00 -0700139 EXPECT_FALSE(profile->GetStoragePath(&path));
140 id.user = kUser;
141 profile =
Chris Masone2176a882011-09-14 22:29:15 -0700142 new Profile(control_interface(), manager(), id, kFormat, false);
Chris Masone2ae797d2011-08-23 20:41:00 -0700143 EXPECT_TRUE(profile->GetStoragePath(&path));
144 string suffix = base::StringPrintf("/%s.profile", kIdentifier);
145 EXPECT_EQ(base::StringPrintf(kFormat, kUser) + suffix, path.value());
Darin Petkova4766822011-07-07 10:42:22 -0700146}
147
Chris Masone6791a432011-07-12 13:23:19 -0700148TEST_F(ProfileTest, ServiceManagement) {
Chris Masone6515aab2011-10-12 16:19:09 -0700149 scoped_refptr<MockService> service1(CreateMockService());
150 scoped_refptr<MockService> service2(CreateMockService());
Chris Masone6791a432011-07-12 13:23:19 -0700151
Chris Masone6515aab2011-10-12 16:19:09 -0700152 EXPECT_CALL(*service1.get(), Save(_))
153 .WillRepeatedly(Invoke(service1.get(), &MockService::FauxSave));
154 EXPECT_CALL(*service2.get(), Save(_))
155 .WillRepeatedly(Invoke(service2.get(), &MockService::FauxSave));
Chris Masone6791a432011-07-12 13:23:19 -0700156
Chris Masone6515aab2011-10-12 16:19:09 -0700157 ASSERT_TRUE(profile_->AdoptService(service1));
158 ASSERT_TRUE(profile_->AdoptService(service2));
159
160 // Ensure services are in the profile now.
161 ASSERT_TRUE(profile_->ContainsService(service1));
162 ASSERT_TRUE(profile_->ContainsService(service2));
163
164 // Ensure we can't add them twice.
165 ASSERT_FALSE(profile_->AdoptService(service1));
166 ASSERT_FALSE(profile_->AdoptService(service2));
167
168 // Ensure that we can abandon individually, and that doing so is idempotent.
169 ASSERT_TRUE(profile_->AbandonService(service1));
170 ASSERT_FALSE(profile_->ContainsService(service1));
171 ASSERT_TRUE(profile_->AbandonService(service1));
172 ASSERT_TRUE(profile_->ContainsService(service2));
173
174 // Clean up.
175 ASSERT_TRUE(profile_->AbandonService(service2));
176 ASSERT_FALSE(profile_->ContainsService(service1));
177 ASSERT_FALSE(profile_->ContainsService(service2));
Chris Masone6791a432011-07-12 13:23:19 -0700178}
179
Paul Stewartbba6a5b2011-11-02 18:45:59 -0700180TEST_F(ProfileTest, ServiceConfigure) {
Chris Masone6515aab2011-10-12 16:19:09 -0700181 ServiceRefPtr service1(new ServiceUnderTest(control_interface(),
182 dispatcher(),
183 manager()));
mukesh agrawal00917ce2011-11-22 23:56:55 +0000184 service1->set_priority(service1->priority() + 1); // Change from default.
Chris Masone6515aab2011-10-12 16:19:09 -0700185 ASSERT_TRUE(profile_->AdoptService(service1));
186 ASSERT_TRUE(profile_->ContainsService(service1));
187
188 // Create new service; ask Profile to merge it with a known, matching,
189 // service; ensure that settings from |service1| wind up in |service2|.
190 ServiceRefPtr service2(new ServiceUnderTest(control_interface(),
191 dispatcher(),
192 manager()));
mukesh agrawal00917ce2011-11-22 23:56:55 +0000193 int32 orig_priority = service2->priority();
Paul Stewartbba6a5b2011-11-02 18:45:59 -0700194 ASSERT_TRUE(profile_->ConfigureService(service2));
mukesh agrawal00917ce2011-11-22 23:56:55 +0000195 ASSERT_EQ(service1->priority(), service2->priority());
196 ASSERT_NE(orig_priority, service2->priority());
Chris Masone6515aab2011-10-12 16:19:09 -0700197
198 // Clean up.
199 ASSERT_TRUE(profile_->AbandonService(service1));
200 ASSERT_FALSE(profile_->ContainsService(service1));
201 ASSERT_FALSE(profile_->ContainsService(service2));
202}
203
204TEST_F(ProfileTest, Save) {
Chris Masone9d779932011-08-25 16:33:41 -0700205 scoped_refptr<MockService> service1(CreateMockService());
206 scoped_refptr<MockService> service2(CreateMockService());
207 EXPECT_CALL(*service1.get(), Save(_)).WillOnce(Return(true));
208 EXPECT_CALL(*service2.get(), Save(_)).WillOnce(Return(true));
209
Chris Masone6515aab2011-10-12 16:19:09 -0700210 ASSERT_TRUE(profile_->AdoptService(service1));
211 ASSERT_TRUE(profile_->AdoptService(service2));
Chris Masone9d779932011-08-25 16:33:41 -0700212
Chris Masone6515aab2011-10-12 16:19:09 -0700213 profile_->Save();
Chris Masone9d779932011-08-25 16:33:41 -0700214}
215
Chris Masone6791a432011-07-12 13:23:19 -0700216TEST_F(ProfileTest, EntryEnumeration) {
Chris Masone6515aab2011-10-12 16:19:09 -0700217 scoped_refptr<MockService> service1(CreateMockService());
218 scoped_refptr<MockService> service2(CreateMockService());
219 EXPECT_CALL(*service1.get(), Save(_))
220 .WillRepeatedly(Invoke(service1.get(), &MockService::FauxSave));
221 EXPECT_CALL(*service2.get(), Save(_))
222 .WillRepeatedly(Invoke(service2.get(), &MockService::FauxSave));
223
mukesh agrawal51a7e932011-07-27 16:18:26 -0700224 string service1_name(service1->UniqueName());
225 string service2_name(service2->UniqueName());
226
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800227 Error error;
Chris Masone6791a432011-07-12 13:23:19 -0700228 ASSERT_TRUE(profile_->AdoptService(service1));
229 ASSERT_TRUE(profile_->AdoptService(service2));
230
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800231 ASSERT_EQ(profile_->EnumerateEntries(&error).size(), 2);
Chris Masone6791a432011-07-12 13:23:19 -0700232
Chris Masone6515aab2011-10-12 16:19:09 -0700233 ASSERT_TRUE(profile_->AbandonService(service1));
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800234 ASSERT_EQ(profile_->EnumerateEntries(&error)[0], service2_name);
Chris Masone6791a432011-07-12 13:23:19 -0700235
Chris Masone6515aab2011-10-12 16:19:09 -0700236 ASSERT_TRUE(profile_->AbandonService(service1));
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800237 ASSERT_EQ(profile_->EnumerateEntries(&error)[0], service2_name);
Chris Masone6791a432011-07-12 13:23:19 -0700238
Chris Masone6515aab2011-10-12 16:19:09 -0700239 ASSERT_TRUE(profile_->AbandonService(service2));
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800240 ASSERT_EQ(profile_->EnumerateEntries(&error).size(), 0);
Chris Masone6791a432011-07-12 13:23:19 -0700241}
242
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700243TEST_F(ProfileTest, MatchesIdentifier) {
244 static const char kUser[] = "theUser";
245 static const char kIdentifier[] = "theIdentifier";
246 Profile::Identifier id(kUser, kIdentifier);
247 ProfileRefPtr profile(
248 new Profile(control_interface(), manager(), id, "", false));
249 EXPECT_TRUE(profile->MatchesIdentifier(id));
250 EXPECT_FALSE(profile->MatchesIdentifier(Profile::Identifier(kUser, "")));
251 EXPECT_FALSE(
252 profile->MatchesIdentifier(Profile::Identifier("", kIdentifier)));
253 EXPECT_FALSE(
254 profile->MatchesIdentifier(Profile::Identifier(kIdentifier, kUser)));
255}
256
257TEST_F(ProfileTest, InitStorage) {
258 Profile::Identifier id("theUser", "theIdentifier");
259
260 // Profile doesn't exist but we wanted it to.
261 EXPECT_FALSE(ProfileInitStorage(id, Profile::kOpenExisting, false,
262 Error::kNotFound));
263
264 // Success case, with a side effect of creating the profile.
265 EXPECT_TRUE(ProfileInitStorage(id, Profile::kCreateNew, true,
266 Error::kSuccess));
267
268 // The results from our two test cases above will now invert since
269 // the profile now exists. First, we now succeed if we require that
270 // the profile already exist...
271 EXPECT_TRUE(ProfileInitStorage(id, Profile::kOpenExisting, false,
272 Error::kSuccess));
273
274 // And we fail if we require that it doesn't.
275 EXPECT_FALSE(ProfileInitStorage(id, Profile::kCreateNew, false,
276 Error::kAlreadyExists));
277
278 // As a sanity check, ensure "create or open" works for both profile-exists...
279 EXPECT_TRUE(ProfileInitStorage(id, Profile::kCreateOrOpenExisting, false,
280 Error::kSuccess));
281
282 // ...and for a new profile that doesn't exist.
283 Profile::Identifier id2("theUser", "theIdentifier2");
284 // Let's just make double-check that this profile really doesn't exist.
285 ASSERT_FALSE(ProfileInitStorage(id2, Profile::kOpenExisting, false,
286 Error::kNotFound));
287
288 // Then test that with "create or open" we succeed.
289 EXPECT_TRUE(ProfileInitStorage(id2, Profile::kCreateOrOpenExisting, false,
290 Error::kSuccess));
291}
292
Paul Stewart7355ce12011-09-02 10:47:01 -0700293} // namespace shill