2007-11-21 Eric Seidel <eric@webkit.org>
authoreric@webkit.org <eric@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 Nov 2007 04:03:18 +0000 (04:03 +0000)
committereric@webkit.org <eric@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 Nov 2007 04:03:18 +0000 (04:03 +0000)
        Reviewed by Tim Hatcher.

        Break out more of DumpRenderTree.mm into individual files

        * DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj:
        * DumpRenderTree/mac/CheckedMalloc.cpp: Added.
        (checkedMalloc):
        (checkedRealloc):
        (makeLargeMallocFailSilently):
        * DumpRenderTree/mac/CheckedMalloc.h: Added.
        * DumpRenderTree/mac/DumpRenderTree.mm:
        (crashHandler):
        (dump):
        * DumpRenderTree/mac/DumpRenderTreeMac.h:
        * DumpRenderTree/mac/DumpRenderTreePasteboard.h:
        * DumpRenderTree/mac/DumpRenderTreePasteboard.m:
        * DumpRenderTree/mac/DumpRenderTreeWindow.h:
        * DumpRenderTree/mac/DumpRenderTreeWindow.mm:
        * DumpRenderTree/mac/JavaScriptThreading.cpp: Added.
        (javaScriptThreads):
        (runJavaScriptThread):
        (startJavaScriptThreads):
        (stopJavaScriptThreads):
        * DumpRenderTree/mac/JavaScriptThreading.h: Added.
        * DumpRenderTree/mac/PixelDumpSupport.h: Added.
        * DumpRenderTree/mac/PixelDumpSupport.mm: Added.
        (restoreColorSpace):
        (setDefaultColorProfileToRGB):
        (initializeColorSpaceAndScreeBufferForPixelTests):
        (md5HashStringForBitmap):
        (dumpWebViewAsPixelsAndCompareWithExpected):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@27949 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
WebKitTools/ChangeLog
WebKitTools/DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj
WebKitTools/DumpRenderTree/mac/CheckedMalloc.cpp [new file with mode: 0644]
WebKitTools/DumpRenderTree/mac/CheckedMalloc.h [new file with mode: 0644]
WebKitTools/DumpRenderTree/mac/DumpRenderTree.mm
WebKitTools/DumpRenderTree/mac/DumpRenderTreeMac.h
WebKitTools/DumpRenderTree/mac/DumpRenderTreePasteboard.h
WebKitTools/DumpRenderTree/mac/DumpRenderTreePasteboard.m
WebKitTools/DumpRenderTree/mac/DumpRenderTreeWindow.h
WebKitTools/DumpRenderTree/mac/DumpRenderTreeWindow.mm
WebKitTools/DumpRenderTree/mac/JavaScriptThreading.cpp [new file with mode: 0644]
WebKitTools/DumpRenderTree/mac/JavaScriptThreading.h [new file with mode: 0644]
WebKitTools/DumpRenderTree/mac/PixelDumpSupport.h [new file with mode: 0644]
WebKitTools/DumpRenderTree/mac/PixelDumpSupport.mm [new file with mode: 0644]

index 9108e507796dc7e805fc483ec493f4dfc0f5a0bc..e0f2b40780e025f9519307513d75d3db9c5ee36b 100644 (file)
@@ -1,3 +1,37 @@
+2007-11-21  Eric Seidel  <eric@webkit.org>
+
+        Reviewed by Tim Hatcher.
+
+        Break out more of DumpRenderTree.mm into individual files
+
+        * DumpRenderTree/DumpRenderTree.xcodeproj/project.pbxproj:
+        * DumpRenderTree/mac/CheckedMalloc.cpp: Added.
+        (checkedMalloc):
+        (checkedRealloc):
+        (makeLargeMallocFailSilently):
+        * DumpRenderTree/mac/CheckedMalloc.h: Added.
+        * DumpRenderTree/mac/DumpRenderTree.mm:
+        (crashHandler):
+        (dump):
+        * DumpRenderTree/mac/DumpRenderTreeMac.h:
+        * DumpRenderTree/mac/DumpRenderTreePasteboard.h:
+        * DumpRenderTree/mac/DumpRenderTreePasteboard.m:
+        * DumpRenderTree/mac/DumpRenderTreeWindow.h:
+        * DumpRenderTree/mac/DumpRenderTreeWindow.mm:
+        * DumpRenderTree/mac/JavaScriptThreading.cpp: Added.
+        (javaScriptThreads):
+        (runJavaScriptThread):
+        (startJavaScriptThreads):
+        (stopJavaScriptThreads):
+        * DumpRenderTree/mac/JavaScriptThreading.h: Added.
+        * DumpRenderTree/mac/PixelDumpSupport.h: Added.
+        * DumpRenderTree/mac/PixelDumpSupport.mm: Added.
+        (restoreColorSpace):
+        (setDefaultColorProfileToRGB):
+        (initializeColorSpaceAndScreeBufferForPixelTests):
+        (md5HashStringForBitmap):
+        (dumpWebViewAsPixelsAndCompareWithExpected):
+
 2007-11-21  Kevin Ollivier  <kevino@theolliviers.com>
 
         Move install-unix-extras to wx directory as it seems only to be used by that 
index 8b55f593aa88ca5922bd473d8387520aeab5cc66..4eb75f5a64b55f79b679ce5e948801ff44658b67 100644 (file)
                A8B91ADC0CF3B32F008F91FF /* DumpRenderTreeWindow.mm in Sources */ = {isa = PBXBuildFile; fileRef = A8B91AD90CF3B32F008F91FF /* DumpRenderTreeWindow.mm */; };
                A8B91AE00CF3B372008F91FF /* DumpRenderTreeWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = A8B91ADD0CF3B372008F91FF /* DumpRenderTreeWindow.h */; };
                A8B91AE20CF3B372008F91FF /* DumpRenderTreePasteboard.h in Headers */ = {isa = PBXBuildFile; fileRef = A8B91ADF0CF3B372008F91FF /* DumpRenderTreePasteboard.h */; };
+               A8B91BFA0CF522B4008F91FF /* PixelDumpSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = A8B91BF40CF522B4008F91FF /* PixelDumpSupport.h */; };
+               A8B91BFB0CF522B4008F91FF /* JavaScriptThreading.h in Headers */ = {isa = PBXBuildFile; fileRef = A8B91BF50CF522B4008F91FF /* JavaScriptThreading.h */; };
+               A8B91BFC0CF522B4008F91FF /* PixelDumpSupport.mm in Sources */ = {isa = PBXBuildFile; fileRef = A8B91BF60CF522B4008F91FF /* PixelDumpSupport.mm */; settings = {COMPILER_FLAGS = "-Wno-deprecated-declarations"; }; };
+               A8B91BFD0CF522B4008F91FF /* CheckedMalloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8B91BF70CF522B4008F91FF /* CheckedMalloc.cpp */; };
+               A8B91BFE0CF522B4008F91FF /* JavaScriptThreading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8B91BF80CF522B4008F91FF /* JavaScriptThreading.cpp */; };
+               A8B91BFF0CF522B4008F91FF /* CheckedMalloc.h in Headers */ = {isa = PBXBuildFile; fileRef = A8B91BF90CF522B4008F91FF /* CheckedMalloc.h */; };
                AE8259F308D22463000507AB /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AE8257EF08D22389000507AB /* Carbon.framework */; };
                AE8259F408D22463000507AB /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AE8257EF08D22389000507AB /* Carbon.framework */; };
                B5A752A208AF5D1F00138E45 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5A752A108AF5D1F00138E45 /* QuartzCore.framework */; };
                A8B91AD90CF3B32F008F91FF /* DumpRenderTreeWindow.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = DumpRenderTreeWindow.mm; path = mac/DumpRenderTreeWindow.mm; sourceTree = "<group>"; };
                A8B91ADD0CF3B372008F91FF /* DumpRenderTreeWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DumpRenderTreeWindow.h; path = mac/DumpRenderTreeWindow.h; sourceTree = "<group>"; };
                A8B91ADF0CF3B372008F91FF /* DumpRenderTreePasteboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DumpRenderTreePasteboard.h; path = mac/DumpRenderTreePasteboard.h; sourceTree = "<group>"; };
+               A8B91BF40CF522B4008F91FF /* PixelDumpSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PixelDumpSupport.h; path = mac/PixelDumpSupport.h; sourceTree = "<group>"; };
+               A8B91BF50CF522B4008F91FF /* JavaScriptThreading.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JavaScriptThreading.h; path = mac/JavaScriptThreading.h; sourceTree = "<group>"; };
+               A8B91BF60CF522B4008F91FF /* PixelDumpSupport.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PixelDumpSupport.mm; path = mac/PixelDumpSupport.mm; sourceTree = "<group>"; };
+               A8B91BF70CF522B4008F91FF /* CheckedMalloc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CheckedMalloc.cpp; path = mac/CheckedMalloc.cpp; sourceTree = "<group>"; };
+               A8B91BF80CF522B4008F91FF /* JavaScriptThreading.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JavaScriptThreading.cpp; path = mac/JavaScriptThreading.cpp; sourceTree = "<group>"; };
+               A8B91BF90CF522B4008F91FF /* CheckedMalloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CheckedMalloc.h; path = mac/CheckedMalloc.h; sourceTree = "<group>"; };
                AA7F10C20CB3C1030003BDC9 /* AHEM____.TTF */ = {isa = PBXFileReference; lastKnownFileType = file; name = "AHEM____.TTF"; path = "qt/fonts/AHEM____.TTF"; sourceTree = "<group>"; };
                AE8257EF08D22389000507AB /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
                B5A7526708AF4A4A00138E45 /* ImageDiff */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ImageDiff; sourceTree = BUILT_PRODUCTS_DIR; };
                                141BF1F5096A439800E0753C /* TestNetscapePlugIn.subproj */,
                                A803FF7409CAAD08009B2A37 /* DumpRenderTree.h */,
                                BCA18C460C9B5B9400114369 /* DumpRenderTree.mm */,
+                               A8B91BF70CF522B4008F91FF /* CheckedMalloc.cpp */,
+                               A8B91BF90CF522B4008F91FF /* CheckedMalloc.h */,
+                               A8B91BF80CF522B4008F91FF /* JavaScriptThreading.cpp */,
+                               A8B91BF50CF522B4008F91FF /* JavaScriptThreading.h */,
+                               A8B91BF40CF522B4008F91FF /* PixelDumpSupport.h */,
+                               A8B91BF60CF522B4008F91FF /* PixelDumpSupport.mm */,
                                BCA18C0A0C9B59EF00114369 /* DumpRenderTreeMac.h */,
                                A8B91AD20CF3B305008F91FF /* AppKit Overrides */,
                                BCA18B730C9B08F100114369 /* DumpRenderTreeDraggingInfo.h */,
                                BC9D90260C97472E0099A4A3 /* WorkQueueItem.h in Headers */,
                                A8B91AE00CF3B372008F91FF /* DumpRenderTreeWindow.h in Headers */,
                                A8B91AE20CF3B372008F91FF /* DumpRenderTreePasteboard.h in Headers */,
+                               A8B91BFA0CF522B4008F91FF /* PixelDumpSupport.h in Headers */,
+                               A8B91BFB0CF522B4008F91FF /* JavaScriptThreading.h in Headers */,
+                               A8B91BFF0CF522B4008F91FF /* CheckedMalloc.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                BCA18B260C9B015C00114369 /* WorkQueueItemMac.mm in Sources */,
                                A8B91ADA0CF3B32F008F91FF /* DumpRenderTreePasteboard.m in Sources */,
                                A8B91ADC0CF3B32F008F91FF /* DumpRenderTreeWindow.mm in Sources */,
+                               A8B91BFC0CF522B4008F91FF /* PixelDumpSupport.mm in Sources */,
+                               A8B91BFD0CF522B4008F91FF /* CheckedMalloc.cpp in Sources */,
+                               A8B91BFE0CF522B4008F91FF /* JavaScriptThreading.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
diff --git a/WebKitTools/DumpRenderTree/mac/CheckedMalloc.cpp b/WebKitTools/DumpRenderTree/mac/CheckedMalloc.cpp
new file mode 100644 (file)
index 0000000..467f1bb
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2005, 2006, 2007 Apple, Inc.  All rights reserved.
+ *           (C) 2007 Graham Dennis (graham.dennis@gmail.com)
+ *           (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#import "CheckedMalloc.h"
+
+#import <malloc/malloc.h>
+
+static void* (*savedMalloc)(malloc_zone_t*, size_t);
+static void* (*savedRealloc)(malloc_zone_t*, void*, size_t);
+
+static void* checkedMalloc(malloc_zone_t* zone, size_t size)
+{
+    if (size >= 0x10000000)
+        return 0;
+    return savedMalloc(zone, size);
+}
+
+static void* checkedRealloc(malloc_zone_t* zone, void* ptr, size_t size)
+{
+    if (size >= 0x10000000)
+        return 0;
+    return savedRealloc(zone, ptr, size);
+}
+
+void makeLargeMallocFailSilently()
+{
+    malloc_zone_t* zone = malloc_default_zone();
+    savedMalloc = zone->malloc;
+    savedRealloc = zone->realloc;
+    zone->malloc = checkedMalloc;
+    zone->realloc = checkedRealloc;
+}
diff --git a/WebKitTools/DumpRenderTree/mac/CheckedMalloc.h b/WebKitTools/DumpRenderTree/mac/CheckedMalloc.h
new file mode 100644 (file)
index 0000000..c03bd20
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2005, 2006, 2007 Apple, Inc.  All rights reserved.
+ *           (C) 2007 Graham Dennis (graham.dennis@gmail.com)
+ *           (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+void makeLargeMallocFailSilently();
index 952d647dafabd05ccac35a7fd5f9347d6c2f393c..466cbb60c65da75485e9d4d65ba808d8b05d2d3e 100644 (file)
  
 #import "DumpRenderTree.h"
 
+#import "CheckedMalloc.h"
 #import "DumpRenderTreePasteboard.h"
 #import "DumpRenderTreeWindow.h"
 #import "EditingDelegate.h"
 #import "EventSendingController.h"
 #import "FrameLoadDelegate.h"
+#import "JavaScriptThreading.h"
 #import "LayoutTestController.h"
 #import "NavigationController.h"
 #import "ObjCPlugin.h"
 #import "ObjCPluginFunction.h"
+#import "PixelDumpSupport.h"
 #import "PolicyDelegate.h"
 #import "ResourceLoadDelegate.h"
 #import "UIDelegate.h"
 #import "WorkQueue.h"
 #import "WorkQueueItem.h"
 
-#import <ApplicationServices/ApplicationServices.h> // for CMSetDefaultProfileBySpace
 #import <CoreFoundation/CoreFoundation.h>
 #import <JavaScriptCore/Assertions.h>
-#import <JavaScriptCore/JavaScriptCore.h>
 #import <WebKit/DOMElementPrivate.h>
 #import <WebKit/DOMExtensions.h>
 #import <WebKit/DOMRange.h>
 #import <WebKit/WebViewPrivate.h>
 #import <getopt.h>
 #import <mach-o/getsect.h>
-#import <malloc/malloc.h>
 #import <objc/objc-runtime.h>                       // for class_poseAs
-#import <pthread.h>
-
-#define COMMON_DIGEST_FOR_OPENSSL
-#import <CommonCrypto/CommonDigest.h>               // for MD5 functions
 
 @interface DumpRenderTreeEvent : NSEvent
 @end
 
 static void runTest(const char *pathOrURL);
-static NSString *md5HashStringForBitmap(CGImageRef bitmap);
 
 // Deciding when it's OK to dump out the state is a bit tricky.  All these must be true:
 // - There is no load in progress
@@ -119,105 +114,10 @@ static BOOL printSeparators;
 static NSString *currentTest = nil;
 
 static WebHistoryItem *prevTestBFItem = nil;  // current b/f item at the end of the previous test
-static unsigned char* screenCaptureBuffer;
-static CGColorSpaceRef sharedColorSpace;
 
 const unsigned maxViewHeight = 600;
 const unsigned maxViewWidth = 800;
 
-static pthread_mutex_t javaScriptThreadsMutex = PTHREAD_MUTEX_INITIALIZER;
-static BOOL javaScriptThreadsShouldTerminate;
-
-static const int javaScriptThreadsCount = 4;
-static CFMutableDictionaryRef javaScriptThreads()
-{
-    assert(pthread_mutex_trylock(&javaScriptThreadsMutex) == EBUSY);
-    static CFMutableDictionaryRef staticJavaScriptThreads;
-    if (!staticJavaScriptThreads)
-        staticJavaScriptThreads = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL);
-    return staticJavaScriptThreads;
-}
-
-// Loops forever, running a script and randomly respawning, until 
-// javaScriptThreadsShouldTerminate becomes true.
-void* runJavaScriptThread(void* arg)
-{
-    const char* const script =
-        "var array = [];"
-        "for (var i = 0; i < 10; i++) {"
-        "    array.push(String(i));"
-        "}";
-
-    while(1) {
-        JSGlobalContextRef ctx = JSGlobalContextCreate(NULL);
-        JSStringRef scriptRef = JSStringCreateWithUTF8CString(script);
-
-        JSValueRef exception = NULL;
-        JSEvaluateScript(ctx, scriptRef, NULL, NULL, 0, &exception);
-        assert(!exception);
-        
-        JSGlobalContextRelease(ctx);
-        JSStringRelease(scriptRef);
-        
-        JSGarbageCollect(ctx);
-
-        pthread_mutex_lock(&javaScriptThreadsMutex);
-
-        // Check for cancellation.
-        if (javaScriptThreadsShouldTerminate) {
-            pthread_mutex_unlock(&javaScriptThreadsMutex);
-            return 0;
-        }
-
-        // Respawn probabilistically.
-        if (random() % 5 == 0) {
-            pthread_t pthread;
-            pthread_create(&pthread, NULL, &runJavaScriptThread, NULL);
-            pthread_detach(pthread);
-
-            CFDictionaryRemoveValue(javaScriptThreads(), pthread_self());
-            CFDictionaryAddValue(javaScriptThreads(), pthread, NULL);
-
-            pthread_mutex_unlock(&javaScriptThreadsMutex);
-            return 0;
-        }
-
-        pthread_mutex_unlock(&javaScriptThreadsMutex);
-    }
-}
-
-static void startJavaScriptThreads()
-{
-    pthread_mutex_lock(&javaScriptThreadsMutex);
-
-    for (int i = 0; i < javaScriptThreadsCount; i++) {
-        pthread_t pthread;
-        pthread_create(&pthread, NULL, &runJavaScriptThread, NULL);
-        pthread_detach(pthread);
-        CFDictionaryAddValue(javaScriptThreads(), pthread, NULL);
-    }
-
-    pthread_mutex_unlock(&javaScriptThreadsMutex);
-}
-
-static void stopJavaScriptThreads()
-{
-    pthread_mutex_lock(&javaScriptThreadsMutex);
-
-    javaScriptThreadsShouldTerminate = true;
-
-    pthread_t* pthreads[javaScriptThreadsCount] = { 0 };
-    ASSERT(CFDictionaryGetCount(javaScriptThreads()) == javaScriptThreadsCount);
-    CFDictionaryGetKeysAndValues(javaScriptThreads(), (const void**)pthreads, 0);
-
-    pthread_mutex_unlock(&javaScriptThreadsMutex);
-
-    for (int i = 0; i < javaScriptThreadsCount; i++) {
-        pthread_t* pthread = pthreads[i];
-        pthread_join(*pthread, 0);
-        free(pthread);
-    }
-}
 
 static BOOL shouldIgnoreWebCoreNodeLeaks(CFStringRef URLString)
 {
@@ -236,24 +136,6 @@ static BOOL shouldIgnoreWebCoreNodeLeaks(CFStringRef URLString)
     return NO;
 }
 
-static CMProfileRef currentColorProfile = 0;
-static void restoreColorSpace(int ignored)
-{
-    if (currentColorProfile) {
-        int error = CMSetDefaultProfileByUse(cmDisplayUse, currentColorProfile);
-        if (error)
-            fprintf(stderr, "Failed to retore previous color profile!  You may need to open System Preferences : Displays : Color and manually restore your color settings.  (Error: %i)", error);
-        currentColorProfile = 0;
-    }
-}
-
-static void crashHandler(int sig)
-{
-    fprintf(stderr, "%s\n", strsignal(sig));
-    restoreColorSpace(0);
-    exit(128 + sig);
-}
-
 static void activateAhemFont()
 {    
     unsigned long fontDataLength;
@@ -272,69 +154,6 @@ static void activateAhemFont()
     }
 }
 
-static void setDefaultColorProfileToRGB()
-{
-    CMProfileRef genericProfile = (CMProfileRef)[[NSColorSpace genericRGBColorSpace] colorSyncProfile];
-    CMProfileRef previousProfile;
-    int error = CMGetDefaultProfileByUse(cmDisplayUse, &previousProfile);
-    if (error) {
-        fprintf(stderr, "Failed to get current color profile.  I will not be able to restore your current profile, thus I'm not changing it.  Many pixel tests may fail as a result.  (Error: %i)\n", error);
-        return;
-    }
-    if (previousProfile == genericProfile)
-        return;
-    CFStringRef previousProfileName;
-    CFStringRef genericProfileName;
-    char previousProfileNameString[1024];
-    char genericProfileNameString[1024];
-    CMCopyProfileDescriptionString(previousProfile, &previousProfileName);
-    CMCopyProfileDescriptionString(genericProfile, &genericProfileName);
-    CFStringGetCString(previousProfileName, previousProfileNameString, sizeof(previousProfileNameString), kCFStringEncodingUTF8);
-    CFStringGetCString(genericProfileName, genericProfileNameString, sizeof(previousProfileNameString), kCFStringEncodingUTF8);
-    CFRelease(genericProfileName);
-    CFRelease(previousProfileName);
-    
-    fprintf(stderr, "\n\nWARNING: Temporarily changing your system color profile from \"%s\" to \"%s\".\n", previousProfileNameString, genericProfileNameString);
-    fprintf(stderr, "This allows the WebKit pixel-based regression tests to have consistent color values across all machines.\n");
-    fprintf(stderr, "The colors on your screen will change for the duration of the testing.\n\n");
-    
-    if ((error = CMSetDefaultProfileByUse(cmDisplayUse, genericProfile)))
-        fprintf(stderr, "Failed to set color profile to \"%s\"! Many pixel tests will fail as a result.  (Error: %i)",
-            genericProfileNameString, error);
-    else {
-        currentColorProfile = previousProfile;
-        signal(SIGINT, restoreColorSpace);
-        signal(SIGHUP, restoreColorSpace);
-        signal(SIGTERM, restoreColorSpace);
-    }
-}
-
-static void* (*savedMalloc)(malloc_zone_t*, size_t);
-static void* (*savedRealloc)(malloc_zone_t*, void*, size_t);
-
-static void* checkedMalloc(malloc_zone_t* zone, size_t size)
-{
-    if (size >= 0x10000000)
-        return 0;
-    return savedMalloc(zone, size);
-}
-
-static void* checkedRealloc(malloc_zone_t* zone, void* ptr, size_t size)
-{
-    if (size >= 0x10000000)
-        return 0;
-    return savedRealloc(zone, ptr, size);
-}
-
-static void makeLargeMallocFailSilently()
-{
-    malloc_zone_t* zone = malloc_default_zone();
-    savedMalloc = zone->malloc;
-    savedRealloc = zone->realloc;
-    zone->malloc = checkedMalloc;
-    zone->realloc = checkedRealloc;
-}
-
 WebView *createWebViewAndOffscreenWindow()
 {
     NSRect rect = NSMakeRect(0, 0, maxViewWidth, maxViewHeight);
@@ -444,6 +263,13 @@ static void setDefaultsToConsistentValuesForTesting()
     [preferences setDOMPasteAllowed:YES];
 }
 
+static void crashHandler(int sig)
+{
+    fprintf(stderr, "%s\n", strsignal(sig));
+    restoreColorSpace(0);
+    exit(128 + sig);
+}
+
 static void installSignalHandlers()
 {
     signal(SIGILL, crashHandler);    /* 4:   illegal instruction (not reset when caught) */
@@ -510,13 +336,6 @@ static void initializeGlobalsFromCommandLineOptions(int argc, const char *argv[]
     }
 }
 
-static void initializeColorSpaceAndScreeBufferForPixelTests()
-{
-    setDefaultColorProfileToRGB();
-    screenCaptureBuffer = (unsigned char *)malloc(maxViewHeight * maxViewWidth * 4);
-    sharedColorSpace = CGColorSpaceCreateDeviceRGB();
-}
-
 static void addTestPluginsToPluginSearchPath(const char* executablePath)
 {
     NSString *pwd = [[NSString stringWithUTF8String:executablePath] stringByDeletingLastPathComponent];
@@ -894,93 +713,6 @@ static void dumpBackForwardListForAllWindows()
     }
 }
 
-static void dumpWebViewAsPixelsAndCompareWithExpected()
-{
-    if (!layoutTestController->dumpAsText() && !layoutTestController->dumpDOMAsWebArchive() && !layoutTestController->dumpSourceAsWebArchive()) {
-        // grab a bitmap from the view
-        WebView* view = [mainFrame webView];
-        NSSize webViewSize = [view frame].size;
-        
-        CGContextRef cgContext = CGBitmapContextCreate(screenCaptureBuffer, static_cast<size_t>(webViewSize.width), static_cast<size_t>(webViewSize.height), 8, static_cast<size_t>(webViewSize.width) * 4, sharedColorSpace, kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedLast);
-        
-        NSGraphicsContext* savedContext = [[[NSGraphicsContext currentContext] retain] autorelease];
-        NSGraphicsContext* nsContext = [NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:NO];
-        [NSGraphicsContext setCurrentContext:nsContext];
-        
-        if (!layoutTestController->testRepaint()) {
-            NSBitmapImageRep *imageRep;
-            [view displayIfNeeded];
-            [view lockFocus];
-            imageRep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:[view frame]];
-            [view unlockFocus];
-            [imageRep draw];
-            [imageRep release];
-        } else if (!layoutTestController->testRepaintSweepHorizontally()) {
-            NSRect line = NSMakeRect(0, 0, webViewSize.width, 1);
-            while (line.origin.y < webViewSize.height) {
-                [view displayRectIgnoringOpacity:line inContext:nsContext];
-                line.origin.y++;
-            }
-        } else {
-            NSRect column = NSMakeRect(0, 0, 1, webViewSize.height);
-            while (column.origin.x < webViewSize.width) {
-                [view displayRectIgnoringOpacity:column inContext:nsContext];
-                column.origin.x++;
-            }
-        }
-        if (layoutTestController->dumpSelectionRect()) {
-            NSView *documentView = [[mainFrame frameView] documentView];
-            if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) {
-                [[NSColor redColor] set];
-                [NSBezierPath strokeRect:[documentView convertRect:[(id <WebDocumentSelection>)documentView selectionRect] fromView:nil]];
-            }
-        }
-        
-        [NSGraphicsContext setCurrentContext:savedContext];
-        
-        CGImageRef bitmapImage = CGBitmapContextCreateImage(cgContext);
-        CGContextRelease(cgContext);
-        
-        // compute the actual hash to compare to the expected image's hash
-        NSString *actualHash = md5HashStringForBitmap(bitmapImage);
-        printf("\nActualHash: %s\n", [actualHash UTF8String]);
-        
-        BOOL dumpImage;
-        if (dumpAllPixels)
-            dumpImage = YES;
-        else {
-            // FIXME: It's unfortunate that we hardcode the file naming scheme here.
-            // At one time, the perl script had all the knowledge about file layout.
-            // Some day we should restore that setup by passing in more parameters to this tool
-            // or returning more information from the tool to the perl script
-            NSString *baseTestPath = [currentTest stringByDeletingPathExtension];
-            NSString *baselineHashPath = [baseTestPath stringByAppendingString:@"-expected.checksum"];
-            NSString *baselineHash = [NSString stringWithContentsOfFile:baselineHashPath encoding:NSUTF8StringEncoding error:nil];
-            NSString *baselineImagePath = [baseTestPath stringByAppendingString:@"-expected.png"];
-            
-            printf("BaselineHash: %s\n", [baselineHash UTF8String]);
-            
-            /// send the image to stdout if the hash mismatches or if there's no file in the file system
-            dumpImage = ![baselineHash isEqualToString:actualHash] || access([baselineImagePath fileSystemRepresentation], F_OK) != 0;
-        }
-        
-        if (dumpImage) {
-            CFMutableDataRef imageData = CFDataCreateMutable(0, 0);
-            CGImageDestinationRef imageDest = CGImageDestinationCreateWithData(imageData, CFSTR("public.png"), 1, 0);
-            CGImageDestinationAddImage(imageDest, bitmapImage, 0);
-            CGImageDestinationFinalize(imageDest);
-            CFRelease(imageDest);
-            printf("Content-length: %lu\n", CFDataGetLength(imageData));
-            fwrite(CFDataGetBytePtr(imageData), 1, CFDataGetLength(imageData), stdout);
-            CFRelease(imageData);
-        }
-        
-        CGImageRelease(bitmapImage);
-    }
-    
-    printf("#EOF\n");
-}
-
 static void invalidateAnyPreviousWaitToDumpWatchdog()
 {
     if (waitToDumpWatchdog) {
@@ -1033,7 +765,7 @@ void dump()
     }
     
     if (dumpPixels)
-        dumpWebViewAsPixelsAndCompareWithExpected();
+        dumpWebViewAsPixelsAndCompareWithExpected(currentTest, dumpAllPixels);
 
     fflush(stdout);
 
@@ -1155,36 +887,6 @@ static void runTest(const char *pathOrURL)
         [WebCoreStatistics stopIgnoringWebCoreNodeLeaks];
 }
 
-/* Hashes a bitmap and returns a text string for comparison and saving to a file */
-static NSString *md5HashStringForBitmap(CGImageRef bitmap)
-{
-    MD5_CTX md5Context;
-    unsigned char hash[16];
-    
-    unsigned bitsPerPixel = CGImageGetBitsPerPixel(bitmap);
-    assert(bitsPerPixel == 32); // ImageDiff assumes 32 bit RGBA, we must as well.
-    unsigned bytesPerPixel = bitsPerPixel / 8;
-    unsigned pixelsHigh = CGImageGetHeight(bitmap);
-    unsigned pixelsWide = CGImageGetWidth(bitmap);
-    unsigned bytesPerRow = CGImageGetBytesPerRow(bitmap);
-    assert(bytesPerRow >= (pixelsWide * bytesPerPixel));
-    
-    MD5_Init(&md5Context);
-    unsigned char *bitmapData = screenCaptureBuffer;
-    for (unsigned row = 0; row < pixelsHigh; row++) {
-        MD5_Update(&md5Context, bitmapData, pixelsWide * bytesPerPixel);
-        bitmapData += bytesPerRow;
-    }
-    MD5_Final(hash, &md5Context);
-    
-    char hex[33] = "";
-    for (int i = 0; i < 16; i++) {
-       snprintf(hex, 33, "%s%02x", hex, hash[i]);
-    }
-
-    return [NSString stringWithUTF8String:hex];
-}
-
 void displayWebView()
 {
     NSView *webView = [mainFrame webView];
index eaa191c0e888a2badd0913e56df83461b4dab9af..fff124b1105398274c4b759f9d0b8be64b6e6467 100644 (file)
@@ -43,6 +43,9 @@ extern DumpRenderTreeDraggingInfo *draggingInfo;
 extern NavigationController* navigationController;
 extern PolicyDelegate* policyDelegate;
 
+extern const unsigned maxViewHeight;
+extern const unsigned maxViewWidth;
+
 WebView* createWebViewAndOffscreenWindow();
 
 #endif // DumpRenderTreeMac_h 
index 1d9dba927b46af29700c00b5670931cc46304ec2..6a01a424c855de20a15789f8ec2ced6e5aa3ae39 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2005, 2006, 2007 Apple, Inc.  All rights reserved.
  *           (C) 2007 Graham Dennis (graham.dennis@gmail.com)
+ *           (C) 2007 Eric Seidel <eric@webkit.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
index d9aaeed5e0f5029b76893bd38cbb598e72a043df..b5a9b7a5000289b33fe6ba471ab23875563ebb13 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2005, 2006, 2007 Apple, Inc.  All rights reserved.
  *           (C) 2007 Graham Dennis (graham.dennis@gmail.com)
+ *           (C) 2007 Eric Seidel <eric@webkit.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
index 0127418770c7c56b7d9765652f9be0d59001b8d0..33c72d68846b85abbabcd26ed499d141e5938b5f 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2005, 2006, 2007 Apple, Inc.  All rights reserved.
  *           (C) 2007 Graham Dennis (graham.dennis@gmail.com)
+ *           (C) 2007 Eric Seidel <eric@webkit.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
index d893e68c216b3c2317cc2f378f903b7af9e02397..1ea7fcb195b0569adc35c4716f918c89693aade6 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2005, 2006, 2007 Apple, Inc.  All rights reserved.
  *           (C) 2007 Graham Dennis (graham.dennis@gmail.com)
+ *           (C) 2007 Eric Seidel <eric@webkit.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
diff --git a/WebKitTools/DumpRenderTree/mac/JavaScriptThreading.cpp b/WebKitTools/DumpRenderTree/mac/JavaScriptThreading.cpp
new file mode 100644 (file)
index 0000000..7f1bfd7
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2005, 2006, 2007 Apple, Inc.  All rights reserved.
+ *           (C) 2007 Graham Dennis (graham.dennis@gmail.com)
+ *           (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#import "JavaScriptThreading.h"
+
+#import <JavaScriptCore/Assertions.h>
+#import <JavaScriptCore/JavaScriptCore.h>
+
+#import <CoreFoundation/CoreFoundation.h>
+
+#import <pthread.h>
+
+static pthread_mutex_t javaScriptThreadsMutex = PTHREAD_MUTEX_INITIALIZER;
+static bool javaScriptThreadsShouldTerminate;
+
+static const int javaScriptThreadsCount = 4;
+static CFMutableDictionaryRef javaScriptThreads()
+{
+    assert(pthread_mutex_trylock(&javaScriptThreadsMutex) == EBUSY);
+    static CFMutableDictionaryRef staticJavaScriptThreads;
+    if (!staticJavaScriptThreads)
+        staticJavaScriptThreads = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL);
+    return staticJavaScriptThreads;
+}
+
+// Loops forever, running a script and randomly respawning, until 
+// javaScriptThreadsShouldTerminate becomes true.
+void* runJavaScriptThread(void* arg)
+{
+    const char* const script =
+        "var array = [];"
+        "for (var i = 0; i < 10; i++) {"
+        "    array.push(String(i));"
+        "}";
+
+    while(1) {
+        JSGlobalContextRef ctx = JSGlobalContextCreate(NULL);
+        JSStringRef scriptRef = JSStringCreateWithUTF8CString(script);
+
+        JSValueRef exception = NULL;
+        JSEvaluateScript(ctx, scriptRef, NULL, NULL, 0, &exception);
+        assert(!exception);
+        
+        JSGlobalContextRelease(ctx);
+        JSStringRelease(scriptRef);
+        
+        JSGarbageCollect(ctx);
+
+        pthread_mutex_lock(&javaScriptThreadsMutex);
+
+        // Check for cancellation.
+        if (javaScriptThreadsShouldTerminate) {
+            pthread_mutex_unlock(&javaScriptThreadsMutex);
+            return 0;
+        }
+
+        // Respawn probabilistically.
+        if (random() % 5 == 0) {
+            pthread_t pthread;
+            pthread_create(&pthread, NULL, &runJavaScriptThread, NULL);
+            pthread_detach(pthread);
+
+            CFDictionaryRemoveValue(javaScriptThreads(), pthread_self());
+            CFDictionaryAddValue(javaScriptThreads(), pthread, NULL);
+
+            pthread_mutex_unlock(&javaScriptThreadsMutex);
+            return 0;
+        }
+
+        pthread_mutex_unlock(&javaScriptThreadsMutex);
+    }
+}
+
+void startJavaScriptThreads()
+{
+    pthread_mutex_lock(&javaScriptThreadsMutex);
+
+    for (int i = 0; i < javaScriptThreadsCount; i++) {
+        pthread_t pthread;
+        pthread_create(&pthread, NULL, &runJavaScriptThread, NULL);
+        pthread_detach(pthread);
+        CFDictionaryAddValue(javaScriptThreads(), pthread, NULL);
+    }
+
+    pthread_mutex_unlock(&javaScriptThreadsMutex);
+}
+
+void stopJavaScriptThreads()
+{
+    pthread_mutex_lock(&javaScriptThreadsMutex);
+
+    javaScriptThreadsShouldTerminate = true;
+
+    pthread_t* pthreads[javaScriptThreadsCount] = { 0 };
+    ASSERT(CFDictionaryGetCount(javaScriptThreads()) == javaScriptThreadsCount);
+    CFDictionaryGetKeysAndValues(javaScriptThreads(), (const void**)pthreads, 0);
+
+    pthread_mutex_unlock(&javaScriptThreadsMutex);
+
+    for (int i = 0; i < javaScriptThreadsCount; i++) {
+        pthread_t* pthread = pthreads[i];
+        pthread_join(*pthread, 0);
+        free(pthread);
+    }
+}
diff --git a/WebKitTools/DumpRenderTree/mac/JavaScriptThreading.h b/WebKitTools/DumpRenderTree/mac/JavaScriptThreading.h
new file mode 100644 (file)
index 0000000..57744dc
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2005, 2006, 2007 Apple, Inc.  All rights reserved.
+ *           (C) 2007 Graham Dennis (graham.dennis@gmail.com)
+ *           (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* These functions start/stop threads used to abuse the JavaScript interpreter
+ and assure that our JS implementation remains threadsafe */
+
+void startJavaScriptThreads();
+void stopJavaScriptThreads();
diff --git a/WebKitTools/DumpRenderTree/mac/PixelDumpSupport.h b/WebKitTools/DumpRenderTree/mac/PixelDumpSupport.h
new file mode 100644 (file)
index 0000000..13d734d
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2005, 2006, 2007 Apple, Inc.  All rights reserved.
+ *           (C) 2007 Graham Dennis (graham.dennis@gmail.com)
+ *           (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// can be used as a signal handler
+void restoreColorSpace(int ignored);
+
+// may change your color space, requiring a call to restoreColorSpace
+void initializeColorSpaceAndScreeBufferForPixelTests();
+
+// a poor abstraction, parts of this should be in this file, and parts should not
+void dumpWebViewAsPixelsAndCompareWithExpected(NSString *currentTest, bool forceAllTestsToDumpPixels);
diff --git a/WebKitTools/DumpRenderTree/mac/PixelDumpSupport.mm b/WebKitTools/DumpRenderTree/mac/PixelDumpSupport.mm
new file mode 100644 (file)
index 0000000..ad770c8
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2005, 2006, 2007 Apple, Inc.  All rights reserved.
+ *           (C) 2007 Graham Dennis (graham.dennis@gmail.com)
+ *           (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#import "PixelDumpSupport.h"
+
+#import "DumpRenderTree.h"
+#import "LayoutTestController.h"
+
+#import <AppKit/AppKit.h>
+#import <ApplicationServices/ApplicationServices.h> // for CMSetDefaultProfileBySpace
+#import <WebKit/WebKit.h>
+#import <WebKit/WebDocumentPrivate.h>
+
+#define COMMON_DIGEST_FOR_OPENSSL
+#import <CommonCrypto/CommonDigest.h>               // for MD5 functions
+
+static unsigned char* screenCaptureBuffer;
+
+static CMProfileRef currentColorProfile = 0;
+static CGColorSpaceRef sharedColorSpace;
+
+void restoreColorSpace(int ignored)
+{
+    // This is used as a signal handler, and thus the calls into ColorSync are unsafe
+    // But we might as well try to restore the user's color profile, we're going down anyway...
+    if (currentColorProfile) {
+        // This call is deprecated in Leopard, but there appears to be no replacement.
+        int error = CMSetDefaultProfileByUse(cmDisplayUse, currentColorProfile);
+        if (error)
+            fprintf(stderr, "Failed to retore previous color profile!  You may need to open System Preferences : Displays : Color and manually restore your color settings.  (Error: %i)", error);
+        currentColorProfile = 0;
+    }
+}
+
+static void setDefaultColorProfileToRGB()
+{
+    CMProfileRef genericProfile = (CMProfileRef)[[NSColorSpace genericRGBColorSpace] colorSyncProfile];
+    CMProfileRef previousProfile;
+    int error = CMGetDefaultProfileByUse(cmDisplayUse, &previousProfile);
+    if (error) {
+        fprintf(stderr, "Failed to get current color profile.  I will not be able to restore your current profile, thus I'm not changing it.  Many pixel tests may fail as a result.  (Error: %i)\n", error);
+        return;
+    }
+    if (previousProfile == genericProfile)
+        return;
+    CFStringRef previousProfileName;
+    CFStringRef genericProfileName;
+    char previousProfileNameString[1024];
+    char genericProfileNameString[1024];
+    CMCopyProfileDescriptionString(previousProfile, &previousProfileName);
+    CMCopyProfileDescriptionString(genericProfile, &genericProfileName);
+    CFStringGetCString(previousProfileName, previousProfileNameString, sizeof(previousProfileNameString), kCFStringEncodingUTF8);
+    CFStringGetCString(genericProfileName, genericProfileNameString, sizeof(previousProfileNameString), kCFStringEncodingUTF8);
+    CFRelease(genericProfileName);
+    CFRelease(previousProfileName);
+    
+    fprintf(stderr, "\n\nWARNING: Temporarily changing your system color profile from \"%s\" to \"%s\".\n", previousProfileNameString, genericProfileNameString);
+    fprintf(stderr, "This allows the WebKit pixel-based regression tests to have consistent color values across all machines.\n");
+    fprintf(stderr, "The colors on your screen will change for the duration of the testing.\n\n");
+    
+    if ((error = CMSetDefaultProfileByUse(cmDisplayUse, genericProfile)))
+        fprintf(stderr, "Failed to set color profile to \"%s\"! Many pixel tests will fail as a result.  (Error: %i)",
+            genericProfileNameString, error);
+    else {
+        currentColorProfile = previousProfile;
+        signal(SIGINT, restoreColorSpace);
+        signal(SIGHUP, restoreColorSpace);
+        signal(SIGTERM, restoreColorSpace);
+    }
+}
+
+void initializeColorSpaceAndScreeBufferForPixelTests()
+{
+    setDefaultColorProfileToRGB();
+    screenCaptureBuffer = (unsigned char *)malloc(maxViewHeight * maxViewWidth * 4);
+    sharedColorSpace = CGColorSpaceCreateDeviceRGB();
+}
+
+/* Hashes a bitmap and returns a text string for comparison and saving to a file */
+static NSString *md5HashStringForBitmap(CGImageRef bitmap)
+{
+    MD5_CTX md5Context;
+    unsigned char hash[16];
+    
+    unsigned bitsPerPixel = CGImageGetBitsPerPixel(bitmap);
+    assert(bitsPerPixel == 32); // ImageDiff assumes 32 bit RGBA, we must as well.
+    unsigned bytesPerPixel = bitsPerPixel / 8;
+    unsigned pixelsHigh = CGImageGetHeight(bitmap);
+    unsigned pixelsWide = CGImageGetWidth(bitmap);
+    unsigned bytesPerRow = CGImageGetBytesPerRow(bitmap);
+    assert(bytesPerRow >= (pixelsWide * bytesPerPixel));
+    
+    MD5_Init(&md5Context);
+    unsigned char *bitmapData = screenCaptureBuffer;
+    for (unsigned row = 0; row < pixelsHigh; row++) {
+        MD5_Update(&md5Context, bitmapData, pixelsWide * bytesPerPixel);
+        bitmapData += bytesPerRow;
+    }
+    MD5_Final(hash, &md5Context);
+    
+    char hex[33] = "";
+    for (int i = 0; i < 16; i++) {
+        snprintf(hex, 33, "%s%02x", hex, hash[i]);
+    }
+    
+    return [NSString stringWithUTF8String:hex];
+}
+
+void dumpWebViewAsPixelsAndCompareWithExpected(NSString* currentTest, bool forceAllTestsToDumpPixels)
+{
+    if (!layoutTestController->dumpAsText() && !layoutTestController->dumpDOMAsWebArchive() && !layoutTestController->dumpSourceAsWebArchive()) {
+        // grab a bitmap from the view
+        WebView* view = [mainFrame webView];
+        NSSize webViewSize = [view frame].size;
+        
+        CGContextRef cgContext = CGBitmapContextCreate(screenCaptureBuffer, static_cast<size_t>(webViewSize.width), static_cast<size_t>(webViewSize.height), 8, static_cast<size_t>(webViewSize.width) * 4, sharedColorSpace, kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedLast);
+        
+        NSGraphicsContext* savedContext = [[[NSGraphicsContext currentContext] retain] autorelease];
+        NSGraphicsContext* nsContext = [NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:NO];
+        [NSGraphicsContext setCurrentContext:nsContext];
+        
+        if (!layoutTestController->testRepaint()) {
+            NSBitmapImageRep *imageRep;
+            [view displayIfNeeded];
+            [view lockFocus];
+            imageRep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:[view frame]];
+            [view unlockFocus];
+            [imageRep draw];
+            [imageRep release];
+        } else if (!layoutTestController->testRepaintSweepHorizontally()) {
+            NSRect line = NSMakeRect(0, 0, webViewSize.width, 1);
+            while (line.origin.y < webViewSize.height) {
+                [view displayRectIgnoringOpacity:line inContext:nsContext];
+                line.origin.y++;
+            }
+        } else {
+            NSRect column = NSMakeRect(0, 0, 1, webViewSize.height);
+            while (column.origin.x < webViewSize.width) {
+                [view displayRectIgnoringOpacity:column inContext:nsContext];
+                column.origin.x++;
+            }
+        }
+        if (layoutTestController->dumpSelectionRect()) {
+            NSView *documentView = [[mainFrame frameView] documentView];
+            if ([documentView conformsToProtocol:@protocol(WebDocumentSelection)]) {
+                [[NSColor redColor] set];
+                [NSBezierPath strokeRect:[documentView convertRect:[(id <WebDocumentSelection>)documentView selectionRect] fromView:nil]];
+            }
+        }
+        
+        [NSGraphicsContext setCurrentContext:savedContext];
+        
+        CGImageRef bitmapImage = CGBitmapContextCreateImage(cgContext);
+        CGContextRelease(cgContext);
+        
+        // compute the actual hash to compare to the expected image's hash
+        NSString *actualHash = md5HashStringForBitmap(bitmapImage);
+        printf("\nActualHash: %s\n", [actualHash UTF8String]);
+        
+        BOOL dumpImage;
+        if (forceAllTestsToDumpPixels)
+            dumpImage = YES;
+        else {
+            // FIXME: It's unfortunate that we hardcode the file naming scheme here.
+            // At one time, the perl script had all the knowledge about file layout.
+            // Some day we should restore that setup by passing in more parameters to this tool
+            // or returning more information from the tool to the perl script
+            NSString *baseTestPath = [currentTest stringByDeletingPathExtension];
+            NSString *baselineHashPath = [baseTestPath stringByAppendingString:@"-expected.checksum"];
+            NSString *baselineHash = [NSString stringWithContentsOfFile:baselineHashPath encoding:NSUTF8StringEncoding error:nil];
+            NSString *baselineImagePath = [baseTestPath stringByAppendingString:@"-expected.png"];
+            
+            printf("BaselineHash: %s\n", [baselineHash UTF8String]);
+            
+            /// send the image to stdout if the hash mismatches or if there's no file in the file system
+            dumpImage = ![baselineHash isEqualToString:actualHash] || access([baselineImagePath fileSystemRepresentation], F_OK) != 0;
+        }
+        
+        if (dumpImage) {
+            CFMutableDataRef imageData = CFDataCreateMutable(0, 0);
+            CGImageDestinationRef imageDest = CGImageDestinationCreateWithData(imageData, CFSTR("public.png"), 1, 0);
+            CGImageDestinationAddImage(imageDest, bitmapImage, 0);
+            CGImageDestinationFinalize(imageDest);
+            CFRelease(imageDest);
+            printf("Content-length: %lu\n", CFDataGetLength(imageData));
+            fwrite(CFDataGetBytePtr(imageData), 1, CFDataGetLength(imageData), stdout);
+            CFRelease(imageData);
+        }
+        
+        CGImageRelease(bitmapImage);
+    }
+    
+    printf("#EOF\n");
+}