signed_in_devices_api_unittest.cc revision 58537e28ecd584eab876aee8be7156509866d23a
1// Copyright (c) 2013 The Chromium 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
5#include <string>
6
7#include <vector>
8
9#include "base/guid.h"
10#include "base/message_loop/message_loop.h"
11#include "base/prefs/pref_service.h"
12#include "base/values.h"
13#include "chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.h"
14#include "chrome/browser/extensions/extension_function_test_utils.h"
15#include "chrome/browser/extensions/test_extension_prefs.h"
16#include "chrome/browser/profiles/profile.h"
17#include "chrome/browser/sync/glue/device_info.h"
18#include "chrome/browser/sync/profile_sync_service_factory.h"
19#include "chrome/browser/sync/profile_sync_service_mock.h"
20#include "chrome/common/extensions/extension.h"
21#include "chrome/common/extensions/extension_manifest_constants.h"
22#include "chrome/common/pref_names.h"
23#include "chrome/test/base/browser_with_test_window_test.h"
24#include "testing/gmock/include/gmock/gmock.h"
25#include "testing/gtest/include/gtest/gtest.h"
26
27using extensions::Extension;
28using extensions::TestExtensionPrefs;
29using browser_sync::DeviceInfo;
30using testing::Return;
31
32namespace extensions {
33
34namespace utils = extension_function_test_utils;
35
36TEST(SignedInDevicesAPITest, GetSignedInDevices) {
37  ProfileSyncServiceMock pss_mock;
38  base::MessageLoop message_loop_;
39  TestExtensionPrefs extension_prefs(
40      message_loop_.message_loop_proxy().get());
41
42  // Add a couple of devices and make sure we get back public ids for them.
43  std::string extension_name = "test";
44  scoped_refptr<Extension> extension_test =
45      extension_prefs.AddExtension(extension_name);
46
47  DeviceInfo device_info1(
48      base::GenerateGUID(),
49      "abc Device", "XYZ v1", "XYZ SyncAgent v1",
50      sync_pb::SyncEnums_DeviceType_TYPE_LINUX);
51
52  DeviceInfo device_info2(
53      base::GenerateGUID(),
54      "def Device", "XYZ v2", "XYZ SyncAgent v2",
55      sync_pb::SyncEnums_DeviceType_TYPE_LINUX);
56
57  std::vector<DeviceInfo*> devices;
58  devices.push_back(&device_info1);
59  devices.push_back(&device_info2);
60
61  EXPECT_CALL(pss_mock, GetAllSignedInDevicesMock()).
62              WillOnce(Return(&devices));
63
64  ScopedVector<DeviceInfo> output1 = GetAllSignedInDevices(
65      extension_test.get()->id(),
66      &pss_mock,
67      extension_prefs.prefs());
68
69  std::string public_id1 = device_info1.public_id();
70  std::string public_id2 = device_info2.public_id();
71
72  EXPECT_FALSE(public_id1.empty());
73  EXPECT_FALSE(public_id2.empty());
74  EXPECT_NE(public_id1, public_id2);
75
76  // Now clear output1 so its destructor will not destroy the pointers for
77  // |device_info1| and |device_info2|.
78  output1.weak_clear();
79
80  // Add a third device and make sure the first 2 ids are retained and a new
81  // id is generated for the third device.
82  DeviceInfo device_info3(
83      base::GenerateGUID(),
84      "def Device", "jkl v2", "XYZ SyncAgent v2",
85      sync_pb::SyncEnums_DeviceType_TYPE_LINUX);
86
87  devices.push_back(&device_info3);
88
89  EXPECT_CALL(pss_mock, GetAllSignedInDevicesMock()).
90              WillOnce(Return(&devices));
91
92  ScopedVector<DeviceInfo> output2 = GetAllSignedInDevices(
93      extension_test.get()->id(),
94      &pss_mock,
95      extension_prefs.prefs());
96
97  EXPECT_EQ(device_info1.public_id(), public_id1);
98  EXPECT_EQ(device_info2.public_id(), public_id2);
99
100  std::string public_id3 = device_info3.public_id();
101  EXPECT_FALSE(public_id3.empty());
102  EXPECT_NE(public_id3, public_id1);
103  EXPECT_NE(public_id3, public_id2);
104
105  // Now clear output2 so that its destructor does not destroy the
106  // |DeviceInfo| pointers.
107  output2.weak_clear();
108}
109
110class ProfileSyncServiceMockForExtensionTests:
111    public ProfileSyncServiceMock {
112 public:
113  ProfileSyncServiceMockForExtensionTests() {}
114  ~ProfileSyncServiceMockForExtensionTests() {}
115  MOCK_METHOD0(Shutdown, void());
116};
117
118BrowserContextKeyedService* CreateProfileSyncServiceMock(
119    content::BrowserContext* profile) {
120  return new ProfileSyncServiceMockForExtensionTests();
121}
122
123class ExtensionSignedInDevicesTest : public BrowserWithTestWindowTest {
124 public:
125  virtual void SetUp() {
126    BrowserWithTestWindowTest::SetUp();
127
128    ProfileSyncServiceFactory::GetInstance()->SetTestingFactory(
129        profile(), CreateProfileSyncServiceMock);
130
131    extension_ = utils::CreateEmptyExtensionWithLocation(
132        extensions::Manifest::UNPACKED);
133
134  }
135
136  base::Value* RunFunctionWithExtension(
137      UIThreadExtensionFunction* function,
138      const std::string& args) {
139    scoped_refptr<UIThreadExtensionFunction> delete_function(function);
140    function->set_extension(extension_.get());
141    return utils::RunFunctionAndReturnSingleResult(function, args, browser());
142  }
143
144  base::ListValue* RunFunctionAndReturnList(
145      UIThreadExtensionFunction* function,
146      const std::string& args) {
147    base::Value* result = RunFunctionWithExtension(function, args);
148    return result ? utils::ToList(result) : NULL;
149  }
150
151 protected:
152  scoped_refptr<extensions::Extension> extension_;
153};
154
155DeviceInfo* CreateDeviceInfo(const DeviceInfo& device_info) {
156  return new DeviceInfo(device_info.guid(),
157                        device_info.client_name(),
158                        device_info.chrome_version(),
159                        device_info.sync_user_agent(),
160                        device_info.device_type());
161}
162
163std::string GetPublicId(const base::DictionaryValue* dictionary) {
164  std::string public_id;
165  if (!dictionary->GetString("id", &public_id)) {
166    ADD_FAILURE() << "Not able to find public id in the dictionary";
167  }
168
169  return public_id;
170}
171
172void VerifyDictionaryWithDeviceInfo(const base::DictionaryValue* actual_value,
173                                    DeviceInfo* device_info) {
174  std::string public_id = GetPublicId(actual_value);
175  device_info->set_public_id(public_id);
176
177  scoped_ptr<base::DictionaryValue> expected_value(device_info->ToValue());
178  EXPECT_TRUE(expected_value->Equals(actual_value));
179}
180
181base::DictionaryValue* GetDictionaryFromList(int index,
182                                             base::ListValue* value) {
183  base::DictionaryValue* dictionary;
184  if (!value->GetDictionary(index, &dictionary)) {
185    ADD_FAILURE() << "Expected a list of dictionaries";
186    return NULL;
187  }
188  return dictionary;
189}
190
191TEST_F(ExtensionSignedInDevicesTest, GetAll) {
192  ProfileSyncServiceMockForExtensionTests* pss_mock =
193      static_cast<ProfileSyncServiceMockForExtensionTests*>(
194          ProfileSyncServiceFactory::GetForProfile(profile()));
195
196  DeviceInfo device_info1(
197      base::GenerateGUID(),
198      "abc Device", "XYZ v1", "XYZ SyncAgent v1",
199      sync_pb::SyncEnums_DeviceType_TYPE_LINUX);
200
201  DeviceInfo device_info2(
202      base::GenerateGUID(),
203      "def Device", "XYZ v2", "XYZ SyncAgent v2",
204      sync_pb::SyncEnums_DeviceType_TYPE_LINUX);
205
206  std::vector<DeviceInfo*> devices;
207  devices.push_back(CreateDeviceInfo(device_info1));
208  devices.push_back(CreateDeviceInfo(device_info2));
209
210  EXPECT_CALL(*pss_mock, GetAllSignedInDevicesMock()).
211              WillOnce(Return(&devices));
212
213  EXPECT_CALL(*pss_mock, Shutdown());
214
215  scoped_ptr<base::ListValue> result(RunFunctionAndReturnList(
216      new SignedInDevicesGetFunction(), "[null]"));
217
218  // Ensure dictionary matches device info.
219  VerifyDictionaryWithDeviceInfo(GetDictionaryFromList(0, result.get()),
220                                 &device_info1);
221  VerifyDictionaryWithDeviceInfo(GetDictionaryFromList(1, result.get()),
222                                 &device_info2);
223
224  // Ensure public ids are set and unique.
225  std::string public_id1 = GetPublicId(GetDictionaryFromList(0, result.get()));
226  std::string public_id2 = GetPublicId(GetDictionaryFromList(1, result.get()));
227
228  EXPECT_FALSE(public_id1.empty());
229  EXPECT_FALSE(public_id2.empty());
230  EXPECT_NE(public_id1, public_id2);
231}
232
233}  // namespace extensions
234