/core/externals/update-engine/Core/KSUpdateActionTest.m

http://macfuse.googlecode.com/ · Objective C · 269 lines · 197 code · 52 blank · 20 comment · 2 complexity · 5bfb7ca4a8475984bacefc40b6508b01 MD5 · raw file

  1. // Copyright 2008 Google Inc.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #import <SenTestingKit/SenTestingKit.h>
  15. #import "KSUpdateAction.h"
  16. #import "KSInstallAction.h"
  17. #import "KSActionProcessor.h"
  18. #import "KSActionPipe.h"
  19. #import "KSCommandRunner.h"
  20. #import "NSData+Hash.h"
  21. #import "GTMBase64.h"
  22. #import <unistd.h>
  23. @interface KSUpdateActionTest : SenTestCase {
  24. @private
  25. NSString *successDMGPath_;
  26. NSString *failureDMGPath_;
  27. NSMutableArray *progressArray_;
  28. }
  29. @end
  30. @interface SuccessDelegate : NSObject {
  31. BOOL wasSuccessful_;
  32. }
  33. - (BOOL)wasSuccessful;
  34. @end
  35. @implementation SuccessDelegate
  36. - (BOOL)wasSuccessful {
  37. return wasSuccessful_;
  38. }
  39. - (void)processor:(KSActionProcessor *)processor
  40. finishedAction:(KSAction *)action
  41. successfully:(BOOL)wasOK {
  42. wasSuccessful_ = wasOK;
  43. }
  44. @end
  45. @implementation KSUpdateActionTest
  46. - (void)setUp {
  47. NSBundle *mainBundle = [NSBundle bundleForClass:[self class]];
  48. successDMGPath_ = [[mainBundle pathForResource:@"Test-SUCCESS"
  49. ofType:@"dmg"] retain];
  50. failureDMGPath_ = [[mainBundle pathForResource:@"Test-FAILURE"
  51. ofType:@"dmg"] retain];
  52. progressArray_ = [[NSMutableArray array] retain];
  53. STAssertNotNil(successDMGPath_, nil);
  54. STAssertNotNil(failureDMGPath_, nil);
  55. STAssertNotNil(progressArray_, nil);
  56. }
  57. - (void)tearDown {
  58. [successDMGPath_ release];
  59. [failureDMGPath_ release];
  60. [progressArray_ release];
  61. }
  62. - (void)testCreation {
  63. KSUpdateAction *action = nil;
  64. // Make sure calling super's designated initializer returns nil
  65. action = [[[KSUpdateAction alloc] initWithActions:nil] autorelease];
  66. STAssertNil(action, nil);
  67. action = [KSUpdateAction actionWithUpdateInfo:nil runner:nil userInitiated:NO];
  68. STAssertNil(action, nil);
  69. KSUpdateInfo *info =
  70. [NSDictionary dictionaryWithObjectsAndKeys:
  71. @"foo", kServerProductID,
  72. [NSURL URLWithString:@"a://a"], kServerCodebaseURL,
  73. [NSNumber numberWithInt:2], kServerCodeSize,
  74. @"zzz", kServerCodeHash,
  75. @"a://b", kServerMoreInfoURLString,
  76. [NSNumber numberWithBool:YES], kServerPromptUser,
  77. nil];
  78. action = [KSUpdateAction actionWithUpdateInfo:info
  79. runner:@"not nil"
  80. userInitiated:NO];
  81. STAssertNotNil(action, nil);
  82. STAssertTrue([[action description] length] > 1, nil);
  83. // Make sure the -wantsReboot method works correctly.
  84. STAssertFalse([action wantsReboot], nil);
  85. KSInstallAction *install = [[action actions] lastObject];
  86. [[install outPipe] setContents:[NSNumber numberWithInt:KS_INSTALL_WANTS_REBOOT]];
  87. STAssertTrue([action wantsReboot], nil);
  88. [[install outPipe] setContents:[NSNumber numberWithInt:0]];
  89. STAssertFalse([action wantsReboot], nil);
  90. [[install outPipe] setContents:[NSNumber numberWithInt:1]];
  91. STAssertFalse([action wantsReboot], nil);
  92. }
  93. - (void)loopUntilDone:(KSAction *)action {
  94. int count = 10;
  95. while ([action isRunning] && (count > 0)) {
  96. NSDate *quick = [NSDate dateWithTimeIntervalSinceNow:0.2];
  97. [[NSRunLoop currentRunLoop] runUntilDate:quick];
  98. count--;
  99. }
  100. STAssertFalse([action isRunning], nil);
  101. }
  102. // Return a happy action which, if executed, will perform a successful update.
  103. - (KSUpdateAction *)happyAction {
  104. id<KSCommandRunner> runner = [KSTaskCommandRunner commandRunner];
  105. STAssertNotNil(runner, nil);
  106. NSURL *url = [NSURL fileURLWithPath:successDMGPath_];
  107. NSData *data = [NSData dataWithContentsOfFile:successDMGPath_];
  108. NSData *dhash = [data SHA1Hash];
  109. NSString *hash = [GTMBase64 stringByEncodingData:dhash];
  110. NSString *name = [NSString stringWithFormat:@"KSUpdateActionUnitTest-%x",
  111. geteuid()];
  112. unsigned long long size =
  113. [[[NSFileManager defaultManager] fileAttributesAtPath:successDMGPath_
  114. traverseLink:NO] fileSize];
  115. KSUpdateInfo *info =
  116. [NSDictionary dictionaryWithObjectsAndKeys:
  117. name, kServerProductID,
  118. url, kServerCodebaseURL,
  119. [NSNumber numberWithInt:size], kServerCodeSize,
  120. hash, kServerCodeHash,
  121. nil];
  122. KSUpdateAction *action = nil;
  123. action = [KSUpdateAction actionWithUpdateInfo:info
  124. runner:runner
  125. userInitiated:NO];
  126. STAssertNotNil(action, nil);
  127. return action;
  128. }
  129. - (void)testSuccessfullUpdate {
  130. KSUpdateAction *action = [self happyAction];
  131. SuccessDelegate *delegate = [[[SuccessDelegate alloc] init] autorelease];
  132. // Create an action processor and run the action
  133. KSActionProcessor *ap = [[[KSActionProcessor alloc] initWithDelegate:delegate] autorelease];
  134. STAssertNotNil(ap, nil);
  135. [ap enqueueAction:action];
  136. [ap startProcessing];
  137. [self loopUntilDone:action];
  138. STAssertFalse([action isRunning], nil);
  139. STAssertTrue([delegate wasSuccessful], nil);
  140. STAssertFalse([action wantsReboot], nil);
  141. STAssertEqualObjects([action returnCode], [NSNumber numberWithInt:0], nil);
  142. }
  143. - (void)testFailedUpdate {
  144. id<KSCommandRunner> runner = [KSTaskCommandRunner commandRunner];
  145. STAssertNotNil(runner, nil);
  146. NSURL *url = [NSURL fileURLWithPath:failureDMGPath_];
  147. NSData *data = [NSData dataWithContentsOfFile:failureDMGPath_];
  148. NSData *dhash = [data SHA1Hash];
  149. NSString *hash = [GTMBase64 stringByEncodingData:dhash];
  150. NSString *name = [NSString stringWithFormat:@"KSUpdateActionUnitTest-%x",
  151. geteuid()];
  152. unsigned long long size =
  153. [[[NSFileManager defaultManager] fileAttributesAtPath:failureDMGPath_
  154. traverseLink:NO] fileSize];
  155. KSUpdateInfo *info =
  156. [NSDictionary dictionaryWithObjectsAndKeys:
  157. name, kServerProductID,
  158. url, kServerCodebaseURL,
  159. [NSNumber numberWithInt:size], kServerCodeSize,
  160. hash, kServerCodeHash,
  161. nil];
  162. KSUpdateAction *action = nil;
  163. action = [KSUpdateAction actionWithUpdateInfo:info
  164. runner:runner
  165. userInitiated:NO];
  166. STAssertNotNil(action, nil);
  167. SuccessDelegate *delegate = [[[SuccessDelegate alloc] init] autorelease];
  168. // Create an action processor and run the action
  169. KSActionProcessor *ap = [[[KSActionProcessor alloc] initWithDelegate:delegate] autorelease];
  170. STAssertNotNil(ap, nil);
  171. [ap enqueueAction:action];
  172. [ap startProcessing];
  173. [self loopUntilDone:action];
  174. STAssertFalse([action isRunning], nil);
  175. STAssertFalse([delegate wasSuccessful], nil);
  176. STAssertFalse([action wantsReboot], nil);
  177. STAssertEqualObjects([action returnCode], [NSNumber numberWithInt:11], nil);
  178. }
  179. - (void)testFailedDownload {
  180. id<KSCommandRunner> runner = [KSTaskCommandRunner commandRunner];
  181. STAssertNotNil(runner, nil);
  182. NSString *path = @"/path/to/fake/file/blah/blah/blah";
  183. NSURL *url = [NSURL fileURLWithPath:path];
  184. NSString *hash = @"zzz";
  185. NSString *name = [NSString stringWithFormat:@"KSUpdateActionUnitTest-%x",
  186. geteuid()];
  187. unsigned long long size = 1;
  188. KSUpdateInfo *info =
  189. [NSDictionary dictionaryWithObjectsAndKeys:
  190. name, kServerProductID,
  191. url, kServerCodebaseURL,
  192. [NSNumber numberWithInt:size], kServerCodeSize,
  193. hash, kServerCodeHash,
  194. nil];
  195. KSUpdateAction *action = nil;
  196. action = [KSUpdateAction actionWithUpdateInfo:info
  197. runner:runner
  198. userInitiated:NO];
  199. STAssertNotNil(action, nil);
  200. SuccessDelegate *delegate = [[[SuccessDelegate alloc] init] autorelease];
  201. // Create an action processor and run the action
  202. KSActionProcessor *ap = [[[KSActionProcessor alloc] initWithDelegate:delegate] autorelease];
  203. STAssertNotNil(ap, nil);
  204. [ap enqueueAction:action];
  205. [ap startProcessing];
  206. [self loopUntilDone:action];
  207. STAssertFalse([action isRunning], nil);
  208. STAssertFalse([delegate wasSuccessful], nil);
  209. STAssertFalse([action wantsReboot], nil);
  210. STAssertNil([action returnCode], nil);
  211. }
  212. // Be sure we implement the progress protocol
  213. - (void)runningAction:(KSUpdateAction *)action
  214. progress:(NSNumber *)progress {
  215. [progressArray_ addObject:progress];
  216. }
  217. @end