Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(508)

Side by Side Diff: testing/iossim/iossim.mm

Issue 23460032: Add support in iossim for recognizing sandboxed system logs. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import <Foundation/Foundation.h> 5 #import <Foundation/Foundation.h>
6 #include <asl.h> 6 #include <asl.h>
7 #include <libgen.h> 7 #include <libgen.h>
8 #include <stdarg.h> 8 #include <stdarg.h>
9 #include <stdio.h> 9 #include <stdio.h>
10 10
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
121 } 121 }
122 122
123 } // namespace 123 } // namespace
124 124
125 // A delegate that is called when the simulated app is started or ended in the 125 // A delegate that is called when the simulated app is started or ended in the
126 // simulator. 126 // simulator.
127 @interface SimulatorDelegate : NSObject <DTiPhoneSimulatorSessionDelegate> { 127 @interface SimulatorDelegate : NSObject <DTiPhoneSimulatorSessionDelegate> {
128 @private 128 @private
129 NSString* stdioPath_; 129 NSString* stdioPath_;
130 NSString* developerDir_; 130 NSString* developerDir_;
131 NSString* simulatorHome_;
131 NSThread* outputThread_; 132 NSThread* outputThread_;
132 NSBundle* simulatorBundle_; 133 NSBundle* simulatorBundle_;
133 BOOL appRunning_; 134 BOOL appRunning_;
134 } 135 }
135 @end 136 @end
136 137
137 // An implementation that copies the simulated app's stdio to stdout of this 138 // An implementation that copies the simulated app's stdio to stdout of this
138 // executable. While it would be nice to get stdout and stderr independently 139 // executable. While it would be nice to get stdout and stderr independently
139 // from iOS Simulator, issues like I/O buffering and interleaved output 140 // from iOS Simulator, issues like I/O buffering and interleaved output
140 // between iOS Simulator and the app would cause iossim to display things out 141 // between iOS Simulator and the app would cause iossim to display things out
141 // of order here. Printing all output to a single file keeps the order correct. 142 // of order here. Printing all output to a single file keeps the order correct.
142 // Instances of this classe should be initialized with the location of the 143 // Instances of this classe should be initialized with the location of the
143 // simulated app's output file. When the simulated app starts, a thread is 144 // simulated app's output file. When the simulated app starts, a thread is
144 // started which handles copying data from the simulated app's output file to 145 // started which handles copying data from the simulated app's output file to
145 // the stdout of this executable. 146 // the stdout of this executable.
146 @implementation SimulatorDelegate 147 @implementation SimulatorDelegate
147 148
148 // Specifies the file locations of the simulated app's stdout and stderr. 149 // Specifies the file locations of the simulated app's stdout and stderr.
149 - (SimulatorDelegate*)initWithStdioPath:(NSString*)stdioPath 150 - (SimulatorDelegate*)initWithStdioPath:(NSString*)stdioPath
150 developerDir:(NSString*)developerDir { 151 developerDir:(NSString*)developerDir
152 simulatorHome:(NSString*)simulatorHome {
151 self = [super init]; 153 self = [super init];
152 if (self) { 154 if (self) {
153 stdioPath_ = [stdioPath copy]; 155 stdioPath_ = [stdioPath copy];
154 developerDir_ = [developerDir copy]; 156 developerDir_ = [developerDir copy];
157 simulatorHome_ = [simulatorHome copy];
155 } 158 }
156 159
157 return self; 160 return self;
158 } 161 }
159 162
160 - (void)dealloc { 163 - (void)dealloc {
161 [stdioPath_ release]; 164 [stdioPath_ release];
162 [developerDir_ release]; 165 [developerDir_ release];
163 [simulatorBundle_ release]; 166 [simulatorBundle_ release];
164 [super dealloc]; 167 [super dealloc];
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 localizedDescription, [error domain], 276 localizedDescription, [error domain],
274 static_cast<long int>([error code])); 277 static_cast<long int>([error code]));
275 } else { 278 } else {
276 LogError(@"Simulator ended with error: \"%@\" (%@:%ld)", 279 LogError(@"Simulator ended with error: \"%@\" (%@:%ld)",
277 localizedDescription, [error domain], 280 localizedDescription, [error domain],
278 static_cast<long int>([error code])); 281 static_cast<long int>([error code]));
279 exit(kExitFailure); 282 exit(kExitFailure);
280 } 283 }
281 } 284 }
282 285
283 // Check if the simulated app exited abnormally by looking for system log 286 // Try to determine if the simulated app crashed or quit with a non-zero
284 // messages from launchd that refer to the simulated app's PID. Limit query 287 // status code. iOS Simluator handles things a bit differently depending on
285 // to messages in the last minute since PIDs are cyclical. 288 // the version, so first determine the iOS version being used.
286 aslmsg query = asl_new(ASL_TYPE_QUERY); 289 BOOL badEntryFound = NO;
287 asl_set_query(query, ASL_KEY_SENDER, "launchd", 290 NSString* versionString =
288 ASL_QUERY_OP_EQUAL | ASL_QUERY_OP_SUBSTRING); 291 [[[session sessionConfig] simulatedSystemRoot] sdkVersion];
289 asl_set_query(query, ASL_KEY_REF_PID, 292 NSInteger majorVersion = [[versionString substringToIndex:
290 [[[session simulatedApplicationPID] stringValue] UTF8String], 293 [versionString rangeOfString:@"."].location] intValue];
TVL 2013/09/12 13:56:08 [[[versionString componentsSeparatedByString:@"."]
lliabraa 2013/09/12 16:11:55 hmm..my compiler didn't like firstObject (and I do
TVL 2013/09/12 16:36:44 Ah, you must be using a mac sdk without it protoyp
291 ASL_QUERY_OP_EQUAL); 294 if (majorVersion <= 6) {
292 asl_set_query(query, ASL_KEY_TIME, "-1m", ASL_QUERY_OP_GREATER_EQUAL); 295 // In iOS 6 and before, logging from the simulated apps went to the main
296 // system logs, so use ASL to check if the simulated app exited abnormally
297 // by looking for system log messages from launchd that refer to the
298 // simulated app's PID. Limit query to messages in the last minute since
299 // PIDs are cyclical.
300 aslmsg query = asl_new(ASL_TYPE_QUERY);
301 asl_set_query(query, ASL_KEY_SENDER, "launchd",
302 ASL_QUERY_OP_EQUAL | ASL_QUERY_OP_SUBSTRING);
303 asl_set_query(query, ASL_KEY_REF_PID,
304 [[[session simulatedApplicationPID] stringValue] UTF8String],
305 ASL_QUERY_OP_EQUAL);
306 asl_set_query(query, ASL_KEY_TIME, "-1m", ASL_QUERY_OP_GREATER_EQUAL);
293 307
294 // Log any messages found, and take note of any messages that may indicate the 308 // Log any messages found, and take note of any messages that may indicate
295 // app crashed or did not exit cleanly. 309 // the app crashed or did not exit cleanly.
296 aslresponse response = asl_search(NULL, query); 310 aslresponse response = asl_search(NULL, query);
297 BOOL badEntryFound = NO; 311 aslmsg entry;
298 aslmsg entry; 312 while ((entry = aslresponse_next(response)) != NULL) {
299 while ((entry = aslresponse_next(response)) != NULL) { 313 const char* message = asl_get(entry, ASL_KEY_MSG);
300 const char* message = asl_get(entry, ASL_KEY_MSG); 314 LogWarning(@"Console message: %s", message);
301 LogWarning(@"Console message: %s", message); 315 // Some messages are harmless, so don't trigger a failure for them.
302 // Some messages are harmless, so don't trigger a failure for them. 316 if (strstr(message, "The following job tried to hijack the service"))
303 if (strstr(message, "The following job tried to hijack the service")) 317 continue;
304 continue; 318 badEntryFound = YES;
305 badEntryFound = YES; 319 }
320 } else {
321 // Otherwise, the iOS Simulator's system logging is sandboxed, so parse the
322 // sandboxed system.log file for known errors.
323 NSString* relativePathToSystemLog =
324 [NSString stringWithFormat:
325 @"Library/Logs/iOS Simulator/%@/system.log", versionString];
326 NSString* path =
327 [simulatorHome_ stringByAppendingPathComponent:relativePathToSystemLog];
328 NSString* content = [NSString stringWithContentsOfFile:path
329 encoding:NSUTF8StringEncoding
330 error:NULL];
331 NSArray* lines = [content componentsSeparatedByCharactersInSet:
332 [NSCharacterSet newlineCharacterSet]];
333 for (NSString* line in lines) {
TVL 2013/09/12 13:56:08 You have no checks here for if the file doesn't ex
lliabraa 2013/09/12 16:11:55 Done.
334 NSString* const kErrorString = @"Service exited with abnormal code:";
335 if ([line rangeOfString:kErrorString].location != NSNotFound) {
336 LogWarning(@"Console message: %@", line);
337 badEntryFound = YES;
338 break;
339 }
340 }
341 // Remove the log file so subsequent invocations of iossim won't be looking
342 // at stale logs.
343 remove([path UTF8String]);
TVL 2013/09/12 13:56:08 [path fileSystemRepresentation] (but we probably h
lliabraa 2013/09/12 16:11:55 Done.
306 } 344 }
307 345
308 // If the query returned any nasty-looking results, iossim should exit with 346 // If the query returned any nasty-looking results, iossim should exit with
309 // non-zero status. 347 // non-zero status.
310 if (badEntryFound) { 348 if (badEntryFound) {
311 LogError(@"Simulated app crashed or exited with non-zero status"); 349 LogError(@"Simulated app crashed or exited with non-zero status");
312 exit(kExitAppCrashed); 350 exit(kExitAppCrashed);
313 } 351 }
314 exit(kExitSuccess); 352 exit(kExitSuccess);
315 } 353 }
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after
693 // Create the config and simulator session. 731 // Create the config and simulator session.
694 DTiPhoneSimulatorSessionConfig* config = BuildSessionConfig(appSpec, 732 DTiPhoneSimulatorSessionConfig* config = BuildSessionConfig(appSpec,
695 systemRoot, 733 systemRoot,
696 stdioPath, 734 stdioPath,
697 stdioPath, 735 stdioPath,
698 appArgs, 736 appArgs,
699 appEnv, 737 appEnv,
700 deviceFamily); 738 deviceFamily);
701 SimulatorDelegate* delegate = 739 SimulatorDelegate* delegate =
702 [[[SimulatorDelegate alloc] initWithStdioPath:stdioPath 740 [[[SimulatorDelegate alloc] initWithStdioPath:stdioPath
703 developerDir:developerDir] autorelease]; 741 developerDir:developerDir
742 simulatorHome:simHomePath] autorelease];
704 DTiPhoneSimulatorSession* session = BuildSession(delegate); 743 DTiPhoneSimulatorSession* session = BuildSession(delegate);
705 744
706 // Start the simulator session. 745 // Start the simulator session.
707 NSError* error; 746 NSError* error;
708 BOOL started = [session requestStartWithConfig:config 747 BOOL started = [session requestStartWithConfig:config
709 timeout:sessionStartTimeout 748 timeout:sessionStartTimeout
710 error:&error]; 749 error:&error];
711 750
712 // Spin the runtime indefinitely. When the delegate gets the message that the 751 // Spin the runtime indefinitely. When the delegate gets the message that the
713 // app has quit it will exit this program. 752 // app has quit it will exit this program.
714 if (started) { 753 if (started) {
715 [[NSRunLoop mainRunLoop] run]; 754 [[NSRunLoop mainRunLoop] run];
716 } else { 755 } else {
717 LogError(@"Simulator failed request to start: \"%@\" (%@:%ld)", 756 LogError(@"Simulator failed request to start: \"%@\" (%@:%ld)",
718 [error localizedDescription], 757 [error localizedDescription],
719 [error domain], static_cast<long int>([error code])); 758 [error domain], static_cast<long int>([error code]));
720 } 759 }
721 760
722 // Note that this code is only executed if the simulator fails to start 761 // Note that this code is only executed if the simulator fails to start
723 // because once the main run loop is started, only the delegate calling 762 // because once the main run loop is started, only the delegate calling
724 // exit() will end the program. 763 // exit() will end the program.
725 [pool drain]; 764 [pool drain];
726 return kExitFailure; 765 return kExitFailure;
727 } 766 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698