Add the ability to accumulate logs for specific logging channels to help diagnose...
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 2 May 2016 23:14:01 +0000 (23:14 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 2 May 2016 23:14:01 +0000 (23:14 +0000)
https://bugs.webkit.org/show_bug.cgi?id=157274

Reviewed by Alex Christensen.
Source/WebCore:

* platform/Logging.cpp:
(WebCore::setLogChannelToAccumulate): Set the given log channel to accumulate logging,
  and dirty the initializeLoggingChannelsIfNecessary flag.
(WebCore::initializeLoggingChannelsIfNecessary): Change from being a one-time-only call to a
  one-time-for-each-time-somebody-calls-setLogChannelToAccumulate call.
* platform/Logging.h:

* testing/js/WebCoreTestSupport.cpp:
(WebCoreTestSupport::setLogChannelToAccumulate):
(WebCoreTestSupport::initializeLoggingChannelsIfNecessary):
* testing/js/WebCoreTestSupport.h:

Source/WTF:

This patch changes WTFLog to add the logging string to the logging accumulator if the logging channel says so.
It also adds support for using this new accumulation mechanism.

* WTF.xcodeproj/project.pbxproj:

* wtf/Assertions.cpp:
(WTF::resetAccumulatedLogs):
(WTF::getAndResetAccumulatedLogs):
* wtf/Assertions.h:

* wtf/LoggingAccumulator.h: Added. Expose functions to get accumulated logs and to reset the accumulation.

* wtf/text/WTFString.cpp:
(WTF::String::format): Update to handle %@ on CF (Well, really ObjC) platforms.

Tools:

Add the new accumulate method to DRT's TestRunner, dump the accumulated logs if there's a timeout,
and reset them in between tests:
* DumpRenderTree/TestRunner.cpp:
(accummulateLogsForChannel):
(TestRunner::staticFunctions):
(TestRunner::waitToDumpWatchdogTimerFired):
(TestRunner::setAccummulateLogsForChannel):
* DumpRenderTree/TestRunner.h:
* DumpRenderTree/mac/DumpRenderTree.mm:
(resetWebViewToConsistentStateBeforeTesting):

Also add the new method to WKTR's TestRunner, but just stubbed for now:
* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/TestRunner.cpp:
(WTR::TestRunner::accummulateLogsForChannel):
* WebKitTestRunner/InjectedBundle/TestRunner.h:

LayoutTests:

For the tests that are known flakes that are not imported, add the "accumulate IndexedDB logs" command.

* storage/indexeddb/modern/resources/256-open-databases.js:
* storage/indexeddb/modern/resources/abort-requests-cancelled.js:
* storage/indexeddb/modern/resources/autoincrement-abort.js:
* storage/indexeddb/resources/intversion-open-in-upgradeneeded.js:
* storage/indexeddb/resources/odd-strings.js:

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

24 files changed:
LayoutTests/ChangeLog
LayoutTests/storage/indexeddb/modern/resources/256-open-databases.js
LayoutTests/storage/indexeddb/modern/resources/abort-requests-cancelled.js
LayoutTests/storage/indexeddb/modern/resources/autoincrement-abort.js
LayoutTests/storage/indexeddb/resources/intversion-open-in-upgradeneeded.js
LayoutTests/storage/indexeddb/resources/odd-strings.js
Source/WTF/ChangeLog
Source/WTF/WTF.xcodeproj/project.pbxproj
Source/WTF/wtf/Assertions.cpp
Source/WTF/wtf/Assertions.h
Source/WTF/wtf/LoggingAccumulator.h [new file with mode: 0644]
Source/WTF/wtf/text/WTFString.cpp
Source/WebCore/ChangeLog
Source/WebCore/platform/Logging.cpp
Source/WebCore/platform/Logging.h
Source/WebCore/testing/js/WebCoreTestSupport.cpp
Source/WebCore/testing/js/WebCoreTestSupport.h
Tools/ChangeLog
Tools/DumpRenderTree/TestRunner.cpp
Tools/DumpRenderTree/TestRunner.h
Tools/DumpRenderTree/mac/DumpRenderTree.mm
Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl
Tools/WebKitTestRunner/InjectedBundle/TestRunner.cpp
Tools/WebKitTestRunner/InjectedBundle/TestRunner.h

index 5615827..62f5d56 100644 (file)
@@ -1,3 +1,18 @@
+2016-05-02  Brady Eidson  <beidson@apple.com>
+
+        Add the ability to accumulate logs for specific logging channels to help diagnose test timeouts.
+        https://bugs.webkit.org/show_bug.cgi?id=157274
+
+        Reviewed by Alex Christensen.
+        
+        For the tests that are known flakes that are not imported, add the "accumulate IndexedDB logs" command.
+
+        * storage/indexeddb/modern/resources/256-open-databases.js:
+        * storage/indexeddb/modern/resources/abort-requests-cancelled.js:
+        * storage/indexeddb/modern/resources/autoincrement-abort.js:
+        * storage/indexeddb/resources/intversion-open-in-upgradeneeded.js:
+        * storage/indexeddb/resources/odd-strings.js:
+
 2016-05-02  Per Arne Vollan  <peavo@outlook.com>
 
         [Win] Enable IndexedDB.
index d5851a7..de1cc82 100644 (file)
@@ -1,5 +1,8 @@
 description("This test makes sure that if you open 128 unique databases, close your connections to them, and then open 128 other unique databases, that it works.");
 
+if (window.testRunner)
+    testRunner.accummulateLogsForChannel("IndexedDB");
+
 var databaseConnections = new Array;
 
 for (var i = 0; i < 128; ++i) {
index 77952fe..6488c33 100644 (file)
@@ -1,8 +1,10 @@
 description("This test makes sure that un-handled requests in a transaction receive onerror callbacks when the transaction is aborted.");
 
+if (window.testRunner)
+    testRunner.accummulateLogsForChannel("IndexedDB");
+    
 indexedDBTest(prepareDatabase);
 
-
 function done()
 {
     finishJSTest();
index 594b9fd..5db4b41 100644 (file)
@@ -3,9 +3,11 @@ It then puts some things in that object store, checking the keys that were used.
 But it then aborts that transaction. \
 Then it opens a new one and puts something in it, double checking that the key generator was reverted when the above transaction was aborted.");
 
+if (window.testRunner)
+    testRunner.accummulateLogsForChannel("IndexedDB");
+    
 indexedDBTest(prepareDatabase);
 
-
 function done()
 {
     finishJSTest();
index 0dd91e9..2c2380f 100644 (file)
@@ -5,6 +5,9 @@ if (this.importScripts) {
 
 description("Test calling db.open in upgradeneeded.");
 
+if (window.testRunner)
+    testRunner.accummulateLogsForChannel("IndexedDB");
+
 function test()
 {
     removeVendorPrefixes();
index 25393a6..35142e3 100644 (file)
@@ -5,6 +5,9 @@ if (this.importScripts) {
 
 description("Test IndexedDB odd value datatypes");
 
+if (window.testRunner)
+    testRunner.accummulateLogsForChannel("IndexedDB");
+
 function test()
 {
     removeVendorPrefixes();
index 7a2d87d..0d26c5c 100644 (file)
@@ -1,3 +1,25 @@
+2016-05-02  Brady Eidson  <beidson@apple.com>
+
+        Add the ability to accumulate logs for specific logging channels to help diagnose test timeouts.
+        https://bugs.webkit.org/show_bug.cgi?id=157274
+
+        Reviewed by Alex Christensen.
+
+        This patch changes WTFLog to add the logging string to the logging accumulator if the logging channel says so.
+        It also adds support for using this new accumulation mechanism.
+
+        * WTF.xcodeproj/project.pbxproj:
+
+        * wtf/Assertions.cpp:
+        (WTF::resetAccumulatedLogs):
+        (WTF::getAndResetAccumulatedLogs):
+        * wtf/Assertions.h:
+
+        * wtf/LoggingAccumulator.h: Added. Expose functions to get accumulated logs and to reset the accumulation.
+
+        * wtf/text/WTFString.cpp:
+        (WTF::String::format): Update to handle %@ on CF (Well, really ObjC) platforms.
+
 2016-05-02  Per Arne Vollan  <peavo@outlook.com>
 
         [Win] Enable IndexedDB.
index 54339a5..e00e4fa 100644 (file)
                2CDED0F318115C85004DBA70 /* RunLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2CDED0F118115C85004DBA70 /* RunLoop.cpp */; };
                2CDED0F418115C85004DBA70 /* RunLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = 2CDED0F218115C85004DBA70 /* RunLoop.h */; };
                430B47891AAAAC1A001223DA /* StringCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 430B47871AAAAC1A001223DA /* StringCommon.h */; };
+               513E170B1CD7D5BF00E3650B /* LoggingAccumulator.h in Headers */ = {isa = PBXBuildFile; fileRef = 513E170A1CD7D5BF00E3650B /* LoggingAccumulator.h */; };
                553071CA1C40427200384898 /* TinyLRUCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 553071C91C40427200384898 /* TinyLRUCache.h */; };
                70A993FE1AD7151300FA615B /* SymbolRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70A993FC1AD7151300FA615B /* SymbolRegistry.cpp */; };
                70A993FF1AD7151300FA615B /* SymbolRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 70A993FD1AD7151300FA615B /* SymbolRegistry.h */; };
                2CDED0F118115C85004DBA70 /* RunLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RunLoop.cpp; sourceTree = "<group>"; };
                2CDED0F218115C85004DBA70 /* RunLoop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RunLoop.h; sourceTree = "<group>"; };
                430B47871AAAAC1A001223DA /* StringCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringCommon.h; sourceTree = "<group>"; };
+               513E170A1CD7D5BF00E3650B /* LoggingAccumulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoggingAccumulator.h; sourceTree = "<group>"; };
                553071C91C40427200384898 /* TinyLRUCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TinyLRUCache.h; sourceTree = "<group>"; };
                5D247B6214689B8600E78B76 /* libWTF.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libWTF.a; sourceTree = BUILT_PRODUCTS_DIR; };
                5D247B6E14689C4700E78B76 /* Base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = "<group>"; };
                                0FE164681B6FFC9600400E7C /* Lock.cpp */,
                                0FE164691B6FFC9600400E7C /* Lock.h */,
                                A8A472C3151A825A004123FF /* Locker.h */,
+                               513E170A1CD7D5BF00E3650B /* LoggingAccumulator.h */,
                                A8A472C6151A825A004123FF /* MainThread.cpp */,
                                A8A472C7151A825B004123FF /* MainThread.h */,
                                1A233C7C17DAA6E300A93ACF /* MallocPtr.h */,
                                A8A47415151A825B004123FF /* RandomNumber.h in Headers */,
                                A8A47416151A825B004123FF /* RandomNumberSeed.h in Headers */,
                                0F725CAC1C50461600AD943A /* RangeSet.h in Headers */,
+                               513E170B1CD7D5BF00E3650B /* LoggingAccumulator.h in Headers */,
                                0F87105A16643F190090B0AD /* RawPointer.h in Headers */,
                                A8A47417151A825B004123FF /* RedBlackTree.h in Headers */,
                                26299B6E17A9E5B800ADEBE5 /* Ref.h in Headers */,
index 9054e9c..dba4ac0 100644 (file)
 #include "Assertions.h"
 
 #include "Compiler.h"
+#include <mutex>
+#include <stdio.h>
+#include <string.h>
+#include <wtf/Lock.h>
+#include <wtf/Locker.h>
+#include <wtf/LoggingAccumulator.h>
 #include <wtf/StdLibExtras.h>
 #include <wtf/StringExtras.h>
 #include <wtf/text/CString.h>
+#include <wtf/text/StringBuilder.h>
 #include <wtf/text/WTFString.h>
 
-#include <stdio.h>
-#include <string.h>
-
 #if HAVE(SIGNAL_H)
 #include <signal.h>
 #endif
 
 extern "C" {
 
+static void logToStderr(const char* buffer)
+{
+#if USE(APPLE_SYSTEM_LOG)
+    asl_log(0, 0, ASL_LEVEL_NOTICE, "%s", buffer);
+#endif
+    fputs(buffer, stderr);
+}
+
 WTF_ATTRIBUTE_PRINTF(1, 0)
 static void vprintf_stderr_common(const char* format, va_list args)
 {
@@ -96,10 +108,7 @@ static void vprintf_stderr_common(const char* format, va_list args)
 
         CFStringGetCString(str, buffer, length, kCFStringEncodingUTF8);
 
-#if USE(APPLE_SYSTEM_LOG)
-        asl_log(0, 0, ASL_LEVEL_NOTICE, "%s", buffer);
-#endif
-        fputs(buffer, stderr);
+        logToStderr(buffer);
 
         free(buffer);
         CFRelease(str);
@@ -412,15 +421,83 @@ void WTFReportError(const char* file, int line, const char* function, const char
     printCallSite(file, line, function);
 }
 
+class WTFLoggingAccumulator {
+public:
+    void accumulate(const String&);
+    void resetAccumulatedLogs();
+    String getAndResetAccumulatedLogs();
+
+private:
+    Lock accumulatorLock;
+    StringBuilder loggingAccumulator;
+};
+
+void WTFLoggingAccumulator::accumulate(const String& log)
+{
+    Locker<Lock> locker(accumulatorLock);
+    loggingAccumulator.append(log);
+}
+
+void WTFLoggingAccumulator::resetAccumulatedLogs()
+{
+    Locker<Lock> locker(accumulatorLock);
+    loggingAccumulator.clear();
+}
+
+String WTFLoggingAccumulator::getAndResetAccumulatedLogs()
+{
+    Locker<Lock> locker(accumulatorLock);
+    String result = loggingAccumulator.toString();
+    loggingAccumulator.clear();
+    return result;
+}
+
+static WTFLoggingAccumulator& loggingAccumulator()
+{
+    static WTFLoggingAccumulator* accumulator;
+    static std::once_flag initializeAccumulatorOnce;
+    std::call_once(initializeAccumulatorOnce, [] {
+        accumulator = new WTFLoggingAccumulator;
+    });
+
+    return *accumulator;
+}
+
 void WTFLog(WTFLogChannel* channel, const char* format, ...)
 {
-    if (channel->state != WTFLogChannelOn)
+    if (channel->state == WTFLogChannelOff)
         return;
 
+    if (channel->state == WTFLogChannelOn) {
+        va_list args;
+        va_start(args, format);
+        vprintf_stderr_with_trailing_newline(format, args);
+        va_end(args);
+        return;
+    }
+
+    ASSERT(channel->state == WTFLogChannelOnWithAccumulation);
+
     va_list args;
     va_start(args, format);
-    vprintf_stderr_with_trailing_newline(format, args);
+
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wformat-nonliteral"
+#endif
+    String loggingString = String::format(format, args);
+#if COMPILER(CLANG)
+#pragma clang diagnostic pop
+#endif
+
     va_end(args);
+
+    if (!loggingString.endsWith('\n'))
+        loggingString.append('\n');
+
+    loggingAccumulator().accumulate(loggingString);
+
+    logToStderr(loggingString.utf8().data());
 }
 
 void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel* channel, const char* format, ...)
@@ -430,7 +507,16 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann
 
     va_list args;
     va_start(args, format);
-    vprintf_stderr_with_trailing_newline(format, args);
+
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wformat-nonliteral"
+#endif
+    WTFLog(channel, format, args);
+#if COMPILER(CLANG)
+#pragma clang diagnostic pop
+#endif
+
     va_end(args);
 
     printCallSite(file, line, function);
@@ -503,3 +589,17 @@ void WTFInitializeLogChannelStatesFromString(WTFLogChannel* channels[], size_t c
 }
 
 } // extern "C"
+
+namespace WTF {
+
+void resetAccumulatedLogs()
+{
+    loggingAccumulator().resetAccumulatedLogs();
+}
+
+String getAndResetAccumulatedLogs()
+{
+    return loggingAccumulator().getAndResetAccumulatedLogs();
+}
+
+} // namespace WTF
index b48c862..0b3b712 100644 (file)
@@ -130,7 +130,7 @@ extern "C" {
 #define NO_RETURN_DUE_TO_CRASH
 #endif
 
-typedef enum { WTFLogChannelOff, WTFLogChannelOn } WTFLogChannelState;
+typedef enum { WTFLogChannelOff, WTFLogChannelOn, WTFLogChannelOnWithAccumulation } WTFLogChannelState;
 
 typedef struct {
     WTFLogChannelState state;
diff --git a/Source/WTF/wtf/LoggingAccumulator.h b/Source/WTF/wtf/LoggingAccumulator.h
new file mode 100644 (file)
index 0000000..a8e2320
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 INC. OR
+ * 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. 
+ */
+
+#pragma once
+
+#include <wtf/text/WTFString.h>
+
+namespace WTF {
+
+WTF_EXPORT_PRIVATE void resetAccumulatedLogs();
+WTF_EXPORT_PRIVATE String getAndResetAccumulatedLogs();
+
+} // namespace WTF
+
+using WTF::resetAccumulatedLogs;
+using WTF::getAndResetAccumulatedLogs;
index ce376e2..7991f47 100644 (file)
@@ -463,6 +463,24 @@ String String::format(const char *format, ...)
     va_list args;
     va_start(args, format);
 
+#if USE(CF) && !OS(WINDOWS)
+    if (strstr(format, "%@")) {
+        RetainPtr<CFStringRef> cfFormat = adoptCF(CFStringCreateWithCString(kCFAllocatorDefault, format, kCFStringEncodingUTF8));
+
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wformat-nonliteral"
+#endif
+        RetainPtr<CFStringRef> result = adoptCF(CFStringCreateWithFormatAndArguments(kCFAllocatorDefault, nullptr, cfFormat.get(), args));
+#if COMPILER(CLANG)
+#pragma clang diagnostic pop
+#endif
+
+        va_end(args);
+        return result.get();
+    }
+#endif // USE(CF) && !OS(WINDOWS)
+
     // Do the format once to get the length.
 #if COMPILER(MSVC)
     int result = _vscprintf(format, args);
index 720881a..f021e5e 100644 (file)
@@ -1,3 +1,22 @@
+2016-05-02  Brady Eidson  <beidson@apple.com>
+
+        Add the ability to accumulate logs for specific logging channels to help diagnose test timeouts.
+        https://bugs.webkit.org/show_bug.cgi?id=157274
+
+        Reviewed by Alex Christensen.
+
+        * platform/Logging.cpp:
+        (WebCore::setLogChannelToAccumulate): Set the given log channel to accumulate logging,
+          and dirty the initializeLoggingChannelsIfNecessary flag.
+        (WebCore::initializeLoggingChannelsIfNecessary): Change from being a one-time-only call to a 
+          one-time-for-each-time-somebody-calls-setLogChannelToAccumulate call.
+        * platform/Logging.h:
+
+        * testing/js/WebCoreTestSupport.cpp:
+        (WebCoreTestSupport::setLogChannelToAccumulate):
+        (WebCoreTestSupport::initializeLoggingChannelsIfNecessary):
+        * testing/js/WebCoreTestSupport.h:
+
 2016-05-02  Simon Fraser  <simon.fraser@apple.com>
 
         Sort the project file.
index 0003b78..5bac603 100644 (file)
@@ -57,12 +57,24 @@ bool isLogChannelEnabled(const String& name)
     return channel->state != WTFLogChannelOff;
 }
 
+static bool logChannelsNeedInitialization = true;
+
+void setLogChannelToAccumulate(const String& name)
+{
+    WTFLogChannel* channel = WTFLogChannelByName(logChannels, logChannelCount, name.utf8().data());
+    if (!channel)
+        return;
+
+    channel->state = WTFLogChannelOnWithAccumulation;
+    logChannelsNeedInitialization = true;
+}
+
 void initializeLoggingChannelsIfNecessary()
 {
-    static bool haveInitializedLoggingChannels = false;
-    if (haveInitializedLoggingChannels)
+    if (!logChannelsNeedInitialization)
         return;
-    haveInitializedLoggingChannels = true;
+
+    logChannelsNeedInitialization = false;
 
     WTFInitializeLogChannelStatesFromString(logChannels, logChannelCount, logLevelString().utf8().data());
 }
index afa1519..c6906ec 100644 (file)
@@ -97,6 +97,7 @@ WEBCORE_LOG_CHANNELS(DECLARE_LOG_CHANNEL)
 
 String logLevelString();
 bool isLogChannelEnabled(const String& name);
+WEBCORE_EXPORT void setLogChannelToAccumulate(const String& name);
 WEBCORE_EXPORT void initializeLoggingChannelsIfNecessary();
 #ifndef NDEBUG
 void registerNotifyCallback(const String& notifyID, std::function<void()> callback);
index 7f5a585..4821014 100644 (file)
@@ -31,6 +31,7 @@
 #include "Internals.h"
 #include "JSDocument.h"
 #include "JSInternals.h"
+#include "Logging.h"
 #include "Page.h"
 #include "WheelEventTestTrigger.h"
 #include <JavaScriptCore/APICast.h>
@@ -97,4 +98,20 @@ void clearWheelEventTestTrigger(WebCore::Frame& frame)
     page->clearTrigger();
 }
 
+void setLogChannelToAccumulate(const String& name)
+{
+#if !LOG_DISABLED
+    WebCore::setLogChannelToAccumulate(name);
+#else
+    UNUSED_PARAM(name);
+#endif
+}
+
+void initializeLoggingChannelsIfNecessary()
+{
+#if !LOG_DISABLED
+    WebCore::initializeLoggingChannelsIfNecessary();
+#endif
+}
+
 }
index 1dc8333..648962c 100644 (file)
@@ -35,6 +35,10 @@ typedef struct OpaqueJSValue* JSObjectRef;
 #define TEST_SUPPORT_EXPORT
 #endif
 
+namespace WTF {
+class String;
+}
+
 namespace WebCore {
 class Frame;
 }
@@ -47,6 +51,9 @@ void monitorWheelEvents(WebCore::Frame&) TEST_SUPPORT_EXPORT;
 void setTestCallbackAndStartNotificationTimer(WebCore::Frame&, JSContextRef, JSObjectRef) TEST_SUPPORT_EXPORT;
 void clearWheelEventTestTrigger(WebCore::Frame&) TEST_SUPPORT_EXPORT;
 
+void setLogChannelToAccumulate(const WTF::String& name) TEST_SUPPORT_EXPORT;
+void initializeLoggingChannelsIfNecessary() TEST_SUPPORT_EXPORT;
+
 } // namespace WebCore
 
 #endif
index 1d64f85..4946db2 100644 (file)
@@ -1,3 +1,27 @@
+2016-05-02  Brady Eidson  <beidson@apple.com>
+
+        Add the ability to accumulate logs for specific logging channels to help diagnose test timeouts.
+        https://bugs.webkit.org/show_bug.cgi?id=157274
+
+        Reviewed by Alex Christensen.
+
+        Add the new accumulate method to DRT's TestRunner, dump the accumulated logs if there's a timeout,
+        and reset them in between tests:
+        * DumpRenderTree/TestRunner.cpp:
+        (accummulateLogsForChannel):
+        (TestRunner::staticFunctions):
+        (TestRunner::waitToDumpWatchdogTimerFired):
+        (TestRunner::setAccummulateLogsForChannel):
+        * DumpRenderTree/TestRunner.h:
+        * DumpRenderTree/mac/DumpRenderTree.mm:
+        (resetWebViewToConsistentStateBeforeTesting):
+
+        Also add the new method to WKTR's TestRunner, but just stubbed for now:
+        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+        * WebKitTestRunner/InjectedBundle/TestRunner.cpp:
+        (WTR::TestRunner::accummulateLogsForChannel):
+        * WebKitTestRunner/InjectedBundle/TestRunner.h:
+
 2016-05-02  Srinivasan Vijayaraghavan  <svijayaraghavan@apple.com>
 
         Add fail-fast option to run-javascriptcore-tests
index a69c0f1..c0a62d7 100644 (file)
@@ -30,6 +30,7 @@
 #include "config.h"
 #include "TestRunner.h"
 
+#include "WebCoreTestSupport.h"
 #include "WorkQueue.h"
 #include "WorkQueueItem.h"
 #include <JavaScriptCore/APICast.h>
@@ -37,6 +38,7 @@
 #include <JavaScriptCore/JSCTestRunnerUtils.h>
 #include <JavaScriptCore/JSObjectRef.h>
 #include <JavaScriptCore/JSRetainPtr.h>
+#include <WebCore/Logging.h>
 #include <cstring>
 #include <locale.h>
 #include <runtime/ArrayBufferView.h>
 #include <stdio.h>
 #include <wtf/Assertions.h>
 #include <wtf/CurrentTime.h>
+#include <wtf/LoggingAccumulator.h>
 #include <wtf/MathExtras.h>
 #include <wtf/RefPtr.h>
 #include <wtf/StdLibExtras.h>
+#include <wtf/text/WTFString.h>
 
 #if PLATFORM(MAC) && !PLATFORM(IOS)
 #include <Carbon/Carbon.h>
@@ -1968,6 +1972,20 @@ static JSValueRef neverInlineFunction(JSContextRef context, JSObjectRef function
     return JSC::setNeverInline(context, arguments[0]);
 }
 
+static JSValueRef accummulateLogsForChannel(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    if (argumentCount < 1)
+        return JSValueMakeUndefined(context);
+
+    JSRetainPtr<JSStringRef> channel(Adopt, JSValueToStringCopy(context, arguments[0], exception));
+    ASSERT(!*exception);
+
+    TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
+    controller->setAccummulateLogsForChannel(channel.get());
+
+    return JSValueMakeUndefined(context);
+}
+
 static void testRunnerObjectFinalize(JSObjectRef object)
 {
     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(object));
@@ -2172,6 +2190,7 @@ JSStaticFunction* TestRunner::staticFunctions()
         { "failNextNewCodeBlock", failNextNewCodeBlock, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "numberOfDFGCompiles", numberOfDFGCompiles, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "neverInlineFunction", neverInlineFunction, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+        { "accummulateLogsForChannel", accummulateLogsForChannel, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { 0, 0, 0 }
     };
 
@@ -2222,6 +2241,13 @@ void TestRunner::waitToDumpWatchdogTimerFired()
 {
     const char* message = "FAIL: Timed out waiting for notifyDone to be called\n";
     fprintf(stdout, "%s", message);
+
+    auto accumulatedLogs = getAndResetAccumulatedLogs();
+    if (!accumulatedLogs.isEmpty()) {
+        const char* message = "Logs accumulated during test run:\n";
+        fprintf(stdout, "%s%s\n", message, accumulatedLogs.utf8().data());
+    }
+
     notifyDone();
 }
 
@@ -2252,3 +2278,12 @@ void TestRunner::setShouldPaintBrokenImage(bool shouldPaintBrokenImage)
 {
     m_shouldPaintBrokenImage = shouldPaintBrokenImage;
 }
+
+void TestRunner::setAccummulateLogsForChannel(JSStringRef channel)
+{
+    size_t maxLength = JSStringGetMaximumUTF8CStringSize(channel);
+    auto buffer = std::make_unique<char[]>(maxLength + 1);
+    JSStringGetUTF8CString(channel, buffer.get(), maxLength + 1);
+
+    WebCoreTestSupport::setLogChannelToAccumulate({ buffer.get() });
+}
index 731c8d1..f1b7bea 100644 (file)
@@ -135,6 +135,8 @@ public:
     void setTextAutosizingEnabled(bool);
 #endif
 
+    void setAccummulateLogsForChannel(JSStringRef);
+
     // Legacy here refers to the old TestRunner API for handling web notifications, not the legacy web notification API.
     void ignoreLegacyWebNotificationPermissionRequests();
     // Legacy here refers to the old TestRunner API for handling web notifications, not the legacy web notification API.
index c6d850f..9b42e36 100644 (file)
@@ -58,6 +58,7 @@
 #import <CoreFoundation/CoreFoundation.h>
 #import <JavaScriptCore/HeapStatistics.h>
 #import <JavaScriptCore/Options.h>
+#import <WebCore/Logging.h>
 #import <WebKit/DOMElement.h>
 #import <WebKit/DOMExtensions.h>
 #import <WebKit/DOMRange.h>
@@ -86,6 +87,7 @@
 #import <getopt.h>
 #import <wtf/Assertions.h>
 #import <wtf/FastMalloc.h>
+#import <wtf/LoggingAccumulator.h>
 #import <wtf/ObjcRuntimeExtras.h>
 #import <wtf/RetainPtr.h>
 #import <wtf/Threading.h>
@@ -1894,6 +1896,9 @@ static void resetWebViewToConsistentStateBeforeTesting()
 #endif
 
     [mainFrame _clearOpener];
+
+    resetAccumulatedLogs();
+    WebCoreTestSupport::initializeLoggingChannelsIfNecessary();
 }
 
 #if PLATFORM(IOS)
index a43037d..3fe186f 100644 (file)
@@ -223,5 +223,7 @@ interface TestRunner {
     void runUIScript(DOMString script, object callback);
 
     void clearTestRunnerCallbacks();
+
+    void accummulateLogsForChannel(DOMString channel);
 };
 
index e7d6f5f..0152417 100644 (file)
@@ -601,6 +601,11 @@ void TestRunner::clearTestRunnerCallbacks()
     callbackMap().clear();
 }
 
+void TestRunner::accummulateLogsForChannel(JSStringRef)
+{
+    // FIXME: Implement getting the call to all processes.
+}
+
 void TestRunner::addChromeInputField(JSValueRef callback)
 {
     cacheTestRunnerCallback(AddChromeInputFieldCallbackID, callback);
index 7109453..d08c933 100644 (file)
@@ -320,6 +320,8 @@ public:
 
     void clearTestRunnerCallbacks();
 
+    void accummulateLogsForChannel(JSStringRef channel);
+
 private:
     TestRunner();