Home | History | Annotate | Download | only in cocoa
      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 
    134 namespace {
    135 
    136 class KeystoneGlueTest : public PlatformTest {
    137 };
    138 
    139 // DISABLED because the mocking isn't currently working.
    140 TEST_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.
    163 TEST_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