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