• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (c) 2011 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#import <Foundation/Foundation.h>
6#import <objc/objc-class.h>
7
8#import "chrome/browser/mac/keystone_glue.h"
9#import "chrome/browser/mac/keystone_registration.h"
10#include "testing/gtest/include/gtest/gtest.h"
11#include "testing/platform_test.h"
12
13namespace ksr = keystone_registration;
14
15
16@interface FakeKeystoneRegistration : KSRegistration
17@end
18
19
20// This unit test implements FakeKeystoneRegistration as a KSRegistration
21// subclass. It won't be linked against KSRegistration, so provide a stub
22// KSRegistration class on which to base FakeKeystoneRegistration.
23@implementation KSRegistration
24
25+ (id)registrationWithProductID:(NSString*)productID {
26  return nil;
27}
28
29- (BOOL)registerWithParameters:(NSDictionary*)args {
30  return NO;
31}
32
33- (BOOL)promoteWithParameters:(NSDictionary*)args
34                authorization:(AuthorizationRef)authorization {
35  return NO;
36}
37
38- (BOOL)setActive {
39  return NO;
40}
41
42- (void)checkForUpdateWasUserInitiated:(BOOL)userInitiated {
43}
44
45- (void)startUpdate {
46}
47
48- (ksr::KSRegistrationTicketType)ticketType {
49  return ksr::kKSRegistrationDontKnowWhatKindOfTicket;
50}
51
52@end
53
54
55@implementation FakeKeystoneRegistration
56
57// Send the notifications that a real KeystoneGlue object would send.
58
59- (void)checkForUpdateWasUserInitiated:(BOOL)userInitiated {
60  NSNumber* yesNumber = [NSNumber numberWithBool:YES];
61  NSString* statusKey = @"Status";
62  NSDictionary* dictionary = [NSDictionary dictionaryWithObject:yesNumber
63                                                         forKey:statusKey];
64  NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
65  [center postNotificationName:ksr::KSRegistrationCheckForUpdateNotification
66                        object:nil
67                      userInfo:dictionary];
68}
69
70- (void)startUpdate {
71  NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
72  [center postNotificationName:ksr::KSRegistrationStartUpdateNotification
73                        object:nil];
74}
75
76@end
77
78
79@interface FakeKeystoneGlue : KeystoneGlue {
80 @public
81  BOOL upToDate_;
82  NSString *latestVersion_;
83  BOOL successful_;
84  int installs_;
85}
86
87- (void)fakeAboutWindowCallback:(NSNotification*)notification;
88@end
89
90
91@implementation FakeKeystoneGlue
92
93- (id)init {
94  if ((self = [super init])) {
95    // some lies
96    upToDate_ = YES;
97    latestVersion_ = @"foo bar";
98    successful_ = YES;
99    installs_ = 1010101010;
100
101    // Set up an observer that takes the notification that the About window
102    // listens for.
103    NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
104    [center addObserver:self
105               selector:@selector(fakeAboutWindowCallback:)
106                   name:kAutoupdateStatusNotification
107                 object:nil];
108  }
109  return self;
110}
111
112- (void)dealloc {
113  [[NSNotificationCenter defaultCenter] removeObserver:self];
114  [super dealloc];
115}
116
117// For mocking
118- (NSDictionary*)infoDictionary {
119  NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
120                                     @"http://foo.bar", @"KSUpdateURL",
121                                     @"com.google.whatever", @"KSProductID",
122                                     @"0.0.0.1", @"KSVersion",
123                                     nil];
124  return dict;
125}
126
127// For mocking
128- (BOOL)loadKeystoneRegistration {
129  return YES;
130}
131
132// Confirms certain things are happy
133- (BOOL)dictReadCorrectly {
134  return ([url_ isEqual:@"http://foo.bar"] &&
135          [productID_ isEqual:@"com.google.whatever"] &&
136          [version_ isEqual:@"0.0.0.1"]);
137}
138
139// Confirms certain things are happy
140- (BOOL)hasATimer {
141  return timer_ ? YES : NO;
142}
143
144- (void)addFakeRegistration {
145  registration_ = [[FakeKeystoneRegistration alloc] init];
146}
147
148- (void)fakeAboutWindowCallback:(NSNotification*)notification {
149  NSDictionary* dictionary = [notification userInfo];
150  AutoupdateStatus status = static_cast<AutoupdateStatus>(
151      [[dictionary objectForKey:kAutoupdateStatusStatus] intValue]);
152
153  if (status == kAutoupdateAvailable) {
154    upToDate_ = NO;
155    latestVersion_ = [dictionary objectForKey:kAutoupdateStatusVersion];
156  } else if (status == kAutoupdateInstallFailed) {
157    successful_ = NO;
158    installs_ = 0;
159  }
160}
161
162// Confirm we look like callbacks with nil NSNotifications
163- (BOOL)confirmCallbacks {
164  return (!upToDate_ &&
165          (latestVersion_ == nil) &&
166          !successful_ &&
167          (installs_ == 0));
168}
169
170@end
171
172
173namespace {
174
175class KeystoneGlueTest : public PlatformTest {
176};
177
178// DISABLED because the mocking isn't currently working.
179TEST_F(KeystoneGlueTest, DISABLED_BasicGlobalCreate) {
180  // Allow creation of a KeystoneGlue by mocking out a few calls
181  SEL ids = @selector(infoDictionary);
182  IMP oldInfoImp_ = [[KeystoneGlue class] instanceMethodForSelector:ids];
183  IMP newInfoImp_ = [[FakeKeystoneGlue class] instanceMethodForSelector:ids];
184  Method infoMethod_ = class_getInstanceMethod([KeystoneGlue class], ids);
185  method_setImplementation(infoMethod_, newInfoImp_);
186
187  SEL lks = @selector(loadKeystoneRegistration);
188  IMP oldLoadImp_ = [[KeystoneGlue class] instanceMethodForSelector:lks];
189  IMP newLoadImp_ = [[FakeKeystoneGlue class] instanceMethodForSelector:lks];
190  Method loadMethod_ = class_getInstanceMethod([KeystoneGlue class], lks);
191  method_setImplementation(loadMethod_, newLoadImp_);
192
193  KeystoneGlue *glue = [KeystoneGlue defaultKeystoneGlue];
194  ASSERT_TRUE(glue);
195
196  // Fix back up the class to the way we found it.
197  method_setImplementation(infoMethod_, oldInfoImp_);
198  method_setImplementation(loadMethod_, oldLoadImp_);
199}
200
201// DISABLED because the mocking isn't currently working.
202TEST_F(KeystoneGlueTest, DISABLED_BasicUse) {
203  FakeKeystoneGlue* glue = [[[FakeKeystoneGlue alloc] init] autorelease];
204  [glue loadParameters];
205  ASSERT_TRUE([glue dictReadCorrectly]);
206
207  // Likely returns NO in the unit test, but call it anyway to make
208  // sure it doesn't crash.
209  [glue loadKeystoneRegistration];
210
211  // Confirm we start up an active timer
212  [glue registerWithKeystone];
213  ASSERT_TRUE([glue hasATimer]);
214  [glue stopTimer];
215
216  // Brief exercise of callbacks
217  [glue addFakeRegistration];
218  [glue checkForUpdate];
219  [glue installUpdate];
220  ASSERT_TRUE([glue confirmCallbacks]);
221}
222
223}  // namespace
224