1 /* 2 * Copyright (C) 2010 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 33 #include "TestShell.h" 34 #include "WebThemeEngineDRTMac.h" 35 #include "webkit/support/webkit_support.h" 36 #import <AppKit/AppKit.h> 37 38 static WebThemeEngineDRTMac themeEngine; 39 40 // A class to be the target/selector of the "watchdog" thread that ensures 41 // pages timeout if they take too long and tells the test harness via stdout. 42 @interface WatchDogTarget : NSObject { 43 @private 44 NSTimeInterval _timeout; 45 } 46 // |timeout| is in seconds 47 - (id)initWithTimeout:(NSTimeInterval)timeout; 48 // serves as the "run" method of a NSThread. 49 - (void)run:(id)sender; 50 @end 51 52 @implementation WatchDogTarget 53 54 - (id)initWithTimeout:(NSTimeInterval)timeout 55 { 56 if ((self = [super init])) 57 _timeout = timeout; 58 return self; 59 } 60 61 - (void)run:(id)ignore 62 { 63 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 64 65 // check for debugger, just bail if so. We don't want the timeouts hitting 66 // when we're trying to track down an issue. 67 if (webkit_support::BeingDebugged()) 68 return; 69 70 NSThread* currentThread = [NSThread currentThread]; 71 72 // Wait to be cancelled. If we are that means the test finished. If it hasn't, 73 // then we need to tell the layout script we timed out and start again. 74 NSDate* limitDate = [NSDate dateWithTimeIntervalSinceNow:_timeout]; 75 while ([(NSDate*)[NSDate date] compare:limitDate] == NSOrderedAscending && 76 ![currentThread isCancelled]) { 77 // sleep for a small increment then check again 78 NSDate* incrementDate = [NSDate dateWithTimeIntervalSinceNow:1.0]; 79 [NSThread sleepUntilDate:incrementDate]; 80 } 81 if (![currentThread isCancelled]) { 82 // Print a warning to be caught by the layout-test script. 83 // Note: the layout test driver may or may not recognize 84 // this as a timeout. 85 puts("#TEST_TIMED_OUT\n"); 86 puts("#EOF\n"); 87 fflush(stdout); 88 exit(0); 89 } 90 91 [pool release]; 92 } 93 94 @end 95 96 void TestShell::waitTestFinished() 97 { 98 ASSERT(!m_testIsPending); 99 100 m_testIsPending = true; 101 102 // Create a watchdog thread which just sets a timer and 103 // kills the process if it times out. This catches really 104 // bad hangs where the shell isn't coming back to the 105 // message loop. If the watchdog is what catches a 106 // timeout, it can't do anything except terminate the test 107 // shell, which is unfortunate. 108 // Windows multiplies by 2.5, but that causes us to run for far, far too 109 // long. We use the passed value and let the scripts flag override 110 // the value as needed. 111 NSTimeInterval timeoutSeconds = layoutTestTimeoutForWatchDog() / 1000; 112 WatchDogTarget* watchdog = [[[WatchDogTarget alloc] 113 initWithTimeout:timeoutSeconds] autorelease]; 114 NSThread* thread = [[NSThread alloc] initWithTarget:watchdog 115 selector:@selector(run:) 116 object:nil]; 117 [thread start]; 118 119 // TestFinished() will post a quit message to break this loop when the page 120 // finishes loading. 121 while (m_testIsPending) 122 webkit_support::RunMessageLoop(); 123 124 // Tell the watchdog that we're finished. No point waiting to re-join, it'll 125 // die on its own. 126 [thread cancel]; 127 [thread release]; 128 } 129 130 void platformInit(int*, char***) 131 { 132 webkit_support::SetThemeEngine(&themeEngine); 133 } 134 135 void openStartupDialog() 136 { 137 // FIXME: This code doesn't work. Need NSApplication event loop? 138 NSAlert* alert = [[[NSAlert alloc] init] autorelease]; 139 alert.messageText = @"Attach to me?"; 140 alert.informativeText = @"This would probably be a good time to attach your debugger."; 141 [alert addButtonWithTitle:@"OK"]; 142 [alert runModal]; 143 } 144 145 bool checkLayoutTestSystemDependencies() 146 { 147 return true; 148 } 149 150