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

http://macfuse.googlecode.com/ · Objective C · 650 lines · 444 code · 144 blank · 62 comment · 10 complexity · 56407cf86f21cd61f8585ab50404e429 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 "KSUpdateEngine.h"
  16. #import "KSUpdateEngine+Configuration.h"
  17. #import "KSTicketStore.h"
  18. #import "KSTicket.h"
  19. #import "KSCommandRunner.h"
  20. #import "KSExistenceChecker.h"
  21. #import "KSUUID.h"
  22. #import "KSFrameworkStats.h"
  23. @interface KSUpdateEngineTest : SenTestCase {
  24. @private
  25. NSString *storePath_;
  26. NSURL *serverSuccessPlistURL_;
  27. NSURL *serverFailurePlistURL_;
  28. }
  29. @end
  30. @interface UpdateEngineDelegate : NSObject {
  31. @private
  32. BOOL finished_;
  33. BOOL updateFailed_;
  34. BOOL engineFailed_;
  35. NSMutableArray *progressArray_;
  36. }
  37. - (BOOL)isFinished;
  38. - (BOOL)updateFailed;
  39. - (BOOL)engineFailed;
  40. - (NSArray *)progressArray;
  41. @end
  42. @implementation UpdateEngineDelegate
  43. - (id)init {
  44. if ((self = [super init])) {
  45. progressArray_ = [[NSMutableArray array] retain];
  46. }
  47. return self;
  48. }
  49. - (void)dealloc {
  50. [progressArray_ release];
  51. [super dealloc];
  52. }
  53. - (BOOL)isFinished {
  54. return finished_;
  55. }
  56. - (BOOL)updateFailed{
  57. return updateFailed_;
  58. }
  59. - (BOOL)engineFailed {
  60. return engineFailed_;
  61. }
  62. - (id<KSCommandRunner>)commandRunnerForEngine:(KSUpdateEngine *)engine {
  63. return [KSTaskCommandRunner commandRunner];
  64. }
  65. - (void)engine:(KSUpdateEngine *)engine
  66. running:(KSUpdateInfo *)updateInfo
  67. progress:(NSNumber *)progress {
  68. [progressArray_ addObject:progress];
  69. }
  70. - (NSArray *)progressArray {
  71. return progressArray_;
  72. }
  73. - (void)engine:(KSUpdateEngine *)engine
  74. finished:(KSUpdateInfo *)updateInfo
  75. wasSuccess:(BOOL)wasSuccess
  76. wantsReboot:(BOOL)wantsReboot {
  77. if (wasSuccess == NO)
  78. updateFailed_ = YES;
  79. }
  80. - (void)engineFinished:(KSUpdateEngine *)engine wasSuccess:(BOOL)wasSuccess {
  81. finished_ = YES;
  82. engineFailed_ = !wasSuccess;
  83. }
  84. - (NSDictionary *)engine:(KSUpdateEngine *)engine
  85. statsForProductID:(NSString *)productID {
  86. return [NSDictionary dictionary];
  87. }
  88. @end // UpdateEngineDelegate
  89. // Helper class to serve as a KSUpdateEngine delegate and record all
  90. // the delegate methods that it receives.
  91. @interface CallbackTracker : NSObject {
  92. @private
  93. NSMutableArray *methods_;
  94. }
  95. - (NSArray *)methods;
  96. @end
  97. @implementation CallbackTracker
  98. - (id)init {
  99. if ((self = [super init]))
  100. methods_ = [[NSMutableArray alloc] init];
  101. return self;
  102. }
  103. - (void)dealloc {
  104. [methods_ release];
  105. [super dealloc];
  106. }
  107. - (NSArray *)methods {
  108. return methods_;
  109. }
  110. - (NSArray *)engine:(KSUpdateEngine *)engine
  111. shouldPrefetchProducts:(NSArray *)products {
  112. [methods_ addObject:NSStringFromSelector(_cmd)];
  113. return products;
  114. }
  115. - (NSArray *)engine:(KSUpdateEngine *)engine
  116. shouldSilentlyUpdateProducts:(NSArray *)products {
  117. [methods_ addObject:NSStringFromSelector(_cmd)];
  118. return products;
  119. }
  120. - (id<KSCommandRunner>)commandRunnerForEngine:(KSUpdateEngine *)engine {
  121. [methods_ addObject:NSStringFromSelector(_cmd)];
  122. return nil;
  123. }
  124. - (void)engine:(KSUpdateEngine *)engine
  125. starting:(KSUpdateInfo *)updateInfo {
  126. [methods_ addObject:NSStringFromSelector(_cmd)];
  127. }
  128. - (void)engine:(KSUpdateEngine *)engine
  129. finished:(KSUpdateInfo *)updateInfo
  130. wasSuccess:(BOOL)wasSuccess
  131. wantsReboot:(BOOL)wantsReboot {
  132. [methods_ addObject:NSStringFromSelector(_cmd)];
  133. }
  134. - (NSArray *)engine:(KSUpdateEngine *)engine
  135. shouldUpdateProducts:(NSArray *)products {
  136. [methods_ addObject:NSStringFromSelector(_cmd)];
  137. return products;
  138. }
  139. - (NSDictionary *)engine:(KSUpdateEngine *)engine
  140. statsForProductID:(NSString *)productID {
  141. [methods_ addObject:NSStringFromSelector(_cmd)];
  142. return nil; // Make sure a nil stat directory doesn't cause an exception.
  143. }
  144. @end // CallbackTracker
  145. // Non-public methods that we want to call for testing.
  146. @interface KSUpdateEngine (UpdateEngineFriend)
  147. - (void)processingStarted:(KSActionProcessor *)processor;
  148. - (void)processingStopped:(KSActionProcessor *)processor;
  149. @end
  150. // This delegate is bad because it throws an exception on every call. We throw
  151. // NSStrings instead of NSExceptions to make sure we don't accidentally assume
  152. // that NSExceptions are the only objects that can be thrown.
  153. @interface BadDelegate : NSObject
  154. // Nothing
  155. @end
  156. @implementation BadDelegate
  157. - (void)engineStarted:(KSUpdateEngine *)engine {
  158. @throw @"blah";
  159. }
  160. - (NSDictionary *)engine:(KSUpdateEngine *)engine
  161. statsForProductID:(NSString *)productID {
  162. @throw @"blah";
  163. }
  164. - (void)engineFinished:(KSUpdateEngine *)engine wasSuccess:(BOOL)wasSuccess {
  165. @throw @"blah";
  166. }
  167. - (NSArray *)engine:(KSUpdateEngine *)engine
  168. shouldPrefetchProducts:(NSArray *)products {
  169. @throw @"blah";
  170. }
  171. - (NSArray *)engine:(KSUpdateEngine *)engine
  172. shouldSilentlyUpdateProducts:(NSArray *)products {
  173. @throw @"blah";
  174. }
  175. - (id<KSCommandRunner>)commandRunnerForEngine:(KSUpdateEngine *)engine {
  176. @throw @"blah";
  177. }
  178. - (void)engine:(KSUpdateEngine *)engine
  179. starting:(KSUpdateInfo *)updateInfo {
  180. @throw @"blah";
  181. }
  182. - (void)engine:(KSUpdateEngine *)engine
  183. finished:(KSUpdateInfo *)updateInfo
  184. wasSuccess:(BOOL)wasSuccess
  185. wantsReboot:(BOOL)wantsReboot {
  186. @throw @"blah";
  187. }
  188. - (NSArray *)engine:(KSUpdateEngine *)engine
  189. shouldUpdateProducts:(NSArray *)products {
  190. @throw @"blah";
  191. }
  192. - (void)engine:(KSUpdateEngine *)engine
  193. running:(KSUpdateInfo *)updateInfo
  194. progress:(NSNumber *)progress {
  195. @throw @"blah";
  196. }
  197. @end // BadDelegate
  198. @implementation KSUpdateEngineTest
  199. - (void)setUp {
  200. // Generate a unique temp file name
  201. storePath_ = [[NSString stringWithFormat:@"/tmp/KSUpdateEngineTest.%@",
  202. [KSUUID uuidString]] retain];
  203. STAssertNotNil(storePath_, nil);
  204. NSBundle *mainBundle = [NSBundle bundleForClass:[self class]];
  205. // Get the path to a successful server plist response
  206. NSString *path = [mainBundle pathForResource:@"ServerSuccess"
  207. ofType:@"plist"];
  208. STAssertNotNil(path, nil);
  209. serverSuccessPlistURL_ = [[NSURL fileURLWithPath:path] retain];
  210. STAssertNotNil(serverSuccessPlistURL_, nil);
  211. // Copy the DMG referenced in the ServerSuccess.plist file to /tmp/
  212. NSString *dmg = [mainBundle pathForResource:@"Test-SUCCESS" ofType:@"dmg"];
  213. STAssertNotNil(path, nil);
  214. [[NSFileManager defaultManager] removeFileAtPath:@"/tmp/Test-SUCCESS.dmg"
  215. handler:nil];
  216. BOOL copied = [[NSFileManager defaultManager] copyPath:dmg
  217. toPath:@"/tmp/Test-SUCCESS.dmg"
  218. handler:nil];
  219. STAssertTrue(copied, nil);
  220. // Now, do the same thing for the "failure" XML and DMG
  221. path = [mainBundle pathForResource:@"ServerFailure" ofType:@"plist"];
  222. STAssertNotNil(path, nil);
  223. serverFailurePlistURL_ = [[NSURL fileURLWithPath:path] retain];
  224. STAssertNotNil(serverFailurePlistURL_, nil);
  225. dmg = [mainBundle pathForResource:@"Test-FAILURE" ofType:@"dmg"];
  226. STAssertNotNil(path, nil);
  227. [[NSFileManager defaultManager] removeFileAtPath:@"/tmp/Test-FAILURE.dmg" handler:nil];
  228. copied = [[NSFileManager defaultManager] copyPath:dmg
  229. toPath:@"/tmp/Test-FAILURE.dmg"
  230. handler:nil];
  231. STAssertTrue(copied, nil);
  232. [@"" writeToFile:storePath_ atomically:YES];
  233. [KSUpdateEngine setDefaultTicketStorePath:storePath_];
  234. }
  235. - (void)tearDown {
  236. [KSUpdateEngine setDefaultTicketStorePath:nil];
  237. [[NSFileManager defaultManager] removeFileAtPath:storePath_ handler:nil];
  238. NSString *lock = [storePath_ stringByAppendingPathExtension:@"lock"];
  239. [[NSFileManager defaultManager] removeFileAtPath:lock handler:nil];
  240. [[NSFileManager defaultManager] removeFileAtPath:@"/tmp/Test-SUCCESS.dmg" handler:nil];
  241. [[NSFileManager defaultManager] removeFileAtPath:@"/tmp/Test-FAILURE.dmg" handler:nil];
  242. [storePath_ release];
  243. [serverSuccessPlistURL_ release];
  244. [serverFailurePlistURL_ release];
  245. }
  246. - (void)loopUntilDone:(UpdateEngineDelegate *)delegate {
  247. int count = 50;
  248. while (![delegate isFinished] && (count > 0)) {
  249. [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.2]];
  250. count--;
  251. }
  252. STAssertTrue(count > 0, nil); // make sure we didn't time out
  253. }
  254. - (void)testCreation {
  255. KSUpdateEngine *engine = nil;
  256. engine = [[[KSUpdateEngine alloc] init] autorelease];
  257. STAssertNil(engine, nil);
  258. engine = [KSUpdateEngine engineWithDelegate:nil];
  259. STAssertNotNil(engine, nil);
  260. STAssertTrue([[engine description] length] > 1, nil);
  261. STAssertNotNil([engine ticketStore], nil);
  262. STAssertNil([engine delegate], nil);
  263. [engine setDelegate:@"not nil"];
  264. STAssertNotNil([engine delegate], nil);
  265. STAssertNil([engine statsCollection], nil);
  266. [KSUpdateEngine setDefaultTicketStorePath:nil]; // Reset to default
  267. NSString *defaultPath = [KSUpdateEngine defaultTicketStorePath];
  268. STAssertNil(defaultPath, nil);
  269. [KSUpdateEngine setDefaultTicketStorePath:@"foo"];
  270. STAssertEqualObjects([KSUpdateEngine defaultTicketStorePath],
  271. @"foo", nil);
  272. [KSUpdateEngine setDefaultTicketStorePath:nil]; // Reset to default
  273. STAssertEqualObjects([KSUpdateEngine defaultTicketStorePath],
  274. defaultPath, nil);
  275. }
  276. - (void)testDelegateCallbacks {
  277. CallbackTracker *tracker = [[[CallbackTracker alloc] init] autorelease];
  278. STAssertNotNil(tracker, nil);
  279. KSUpdateEngine *engine = [KSUpdateEngine engineWithDelegate:tracker];
  280. STAssertNotNil(engine, nil);
  281. STAssertNotNil([engine delegate], nil);
  282. STAssertEqualObjects([engine delegate], tracker, nil);
  283. // Call all the delegate methods.
  284. [engine action:nil shouldPrefetchProducts:nil];
  285. [engine action:nil shouldSilentlyUpdateProducts:nil];
  286. [engine commandRunnerForAction:nil];
  287. [engine action:nil shouldUpdateProducts:nil];
  288. [engine action:nil starting:nil];
  289. [engine action:nil finished:nil wasSuccess:NO wantsReboot:NO];
  290. NSArray *expect = [NSArray arrayWithObjects:
  291. @"engine:shouldPrefetchProducts:",
  292. @"engine:shouldSilentlyUpdateProducts:",
  293. @"commandRunnerForEngine:",
  294. @"engine:shouldUpdateProducts:",
  295. @"engine:starting:",
  296. @"engine:finished:wasSuccess:wantsReboot:",
  297. nil];
  298. STAssertEqualObjects([tracker methods], expect, nil);
  299. // Make sure that if the delegate does not respond to the
  300. // commandRunnerForEngine: selector, we get back a default
  301. // command runner.
  302. engine = [KSUpdateEngine engineWithDelegate:nil];
  303. id<KSCommandRunner> runner = [engine commandRunnerForAction:nil];
  304. STAssertNotNil(runner, nil);
  305. }
  306. - (void)testFailedUpdate {
  307. KSTicketStore *store = [KSTicketStore ticketStoreWithPath:storePath_];
  308. STAssertNotNil(store, nil);
  309. STAssertTrue([[store tickets] count] == 0, nil);
  310. KSExistenceChecker *xc = [KSPathExistenceChecker checkerWithPath:@"/"];
  311. KSTicket *t = [KSTicket ticketWithProductID:@"COM.GOOGLE.UPDATEENGINE.KSUPDATEENGINE_TEST"
  312. version:@"1.0"
  313. existenceChecker:xc
  314. serverURL:serverFailurePlistURL_];
  315. STAssertTrue([store storeTicket:t], nil);
  316. UpdateEngineDelegate *delegate = [[[UpdateEngineDelegate alloc] init] autorelease];
  317. KSUpdateEngine *engine = nil;
  318. engine = [KSUpdateEngine engineWithTicketStore:store delegate:delegate];
  319. STAssertNotNil(engine, nil);
  320. KSStatsCollection *stats = [KSStatsCollection statsCollectionWithPath:@"/dev/null"
  321. autoSynchronize:NO];
  322. STAssertTrue([stats count] == 0, nil);
  323. [engine setStatsCollection:stats];
  324. [engine updateAllProducts];
  325. [self loopUntilDone:delegate];
  326. STAssertFalse([engine isUpdating], nil);
  327. // Make sure the update failed
  328. STAssertTrue([delegate updateFailed], nil);
  329. // But UpdateEngine as a whole should have succeeded
  330. STAssertFalse([delegate engineFailed], nil);
  331. STAssertTrue([stats count] > 0, nil);
  332. [engine setStatsCollection:nil];
  333. // Verify that a few stats are present and accurate.
  334. STAssertEqualObjects([stats numberForStat:kStatChecks], [NSNumber numberWithInt:1], nil);
  335. STAssertEqualObjects([stats numberForStat:kStatDownloads], [NSNumber numberWithInt:1], nil);
  336. STAssertEqualObjects([stats numberForStat:kStatTickets], [NSNumber numberWithInt:1], nil);
  337. STAssertEqualObjects([stats numberForStat:kStatValidTickets], [NSNumber numberWithInt:1], nil);
  338. NSString *statKey = KSMakeProductStatKey(@"COM.GOOGLE.UPDATEENGINE.KSUPDATEENGINE_TEST", kStatInstallRC);
  339. STAssertEqualObjects([stats numberForStat:statKey], [NSNumber numberWithInt:11], nil);
  340. }
  341. - (void)testUpdateFromGoodURL {
  342. KSTicketStore *store = [KSTicketStore ticketStoreWithPath:storePath_];
  343. STAssertNotNil(store, nil);
  344. KSExistenceChecker *xc = [KSPathExistenceChecker checkerWithPath:@"/"];
  345. KSTicket *t = [KSTicket ticketWithProductID:@"COM.GOOGLE.UPDATEENGINE.KSUPDATEENGINE_TEST"
  346. version:@"1.0"
  347. existenceChecker:xc
  348. serverURL:serverSuccessPlistURL_];
  349. STAssertTrue([store storeTicket:t], nil);
  350. UpdateEngineDelegate *delegate = [[[UpdateEngineDelegate alloc] init] autorelease];
  351. KSUpdateEngine *engine = nil;
  352. engine = [KSUpdateEngine engineWithTicketStore:store delegate:delegate];
  353. STAssertNotNil(engine, nil);
  354. KSStatsCollection *stats = [KSStatsCollection statsCollectionWithPath:@"/dev/null"
  355. autoSynchronize:NO];
  356. [engine setStatsCollection:stats];
  357. [engine updateAllProducts];
  358. [self loopUntilDone:delegate];
  359. STAssertFalse([engine isUpdating], nil);
  360. // Make sure the update succeeded
  361. STAssertFalse([delegate updateFailed], nil);
  362. // And that UpdateEngine as a whole succeeded
  363. STAssertFalse([delegate engineFailed], nil);
  364. // And that we got legit progress:
  365. NSArray *progress = [delegate progressArray];
  366. STAssertTrue([progress count] >= 2, nil);
  367. // No guarantees about these two but they just make sense
  368. STAssertTrue([[progress objectAtIndex:0]
  369. isEqual:[NSNumber numberWithFloat:0.0]], nil);
  370. STAssertTrue([[progress lastObject]
  371. isEqual:[NSNumber numberWithFloat:1.0]], nil);
  372. // Make sure progress never goes backwards
  373. float f = 0.0;
  374. NSEnumerator *aenum = [progress objectEnumerator];
  375. NSNumber *num = nil;
  376. while ((num = [aenum nextObject]) != nil) {
  377. STAssertTrue([num floatValue] >= f, nil);
  378. f = [num floatValue];
  379. }
  380. STAssertTrue([stats count] > 0, nil);
  381. [engine setStatsCollection:nil];
  382. // Verify that a few stats are present and accurate.
  383. STAssertEqualObjects([stats numberForStat:kStatChecks], [NSNumber numberWithInt:1], nil);
  384. STAssertEqualObjects([stats numberForStat:kStatDownloads], [NSNumber numberWithInt:1], nil);
  385. STAssertEqualObjects([stats numberForStat:kStatTickets], [NSNumber numberWithInt:1], nil);
  386. STAssertEqualObjects([stats numberForStat:kStatValidTickets], [NSNumber numberWithInt:1], nil);
  387. NSString *statKey = KSMakeProductStatKey(@"COM.GOOGLE.UPDATEENGINE.KSUPDATEENGINE_TEST", kStatInstallRC);
  388. STAssertEqualObjects([stats numberForStat:statKey], [NSNumber numberWithInt:0], nil);
  389. //
  390. // Make sure we can update a single product ID
  391. //
  392. delegate = [[[UpdateEngineDelegate alloc] init] autorelease];
  393. [engine setDelegate:delegate];
  394. [engine updateProductWithProductID:@"COM.GOOGLE.UPDATEENGINE.KSUPDATEENGINE_TEST"];
  395. [self loopUntilDone:delegate];
  396. STAssertFalse([engine isUpdating], nil);
  397. // Make sure the update succeeded
  398. STAssertFalse([delegate updateFailed], nil);
  399. // And that UpdateEngine as a whole succeeded
  400. STAssertFalse([delegate engineFailed], nil);
  401. }
  402. - (void)testFailedCheck {
  403. KSTicketStore *store = [KSTicketStore ticketStoreWithPath:storePath_];
  404. STAssertNotNil(store, nil);
  405. //
  406. // First test using 1 ticket with an unreachable URL
  407. //
  408. KSExistenceChecker *xc = [KSPathExistenceChecker checkerWithPath:@"/"];
  409. KSTicket *t = [KSTicket ticketWithProductID:@"com.google.foo"
  410. version:@"1.0"
  411. existenceChecker:xc
  412. serverURL:[NSURL URLWithString:@"https://asdfasdf.tools.google.com"]];
  413. STAssertTrue([store storeTicket:t], nil);
  414. UpdateEngineDelegate *delegate = [[[UpdateEngineDelegate alloc] init] autorelease];
  415. KSUpdateEngine *engine = nil;
  416. engine = [KSUpdateEngine engineWithTicketStore:store delegate:delegate];
  417. STAssertNotNil(engine, nil);
  418. [engine updateAllProducts];
  419. [self loopUntilDone:delegate];
  420. STAssertFalse([engine isUpdating], nil);
  421. // But UpdateEngine as a whole should have succeeded
  422. STAssertTrue([delegate engineFailed], nil);
  423. //
  424. // Second, test with multiple tickets with an unreachable URL
  425. //
  426. t = [KSTicket ticketWithProductID:@"com.google.foo1"
  427. version:@"1.0"
  428. existenceChecker:xc
  429. serverURL:[NSURL URLWithString:@"https://zas4zf4.tools.google.com"]];
  430. STAssertTrue([store storeTicket:t], nil);
  431. delegate = [[[UpdateEngineDelegate alloc] init] autorelease];
  432. engine = [KSUpdateEngine engineWithTicketStore:store delegate:delegate];
  433. STAssertNotNil(engine, nil);
  434. [engine updateAllProducts];
  435. [self loopUntilDone:delegate];
  436. STAssertFalse([engine isUpdating], nil);
  437. // But UpdateEngine as a whole should have succeeded
  438. STAssertTrue([delegate engineFailed], nil);
  439. //
  440. // Third, add one ticket with a GOOD URL, and the check should succeed.
  441. //
  442. t = [KSTicket ticketWithProductID:@"com.google.foo2"
  443. version:@"1.0"
  444. existenceChecker:xc
  445. serverURL:[NSURL URLWithString:@"file:///etc/passwd"]];
  446. STAssertTrue([store storeTicket:t], nil);
  447. delegate = [[[UpdateEngineDelegate alloc] init] autorelease];
  448. engine = [KSUpdateEngine engineWithTicketStore:store delegate:delegate];
  449. STAssertNotNil(engine, nil);
  450. [engine updateAllProducts];
  451. [self loopUntilDone:delegate];
  452. STAssertFalse([engine isUpdating], nil);
  453. //
  454. // Fourth, try updating a product with no corresponding ticket.
  455. //
  456. [engine updateProductWithProductID:@"lotus blossom"];
  457. // But UpdateEngine as a whole should have succeeded
  458. STAssertFalse([delegate engineFailed], nil); // <-- This is the diff
  459. }
  460. - (void)testWithBadDelegate {
  461. KSTicketStore *store = [KSTicketStore ticketStoreWithPath:storePath_];
  462. STAssertNotNil(store, nil);
  463. KSExistenceChecker *xc = [KSPathExistenceChecker checkerWithPath:@"/"];
  464. // Make sure there's at least one ticket, so that the statsForProductID:
  465. // delegate will be called.
  466. KSTicket *t;
  467. t = [KSTicket ticketWithProductID:@"com.google.foo3"
  468. version:@"1.0"
  469. existenceChecker:xc
  470. serverURL:[NSURL URLWithString:@"file:///etc/passwd"]];
  471. STAssertTrue([store storeTicket:t], nil);
  472. BadDelegate *delegate = [[[BadDelegate alloc] init] autorelease];
  473. KSUpdateEngine *engine =
  474. [KSUpdateEngine engineWithTicketStore:store delegate:delegate];
  475. STAssertNotNil(engine, nil);
  476. [engine processingStarted:nil];
  477. [engine processingStopped:nil];
  478. [engine updateAllProducts];
  479. // Call all the delegate methods.
  480. NSArray *products = [NSArray array];
  481. STAssertEqualObjects([engine action:nil shouldPrefetchProducts:products],
  482. products, nil);
  483. STAssertEqualObjects([engine action:nil shouldSilentlyUpdateProducts:products],
  484. products, nil);
  485. STAssertNil([engine commandRunnerForAction:nil], nil);
  486. STAssertEqualObjects([engine action:nil shouldUpdateProducts:nil],
  487. nil, nil);
  488. // void returns
  489. [engine action:nil starting:nil];
  490. [engine action:nil finished:nil wasSuccess:NO wantsReboot:NO];
  491. [engine action:nil running:nil progress:nil];
  492. // Simply make sure we got this far w/o letting an exception through
  493. STAssertTrue(YES, nil);
  494. }
  495. - (void)testParams {
  496. KSTicketStore *store = [KSTicketStore ticketStoreWithPath:storePath_];
  497. KSUpdateEngine *engine = [KSUpdateEngine engineWithTicketStore:store
  498. delegate:nil];
  499. NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:
  500. @"oop", @"ack",
  501. @"bill th", @"e cat", nil];
  502. [engine setParams:params];
  503. NSDictionary *engineParams = [engine valueForKey:@"params_"];
  504. STAssertTrue([params isEqualToDictionary:engineParams], nil);
  505. }
  506. @end