blob: 99be2bcfc3c6ec3553cafa6c5367682598170fcc [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
Chris Masone6515aab2011-10-12 16:19:09 -0700180TEST_F(ProfileTest, ServiceMerge) {
181 ServiceRefPtr service1(new ServiceUnderTest(control_interface(),
182 dispatcher(),
183 manager()));
184 service1->set_favorite(!service1->favorite());
185 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()));
193 bool orig_favorite = service2->favorite();
194 ASSERT_TRUE(profile_->MergeService(service2));
195 ASSERT_EQ(service1->favorite(), service2->favorite());
196 ASSERT_NE(orig_favorite, service2->favorite());
197
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
Chris Masone6791a432011-07-12 13:23:19 -0700227 ASSERT_TRUE(profile_->AdoptService(service1));
228 ASSERT_TRUE(profile_->AdoptService(service2));
229
230 ASSERT_EQ(profile_->EnumerateEntries().size(), 2);
231
Chris Masone6515aab2011-10-12 16:19:09 -0700232 ASSERT_TRUE(profile_->AbandonService(service1));
mukesh agrawal51a7e932011-07-27 16:18:26 -0700233 ASSERT_EQ(profile_->EnumerateEntries()[0], service2_name);
Chris Masone6791a432011-07-12 13:23:19 -0700234
Chris Masone6515aab2011-10-12 16:19:09 -0700235 ASSERT_TRUE(profile_->AbandonService(service1));
mukesh agrawal51a7e932011-07-27 16:18:26 -0700236 ASSERT_EQ(profile_->EnumerateEntries()[0], service2_name);
Chris Masone6791a432011-07-12 13:23:19 -0700237
Chris Masone6515aab2011-10-12 16:19:09 -0700238 ASSERT_TRUE(profile_->AbandonService(service2));
Chris Masone6791a432011-07-12 13:23:19 -0700239 ASSERT_EQ(profile_->EnumerateEntries().size(), 0);
240}
241
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700242TEST_F(ProfileTest, MatchesIdentifier) {
243 static const char kUser[] = "theUser";
244 static const char kIdentifier[] = "theIdentifier";
245 Profile::Identifier id(kUser, kIdentifier);
246 ProfileRefPtr profile(
247 new Profile(control_interface(), manager(), id, "", false));
248 EXPECT_TRUE(profile->MatchesIdentifier(id));
249 EXPECT_FALSE(profile->MatchesIdentifier(Profile::Identifier(kUser, "")));
250 EXPECT_FALSE(
251 profile->MatchesIdentifier(Profile::Identifier("", kIdentifier)));
252 EXPECT_FALSE(
253 profile->MatchesIdentifier(Profile::Identifier(kIdentifier, kUser)));
254}
255
256TEST_F(ProfileTest, InitStorage) {
257 Profile::Identifier id("theUser", "theIdentifier");
258
259 // Profile doesn't exist but we wanted it to.
260 EXPECT_FALSE(ProfileInitStorage(id, Profile::kOpenExisting, false,
261 Error::kNotFound));
262
263 // Success case, with a side effect of creating the profile.
264 EXPECT_TRUE(ProfileInitStorage(id, Profile::kCreateNew, true,
265 Error::kSuccess));
266
267 // The results from our two test cases above will now invert since
268 // the profile now exists. First, we now succeed if we require that
269 // the profile already exist...
270 EXPECT_TRUE(ProfileInitStorage(id, Profile::kOpenExisting, false,
271 Error::kSuccess));
272
273 // And we fail if we require that it doesn't.
274 EXPECT_FALSE(ProfileInitStorage(id, Profile::kCreateNew, false,
275 Error::kAlreadyExists));
276
277 // As a sanity check, ensure "create or open" works for both profile-exists...
278 EXPECT_TRUE(ProfileInitStorage(id, Profile::kCreateOrOpenExisting, false,
279 Error::kSuccess));
280
281 // ...and for a new profile that doesn't exist.
282 Profile::Identifier id2("theUser", "theIdentifier2");
283 // Let's just make double-check that this profile really doesn't exist.
284 ASSERT_FALSE(ProfileInitStorage(id2, Profile::kOpenExisting, false,
285 Error::kNotFound));
286
287 // Then test that with "create or open" we succeed.
288 EXPECT_TRUE(ProfileInitStorage(id2, Profile::kCreateOrOpenExisting, false,
289 Error::kSuccess));
290}
291
Paul Stewart7355ce12011-09-02 10:47:01 -0700292} // namespace shill