blob: 9d49a09451409b05a5d1daad6d418ba7aa2484d8 [file] [log] [blame]
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <Foundation/Foundation.h>
#import <objc/objc-class.h>
#import "chrome/browser/cocoa/keystone_glue.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
@interface FakeGlueRegistration : NSObject
@end
@implementation FakeGlueRegistration
// Send the notifications that a real KeystoneGlue object would send.
- (void)checkForUpdate {
NSNumber* yesNumber = [NSNumber numberWithBool:YES];
NSString* statusKey = @"Status";
NSDictionary* dictionary = [NSDictionary dictionaryWithObject:yesNumber
forKey:statusKey];
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
[center postNotificationName:@"KSRegistrationCheckForUpdateNotification"
object:nil
userInfo:dictionary];
}
- (void)startUpdate {
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
[center postNotificationName:@"KSRegistrationStartUpdateNotification"
object:nil];
}
@end
@interface FakeKeystoneGlue : KeystoneGlue {
@public
BOOL upToDate_;
NSString *latestVersion_;
BOOL successful_;
int installs_;
}
- (void)fakeAboutWindowCallback:(NSNotification*)notification;
@end
@implementation FakeKeystoneGlue
- (id)init {
if ((self = [super init])) {
// some lies
upToDate_ = YES;
latestVersion_ = @"foo bar";
successful_ = YES;
installs_ = 1010101010;
// Set up an observer that takes the notification that the About window
// listens for.
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
[center addObserver:self
selector:@selector(fakeAboutWindowCallback:)
name:kAutoupdateStatusNotification
object:nil];
}
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
// For mocking
- (NSDictionary*)infoDictionary {
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
@"http://foo.bar", @"KSUpdateURL",
@"com.google.whatever", @"KSProductID",
@"0.0.0.1", @"KSVersion",
nil];
return dict;
}
// For mocking
- (BOOL)loadKeystoneRegistration {
return YES;
}
// Confirms certain things are happy
- (BOOL)dictReadCorrectly {
return ([url_ isEqual:@"http://foo.bar"] &&
[productID_ isEqual:@"com.google.whatever"] &&
[version_ isEqual:@"0.0.0.1"]);
}
// Confirms certain things are happy
- (BOOL)hasATimer {
return timer_ ? YES : NO;
}
- (void)addFakeRegistration {
registration_ = [[FakeGlueRegistration alloc] init];
}
- (void)fakeAboutWindowCallback:(NSNotification*)notification {
NSDictionary* dictionary = [notification userInfo];
AutoupdateStatus status = static_cast<AutoupdateStatus>(
[[dictionary objectForKey:kAutoupdateStatusStatus] intValue]);
if (status == kAutoupdateAvailable) {
upToDate_ = NO;
latestVersion_ = [dictionary objectForKey:kAutoupdateStatusVersion];
} else if (status == kAutoupdateInstallFailed) {
successful_ = NO;
installs_ = 0;
}
}
// Confirm we look like callbacks with nil NSNotifications
- (BOOL)confirmCallbacks {
return (!upToDate_ &&
(latestVersion_ == nil) &&
!successful_ &&
(installs_ == 0));
}
@end
namespace {
class KeystoneGlueTest : public PlatformTest {
};
// DISABLED because the mocking isn't currently working.
TEST_F(KeystoneGlueTest, DISABLED_BasicGlobalCreate) {
// Allow creation of a KeystoneGlue by mocking out a few calls
SEL ids = @selector(infoDictionary);
IMP oldInfoImp_ = [[KeystoneGlue class] instanceMethodForSelector:ids];
IMP newInfoImp_ = [[FakeKeystoneGlue class] instanceMethodForSelector:ids];
Method infoMethod_ = class_getInstanceMethod([KeystoneGlue class], ids);
method_setImplementation(infoMethod_, newInfoImp_);
SEL lks = @selector(loadKeystoneRegistration);
IMP oldLoadImp_ = [[KeystoneGlue class] instanceMethodForSelector:lks];
IMP newLoadImp_ = [[FakeKeystoneGlue class] instanceMethodForSelector:lks];
Method loadMethod_ = class_getInstanceMethod([KeystoneGlue class], lks);
method_setImplementation(loadMethod_, newLoadImp_);
KeystoneGlue *glue = [KeystoneGlue defaultKeystoneGlue];
ASSERT_TRUE(glue);
// Fix back up the class to the way we found it.
method_setImplementation(infoMethod_, oldInfoImp_);
method_setImplementation(loadMethod_, oldLoadImp_);
}
// DISABLED because the mocking isn't currently working.
TEST_F(KeystoneGlueTest, DISABLED_BasicUse) {
FakeKeystoneGlue* glue = [[[FakeKeystoneGlue alloc] init] autorelease];
[glue loadParameters];
ASSERT_TRUE([glue dictReadCorrectly]);
// Likely returns NO in the unit test, but call it anyway to make
// sure it doesn't crash.
[glue loadKeystoneRegistration];
// Confirm we start up an active timer
[glue registerWithKeystone];
ASSERT_TRUE([glue hasATimer]);
[glue stopTimer];
// Brief exercise of callbacks
[glue addFakeRegistration];
[glue checkForUpdate];
[glue installUpdate];
ASSERT_TRUE([glue confirmCallbacks]);
}
} // namespace