summaryrefslogtreecommitdiff
path: root/Tools/TestWebKitAPI
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/TestWebKitAPI')
-rw-r--r--Tools/TestWebKitAPI/CMakeLists.txt232
-rw-r--r--Tools/TestWebKitAPI/Counters.cpp36
-rw-r--r--Tools/TestWebKitAPI/Counters.h99
-rw-r--r--Tools/TestWebKitAPI/ForwardingHeaders/WebCore/LayoutUnit.h4
-rw-r--r--Tools/TestWebKitAPI/GNUmakefile.am934
-rw-r--r--Tools/TestWebKitAPI/InjectedBundleController.cpp7
-rw-r--r--Tools/TestWebKitAPI/InjectedBundleController.h4
-rw-r--r--Tools/TestWebKitAPI/InjectedBundleMain.cpp9
-rw-r--r--Tools/TestWebKitAPI/InjectedBundleTest.h2
-rw-r--r--Tools/TestWebKitAPI/JavaScriptTest.cpp9
-rw-r--r--Tools/TestWebKitAPI/JavaScriptTest.h13
-rw-r--r--Tools/TestWebKitAPI/PlatformGTK.cmake158
-rw-r--r--Tools/TestWebKitAPI/PlatformJSCOnly.cmake21
-rw-r--r--Tools/TestWebKitAPI/PlatformUtilities.cpp12
-rw-r--r--Tools/TestWebKitAPI/PlatformUtilities.h33
-rw-r--r--Tools/TestWebKitAPI/PlatformWebView.h45
-rw-r--r--Tools/TestWebKitAPI/Test.h16
-rw-r--r--Tools/TestWebKitAPI/Tests/JavaScriptCore/VMInspector.cpp689
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/AtomicString.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/BloomFilter.cpp250
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/CheckedArithmeticOperations.cpp554
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/Condition.cpp257
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/Consume.cpp141
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/CrossThreadTask.cpp150
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/DateMath.cpp208
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/DeletedAddressOfOperator.h84
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/Deque.cpp191
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/EnumTraits.cpp55
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/Expected.cpp512
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/Functional.cpp218
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/HashCountedSet.cpp468
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp780
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp354
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/LEBDecoder.cpp241
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/ListHashSet.cpp98
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/Lock.cpp189
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp65
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp6
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/NakedPtr.cpp238
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/OptionSet.cpp297
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/Optional.cpp150
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/ParkingLot.cpp273
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/RedBlackTree.cpp2
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/Ref.cpp57
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/RefCounter.cpp170
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/RefLogger.cpp37
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/RefLogger.h10
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/RefPtr.cpp58
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/RunLoop.cpp166
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/Scope.cpp53
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/ScopedLambda.cpp51
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/SetForScope.cpp (renamed from Tools/TestWebKitAPI/Tests/WTF/TemporaryChange.cpp)8
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/StringBuilder.cpp25
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/StringConcatenate.cpp121
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/StringHasher.cpp63
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp550
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/StringOperators.cpp16
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/StringView.cpp928
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp229
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/TextBreakIterator.cpp146
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/Time.cpp318
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/UniqueRef.cpp93
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/Variant.cpp228
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/Vector.cpp430
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp364
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/WeakPtr.cpp193
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/WorkQueue.cpp236
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/darwin/OSObjectPtr.cpp66
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/glib/GUniquePtr.cpp (renamed from Tools/TestWebKitAPI/Tests/WTF/gobject/GUniquePtr.cpp)2
-rw-r--r--Tools/TestWebKitAPI/Tests/WTF/glib/WorkQueueGLib.cpp71
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/AffineTransform.cpp1024
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/CARingBuffer.cpp251
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/CSSParser.cpp84
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/CalculationValue.cpp283
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/Color.cpp190
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/ComplexTextController.cpp391
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp2795
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/DFACombiner.cpp121
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/DFAHelpers.h67
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/DFAMinimizer.cpp121
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/ExtendedColor.cpp162
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/FileSystem.cpp122
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/FloatPoint.cpp598
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/FloatRect.cpp783
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/FloatSize.cpp328
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/GridPosition.cpp73
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/HTMLParserIdioms.cpp164
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/IntPoint.cpp283
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/IntRect.cpp615
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/IntSize.cpp332
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/LayoutUnit.cpp42
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/ParsedContentRange.cpp98
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/PublicSuffix.cpp78
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/SampleMap.cpp224
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/SecurityOrigin.cpp146
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/SharedBuffer.cpp163
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/SharedBufferTest.cpp56
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/SharedBufferTest.h46
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/TimeRanges.cpp291
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/TransformationMatrix.cpp1317
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/URL.cpp54
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp1305
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/UserAgentQuirks.cpp96
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/YouTubePluginReplacement.cpp86
-rw-r--r--Tools/TestWebKitAPI/Tests/WebCore/gtk/UserAgentQuirks.cpp63
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/18-characters.html0
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/AboutBlankLoad.cpp5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/Ahem.ttfbin0 -> 12480 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest_Bundle.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CloseFromWithinCreatePage.cpp94
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CloseThenTerminate.cpp5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CookieManager.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewIsActiveSetIsActive.cpp131
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewIsActiveSetIsActive_Bundle.cpp52
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewRestoreZoomAndScrollBackForward.cpp129
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewUserViewportToContents.cpp148
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/backforward1.html5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/backforward2.html1
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic_Bundle.cpp19
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache.cpp5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache_Bundle.cpp19
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls.cpp5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls_Bundle.cpp13
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DidNotHandleKeyDown.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DidRemoveFrameFromHiearchyInPageCache.cpp109
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DidRemoveFrameFromHiearchyInPageCache_Bundle.cpp75
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash_Bundle.cpp13
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/DownloadDecideDestinationCrash.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/EnumerateMediaDevices.cpp84
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/EphemeralSessionPushStateNoHistoryCallback.cpp87
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/EvaluateJavaScript.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/EventModifiers.cpp82
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/FailedLoad.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/Find.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ForceRepaint.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/FrameHandle.cpp70
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypeHTML.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypePNG.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/Geolocation.cpp55
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback_Bundle.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle_Bundle.cpp13
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic_Bundle.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest_Bundle.cpp17
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins_Bundle.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleMakeAllShadowRootsOpen.cpp109
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleMakeAllShadowRootsOpen_Bundle.cpp98
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/LayoutMilestonesWithAllContentInFrame.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/LimitTitleSize.cpp79
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/LoadAlternateHTMLStringWithNonDirectoryURL.cpp37
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback.cpp11
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback_Bundle.cpp11
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/LoadPageOnCrash.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/MenuTypesForMouseEvents.cpp149
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ModalAlertsSPI.cpp123
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash_Bundle.cpp5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames.cpp11
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout_Bundle.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/PageGroup.cpp80
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/PageLoadBasic.cpp27
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/PageLoadDidChangeLocationWithinPageForFrame.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame_Bundle.cpp11
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/PasteboardNotifications_Bundle.cpp89
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/PendingAPIRequestURL.cpp167
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/PreventEmptyUserAgent.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/PrivateBrowsingPushStateNoHistoryCallback.cpp32
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ProvisionalURLAfterWillSendRequestCallback.cpp89
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ProvisionalURLAfterWillSendRequestCallback_Bundle.cpp85
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ReloadPageAfterCrash.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ResizeReversePaginatedWebView.cpp11
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ResizeWindowAfterCrash.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly.cpp5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly_Bundle.cpp5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/RestoreSessionStateContainingFormData.cpp17
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/RestoreSessionStateWithoutNavigation.cpp105
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ScrollPinningBehaviors.cpp13
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem_Bundle.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/ShouldKeepCurrentBackForwardListItemInList.cpp163
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp27
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/StopLoadingDuringDidFailProvisionalLoad.cpp83
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/StopLoadingDuringDidFailProvisionalLoad_bundle.cpp81
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/TerminateTwice.cpp4
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/TextFieldDidBeginAndEndEditing.cpp137
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/TextFieldDidBeginAndEndEditing_Bundle.cpp76
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/UserMedia.cpp85
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/UserMessage.cpp13
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/UserMessage_Bundle.cpp5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKBundleFileHandle.cpp86
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKBundleFileHandle_Bundle.cpp99
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKImageCreateCGImageCrash.cpp41
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKPageConfiguration.cpp132
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKPageCopySessionStateWithFiltering.cpp136
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKPageGetScaleFactorNotZero.cpp15
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKPageIsPlayingAudio.cpp152
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKPreferences.cpp39
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKRetainPtr.cpp58
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKString.cpp4
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WKStringJSString.cpp7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WebArchive.cpp135
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WebArchive_Bundle.cpp69
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WebCoreStatisticsWithNoWebProcess.cpp55
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WillLoad.cpp11
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WillLoad_Bundle.cpp15
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent.cpp5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent_Bundle.cpp9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/all-content-in-one-iframe.html1
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/associate-form-controls.html31
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/auto-submitting-form.html20
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/autoplay-check-frame.html16
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/autoplay-check-in-iframe.html16
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/autoplay-check.html20
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/autoplay-no-audio-check.html20
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/autoplay-with-controls.html19
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/bundle-file.html16
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/chinese-character-with-image.html15
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/close-from-within-create-page.html16
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/closed-shadow-tree-test.html28
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/contentBlockerCheck.html13
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/custom-protocol-sync-xhr.html6
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/enumerateMediaDevices.html24
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/execCopy.html15
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/file-with-anchor.html19
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/file-with-mse.html41
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/file-with-video.html18
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/find.html5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/findRanges.html11
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/geolocationGetCurrentPosition.html3
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/geolocationGetCurrentPositionWithHighAccuracy.html3
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/geolocationWatchPosition.html3
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/geolocationWatchPositionWithHighAccuracy.html3
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/getUserMedia.html14
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/gtk/InputMethodFilter.cpp (renamed from Tools/TestWebKitAPI/Tests/gtk/InputMethodFilter.cpp)100
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/icon.pngbin0 -> 36541 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/input-focus-blur.html28
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/js-play-with-controls.html20
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/link-with-download-attribute.html10
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/link-with-title.html5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/lots-of-iframes.html35
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/lots-of-images.html17
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/lots-of-text-vertical-lr.html3
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/lots-of-text.html3
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/many-iframes.html15
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/modal-alerts-in-new-about-blank-window.html13
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/mouse-button-listener.html30
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/mouse-move-listener.html16
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/no-autoplay-with-controls.html25
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/open-and-close-window.html11
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/push-state.html3
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/set-long-title.html10
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/should-open-external-schemes.html21
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/simple-accelerated-compositing.html5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/simple-form.html11
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/simple-iframe.html6
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/simple-tall.html7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/simple.html5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/simple2.html5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/simple3.html5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/spacebar-scrolling.html26
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/test-mse.mp4bin0 -> 80933 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/test-without-audio-track.mp4bin0 -> 189906 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/test.mp4bin0 -> 192844 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2/webfont.html15
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/AllAhem.svg111
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ApplicationCache.dbbin0 -> 4096 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ApplicationCache.db-shmbin0 -> 32768 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ApplicationCache.db-walbin0 -> 168952 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/BundleEditingDelegateProtocol.h40
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/BundleRangeHandleProtocol.h35
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.h28
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.html6
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/CookieMessage.html4
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestBlobURL.html16
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURL.html10
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURL2.html6
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURLFrame.html10
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenDelegate.html31
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenLayoutConstraints.html31
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenTopContentInset.html31
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.html14
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3bin0 -> 4096 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3-shmbin0 -> 32768 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3-walbin0 -> 164832 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBIndexUpgradeToV2.html21
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexUpgrade.blob1
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexUpgrade.sqlite3bin0 -> 65536 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBDatabaseProcessKill-1.html33
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-1.html46
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-2.html92
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-3.html21
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBPersistence-1.html35
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBPersistence-2.html22
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LineBreaking.html45
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageClear.html6
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.html6
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.localstoragebin0 -> 12288 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.localstorage-shmbin0 -> 32768 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageQuirkEnabled.html10
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/RemoteObjectRegistry.h51
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/StoreBlobToBeDeleted.html41
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentWorldProtocol.h37
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebProcessKillIDBCleanup-1.html67
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebProcessKillIDBCleanup-2.html25
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/autofocused-text-input.html3
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/autoplaying-video-with-audio.html34
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/blinking-div.html23
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/change-video-source-on-click.html33
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/change-video-source-on-end.html35
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/duplicate-completion-handler-calls.html9
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/editable-body.html7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/enormous-video-with-sound.html15
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/focus-inputs.html15
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/full-size-autoplaying-video-with-audio.html23
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/input-field-in-scrollable-document.html36
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-input-field-focus-onload.html38
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-hides-controls-after-seek-to-end.html40
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-mutes-onplaying.html16
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-offscreen.html29
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-playing-scroll-away.html36
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-seek-after-ending.html21
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-seek-to-beginning-and-play-after-ending.html23
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-test-now-playing.html33
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-with-audio.html12
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-with-audio.mp4bin0 -> 1088986 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-without-audio.html29
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-click-to-pause.html47
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-scroll-to-video.html35
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-paused-video-hides-controls.html38
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-muted-video-hides-controls.html36
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-video-keeps-controls.html35
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-with-audio-autoplay.html18
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-with-audio.html18
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/open-multiple-external-url.html66
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/page-with-csp-iframe.html14
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/page-with-csp.html15
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/page-without-csp-iframe.html11
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/page-without-csp.html12
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/play-audio-on-click.html54
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/skinny-autoplaying-video-with-audio.html23
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/text-and-password-inputs.html39
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Cocoa/wide-autoplaying-video-with-audio.html23
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/AutocleanupsTest.cpp72
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/CMakeLists.txt135
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMDOMWindowTest.cpp221
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeFilterTest.cpp204
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeTest.cpp122
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMXPathNSResolverTest.cpp124
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/EditorTest.cpp131
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/FrameTest.cpp3
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAuthentication.cpp36
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAutocleanups.cpp70
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestBackForwardList.cpp137
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestConsoleMessage.cpp155
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp370
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestCookieManager.cpp71
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMDOMWindow.cpp152
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNode.cpp37
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNodeFilter.cpp55
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMXPathNSResolver.cpp52
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp351
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestEditor.cpp (renamed from Tools/TestWebKitAPI/Tests/WebKitGtk/testapplicationcache.c)35
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestFrame.cpp2
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspector.cpp17
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspectorServer.cpp12
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestLoaderClient.cpp211
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestMultiprocess.cpp77
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp207
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestResources.cpp108
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestSSL.cpp210
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp469
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebExtensions.cpp130
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitAccessibility.cpp5
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFaviconDatabase.cpp69
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFindController.cpp2
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitPolicyClient.cpp15
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSecurityOrigin.cpp142
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSettings.cpp23
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp360
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebContext.cpp412
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp561
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebViewGroup.cpp206
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebViewEditor.cpp328
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebsiteData.cpp537
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp199
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.cpp33
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.h4
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/blank.icobin0 -> 198 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/boring.html1
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/link-title.js1
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/silence.mpgbin0 -> 33227 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/simple.json1
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-cert.pem13
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-key.pem16
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/track.oggbin0 -> 3869 bytes
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/webkit2gtk-tests.gresource.xml7
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsInvalidScheme_Bundle.cpp66
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing_Bundle.cpp69
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/test_utils.c51
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testatk.c1476
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testatkroles.c426
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testcontextmenu.c317
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testcopyandpaste.c266
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdocument.c445
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdomwindow.c258
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testdomnode.c219
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testdownload.c325
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testfavicondatabase.c279
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testglobals.c110
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testhittestresult.c171
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testhttpbackend.c75
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testkeyevents.c390
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testloading.c437
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testmimehandling.c206
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkrequest.c96
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkresponse.c97
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testwebbackforwardlist.c326
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testwebdatasource.c242
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testwebframe.c220
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testwebhistoryitem.c70
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testwebinspector.c173
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testwebplugindatabase.c78
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testwebresource.c334
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testwebsettings.c110
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testwebview.c749
-rw-r--r--Tools/TestWebKitAPI/Tests/WebKitGtk/testwindow.c119
-rw-r--r--Tools/TestWebKitAPI/TestsController.cpp33
-rw-r--r--Tools/TestWebKitAPI/TestsController.h6
-rw-r--r--Tools/TestWebKitAPI/Utilities.h36
-rw-r--r--Tools/TestWebKitAPI/WKWebViewConfigurationExtras.h34
-rw-r--r--Tools/TestWebKitAPI/WTFStringUtilities.h13
-rw-r--r--Tools/TestWebKitAPI/config.h38
-rw-r--r--Tools/TestWebKitAPI/gtk/PlatformUtilitiesGtk.cpp6
-rw-r--r--Tools/TestWebKitAPI/gtk/PlatformWebViewGtk.cpp40
-rw-r--r--Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.cpp83
-rw-r--r--Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.h6
-rw-r--r--Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.cpp23
-rw-r--r--Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.h80
-rw-r--r--Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.cpp59
-rw-r--r--Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.h6
-rw-r--r--Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.cpp26
-rw-r--r--Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.h13
-rw-r--r--Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp100
-rw-r--r--Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h31
-rw-r--r--Tools/TestWebKitAPI/gtk/main.cpp2
-rw-r--r--Tools/TestWebKitAPI/jsconly/PlatformUtilitiesJSCOnly.cpp57
-rw-r--r--Tools/TestWebKitAPI/jsconly/main.cpp32
461 files changed, 37366 insertions, 11532 deletions
diff --git a/Tools/TestWebKitAPI/CMakeLists.txt b/Tools/TestWebKitAPI/CMakeLists.txt
new file mode 100644
index 000000000..de2699e37
--- /dev/null
+++ b/Tools/TestWebKitAPI/CMakeLists.txt
@@ -0,0 +1,232 @@
+set(TESTWEBKITAPI_DIR "${TOOLS_DIR}/TestWebKitAPI")
+set(test_wtf_LIBRARIES
+ WTF${DEBUG_SUFFIX}
+ gtest
+)
+
+set(test_webcore_LIBRARIES
+ WTF${DEBUG_SUFFIX}
+ WebCore${DEBUG_SUFFIX}
+ gtest
+)
+
+set(TestWebKitAPI_LIBRARIES
+ WTF${DEBUG_SUFFIX}
+)
+
+if (ENABLE_WEBKIT2)
+ set(test_webkit2_api_LIBRARIES
+ JavaScriptCore
+ TestWebKitAPIBase
+ WTF
+ WebKit2
+ gtest
+ )
+ list(APPEND TestWebKitAPI_LIBRARIES
+ WebKit2
+ )
+else ()
+ list(APPEND TestWebKitAPI_LIBRARIES
+ WebKit${DEBUG_SUFFIX}
+ )
+endif ()
+
+
+set(TestJavaScriptCore_LIBRARIES
+ JavaScriptCore
+ gtest
+)
+
+set(TestWTF_SOURCES
+ ${TESTWEBKITAPI_DIR}/Counters.cpp
+ ${TESTWEBKITAPI_DIR}/TestsController.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/AtomicString.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/BloomFilter.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/Consume.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/CrossThreadTask.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/CString.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/CheckedArithmeticOperations.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/Condition.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/DateMath.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/Deque.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/EnumTraits.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/Expected.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/HashCountedSet.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/HashMap.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/HashSet.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/IntegerToStringConversion.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/ListHashSet.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/Lock.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/MD5.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/MathExtras.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/MediaTime.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/MetaAllocator.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/NakedPtr.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/Optional.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/OptionSet.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/ParkingLot.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/RedBlackTree.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/Ref.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/RefCounter.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/RefLogger.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/RefPtr.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/SHA1.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/SaturatedArithmeticOperations.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/Scope.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/ScopedLambda.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/SetForScope.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/StringBuilder.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/StringHasher.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/StringImpl.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/StringOperators.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/StringView.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/TextBreakIterator.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/Time.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/UniqueRef.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/Variant.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/Vector.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/WTFString.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/WeakPtr.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/WorkQueue.cpp
+)
+
+# FIXME: Tests/WTF/RunLoop.cpp is missing because it doesn't work for Windows.
+# FIXME: Platform-specific sources in Tests/WTF are not included in TestWTF_SOURCES.
+
+WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS()
+
+include_directories(
+ ${TESTWEBKITAPI_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/Source
+ ${JAVASCRIPTCORE_DIR}
+ ${THIRDPARTY_DIR}/gtest/include
+ ${WEBKIT2_DIR}/Platform/IPC
+ ${WEBKIT2_DIR}/Shared
+ ${WEBKIT2_DIR}/Shared/API
+ ${WEBKIT2_DIR}/Shared/API/c
+ ${WEBKIT2_DIR}/Shared/Plugins
+ ${WEBKIT2_DIR}/UIProcess
+ ${WEBKIT2_DIR}/UIProcess/API
+ ${WEBKIT2_DIR}/WebProcess/InjectedBundle
+ ${WEBKIT2_DIR}/WebProcess/InjectedBundle/API/c
+)
+
+if (ENABLE_WEBKIT2)
+ add_library(TestWebKitAPIInjectedBundle SHARED
+ ${bundle_harness_SOURCES}
+ ${TESTWEBKITAPI_DIR}/InjectedBundleController.cpp
+ ${TESTWEBKITAPI_DIR}/InjectedBundleMain.cpp
+ ${TESTWEBKITAPI_DIR}/PlatformUtilities.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/CanHandleRequest_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/DidAssociateFormControls_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/DOMWindowExtensionBasic_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/DOMWindowExtensionNoCache_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/DocumentStartUserScriptAlertCrash_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/HitTestResultNodeHandle_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/InjectedBundleBasic_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/InjectedBundleFrameHitTest_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/LoadCanceledNoServerRedirectCallback_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/MouseMoveAfterCrash_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/ParentFrame_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/ProvisionalURLAfterWillSendRequestCallback_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/ShouldGoToBackForwardListItem_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/TextFieldDidBeginAndEndEditing_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/UserMessage_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WillLoad_Bundle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WillSendSubmitEvent_Bundle.cpp
+ )
+
+ target_link_libraries(TestWebKitAPIInjectedBundle ${TestWebKitAPI_LIBRARIES})
+ add_dependencies(TestWebKitAPIInjectedBundle WTF ${ForwardingHeadersForTestWebKitAPI_NAME})
+
+ get_property(TestWebKitAPIInjectedBundle_PATH TARGET TestWebKitAPIInjectedBundle PROPERTY LOCATION)
+endif ()
+
+if (WIN32)
+ add_definitions(-DGTEST_LINKED_AS_SHARED_LIBRARY=0)
+else ()
+ add_definitions(-DGTEST_LINKED_AS_SHARED_LIBRARY=1)
+endif ()
+
+add_definitions(-DGTEST_HAS_RTTI=0
+ -DTEST_WEBKIT2_RESOURCES_DIR=\"${TESTWEBKITAPI_DIR}/Tests/WebKit2\"
+ -DTEST_INJECTED_BUNDLE_PATH=\"${TestWebKitAPIInjectedBundle_PATH}\"
+)
+
+# FIXME: This works around compatibility problems in the old version of the third-pary
+# googletest source code checkout. It should be removed once we upgrade to a newer version.
+if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+ add_definitions(-DGTEST_HAS_TR1_TUPLE=0)
+endif ()
+
+add_executable(TestWTF
+ ${test_main_SOURCES}
+ ${TestWTF_SOURCES}
+)
+
+if (WIN32)
+ add_dependencies(TestWTF TestWTFLib)
+endif ()
+
+target_link_libraries(TestWTF ${test_wtf_LIBRARIES})
+add_dependencies(TestWTF WTF ${ForwardingHeadersForTestWebKitAPI_NAME} ${ForwardingNetworkHeadersForTestWebKitAPI_NAME})
+add_test(TestWTF ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY_WTF}/TestWTF)
+set_tests_properties(TestWTF PROPERTIES TIMEOUT 60)
+set_target_properties(TestWTF PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY_WTF}
+)
+
+# FIXME: EFL is the only port that separates the WebCore binaries. Each port ought to do closer to the same thing.
+foreach (testName ${test_webcore_BINARIES})
+ add_executable(${testName} ${test_main_SOURCES} ${TESTWEBKITAPI_DIR}/TestsController.cpp ${TESTWEBKITAPI_DIR}/Tests/WebCore/${testName}.cpp)
+ add_test(${testName} ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebCore/${testName})
+ set_tests_properties(${testName} PROPERTIES TIMEOUT 60)
+ target_link_libraries(${testName} ${test_webcore_LIBRARIES})
+ set_target_properties(${testName} PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebCore
+ )
+endforeach ()
+
+if (ENABLE_WEBKIT2)
+ add_library(TestWebKitAPIBase
+ ${test_main_SOURCES}
+ ${webkit2_api_harness_SOURCES}
+ ${TESTWEBKITAPI_DIR}/JavaScriptTest.cpp
+ ${TESTWEBKITAPI_DIR}/PlatformUtilities.cpp
+ ${TESTWEBKITAPI_DIR}/TestsController.cpp
+ )
+
+ target_link_libraries(TestWebKitAPIBase JavaScriptCore WTF WebKit2 gtest)
+
+ add_dependencies(TestWebKitAPIBase WebKit2 ${ForwardingHeadersForTestWebKitAPI_NAME} ${ForwardingNetworkHeadersForTestWebKitAPI_NAME})
+
+ foreach (testName ${test_webkit2_api_BINARIES})
+ get_filename_component(testBaseName ${testName} NAME)
+ add_executable(${testBaseName} ${TESTWEBKITAPI_DIR}/Tests/WebKit2/${testName}.cpp)
+ add_test(${testBaseName} ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebKit2/${testBaseName})
+ set_tests_properties(${testBaseName} PROPERTIES TIMEOUT 60)
+ target_link_libraries(${testBaseName} ${test_webkit2_api_LIBRARIES})
+ set_target_properties(${testBaseName} PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebKit2
+ )
+ endforeach ()
+
+ # We don't run tests that are expected to fail. We could use the WILL_FAIL
+ # property, but it reports failure when the test crashes or timeouts and would
+ # make the bot red.
+ foreach (testName ${test_webkit2_api_fail_BINARIES})
+ add_executable(${testName} ${TESTWEBKITAPI_DIR}/Tests/WebKit2/${testName}.cpp)
+ target_link_libraries(${testName} ${test_webkit2_api_LIBRARIES})
+ set_target_properties(${testName} PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebKit2/failure
+ )
+ endforeach ()
+endif ()
diff --git a/Tools/TestWebKitAPI/Counters.cpp b/Tools/TestWebKitAPI/Counters.cpp
new file mode 100644
index 000000000..536a434bf
--- /dev/null
+++ b/Tools/TestWebKitAPI/Counters.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2014, 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. 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 INC. 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.
+ */
+
+#include "config.h"
+#include "Counters.h"
+
+unsigned CopyMoveCounter::constructionCount = 0;
+unsigned CopyMoveCounter::copyCount = 0;
+unsigned CopyMoveCounter::moveCount = 0;
+
+unsigned ConstructorDestructorCounter::constructionCount = 0;
+unsigned ConstructorDestructorCounter::destructionCount = 0;
+
+template<> unsigned DeleterCounter<ConstructorDestructorCounter>::m_deleterCount = 0;
diff --git a/Tools/TestWebKitAPI/Counters.h b/Tools/TestWebKitAPI/Counters.h
new file mode 100644
index 000000000..f9ea22402
--- /dev/null
+++ b/Tools/TestWebKitAPI/Counters.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ * Copyright (C) 2014, 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. 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 INC. 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.
+ */
+
+#ifndef Counters_h
+#define Counters_h
+
+struct CopyMoveCounter {
+ static unsigned constructionCount;
+ static unsigned copyCount;
+ static unsigned moveCount;
+
+ struct TestingScope {
+ TestingScope()
+ {
+ constructionCount = 0;
+ copyCount = 0;
+ moveCount = 0;
+ }
+ };
+
+ CopyMoveCounter() { constructionCount++; }
+ CopyMoveCounter(const CopyMoveCounter&) { copyCount++; }
+ CopyMoveCounter& operator=(const CopyMoveCounter&) { copyCount++; return *this; }
+ CopyMoveCounter(CopyMoveCounter&&) { moveCount++; }
+ CopyMoveCounter& operator=(CopyMoveCounter&&) { moveCount++; return *this; }
+};
+
+
+struct ConstructorDestructorCounter {
+ static unsigned constructionCount;
+ static unsigned destructionCount;
+
+ struct TestingScope {
+ TestingScope()
+ {
+ constructionCount = 0;
+ destructionCount = 0;
+ }
+ };
+
+ ConstructorDestructorCounter() { constructionCount++; }
+ ~ConstructorDestructorCounter() { destructionCount++; }
+};
+
+#if COMPILER(CLANG)
+#if __has_warning("-Wundefined-var-template")
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wundefined-var-template"
+#endif
+#endif
+template<typename T>
+struct DeleterCounter {
+ static unsigned m_deleterCount;
+
+ static unsigned deleterCount() { return m_deleterCount; }
+
+ struct TestingScope {
+ TestingScope()
+ {
+ m_deleterCount = 0;
+ }
+ };
+
+ void operator()(T* p) const
+ {
+ m_deleterCount++;
+ delete p;
+ }
+};
+#if COMPILER(CLANG)
+#if __has_warning("-Wundefined-var-template")
+#pragma clang diagnostic pop
+#endif
+#endif
+
+#endif // Counters_h
diff --git a/Tools/TestWebKitAPI/ForwardingHeaders/WebCore/LayoutUnit.h b/Tools/TestWebKitAPI/ForwardingHeaders/WebCore/LayoutUnit.h
new file mode 100644
index 000000000..de0a7454e
--- /dev/null
+++ b/Tools/TestWebKitAPI/ForwardingHeaders/WebCore/LayoutUnit.h
@@ -0,0 +1,4 @@
+#ifndef TestWebKitAPI_FWD_LayoutUnit_h
+#define TestWebKitAPI_FWD_LayoutUnit_h
+#include <LayoutUnit.h>
+#endif
diff --git a/Tools/TestWebKitAPI/GNUmakefile.am b/Tools/TestWebKitAPI/GNUmakefile.am
deleted file mode 100644
index 2ea61734d..000000000
--- a/Tools/TestWebKitAPI/GNUmakefile.am
+++ /dev/null
@@ -1,934 +0,0 @@
-noinst_LTLIBRARIES += \
- Libraries/libTestWebKitAPIMain.la
-
-if ENABLE_WEBKIT2
-noinst_LTLIBRARIES += \
- Libraries/libTestWebKit2GtkAPI.la
-endif
-
-Libraries_libTestWebKitAPIMain_la_SOURCES = \
- Tools/TestWebKitAPI/Test.h \
- Tools/TestWebKitAPI/TestsController.cpp \
- Tools/TestWebKitAPI/TestsController.h \
- Tools/TestWebKitAPI/gtk/main.cpp
-
-# Use -isystem gcc flag so that gcc considers gtest headers as system headers.
-# We need this to avoid a lot of compile warnings due to -Wundef.
-# See http://code.google.com/p/googletest/issues/detail?id=258
-Libraries_libTestWebKitAPIMain_la_CPPFLAGS = \
- -isystem $(srcdir)/Source/ThirdParty/gtest/include \
- -I$(srcdir)/Tools/TestWebKitAPI \
- -I$(srcdir)/Source/ThirdParty/gtest/include \
- -I$(top_builddir)/DerivedSources/WebCore/include \
- -I$(top_builddir)/DerivedSources/WebKit2/include \
- $(global_cppflags) \
- $(javascriptcore_cppflags) \
- $(GTK_CFLAGS)
-
-webkitgtk_tests_cflags = \
- -fno-strict-aliasing \
- -DTEST_PLUGIN_DIR=\"${shell pwd}/${top_builddir}/TestNetscapePlugin/.libs\" \
- -I$(srcdir)/Source/JavaScriptCore/ForwardingHeaders \
- -I$(WebKit) \
- -I$(GENSOURCES) \
- -I$(top_builddir)/Source/WebKit/gtk \
- -I$(top_srcdir)/Source/WebCore/bindings \
- -I$(top_srcdir)/Source/WebCore/bindings/gobject \
- $(global_cppflags) \
- $(global_cflags) \
- $(javascriptcore_cppflags) \
- $(FREETYPE_CFLAGS) \
- $(GLIB_CFLAGS) \
- $(GTK_CFLAGS) \
- $(LIBSOUP_CFLAGS) \
- $(XRENDER_CFLAGS) \
- $(XT_CFLAGS)
-
-webkitgtk_tests_ldadd = \
- libjavascriptcoregtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- libwebkitgtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- $(FREETYPE_LIBS) \
- $(GTK_LIBS) \
- $(GLIB_LIBS) \
- $(LIBSOUP_LIBS) \
- $(XRENDER_LIBS)
-
-webkitgtk_tests_ldflags = \
- -no-install
-
-
-webkit2gtk_tests_cppflags = \
- -DWEBKIT_EXEC_PATH=\"${shell pwd}/$(top_builddir)/Programs\" \
- -DWEBKIT_SRC_DIR=\"${shell pwd}/${srcdir}\" \
- -DWEBKIT_DERIVED_SRC_DIR=\"${shell pwd}/${top_builddir}/DerivedSources\" \
- -DWEBKIT_TEST_PLUGIN_DIR=\"${shell pwd}/${top_builddir}/TestNetscapePlugin/.libs\" \
- -DWEBKIT_TEST_WEB_EXTENSIONS_DIR=\"${shell pwd}/${top_builddir}/Libraries/WebExtensions/.libs\" \
- -DWEBKIT_INJECTED_BUNDLE_PATH=\"${shell pwd}/$(top_builddir)/.libs\" \
- $(javascriptcore_cppflags) \
- -I$(srcdir)/Source \
- -I$(srcdir)/Source/WebKit2 \
- -I$(srcdir)/Source/JavaScriptCore \
- -I$(srcdir)/Tools/TestWebKitAPI/gtk/WebKit2Gtk \
- -I$(top_builddir)/DerivedSources/WebKit2/include \
- -I$(top_builddir)/DerivedSources/WebKit2/webkit2gtk \
- -I$(top_builddir)/DerivedSources/WebKit2/webkit2gtk/include \
- -I$(srcdir)/Source/WebKit2/UIProcess/API/gtk \
- $(global_cppflags) \
- $(FREETYPE_CFLAGS) \
- $(GLIB_CFLAGS) \
- $(GTK_CFLAGS) \
- $(LIBSOUP_CFLAGS)
-
-webkit2gtk_tests_ldadd = \
- Libraries/libTestWebKit2GtkAPI.la \
- libjavascriptcoregtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- libwebkit2gtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- $(FREETYPE_LIBS) \
- $(GEOCLUE_LIBS) \
- $(GLIB_LIBS) \
- $(GTK_LIBS) \
- $(LIBSOUP_LIBS)
-
-webkit2gtk_tests_ldflags = \
- -no-install
-
-Libraries_libTestWebKit2GtkAPI_la_SOURCES = \
- Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.cpp \
- Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.h \
- Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.cpp \
- Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.h \
- Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.cpp \
- Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.h \
- Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.cpp \
- Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.h \
- Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp \
- Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h
-
-Libraries_libTestWebKit2GtkAPI_la_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-
-
-noinst_PROGRAMS += \
- Programs/TestWebKitAPI/WTF/TestWTF \
- Programs/TestWebKitAPI/JavaScriptCore/TestJavaScriptCore \
- Programs/TestWebKitAPI/WebCore/TestWebCore
-
-if ENABLE_WEBKIT1
-noinst_PROGRAMS += \
- Programs/TestWebKitAPI/WebKitGtk/testapplicationcache \
- Programs/TestWebKitAPI/WebKitGtk/testcontextmenu \
- Programs/TestWebKitAPI/WebKitGtk/testdomdocument \
- Programs/TestWebKitAPI/WebKitGtk/testdomdomwindow \
- Programs/TestWebKitAPI/WebKitGtk/testdomnode \
- Programs/TestWebKitAPI/WebKitGtk/testhttpbackend \
- Programs/TestWebKitAPI/WebKitGtk/testfavicondatabase \
- Programs/TestWebKitAPI/WebKitGtk/testloading \
- Programs/TestWebKitAPI/WebKitGtk/testglobals \
- Programs/TestWebKitAPI/WebKitGtk/testmimehandling \
- Programs/TestWebKitAPI/WebKitGtk/testnetworkrequest \
- Programs/TestWebKitAPI/WebKitGtk/testnetworkresponse \
- Programs/TestWebKitAPI/WebKitGtk/testwebframe \
- Programs/TestWebKitAPI/WebKitGtk/testwebbackforwardlist \
- Programs/TestWebKitAPI/WebKitGtk/testwebhistoryitem \
- Programs/TestWebKitAPI/WebKitGtk/testwindow \
- Programs/TestWebKitAPI/WebKitGtk/testdownload \
- Programs/TestWebKitAPI/WebKitGtk/testatk \
- Programs/TestWebKitAPI/WebKitGtk/testatkroles \
- Programs/TestWebKitAPI/WebKitGtk/testhittestresult \
- Programs/TestWebKitAPI/WebKitGtk/testwebinspector \
- Programs/TestWebKitAPI/WebKitGtk/testwebsettings \
- Programs/TestWebKitAPI/WebKitGtk/testwebresource \
- Programs/TestWebKitAPI/WebKitGtk/testwebdatasource \
- Programs/TestWebKitAPI/WebKitGtk/testwebplugindatabase \
- Programs/TestWebKitAPI/WebKitGtk/testwebview \
- Programs/TestWebKitAPI/WebKitGtk/testkeyevents \
- Programs/TestWebKitAPI/WebKitGtk/testcopyandpaste
-endif
-
-if ENABLE_WEBKIT2
-noinst_PROGRAMS += \
- Programs/TestWebKitAPI/WebKit2/TestWebKit2 \
- Programs/TestWebKitAPI/WebKit2Gtk/InspectorTestServer \
- Programs/TestWebKitAPI/WebKit2Gtk/TestAuthentication \
- Programs/TestWebKitAPI/WebKit2Gtk/TestBackForwardList \
- Programs/TestWebKitAPI/WebKit2Gtk/TestContextMenu \
- Programs/TestWebKitAPI/WebKit2Gtk/TestCookieManager \
- Programs/TestWebKitAPI/WebKit2Gtk/TestDOMNode \
- Programs/TestWebKitAPI/WebKit2Gtk/TestDownloads \
- Programs/TestWebKitAPI/WebKit2Gtk/TestFrame \
- Programs/TestWebKitAPI/WebKit2Gtk/TestInspector \
- Programs/TestWebKitAPI/WebKit2Gtk/TestInspectorServer \
- Programs/TestWebKitAPI/WebKit2Gtk/TestLoaderClient \
- Programs/TestWebKitAPI/WebKit2Gtk/TestMultiprocess \
- Programs/TestWebKitAPI/WebKit2Gtk/TestPrinting \
- Programs/TestWebKitAPI/WebKit2Gtk/TestResources \
- Programs/TestWebKitAPI/WebKit2Gtk/TestSSL \
- Programs/TestWebKitAPI/WebKit2Gtk/TestUIClient \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebExtensions \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebKitVersion \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebKitFaviconDatabase \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebKitFindController \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebKitPolicyClient \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebKitSettings \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebKitWebContext \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebKitWebView \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebKitWebViewGroup \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebViewEditor
-
-if HAVE_ATSPI2
-noinst_PROGRAMS += \
- Programs/TestWebKitAPI/WebKit2Gtk/AccessibilityTestServer \
- Programs/TestWebKitAPI/WebKit2Gtk/TestWebKitAccessibility
-endif
-endif # ENABLE_WEBKIT2
-
-Programs_TestWebKitAPI_WTF_TestWTF_CPPFLAGS = \
- $(Libraries_libTestWebKitAPIMain_la_CPPFLAGS) \
- $(GLIB_LIBS) \
- $(CAIRO_CFLAGS)
-
-Programs_TestWebKitAPI_WTF_TestWTF_CXXFLAGS = \
- -DGTEST_HAS_RTTI=0 \
- $(global_cxxflags)
-
-Programs_TestWebKitAPI_WTF_TestWTF_LDADD = \
- Libraries/libTestWebKitAPIMain.la \
- Libraries/libgtest.la \
- libWTF.la \
- $(GTK_LIBS) \
- $(GLIB_LIBS)
-
-Programs_TestWebKitAPI_WTF_TestWTF_LDFLAGS = \
- -no-install
-
-Programs_TestWebKitAPI_WTF_TestWTF_SOURCES = \
- Tools/TestWebKitAPI/Tests/WTF/AtomicString.cpp \
- Tools/TestWebKitAPI/Tests/WTF/CString.cpp \
- Tools/TestWebKitAPI/Tests/WTF/CheckedArithmeticOperations.cpp \
- Tools/TestWebKitAPI/Tests/WTF/Functional.cpp \
- Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp \
- Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp \
- Tools/TestWebKitAPI/Tests/WTF/IntegerToStringConversion.cpp \
- Tools/TestWebKitAPI/Tests/WTF/ListHashSet.cpp \
- Tools/TestWebKitAPI/Tests/WTF/MD5.cpp \
- Tools/TestWebKitAPI/Tests/WTF/MathExtras.cpp \
- Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp \
- Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp \
- Tools/TestWebKitAPI/Tests/WTF/MoveOnly.h \
- Tools/TestWebKitAPI/Tests/WTF/RedBlackTree.cpp \
- Tools/TestWebKitAPI/Tests/WTF/Ref.cpp \
- Tools/TestWebKitAPI/Tests/WTF/RefLogger.h \
- Tools/TestWebKitAPI/Tests/WTF/RefPtr.cpp \
- Tools/TestWebKitAPI/Tests/WTF/SHA1.cpp \
- Tools/TestWebKitAPI/Tests/WTF/SaturatedArithmeticOperations.cpp \
- Tools/TestWebKitAPI/Tests/WTF/StringBuilder.cpp \
- Tools/TestWebKitAPI/Tests/WTF/StringHasher.cpp \
- Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp \
- Tools/TestWebKitAPI/Tests/WTF/StringOperators.cpp \
- Tools/TestWebKitAPI/Tests/WTF/TemporaryChange.cpp \
- Tools/TestWebKitAPI/Tests/WTF/Vector.cpp \
- Tools/TestWebKitAPI/Tests/WTF/gobject/GUniquePtr.cpp \
- Tools/TestWebKitAPI/WTFStringUtilities.h
-
-Programs_TestWebKitAPI_JavaScriptCore_TestJavaScriptCore_CPPFLAGS = \
- $(Libraries_libTestWebKitAPIMain_la_CPPFLAGS)
-
-Programs_TestWebKitAPI_JavaScriptCore_TestJavaScriptCore_CXXFLAGS = \
- -DGTEST_HAS_RTTI=0 \
- $(global_cxxflags)
-
-Programs_TestWebKitAPI_JavaScriptCore_TestJavaScriptCore_LDADD = \
- Libraries/libTestWebKitAPIMain.la \
- Libraries/libgtest.la \
- libWTF.la \
- $(GTK_LIBS)
-
-Programs_TestWebKitAPI_JavaScriptCore_TestJavaScriptCore_LDFLAGS = \
- -no-install
-
-Programs_TestWebKitAPI_JavaScriptCore_TestJavaScriptCore_SOURCES = \
- Tools/TestWebKitAPI/Tests/JavaScriptCore/VMInspector.cpp
-
-webcore_layer_deps = \
- libPlatform.la \
- libPlatformGtk.la \
- libWebCorePlatform.la \
- libWebCoreGtk.la \
- libWebCore.la \
- libWebCoreModules.la
-if ENABLE_SVG
-webcore_layer_deps += \
- libWebCoreSVG.la
-endif
-if ENABLE_INDEXED_DATABASE
-webcore_layer_deps += \
- libLevelDB.la
-endif
-if USE_OPENGL
-webcore_layer_deps += \
- libANGLE.la
-endif
-
-webcore_layer_archives = $(foreach lib, $(webcore_layer_deps), $(shell echo $(lib) | sed "s/\(.*\)\.la/.libs\/\1.a/"))
-
-libWebCoreLayer.a: $(webcore_layer_deps)
- $(AM_V_GEN)
- $(AM_V_at)$(shell rm -f $@)
- $(AM_V_at)$(shell find . -name "*.o" > objects_list)
- $(AM_V_at)$(foreach archive, $(webcore_layer_archives), $(shell $(AR) t $(archive) | xargs -n1 basename | xargs -I obj_file grep -F obj_file objects_list | xargs -n50 $(AR) $(AR_FLAGS) $@))
- $(AM_V_at)$(shell rm -f objects_list)
-
-DISTCLEANFILES += \
- $(top_builddir)/libWebCoreLayer.a
-
-Programs_TestWebKitAPI_WebCore_TestWebCore_CPPFLAGS = \
- $(Libraries_libTestWebKitAPIMain_la_CPPFLAGS) \
- $(platform_cppflags) \
- $(platformgtk_cppflags) \
- $(webcore_cppflags) \
- $(webcoregtk_cppflags) \
- $(LIBSOUP_CFLAGS)
-
-Programs_TestWebKitAPI_WebCore_TestWebCore_CXXFLAGS = \
- -DGTEST_HAS_RTTI=0 \
- $(global_cxxflags)
-
-Programs_TestWebKitAPI_WebCore_TestWebCore_LDADD = \
- Libraries/libTestWebKitAPIMain.la \
- Libraries/libgtest.la \
- libjavascriptcoregtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- libWTF.la \
- libWebCoreLayer.a \
- $(CAIRO_LIBS) \
- $(FREETYPE_LIBS) \
- $(GAMEPAD_LIBS) \
- $(GEOCLUE_LIBS) \
- $(GLIB_LIBS) \
- $(GSTREAMER_LIBS) \
- $(GTK_LIBS) \
- $(JPEG_LIBS) \
- $(LIBSECRET_LIBS) \
- $(LIBSOUP_LIBS) \
- $(LIBXML_LIBS) \
- $(OPENGL_LIBS) \
- $(PANGO_LIBS) \
- $(PNG_LIBS) \
- $(SQLITE3_LIBS) \
- $(UNICODE_LIBS) \
- $(WEBP_LIBS) \
- $(XRENDER_LIBS) \
- $(XT_LIBS) \
- $(ZLIB_LIBS)
-
-Programs_TestWebKitAPI_WebCore_TestWebCore_LDFLAGS = \
- -no-install
-
-Programs_TestWebKitAPI_WebCore_TestWebCore_SOURCES = \
- Source/WebCore/platform/graphics/IntPoint.cpp \
- Source/WebCore/platform/graphics/IntRect.cpp \
- Source/WebCore/platform/graphics/IntSize.cpp \
- Source/WebCore/platform/graphics/cairo/IntRectCairo.cpp \
- Source/WebCore/platform/graphics/gtk/IntRectGtk.cpp \
- Source/WebCore/platform/gtk/GtkInputMethodFilter.cpp \
- Tools/TestWebKitAPI/config.h \
- Tools/TestWebKitAPI/Tests/gtk/InputMethodFilter.cpp \
- Tools/TestWebKitAPI/Tests/WebCore/gtk/UserAgentQuirks.cpp \
- Tools/TestWebKitAPI/Tests/WebCore/URL.cpp \
- Tools/TestWebKitAPI/Tests/WebCore/LayoutUnit.cpp
-
-Programs_TestWebKitAPI_WebKitGtk_testapplicationcache_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testapplicationcache.c
-Programs_TestWebKitAPI_WebKitGtk_testapplicationcache_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testapplicationcache_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testapplicationcache_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testcontextmenu_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testcontextmenu.c
-Programs_TestWebKitAPI_WebKitGtk_testcontextmenu_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testcontextmenu_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testcontextmenu_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testdomdocument_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdocument.c
-Programs_TestWebKitAPI_WebKitGtk_testdomdocument_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testdomdocument_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testdomdocument_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testdomdomwindow_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdomwindow.c
-Programs_TestWebKitAPI_WebKitGtk_testdomdomwindow_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testdomdomwindow_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testdomdomwindow_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testdomnode_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testdomnode.c
-Programs_TestWebKitAPI_WebKitGtk_testdomnode_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testdomnode_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testdomnode_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testhttpbackend_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testhttpbackend.c
-Programs_TestWebKitAPI_WebKitGtk_testhttpbackend_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testhttpbackend_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testhttpbackend_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testfavicondatabase_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testfavicondatabase.c \
- Tools/TestWebKitAPI/Tests/WebKitGtk/test_utils.c
-Programs_TestWebKitAPI_WebKitGtk_testfavicondatabase_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testfavicondatabase_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testfavicondatabase_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testglobals_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testglobals.c
-Programs_TestWebKitAPI_WebKitGtk_testglobals_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testglobals_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testglobals_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testloading_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testloading.c
-Programs_TestWebKitAPI_WebKitGtk_testloading_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testloading_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testloading_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testmimehandling_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testmimehandling.c \
- Tools/TestWebKitAPI/Tests/WebKitGtk/test_utils.c
-Programs_TestWebKitAPI_WebKitGtk_testmimehandling_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testmimehandling_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testmimehandling_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testnetworkrequest_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkrequest.c
-Programs_TestWebKitAPI_WebKitGtk_testnetworkrequest_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testnetworkrequest_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testnetworkrequest_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testnetworkresponse_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkresponse.c
-Programs_TestWebKitAPI_WebKitGtk_testnetworkresponse_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testnetworkresponse_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testnetworkresponse_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testwebframe_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testwebframe.c
-Programs_TestWebKitAPI_WebKitGtk_testwebframe_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testwebframe_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testwebframe_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testwebplugindatabase_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testwebplugindatabase.c
-Programs_TestWebKitAPI_WebKitGtk_testwebplugindatabase_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testwebplugindatabase_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testwebplugindatabase_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testwebbackforwardlist_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testwebbackforwardlist.c
-Programs_TestWebKitAPI_WebKitGtk_testwebbackforwardlist_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testwebbackforwardlist_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testwebbackforwardlist_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testwebhistoryitem_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testwebhistoryitem.c
-Programs_TestWebKitAPI_WebKitGtk_testwebhistoryitem_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testwebhistoryitem_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testwebhistoryitem_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testwindow_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testwindow.c
-Programs_TestWebKitAPI_WebKitGtk_testwindow_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testwindow_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testwindow_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testdownload_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testdownload.c
-Programs_TestWebKitAPI_WebKitGtk_testdownload_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testdownload_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testdownload_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testatk_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testatk.c
-Programs_TestWebKitAPI_WebKitGtk_testatk_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testatk_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testatk_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testatkroles_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testatkroles.c
-Programs_TestWebKitAPI_WebKitGtk_testatkroles_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testatkroles_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testatkroles_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testwebinspector_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testwebinspector.c \
- Tools/TestWebKitAPI/Tests/WebKitGtk/test_utils.c
-Programs_TestWebKitAPI_WebKitGtk_testwebinspector_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testwebinspector_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testwebinspector_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testwebsettings_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testwebsettings.c
-Programs_TestWebKitAPI_WebKitGtk_testwebsettings_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testwebsettings_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testwebsettings_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testwebresource_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testwebresource.c
-Programs_TestWebKitAPI_WebKitGtk_testwebresource_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testwebresource_LDADD = $(webkitgtk_tests_ldadd)
-
-Programs_TestWebKitAPI_WebKitGtk_testwebdatasource_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testwebdatasource.c
-Programs_TestWebKitAPI_WebKitGtk_testwebdatasource_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testwebdatasource_LDADD = $(webkitgtk_tests_ldadd)
-
-Programs_TestWebKitAPI_WebKitGtk_testwebview_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testwebview.c Tools/TestWebKitAPI/Tests/WebKitGtk/test_utils.c
-Programs_TestWebKitAPI_WebKitGtk_testwebview_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testwebview_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testwebview_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testhittestresult_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testhittestresult.c
-Programs_TestWebKitAPI_WebKitGtk_testhittestresult_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testhittestresult_LDADD = $(webkitgtk_tests_ldadd)
-
-Programs_TestWebKitAPI_WebKitGtk_testkeyevents_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testkeyevents.c
-Programs_TestWebKitAPI_WebKitGtk_testkeyevents_CFLAGS = $(webkitgtk_tests_cflags)
-Programs_TestWebKitAPI_WebKitGtk_testkeyevents_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testkeyevents_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKitGtk_testcopyandpaste_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKitGtk/testcopyandpaste.c \
- Source/WebCore/platform/gtk/GtkVersioning.c
-Programs_TestWebKitAPI_WebKitGtk_testcopyandpaste_CFLAGS = \
- $(webkitgtk_tests_cflags) \
- -I$(srcdir)/Source/WebCore/platform/gtk \
- -I$(srcdir)/Source/WebCore
-Programs_TestWebKitAPI_WebKitGtk_testcopyandpaste_LDADD = $(webkitgtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKitGtk_testcopyandpaste_LDFLAGS = $(webkitgtk_tests_ldflags)
-
-
-Programs_TestWebKitAPI_WebKit2_TestWebKit2_CPPFLAGS = \
- $(Programs_TestWebKitAPI_WTF_TestWTF_CPPFLAGS) \
- -I$(top_builddir)/DerivedSources/WebKit2/include \
- $(FREETYPE_CFLAGS) \
- $(GLIB_CFLAGS) \
- $(GTK_CFLAGS) \
- $(LIBSOUP_CFLAGS)
-
-Programs_TestWebKitAPI_WebKit2_TestWebKit2_CXXFLAGS = \
- -DGTEST_HAS_RTTI=0 \
- $(global_cxxflags)
-
-Programs_TestWebKitAPI_WebKit2_TestWebKit2_LDADD = \
- Libraries/libTestWebKitAPIMain.la \
- Libraries/libgtest.la \
- libjavascriptcoregtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- libwebkit2gtk-@WEBKITGTK_API_MAJOR_VERSION@.@WEBKITGTK_API_MINOR_VERSION@.la \
- $(FREETYPE_LIBS) \
- $(GLIB_LIBS) \
- $(GTK_LIBS) \
- $(LIBSOUP_LIBS)
-
-Programs_TestWebKitAPI_WebKit2_TestWebKit2_LDFLAGS = \
- $(Programs_TestWebKitAPI_WTF_TestWTF_LDFLAGS)
-
-Programs_TestWebKitAPI_WebKit2_TestWebKit2_SOURCES = \
- Tools/TestWebKitAPI/config.h \
- Tools/TestWebKitAPI/gtk/PlatformUtilitiesGtk.cpp \
- Tools/TestWebKitAPI/gtk/PlatformWebViewGtk.cpp \
- Tools/TestWebKitAPI/JavaScriptTest.cpp \
- Tools/TestWebKitAPI/JavaScriptTest.h \
- Tools/TestWebKitAPI/PlatformUtilities.cpp \
- Tools/TestWebKitAPI/PlatformUtilities.h \
- Tools/TestWebKitAPI/PlatformWebView.h \
- Tools/TestWebKitAPI/Tests/WebKit2/AboutBlankLoad.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/CloseThenTerminate.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/CookieManager.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/DidNotHandleKeyDown.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/DownloadDecideDestinationCrash.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/EvaluateJavaScript.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/FailedLoad.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/Find.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ForceRepaint.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypeHTML.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypePNG.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/Geolocation.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/LayoutMilestonesWithAllContentInFrame.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/LoadAlternateHTMLStringWithNonDirectoryURL.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/LoadPageOnCrash.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/PageLoadBasic.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/PageLoadDidChangeLocationWithinPageForFrame.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/PreventEmptyUserAgent.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/PrivateBrowsingPushStateNoHistoryCallback.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ReloadPageAfterCrash.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ResizeReversePaginatedWebView.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ResizeWindowAfterCrash.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/RestoreSessionStateContainingFormData.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ScrollPinningBehaviors.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/TerminateTwice.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/UserMessage.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/WillLoad.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/WKPageGetScaleFactorNotZero.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/WKPreferences.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/WKString.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/WKStringJSString.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/WKURL.cpp
-
-if ENABLE_WEBKIT2
-noinst_LTLIBRARIES += \
- Libraries/libTestWebKitAPIInjectedBundle.la
-endif # ENABLE_WEBKIT2
-
-Libraries_libTestWebKitAPIInjectedBundle_la_SOURCES = \
- Tools/TestWebKitAPI/InjectedBundleController.cpp \
- Tools/TestWebKitAPI/InjectedBundleController.h \
- Tools/TestWebKitAPI/InjectedBundleMain.cpp \
- Tools/TestWebKitAPI/InjectedBundleTest.h \
- Tools/TestWebKitAPI/PlatformUtilities.cpp \
- Tools/TestWebKitAPI/PlatformUtilities.h \
- Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/UserMessage_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/WillLoad_Bundle.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent_Bundle.cpp \
- Tools/TestWebKitAPI/gtk/InjectedBundleControllerGtk.cpp \
- Tools/TestWebKitAPI/gtk/PlatformUtilitiesGtk.cpp
-
-Libraries_libTestWebKitAPIInjectedBundle_la_LDFLAGS = \
- -rpath ${shell pwd}/$(top_builddir)/Libraries/.libs \
- $(no_undefined) \
- -avoid-version \
- -module
-
-Libraries_libTestWebKitAPIInjectedBundle_la_CPPFLAGS = \
- $(Libraries_libTestWebKitAPIMain_la_CPPFLAGS) \
- -I$(top_builddir)/DerivedSources/InjectedBundle \
- $(GTK_CFLAGS)
-
-Libraries_libTestWebKitAPIInjectedBundle_la_CXXFLAGS = \
- -DGTEST_HAS_RTTI=0 \
- $(global_cxxflags)
-
-Libraries_libTestWebKitAPIInjectedBundle_la_CFLAGS = \
- $(global_cflags)
-
-
-if ENABLE_WEBKIT2
-noinst_LTLIBRARIES += Libraries/WebExtensions/libWebExtensionTest.la
-endif
-
-Libraries_WebExtensions_libWebExtensionTest_la_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp
-
-Libraries_WebExtensions_libWebExtensionTest_la_LDFLAGS = \
- -rpath ${shell pwd}/$(top_builddir)/Libraries/WebExtensions/.libs \
- $(no_undefined) \
- -avoid-version \
- -module
-
-Libraries_WebExtensions_libWebExtensionTest_la_CPPFLAGS = \
- -I$(srcdir)/Source/WebKit2/WebProcess/InjectedBundle/API/gtk \
- -I$(top_builddir)/DerivedSources \
- -I$(top_builddir)/DerivedSources/WebKit2/webkit2extension/include \
- -DWEBKIT2_COMPILATION \
- $(webkit2gtk_tests_cppflags)
-
-Libraries_WebExtensions_libWebExtensionTest_la_CXXFLAGS = \
- $(global_cxxflags)
-
-Libraries_WebExtensions_libWebExtensionTest_la_CFLAGS = \
- $(global_cflags)
-
-
-if ENABLE_WEBKIT2
-noinst_LTLIBRARIES += Libraries/WebExtensions/libWebProcessTest.la
-endif
-
-Libraries_WebExtensions_libWebProcessTest_la_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeTest.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/FrameTest.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.cpp \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.h
-
-Libraries_WebExtensions_libWebProcessTest_la_LDFLAGS = \
- -rpath ${shell pwd}/$(top_builddir)/Libraries/WebExtensions/.libs \
- $(no_undefined) \
- -avoid-version \
- -module
-
-Libraries_WebExtensions_libWebProcessTest_la_CPPFLAGS = \
- -I$(srcdir)/Source/WebKit2/WebProcess/InjectedBundle/API/gtk \
- -I$(top_builddir)/DerivedSources \
- -I$(top_builddir)/DerivedSources/WebKit2/webkit2extension/include \
- -DWEBKIT2_COMPILATION \
- $(webkit2gtk_tests_cppflags)
-
-Libraries_WebExtensions_libWebProcessTest_la_CXXFLAGS = \
- $(global_cxxflags)
-
-Libraries_WebExtensions_libWebProcessTest_la_CFLAGS = \
- $(global_cflags)
-
-
-Programs/TestWebKitAPI/WebKit2Gtk/resources/webkit2gtk-tests-resources.gresource: Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/webkit2gtk-tests.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/webkit2gtk-tests.gresource.xml)
- $(AM_V_at)mkdir -p ${GENPROGRAMS}/TestWebKitAPI/WebKit2Gtk/resources
- $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) --target=$@ --sourcedir=$(srcdir) $<
-
-DISTCLEANFILES += \
- Programs/TestWebKitAPI/WebKit2Gtk/resources/webkit2gtk-tests-resources.gresource
-
-noinst_DATA += \
- Programs/TestWebKitAPI/WebKit2Gtk/resources/webkit2gtk-tests-resources.gresource
-
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebContext_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebContext.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebContext_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebContext_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebContext_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebView_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebView_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebView_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebView_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestLoaderClient_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestLoaderClient.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestLoaderClient_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestLoaderClient_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestLoaderClient_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestMultiprocess_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestMultiprocess.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestMultiprocess_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestMultiprocess_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestMultiprocess_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitSettings_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSettings.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitSettings_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitSettings_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitSettings_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_InspectorTestServer_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/InspectorTestServer.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_InspectorTestServer_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_InspectorTestServer_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_InspectorTestServer_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestBackForwardList_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestBackForwardList.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestBackForwardList_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestBackForwardList_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestBackForwardList_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitPolicyClient_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitPolicyClient.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitPolicyClient_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitPolicyClient_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitPolicyClient_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-if HAVE_ATSPI2
-Programs_TestWebKitAPI_WebKit2Gtk_AccessibilityTestServer_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/AccessibilityTestServer.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_AccessibilityTestServer_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_AccessibilityTestServer_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_AccessibilityTestServer_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitAccessibility_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitAccessibility.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitAccessibility_CPPFLAGS = $(webkit2gtk_tests_cppflags) $(ATSPI2_CFLAGS)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitAccessibility_LDADD = $(webkit2gtk_tests_ldadd) $(ATSPI2_LIBS)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitAccessibility_LDFLAGS = $(webkit2gtk_tests_ldflags)
-endif
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestDownloads_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestDownloads_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestDownloads_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestDownloads_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebViewEditor_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebViewEditor.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebViewEditor_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebViewEditor_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebViewEditor_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestPrinting_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestPrinting_CPPFLAGS = $(webkit2gtk_tests_cppflags) $(GTK_UNIX_PRINTING_CFLAGS)
-Programs_TestWebKitAPI_WebKit2Gtk_TestPrinting_LDADD = $(webkit2gtk_tests_ldadd) $(GTK_UNIX_PRINTING_LIBS)
-Programs_TestWebKitAPI_WebKit2Gtk_TestPrinting_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitFaviconDatabase_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFaviconDatabase.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitFaviconDatabase_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitFaviconDatabase_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitFaviconDatabase_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitFindController_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFindController.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitFindController_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitFindController_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitFindController_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestResources_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestResources.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestResources_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestResources_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestResources_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestCookieManager_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestCookieManager.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestCookieManager_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestCookieManager_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestCookieManager_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestInspector_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspector.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestInspector_CPPFLAGS = \
- $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestInspector_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestInspector_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestInspectorServer_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspectorServer.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestInspectorServer_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestInspectorServer_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestInspectorServer_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitVersion_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitVersion.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitVersion_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitVersion_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitVersion_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestContextMenu_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestContextMenu_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestContextMenu_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestContextMenu_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestSSL_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestSSL.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestSSL_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestSSL_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestSSL_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebExtensions_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebExtensions.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebExtensions_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebExtensions_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebExtensions_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebViewGroup_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebViewGroup.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebViewGroup_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebViewGroup_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestWebKitWebViewGroup_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestDOMNode_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNode.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestDOMNode_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestDOMNode_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestDOMNode_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestFrame_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestFrame.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestFrame_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestFrame_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestFrame_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestAuthentication_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAuthentication.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestAuthentication_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestAuthentication_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestAuthentication_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-Programs_TestWebKitAPI_WebKit2Gtk_TestUIClient_SOURCES = \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp
-Programs_TestWebKitAPI_WebKit2Gtk_TestUIClient_CPPFLAGS = $(webkit2gtk_tests_cppflags)
-Programs_TestWebKitAPI_WebKit2Gtk_TestUIClient_LDADD = $(webkit2gtk_tests_ldadd)
-Programs_TestWebKitAPI_WebKit2Gtk_TestUIClient_LDFLAGS = $(webkit2gtk_tests_ldflags)
-
-
-stamp-testwebkitapi-webcore-forwarding-headers: $(WebKit2)/Scripts/generate-forwarding-headers.pl $(Programs_TestWebKitAPI_WebCore_TestWebCore_SOURCES)
- $(AM_V_GEN)$(PERL) $< $(srcdir)/Tools/TestWebKitAPI/Tests/WebCore $(GENSOURCES_WEBCORE)/include gtk \
- && echo timestamp > $(@F)
-
-stamp-testwebkitapi-webkit2-forwarding-headers: $(WebKit2)/Scripts/generate-forwarding-headers.pl $(Programs_TestWebKitAPI_WebKit2_TestWebKit2_SOURCES) $(Libraries_libTestWebKitAPIInjectedBundle_la_SOURCES)
- $(AM_V_GEN)$(PERL) $< $(srcdir)/Tools/TestWebKitAPI $(GENSOURCES_WEBKIT2)/include gtk \
- && echo timestamp > $(@F)
-
-BUILT_SOURCES += $(top_builddir)/stamp-testwebkitapi-webcore-forwarding-headers
-if ENABLE_WEBKIT2
-BUILT_SOURCES += $(top_builddir)/stamp-testwebkitapi-webkit2-forwarding-headers
-endif # ENABLE_WEBKIT2
-
-
-EXTRA_DIST += \
- Tools/TestWebKitAPI/Tests/WebKit2/18-characters.html \
- Tools/TestWebKitAPI/Tests/WebKit2/file-with-anchor.html \
- Tools/TestWebKitAPI/Tests/WebKit2/find.html \
- Tools/TestWebKitAPI/Tests/WebKit2/icon.png \
- Tools/TestWebKitAPI/Tests/WebKit2/lots-of-iframes.html \
- Tools/TestWebKitAPI/Tests/WebKit2/lots-of-images.html \
- Tools/TestWebKitAPI/Tests/WebKit2/lots-of-text.html \
- Tools/TestWebKitAPI/Tests/WebKit2/mouse-move-listener.html \
- Tools/TestWebKitAPI/Tests/WebKit2/push-state.html \
- Tools/TestWebKitAPI/Tests/WebKit2/simple-accelerated-compositing.html \
- Tools/TestWebKitAPI/Tests/WebKit2/simple-form.html \
- Tools/TestWebKitAPI/Tests/WebKit2/simple.html \
- Tools/TestWebKitAPI/Tests/WebKit2/simple-iframe.html \
- Tools/TestWebKitAPI/Tests/WebKit2/simple-tall.html \
- Tools/TestWebKitAPI/Tests/WebKit2/spacebar-scrolling.html \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-cert.pem \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-key.pem \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/webkit2gtk-tests.gresource.xml \
- Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/link-title.js \
- Tools/TestWebKitAPI/Tests/WebKitGtk/test_utils.h \
- Tools/TestWebKitAPI/Tests/WebKitGtk/resources/blank.ico \
- Tools/TestWebKitAPI/Tests/WebKitGtk/resources/test.html \
- Tools/TestWebKitAPI/Tests/WebKitGtk/resources/test.ogg \
- Tools/TestWebKitAPI/Tests/WebKitGtk/resources/test.pdf \
- Tools/TestWebKitAPI/Tests/WebKitGtk/resources/test.txt
diff --git a/Tools/TestWebKitAPI/InjectedBundleController.cpp b/Tools/TestWebKitAPI/InjectedBundleController.cpp
index 00b534b0e..53f39a874 100644
--- a/Tools/TestWebKitAPI/InjectedBundleController.cpp
+++ b/Tools/TestWebKitAPI/InjectedBundleController.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleController.h"
#include "InjectedBundleTest.h"
@@ -33,7 +36,7 @@
namespace TestWebKitAPI {
-InjectedBundleController& InjectedBundleController::shared()
+InjectedBundleController& InjectedBundleController::singleton()
{
static InjectedBundleController& shared = *new InjectedBundleController;
return shared;
@@ -138,3 +141,5 @@ void InjectedBundleController::registerCreateInjectedBundleTestFunction(const st
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/InjectedBundleController.h b/Tools/TestWebKitAPI/InjectedBundleController.h
index 0ca112584..eaa7f0d17 100644
--- a/Tools/TestWebKitAPI/InjectedBundleController.h
+++ b/Tools/TestWebKitAPI/InjectedBundleController.h
@@ -26,7 +26,7 @@
#ifndef InjectedBundleController_h
#define InjectedBundleController_h
-#include <WebKit2/WKBundle.h>
+#include <WebKit/WKBundle.h>
#include <map>
#include <string>
@@ -36,7 +36,7 @@ class InjectedBundleTest;
class InjectedBundleController {
public:
- static InjectedBundleController& shared();
+ static InjectedBundleController& singleton();
void initialize(WKBundleRef, WKTypeRef);
diff --git a/Tools/TestWebKitAPI/InjectedBundleMain.cpp b/Tools/TestWebKitAPI/InjectedBundleMain.cpp
index 8ad6c2bad..b2537f737 100644
--- a/Tools/TestWebKitAPI/InjectedBundleMain.cpp
+++ b/Tools/TestWebKitAPI/InjectedBundleMain.cpp
@@ -24,8 +24,11 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleController.h"
-#include <WebKit2/WKBundleInitialize.h>
+#include <WebKit/WKBundleInitialize.h>
#if defined(WIN32) || defined(_WIN32)
extern "C" __declspec(dllexport)
@@ -34,5 +37,7 @@ extern "C"
#endif
void WKBundleInitialize(WKBundleRef bundle, WKTypeRef initializationUserData)
{
- TestWebKitAPI::InjectedBundleController::shared().initialize(bundle, initializationUserData);
+ TestWebKitAPI::InjectedBundleController::singleton().initialize(bundle, initializationUserData);
}
+
+#endif
diff --git a/Tools/TestWebKitAPI/InjectedBundleTest.h b/Tools/TestWebKitAPI/InjectedBundleTest.h
index d0f996aff..ad2cb9581 100644
--- a/Tools/TestWebKitAPI/InjectedBundleTest.h
+++ b/Tools/TestWebKitAPI/InjectedBundleTest.h
@@ -48,7 +48,7 @@ public:
public:
Register(const std::string& test)
{
- InjectedBundleController::shared().registerCreateInjectedBundleTestFunction(test, Register::create);
+ InjectedBundleController::singleton().registerCreateInjectedBundleTestFunction(test, Register::create);
}
private:
diff --git a/Tools/TestWebKitAPI/JavaScriptTest.cpp b/Tools/TestWebKitAPI/JavaScriptTest.cpp
index de1848fdc..133d99eee 100644
--- a/Tools/TestWebKitAPI/JavaScriptTest.cpp
+++ b/Tools/TestWebKitAPI/JavaScriptTest.cpp
@@ -24,14 +24,17 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "JavaScriptTest.h"
#include "PlatformUtilities.h"
#include "Test.h"
#include <JavaScriptCore/JSContextRef.h>
#include <JavaScriptCore/JSRetainPtr.h>
-#include <WebKit2/WKRetainPtr.h>
-#include <WebKit2/WKSerializedScriptValue.h>
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKSerializedScriptValue.h>
#include <wtf/StdLibExtras.h>
namespace TestWebKitAPI {
@@ -90,3 +93,5 @@ static void javaScriptCallback(WKSerializedScriptValueRef resultSerializedScript
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/JavaScriptTest.h b/Tools/TestWebKitAPI/JavaScriptTest.h
index c6e79c3b6..c0494b2ca 100644
--- a/Tools/TestWebKitAPI/JavaScriptTest.h
+++ b/Tools/TestWebKitAPI/JavaScriptTest.h
@@ -23,14 +23,9 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#if PLATFORM(MAC)
-#ifdef __OBJC__
-@class WKView;
-@class WebView;
-#else
-class WKView;
-class WebView;
-#endif
+#if PLATFORM(COCOA)
+OBJC_CLASS WKView;
+OBJC_CLASS WebView;
#endif
namespace TestWebKitAPI {
@@ -44,7 +39,7 @@ namespace TestWebKitAPI {
::testing::AssertionResult runJSTest(const char* pageExpr, const char* scriptExpr, const char* expectedResultExpr, WKPageRef, const char* script, const char* expectedResult);
::testing::AssertionResult compareJSResult(const char* script, const char* actualResult, const char* expectedResult);
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA)
::testing::AssertionResult runJSTest(const char* webViewExpr, const char* scriptExpr, const char* expectedResultExpr, WebView *, const char* script, const char* expectedResult);
::testing::AssertionResult runJSTest(const char* viewExpr, const char* scriptExpr, const char* expectedResultExpr, WKView *, const char* script, const char* expectedResult);
#endif
diff --git a/Tools/TestWebKitAPI/PlatformGTK.cmake b/Tools/TestWebKitAPI/PlatformGTK.cmake
new file mode 100644
index 000000000..ffc72f291
--- /dev/null
+++ b/Tools/TestWebKitAPI/PlatformGTK.cmake
@@ -0,0 +1,158 @@
+set(TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/TestWebKitAPI")
+set(TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY_WTF "${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WTF")
+
+# This is necessary because it is possible to build TestWebKitAPI with WebKit2
+# disabled and this triggers the inclusion of the WebKit2 headers.
+add_definitions(-DBUILDING_WEBKIT2__)
+
+add_custom_target(TestWebKitAPI-forwarding-headers
+ COMMAND ${PERL_EXECUTABLE} ${WEBKIT2_DIR}/Scripts/generate-forwarding-headers.pl --include-path ${TESTWEBKITAPI_DIR} --output ${FORWARDING_HEADERS_DIR} --platform gtk --platform soup
+ DEPENDS WebKit2-forwarding-headers
+)
+
+set(ForwardingHeadersForTestWebKitAPI_NAME TestWebKitAPI-forwarding-headers)
+
+include_directories(
+ ${FORWARDING_HEADERS_DIR}
+ ${FORWARDING_HEADERS_DIR}/JavaScriptCore
+ ${WEBKIT2_DIR}/UIProcess/API/C/soup
+ ${WEBKIT2_DIR}/UIProcess/API/C/gtk
+ ${WEBKIT2_DIR}/UIProcess/API/gtk
+)
+
+include_directories(SYSTEM
+ ${GDK3_INCLUDE_DIRS}
+ ${GLIB_INCLUDE_DIRS}
+ ${GTK3_INCLUDE_DIRS}
+ ${LIBSOUP_INCLUDE_DIRS}
+)
+
+set(test_main_SOURCES
+ ${TESTWEBKITAPI_DIR}/gtk/main.cpp
+)
+
+set(bundle_harness_SOURCES
+ ${TESTWEBKITAPI_DIR}/gtk/InjectedBundleControllerGtk.cpp
+ ${TESTWEBKITAPI_DIR}/gtk/PlatformUtilitiesGtk.cpp
+)
+
+set(webkit2_api_harness_SOURCES
+ ${TESTWEBKITAPI_DIR}/gtk/PlatformUtilitiesGtk.cpp
+ ${TESTWEBKITAPI_DIR}/gtk/PlatformWebViewGtk.cpp
+)
+
+list(APPEND test_wtf_LIBRARIES
+ ${GDK3_LIBRARIES}
+ ${GTK3_LIBRARIES}
+)
+
+list(APPEND test_webkit2_api_LIBRARIES
+ ${GDK3_LIBRARIES}
+ ${GTK3_LIBRARIES}
+)
+
+list(APPEND test_webcore_LIBRARIES
+ WebCorePlatformGTK
+ ${GDK3_LIBRARIES}
+ ${GTK3_LIBRARIES}
+)
+ADD_WHOLE_ARCHIVE_TO_LIBRARIES(test_webcore_LIBRARIES)
+
+list(APPEND TestWebKitAPI_LIBRARIES
+ ${GDK3_LIBRARIES}
+ ${GTK3_LIBRARIES}
+)
+
+list(APPEND TestJavaScriptCore_LIBRARIES
+ ${GDK3_LIBRARIES}
+ ${GTK3_LIBRARIES}
+)
+
+add_executable(TestWebKit2
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/AboutBlankLoad.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/CanHandleRequest.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/CookieManager.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/DocumentStartUserScriptAlertCrash.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/DOMWindowExtensionBasic.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/DOMWindowExtensionNoCache.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/DownloadDecideDestinationCrash.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/EnumerateMediaDevices.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/EvaluateJavaScript.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/FailedLoad.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/Find.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/ForceRepaint.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/FrameMIMETypeHTML.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/FrameMIMETypePNG.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/Geolocation.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/HitTestResultNodeHandle.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/InjectedBundleBasic.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/InjectedBundleFrameHitTest.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/LoadAlternateHTMLStringWithNonDirectoryURL.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/LoadCanceledNoServerRedirectCallback.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/LoadPageOnCrash.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/MouseMoveAfterCrash.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/PageLoadBasic.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/PageLoadDidChangeLocationWithinPageForFrame.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/ParentFrame.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/PendingAPIRequestURL.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/PreventEmptyUserAgent.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/PrivateBrowsingPushStateNoHistoryCallback.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/ProvisionalURLAfterWillSendRequestCallback.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/ReloadPageAfterCrash.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/ResizeWindowAfterCrash.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/RestoreSessionStateContainingFormData.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/ShouldGoToBackForwardListItem.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/TextFieldDidBeginAndEndEditing.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/UserMedia.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/UserMessage.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WillSendSubmitEvent.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WKPageCopySessionStateWithFiltering.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WKPageGetScaleFactorNotZero.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WKPreferences.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WKRetainPtr.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WKString.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WKStringJSString.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/WKURL.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebKit2/gtk/InputMethodFilter.cpp
+)
+
+target_link_libraries(TestWebKit2 ${test_webkit2_api_LIBRARIES})
+add_test(TestWebKit2 ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebKit2/TestWebKit2)
+set_tests_properties(TestWebKit2 PROPERTIES TIMEOUT 60)
+set_target_properties(TestWebKit2 PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebKit2)
+
+add_executable(TestWebCore
+ ${test_main_SOURCES}
+ ${TESTWEBKITAPI_DIR}/TestsController.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebCore/CSSParser.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebCore/ComplexTextController.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebCore/FileSystem.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebCore/GridPosition.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebCore/HTMLParserIdioms.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebCore/LayoutUnit.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebCore/PublicSuffix.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebCore/SecurityOrigin.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebCore/SharedBuffer.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebCore/SharedBufferTest.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebCore/URL.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebCore/URLParser.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WebCore/UserAgentQuirks.cpp
+)
+
+target_link_libraries(TestWebCore ${test_webcore_LIBRARIES})
+add_dependencies(TestWebCore ${ForwardingHeadersForTestWebKitAPI_NAME})
+
+add_test(TestWebCore ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebCore/TestWebCore)
+set_tests_properties(TestWebCore PROPERTIES TIMEOUT 60)
+set_target_properties(TestWebCore PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WebCore)
+
+list(APPEND TestWTF_SOURCES
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/glib/GUniquePtr.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/glib/WorkQueueGLib.cpp
+)
diff --git a/Tools/TestWebKitAPI/PlatformJSCOnly.cmake b/Tools/TestWebKitAPI/PlatformJSCOnly.cmake
new file mode 100644
index 000000000..986796034
--- /dev/null
+++ b/Tools/TestWebKitAPI/PlatformJSCOnly.cmake
@@ -0,0 +1,21 @@
+set(TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/TestWebKitAPI")
+set(TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY_WTF "${TESTWEBKITAPI_RUNTIME_OUTPUT_DIRECTORY}/WTF")
+
+include_directories(
+ ${DERIVED_SOURCES_DIR}/ForwardingHeaders
+)
+
+if (LOWERCASE_EVENT_LOOP_TYPE STREQUAL "glib")
+ include_directories(SYSTEM
+ ${GLIB_INCLUDE_DIRS}
+ )
+endif ()
+
+set(test_main_SOURCES
+ ${TESTWEBKITAPI_DIR}/jsconly/main.cpp
+)
+
+list(APPEND TestWTF_SOURCES
+ ${TESTWEBKITAPI_DIR}/jsconly/PlatformUtilitiesJSCOnly.cpp
+ ${TESTWEBKITAPI_DIR}/Tests/WTF/RunLoop.cpp
+)
diff --git a/Tools/TestWebKitAPI/PlatformUtilities.cpp b/Tools/TestWebKitAPI/PlatformUtilities.cpp
index cebff7be9..c341d80be 100644
--- a/Tools/TestWebKitAPI/PlatformUtilities.cpp
+++ b/Tools/TestWebKitAPI/PlatformUtilities.cpp
@@ -31,6 +31,8 @@
namespace TestWebKitAPI {
namespace Util {
+#if WK_HAVE_C_SPI
+
WKContextRef createContextWithInjectedBundle()
{
WKRetainPtr<WKStringRef> injectedBundlePath(AdoptWK, createInjectedBundlePath());
@@ -76,14 +78,16 @@ std::string toSTD(WKRetainPtr<WKStringRef> string)
return toSTD(string.get());
}
-std::string toSTD(const char* string)
+WKRetainPtr<WKStringRef> toWK(const char* utf8String)
{
- return std::string(string);
+ return WKRetainPtr<WKStringRef>(AdoptWK, WKStringCreateWithUTF8CString(utf8String));
}
-WKRetainPtr<WKStringRef> toWK(const char* utf8String)
+#endif // WK_HAVE_C_SPI
+
+std::string toSTD(const char* string)
{
- return WKRetainPtr<WKStringRef>(AdoptWK, WKStringCreateWithUTF8CString(utf8String));
+ return std::string(string);
}
} // namespace Util
diff --git a/Tools/TestWebKitAPI/PlatformUtilities.h b/Tools/TestWebKitAPI/PlatformUtilities.h
index 10da84d33..86ddcfa57 100644
--- a/Tools/TestWebKitAPI/PlatformUtilities.h
+++ b/Tools/TestWebKitAPI/PlatformUtilities.h
@@ -26,15 +26,16 @@
#ifndef PlatformUtilities_h
#define PlatformUtilities_h
-#include <WebKit2/WKRetainPtr.h>
+#ifndef BUILDING_JSCONLY__
+#include <WebKit/WKNativeEvent.h>
+#include <WebKit/WKRetainPtr.h>
+#endif
+
+#include "Utilities.h"
#include <string>
-#if PLATFORM(MAC)
-#if __OBJC__
-@class NSString;
-#else
-class NSString;
-#endif
+#if USE(FOUNDATION)
+OBJC_CLASS NSString;
#endif
namespace TestWebKitAPI {
@@ -42,12 +43,14 @@ namespace Util {
// Runs a platform runloop until the 'done' is true.
void run(bool* done);
+void sleep(double seconds);
-#if PLATFORM(WIN)
-bool shouldTranslateMessage(const MSG&);
+std::string toSTD(const char*);
+#if USE(FOUNDATION)
+std::string toSTD(NSString *);
#endif
-void sleep(double seconds);
+#if WK_HAVE_C_SPI
WKContextRef createContextWithInjectedBundle();
WKContextRef createContextForInjectedBundleTest(const std::string&, WKTypeRef userData = 0);
@@ -62,13 +65,11 @@ bool isKeyDown(WKNativeEventPtr);
std::string toSTD(WKStringRef);
std::string toSTD(WKRetainPtr<WKStringRef>);
-std::string toSTD(const char*);
-#if PLATFORM(MAC)
-std::string toSTD(NSString *);
-#endif
WKRetainPtr<WKStringRef> toWK(const char* utf8String);
+#endif // WK_HAVE_C_SPI
+
template<typename T, typename U>
static inline ::testing::AssertionResult assertWKStringEqual(const char* expected_expression, const char* actual_expression, T expected, U actual)
{
@@ -78,6 +79,10 @@ static inline ::testing::AssertionResult assertWKStringEqual(const char* expecte
#define EXPECT_WK_STREQ(expected, actual) \
EXPECT_PRED_FORMAT2(TestWebKitAPI::Util::assertWKStringEqual, expected, actual)
+#if WK_API_ENABLED
+extern NSString * const TestPlugInClassNameParameter;
+#endif
+
} // namespace Util
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/PlatformWebView.h b/Tools/TestWebKitAPI/PlatformWebView.h
index 8679fa2c4..9c807321c 100644
--- a/Tools/TestWebKitAPI/PlatformWebView.h
+++ b/Tools/TestWebKitAPI/PlatformWebView.h
@@ -30,7 +30,11 @@
#include <CoreGraphics/CGGeometry.h>
#endif
-#ifdef __APPLE__
+#if PLATFORM(MAC)
+#include <objc/objc.h>
+#endif
+
+#if defined(__APPLE__) && !PLATFORM(GTK)
#ifdef __OBJC__
@class WKView;
@class NSWindow;
@@ -40,32 +44,24 @@ class NSWindow;
#endif
typedef WKView *PlatformWKView;
typedef NSWindow *PlatformWindow;
-#elif defined(WIN32) || defined(_WIN32)
-typedef WKViewRef PlatformWKView;
-typedef HWND PlatformWindow;
#elif PLATFORM(GTK)
typedef WKViewRef PlatformWKView;
typedef GtkWidget *PlatformWindow;
#elif PLATFORM(EFL)
-typedef struct _Ecore_Evas Ecore_Evas;
-#if USE(EO)
-typedef struct _Eo_Opaque Evas_Object;
-#else
-typedef struct _Evas_Object Evas_Object;
-#endif
typedef Evas_Object* PlatformWKView;
typedef Ecore_Evas* PlatformWindow;
#endif
namespace TestWebKitAPI {
-#if PLATFORM(WIN)
-class WindowMessageObserver;
-#endif
-
class PlatformWebView {
public:
- PlatformWebView(WKContextRef, WKPageGroupRef = 0);
+ explicit PlatformWebView(WKPageConfigurationRef);
+ explicit PlatformWebView(WKContextRef, WKPageGroupRef = 0);
+ explicit PlatformWebView(WKPageRef relatedPage);
+#if PLATFORM(MAC)
+ explicit PlatformWebView(WKContextRef, WKPageGroupRef, Class wkViewSubclass);
+#endif
~PlatformWebView();
WKPageRef page() const;
@@ -76,25 +72,20 @@ public:
void simulateSpacebarKeyPress();
void simulateAltKeyPress();
void simulateRightClick(unsigned x, unsigned y);
- void simulateMouseMove(unsigned x, unsigned y);
-
-#if PLATFORM(WIN)
- void simulateAKeyDown();
- void setParentWindowMessageObserver(WindowMessageObserver* observer) { m_parentWindowMessageObserver = observer; }
+ void simulateMouseMove(unsigned x, unsigned y, WKEventModifiers = 0);
+#if PLATFORM(MAC)
+ void simulateButtonClick(WKEventMouseButton, unsigned x, unsigned y, WKEventModifiers);
#endif
private:
-#if PLATFORM(WIN)
- static void registerWindowClass();
- static LRESULT CALLBACK wndProc(HWND, UINT message, WPARAM, LPARAM);
+#if PLATFORM(MAC)
+ void initialize(WKPageConfigurationRef, Class wkViewSubclass);
+#elif PLATFORM(GTK)
+ void initialize(WKPageConfigurationRef);
#endif
PlatformWKView m_view;
PlatformWindow m_window;
-
-#if PLATFORM(WIN)
- WindowMessageObserver* m_parentWindowMessageObserver;
-#endif
};
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Test.h b/Tools/TestWebKitAPI/Test.h
index ca43924a2..cf44045fb 100644
--- a/Tools/TestWebKitAPI/Test.h
+++ b/Tools/TestWebKitAPI/Test.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 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
@@ -26,6 +26,8 @@
#ifndef Test_h
#define Test_h
+#include <type_traits>
+
namespace TestWebKitAPI {
#define EXPECT_NOT_NULL(expression) \
@@ -40,6 +42,18 @@ namespace TestWebKitAPI {
#define ASSERT_NULL(expression) \
ASSERT_TRUE(!(expression))
+template<typename T>
+static inline ::testing::AssertionResult assertStrongEnum(const char* expected_expression, const char* actual_expression, T expected, T actual)
+{
+ static_assert(std::is_enum<T>::value, "T is not an enum type");
+ typedef typename std::underlying_type<T>::type UnderlyingStorageType;
+ return ::testing::internal::CmpHelperEQ(expected_expression, actual_expression, static_cast<UnderlyingStorageType>(expected), static_cast<UnderlyingStorageType>(actual));
+}
+
+#define EXPECT_STRONG_ENUM_EQ(expected, actual) \
+ EXPECT_PRED_FORMAT2(TestWebKitAPI::assertStrongEnum, expected, actual)
+
+
} // namespace TestWebKitAPI
#endif // Test_h
diff --git a/Tools/TestWebKitAPI/Tests/JavaScriptCore/VMInspector.cpp b/Tools/TestWebKitAPI/Tests/JavaScriptCore/VMInspector.cpp
deleted file mode 100644
index b1c1bacf3..000000000
--- a/Tools/TestWebKitAPI/Tests/JavaScriptCore/VMInspector.cpp
+++ /dev/null
@@ -1,689 +0,0 @@
-/*
- * Copyright (C) 2012 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. 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 INC. 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.
- */
-
-#include "config.h"
-
-#include <interpreter/VMInspector.h>
-#include <stdarg.h>
-#include <stdio.h>
-
-using namespace JSC;
-
-// There's not much we can test for the VMInspector::printf() case except to
-// make sure it does not crash. Unfortunately, we also don't want all the
-// test strings crowding out stdout. So, we forego the printf tests.
-// NOTE that the most interesting part of VMInspector::printf() is the
-// formatting functionality, and it is are already being tested by the
-// fprintf() and sprintf() cases.
-
-
-// The VMInspector::fprintf() test works by printing the string to a temp file,
-// and then reading the file content back into a buffer, which we, in turn,
-// compare against the expected string.
-
-TEST(JSC, VMInspectorFprintf)
-{
-#if ENABLE(VMINSPECTOR)
- char actual[1024];
- char expected[1024];
- const char* format;
- const char* expectedLiteral;
- FILE* file;
- const char* filename = "/tmp/VMInspectorFprintfTest.txt";
- size_t size;
-
-#define OPEN_FILE(file) \
- do { \
- file = fopen(filename, "w"); \
- } while (false)
-
-#define READ_AND_CLOSE_FILE(file, actual) \
- do { \
- fclose(file); \
- file = fopen(filename, "r"); \
- fseek(file, 0, SEEK_END); \
- size = ftell(file); \
- rewind(file); \
- fread(actual, 1, size, file); \
- actual[size] = '\0'; \
- fclose(file); \
- } while (false)
-
- // Testing standard default format specifiers:
- // Note: should work just like sprintf. So, we just compare against that.
- memset(actual, 'z', sizeof(actual));
- // The compiler warning flags are configured to expect a literal string for
- // ::sprintf below. So, use a #define for this one case to keep the
- // compiler happy.
-#undef LITERAL_FORMAT
-#define LITERAL_FORMAT "'%%%%' ==> '%%'\n"
-
- OPEN_FILE(file);
- VMInspector::fprintf(file, LITERAL_FORMAT);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, LITERAL_FORMAT);
-
-#undef LITERAL_FORMAT
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%c', 'x' ==> '%c'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 'x');
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 'x');
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%*c', 8, 'x' ==> '%*c'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 8, 'x');
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 8, 'x');
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%s', \"hello world\" ==> '%s'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, "hello world");
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, "hello world");
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%*s', 8, \"hello world\" ==> '%*s'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 8, "hello world");
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 8, "hello world");
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%*s', 8, \"hello\" ==> '%*s'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 8, "hello");
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 8, "hello");
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%d', 987654321 ==> '%d'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 987654321);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 987654321);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%u', 4276543210u ==> '%u'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 4276543210u);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 4276543210u);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%u', 0xffffffff ==> '%u'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 0xffffffff);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 0xffffffff);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%x', 0xffffffff ==> '%x'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 0xffffffff);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 0xffffffff);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%p', (void*)0xabcdbabe ==> '%p'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, (void*)0xabcdbabe);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, (void*)0xabcdbabe);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%lu', 1234567890987654321ul ==> '%lu'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 1234567890987654321ul);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 1234567890987654321ul);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%f', 1234.567 ==> '%f'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 1234.567);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%.2f', 1234.567 ==> '%.2f'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 1234.567);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%10.2f', 1234.567 ==> '%10.2f'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 1234.567);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%010.2f', 1234.567 ==> '%010.2f'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 1234.567);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- // Bad / weird formats:
- memset(actual, 'z', sizeof(actual));
- format = "'%%5.4', 987654321 ==> '%5.4'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 987654321);
- READ_AND_CLOSE_FILE(file, actual);
- expectedLiteral = "'%5.4', 987654321 ==> 'ERROR @ \"%5.4' \"\n";
- ASSERT_EQ(strcmp(actual, expectedLiteral), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%5.4' '%%d', 987654321, 4 ==> '%5.4' '%d'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 987654321, 4);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 987654321, 4);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%w' '%%d', 987654321, 6 ==> '%w' '%d'\n";
- OPEN_FILE(file);
- VMInspector::fprintf(file, format, 987654321, 6);
- READ_AND_CLOSE_FILE(file, actual);
- ::sprintf(expected, format, 987654321, 6);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
-
- // Testing the %b extension:
- memset(actual, 'z', sizeof(actual));
- OPEN_FILE(file);
- VMInspector::fprintf(file, "'%%b', 0 ==> '%b'\n", 0);
- READ_AND_CLOSE_FILE(file, actual);
- ASSERT_EQ(strcmp(actual, "'%b', 0 ==> 'FALSE'\n"), 0);
-
- memset(actual, 'z', sizeof(actual));
- OPEN_FILE(file);
- VMInspector::fprintf(file, "'%%b', 1 ==> '%b'\n", 1);
- READ_AND_CLOSE_FILE(file, actual);
- ASSERT_EQ(strcmp(actual, "'%b', 1 ==> 'TRUE'\n"), 0);
-
- memset(actual, 'z', sizeof(actual));
- OPEN_FILE(file);
- VMInspector::fprintf(file, "'%%b', -123456789 ==> '%b'\n", -123456789);
- READ_AND_CLOSE_FILE(file, actual);
- ASSERT_EQ(strcmp(actual, "'%b', -123456789 ==> 'TRUE'\n"), 0);
-
- memset(actual, 'z', sizeof(actual));
- OPEN_FILE(file);
- VMInspector::fprintf(file, "'%%b', 123456789 ==> '%b'\n", 123456789);
- READ_AND_CLOSE_FILE(file, actual);
- ASSERT_EQ(strcmp(actual, "'%b', 123456789 ==> 'TRUE'\n"), 0);
-
-
- // Testing the %J<x> extensions:
- String str1("Test WTF String");
- String str2("");
-
- memset(actual, 'z', sizeof(actual));
- OPEN_FILE(file);
- VMInspector::fprintf(file, "'%%Js' is %%s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%Js' is %s\n",
- &str1, str1.isEmpty() ? "EMPTY" : "NOT EMPTY");
- READ_AND_CLOSE_FILE(file, actual);
- expectedLiteral = "'%Js' is %s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> 'Test WTF String' is NOT EMPTY\n";
- ASSERT_EQ(strcmp(actual, expectedLiteral), 0);
-
- memset(actual, 'z', sizeof(actual));
- OPEN_FILE(file);
- VMInspector::fprintf(file, "'%%Js' is %%s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%Js' is %s\n",
- &str2, str2.isEmpty() ? "EMPTY" : "NOT EMPTY");
- READ_AND_CLOSE_FILE(file, actual);
- expectedLiteral = "'%Js' is %s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '' is EMPTY\n";
- ASSERT_EQ(strcmp(actual, expectedLiteral), 0);
-
- memset(actual, 'z', sizeof(actual));
- OPEN_FILE(file);
- VMInspector::fprintf(file, "'%%J+s' is %%s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%J+s' is %s\n",
- &str1, str1.isEmpty() ? "EMPTY" : "NOT EMPTY");
- READ_AND_CLOSE_FILE(file, actual);
- expectedLiteral = "'%J+s' is %s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> 'WTF::String \"Test WTF String\"' is NOT EMPTY\n";
- ASSERT_EQ(strcmp(actual, expectedLiteral), 0);
-
- memset(actual, 'z', sizeof(actual));
- OPEN_FILE(file);
- VMInspector::fprintf(file, "'%%J+s' is %%s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%J+s' is %s\n",
- &str2, str2.isEmpty() ? "EMPTY" : "NOT EMPTY");
- READ_AND_CLOSE_FILE(file, actual);
- expectedLiteral = "'%J+s' is %s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> 'WTF::String \"\"' is EMPTY\n";
- ASSERT_EQ(strcmp(actual, expectedLiteral), 0);
-
-#undef OPEN_FILE
-#undef READ_AND_CLOSE_FILE
-
-#endif
-}
-
-
-TEST(JSC, VMInspectorSprintf)
-{
-#if ENABLE(VMINSPECTOR)
- char actual[1024];
- char expected[1024];
- const char* format;
- const char* expectedLiteral;
-
- // Testing standard default format specifiers:
- // Note: should work just like sprintf. So, we just compare against that.
- memset(actual, 'z', sizeof(actual));
- // The compiler warning flags are configured to expect a literal string for
- // ::sprintf below. So, use a #define for this one case to keep the
- // compiler happy.
-#undef LITERAL_FORMAT
-#define LITERAL_FORMAT "'%%%%' ==> '%%'\n"
- VMInspector::sprintf(actual, LITERAL_FORMAT);
- ::sprintf(expected, LITERAL_FORMAT);
-#undef LITERAL_FORMAT
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%c', 'x' ==> '%c'\n";
- VMInspector::sprintf(actual, format, 'x');
- ::sprintf(expected, format, 'x');
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%*c', 8, 'x' ==> '%*c'\n";
- VMInspector::sprintf(actual, format, 8, 'x');
- ::sprintf(expected, format, 8, 'x');
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%s', \"hello world\" ==> '%s'\n";
- VMInspector::sprintf(actual, format, "hello world");
- ::sprintf(expected, format, "hello world");
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%*s', 8, \"hello world\" ==> '%*s'\n";
- VMInspector::sprintf(actual, format, 8, "hello world");
- ::sprintf(expected, format, 8, "hello world");
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%*s', 8, \"hello\" ==> '%*s'\n";
- VMInspector::sprintf(actual, format, 8, "hello");
- ::sprintf(expected, format, 8, "hello");
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%d', 987654321 ==> '%d'\n";
- VMInspector::sprintf(actual, format, 987654321);
- ::sprintf(expected, format, 987654321);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%u', 4276543210u ==> '%u'\n";
- VMInspector::sprintf(actual, format, 4276543210u);
- ::sprintf(expected, format, 4276543210u);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%u', 0xffffffff ==> '%u'\n";
- VMInspector::sprintf(actual, format, 0xffffffff);
- ::sprintf(expected, format, 0xffffffff);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%x', 0xffffffff ==> '%x'\n";
- VMInspector::sprintf(actual, format, 0xffffffff);
- ::sprintf(expected, format, 0xffffffff);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%p', (void*)0xabcdbabe ==> '%p'\n";
- VMInspector::sprintf(actual, format, (void*)0xabcdbabe);
- ::sprintf(expected, format, (void*)0xabcdbabe);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%lu', 1234567890987654321ul ==> '%lu'\n";
- VMInspector::sprintf(actual, format, 1234567890987654321ul);
- ::sprintf(expected, format, 1234567890987654321ul);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%f', 1234.567 ==> '%f'\n";
- VMInspector::sprintf(actual, format, 1234.567);
- ::sprintf(expected, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%.2f', 1234.567 ==> '%.2f'\n";
- VMInspector::sprintf(actual, format, 1234.567);
- ::sprintf(expected, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%10.2f', 1234.567 ==> '%10.2f'\n";
- VMInspector::sprintf(actual, format, 1234.567);
- ::sprintf(expected, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%010.2f', 1234.567 ==> '%010.2f'\n";
- VMInspector::sprintf(actual, format, 1234.567);
- ::sprintf(expected, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- // Bad / weird formats:
- memset(actual, 'z', sizeof(actual));
- format = "'%%5.4', 987654321 ==> '%5.4'\n";
- VMInspector::sprintf(actual, format, 987654321);
- expectedLiteral = "'%5.4', 987654321 ==> 'ERROR @ \"%5.4' \"\n";
- ASSERT_EQ(strcmp(actual, expectedLiteral), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%5.4' '%%d', 987654321, 4 ==> '%5.4' '%d'\n";
- VMInspector::sprintf(actual, format, 987654321, 4);
- ::sprintf(expected, format, 987654321, 4);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%w' '%%d', 987654321, 6 ==> '%w' '%d'\n";
- VMInspector::sprintf(actual, format, 987654321, 6);
- ::sprintf(expected, format, 987654321, 6);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
-
- // Testing the %b extension:
- memset(actual, 'z', sizeof(actual));
- VMInspector::sprintf(actual, "'%%b', 0 ==> '%b'\n", 0);
- ASSERT_EQ(strcmp(actual, "'%b', 0 ==> 'FALSE'\n"), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::sprintf(actual, "'%%b', 1 ==> '%b'\n", 1);
- ASSERT_EQ(strcmp(actual, "'%b', 1 ==> 'TRUE'\n"), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::sprintf(actual, "'%%b', -123456789 ==> '%b'\n", -123456789);
- ASSERT_EQ(strcmp(actual, "'%b', -123456789 ==> 'TRUE'\n"), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::sprintf(actual, "'%%b', 123456789 ==> '%b'\n", 123456789);
- ASSERT_EQ(strcmp(actual, "'%b', 123456789 ==> 'TRUE'\n"), 0);
-
-
- // Testing the %J<x> extensions:
- String str1("Test WTF String");
- String str2("");
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::sprintf(actual, "'%%Js' is %%s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%Js' is %s\n",
- &str1, str1.isEmpty() ? "EMPTY" : "NOT EMPTY");
- expectedLiteral = "'%Js' is %s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> 'Test WTF String' is NOT EMPTY\n";
- ASSERT_EQ(strcmp(actual, expectedLiteral), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::sprintf(actual, "'%%Js' is %%s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%Js' is %s\n",
- &str2, str2.isEmpty() ? "EMPTY" : "NOT EMPTY");
- expectedLiteral = "'%Js' is %s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '' is EMPTY\n";
- ASSERT_EQ(strcmp(actual, expectedLiteral), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::sprintf(actual, "'%%J+s' is %%s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%J+s' is %s\n",
- &str1, str1.isEmpty() ? "EMPTY" : "NOT EMPTY");
- expectedLiteral = "'%J+s' is %s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> 'WTF::String \"Test WTF String\"' is NOT EMPTY\n";
- ASSERT_EQ(strcmp(actual, expectedLiteral), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::sprintf(actual, "'%%J+s' is %%s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%J+s' is %s\n",
- &str2, str2.isEmpty() ? "EMPTY" : "NOT EMPTY");
- expectedLiteral = "'%J+s' is %s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> 'WTF::String \"\"' is EMPTY\n";
- ASSERT_EQ(strcmp(actual, expectedLiteral), 0);
-#endif
-}
-
-
-TEST(JSC, VMInspectorSnprintf)
-{
-#if ENABLE(VMINSPECTOR)
- char actual[1024];
- char expected[1024];
- const char* format;
- const char* expectedLiteral;
-
- size_t size = 1;
- while (size <= 100) {
-
- // Testing standard default format specifiers:
- // Note: should work just like snprintf. So, we just compare against that.
- memset(actual, 'z', sizeof(actual));
- // The compiler warning flags are configured to expect a literal string for
- // ::snprintf below. So, use a #define for this one case to keep the
- // compiler happy.
-#undef LITERAL_FORMAT
-#define LITERAL_FORMAT "'%%%%' ==> '%%'\n"
- VMInspector::snprintf(actual, size, LITERAL_FORMAT);
- ::snprintf(expected, size, LITERAL_FORMAT);
-#undef LITERAL_FORMAT
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%c', 'x' ==> '%c'\n";
- VMInspector::snprintf(actual, size, format, 'x');
- ::snprintf(expected, size, format, 'x');
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%*c', 8, 'x' ==> '%*c'\n";
- VMInspector::snprintf(actual, size, format, 8, 'x');
- ::snprintf(expected, size, format, 8, 'x');
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%s', \"hello world\" ==> '%s'\n";
- VMInspector::snprintf(actual, size, format, "hello world");
- ::snprintf(expected, size, format, "hello world");
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%*s', 8, \"hello world\" ==> '%*s'\n";
- VMInspector::snprintf(actual, size, format, 8, "hello world");
- ::snprintf(expected, size, format, 8, "hello world");
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%*s', 8, \"hello\" ==> '%*s'\n";
- VMInspector::snprintf(actual, size, format, 8, "hello");
- ::snprintf(expected, size, format, 8, "hello");
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%d', 987654321 ==> '%d'\n";
- VMInspector::snprintf(actual, size, format, 987654321);
- ::snprintf(expected, size, format, 987654321);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%u', 4276543210u ==> '%u'\n";
- VMInspector::snprintf(actual, size, format, 4276543210u);
- ::snprintf(expected, size, format, 4276543210u);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%u', 0xffffffff ==> '%u'\n";
- VMInspector::snprintf(actual, size, format, 0xffffffff);
- ::snprintf(expected, size, format, 0xffffffff);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%x', 0xffffffff ==> '%x'\n";
- VMInspector::snprintf(actual, size, format, 0xffffffff);
- ::snprintf(expected, size, format, 0xffffffff);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%p', (void*)0xabcdbabe ==> '%p'\n";
- VMInspector::snprintf(actual, size, format, (void*)0xabcdbabe);
- ::snprintf(expected, size, format, (void*)0xabcdbabe);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%lu', 1234567890987654321ul ==> '%lu'\n";
- VMInspector::snprintf(actual, size, format, 1234567890987654321ul);
- ::snprintf(expected, size, format, 1234567890987654321ul);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%f', 1234.567 ==> '%f'\n";
- VMInspector::snprintf(actual, size, format, 1234.567);
- ::snprintf(expected, size, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%.2f', 1234.567 ==> '%.2f'\n";
- VMInspector::snprintf(actual, size, format, 1234.567);
- ::snprintf(expected, size, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%10.2f', 1234.567 ==> '%10.2f'\n";
- VMInspector::snprintf(actual, size, format, 1234.567);
- ::snprintf(expected, size, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%010.2f', 1234.567 ==> '%010.2f'\n";
- VMInspector::snprintf(actual, size, format, 1234.567);
- ::snprintf(expected, size, format, 1234.567);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- // Bad / weird formats:
- memset(actual, 'z', sizeof(actual));
- format = "'%%5.4', 987654321 ==> '%5.4'\n";
- VMInspector::snprintf(actual, size, format, 987654321);
- expectedLiteral = "'%5.4', 987654321 ==> 'ERROR @ \"%5.4' \"\n";
- ::snprintf(expected, size, "%s", expectedLiteral);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%5.4' '%%d', 987654321, 4 ==> '%5.4' '%d'\n";
- VMInspector::snprintf(actual, size, format, 987654321, 4);
- ::snprintf(expected, size, format, 987654321, 4);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- format = "'%%w' '%%d', 987654321, 6 ==> '%w' '%d'\n";
- VMInspector::snprintf(actual, size, format, 987654321, 6);
- ::snprintf(expected, size, format, 987654321, 6);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
-
- // Testing the %b extension:
- memset(actual, 'z', sizeof(actual));
- VMInspector::snprintf(actual, size, "'%%b', 0 ==> '%b'\n", 0);
- expectedLiteral = "'%b', 0 ==> 'FALSE'\n";
- ::snprintf(expected, size, "%s", expectedLiteral);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::snprintf(actual, size, "'%%b', 1 ==> '%b'\n", 1);
- expectedLiteral = "'%b', 1 ==> 'TRUE'\n";
- ::snprintf(expected, size, "%s", expectedLiteral);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::snprintf(actual, size, "'%%b', -123456789 ==> '%b'\n", -123456789);
- expectedLiteral = "'%b', -123456789 ==> 'TRUE'\n";
- ::snprintf(expected, size, "%s", expectedLiteral);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::snprintf(actual, size, "'%%b', 123456789 ==> '%b'\n", 123456789);
- expectedLiteral = "'%b', 123456789 ==> 'TRUE'\n";
- ::snprintf(expected, size, "%s", expectedLiteral);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- // Testing the %J<x> extensions:
- String str1("Test WTF String");
- String str2("");
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::snprintf(actual, size, "'%%Js' is %%s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%Js' is %s\n",
- &str1, str1.isEmpty() ? "EMPTY" : "NOT EMPTY");
- expectedLiteral = "'%Js' is %s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> 'Test WTF String' is NOT EMPTY\n";
- ::snprintf(expected, size, "%s", expectedLiteral);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::snprintf(actual, size, "'%%Js' is %%s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%Js' is %s\n",
- &str2, str2.isEmpty() ? "EMPTY" : "NOT EMPTY");
- expectedLiteral = "'%Js' is %s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '' is EMPTY\n";
- ::snprintf(expected, size, "%s", expectedLiteral);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::snprintf(actual, size, "'%%J+s' is %%s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%J+s' is %s\n",
- &str1, str1.isEmpty() ? "EMPTY" : "NOT EMPTY");
- expectedLiteral = "'%J+s' is %s, &str1, str1.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> 'WTF::String \"Test WTF String\"' is NOT EMPTY\n";
- ::snprintf(expected, size, "%s", expectedLiteral);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- memset(actual, 'z', sizeof(actual));
- VMInspector::snprintf(actual, size, "'%%J+s' is %%s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> '%J+s' is %s\n",
- &str2, str2.isEmpty() ? "EMPTY" : "NOT EMPTY");
- expectedLiteral = "'%J+s' is %s, &str2, str2.isEmpty()?\"EMPTY\":\"NOT EMPTY\" ==> 'WTF::String \"\"' is EMPTY\n";
- ::snprintf(expected, size, "%s", expectedLiteral);
- ASSERT_EQ(strcmp(actual, expected), 0);
-
- // Test lower sizes more densely, and then space out to larger sizes.
- // We're doing this because the lower sizes might be interesting, but
- // for expediency, we don't want to test at this fine grain resolution
- // for all possible sizes. Hence, we accelerate the rate once we're
- // pass the interesting small sizes.
- if (size <= 5)
- size++;
- else
- size += 4;
- }
-#endif
-}
diff --git a/Tools/TestWebKitAPI/Tests/WTF/AtomicString.cpp b/Tools/TestWebKitAPI/Tests/WTF/AtomicString.cpp
index 9df71ce44..de962ec42 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/AtomicString.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/AtomicString.cpp
@@ -39,7 +39,6 @@ TEST(WTF, AtomicStringCreationFromLiteral)
const char* programmaticStringData = "Explicit Size Literal";
AtomicString programmaticString(programmaticStringData, strlen(programmaticStringData), AtomicString::ConstructFromLiteral);
ASSERT_EQ(strlen(programmaticStringData), programmaticString.length());
- ASSERT_TRUE(programmaticStringData == programmaticStringData);
ASSERT_TRUE(programmaticString.string().is8Bit());
ASSERT_EQ(programmaticStringData, reinterpret_cast<const char*>(programmaticString.string().characters8()));
}
@@ -54,4 +53,12 @@ TEST(WTF, AtomicStringCreationFromLiteralUniqueness)
ASSERT_EQ(string1.impl(), string3.impl());
}
+TEST(WTF, AtomicStringExistingHash)
+{
+ AtomicString string1("Template Literal", AtomicString::ConstructFromLiteral);
+ ASSERT_EQ(string1.existingHash(), string1.impl()->existingHash());
+ AtomicString string2;
+ ASSERT_EQ(string2.existingHash(), 0u);
+}
+
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/BloomFilter.cpp b/Tools/TestWebKitAPI/Tests/WTF/BloomFilter.cpp
new file mode 100644
index 000000000..802165211
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/BloomFilter.cpp
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <wtf/BloomFilter.h>
+#include <wtf/RandomNumber.h>
+#include <wtf/SHA1.h>
+
+namespace TestWebKitAPI {
+
+static Vector<unsigned> generateRandomHashes(size_t hashCount)
+{
+ Vector<unsigned> hashes;
+ for (unsigned i = 0; i < hashCount; ++i)
+ hashes.append(static_cast<unsigned>(randomNumber() * std::numeric_limits<unsigned>::max()));
+ return hashes;
+}
+
+static Vector<SHA1::Digest> generateRandomDigests(size_t hashCount)
+{
+ Vector<SHA1::Digest> hashes;
+ SHA1 sha1;
+ for (unsigned i = 0; i < hashCount; ++i) {
+ double random = randomNumber();
+ sha1.addBytes(reinterpret_cast<uint8_t*>(&random), sizeof(double));
+ SHA1::Digest digest;
+ sha1.computeHash(digest);
+ hashes.append(digest);
+ }
+ return hashes;
+}
+
+TEST(WTF_BloomFilter, Basic)
+{
+ const unsigned hashCount = 1000;
+ auto hashes = generateRandomHashes(hashCount);
+
+ BloomFilter<16> filter;
+ for (auto hash : hashes)
+ filter.add(hash);
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+
+ auto moreHashes = generateRandomHashes(hashCount);
+ unsigned mayContainCount = 0;
+ for (auto hash : moreHashes)
+ mayContainCount += filter.mayContain(hash) ? 1 : 0;
+ // False positive rate is ~0.09% so this should always be true.
+ EXPECT_TRUE(mayContainCount < hashCount / 10);
+
+ for (auto hash : moreHashes)
+ filter.add(hash);
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+ for (auto hash : moreHashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+}
+
+TEST(WTF_BloomFilter, BasicDigest)
+{
+ const unsigned hashCount = 1000;
+ auto hashes = generateRandomDigests(hashCount);
+
+ BloomFilter<20> filter;
+ for (auto hash : hashes)
+ filter.add(hash);
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+
+ auto moreHashes = generateRandomDigests(hashCount);
+ unsigned mayContainCount = 0;
+ for (auto hash : moreHashes)
+ mayContainCount += filter.mayContain(hash) ? 1 : 0;
+ // False positive rate is ~0.000004% so this should always be true.
+ EXPECT_TRUE(mayContainCount < hashCount / 10);
+
+ for (auto hash : moreHashes)
+ filter.add(hash);
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+ for (auto hash : moreHashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+}
+
+TEST(WTF_BloomFilter, BasicCounting)
+{
+ const unsigned hashCount = 1000;
+ auto hashes = generateRandomHashes(hashCount);
+
+ CountingBloomFilter<16> filter;
+ for (auto hash : hashes)
+ filter.add(hash);
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+
+ for (auto hash : hashes)
+ filter.add(hash);
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+
+ for (auto hash : hashes)
+ filter.remove(hash);
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+
+ auto moreHashes = generateRandomHashes(hashCount);
+ unsigned mayContainCount = 0;
+ for (auto hash : moreHashes)
+ mayContainCount += filter.mayContain(hash) ? 1 : 0;
+ // False positive rate is ~0.09% so this should always be true.
+ EXPECT_TRUE(mayContainCount < hashCount / 10);
+
+ for (auto hash : moreHashes)
+ filter.add(hash);
+ for (auto hash : hashes)
+ filter.remove(hash);
+
+ for (auto hash : moreHashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+
+ for (auto hash : moreHashes)
+ filter.remove(hash);
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(!filter.mayContain(hash));
+ for (auto hash : moreHashes)
+ EXPECT_TRUE(!filter.mayContain(hash));
+}
+
+TEST(WTF_BloomFilter, Clear)
+{
+ const unsigned hashCount = 1000;
+ auto hashes = generateRandomHashes(hashCount);
+
+ BloomFilter<16> filter;
+ for (auto hash : hashes)
+ filter.add(hash);
+
+ filter.clear();
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(!filter.mayContain(hash));
+}
+
+TEST(WTF_BloomFilter, ClearCounting)
+{
+ const unsigned hashCount = 1000;
+ auto hashes = generateRandomHashes(hashCount);
+
+ CountingBloomFilter<16> filter;
+ for (auto hash : hashes)
+ filter.add(hash);
+ for (auto hash : hashes)
+ filter.add(hash);
+
+ filter.clear();
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(!filter.mayContain(hash));
+}
+
+TEST(WTF_BloomFilter, CountingOverflow)
+{
+ const unsigned hashCount = 1000;
+ auto hashes = generateRandomHashes(hashCount);
+
+ CountingBloomFilter<16> filter;
+ for (auto hash : hashes)
+ filter.add(hash);
+
+ for (unsigned i = 0; i < filter.maximumCount() + 100; ++i)
+ filter.add(hashes[0]);
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+
+ for (auto hash : hashes)
+ filter.remove(hash);
+
+ unsigned mayContainCount = 0;
+ for (auto hash : hashes) {
+ if (hash == hashes[0])
+ EXPECT_TRUE(filter.mayContain(hash));
+ else
+ mayContainCount += filter.mayContain(hash) ? 1 : 0;
+ }
+ // False positive rate should be very low.
+ EXPECT_TRUE(mayContainCount < hashCount / 100);
+
+ for (unsigned i = 0; i < filter.maximumCount() + 100; ++i)
+ filter.remove(hashes[0]);
+
+ // The bucket has overflowed and is stuck.
+ EXPECT_TRUE(filter.mayContain(hashes[0]));
+}
+
+TEST(WTF_BloomFilter, Combine)
+{
+ const unsigned hashCount = 1000;
+ auto hashes = generateRandomHashes(hashCount);
+
+ BloomFilter<16> filter;
+ for (auto hash : hashes)
+ filter.add(hash);
+
+ auto moreHashes = generateRandomHashes(hashCount);
+
+ BloomFilter<16> anotherFilter;
+ for (auto hash : moreHashes)
+ anotherFilter.add(hash);
+
+ filter.add(anotherFilter);
+
+ for (auto hash : hashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+ for (auto hash : moreHashes)
+ EXPECT_TRUE(filter.mayContain(hash));
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WTF/CheckedArithmeticOperations.cpp b/Tools/TestWebKitAPI/Tests/WTF/CheckedArithmeticOperations.cpp
index 77b8ff458..d6b548316 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/CheckedArithmeticOperations.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/CheckedArithmeticOperations.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,117 +28,397 @@
namespace TestWebKitAPI {
-#define CheckedArithmeticTest(type, coerceLiteral, MixedSignednessTest) \
+class OverflowCrashLogger {
+protected:
+ void overflowed()
+ {
+ m_overflowCount++;
+ }
+
+ void clearOverflow()
+ {
+ m_overflowCount = 0;
+ }
+
+ static void crash()
+ {
+ s_didCrash = true;
+ }
+
+public:
+ void reset()
+ {
+ m_overflowCount = 0;
+ s_didCrash = false;
+ }
+
+ bool hasOverflowed() const { return m_overflowCount > 0; }
+ int overflowCount() const { return m_overflowCount; }
+
+ bool didCrash() const { return s_didCrash; }
+
+private:
+ int m_overflowCount { 0 };
+ static bool s_didCrash;
+};
+
+bool OverflowCrashLogger::s_didCrash = false;
+
+template <typename type>
+static void resetOverflow(Checked<type, OverflowCrashLogger>& value)
+{
+ value.reset();
+ value = 100;
+ value *= std::numeric_limits<type>::max();
+}
+
+#define CheckedArithmeticTest(type, Coercer, MixedSignednessTester) \
TEST(WTF, Checked_##type) \
{ \
- Checked<type, RecordOverflow> value; \
- EXPECT_EQ(coerceLiteral(0), value.unsafeGet()); \
- EXPECT_EQ(std::numeric_limits<type>::max(), (value + std::numeric_limits<type>::max()).unsafeGet()); \
- EXPECT_EQ(std::numeric_limits<type>::max(), (std::numeric_limits<type>::max() + value).unsafeGet()); \
- EXPECT_EQ(std::numeric_limits<type>::min(), (value + std::numeric_limits<type>::min()).unsafeGet()); \
- EXPECT_EQ(std::numeric_limits<type>::min(), (std::numeric_limits<type>::min() + value).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), (value * coerceLiteral(0)).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), (coerceLiteral(0) * value).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), (value * value).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), (value - coerceLiteral(0)).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), (coerceLiteral(0) - value).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), (value - value).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), (value++).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(1), (value--).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(1), (++value).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), (--value).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(10), (value += coerceLiteral(10)).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(10), value.unsafeGet()); \
- EXPECT_EQ(coerceLiteral(100), (value *= coerceLiteral(10)).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(100), value.unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), (value -= coerceLiteral(100)).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), value.unsafeGet()); \
- value = 10; \
- EXPECT_EQ(coerceLiteral(10), value.unsafeGet()); \
- EXPECT_EQ(coerceLiteral(0), (value - coerceLiteral(10)).unsafeGet()); \
- EXPECT_EQ(coerceLiteral(10), value.unsafeGet()); \
- value = std::numeric_limits<type>::min(); \
- EXPECT_EQ(true, (Checked<type, RecordOverflow>(value - coerceLiteral(1))).hasOverflowed()); \
- EXPECT_EQ(true, !((value--).hasOverflowed())); \
- EXPECT_EQ(true, value.hasOverflowed()); \
- value = std::numeric_limits<type>::max(); \
- EXPECT_EQ(true, !value.hasOverflowed()); \
- EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + coerceLiteral(1))).hasOverflowed()); \
- EXPECT_EQ(true, !(value++).hasOverflowed()); \
- EXPECT_EQ(true, value.hasOverflowed()); \
- value = std::numeric_limits<type>::max(); \
- EXPECT_EQ(true, (value += coerceLiteral(1)).hasOverflowed()); \
- EXPECT_EQ(true, value.hasOverflowed()); \
- value = 10; \
- type _value = 0; \
- EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(0)).safeGet(_value)); \
- _value = 0; \
- EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(0) * value).safeGet(_value)); \
- _value = 0; \
- EXPECT_EQ(true, CheckedState::DidOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
- _value = 0; \
- EXPECT_EQ(true, CheckedState::DidOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value)); \
- value = 0; \
- _value = 0; \
- EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
- _value = 0; \
- EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value)); \
- value = 1; \
- _value = 0; \
- EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
- _value = 0; \
- EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value)); \
- _value = 0; \
- value = 0; \
- EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
- _value = 0; \
- EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)0).safeGet(_value)); \
- _value = 0; \
- value = 1; \
- EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
- _value = 0; \
- EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)1).safeGet(_value)); \
- _value = 0; \
- value = 2; \
- EXPECT_EQ(true, CheckedState::DidOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value)); \
- _value = 0; \
- EXPECT_EQ(true, CheckedState::DidOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)2).safeGet(_value)); \
- value = 10; \
- EXPECT_EQ(true, (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).hasOverflowed()); \
- MixedSignednessTest(EXPECT_EQ(coerceLiteral(0), (value + -10).unsafeGet())); \
- MixedSignednessTest(EXPECT_EQ(0U, (value - 10U).unsafeGet())); \
- MixedSignednessTest(EXPECT_EQ(coerceLiteral(0), (-10 + value).unsafeGet())); \
- MixedSignednessTest(EXPECT_EQ(0U, (10U - value).unsafeGet())); \
- value = std::numeric_limits<type>::min(); \
- MixedSignednessTest(EXPECT_EQ(true, (Checked<type, RecordOverflow>(value - 1)).hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, !(value--).hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
- value = std::numeric_limits<type>::max(); \
- MixedSignednessTest(EXPECT_EQ(true, !value.hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + 1)).hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, !(value++).hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
- value = std::numeric_limits<type>::max(); \
- MixedSignednessTest(EXPECT_EQ(true, (value += 1).hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
- value = std::numeric_limits<type>::min(); \
- MixedSignednessTest(EXPECT_EQ(true, (value - 1U).hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, !(value--).hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
- value = std::numeric_limits<type>::max(); \
- MixedSignednessTest(EXPECT_EQ(true, !value.hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + 1U)).hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, !(value++).hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
- value = std::numeric_limits<type>::max(); \
- MixedSignednessTest(EXPECT_EQ(true, (value += 1U).hasOverflowed())); \
- MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \
+ typedef Coercer<type> CoercerType; \
+ typedef MixedSignednessTester<type, CoercerType> MixedSignednessTesterType; \
+ CheckedArithmeticTester<type, CoercerType, MixedSignednessTesterType>::run(); \
}
+
+#define coerceLiteral(x) Coercer::coerce(x)
+
+template <typename type, typename Coercer, typename MixedSignednessTester>
+class CheckedArithmeticTester {
+public:
+ static void run()
+ {
+ Checked<type, RecordOverflow> value;
+ EXPECT_EQ(coerceLiteral(0), value.unsafeGet());
+ EXPECT_EQ(std::numeric_limits<type>::max(), (value + std::numeric_limits<type>::max()).unsafeGet());
+ EXPECT_EQ(std::numeric_limits<type>::max(), (std::numeric_limits<type>::max() + value).unsafeGet());
+ EXPECT_EQ(std::numeric_limits<type>::min(), (value + std::numeric_limits<type>::min()).unsafeGet());
+ EXPECT_EQ(std::numeric_limits<type>::min(), (std::numeric_limits<type>::min() + value).unsafeGet());
+
+ EXPECT_EQ(coerceLiteral(0), (value * coerceLiteral(0)).unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), (coerceLiteral(0) * value).unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), (value * value).unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), (value - coerceLiteral(0)).unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), (coerceLiteral(0) - value).unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), (value - value).unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), (value++).unsafeGet());
+ EXPECT_EQ(coerceLiteral(1), (value--).unsafeGet());
+ EXPECT_EQ(coerceLiteral(1), (++value).unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), (--value).unsafeGet());
+ EXPECT_EQ(coerceLiteral(10), (value += coerceLiteral(10)).unsafeGet());
+ EXPECT_EQ(coerceLiteral(10), value.unsafeGet());
+ EXPECT_EQ(coerceLiteral(100), (value *= coerceLiteral(10)).unsafeGet());
+ EXPECT_EQ(coerceLiteral(100), value.unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), (value -= coerceLiteral(100)).unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), value.unsafeGet());
+ value = 10;
+ EXPECT_EQ(coerceLiteral(10), value.unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), (value - coerceLiteral(10)).unsafeGet());
+ EXPECT_EQ(coerceLiteral(10), value.unsafeGet());
+
+ value = std::numeric_limits<type>::min();
+ EXPECT_EQ(true, (Checked<type, RecordOverflow>(value - coerceLiteral(1))).hasOverflowed());
+ EXPECT_EQ(true, !((value--).hasOverflowed()));
+ EXPECT_EQ(true, value.hasOverflowed());
+ value = std::numeric_limits<type>::max();
+ EXPECT_EQ(true, !value.hasOverflowed());
+ EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + coerceLiteral(1))).hasOverflowed());
+ EXPECT_EQ(true, !(value++).hasOverflowed());
+ EXPECT_EQ(true, value.hasOverflowed());
+ value = std::numeric_limits<type>::max();
+ EXPECT_EQ(true, (value += coerceLiteral(1)).hasOverflowed());
+ EXPECT_EQ(true, value.hasOverflowed());
+
+ value = 10;
+ type _value = 0;
+ EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(0)).safeGet(_value));
+ _value = 0;
+ EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(0) * value).safeGet(_value));
+ _value = 0;
+ EXPECT_EQ(true, CheckedState::DidOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value));
+ _value = 0;
+ EXPECT_EQ(true, CheckedState::DidOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value));
+ value = 0;
+ _value = 0;
+ EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value));
+ _value = 0;
+ EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value));
+ value = 1;
+ _value = 0;
+ EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value));
+ _value = 0;
+ EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * value).safeGet(_value));
+ _value = 0;
+ value = 0;
+ EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value));
+ _value = 0;
+ EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)0).safeGet(_value));
+ _value = 0;
+ value = 1;
+ EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value));
+ _value = 0;
+ EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)1).safeGet(_value));
+ _value = 0;
+ value = 2;
+ EXPECT_EQ(true, CheckedState::DidOverflow == (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).safeGet(_value));
+ _value = 0;
+ EXPECT_EQ(true, CheckedState::DidOverflow == (Checked<type, RecordOverflow>(std::numeric_limits<type>::max()) * (type)2).safeGet(_value));
+ value = 10;
+ EXPECT_EQ(true, (value * Checked<type, RecordOverflow>(std::numeric_limits<type>::max())).hasOverflowed());
+
+
+ Checked<type, OverflowCrashLogger> nvalue; // to hold a not overflowed value.
+ Checked<type, OverflowCrashLogger> ovalue; // to hold an overflowed value.
+ bool unused;
+
+ _value = 75;
+ type _largeValue = 100;
+ type _smallValue = 50;
+
+ value = _smallValue;
+ nvalue = _value;
+ ovalue = _value;
+
+ // Make sure the OverflowCrashLogger is working as expected.
+ EXPECT_EQ(false, (ovalue.hasOverflowed()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), ovalue.hasOverflowed()));
+ EXPECT_EQ(false, (resetOverflow(ovalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (unused = (ovalue == ovalue), ovalue.didCrash()));
+ EXPECT_EQ(false, (resetOverflow(ovalue), ovalue.didCrash()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+ EXPECT_EQ(false, nvalue.didCrash());
+
+ // Test operator== that should not overflow nor crash.
+ EXPECT_EQ(true, (nvalue == nvalue));
+ EXPECT_EQ(true, (nvalue == Checked<type, OverflowCrashLogger>(_value)));
+ EXPECT_EQ(false, (nvalue == value));
+ EXPECT_EQ(true, (nvalue == _value));
+ EXPECT_EQ(false, (nvalue == Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())));
+ EXPECT_EQ(false, (nvalue == std::numeric_limits<type>::max()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+ EXPECT_EQ(false, nvalue.didCrash());
+
+ // Test operator!= that should not overflow nor crash.
+ EXPECT_EQ(false, (nvalue != nvalue));
+ EXPECT_EQ(false, (nvalue != Checked<type, OverflowCrashLogger>(_value)));
+ EXPECT_EQ(true, (nvalue != value));
+ EXPECT_EQ(false, (nvalue != _value));
+ EXPECT_EQ(true, (nvalue != Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())));
+ EXPECT_EQ(true, (nvalue != std::numeric_limits<type>::max()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+ EXPECT_EQ(false, nvalue.didCrash());
+
+ // Test operator< that should not overflow nor crash.
+ EXPECT_EQ(false, (nvalue < nvalue));
+ EXPECT_EQ(false, (nvalue < value));
+ EXPECT_EQ(true, (nvalue < Checked<type, OverflowCrashLogger>(_largeValue)));
+ EXPECT_EQ(false, (nvalue < Checked<type, OverflowCrashLogger>(_value)));
+ EXPECT_EQ(false, (nvalue < Checked<type, OverflowCrashLogger>(_smallValue)));
+ EXPECT_EQ(true, (nvalue < _largeValue));
+ EXPECT_EQ(false, (nvalue < _value));
+ EXPECT_EQ(false, (nvalue < _smallValue));
+ EXPECT_EQ(true, (nvalue < Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())));
+ EXPECT_EQ(true, (nvalue < std::numeric_limits<type>::max()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+ EXPECT_EQ(false, nvalue.didCrash());
+
+ // Test operator<= that should not overflow nor crash.
+ EXPECT_EQ(true, (nvalue <= nvalue));
+ EXPECT_EQ(false, (nvalue <= value));
+ EXPECT_EQ(true, (nvalue <= Checked<type, OverflowCrashLogger>(_largeValue)));
+ EXPECT_EQ(true, (nvalue <= Checked<type, OverflowCrashLogger>(_value)));
+ EXPECT_EQ(false, (nvalue <= Checked<type, OverflowCrashLogger>(_smallValue)));
+ EXPECT_EQ(true, (nvalue <= _largeValue));
+ EXPECT_EQ(true, (nvalue <= _value));
+ EXPECT_EQ(false, (nvalue <= _smallValue));
+ EXPECT_EQ(true, (nvalue <= Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())));
+ EXPECT_EQ(true, (nvalue <= std::numeric_limits<type>::max()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+ EXPECT_EQ(false, nvalue.didCrash());
+
+ // Test operator> that should not overflow nor crash.
+ EXPECT_EQ(false, (nvalue > nvalue));
+ EXPECT_EQ(true, (nvalue > value));
+ EXPECT_EQ(false, (nvalue > Checked<type, OverflowCrashLogger>(_largeValue)));
+ EXPECT_EQ(false, (nvalue > Checked<type, OverflowCrashLogger>(_value)));
+ EXPECT_EQ(true, (nvalue > Checked<type, OverflowCrashLogger>(_smallValue)));
+ EXPECT_EQ(false, (nvalue > _largeValue));
+ EXPECT_EQ(false, (nvalue > _value));
+ EXPECT_EQ(true, (nvalue > _smallValue));
+ EXPECT_EQ(false, (nvalue > Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())));
+ EXPECT_EQ(false, (nvalue > std::numeric_limits<type>::max()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+ EXPECT_EQ(false, nvalue.didCrash());
+
+ // Test operator>= that should not overflow nor crash.
+ EXPECT_EQ(true, (nvalue >= nvalue));
+ EXPECT_EQ(true, (nvalue >= value));
+ EXPECT_EQ(false, (nvalue >= Checked<type, OverflowCrashLogger>(_largeValue)));
+ EXPECT_EQ(true, (nvalue >= Checked<type, OverflowCrashLogger>(_value)));
+ EXPECT_EQ(true, (nvalue >= Checked<type, OverflowCrashLogger>(_smallValue)));
+ EXPECT_EQ(false, (nvalue >= _largeValue));
+ EXPECT_EQ(true, (nvalue >= _value));
+ EXPECT_EQ(true, (nvalue >= _smallValue));
+ EXPECT_EQ(false, (nvalue >= Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())));
+ EXPECT_EQ(false, (nvalue >= std::numeric_limits<type>::max()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+ EXPECT_EQ(false, nvalue.didCrash());
+
+ // Test operator== with an overflowed value.
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == ovalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == Checked<type, OverflowCrashLogger>(_value)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == _value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == _value * std::numeric_limits<type>::max()), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == std::numeric_limits<type>::max()), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == nvalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (nvalue == ovalue), ovalue.didCrash()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+
+ // Test operator!= with an overflowed value.
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != ovalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != Checked<type, OverflowCrashLogger>(_value)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != _value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != _value * std::numeric_limits<type>::max()), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != std::numeric_limits<type>::max()), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != nvalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (nvalue != ovalue), ovalue.didCrash()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+
+ // Test operator< with an overflowed value.
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < ovalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < Checked<type, OverflowCrashLogger>(_largeValue)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < Checked<type, OverflowCrashLogger>(_value)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < Checked<type, OverflowCrashLogger>(_smallValue)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < _largeValue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < _value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < _smallValue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < std::numeric_limits<type>::max()), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < nvalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (nvalue < ovalue), ovalue.didCrash()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+
+ // Test operator<= with an overflowed value.
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= ovalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= Checked<type, OverflowCrashLogger>(_largeValue)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= Checked<type, OverflowCrashLogger>(_value)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= Checked<type, OverflowCrashLogger>(_smallValue)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= _largeValue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= _value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= _smallValue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= std::numeric_limits<type>::max()), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= nvalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (nvalue <= ovalue), ovalue.didCrash()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+
+ // Test operator> with an overflowed value.
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > ovalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > Checked<type, OverflowCrashLogger>(_largeValue)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > Checked<type, OverflowCrashLogger>(_value)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > Checked<type, OverflowCrashLogger>(_smallValue)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > _largeValue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > _value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > _smallValue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > std::numeric_limits<type>::max()), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > nvalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (nvalue > ovalue), ovalue.didCrash()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+
+ // Test operator>= with an overflowed value.
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= ovalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= Checked<type, OverflowCrashLogger>(_largeValue)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= Checked<type, OverflowCrashLogger>(_value)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= Checked<type, OverflowCrashLogger>(_smallValue)), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= _largeValue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= _value), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= _smallValue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= Checked<type, OverflowCrashLogger>(std::numeric_limits<type>::max())), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= std::numeric_limits<type>::max()), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= nvalue), ovalue.didCrash()));
+ EXPECT_EQ(true, (resetOverflow(ovalue), unused = (nvalue >= ovalue), ovalue.didCrash()));
+
+ EXPECT_EQ(false, nvalue.hasOverflowed());
+
+ MixedSignednessTester::run();
+ }
+};
+
+template <typename type, typename Coercer>
+class AllowMixedSignednessTest {
+public:
+ static void run()
+ {
+ Checked<type, RecordOverflow> value;
+ value = 10;
+
+ EXPECT_EQ(coerceLiteral(0), (value + -10).unsafeGet());
+ EXPECT_EQ(0U, (value - 10U).unsafeGet());
+ EXPECT_EQ(coerceLiteral(0), (-10 + value).unsafeGet());
+ EXPECT_EQ(0U, (10U - value).unsafeGet());
+ value = std::numeric_limits<type>::min();
+ EXPECT_EQ(true, (Checked<type, RecordOverflow>(value - 1)).hasOverflowed());
+ EXPECT_EQ(true, !(value--).hasOverflowed());
+ EXPECT_EQ(true, value.hasOverflowed());
+ value = std::numeric_limits<type>::max();
+ EXPECT_EQ(true, !value.hasOverflowed());
+ EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + 1)).hasOverflowed());
+ EXPECT_EQ(true, !(value++).hasOverflowed());
+ EXPECT_EQ(true, value.hasOverflowed());
+ value = std::numeric_limits<type>::max();
+ EXPECT_EQ(true, (value += 1).hasOverflowed());
+ EXPECT_EQ(true, value.hasOverflowed());
+ value = std::numeric_limits<type>::min();
+ EXPECT_EQ(true, (value - 1U).hasOverflowed());
+ EXPECT_EQ(true, !(value--).hasOverflowed());
+ EXPECT_EQ(true, value.hasOverflowed());
+ value = std::numeric_limits<type>::max();
+ EXPECT_EQ(true, !value.hasOverflowed());
+ EXPECT_EQ(true, (Checked<type, RecordOverflow>(value + 1U)).hasOverflowed());
+ EXPECT_EQ(true, !(value++).hasOverflowed());
+ EXPECT_EQ(true, value.hasOverflowed());
+ value = std::numeric_limits<type>::max();
+ EXPECT_EQ(true, (value += 1U).hasOverflowed());
+ EXPECT_EQ(true, value.hasOverflowed());
+ }
+};
+
+template <typename type, typename Coercer>
+class IgnoreMixedSignednessTest {
+public:
+ static void run() { }
+};
+
+template <typename type> class CoerceLiteralToUnsigned {
+public:
+ static unsigned coerce(type x) { return static_cast<unsigned>(x); }
+};
+
+template <typename type> class CoerceLiteralNop {
+public:
+ static type coerce(type x) { return x; }
+};
-#define CoerceLiteralToUnsigned(x) x##U
-#define CoerceLiteralNop(x) x
-#define AllowMixedSignednessTest(x) x
-#define IgnoreMixedSignednessTest(x)
CheckedArithmeticTest(int8_t, CoerceLiteralNop, IgnoreMixedSignednessTest)
CheckedArithmeticTest(int16_t, CoerceLiteralNop, IgnoreMixedSignednessTest)
CheckedArithmeticTest(int32_t, CoerceLiteralNop, AllowMixedSignednessTest)
@@ -146,4 +426,62 @@ CheckedArithmeticTest(uint32_t, CoerceLiteralToUnsigned, AllowMixedSignednessTes
CheckedArithmeticTest(int64_t, CoerceLiteralNop, IgnoreMixedSignednessTest)
CheckedArithmeticTest(uint64_t, CoerceLiteralToUnsigned, IgnoreMixedSignednessTest)
+TEST(CheckedArithmeticTest, IsInBounds)
+{
+ // bigger precision, signed, signed
+ EXPECT_TRUE(WTF::isInBounds<int32_t>(std::numeric_limits<int16_t>::max()));
+ EXPECT_TRUE(WTF::isInBounds<int32_t>(std::numeric_limits<int16_t>::min()));
+
+ // bigger precision, unsigned, signed
+ EXPECT_TRUE(WTF::isInBounds<uint32_t>(std::numeric_limits<int32_t>::max()));
+ EXPECT_FALSE(WTF::isInBounds<uint32_t>(std::numeric_limits<int16_t>::min()));
+
+ EXPECT_FALSE(WTF::isInBounds<uint32_t>((int32_t)-1));
+ EXPECT_FALSE(WTF::isInBounds<uint16_t>((int32_t)-1));
+ EXPECT_FALSE(WTF::isInBounds<unsigned long>((int)-1));
+
+ EXPECT_TRUE(WTF::isInBounds<uint32_t>((int32_t)1));
+ EXPECT_TRUE(WTF::isInBounds<uint32_t>((int16_t)1));
+ EXPECT_TRUE(WTF::isInBounds<unsigned>((int)1));
+
+ EXPECT_TRUE(WTF::isInBounds<uint32_t>((int32_t)0));
+ EXPECT_TRUE(WTF::isInBounds<uint16_t>((int32_t)0));
+ EXPECT_TRUE(WTF::isInBounds<uint32_t>((int16_t)0));
+ EXPECT_TRUE(WTF::isInBounds<unsigned>((int)0));
+
+ EXPECT_TRUE(WTF::isInBounds<uint32_t>(std::numeric_limits<int32_t>::max()));
+ EXPECT_TRUE(WTF::isInBounds<uint32_t>(std::numeric_limits<int16_t>::max()));
+ EXPECT_TRUE(WTF::isInBounds<unsigned>(std::numeric_limits<int>::max()));
+
+ // bigger precision, signed, unsigned
+ EXPECT_TRUE(WTF::isInBounds<int32_t>(std::numeric_limits<uint16_t>::max()));
+ EXPECT_FALSE(WTF::isInBounds<int32_t>(std::numeric_limits<uint32_t>::max()));
+ EXPECT_TRUE(WTF::isInBounds<int32_t>((uint32_t)0));
+
+ // bigger precision, unsigned, unsigned
+ EXPECT_TRUE(WTF::isInBounds<uint32_t>(std::numeric_limits<uint16_t>::max()));
+ EXPECT_TRUE(WTF::isInBounds<uint32_t>(std::numeric_limits<uint16_t>::min()));
+
+ // lower precision, signed signed
+ EXPECT_FALSE(WTF::isInBounds<int16_t>(std::numeric_limits<int32_t>::max()));
+ EXPECT_FALSE(WTF::isInBounds<int16_t>(std::numeric_limits<int32_t>::min()));
+ EXPECT_TRUE(WTF::isInBounds<int16_t>((int32_t)-1));
+ EXPECT_TRUE(WTF::isInBounds<int16_t>((int32_t)0));
+ EXPECT_TRUE(WTF::isInBounds<int16_t>((int32_t)1));
+ // lower precision, unsigned, signed
+ EXPECT_FALSE(WTF::isInBounds<uint16_t>(std::numeric_limits<int32_t>::max()));
+ EXPECT_FALSE(WTF::isInBounds<uint16_t>(std::numeric_limits<int32_t>::min()));
+ EXPECT_FALSE(WTF::isInBounds<uint16_t>((int32_t)-1));
+ EXPECT_TRUE(WTF::isInBounds<uint16_t>((int32_t)0));
+ EXPECT_TRUE(WTF::isInBounds<uint16_t>((int32_t)1));
+ // lower precision, signed, unsigned
+ EXPECT_FALSE(WTF::isInBounds<int16_t>(std::numeric_limits<uint32_t>::max()));
+ EXPECT_TRUE(WTF::isInBounds<int16_t>((uint32_t)0));
+ EXPECT_TRUE(WTF::isInBounds<int16_t>((uint32_t)1));
+ // lower precision, unsigned, unsigned
+ EXPECT_FALSE(WTF::isInBounds<uint16_t>(std::numeric_limits<uint32_t>::max()));
+ EXPECT_TRUE(WTF::isInBounds<uint16_t>((uint32_t)0));
+ EXPECT_TRUE(WTF::isInBounds<uint16_t>((uint32_t)1));
+}
+
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/Condition.cpp b/Tools/TestWebKitAPI/Tests/WTF/Condition.cpp
new file mode 100644
index 000000000..848527351
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/Condition.cpp
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2015-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. 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 INC. 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.
+ */
+
+#include "config.h"
+#include <mutex>
+#include <thread>
+#include <wtf/Condition.h>
+#include <wtf/DataLog.h>
+#include <wtf/Deque.h>
+#include <wtf/Lock.h>
+#include <wtf/StringPrintStream.h>
+#include <wtf/Threading.h>
+#include <wtf/Vector.h>
+
+using namespace WTF;
+
+namespace TestWebKitAPI {
+
+namespace {
+
+const bool verbose = false;
+
+enum NotifyStyle {
+ AlwaysNotifyOne,
+ TacticallyNotifyAll
+};
+
+template<typename Functor>
+void wait(Condition& condition, std::unique_lock<Lock>& locker, const Functor& predicate, Seconds timeout)
+{
+ if (timeout == Seconds::infinity())
+ condition.wait(locker, predicate);
+ else {
+ // This tests timeouts in the sense that it verifies that we can call wait() again after a
+ // timeout happened. That's a non-trivial piece of functionality since upon timeout the
+ // ParkingLot has to remove us from the queue.
+ while (!predicate())
+ condition.waitFor(locker, timeout, predicate);
+ }
+}
+
+void notify(NotifyStyle notifyStyle, Condition& condition, bool shouldNotify)
+{
+ switch (notifyStyle) {
+ case AlwaysNotifyOne:
+ condition.notifyOne();
+ break;
+ case TacticallyNotifyAll:
+ if (shouldNotify)
+ condition.notifyAll();
+ break;
+ }
+}
+
+void runTest(
+ unsigned numProducers,
+ unsigned numConsumers,
+ unsigned maxQueueSize,
+ unsigned numMessagesPerProducer,
+ NotifyStyle notifyStyle,
+ Seconds timeout = Seconds::infinity(),
+ Seconds delay = 0_s)
+{
+ Deque<unsigned> queue;
+ bool shouldContinue = true;
+ Lock lock;
+ Condition emptyCondition;
+ Condition fullCondition;
+
+ Vector<ThreadIdentifier> consumerThreads;
+ Vector<ThreadIdentifier> producerThreads;
+
+ Vector<unsigned> received;
+ Lock receivedLock;
+
+ for (unsigned i = numConsumers; i--;) {
+ ThreadIdentifier threadIdentifier = createThread(
+ "Consumer thread",
+ [&] () {
+ for (;;) {
+ unsigned result;
+ unsigned shouldNotify = false;
+ {
+ std::unique_lock<Lock> locker(lock);
+ wait(
+ emptyCondition, locker,
+ [&] () {
+ if (verbose)
+ dataLog(toString(currentThread(), ": Checking consumption predicate with shouldContinue = ", shouldContinue, ", queue.size() == ", queue.size(), "\n"));
+ return !shouldContinue || !queue.isEmpty();
+ },
+ timeout);
+ if (!shouldContinue && queue.isEmpty())
+ return;
+ shouldNotify = queue.size() == maxQueueSize;
+ result = queue.takeFirst();
+ }
+ notify(notifyStyle, fullCondition, shouldNotify);
+
+ {
+ std::lock_guard<Lock> locker(receivedLock);
+ received.append(result);
+ }
+ }
+ });
+ consumerThreads.append(threadIdentifier);
+ }
+
+ sleep(delay);
+
+ for (unsigned i = numProducers; i--;) {
+ ThreadIdentifier threadIdentifier = createThread(
+ "Producer Thread",
+ [&] () {
+ for (unsigned i = 0; i < numMessagesPerProducer; ++i) {
+ bool shouldNotify = false;
+ {
+ std::unique_lock<Lock> locker(lock);
+ wait(
+ fullCondition, locker,
+ [&] () {
+ if (verbose)
+ dataLog(toString(currentThread(), ": Checking production predicate with shouldContinue = ", shouldContinue, ", queue.size() == ", queue.size(), "\n"));
+ return queue.size() < maxQueueSize;
+ },
+ timeout);
+ shouldNotify = queue.isEmpty();
+ queue.append(i);
+ }
+ notify(notifyStyle, emptyCondition, shouldNotify);
+ }
+ });
+ producerThreads.append(threadIdentifier);
+ }
+
+ for (ThreadIdentifier threadIdentifier : producerThreads)
+ waitForThreadCompletion(threadIdentifier);
+
+ {
+ std::lock_guard<Lock> locker(lock);
+ shouldContinue = false;
+ }
+ emptyCondition.notifyAll();
+
+ for (ThreadIdentifier threadIdentifier : consumerThreads)
+ waitForThreadCompletion(threadIdentifier);
+
+ EXPECT_EQ(numProducers * numMessagesPerProducer, received.size());
+ std::sort(received.begin(), received.end());
+ for (unsigned messageIndex = 0; messageIndex < numMessagesPerProducer; ++messageIndex) {
+ for (unsigned producerIndex = 0; producerIndex < numProducers; ++producerIndex)
+ EXPECT_EQ(messageIndex, received[messageIndex * numProducers + producerIndex]);
+ }
+}
+
+} // anonymous namespace
+
+TEST(WTF_Condition, OneProducerOneConsumerOneSlot)
+{
+ runTest(1, 1, 1, 100000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, OneProducerOneConsumerOneSlotTimeout)
+{
+ runTest(
+ 1, 1, 1, 100000, TacticallyNotifyAll,
+ Seconds::fromMilliseconds(10),
+ Seconds(1));
+}
+
+TEST(WTF_Condition, OneProducerOneConsumerHundredSlots)
+{
+ runTest(1, 1, 100, 1000000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, TenProducersOneConsumerOneSlot)
+{
+ runTest(10, 1, 1, 10000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, TenProducersOneConsumerHundredSlotsNotifyAll)
+{
+ runTest(10, 1, 100, 10000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, TenProducersOneConsumerHundredSlotsNotifyOne)
+{
+ runTest(10, 1, 100, 10000, AlwaysNotifyOne);
+}
+
+TEST(WTF_Condition, OneProducerTenConsumersOneSlot)
+{
+ runTest(1, 10, 1, 10000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, OneProducerTenConsumersHundredSlotsNotifyAll)
+{
+ runTest(1, 10, 100, 100000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, OneProducerTenConsumersHundredSlotsNotifyOne)
+{
+ runTest(1, 10, 100, 100000, AlwaysNotifyOne);
+}
+
+TEST(WTF_Condition, TenProducersTenConsumersOneSlot)
+{
+ runTest(10, 10, 1, 50000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, TenProducersTenConsumersHundredSlotsNotifyAll)
+{
+ runTest(10, 10, 100, 50000, TacticallyNotifyAll);
+}
+
+TEST(WTF_Condition, TenProducersTenConsumersHundredSlotsNotifyOne)
+{
+ runTest(10, 10, 100, 50000, AlwaysNotifyOne);
+}
+
+TEST(WTF_Condition, TimeoutTimesOut)
+{
+ Lock lock;
+ Condition condition;
+
+ lock.lock();
+ bool result = condition.waitFor(
+ lock, Seconds::fromMilliseconds(10), [] () -> bool { return false; });
+ lock.unlock();
+
+ EXPECT_FALSE(result);
+}
+
+} // namespace TestWebKitAPI
+
diff --git a/Tools/TestWebKitAPI/Tests/WTF/Consume.cpp b/Tools/TestWebKitAPI/Tests/WTF/Consume.cpp
new file mode 100644
index 000000000..e1a5d7a07
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/Consume.cpp
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+#include <thread>
+#include <wtf/Atomics.h>
+
+template <typename T>
+NEVER_INLINE auto testConsume(const T* location)
+{
+ WTF::compilerFence(); // Paranoid testing.
+ auto ret = WTF::consumeLoad(location);
+ WTF::compilerFence(); // Paranoid testing.
+ return ret;
+}
+
+namespace TestWebKitAPI {
+
+TEST(WTF, Consumei8)
+{
+ uint8_t i8 = 42;
+ auto i8_consumed = testConsume(&i8);
+ ASSERT_EQ(i8_consumed.value, 42u);
+ ASSERT_EQ(i8_consumed.dependency, 0u);
+}
+
+TEST(WTF, Consumei16)
+{
+ uint16_t i16 = 42;
+ auto i16_consumed = testConsume(&i16);
+ ASSERT_EQ(i16_consumed.value, 42u);
+ ASSERT_EQ(i16_consumed.dependency, 0u);
+}
+
+TEST(WTF, Consumei32)
+{
+ uint32_t i32 = 42;
+ auto i32_consumed = testConsume(&i32);
+ ASSERT_EQ(i32_consumed.value, 42u);
+ ASSERT_EQ(i32_consumed.dependency, 0u);
+}
+
+TEST(WTF, Consumei64)
+{
+ uint64_t i64 = 42;
+ auto i64_consumed = testConsume(&i64);
+ ASSERT_EQ(i64_consumed.value, 42u);
+ ASSERT_EQ(i64_consumed.dependency, 0u);
+}
+
+TEST(WTF, Consumef32)
+{
+ float f32 = 42.f;
+ auto f32_consumed = testConsume(&f32);
+ ASSERT_EQ(f32_consumed.value, 42.f);
+ ASSERT_EQ(f32_consumed.dependency, 0u);
+}
+
+TEST(WTF, Consumef64)
+{
+ double f64 = 42.;
+ auto f64_consumed = testConsume(&f64);
+ ASSERT_EQ(f64_consumed.value, 42.);
+ ASSERT_EQ(f64_consumed.dependency, 0u);
+}
+
+static int* global;
+
+TEST(WTF, ConsumeGlobalPtr)
+{
+ auto* ptr = &global;
+ auto ptr_consumed = testConsume(&ptr);
+ ASSERT_EQ(ptr_consumed.value, &global);
+ ASSERT_EQ(ptr_consumed.dependency, 0u);
+}
+
+static int* globalArray[128];
+
+TEST(WTF, ConsumeGlobalArrayPtr)
+{
+ auto* ptr = &globalArray[64];
+ auto ptr_consumed = testConsume(&ptr);
+ ASSERT_EQ(ptr_consumed.value, &globalArray[64]);
+ ASSERT_EQ(ptr_consumed.dependency, 0u);
+}
+
+TEST(WTF, ConsumeStackPtr)
+{
+ char* hello = nullptr;
+ auto* stack = &hello;
+ auto stack_consumed = testConsume(&stack);
+ ASSERT_EQ(stack_consumed.value, &hello);
+ ASSERT_EQ(stack_consumed.dependency, 0u);
+}
+
+TEST(WTF, ConsumeWithThread)
+{
+ bool ready = false;
+ constexpr size_t num = 1024;
+ uint32_t* vec = new uint32_t[num];
+ std::thread t([&]() {
+ for (size_t i = 0; i != num; ++i)
+ vec[i] = i * 2;
+ WTF::storeStoreFence();
+ ready = true;
+ });
+ do {
+ auto stack_consumed = testConsume(&ready);
+ if (stack_consumed.value) {
+ for (size_t i = 0; i != num; ++i)
+ ASSERT_EQ(vec[i + stack_consumed.dependency], i * 2);
+ break;
+ }
+ } while (true);
+ t.join();
+ delete[] vec;
+}
+}
diff --git a/Tools/TestWebKitAPI/Tests/WTF/CrossThreadTask.cpp b/Tools/TestWebKitAPI/Tests/WTF/CrossThreadTask.cpp
new file mode 100644
index 000000000..52c0bcd41
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/CrossThreadTask.cpp
@@ -0,0 +1,150 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <wtf/CrossThreadTask.h>
+#include <wtf/HashCountedSet.h>
+#include <wtf/text/StringBuilder.h>
+#include <wtf/text/StringHash.h>
+
+namespace TestWebKitAPI {
+
+static size_t totalDestructorCalls;
+static size_t totalIsolatedCopyCalls;
+
+static HashCountedSet<String> defaultConstructorSet;
+static HashCountedSet<String> nameConstructorSet;
+static HashCountedSet<String> copyConstructorSet;
+static HashCountedSet<String> moveConstructorSet;
+
+struct LifetimeLogger {
+ LifetimeLogger()
+ {
+ defaultConstructorSet.add(fullName());
+ }
+
+ LifetimeLogger(const char* inputName)
+ : name(*inputName)
+ {
+ nameConstructorSet.add(fullName());
+ }
+
+ LifetimeLogger(const LifetimeLogger& other)
+ : name(other.name)
+ , copyGeneration(other.copyGeneration + 1)
+ , moveGeneration(other.moveGeneration)
+ {
+ copyConstructorSet.add(fullName());
+ }
+
+ LifetimeLogger(LifetimeLogger&& other)
+ : name(other.name)
+ , copyGeneration(other.copyGeneration)
+ , moveGeneration(other.moveGeneration + 1)
+ {
+ moveConstructorSet.add(fullName());
+ }
+
+ ~LifetimeLogger()
+ {
+ ++totalDestructorCalls;
+ }
+
+ LifetimeLogger isolatedCopy() const
+ {
+ ++totalIsolatedCopyCalls;
+ return LifetimeLogger(*this);
+ }
+
+ String fullName()
+ {
+ StringBuilder builder;
+ builder.append(&name);
+ builder.append("-");
+ builder.append(String::number(copyGeneration));
+ builder.append("-");
+ builder.append(String::number(moveGeneration));
+
+ return builder.toString();
+ }
+
+ const char& name { *"<default>" };
+ int copyGeneration { 0 };
+ int moveGeneration { 0 };
+};
+
+void testFunction(const LifetimeLogger&, const LifetimeLogger&, const LifetimeLogger&)
+{
+ // Do nothing - Just need to check the side effects of the arguments getting in here.
+}
+
+TEST(WTF_CrossThreadTask, Basic)
+{
+ {
+ LifetimeLogger logger1;
+ LifetimeLogger logger2(logger1);
+ LifetimeLogger logger3("logger");
+
+ auto task = createCrossThreadTask(testFunction, logger1, logger2, logger3);
+ task.performTask();
+ }
+
+ ASSERT_EQ(1u, defaultConstructorSet.size());
+ ASSERT_EQ(1u, defaultConstructorSet.count("<default>-0-0"));
+
+ ASSERT_EQ(1u, nameConstructorSet.size());
+ ASSERT_EQ(1u, nameConstructorSet.count("logger-0-0"));
+
+ ASSERT_EQ(3u, copyConstructorSet.size());
+ ASSERT_EQ(1u, copyConstructorSet.count("logger-1-0"));
+ ASSERT_EQ(2u, copyConstructorSet.count("<default>-1-0"));
+ ASSERT_EQ(1u, copyConstructorSet.count("<default>-2-0"));
+
+#if !COMPILER(MSVC)
+ ASSERT_EQ(6u, moveConstructorSet.size());
+#else
+ // The number of times the move constructor is called is different on Windows in this test.
+ // This seems to be caused by differences in MSVC's implementation of lambdas or std functions like std::make_tuple.
+ ASSERT_EQ(9u, moveConstructorSet.size());
+#endif
+ ASSERT_EQ(1u, moveConstructorSet.count("logger-1-1"));
+ ASSERT_EQ(1u, moveConstructorSet.count("logger-1-2"));
+ ASSERT_EQ(1u, moveConstructorSet.count("<default>-2-1"));
+ ASSERT_EQ(1u, moveConstructorSet.count("<default>-2-2"));
+ ASSERT_EQ(1u, moveConstructorSet.count("<default>-1-1"));
+ ASSERT_EQ(1u, moveConstructorSet.count("<default>-1-2"));
+
+#if !COMPILER(MSVC)
+ ASSERT_EQ(12u, totalDestructorCalls);
+#else
+ // Since the move constructor is called 3 more times on Windows (see above), we will have 3 more destructor calls.
+ ASSERT_EQ(15u, totalDestructorCalls);
+#endif
+ ASSERT_EQ(3u, totalIsolatedCopyCalls);
+
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/DateMath.cpp b/Tools/TestWebKitAPI/Tests/WTF/DateMath.cpp
new file mode 100644
index 000000000..463041d48
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/DateMath.cpp
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include "Test.h"
+#include <wtf/DateMath.h>
+
+namespace TestWebKitAPI {
+
+// Note: The results of these function look weird if you do not understand the following mappings:
+// dayOfWeek: [0, 6] 0 being Monday, day: [1, 31], month: [0, 11], year: ex: 2011,
+// hours: [0, 23], minutes: [0, 59], seconds: [0, 59], utcOffset: [-720,720].
+
+TEST(WTF_DateMath, dateToDaysFrom1970)
+{
+ EXPECT_EQ(0.0, dateToDaysFrom1970(1970, 0, 1));
+ EXPECT_EQ(157.0, dateToDaysFrom1970(1970, 5, 7));
+ EXPECT_EQ(-145.0, dateToDaysFrom1970(1969, 7, 9));
+ EXPECT_EQ(16322, dateToDaysFrom1970(2014, 8, 9));
+}
+
+
+TEST(WTF_DateMath, isLeapYear)
+{
+ EXPECT_TRUE(isLeapYear(1804));
+ EXPECT_FALSE(isLeapYear(1900));
+ EXPECT_TRUE(isLeapYear(1968));
+ EXPECT_TRUE(isLeapYear(1976));
+ EXPECT_TRUE(isLeapYear(2000));
+ EXPECT_FALSE(isLeapYear(2010));
+ EXPECT_TRUE(isLeapYear(2012));
+ EXPECT_FALSE(isLeapYear(2100));
+}
+
+TEST(WTF_DateMath, msToYear)
+{
+ EXPECT_EQ(1962, msToYear(-220953600000));
+ EXPECT_EQ(1970, msToYear(0));
+ EXPECT_EQ(1970, msToYear(100));
+ EXPECT_EQ(1977, msToYear(220953600000));
+ EXPECT_EQ(2013, msToYear(1365318000000));
+}
+
+TEST(WTF_DateMath, msToDays)
+{
+ EXPECT_EQ(0, msToDays(0));
+ EXPECT_EQ(2557, msToDays(220953600000));
+ EXPECT_EQ(255, msToDays(22095360000));
+ EXPECT_EQ(25, msToDays(2209536000));
+ EXPECT_EQ(2, msToDays(220953600));
+ EXPECT_EQ(0, msToDays(22095360));
+ EXPECT_EQ(0, msToDays(2209536));
+}
+
+TEST(WTF_DateMath, msToMinutes)
+{
+ EXPECT_EQ(0, msToMinutes(0));
+ EXPECT_EQ(0, msToMinutes(220953600000));
+ EXPECT_EQ(36, msToMinutes(22095360000));
+ EXPECT_EQ(36, msToMinutes(22095360000));
+ EXPECT_EQ(45, msToMinutes(2209536000));
+ EXPECT_EQ(22, msToMinutes(220953600));
+ EXPECT_EQ(8, msToMinutes(22095360));
+ EXPECT_EQ(36, msToMinutes(2209536));
+}
+
+TEST(WTF_DateMath, msToHours)
+{
+ EXPECT_EQ(0, msToHours(0));
+ EXPECT_EQ(8, msToHours(220953600000));
+ EXPECT_EQ(17, msToHours(22095360000));
+ EXPECT_EQ(13, msToHours(2209536000));
+ EXPECT_EQ(13, msToHours(220953600));
+ EXPECT_EQ(6, msToHours(22095360));
+ EXPECT_EQ(0, msToHours(2209536));
+}
+
+TEST(WTF_DateMath, dayInYear)
+{
+ EXPECT_EQ(59, dayInYear(2015, 2, 1));
+ EXPECT_EQ(60, dayInYear(2012, 2, 1));
+ EXPECT_EQ(0, dayInYear(2015, 0, 1));
+ EXPECT_EQ(31, dayInYear(2015, 1, 1));
+}
+
+TEST(WTF_DateMath, monthFromDayInYear)
+{
+ EXPECT_EQ(2, monthFromDayInYear(59, false));
+ EXPECT_EQ(1, monthFromDayInYear(59, true));
+ EXPECT_EQ(2, monthFromDayInYear(60, true));
+ EXPECT_EQ(0, monthFromDayInYear(0, false));
+ EXPECT_EQ(0, monthFromDayInYear(0, true));
+ EXPECT_EQ(1, monthFromDayInYear(31, true));
+ EXPECT_EQ(1, monthFromDayInYear(31, false));
+}
+
+TEST(WTF_DateMath, dayInMonthFromDayInYear)
+{
+ EXPECT_EQ(1, dayInMonthFromDayInYear(0, false));
+ EXPECT_EQ(1, dayInMonthFromDayInYear(0, true));
+ EXPECT_EQ(1, dayInMonthFromDayInYear(59, false));
+ EXPECT_EQ(29, dayInMonthFromDayInYear(59, true));
+ EXPECT_EQ(1, dayInMonthFromDayInYear(60, true));
+ EXPECT_EQ(1, dayInMonthFromDayInYear(0, false));
+ EXPECT_EQ(1, dayInMonthFromDayInYear(0, true));
+ EXPECT_EQ(31, dayInMonthFromDayInYear(30, true));
+ EXPECT_EQ(31, dayInMonthFromDayInYear(30, false));
+ EXPECT_EQ(31, dayInMonthFromDayInYear(365, true));
+ EXPECT_EQ(32, dayInMonthFromDayInYear(365, false));
+ EXPECT_EQ(32, dayInMonthFromDayInYear(366, true));
+}
+
+TEST(WTF_DateMath, calculateLocalTimeOffset)
+{
+ // DST Start: April 30, 1967 (02:00 am)
+ LocalTimeOffset dstStart1967 = calculateLocalTimeOffset(-84301200000, WTF::LocalTime);
+ EXPECT_TRUE(dstStart1967.isDST);
+ EXPECT_EQ(-25200000, dstStart1967.offset);
+
+ // November 1, 1967 (02:00 am)
+ LocalTimeOffset dstAlmostEnd1967 = calculateLocalTimeOffset(-68317200000, WTF::LocalTime);
+ EXPECT_TRUE(dstAlmostEnd1967.isDST);
+ EXPECT_EQ(-25200000, dstAlmostEnd1967.offset);
+
+ // DST End: November 11, 1967 (02:00 am)
+ LocalTimeOffset dstEnd1967 = calculateLocalTimeOffset(-67536000000, WTF::LocalTime);
+ EXPECT_FALSE(dstEnd1967.isDST);
+ EXPECT_EQ(-25200000, dstStart1967.offset);
+
+ // DST Start: April 3, 1988 (02:00 am)
+ LocalTimeOffset dstStart1988 = calculateLocalTimeOffset(576054000000, WTF::LocalTime);
+ EXPECT_TRUE(dstStart1988.isDST);
+ EXPECT_EQ(-25200000, dstStart1988.offset);
+
+ // DST End: November 4, 2012 (02:00 am)
+ LocalTimeOffset dstEnd2012 = calculateLocalTimeOffset(1352012400000, WTF::LocalTime);
+ EXPECT_FALSE(dstEnd2012.isDST);
+ EXPECT_EQ(-28800000, dstEnd2012.offset);
+
+ // DST Begin: March 8, 2015
+ LocalTimeOffset dstBegin2015 = calculateLocalTimeOffset(1425801600000, WTF::LocalTime);
+ EXPECT_TRUE(dstBegin2015.isDST);
+ EXPECT_EQ(-25200000, dstBegin2015.offset);
+
+ LocalTimeOffset dstBegin2015UTC = calculateLocalTimeOffset(1425801600000, WTF::UTCTime);
+ EXPECT_FALSE(dstBegin2015UTC.isDST);
+ EXPECT_EQ(-28800000, dstBegin2015UTC.offset);
+
+ // DST End: November 1, 2015
+ LocalTimeOffset dstEnd2015 = calculateLocalTimeOffset(1446361200000, WTF::LocalTime);
+ EXPECT_FALSE(dstEnd2015.isDST);
+ EXPECT_EQ(-28800000, dstEnd2015.offset);
+
+ // DST Begin: March 13, 2016
+ LocalTimeOffset dstBegin2016 = calculateLocalTimeOffset(1458111600000, WTF::LocalTime);
+ EXPECT_TRUE(dstBegin2016.isDST);
+ EXPECT_EQ(-25200000, dstBegin2016.offset);
+
+ // DST End: November 6, 2016
+ LocalTimeOffset dstEnd2016 = calculateLocalTimeOffset(1478415600000, WTF::LocalTime);
+ EXPECT_FALSE(dstEnd2016.isDST);
+ EXPECT_EQ(-28800000, dstEnd2016.offset);
+
+ // DST Begin: March 12, 2017
+ LocalTimeOffset dstBegin2017 = calculateLocalTimeOffset(1489305600000, WTF::LocalTime);
+ EXPECT_TRUE(dstBegin2017.isDST);
+ EXPECT_EQ(-25200000, dstBegin2017.offset);
+
+ // DST End: November 5, 2017
+ LocalTimeOffset dstEnd2017 = calculateLocalTimeOffset(1509865200000, WTF::LocalTime);
+ EXPECT_FALSE(dstEnd2017.isDST);
+ EXPECT_EQ(-28800000, dstEnd2017.offset);
+
+ // DST Begin: March 11, 2018
+ LocalTimeOffset dstBegin2018 = calculateLocalTimeOffset(1520755200000, WTF::LocalTime);
+ EXPECT_TRUE(dstBegin2018.isDST);
+ EXPECT_EQ(-25200000, dstBegin2018.offset);
+
+ // DST End: November 4, 2018
+ LocalTimeOffset dstEnd2018 = calculateLocalTimeOffset(1541314800000, WTF::LocalTime);
+ EXPECT_FALSE(dstEnd2018.isDST);
+ EXPECT_EQ(-28800000, dstEnd2018.offset);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/DeletedAddressOfOperator.h b/Tools/TestWebKitAPI/Tests/WTF/DeletedAddressOfOperator.h
new file mode 100644
index 000000000..31d5d80b9
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/DeletedAddressOfOperator.h
@@ -0,0 +1,84 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#pragma once
+
+#include <wtf/HashFunctions.h>
+#include <wtf/HashTraits.h>
+
+class DeletedAddressOfOperator {
+public:
+ DeletedAddressOfOperator()
+ : m_value(0)
+ {
+ }
+
+ DeletedAddressOfOperator(unsigned value)
+ : m_value(value)
+ {
+ }
+
+ DeletedAddressOfOperator* operator&() = delete;
+
+ unsigned value() const
+ {
+ return m_value;
+ }
+
+ friend bool operator==(const DeletedAddressOfOperator& a, const DeletedAddressOfOperator& b)
+ {
+ return a.m_value == b.m_value;
+ }
+
+private:
+ unsigned m_value;
+};
+
+namespace WTF {
+
+template<> struct HashTraits<DeletedAddressOfOperator> : public GenericHashTraits<DeletedAddressOfOperator> {
+ static const bool emptyValueIsZero = true;
+
+ static void constructDeletedValue(DeletedAddressOfOperator& slot) { slot = DeletedAddressOfOperator(std::numeric_limits<unsigned>::max()); }
+ static bool isDeletedValue(const DeletedAddressOfOperator& slot) { return slot.value() == std::numeric_limits<unsigned>::max(); }
+};
+
+template<> struct DefaultHash<DeletedAddressOfOperator> {
+ struct Hash {
+ static unsigned hash(const DeletedAddressOfOperator& key)
+ {
+ return intHash(key.value());
+ }
+
+ static bool equal(const DeletedAddressOfOperator& a, const DeletedAddressOfOperator& b)
+ {
+ return a == b;
+ }
+
+ static const bool safeToCompareToEmptyOrDeleted = true;
+ };
+};
+}
+
diff --git a/Tools/TestWebKitAPI/Tests/WTF/Deque.cpp b/Tools/TestWebKitAPI/Tests/WTF/Deque.cpp
new file mode 100644
index 000000000..83f1f82ee
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/Deque.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2011 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include "MoveOnly.h"
+#include <wtf/Deque.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF_Deque, Iterator)
+{
+ Deque<int> deque;
+ deque.append(11);
+ deque.prepend(10);
+ deque.append(12);
+ deque.append(13);
+
+ Deque<int>::iterator it = deque.begin();
+ Deque<int>::iterator end = deque.end();
+ EXPECT_TRUE(end != it);
+
+ EXPECT_EQ(10, *it);
+ ++it;
+ EXPECT_EQ(11, *it);
+ ++it;
+ EXPECT_EQ(12, *it);
+ ++it;
+ EXPECT_EQ(13, *it);
+ ++it;
+
+ EXPECT_TRUE(end == it);
+}
+
+TEST(WTF_Deque, InitializerList)
+{
+ Deque<int> deque = { 1, 2, 3, 4 };
+
+ EXPECT_EQ(4u, deque.size());
+
+ auto it = deque.begin();
+ auto end = deque.end();
+ EXPECT_TRUE(end != it);
+
+ EXPECT_EQ(1, *it);
+ ++it;
+ EXPECT_EQ(2, *it);
+ ++it;
+ EXPECT_EQ(3, *it);
+ ++it;
+ EXPECT_EQ(4, *it);
+ ++it;
+
+ EXPECT_TRUE(end == it);
+}
+
+TEST(WTF, DequeReverseIterator)
+{
+ Deque<int> deque;
+ deque.append(11);
+ deque.prepend(10);
+ deque.append(12);
+ deque.append(13);
+
+ Deque<int>::reverse_iterator it = deque.rbegin();
+ Deque<int>::reverse_iterator end = deque.rend();
+ EXPECT_TRUE(end != it);
+
+ EXPECT_EQ(13, *it);
+ ++it;
+ EXPECT_EQ(12, *it);
+ ++it;
+ EXPECT_EQ(11, *it);
+ ++it;
+ EXPECT_EQ(10, *it);
+ ++it;
+
+ EXPECT_TRUE(end == it);
+}
+
+TEST(WTF_Deque, Remove)
+{
+ Deque<int> deque;
+ deque.append(11);
+ deque.prepend(10);
+ deque.append(12);
+ deque.append(13);
+
+ EXPECT_EQ(10, deque.first());
+ EXPECT_EQ(13, deque.last());
+
+ deque.removeLast();
+ EXPECT_EQ(10, deque.first());
+ EXPECT_EQ(12, deque.last());
+
+ deque.removeFirst();
+ EXPECT_EQ(11, deque.first());
+ EXPECT_EQ(12, deque.last());
+
+ deque.removeFirst();
+ EXPECT_EQ(12, deque.first());
+ EXPECT_EQ(12, deque.last());
+
+ deque.removeLast();
+ EXPECT_TRUE(deque.isEmpty());
+}
+
+TEST(WTF_Deque, MoveOnly)
+{
+ Deque<MoveOnly> deque;
+
+ deque.append(MoveOnly(1));
+ deque.prepend(MoveOnly(0));
+
+ EXPECT_EQ(0U, deque.first().value());
+ EXPECT_EQ(1U, deque.last().value());
+
+ auto first = deque.takeFirst();
+ EXPECT_EQ(0U, first.value());
+
+ auto last = deque.takeLast();
+ EXPECT_EQ(1U, last.value());
+}
+
+TEST(WTF_Deque, MoveConstructor)
+{
+ Deque<MoveOnly, 4> deque;
+
+ for (unsigned i = 0; i < 10; ++i)
+ deque.append(MoveOnly(i));
+
+ EXPECT_EQ(10u, deque.size());
+
+ Deque<MoveOnly, 4> deque2 = WTFMove(deque);
+
+ EXPECT_EQ(10u, deque2.size());
+
+ unsigned i = 0;
+ for (auto& element : deque2) {
+ EXPECT_EQ(i, element.value());
+ ++i;
+ }
+}
+
+TEST(WTF_Deque, MoveAssignmentOperator)
+{
+ Deque<MoveOnly, 4> deque1;
+
+ for (unsigned i = 0; i < 10; ++i)
+ deque1.append(MoveOnly(i));
+
+ EXPECT_EQ(10u, deque1.size());
+
+ Deque<MoveOnly, 4> deque2;
+ for (unsigned i = 0; i < 10; ++i)
+ deque2.append(MoveOnly(i * 2));
+
+ deque1 = WTFMove(deque2);
+
+ EXPECT_EQ(10u, deque2.size());
+
+ unsigned i = 0;
+ for (auto& element : deque1) {
+ EXPECT_EQ(i * 2, element.value());
+ ++i;
+ }
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/EnumTraits.cpp b/Tools/TestWebKitAPI/Tests/WTF/EnumTraits.cpp
new file mode 100644
index 000000000..0246fde29
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/EnumTraits.cpp
@@ -0,0 +1,55 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <wtf/EnumTraits.h>
+
+enum class TestEnum {
+ A,
+ B,
+ C,
+};
+
+namespace WTF {
+template<> struct EnumTraits<TestEnum> {
+ using values = EnumValues<TestEnum, TestEnum::A, TestEnum::B, TestEnum::C>;
+};
+}
+
+namespace TestWebKitAPI {
+
+static_assert(WTF::isValidEnum<TestEnum>(0), "");
+static_assert(!WTF::isValidEnum<TestEnum>(-1), "");
+static_assert(!WTF::isValidEnum<TestEnum>(3), "");
+
+TEST(WTF_EnumTraits, IsValidEnum)
+{
+ EXPECT_TRUE(isValidEnum<TestEnum>(0));
+ EXPECT_FALSE(isValidEnum<TestEnum>(-1));
+ EXPECT_FALSE(isValidEnum<TestEnum>(3));
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WTF/Expected.cpp b/Tools/TestWebKitAPI/Tests/WTF/Expected.cpp
new file mode 100644
index 000000000..73654c5dd
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/Expected.cpp
@@ -0,0 +1,512 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include "RefLogger.h"
+
+#include <string>
+#include <unordered_map>
+
+#include <wtf/Expected.h>
+#include <wtf/Ref.h>
+
+namespace WTF {
+
+template <class E> std::ostream& operator<<(std::ostream& os, const UnexpectedType<E>& u)
+{
+ return os << u.value();
+}
+
+template <class T, class E> std::ostream& operator<<(std::ostream& os, const Expected<T, E>& e)
+{
+ if (e.hasValue())
+ return os << e.value();
+ return os << e.error();
+}
+
+template <class E> std::ostream& operator<<(std::ostream& os, const Expected<void, E>& e)
+{
+ if (e.hasValue())
+ return os << "";
+ return os << e.error();
+}
+
+}
+
+namespace TestWebKitAPI {
+
+constexpr const char* oops = "oops";
+constexpr const char* foof = "foof";
+
+TEST(WTF_Expected, UnexpectedType)
+{
+ {
+ auto u = UnexpectedType<int>(42);
+ EXPECT_EQ(u.value(), 42);
+ constexpr auto c = makeUnexpected(42);
+ EXPECT_EQ(c.value(), 42);
+ EXPECT_EQ(u, c);
+ EXPECT_FALSE(u != c);
+ EXPECT_FALSE(u < c);
+ EXPECT_FALSE(u > c);
+ EXPECT_LE(u, c);
+ EXPECT_GE(u, c);
+ }
+ {
+ auto c = makeUnexpected(oops);
+ EXPECT_EQ(c.value(), oops);
+ }
+ {
+ auto s = makeUnexpected(std::string(oops));
+ EXPECT_EQ(s.value(), oops);
+ }
+ {
+ constexpr auto s0 = makeUnexpected(oops);
+ constexpr auto s1(s0);
+ EXPECT_EQ(s0, s1);
+ }
+}
+
+struct foo {
+ int v;
+ foo(int v)
+ : v(v)
+ { }
+ ~foo() { }
+ bool operator==(const foo& y) const { return v == y.v; }
+ friend std::ostream& operator<<(std::ostream&, const foo&);
+};
+std::ostream& operator<<(std::ostream& os, const foo& f) { return os << f.v; }
+
+TEST(WTF_Expected, expected)
+{
+ typedef Expected<int, const char*> E;
+ typedef Expected<int, const void*> EV;
+ typedef Expected<foo, const char*> FooChar;
+ typedef Expected<foo, std::string> FooString;
+ {
+ auto e = E();
+ EXPECT_TRUE(e.hasValue());
+ EXPECT_EQ(e.value(), 0);
+ EXPECT_EQ(e.valueOr(3.14), 0);
+ }
+ {
+ constexpr E e;
+ EXPECT_TRUE(e.hasValue());
+ EXPECT_EQ(e.value(), 0);
+ EXPECT_EQ(e.valueOr(3.14), 0);
+ }
+ {
+ auto e = E(42);
+ EXPECT_TRUE(e.hasValue());
+ EXPECT_EQ(e.value(), 42);
+ EXPECT_EQ(e.valueOr(3.14), 42);
+ const auto e2(e);
+ EXPECT_TRUE(e2.hasValue());
+ EXPECT_EQ(e2.value(), 42);
+ EXPECT_EQ(e2.valueOr(3.14), 42);
+ E e3;
+ e3 = e2;
+ EXPECT_TRUE(e3.hasValue());
+ EXPECT_EQ(e3.value(), 42);
+ EXPECT_EQ(e3.valueOr(3.14), 42);
+ const E e4 = e2;
+ EXPECT_TRUE(e4.hasValue());
+ EXPECT_EQ(e4.value(), 42);
+ EXPECT_EQ(e4.valueOr(3.14), 42);
+ }
+ {
+ constexpr E c(42);
+ EXPECT_TRUE(c.hasValue());
+ EXPECT_EQ(c.value(), 42);
+ EXPECT_EQ(c.valueOr(3.14), 42);
+ constexpr const auto c2(c);
+ EXPECT_TRUE(c2.hasValue());
+ EXPECT_EQ(c2.value(), 42);
+ EXPECT_EQ(c2.valueOr(3.14), 42);
+ }
+ {
+ auto u = E(makeUnexpected(oops));
+ EXPECT_FALSE(u.hasValue());
+ EXPECT_EQ(u.error(), oops);
+ EXPECT_EQ(u.getUnexpected().value(), oops);
+ EXPECT_EQ(u.valueOr(3.14), 3);
+ }
+ {
+ auto uv = EV(makeUnexpected(oops));
+ EXPECT_FALSE(uv.hasValue());
+ EXPECT_EQ(uv.error(), oops);
+ EXPECT_EQ(uv.getUnexpected().value(), oops);
+ EXPECT_EQ(uv.valueOr(3.14), 3);
+ }
+ {
+ E e = makeUnexpected(oops);
+ EXPECT_FALSE(e.hasValue());
+ EXPECT_EQ(e.error(), oops);
+ EXPECT_EQ(e.getUnexpected().value(), oops);
+ EXPECT_EQ(e.valueOr(3.14), 3);
+ }
+ {
+ auto e = makeExpectedFromError<int, const char*>(oops);
+ EXPECT_FALSE(e.hasValue());
+ EXPECT_EQ(e.error(), oops);
+ EXPECT_EQ(e.getUnexpected().value(), oops);
+ EXPECT_EQ(e.valueOr(3.14), 3);
+ }
+ {
+ auto e = makeExpectedFromError<int, const void*>(oops);
+ EXPECT_FALSE(e.hasValue());
+ EXPECT_EQ(e.error(), oops);
+ EXPECT_EQ(e.getUnexpected().value(), oops);
+ EXPECT_EQ(e.valueOr(3.14), 3);
+ }
+ {
+ auto e = FooChar(42);
+ EXPECT_EQ(e->v, 42);
+ EXPECT_EQ((*e).v, 42);
+ }
+ {
+ auto e0 = E(42);
+ auto e1 = E(1024);
+ swap(e0, e1);
+ EXPECT_EQ(e0.value(), 1024);
+ EXPECT_EQ(e1.value(), 42);
+ }
+ {
+ auto e0 = E(makeUnexpected(oops));
+ auto e1 = E(makeUnexpected(foof));
+ swap(e0, e1);
+ EXPECT_EQ(e0.error(), foof);
+ EXPECT_EQ(e1.error(), oops);
+ }
+ {
+ FooChar c(foo(42));
+ EXPECT_EQ(c->v, 42);
+ EXPECT_EQ((*c).v, 42);
+ }
+ {
+ FooString s(foo(42));
+ EXPECT_EQ(s->v, 42);
+ EXPECT_EQ((*s).v, 42);
+ const char* message = "very long failure string, for very bad failure cases";
+ FooString e0(makeUnexpected<std::string>(message));
+ FooString e1(makeUnexpected<std::string>(message));
+ FooString e2(makeUnexpected<std::string>(std::string()));
+ EXPECT_EQ(e0.error(), std::string(message));
+ EXPECT_EQ(e0, e1);
+ EXPECT_NE(e0, e2);
+ FooString* e4 = new FooString(makeUnexpected<std::string>(message));
+ FooString* e5 = new FooString(*e4);
+ EXPECT_EQ(e0, *e4);
+ delete e4;
+ EXPECT_EQ(e0, *e5);
+ delete e5;
+ }
+}
+
+TEST(WTF_Expected, Expected_void)
+{
+ typedef Expected<void, const char*> E;
+ typedef Expected<void, const void*> EV;
+ typedef Expected<void, std::string> String;
+ {
+ auto e = E();
+ EXPECT_TRUE(e.hasValue());
+ const auto e2(e);
+ EXPECT_TRUE(e2.hasValue());
+ EXPECT_EQ(e, e2);
+ E e3;
+ e3 = e2;
+ EXPECT_TRUE(e3.hasValue());
+ EXPECT_EQ(e, e3);
+ }
+ {
+ constexpr E c;
+ EXPECT_TRUE(c.hasValue());
+ constexpr const auto c2(c);
+ EXPECT_TRUE(c2.hasValue());
+ EXPECT_EQ(c, c2);
+ }
+ {
+ auto u = E(makeUnexpected(oops));
+ EXPECT_FALSE(u.hasValue());
+ EXPECT_EQ(u.error(), oops);
+ EXPECT_EQ(u.getUnexpected().value(), oops);
+ }
+ {
+ auto uv = EV(makeUnexpected(oops));
+ EXPECT_FALSE(uv.hasValue());
+ EXPECT_EQ(uv.error(), oops);
+ EXPECT_EQ(uv.getUnexpected().value(), oops);
+ }
+ {
+ E e = makeUnexpected(oops);
+ EXPECT_FALSE(e.hasValue());
+ EXPECT_EQ(e.error(), oops);
+ EXPECT_EQ(e.getUnexpected().value(), oops);
+ }
+ {
+ auto e = makeExpectedFromError<void, const char*>(oops);
+ EXPECT_FALSE(e.hasValue());
+ EXPECT_EQ(e.error(), oops);
+ EXPECT_EQ(e.getUnexpected().value(), oops);
+ }
+ {
+ auto e = makeExpectedFromError<void, const void*>(oops);
+ EXPECT_FALSE(e.hasValue());
+ EXPECT_EQ(e.error(), oops);
+ EXPECT_EQ(e.getUnexpected().value(), oops);
+ }
+ {
+ auto e0 = E();
+ auto e1 = E();
+ swap(e0, e1);
+ EXPECT_EQ(e0, e1);
+ }
+ {
+ auto e0 = E(makeUnexpected(oops));
+ auto e1 = E(makeUnexpected(foof));
+ swap(e0, e1);
+ EXPECT_EQ(e0.error(), foof);
+ EXPECT_EQ(e1.error(), oops);
+ }
+ {
+ const char* message = "very long failure string, for very bad failure cases";
+ String e0(makeUnexpected<std::string>(message));
+ String e1(makeUnexpected<std::string>(message));
+ String e2(makeUnexpected<std::string>(std::string()));
+ EXPECT_EQ(e0.error(), std::string(message));
+ EXPECT_EQ(e0, e1);
+ EXPECT_NE(e0, e2);
+ String* e4 = new String(makeUnexpected<std::string>(message));
+ String* e5 = new String(*e4);
+ EXPECT_EQ(e0, *e4);
+ delete e4;
+ EXPECT_EQ(e0, *e5);
+ delete e5;
+ }
+}
+
+TEST(WTF_Expected, comparison)
+{
+ typedef Expected<int, const char*> Ex;
+ typedef Expected<int, int> Er;
+
+ // Two Expected, no errors.
+ EXPECT_EQ(Ex(42), Ex(42));
+ EXPECT_NE(Ex(42), Ex(1024));
+ EXPECT_LT(Ex(42), Ex(1024));
+ EXPECT_GT(Ex(1024), Ex(42));
+ EXPECT_LE(Ex(42), Ex(42));
+ EXPECT_GE(Ex(42), Ex(42));
+ EXPECT_LE(Ex(42), Ex(1024));
+ EXPECT_GE(Ex(1024), Ex(42));
+
+ EXPECT_FALSE(Ex(42) == Ex(1024));
+ EXPECT_FALSE(Ex(42) != Ex(42));
+ EXPECT_FALSE(Ex(1024) < Ex(42));
+ EXPECT_FALSE(Ex(42) > Ex(1024));
+ EXPECT_FALSE(Ex(1024) < Ex(42));
+ EXPECT_FALSE(Ex(42) >= Ex(1024));
+
+ // Two Expected, half errors.
+ EXPECT_FALSE(Ex(42) == Ex(makeUnexpected(oops)));
+ EXPECT_NE(Ex(42), Ex(makeUnexpected(oops)));
+ EXPECT_LT(Ex(42), Ex(makeUnexpected(oops)));
+ EXPECT_FALSE(Ex(42) > Ex(makeUnexpected(oops)));
+ EXPECT_LE(Ex(42), Ex(makeUnexpected(oops)));
+ EXPECT_FALSE(Ex(42) >= Ex(makeUnexpected(oops)));
+
+ EXPECT_FALSE(Ex(makeUnexpected(oops)) == Ex(42));
+ EXPECT_NE(Ex(makeUnexpected(oops)), Ex(42));
+ EXPECT_FALSE(Ex(makeUnexpected(oops)) < Ex(42));
+ EXPECT_GT(Ex(makeUnexpected(oops)), Ex(42));
+ EXPECT_FALSE(Ex(makeUnexpected(oops)) <= Ex(42));
+ EXPECT_GE(Ex(makeUnexpected(oops)), Ex(42));
+
+ // Two Expected, all errors.
+ EXPECT_EQ(Er(42), Er(42));
+ EXPECT_NE(Er(42), Er(1024));
+ EXPECT_LT(Er(42), Er(1024));
+ EXPECT_GT(Er(1024), Er(42));
+ EXPECT_LE(Er(42), Er(42));
+ EXPECT_GE(Er(42), Er(42));
+ EXPECT_LE(Er(42), Er(1024));
+ EXPECT_GE(Er(1024), Er(42));
+
+ EXPECT_FALSE(Er(42) == Er(1024));
+ EXPECT_FALSE(Er(42) != Er(42));
+ EXPECT_FALSE(Er(1024) < Er(42));
+ EXPECT_FALSE(Er(42) > Er(1024));
+ EXPECT_FALSE(Er(1024) <= Er(42));
+ EXPECT_FALSE(Er(42) >= Er(1024));
+
+ // One Expected, one value.
+ EXPECT_EQ(Ex(42), 42);
+ EXPECT_NE(Ex(42), 0);
+ EXPECT_LT(Ex(42), 1024);
+ EXPECT_GT(Ex(1024), 42);
+ EXPECT_LE(Ex(42), 42);
+ EXPECT_GE(Ex(42), 42);
+ EXPECT_LE(Ex(42), 1024);
+ EXPECT_GE(Ex(1024), 42);
+
+ EXPECT_FALSE(Ex(42) == 0);
+ EXPECT_FALSE(Ex(42) != 42);
+ EXPECT_FALSE(Ex(1024) < 42);
+ EXPECT_FALSE(Ex(42) > 1024);
+ EXPECT_FALSE(Ex(1024) < 42);
+ EXPECT_FALSE(Ex(42) >= 1024);
+
+ EXPECT_EQ(42, Ex(42));
+ EXPECT_NE(42, Ex(1024));
+ EXPECT_LT(42, Ex(1024));
+ EXPECT_GT(1024, Ex(42));
+ EXPECT_LE(42, Ex(42));
+ EXPECT_GE(42, Ex(42));
+ EXPECT_LE(42, Ex(1024));
+ EXPECT_GE(1024, Ex(42));
+
+ EXPECT_FALSE(42 == Ex(1024));
+ EXPECT_FALSE(42 != Ex(42));
+ EXPECT_FALSE(1024 < Ex(42));
+ EXPECT_FALSE(42 > Ex(1024));
+ EXPECT_FALSE(1024 <= Ex(42));
+ EXPECT_FALSE(42 >= Ex(1024));
+
+ // One Expected, one unexpected.
+ EXPECT_FALSE(Ex(42) == makeUnexpected(oops));
+ EXPECT_NE(Ex(42), makeUnexpected(oops));
+ EXPECT_LT(Ex(42), makeUnexpected(oops));
+ EXPECT_FALSE(Ex(42) > makeUnexpected(oops));
+ EXPECT_LE(Ex(42), makeUnexpected(oops));
+ EXPECT_FALSE(Ex(42) >= makeUnexpected(oops));
+
+ EXPECT_FALSE(makeUnexpected(oops) == Ex(42));
+ EXPECT_NE(makeUnexpected(oops), Ex(42));
+ EXPECT_FALSE(makeUnexpected(oops) < Ex(42));
+ EXPECT_GT(makeUnexpected(oops), Ex(42));
+ EXPECT_FALSE(makeUnexpected(oops) <= Ex(42));
+ EXPECT_GE(makeUnexpected(oops), Ex(42));
+}
+
+struct NonTrivialDtor {
+ ~NonTrivialDtor() { ++count; }
+ static int count;
+};
+int NonTrivialDtor::count = 0;
+
+TEST(WTF_Expected, destructors)
+{
+ typedef Expected<NonTrivialDtor, const char*> NT;
+ typedef Expected<const char*, NonTrivialDtor> TN;
+ typedef Expected<NonTrivialDtor, NonTrivialDtor> NN;
+ typedef Expected<void, NonTrivialDtor> VN;
+ EXPECT_EQ(NonTrivialDtor::count, 0);
+ { NT nt; }
+ EXPECT_EQ(NonTrivialDtor::count, 1);
+ { NT nt = makeUnexpected(oops); }
+ EXPECT_EQ(NonTrivialDtor::count, 1);
+ { TN tn; }
+ EXPECT_EQ(NonTrivialDtor::count, 1);
+ { TN tn = makeUnexpected(NonTrivialDtor()); }
+ EXPECT_EQ(NonTrivialDtor::count, 4);
+ { NN nn; }
+ EXPECT_EQ(NonTrivialDtor::count, 5);
+ { NN nn = makeUnexpected(NonTrivialDtor()); }
+ EXPECT_EQ(NonTrivialDtor::count, 8);
+ { VN vn; }
+ EXPECT_EQ(NonTrivialDtor::count, 8);
+ { VN vn = makeUnexpected(NonTrivialDtor()); }
+ EXPECT_EQ(NonTrivialDtor::count, 11);
+}
+
+TEST(WTF_Expected, hash)
+{
+ typedef Expected<int, const char*> E;
+ std::unordered_map<E, int> m;
+ m.insert({ E(42), 42 });
+ m.insert({ E(makeUnexpected(oops)), 5 });
+ m.insert({ E(1024), 1024 });
+ m.insert({ E(makeUnexpected(foof)), 0xf00f });
+ EXPECT_EQ(m[E(42)], 42);
+ EXPECT_EQ(m[E(1024)], 1024);
+ EXPECT_EQ(m[E(makeUnexpected(oops))], 5);
+ EXPECT_EQ(m[E(makeUnexpected(foof))], 0xf00f);
+}
+
+TEST(WTF_Expected, hash_void)
+{
+ typedef Expected<void, const char*> E;
+ std::unordered_map<E, int> m;
+ m.insert({ E(), 42 });
+ m.insert({ E(makeUnexpected(oops)), 5 });
+ m.insert({ E(makeUnexpected(foof)), 0xf00f });
+ EXPECT_EQ(m[E()], 42);
+ EXPECT_EQ(m[E(makeUnexpected(oops))], 5);
+ EXPECT_EQ(m[E(makeUnexpected(foof))], 0xf00f);
+}
+
+TEST(WTF_Expected, Ref)
+{
+ {
+ RefLogger a("a");
+ Expected<Ref<RefLogger>, int> expected = Ref<RefLogger>(a);
+ EXPECT_TRUE(expected.hasValue());
+ EXPECT_EQ(&a, expected.value().ptr());
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ RefLogger a("a");
+ Expected<Ref<RefLogger>, int> expected = makeExpected<Ref<RefLogger>, int>(Ref<RefLogger>(a));
+ EXPECT_TRUE(expected.hasValue());
+ EXPECT_EQ(&a, expected.value().ptr());
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ RefLogger a("a");
+ Expected<int, Ref<RefLogger>> expected = makeUnexpected(Ref<RefLogger>(a));
+ EXPECT_FALSE(expected.hasValue());
+ EXPECT_EQ(&a, expected.error().ptr());
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ RefLogger a("a");
+ Expected<void, Ref<RefLogger>> expected = makeUnexpected(Ref<RefLogger>(a));
+ EXPECT_FALSE(expected.hasValue());
+ EXPECT_EQ(&a, expected.error().ptr());
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+} // namespace TestWebkitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/Functional.cpp b/Tools/TestWebKitAPI/Tests/WTF/Functional.cpp
deleted file mode 100644
index cf8c3c39c..000000000
--- a/Tools/TestWebKitAPI/Tests/WTF/Functional.cpp
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 2011 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. 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 INC. 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.
- */
-
-#include "config.h"
-#include <wtf/RefCounted.h>
-#include <wtf/Functional.h>
-
-namespace TestWebKitAPI {
-
-static int returnFortyTwo()
-{
- return 42;
-}
-
-TEST(FunctionalTest, Basic)
-{
- Function<int ()> emptyFunction;
- ASSERT_TRUE(emptyFunction.isNull());
-
- Function<int ()> returnFortyTwoFunction = bind(returnFortyTwo);
- ASSERT_FALSE(returnFortyTwoFunction.isNull());
- ASSERT_EQ(42, returnFortyTwoFunction());
-}
-
-static int multiplyByTwo(int n)
-{
- return n * 2;
-}
-
-static double multiplyByOneAndAHalf(double d)
-{
- return d * 1.5;
-}
-
-TEST(FunctionalTest, UnaryBind)
-{
- Function<int ()> multiplyFourByTwoFunction = bind(multiplyByTwo, 4);
- ASSERT_EQ(8, multiplyFourByTwoFunction());
-
- Function<double ()> multiplyByOneAndAHalfFunction = bind(multiplyByOneAndAHalf, 3);
- ASSERT_EQ(4.5, multiplyByOneAndAHalfFunction());
-}
-
-static int multiply(int x, int y)
-{
- return x * y;
-}
-
-static int subtract(int x, int y)
-{
- return x - y;
-}
-
-TEST(FunctionalTest, BinaryBind)
-{
- Function<int ()> multiplyFourByTwoFunction = bind(multiply, 4, 2);
- ASSERT_EQ(8, multiplyFourByTwoFunction());
-
- Function<int ()> subtractTwoFromFourFunction = bind(subtract, 4, 2);
- ASSERT_EQ(2, subtractTwoFromFourFunction());
-}
-
-class A {
-public:
- explicit A(int i)
- : m_i(i)
- {
- }
-
- int f() { return m_i; }
- int addF(int j) { return m_i + j; }
-
-private:
- int m_i;
-};
-
-TEST(FunctionalTest, MemberFunctionBind)
-{
- A a(10);
- Function<int ()> function1 = bind(&A::f, &a);
- ASSERT_EQ(10, function1());
-
- Function<int ()> function2 = bind(&A::addF, &a, 15);
- ASSERT_EQ(25, function2());
-}
-
-class B {
-public:
- B()
- : m_numRefCalls(0)
- , m_numDerefCalls(0)
- {
- }
-
- ~B()
- {
- }
-
- void ref()
- {
- m_numRefCalls++;
- }
-
- void deref()
- {
- m_numDerefCalls++;
- }
-
- void f() { ASSERT_GT(m_numRefCalls, 0); }
- void g(int) { ASSERT_GT(m_numRefCalls, 0); }
-
- int m_numRefCalls;
- int m_numDerefCalls;
-};
-
-TEST(FunctionalTest, MemberFunctionBindRefDeref)
-{
- B b;
-
- {
- Function<void ()> function1 = bind(&B::f, &b);
- function1();
-
- Function<void ()> function2 = bind(&B::g, &b, 10);
- function2();
- }
-
- ASSERT_TRUE(b.m_numRefCalls == b.m_numDerefCalls);
- ASSERT_GT(b.m_numRefCalls, 0);
-
-}
-
-class Number : public RefCounted<Number> {
-public:
- static PassRefPtr<Number> create(int value)
- {
- return adoptRef(new Number(value));
- }
-
- ~Number()
- {
- m_value = 0;
- }
-
- int value() const { return m_value; }
-
-private:
- explicit Number(int value)
- : m_value(value)
- {
- }
-
- int m_value;
-};
-
-static int multiplyNumberByTwo(Number* number)
-{
- return number->value() * 2;
-}
-
-TEST(FunctionalTest, RefCountedStorage)
-{
- RefPtr<Number> five = Number::create(5);
- Function<int ()> multiplyFiveByTwoFunction = bind(multiplyNumberByTwo, five);
- ASSERT_EQ(10, multiplyFiveByTwoFunction());
-
- Function<int ()> multiplyFourByTwoFunction = bind(multiplyNumberByTwo, Number::create(4));
- ASSERT_EQ(8, multiplyFourByTwoFunction());
-
- RefPtr<Number> six = Number::create(6);
- Function<int ()> multiplySixByTwoFunction = bind(multiplyNumberByTwo, six.release());
- ASSERT_FALSE(six);
- ASSERT_EQ(12, multiplySixByTwoFunction());
-}
-
-namespace RefAndDerefTests {
-
- template<typename T> struct RefCounted {
- void ref();
- void deref();
- };
- struct Connection : RefCounted<Connection> { };
- COMPILE_ASSERT(WTF::HasRefAndDeref<Connection>::value, class_has_ref_and_deref);
-
- struct NoRefOrDeref { };
- COMPILE_ASSERT(!WTF::HasRefAndDeref<NoRefOrDeref>::value, class_has_no_ref_or_deref);
-
- struct RefOnly { void ref(); };
- COMPILE_ASSERT(!WTF::HasRefAndDeref<RefOnly>::value, class_has_ref_only);
-
- struct DerefOnly { void deref(); };
- COMPILE_ASSERT(!WTF::HasRefAndDeref<DerefOnly>::value, class_has_deref_only);
-
-}
-
-} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/HashCountedSet.cpp b/Tools/TestWebKitAPI/Tests/WTF/HashCountedSet.cpp
new file mode 100644
index 000000000..9627bd05a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/HashCountedSet.cpp
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Google 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include "Counters.h"
+#include "MoveOnly.h"
+#include "RefLogger.h"
+#include <string>
+#include <wtf/HashCountedSet.h>
+#include <wtf/text/StringHash.h>
+
+namespace TestWebKitAPI {
+
+typedef WTF::HashCountedSet<int> IntHashCountedSet;
+
+TEST(WTF_HashCountedSet, HashTableIteratorComparison)
+{
+ IntHashCountedSet hashCountedSet;
+ hashCountedSet.add(1);
+ ASSERT_TRUE(hashCountedSet.begin() != hashCountedSet.end());
+ ASSERT_FALSE(hashCountedSet.begin() == hashCountedSet.end());
+
+ IntHashCountedSet::const_iterator begin = hashCountedSet.begin();
+ ASSERT_TRUE(begin == hashCountedSet.begin());
+ ASSERT_TRUE(hashCountedSet.begin() == begin);
+ ASSERT_TRUE(begin != hashCountedSet.end());
+ ASSERT_TRUE(hashCountedSet.end() != begin);
+ ASSERT_FALSE(begin != hashCountedSet.begin());
+ ASSERT_FALSE(hashCountedSet.begin() != begin);
+ ASSERT_FALSE(begin == hashCountedSet.end());
+ ASSERT_FALSE(hashCountedSet.end() == begin);
+}
+
+struct TestDoubleHashTraits : HashTraits<double> {
+ static const int minimumTableSize = 8;
+};
+
+typedef HashCountedSet<double, DefaultHash<double>::Hash, TestDoubleHashTraits> DoubleHashCountedSet;
+
+static int bucketForKey(double key)
+{
+ return DefaultHash<double>::Hash::hash(key) & (TestDoubleHashTraits::minimumTableSize - 1);
+}
+
+TEST(WTF_HashCountedSet, DoubleHashCollisions)
+{
+ // The "clobber" key here is one that ends up stealing the bucket that the -0 key
+ // originally wants to be in. This makes the 0 and -0 keys collide and the test then
+ // fails unless the FloatHash::equals() implementation can distinguish them.
+ const double clobberKey = 6;
+ const double zeroKey = 0;
+ const double negativeZeroKey = -zeroKey;
+
+ DoubleHashCountedSet hashCountedSet;
+
+ hashCountedSet.add(clobberKey);
+
+ ASSERT_EQ(hashCountedSet.count(clobberKey), 1u);
+ ASSERT_EQ(hashCountedSet.count(zeroKey), 0u);
+ ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 0u);
+
+ hashCountedSet.add(zeroKey);
+ hashCountedSet.add(negativeZeroKey);
+
+ ASSERT_EQ(bucketForKey(clobberKey), bucketForKey(negativeZeroKey));
+ ASSERT_EQ(hashCountedSet.count(clobberKey), 1u);
+ ASSERT_EQ(hashCountedSet.count(zeroKey), 1u);
+ ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 1u);
+
+ hashCountedSet.add(clobberKey);
+ hashCountedSet.add(zeroKey);
+ hashCountedSet.add(negativeZeroKey);
+
+ ASSERT_EQ(hashCountedSet.count(clobberKey), 2u);
+ ASSERT_EQ(hashCountedSet.count(zeroKey), 2u);
+ ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 2u);
+
+ hashCountedSet.add(clobberKey, 12);
+ hashCountedSet.add(zeroKey, 15);
+ hashCountedSet.add(negativeZeroKey, 17);
+
+ ASSERT_EQ(hashCountedSet.count(clobberKey), 14u);
+ ASSERT_EQ(hashCountedSet.count(zeroKey), 17u);
+ ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 19u);
+}
+
+TEST(WTF_HashCountedSet, DoubleHashCollisionsInitialCount)
+{
+ // The "clobber" key here is one that ends up stealing the bucket that the -0 key
+ // originally wants to be in. This makes the 0 and -0 keys collide and the test then
+ // fails unless the FloatHash::equals() implementation can distinguish them.
+ const double clobberKey = 6;
+ const double zeroKey = 0;
+ const double negativeZeroKey = -zeroKey;
+
+ DoubleHashCountedSet hashCountedSet;
+
+ hashCountedSet.add(clobberKey, 5);
+
+ ASSERT_EQ(hashCountedSet.count(clobberKey), 5u);
+ ASSERT_EQ(hashCountedSet.count(zeroKey), 0u);
+ ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 0u);
+
+ hashCountedSet.add(zeroKey, 22);
+ hashCountedSet.add(negativeZeroKey, 0);
+
+ ASSERT_EQ(bucketForKey(clobberKey), bucketForKey(negativeZeroKey));
+ ASSERT_EQ(hashCountedSet.count(clobberKey), 5u);
+ ASSERT_EQ(hashCountedSet.count(zeroKey), 22u);
+ ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 0u);
+
+ hashCountedSet.add(clobberKey);
+ hashCountedSet.add(zeroKey);
+ hashCountedSet.add(negativeZeroKey);
+
+ ASSERT_EQ(hashCountedSet.count(clobberKey), 6u);
+ ASSERT_EQ(hashCountedSet.count(zeroKey), 23u);
+ ASSERT_EQ(hashCountedSet.count(negativeZeroKey), 1u);
+}
+
+
+TEST(WTF_HashCountedSet, MoveOnlyKeys)
+{
+ HashCountedSet<MoveOnly> moveOnlyKeys;
+
+ for (size_t i = 0; i < 100; ++i) {
+ MoveOnly moveOnly(i + 1);
+ moveOnlyKeys.add(WTFMove(moveOnly));
+ }
+
+ for (size_t i = 0; i < 100; ++i) {
+ auto it = moveOnlyKeys.find(MoveOnly(i + 1));
+ ASSERT_FALSE(it == moveOnlyKeys.end());
+ ASSERT_EQ(it->value, 1u);
+ }
+
+ for (size_t i = 0; i < 100; ++i)
+ ASSERT_FALSE(moveOnlyKeys.add(MoveOnly(i + 1)).isNewEntry);
+
+ for (size_t i = 0; i < 100; ++i)
+ ASSERT_FALSE(moveOnlyKeys.remove(MoveOnly(i + 1)));
+
+ for (size_t i = 0; i < 100; ++i)
+ ASSERT_TRUE(moveOnlyKeys.remove(MoveOnly(i + 1)));
+
+ ASSERT_TRUE(moveOnlyKeys.isEmpty());
+}
+
+TEST(WTF_HashCountedSet, MoveOnlyKeysInitialCount)
+{
+ HashCountedSet<MoveOnly> moveOnlyKeys;
+
+ for (size_t i = 0; i < 100; ++i) {
+ MoveOnly moveOnly(i + 1);
+ moveOnlyKeys.add(WTFMove(moveOnly), i + 1);
+ }
+
+ for (size_t i = 0; i < 100; ++i) {
+ auto it = moveOnlyKeys.find(MoveOnly(i + 1));
+ ASSERT_FALSE(it == moveOnlyKeys.end());
+ ASSERT_EQ(it->value, i + 1);
+ }
+
+ for (size_t i = 0; i < 100; ++i)
+ ASSERT_FALSE(moveOnlyKeys.add(MoveOnly(i + 1)).isNewEntry);
+
+ for (size_t i = 0; i < 100; ++i)
+ ASSERT_EQ(moveOnlyKeys.count(MoveOnly(i + 1)), i + 2);
+
+ for (size_t i = 0; i < 100; ++i)
+ ASSERT_FALSE(moveOnlyKeys.remove(MoveOnly(i + 1)));
+
+ for (size_t i = 0; i < 100; ++i)
+ ASSERT_EQ(moveOnlyKeys.count(MoveOnly(i + 1)), i + 1);
+}
+
+TEST(WTF_HashCountedSet, InitializerList)
+{
+ HashCountedSet<String> hashCountedSet = {
+ "one",
+ "two",
+ "three",
+ "four",
+ "four",
+ "four",
+ "four",
+ };
+
+ EXPECT_EQ(4u, hashCountedSet.size());
+
+ EXPECT_EQ(hashCountedSet.count("one"), 1u);
+ EXPECT_EQ(hashCountedSet.count("two"), 1u);
+ EXPECT_EQ(hashCountedSet.count("three"), 1u);
+ EXPECT_EQ(hashCountedSet.count("four"), 4u);
+}
+
+TEST(WTF_HashCountedSet, InitializerListInitialCount)
+{
+ HashCountedSet<String> hashCountedSet = {
+ { String("one"), 1u },
+ { String("two"), 2u },
+ { String("three"), 3u },
+ { String("four"), 4u },
+ };
+
+ EXPECT_EQ(4u, hashCountedSet.size());
+
+ EXPECT_EQ(hashCountedSet.count("one"), 1u);
+ EXPECT_EQ(hashCountedSet.count("two"), 2u);
+ EXPECT_EQ(hashCountedSet.count("three"), 3u);
+ EXPECT_EQ(hashCountedSet.count("four"), 4u);
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKey)
+{
+ ConstructorDestructorCounter::TestingScope scope;
+
+ HashCountedSet<std::unique_ptr<ConstructorDestructorCounter>> hashCountedSet;
+
+ auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+ hashCountedSet.add(WTFMove(uniquePtr));
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ hashCountedSet.clear();
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKeyInitialCount)
+{
+ ConstructorDestructorCounter::TestingScope scope;
+
+ HashCountedSet<std::unique_ptr<ConstructorDestructorCounter>> hashCountedSet;
+
+ auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+ hashCountedSet.add(WTFMove(uniquePtr), 12);
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ hashCountedSet.clear();
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKey_CustomDeleter)
+{
+ ConstructorDestructorCounter::TestingScope constructorDestructorCounterScope;
+ DeleterCounter<ConstructorDestructorCounter>::TestingScope deleterCounterScope;
+
+ HashCountedSet<std::unique_ptr<ConstructorDestructorCounter, DeleterCounter<ConstructorDestructorCounter>>> hashCountedSet;
+
+ std::unique_ptr<ConstructorDestructorCounter, DeleterCounter<ConstructorDestructorCounter>> uniquePtr(new ConstructorDestructorCounter(), DeleterCounter<ConstructorDestructorCounter>());
+ hashCountedSet.add(WTFMove(uniquePtr));
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ EXPECT_EQ(0u, DeleterCounter<ConstructorDestructorCounter>::deleterCount());
+
+ hashCountedSet.clear();
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+
+ EXPECT_EQ(1u, DeleterCounter<ConstructorDestructorCounter>::deleterCount());
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKey_FindUsingRawPointer)
+{
+ HashCountedSet<std::unique_ptr<int>> hashCountedSet;
+
+ auto uniquePtr = std::make_unique<int>(5);
+ int* ptr = uniquePtr.get();
+ hashCountedSet.add(WTFMove(uniquePtr));
+
+ auto it = hashCountedSet.find(ptr);
+ ASSERT_TRUE(it != hashCountedSet.end());
+ EXPECT_EQ(ptr, it->key.get());
+ EXPECT_EQ(1u, it->value);
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKey_ContainsUsingRawPointer)
+{
+ HashCountedSet<std::unique_ptr<int>> hashCountedSet;
+
+ auto uniquePtr = std::make_unique<int>(5);
+ int* ptr = uniquePtr.get();
+ hashCountedSet.add(WTFMove(uniquePtr));
+
+ EXPECT_EQ(true, hashCountedSet.contains(ptr));
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKey_GetUsingRawPointer)
+{
+ HashCountedSet<std::unique_ptr<int>> hashCountedSet;
+
+ auto uniquePtr = std::make_unique<int>(5);
+ int* ptr = uniquePtr.get();
+ hashCountedSet.add(WTFMove(uniquePtr));
+
+ int value = hashCountedSet.count(ptr);
+ EXPECT_EQ(1, value);
+}
+
+TEST(WTF_HashCountedSet, UniquePtrKey_RemoveUsingRawPointer)
+{
+ ConstructorDestructorCounter::TestingScope scope;
+
+ HashCountedSet<std::unique_ptr<ConstructorDestructorCounter>> hashCountedSet;
+
+ auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+ ConstructorDestructorCounter* ptr = uniquePtr.get();
+ hashCountedSet.add(WTFMove(uniquePtr));
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ bool result = hashCountedSet.remove(ptr);
+ EXPECT_EQ(true, result);
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_Add)
+{
+ HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ hashCountedSet.add(ptr);
+
+ ASSERT_STREQ("ref(a) ref(a) ", takeLogStr().c_str());
+ EXPECT_EQ(1U, hashCountedSet.count(ptr));
+ EXPECT_EQ(1U, hashCountedSet.count(ptr.get()));
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_AddUsingRelease)
+{
+ HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ hashCountedSet.add(WTFMove(ptr));
+
+ EXPECT_STREQ("ref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_AddUsingMove)
+{
+ HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ hashCountedSet.add(WTFMove(ptr));
+
+ EXPECT_STREQ("ref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_AddUsingRaw)
+{
+ HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ hashCountedSet.add(ptr.get());
+
+ EXPECT_STREQ("ref(a) ref(a) ", takeLogStr().c_str());
+ EXPECT_EQ(1U, hashCountedSet.count(ptr));
+ EXPECT_EQ(1U, hashCountedSet.count(ptr.get()));
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_AddKeyAlreadyPresent)
+{
+ HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+
+ DerivedRefLogger a("a");
+
+ {
+ RefPtr<RefLogger> ptr(&a);
+ hashCountedSet.add(ptr);
+ }
+
+ EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ RefPtr<RefLogger> ptr2(&a);
+ auto addResult = hashCountedSet.add(ptr2);
+ EXPECT_FALSE(addResult.isNewEntry);
+ }
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_AddUsingReleaseKeyAlreadyPresent)
+{
+ HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+
+ DerivedRefLogger a("a");
+
+ {
+ RefPtr<RefLogger> ptr(&a);
+ hashCountedSet.add(ptr);
+ }
+
+ EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ RefPtr<RefLogger> ptr2(&a);
+ auto addResult = hashCountedSet.add(WTFMove(ptr2));
+ EXPECT_FALSE(addResult.isNewEntry);
+ }
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashCountedSet, RefPtrKey_AddUsingMoveKeyAlreadyPresent)
+{
+ HashCountedSet<RefPtr<RefLogger>> hashCountedSet;
+
+ DerivedRefLogger a("a");
+
+ {
+ RefPtr<RefLogger> ptr(&a);
+ hashCountedSet.add(ptr);
+ }
+
+ EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ RefPtr<RefLogger> ptr2(&a);
+ auto addResult = hashCountedSet.add(WTFMove(ptr2));
+ EXPECT_FALSE(addResult.isNewEntry);
+ }
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp b/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp
index d03fb9594..222f23c5c 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp
@@ -25,9 +25,14 @@
#include "config.h"
+#include "Counters.h"
+#include "DeletedAddressOfOperator.h"
#include "MoveOnly.h"
+#include "RefLogger.h"
+#include "Test.h"
#include <string>
#include <wtf/HashMap.h>
+#include <wtf/Ref.h>
#include <wtf/text/StringHash.h>
namespace TestWebKitAPI {
@@ -90,7 +95,7 @@ TEST(WTF_HashMap, MoveOnlyValues)
for (size_t i = 0; i < 100; ++i) {
MoveOnly moveOnly(i + 1);
- moveOnlyValues.set(i + 1, std::move(moveOnly));
+ moveOnlyValues.set(i + 1, WTFMove(moveOnly));
}
for (size_t i = 0; i < 100; ++i) {
@@ -113,7 +118,7 @@ TEST(WTF_HashMap, MoveOnlyKeys)
for (size_t i = 0; i < 100; ++i) {
MoveOnly moveOnly(i + 1);
- moveOnlyKeys.set(std::move(moveOnly), i + 1);
+ moveOnlyKeys.set(WTFMove(moveOnly), i + 1);
}
for (size_t i = 0; i < 100; ++i) {
@@ -139,7 +144,7 @@ TEST(WTF_HashMap, InitializerList)
{ 4, "four" },
};
- EXPECT_EQ(4, map.size());
+ EXPECT_EQ(4u, map.size());
EXPECT_EQ("one", map.get(1));
EXPECT_EQ("two", map.get(2));
@@ -148,4 +153,773 @@ TEST(WTF_HashMap, InitializerList)
EXPECT_EQ(std::string(), map.get(5));
}
+TEST(WTF_HashMap, EfficientGetter)
+{
+ HashMap<unsigned, CopyMoveCounter> map;
+ map.set(1, CopyMoveCounter());
+
+ {
+ CopyMoveCounter::TestingScope scope;
+ map.get(1);
+ EXPECT_EQ(0U, CopyMoveCounter::constructionCount);
+ EXPECT_EQ(1U, CopyMoveCounter::copyCount);
+ EXPECT_EQ(0U, CopyMoveCounter::moveCount);
+ }
+
+ {
+ CopyMoveCounter::TestingScope scope;
+ map.get(2);
+ EXPECT_EQ(1U, CopyMoveCounter::constructionCount);
+ EXPECT_EQ(0U, CopyMoveCounter::copyCount);
+ EXPECT_EQ(1U, CopyMoveCounter::moveCount);
+ }
+}
+
+TEST(WTF_HashMap, UniquePtrKey)
+{
+ ConstructorDestructorCounter::TestingScope scope;
+
+ HashMap<std::unique_ptr<ConstructorDestructorCounter>, int> map;
+
+ auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+ map.add(WTFMove(uniquePtr), 2);
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ map.clear();
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashMap, UniquePtrKey_CustomDeleter)
+{
+ ConstructorDestructorCounter::TestingScope constructorDestructorCounterScope;
+ DeleterCounter<ConstructorDestructorCounter>::TestingScope deleterCounterScope;
+
+ HashMap<std::unique_ptr<ConstructorDestructorCounter, DeleterCounter<ConstructorDestructorCounter>>, int> map;
+
+ std::unique_ptr<ConstructorDestructorCounter, DeleterCounter<ConstructorDestructorCounter>> uniquePtr(new ConstructorDestructorCounter(), DeleterCounter<ConstructorDestructorCounter>());
+ map.add(WTFMove(uniquePtr), 2);
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ EXPECT_EQ(0u, DeleterCounter<ConstructorDestructorCounter>::deleterCount());
+
+ map.clear();
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+
+ EXPECT_EQ(1u, DeleterCounter<ConstructorDestructorCounter>::deleterCount());
+}
+
+TEST(WTF_HashMap, UniquePtrKey_FindUsingRawPointer)
+{
+ HashMap<std::unique_ptr<int>, int> map;
+
+ auto uniquePtr = std::make_unique<int>(5);
+ int* ptr = uniquePtr.get();
+ map.add(WTFMove(uniquePtr), 2);
+
+ auto it = map.find(ptr);
+ ASSERT_TRUE(it != map.end());
+ EXPECT_EQ(ptr, it->key.get());
+ EXPECT_EQ(2, it->value);
+}
+
+TEST(WTF_HashMap, UniquePtrKey_ContainsUsingRawPointer)
+{
+ HashMap<std::unique_ptr<int>, int> map;
+
+ auto uniquePtr = std::make_unique<int>(5);
+ int* ptr = uniquePtr.get();
+ map.add(WTFMove(uniquePtr), 2);
+
+ EXPECT_EQ(true, map.contains(ptr));
+}
+
+TEST(WTF_HashMap, UniquePtrKey_GetUsingRawPointer)
+{
+ HashMap<std::unique_ptr<int>, int> map;
+
+ auto uniquePtr = std::make_unique<int>(5);
+ int* ptr = uniquePtr.get();
+ map.add(WTFMove(uniquePtr), 2);
+
+ int value = map.get(ptr);
+ EXPECT_EQ(2, value);
+}
+
+TEST(WTF_HashMap, UniquePtrKey_RemoveUsingRawPointer)
+{
+ ConstructorDestructorCounter::TestingScope scope;
+
+ HashMap<std::unique_ptr<ConstructorDestructorCounter>, int> map;
+
+ auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+ ConstructorDestructorCounter* ptr = uniquePtr.get();
+ map.add(WTFMove(uniquePtr), 2);
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ bool result = map.remove(ptr);
+ EXPECT_EQ(true, result);
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashMap, UniquePtrKey_TakeUsingRawPointer)
+{
+ ConstructorDestructorCounter::TestingScope scope;
+
+ HashMap<std::unique_ptr<ConstructorDestructorCounter>, int> map;
+
+ auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+ ConstructorDestructorCounter* ptr = uniquePtr.get();
+ map.add(WTFMove(uniquePtr), 2);
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ int result = map.take(ptr);
+ EXPECT_EQ(2, result);
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashMap, RefPtrKey_Add)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ map.add(ptr, 0);
+
+ ASSERT_STREQ("ref(a) ref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_AddUsingRelease)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ map.add(WTFMove(ptr), 0);
+
+ EXPECT_STREQ("ref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_AddUsingMove)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ map.add(WTFMove(ptr), 0);
+
+ EXPECT_STREQ("ref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_AddUsingRaw)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ map.add(ptr.get(), 0);
+
+ EXPECT_STREQ("ref(a) ref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_AddKeyAlreadyPresent)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+
+ {
+ RefPtr<RefLogger> ptr(&a);
+ map.add(ptr, 0);
+ }
+
+ EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ RefPtr<RefLogger> ptr2(&a);
+ auto addResult = map.add(ptr2, 0);
+ EXPECT_FALSE(addResult.isNewEntry);
+ }
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_AddUsingReleaseKeyAlreadyPresent)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+
+ {
+ RefPtr<RefLogger> ptr(&a);
+ map.add(ptr, 0);
+ }
+
+ EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ RefPtr<RefLogger> ptr2(&a);
+ auto addResult = map.add(WTFMove(ptr2), 0);
+ EXPECT_FALSE(addResult.isNewEntry);
+ }
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_AddUsingMoveKeyAlreadyPresent)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+
+ {
+ RefPtr<RefLogger> ptr(&a);
+ map.add(ptr, 0);
+ }
+
+ EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ RefPtr<RefLogger> ptr2(&a);
+ auto addResult = map.add(WTFMove(ptr2), 0);
+ EXPECT_FALSE(addResult.isNewEntry);
+ }
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_Set)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ map.set(ptr, 0);
+
+ ASSERT_STREQ("ref(a) ref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_SetUsingRelease)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ map.set(WTFMove(ptr), 0);
+
+ EXPECT_STREQ("ref(a) ", takeLogStr().c_str());
+}
+
+
+TEST(WTF_HashMap, RefPtrKey_SetUsingMove)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ map.set(WTFMove(ptr), 0);
+
+ EXPECT_STREQ("ref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_SetUsingRaw)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+ RefPtr<RefLogger> ptr(&a);
+ map.set(ptr.get(), 0);
+
+ EXPECT_STREQ("ref(a) ref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_SetKeyAlreadyPresent)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+
+ RefPtr<RefLogger> ptr(&a);
+ map.set(ptr, 0);
+
+ EXPECT_STREQ("ref(a) ref(a) ", takeLogStr().c_str());
+
+ {
+ RefPtr<RefLogger> ptr2(&a);
+ auto addResult = map.set(ptr2, 1);
+ EXPECT_FALSE(addResult.isNewEntry);
+ EXPECT_EQ(1, map.get(ptr.get()));
+ }
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_SetUsingReleaseKeyAlreadyPresent)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+
+ RefPtr<RefLogger> ptr(&a);
+ map.set(ptr, 0);
+
+ EXPECT_STREQ("ref(a) ref(a) ", takeLogStr().c_str());
+
+ {
+ RefPtr<RefLogger> ptr2(&a);
+ auto addResult = map.set(WTFMove(ptr2), 1);
+ EXPECT_FALSE(addResult.isNewEntry);
+ EXPECT_EQ(1, map.get(ptr.get()));
+ }
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, RefPtrKey_SetUsingMoveKeyAlreadyPresent)
+{
+ HashMap<RefPtr<RefLogger>, int> map;
+
+ DerivedRefLogger a("a");
+
+ RefPtr<RefLogger> ptr(&a);
+ map.set(ptr, 0);
+
+ EXPECT_STREQ("ref(a) ref(a) ", takeLogStr().c_str());
+
+ {
+ RefPtr<RefLogger> ptr2(&a);
+ auto addResult = map.set(WTFMove(ptr2), 1);
+ EXPECT_FALSE(addResult.isNewEntry);
+ EXPECT_EQ(1, map.get(ptr.get()));
+ }
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, Ensure)
+{
+ HashMap<unsigned, unsigned> map;
+ {
+ auto addResult = map.ensure(1, [] { return 1; });
+ EXPECT_EQ(1u, addResult.iterator->value);
+ EXPECT_EQ(1u, addResult.iterator->key);
+ EXPECT_TRUE(addResult.isNewEntry);
+ auto addResult2 = map.ensure(1, [] { return 2; });
+ EXPECT_EQ(1u, addResult2.iterator->value);
+ EXPECT_EQ(1u, addResult2.iterator->key);
+ EXPECT_FALSE(addResult2.isNewEntry);
+ }
+}
+
+TEST(WTF_HashMap, Ensure_MoveOnlyValues)
+{
+ HashMap<unsigned, MoveOnly> moveOnlyValues;
+ {
+ auto addResult = moveOnlyValues.ensure(1, [] { return MoveOnly(1); });
+ EXPECT_EQ(1u, addResult.iterator->value.value());
+ EXPECT_EQ(1u, addResult.iterator->key);
+ EXPECT_TRUE(addResult.isNewEntry);
+ auto addResult2 = moveOnlyValues.ensure(1, [] { return MoveOnly(2); });
+ EXPECT_EQ(1u, addResult2.iterator->value.value());
+ EXPECT_EQ(1u, addResult2.iterator->key);
+ EXPECT_FALSE(addResult2.isNewEntry);
+ }
+}
+
+TEST(WTF_HashMap, Ensure_UniquePointer)
+{
+ HashMap<unsigned, std::unique_ptr<unsigned>> map;
+ {
+ auto addResult = map.ensure(1, [] { return std::make_unique<unsigned>(1); });
+ EXPECT_EQ(1u, *map.get(1));
+ EXPECT_EQ(1u, *addResult.iterator->value.get());
+ EXPECT_EQ(1u, addResult.iterator->key);
+ EXPECT_TRUE(addResult.isNewEntry);
+ auto addResult2 = map.ensure(1, [] { return std::make_unique<unsigned>(2); });
+ EXPECT_EQ(1u, *map.get(1));
+ EXPECT_EQ(1u, *addResult2.iterator->value.get());
+ EXPECT_EQ(1u, addResult2.iterator->key);
+ EXPECT_FALSE(addResult2.isNewEntry);
+ }
+}
+
+TEST(WTF_HashMap, Ensure_RefPtr)
+{
+ HashMap<unsigned, RefPtr<RefLogger>> map;
+
+ {
+ DerivedRefLogger a("a");
+
+ map.ensure(1, [&] { return RefPtr<RefLogger>(&a); });
+ EXPECT_STREQ("ref(a) ", takeLogStr().c_str());
+
+ map.ensure(1, [&] { return RefPtr<RefLogger>(&a); });
+ EXPECT_STREQ("", takeLogStr().c_str());
+ }
+}
+
+class ObjectWithRefLogger {
+public:
+ ObjectWithRefLogger(Ref<RefLogger>&& logger)
+ : m_logger(WTFMove(logger))
+ {
+ }
+
+ Ref<RefLogger> m_logger;
+};
+
+
+void testMovingUsingEnsure(Ref<RefLogger>&& logger)
+{
+ HashMap<unsigned, std::unique_ptr<ObjectWithRefLogger>> map;
+
+ map.ensure(1, [&] { return std::make_unique<ObjectWithRefLogger>(WTFMove(logger)); });
+}
+
+void testMovingUsingAdd(Ref<RefLogger>&& logger)
+{
+ HashMap<unsigned, std::unique_ptr<ObjectWithRefLogger>> map;
+
+ auto& slot = map.add(1, nullptr).iterator->value;
+ slot = std::make_unique<ObjectWithRefLogger>(WTFMove(logger));
+}
+
+TEST(WTF_HashMap, Ensure_LambdasCapturingByReference)
+{
+ {
+ DerivedRefLogger a("a");
+ Ref<RefLogger> ref(a);
+ testMovingUsingEnsure(WTFMove(ref));
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+ }
+
+ {
+ DerivedRefLogger a("a");
+ Ref<RefLogger> ref(a);
+ testMovingUsingAdd(WTFMove(ref));
+
+ EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+ }
+}
+
+
+TEST(WTF_HashMap, ValueIsDestructedOnRemove)
+{
+ struct DestructorObserver {
+ DestructorObserver() = default;
+
+ DestructorObserver(bool* destructed)
+ : destructed(destructed)
+ {
+ }
+
+ ~DestructorObserver()
+ {
+ if (destructed)
+ *destructed = true;
+ }
+
+ DestructorObserver(DestructorObserver&& other)
+ : destructed(other.destructed)
+ {
+ other.destructed = nullptr;
+ }
+
+ DestructorObserver& operator=(DestructorObserver&& other)
+ {
+ destructed = other.destructed;
+ other.destructed = nullptr;
+ return *this;
+ }
+
+ bool* destructed { nullptr };
+ };
+
+ HashMap<int, DestructorObserver> map;
+
+ bool destructed = false;
+ map.add(5, DestructorObserver { &destructed });
+
+ EXPECT_FALSE(destructed);
+
+ bool removeResult = map.remove(5);
+
+ EXPECT_TRUE(removeResult);
+ EXPECT_TRUE(destructed);
+}
+
+TEST(WTF_HashMap, RefPtrNotZeroedBeforeDeref)
+{
+ struct DerefObserver {
+ NEVER_INLINE void ref()
+ {
+ ++count;
+ }
+ NEVER_INLINE void deref()
+ {
+ --count;
+ observedBucket = bucketAddress->get();
+ }
+ unsigned count { 1 };
+ const RefPtr<DerefObserver>* bucketAddress { nullptr };
+ const DerefObserver* observedBucket { nullptr };
+ };
+
+ auto observer = std::make_unique<DerefObserver>();
+
+ HashMap<RefPtr<DerefObserver>, int> map;
+ map.add(adoptRef(observer.get()), 5);
+
+ auto iterator = map.find(observer.get());
+ EXPECT_TRUE(iterator != map.end());
+
+ observer->bucketAddress = &iterator->key;
+
+ EXPECT_TRUE(observer->observedBucket == nullptr);
+ EXPECT_TRUE(map.remove(observer.get()));
+
+ // It if fine to either leave the old value intact at deletion or already set it to the deleted
+ // value.
+ // A zero would be a incorrect outcome as it would mean we nulled the bucket before an opaque
+ // call.
+ EXPECT_TRUE(observer->observedBucket == observer.get() || observer->observedBucket == RefPtr<DerefObserver>::hashTableDeletedValue());
+ EXPECT_EQ(observer->count, 0u);
+}
+
+TEST(WTF_HashMap, Ref_Key)
+{
+ {
+ HashMap<Ref<RefLogger>, int> map;
+
+ RefLogger a("a");
+ Ref<RefLogger> ref(a);
+ map.add(WTFMove(ref), 1);
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ HashMap<Ref<RefLogger>, int> map;
+
+ RefLogger a("a");
+ Ref<RefLogger> ref(a);
+ map.set(WTFMove(ref), 1);
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ HashMap<Ref<RefLogger>, int> map;
+
+ RefLogger a("a");
+ Ref<RefLogger> refA(a);
+ map.add(WTFMove(refA), 1);
+
+ Ref<RefLogger> refA2(a);
+ map.set(WTFMove(refA2), 1);
+ }
+
+ ASSERT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ HashMap<Ref<RefLogger>, int> map;
+
+ RefLogger a("a");
+ Ref<RefLogger> ref(a);
+ map.ensure(WTFMove(ref), []() {
+ return 1;
+ });
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ HashMap<Ref<RefLogger>, int> map;
+
+ RefLogger a("a");
+ Ref<RefLogger> ref(a);
+ map.add(WTFMove(ref), 1);
+
+ auto it = map.find(&a);
+ ASSERT_TRUE(it != map.end());
+
+ ASSERT_EQ(it->key.ptr(), &a);
+ ASSERT_EQ(it->value, 1);
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ HashMap<Ref<RefLogger>, int> map;
+
+ RefLogger a("a");
+ Ref<RefLogger> ref(a);
+ map.add(WTFMove(ref), 1);
+
+ map.remove(&a);
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ HashMap<Ref<RefLogger>, int> map;
+
+ RefLogger a("a");
+ Ref<RefLogger> ref(a);
+ map.add(WTFMove(ref), 1);
+
+ int i = map.take(&a);
+ ASSERT_EQ(i, 1);
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ HashMap<Ref<RefLogger>, int> map;
+ for (int i = 0; i < 64; ++i) {
+ Ref<RefLogger> ref = adoptRef(*new RefLogger("a"));
+ auto* pointer = ref.ptr();
+ map.add(WTFMove(ref), i + 1);
+ ASSERT_TRUE(map.contains(pointer));
+ }
+ }
+
+ ASSERT_STREQ("deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, Ref_Value)
+{
+ {
+ HashMap<int, Ref<RefLogger>> map;
+
+ RefLogger a("a");
+ Ref<RefLogger> ref(a);
+ map.add(1, WTFMove(ref));
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ HashMap<int, Ref<RefLogger>> map;
+
+ RefLogger a("a");
+ Ref<RefLogger> ref(a);
+ map.set(1, WTFMove(ref));
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ HashMap<int, Ref<RefLogger>> map;
+
+ RefLogger a("a");
+ Ref<RefLogger> refA(a);
+ map.add(1, WTFMove(refA));
+
+ RefLogger b("b");
+ Ref<RefLogger> refB(b);
+ map.set(1, WTFMove(refB));
+ }
+
+ ASSERT_STREQ("ref(a) ref(b) deref(a) deref(b) ", takeLogStr().c_str());
+
+ {
+ HashMap<int, Ref<RefLogger>> map;
+
+ RefLogger a("a");
+ Ref<RefLogger> ref(a);
+ map.add(1, WTFMove(ref));
+
+ auto aGet = map.get(1);
+ ASSERT_EQ(aGet, &a);
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ HashMap<int, Ref<RefLogger>> map;
+
+ auto emptyGet = map.get(1);
+ ASSERT_TRUE(emptyGet == nullptr);
+ }
+
+ {
+ HashMap<int, Ref<RefLogger>> map;
+
+ RefLogger a("a");
+ Ref<RefLogger> ref(a);
+ map.add(1, WTFMove(ref));
+
+ auto aOut = map.take(1);
+ ASSERT_TRUE(static_cast<bool>(aOut));
+ ASSERT_EQ(&a, aOut.value().ptr());
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ HashMap<int, Ref<RefLogger>> map;
+
+ auto emptyTake = map.take(1);
+ ASSERT_FALSE(static_cast<bool>(emptyTake));
+ }
+
+ {
+ HashMap<int, Ref<RefLogger>> map;
+
+ RefLogger a("a");
+ Ref<RefLogger> ref(a);
+ map.add(1, WTFMove(ref));
+ map.remove(1);
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ HashMap<int, Ref<RefLogger>> map;
+
+ RefLogger a("a");
+ map.ensure(1, [&]() mutable {
+ Ref<RefLogger> ref(a);
+ return ref;
+ });
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ HashMap<int, Ref<RefLogger>> map;
+ for (int i = 0; i < 64; ++i) {
+ Ref<RefLogger> ref = adoptRef(*new RefLogger("a"));
+ map.add(i + 1, WTFMove(ref));
+ ASSERT_TRUE(map.contains(i + 1));
+ }
+ }
+
+ ASSERT_STREQ("deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashMap, DeletedAddressOfOperator)
+{
+ HashMap<int, DeletedAddressOfOperator> map1;
+ for (auto& value : map1.values())
+ (void)value;
+}
+
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp b/Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp
index 88e7d075f..3d25057f8 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp
@@ -25,9 +25,12 @@
#include "config.h"
+#include "Counters.h"
+#include "DeletedAddressOfOperator.h"
#include "MoveOnly.h"
+#include "RefLogger.h"
#include <wtf/HashSet.h>
-
+#include <wtf/RefPtr.h>
namespace TestWebKitAPI {
@@ -43,7 +46,7 @@ void testInitialCapacity()
HashSet<int, DefaultHash<int>::Hash, InitialCapacityTestHashTraits<initialCapacity> > testSet;
// Initial capacity is null.
- ASSERT_EQ(0, testSet.capacity());
+ ASSERT_EQ(0u, testSet.capacity());
// Adding items up to size should never change the capacity.
for (size_t i = 0; i < size; ++i) {
@@ -84,7 +87,7 @@ TEST(WTF_HashSet, MoveOnly)
for (size_t i = 0; i < 100; ++i) {
MoveOnly moveOnly(i + 1);
- hashSet.add(std::move(moveOnly));
+ hashSet.add(WTFMove(moveOnly));
}
for (size_t i = 0; i < 100; ++i)
@@ -96,11 +99,354 @@ TEST(WTF_HashSet, MoveOnly)
EXPECT_TRUE(hashSet.isEmpty());
for (size_t i = 0; i < 100; ++i)
- hashSet.add(std::move(MoveOnly(i + 1)));
+ hashSet.add(MoveOnly(i + 1));
for (size_t i = 0; i < 100; ++i)
EXPECT_TRUE(hashSet.take(MoveOnly(i + 1)) == MoveOnly(i + 1));
+ EXPECT_TRUE(hashSet.isEmpty());
+
+ for (size_t i = 0; i < 100; ++i)
+ hashSet.add(MoveOnly(i + 1));
+
+ HashSet<MoveOnly> secondSet;
+
+ for (size_t i = 0; i < 100; ++i)
+ secondSet.add(hashSet.takeAny());
+
+ EXPECT_TRUE(hashSet.isEmpty());
+
+ for (size_t i = 0; i < 100; ++i)
+ EXPECT_TRUE(secondSet.contains(MoveOnly(i + 1)));
+}
+
+
+TEST(WTF_HashSet, UniquePtrKey)
+{
+ ConstructorDestructorCounter::TestingScope scope;
+
+ HashSet<std::unique_ptr<ConstructorDestructorCounter>> set;
+
+ auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+ set.add(WTFMove(uniquePtr));
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ set.clear();
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashSet, UniquePtrKey_FindUsingRawPointer)
+{
+ HashSet<std::unique_ptr<int>> set;
+
+ auto uniquePtr = std::make_unique<int>(5);
+ int* ptr = uniquePtr.get();
+ set.add(WTFMove(uniquePtr));
+
+ auto it = set.find(ptr);
+ ASSERT_TRUE(it != set.end());
+ EXPECT_EQ(ptr, it->get());
+ EXPECT_EQ(5, *it->get());
+}
+
+TEST(WTF_HashSet, UniquePtrKey_ContainsUsingRawPointer)
+{
+ HashSet<std::unique_ptr<int>> set;
+
+ auto uniquePtr = std::make_unique<int>(5);
+ int* ptr = uniquePtr.get();
+ set.add(WTFMove(uniquePtr));
+
+ EXPECT_EQ(true, set.contains(ptr));
+}
+
+TEST(WTF_HashSet, UniquePtrKey_RemoveUsingRawPointer)
+{
+ ConstructorDestructorCounter::TestingScope scope;
+
+ HashSet<std::unique_ptr<ConstructorDestructorCounter>> set;
+
+ auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+ ConstructorDestructorCounter* ptr = uniquePtr.get();
+ set.add(WTFMove(uniquePtr));
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ bool result = set.remove(ptr);
+ EXPECT_EQ(true, result);
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashSet, UniquePtrKey_TakeUsingRawPointer)
+{
+ ConstructorDestructorCounter::TestingScope scope;
+
+ HashSet<std::unique_ptr<ConstructorDestructorCounter>> set;
+
+ auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+ ConstructorDestructorCounter* ptr = uniquePtr.get();
+ set.add(WTFMove(uniquePtr));
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ auto result = set.take(ptr);
+ EXPECT_EQ(ptr, result.get());
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+
+ result = nullptr;
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_HashSet, CopyEmpty)
+{
+ {
+ HashSet<unsigned> foo;
+ HashSet<unsigned> bar(foo);
+
+ EXPECT_EQ(0u, bar.capacity());
+ EXPECT_EQ(0u, bar.size());
+ }
+ {
+ HashSet<unsigned> foo({ 1, 5, 64, 42 });
+ EXPECT_EQ(4u, foo.size());
+ foo.remove(1);
+ foo.remove(5);
+ foo.remove(42);
+ foo.remove(64);
+ HashSet<unsigned> bar(foo);
+
+ EXPECT_EQ(0u, bar.capacity());
+ EXPECT_EQ(0u, bar.size());
+ }
+}
+
+TEST(WTF_HashSet, CopyAllocateAtLeastMinimumCapacity)
+{
+ HashSet<unsigned> foo({ 42 });
+ EXPECT_EQ(1u, foo.size());
+ HashSet<unsigned> bar(foo);
+
+ EXPECT_EQ(8u, bar.capacity());
+ EXPECT_EQ(1u, bar.size());
+}
+
+TEST(WTF_HashSet, CopyCapacityIsNotOnBoundary)
+{
+ // Starting at 4 because the minimum size is 8.
+ // With a size of 8, a medium load can be up to 3.3333->3.
+ // Adding 1 to 3 would reach max load.
+ // While correct, that's not really what we care about here.
+ for (unsigned size = 4; size < 100; ++size) {
+ HashSet<unsigned> source;
+ for (unsigned i = 1; i < size + 1; ++i)
+ source.add(i);
+
+ HashSet<unsigned> copy1(source);
+ HashSet<unsigned> copy2(source);
+ HashSet<unsigned> copy3(source);
+
+ EXPECT_EQ(size, copy1.size());
+ EXPECT_EQ(size, copy2.size());
+ EXPECT_EQ(size, copy3.size());
+ for (unsigned i = 1; i < size + 1; ++i) {
+ EXPECT_TRUE(copy1.contains(i));
+ EXPECT_TRUE(copy2.contains(i));
+ EXPECT_TRUE(copy3.contains(i));
+ }
+ EXPECT_FALSE(copy1.contains(size + 2));
+ EXPECT_FALSE(copy2.contains(size + 2));
+ EXPECT_FALSE(copy3.contains(size + 2));
+
+ EXPECT_TRUE(copy2.remove(1));
+ EXPECT_EQ(copy1.capacity(), copy2.capacity());
+ EXPECT_FALSE(copy2.contains(1));
+
+ EXPECT_TRUE(copy3.add(size + 2).isNewEntry);
+ EXPECT_EQ(copy1.capacity(), copy3.capacity());
+ EXPECT_TRUE(copy3.contains(size + 2));
+ }
+}
+
+TEST(WTF_HashSet, RefPtrNotZeroedBeforeDeref)
+{
+ struct DerefObserver {
+ NEVER_INLINE void ref()
+ {
+ ++count;
+ }
+ NEVER_INLINE void deref()
+ {
+ --count;
+ observedBucket = bucketAddress->get();
+ }
+ unsigned count { 1 };
+ const RefPtr<DerefObserver>* bucketAddress { nullptr };
+ const DerefObserver* observedBucket { nullptr };
+ };
+
+ auto observer = std::make_unique<DerefObserver>();
+
+ HashSet<RefPtr<DerefObserver>> set;
+ set.add(adoptRef(observer.get()));
+
+ auto iterator = set.find(observer.get());
+ EXPECT_TRUE(iterator != set.end());
+
+ observer->bucketAddress = iterator.get();
+
+ EXPECT_TRUE(observer->observedBucket == nullptr);
+ EXPECT_TRUE(set.remove(observer.get()));
+
+ // It if fine to either leave the old value intact at deletion or already set it to the deleted
+ // value.
+ // A zero would be a incorrect outcome as it would mean we nulled the bucket before an opaque
+ // call.
+ EXPECT_TRUE(observer->observedBucket == observer.get() || observer->observedBucket == RefPtr<DerefObserver>::hashTableDeletedValue());
+ EXPECT_EQ(observer->count, 0u);
+}
+
+
+TEST(WTF_HashSet, UniquePtrNotZeroedBeforeDestructor)
+{
+ struct DestructorObserver {
+ ~DestructorObserver()
+ {
+ observe();
+ }
+ std::function<void()> observe;
+ };
+
+ const std::unique_ptr<DestructorObserver>* bucketAddress = nullptr;
+ const DestructorObserver* observedBucket = nullptr;
+ std::unique_ptr<DestructorObserver> observer(new DestructorObserver { [&]() {
+ observedBucket = bucketAddress->get();
+ }});
+
+ const DestructorObserver* observerAddress = observer.get();
+
+ HashSet<std::unique_ptr<DestructorObserver>> set;
+ auto addResult = set.add(WTFMove(observer));
+
+ EXPECT_TRUE(addResult.isNewEntry);
+ EXPECT_TRUE(observedBucket == nullptr);
+
+ bucketAddress = addResult.iterator.get();
+
+ EXPECT_TRUE(observedBucket == nullptr);
+ EXPECT_TRUE(set.remove(*addResult.iterator));
+
+ EXPECT_TRUE(observedBucket == observerAddress || observedBucket == reinterpret_cast<const DestructorObserver*>(-1));
+}
+
+TEST(WTF_HashSet, Ref)
+{
+ {
+ HashSet<Ref<RefLogger>> set;
+
+ RefLogger a("a");
+ Ref<RefLogger> ref(a);
+ set.add(WTFMove(ref));
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ HashSet<Ref<RefLogger>> set;
+
+ RefLogger a("a");
+ Ref<RefLogger> ref(a);
+ set.add(ref.copyRef());
+ }
+
+ ASSERT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ HashSet<Ref<RefLogger>> set;
+
+ RefLogger a("a");
+ Ref<RefLogger> ref(a);
+ set.add(WTFMove(ref));
+ set.remove(&a);
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ HashSet<Ref<RefLogger>> set;
+
+ RefLogger a("a");
+ Ref<RefLogger> ref(a);
+ set.add(WTFMove(ref));
+
+ auto aOut = set.take(&a);
+ ASSERT_TRUE(static_cast<bool>(aOut));
+ ASSERT_EQ(&a, aOut.value().ptr());
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ HashSet<Ref<RefLogger>> set;
+
+ RefLogger a("a");
+ Ref<RefLogger> ref(a);
+ set.add(WTFMove(ref));
+
+ auto aOut = set.takeAny();
+ ASSERT_TRUE(static_cast<bool>(aOut));
+ ASSERT_EQ(&a, aOut.value().ptr());
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ HashSet<Ref<RefLogger>> set;
+ auto emptyTake = set.takeAny();
+ ASSERT_FALSE(static_cast<bool>(emptyTake));
+ }
+
+ {
+ HashSet<Ref<RefLogger>> set;
+
+ RefLogger a("a");
+ Ref<RefLogger> ref(a);
+ set.add(WTFMove(ref));
+
+ ASSERT_TRUE(set.contains(&a));
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ HashSet<Ref<RefLogger>> set;
+ for (int i = 0; i < 64; ++i) {
+ Ref<RefLogger> ref = adoptRef(*new RefLogger("a"));
+ auto* pointer = ref.ptr();
+ set.add(WTFMove(ref));
+ ASSERT_TRUE(set.contains(pointer));
+ }
+ }
+ ASSERT_STREQ("deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_HashSet, DeletedAddressOfOperator)
+{
+ HashSet<DeletedAddressOfOperator> set1;
+ set1.add(10);
+
+ set1.remove(10);
}
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/LEBDecoder.cpp b/Tools/TestWebKitAPI/Tests/WTF/LEBDecoder.cpp
new file mode 100644
index 000000000..2141080c4
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/LEBDecoder.cpp
@@ -0,0 +1,241 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+#include <wtf/LEBDecoder.h>
+#include <wtf/Vector.h>
+
+namespace TestWebKitAPI {
+
+static void testUInt32LEBDecode(std::initializer_list<uint8_t> data, size_t startOffset, bool expectedStatus, uint32_t expectedResult, size_t expectedOffset)
+{
+ Vector<uint8_t> vector(data);
+ uint32_t result;
+ bool status = WTF::LEBDecoder::decodeUInt32(vector.data(), vector.size(), startOffset, result);
+ EXPECT_EQ(expectedStatus, status);
+ if (expectedStatus) {
+ EXPECT_EQ(expectedResult, result);
+ EXPECT_EQ(expectedOffset, startOffset);
+ }
+}
+
+TEST(WTF, LEBDecoderUInt32)
+{
+ // Simple tests that use all the bits in the array
+ testUInt32LEBDecode({ 0x07 }, 0, true, 0x7lu, 1lu);
+ testUInt32LEBDecode({ 0x77 }, 0, true, 0x77lu, 1lu);
+ testUInt32LEBDecode({ 0x80, 0x07 }, 0, true, 0x380lu, 2lu);
+ testUInt32LEBDecode({ 0x89, 0x12 }, 0, true, 0x909lu, 2lu);
+ testUInt32LEBDecode({ 0xf3, 0x85, 0x02 }, 0, true, 0x82f3lu, 3lu);
+ testUInt32LEBDecode({ 0xf3, 0x85, 0xff, 0x74 }, 0, true, 0xe9fc2f3lu, 4lu);
+ testUInt32LEBDecode({ 0xf3, 0x85, 0xff, 0xf4, 0x7f }, 0, true, 0xfe9fc2f3lu, 5lu);
+ // Test with extra trailing numbers
+ testUInt32LEBDecode({ 0x07, 0x80 }, 0, true, 0x7lu, 1lu);
+ testUInt32LEBDecode({ 0x07, 0x75 }, 0, true, 0x7lu, 1lu);
+ testUInt32LEBDecode({ 0xf3, 0x85, 0xff, 0x74, 0x43 }, 0, true, 0xe9fc2f3lu, 4lu);
+ testUInt32LEBDecode({ 0xf3, 0x85, 0xff, 0x74, 0x80 }, 0, true, 0xe9fc2f3lu, 4lu);
+ // Test with preceeding numbers
+ testUInt32LEBDecode({ 0xf3, 0x07 }, 1, true, 0x7lu, 2lu);
+ testUInt32LEBDecode({ 0x03, 0x07 }, 1, true, 0x7lu, 2lu);
+ testUInt32LEBDecode({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77 }, 5, true, 0x77lu, 6lu);
+ testUInt32LEBDecode({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77 }, 5, true, 0x77lu, 6ul);
+ testUInt32LEBDecode({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02 }, 3, true, 0x82f3lu, 6lu);
+ // Test in the middle
+ testUInt32LEBDecode({ 0xf3, 0x07, 0x89 }, 1, true, 0x7lu, 2lu);
+ testUInt32LEBDecode({ 0x03, 0x07, 0x23 }, 1, true, 0x7lu, 2lu);
+ testUInt32LEBDecode({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77, 0x43 }, 5, true, 0x77lu, 6lu);
+ testUInt32LEBDecode({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77, 0xf9 }, 5, true, 0x77lu, 6lu);
+ testUInt32LEBDecode({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02, 0xa4 }, 3, true, 0x82f3lu, 6lu);
+ // Test decode too long
+ testUInt32LEBDecode({ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, 0, false, 0x0lu, 0lu);
+ testUInt32LEBDecode({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff }, 1, false, 0x0lu, 0lu);
+ testUInt32LEBDecode({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff }, 0, false, 0x0lu, 0lu);
+ // Test decode off end of array
+ testUInt32LEBDecode({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff }, 2, false, 0x0lu, 0lu);
+}
+
+static void testUInt64LEBDecode(std::initializer_list<uint8_t> data, size_t startOffset, bool expectedStatus, uint64_t expectedResult, size_t expectedOffset)
+{
+ Vector<uint8_t> vector(data);
+ uint64_t result;
+ bool status = WTF::LEBDecoder::decodeUInt64(vector.data(), vector.size(), startOffset, result);
+ EXPECT_EQ(expectedStatus, status);
+ if (expectedStatus) {
+ EXPECT_EQ(expectedResult, result);
+ EXPECT_EQ(expectedOffset, startOffset);
+ }
+}
+
+TEST(WTF, LEBDecoderUInt64)
+{
+ // Simple tests that use all the bits in the array
+ testUInt64LEBDecode({ 0x07 }, 0, true, 0x7lu, 1lu);
+ testUInt64LEBDecode({ 0x77 }, 0, true, 0x77lu, 1lu);
+ testUInt64LEBDecode({ 0x80, 0x07 }, 0, true, 0x380lu, 2lu);
+ testUInt64LEBDecode({ 0x89, 0x12 }, 0, true, 0x909lu, 2lu);
+ testUInt64LEBDecode({ 0xf3, 0x85, 0x02 }, 0, true, 0x82f3lu, 3lu);
+ testUInt64LEBDecode({ 0xf3, 0x85, 0xff, 0x74 }, 0, true, 0xe9fc2f3lu, 4lu);
+ testUInt64LEBDecode({ 0xf3, 0x85, 0xff, 0xf4, 0x7f }, 0, true, 0x7fe9fc2f3lu, 5lu);
+ testUInt64LEBDecode({ 0xf3, 0x85, 0xff, 0xf4, 0xff, 0x4b }, 0, true, 0x25ffe9fc2f3lu, 6lu);
+ testUInt64LEBDecode({ 0xf3, 0x85, 0xff, 0xf4, 0xff, 0xcb, 0x3a }, 0, true, 0xea5ffe9fc2f3lu, 7lu);
+ testUInt64LEBDecode({ 0xf3, 0x85, 0xff, 0xf4, 0xff, 0xcb, 0xba, 0x0f }, 0, true, 0x1eea5ffe9fc2f3lu, 8lu);
+ testUInt64LEBDecode({ 0xf3, 0x85, 0xff, 0xf4, 0xff, 0xcb, 0xba, 0x8f, 0x69 }, 0, true, 0x691eea5ffe9fc2f3lu, 9lu);
+ testUInt64LEBDecode({ 0xf3, 0x85, 0xff, 0xf4, 0xff, 0xcb, 0xba, 0x8f, 0xe9, 0x01 }, 0, true, 0xe91eea5ffe9fc2f3lu, 10lu);
+ testUInt64LEBDecode({ 0xf3, 0x85, 0xff, 0xf4, 0xff, 0xcb, 0xba, 0x8f, 0xe9, 0x70 }, 0, true, 0x691eea5ffe9fc2f3lu, 10lu);
+ // Test with extra trailing numbers
+ testUInt64LEBDecode({ 0x07, 0x80 }, 0, true, 0x7lu, 1lu);
+ testUInt64LEBDecode({ 0x07, 0x75 }, 0, true, 0x7lu, 1lu);
+ testUInt64LEBDecode({ 0xf3, 0x85, 0xff, 0x74, 0x43 }, 0, true, 0xe9fc2f3lu, 4lu);
+ testUInt64LEBDecode({ 0xf3, 0x85, 0xff, 0x74, 0x80 }, 0, true, 0xe9fc2f3lu, 4lu);
+ testUInt64LEBDecode({ 0xf3, 0x85, 0xff, 0xf4, 0xff, 0xcb, 0xba, 0x8f, 0x69, 0x45 }, 0, true, 0x691eea5ffe9fc2f3lu, 9lu);
+ // Test with preceeding numbers
+ testUInt64LEBDecode({ 0xf3, 0x07 }, 1, true, 0x7lu, 2lu);
+ testUInt64LEBDecode({ 0x03, 0x07 }, 1, true, 0x7lu, 2lu);
+ testUInt64LEBDecode({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77 }, 5, true, 0x77lu, 6lu);
+ testUInt64LEBDecode({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77 }, 5, true, 0x77lu, 6ul);
+ testUInt64LEBDecode({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02 }, 3, true, 0x82f3lu, 6lu);
+ testUInt64LEBDecode({ 0x92, 0xf3, 0x85, 0xff, 0xf4, 0xff, 0xcb, 0xba, 0x8f, 0x69 }, 1, true, 0x691eea5ffe9fc2f3lu, 10lu);
+ // Test in the middle
+ testUInt64LEBDecode({ 0xf3, 0x07, 0x89 }, 1, true, 0x7lu, 2lu);
+ testUInt64LEBDecode({ 0x03, 0x07, 0x23 }, 1, true, 0x7lu, 2lu);
+ testUInt64LEBDecode({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77, 0x43 }, 5, true, 0x77lu, 6lu);
+ testUInt64LEBDecode({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77, 0xf9 }, 5, true, 0x77lu, 6lu);
+ testUInt64LEBDecode({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02, 0xa4 }, 3, true, 0x82f3lu, 6lu);
+ testUInt64LEBDecode({ 0x92, 0xf3, 0x85, 0xff, 0xf4, 0xff, 0xcb, 0xba, 0x8f, 0x69, 0x85, 0x75 }, 1, true, 0x691eea5ffe9fc2f3lu, 10lu);
+ testUInt64LEBDecode({ 0x92, 0x65, 0xf3, 0x85, 0xff, 0xf4, 0xff, 0xcb, 0xba, 0x8f, 0x69, 0x85, 0x75 }, 2, true, 0x691eea5ffe9fc2f3lu, 11lu);
+ // Test decode too long
+ testUInt64LEBDecode({ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, 0, false, 0x0lu, 0lu);
+ testUInt64LEBDecode({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xa3, 0x9f, 0xd2, 0xef, 0x8a, 0x4e }, 1, false, 0x0lu, 0lu);
+ testUInt64LEBDecode({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff, 0xef, 0xd8, 0xee, 0xaa, 0xbb }, 0, false, 0x0lu, 0lu);
+ testUInt64LEBDecode({ 0xf3, 0x85, 0xff, 0xf4, 0xff, 0xcb, 0xba, 0x8f, 0xa9, 0xa8, 0x05 }, 0, false, 0x0lu, 0lu);
+ // Test decode off end of array
+ testUInt64LEBDecode({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff }, 2, false, 0x0lu, 0lu);
+ testUInt64LEBDecode({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff }, 2, false, 0x0lu, 0lu);
+ testUInt64LEBDecode({ 0x92, 0xf3, 0x85, 0xff, 0xf4, 0xff, 0xcb, 0xba, 0x8f }, 1, false, 0x0lu, 0lu);
+}
+
+static void testInt32LEBDecode(std::initializer_list<uint8_t> data, size_t startOffset, bool expectedStatus, int32_t expectedResult, size_t expectedOffset)
+{
+ Vector<uint8_t> vector(data);
+ int32_t result;
+ bool status = WTF::LEBDecoder::decodeInt32(vector.data(), vector.size(), startOffset, result);
+ EXPECT_EQ(expectedStatus, status);
+ if (expectedStatus) {
+ EXPECT_EQ(expectedResult, result);
+ EXPECT_EQ(expectedOffset, startOffset);
+ }
+}
+
+TEST(WTF, LEBDecoderInt32)
+{
+ // Simple tests that use all the bits in the array
+ testInt32LEBDecode({ 0x07 }, 0, true, 0x7, 1lu);
+ testInt32LEBDecode({ 0x77 }, 0, true, -0x9, 1lu);
+ testInt32LEBDecode({ 0x80, 0x07 }, 0, true, 0x380, 2lu);
+ testInt32LEBDecode({ 0x89, 0x12 }, 0, true, 0x909, 2lu);
+ testInt32LEBDecode({ 0xf3, 0x85, 0x02 }, 0, true, 0x82f3, 3lu);
+ testInt32LEBDecode({ 0xf3, 0x85, 0xff, 0x74 }, 0, true, 0xfe9fc2f3, 4lu);
+ testInt32LEBDecode({ 0xf3, 0x85, 0xff, 0xf4, 0x7f }, 0, true, 0xfe9fc2f3, 5lu);
+ // Test with extra trailing numbers
+ testInt32LEBDecode({ 0x07, 0x80 }, 0, true, 0x7, 1lu);
+ testInt32LEBDecode({ 0x07, 0x75 }, 0, true, 0x7, 1lu);
+ testInt32LEBDecode({ 0xf3, 0x85, 0xff, 0x74, 0x43 }, 0, true, 0xfe9fc2f3, 4lu);
+ testInt32LEBDecode({ 0xf3, 0x85, 0xff, 0x74, 0x80 }, 0, true, 0xfe9fc2f3, 4lu);
+ // Test with preceeding numbers
+ testInt32LEBDecode({ 0xf3, 0x07 }, 1, true, 0x7, 2lu);
+ testInt32LEBDecode({ 0x03, 0x07 }, 1, true, 0x7, 2lu);
+ testInt32LEBDecode({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77 }, 5, true, -0x9, 6lu);
+ testInt32LEBDecode({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77 }, 5, true, -0x9, 6lu);
+ testInt32LEBDecode({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02 }, 3, true, 0x82f3, 6lu);
+ // Test in the middle
+ testInt32LEBDecode({ 0xf3, 0x07, 0x89 }, 1, true, 0x7, 2lu);
+ testInt32LEBDecode({ 0x03, 0x07, 0x23 }, 1, true, 0x7, 2lu);
+ testInt32LEBDecode({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77, 0x43 }, 5, true, -0x9, 6lu);
+ testInt32LEBDecode({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77, 0xf9 }, 5, true, -0x9, 6lu);
+ testInt32LEBDecode({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02, 0xa4 }, 3, true, 0x82f3, 6lu);
+ // Test decode too long
+ testInt32LEBDecode({ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, 0, false, 0x0, 0lu);
+ testInt32LEBDecode({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff }, 1, false, 0x0, 0lu);
+ testInt32LEBDecode({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff }, 0, false, 0x0, 0lu);
+ // Test decode off end of array
+ testInt32LEBDecode({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff }, 2, false, 0x0, 0lu);
+}
+
+static void testInt64LEBDecode(std::initializer_list<uint8_t> data, size_t startOffset, bool expectedStatus, int64_t expectedResult, size_t expectedOffset)
+{
+ Vector<uint8_t> vector(data);
+ int64_t result;
+ bool status = WTF::LEBDecoder::decodeInt64(vector.data(), vector.size(), startOffset, result);
+ EXPECT_EQ(expectedStatus, status);
+ if (expectedStatus) {
+ EXPECT_EQ(expectedResult, result);
+ EXPECT_EQ(expectedOffset, startOffset);
+ }
+}
+
+TEST(WTF, LEBDecoderInt64)
+{
+ // Simple tests that use all the bits in the array
+ testInt64LEBDecode({ 0x07 }, 0, true, 0x7, 1lu);
+ testInt64LEBDecode({ 0x77 }, 0, true, -0x9, 1lu);
+ testInt64LEBDecode({ 0x80, 0x07 }, 0, true, 0x380, 2lu);
+ testInt64LEBDecode({ 0x89, 0x12 }, 0, true, 0x909, 2lu);
+ testInt64LEBDecode({ 0xf3, 0x85, 0x02 }, 0, true, 0x82f3, 3lu);
+ testInt64LEBDecode({ 0xf3, 0x85, 0xff, 0x74 }, 0, true, 0xfffffffffe9fc2f3, 4lu);
+ testInt64LEBDecode({ 0xf3, 0x85, 0xff, 0xf4, 0x7f }, 0, true, 0xfffffffffe9fc2f3, 5lu);
+ testInt64LEBDecode({ 0xf3, 0x85, 0xff, 0xf4, 0x3f }, 0, true, 0x3fe9fc2f3, 5lu);
+ testInt64LEBDecode({ 0xf3, 0x85, 0xff, 0xf4, 0x8f, 0x1a }, 0, true, 0xd0fe9fc2f3, 6lu);
+ testInt64LEBDecode({ 0xf3, 0x85, 0xff, 0xf4, 0x8f, 0x9a, 0x80, 0x2a }, 0, true, 0x5400d0fe9fc2f3, 8lu);
+ testInt64LEBDecode({ 0xf3, 0x85, 0xff, 0xf4, 0x8f, 0x9a, 0x80, 0xaa, 0x41 }, 0, true, 0xc15400d0fe9fc2f3, 9lu);
+ testInt64LEBDecode({ 0xf3, 0x85, 0xff, 0xf4, 0x8f, 0x9a, 0x80, 0xaa, 0xc1, 0x01 }, 0, true, 0xc15400d0fe9fc2f3, 10lu);
+ testInt64LEBDecode({ 0xf3, 0x85, 0xff, 0xf4, 0x8f, 0x9a, 0x80, 0xaa, 0xc1, 0x62 }, 0, true, 0x415400d0fe9fc2f3, 10lu);
+ // Test with extra trailing numbers
+ testInt64LEBDecode({ 0x07, 0x80 }, 0, true, 0x7, 1lu);
+ testInt64LEBDecode({ 0x07, 0x75 }, 0, true, 0x7, 1lu);
+ testInt64LEBDecode({ 0xf3, 0x85, 0xff, 0x74, 0x43 }, 0, true, 0xfffffffffe9fc2f3, 4lu);
+ testInt64LEBDecode({ 0xf3, 0x85, 0xff, 0x74, 0x80 }, 0, true, 0xfffffffffe9fc2f3, 4lu);
+ // Test with preceeding numbers
+ testInt64LEBDecode({ 0xf3, 0x07 }, 1, true, 0x7, 2lu);
+ testInt64LEBDecode({ 0x03, 0x07 }, 1, true, 0x7, 2lu);
+ testInt64LEBDecode({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77 }, 5, true, -0x9, 6lu);
+ testInt64LEBDecode({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77 }, 5, true, -0x9, 6lu);
+ testInt64LEBDecode({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02 }, 3, true, 0x82f3, 6lu);
+ // Test in the middle
+ testInt64LEBDecode({ 0xf3, 0x07, 0x89 }, 1, true, 0x7, 2lu);
+ testInt64LEBDecode({ 0x03, 0x07, 0x23 }, 1, true, 0x7, 2lu);
+ testInt64LEBDecode({ 0xf2, 0x53, 0x43, 0x67, 0x79, 0x77, 0x43 }, 5, true, -0x9, 6lu);
+ testInt64LEBDecode({ 0xf2, 0x53, 0x43, 0xf7, 0x84, 0x77, 0xf9 }, 5, true, -0x9, 6lu);
+ testInt64LEBDecode({ 0xf2, 0x53, 0x43, 0xf3, 0x85, 0x02, 0xa4 }, 3, true, 0x82f3, 6lu);
+ // Test decode too long
+ testInt64LEBDecode({ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }, 0, false, 0x0, 0lu);
+ testInt64LEBDecode({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff }, 1, false, 0x0, 0lu);
+ testInt64LEBDecode({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff }, 0, false, 0x0, 0lu);
+ // Test decode off end of array
+ testInt64LEBDecode({ 0x80, 0x80, 0xab, 0x8a, 0x9a, 0xa3, 0xff }, 2, false, 0x0, 0lu);
+}
+
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/ListHashSet.cpp b/Tools/TestWebKitAPI/Tests/WTF/ListHashSet.cpp
index a550a845b..b97d866e7 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/ListHashSet.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/ListHashSet.cpp
@@ -78,7 +78,7 @@ TEST(WTF_ListHashSet, AppendOrMoveToLastNewItems)
result = list.appendOrMoveToLast(3);
ASSERT_TRUE(result.isNewEntry);
- ASSERT_EQ(list.size(), 3);
+ ASSERT_EQ(list.size(), 3u);
// The list should be in order 1, 2, 3.
ListHashSet<int>::iterator iterator = list.begin();
@@ -99,11 +99,11 @@ TEST(WTF_ListHashSet, AppendOrMoveToLastWithDuplicates)
ASSERT_TRUE(result.isNewEntry);
result = list.appendOrMoveToLast(1);
ASSERT_FALSE(result.isNewEntry);
- ASSERT_EQ(1, list.size());
+ ASSERT_EQ(1u, list.size());
list.add(2);
list.add(3);
- ASSERT_EQ(3, list.size());
+ ASSERT_EQ(3u, list.size());
// Appending 2 move it to the end.
ASSERT_EQ(3, list.last());
@@ -118,7 +118,7 @@ TEST(WTF_ListHashSet, AppendOrMoveToLastWithDuplicates)
ASSERT_FALSE(result.isNewEntry);
result = list.appendOrMoveToLast(1);
ASSERT_FALSE(result.isNewEntry);
- ASSERT_EQ(3, list.size());
+ ASSERT_EQ(3u, list.size());
ListHashSet<int>::iterator iterator = list.begin();
ASSERT_EQ(3, *iterator);
@@ -139,7 +139,7 @@ TEST(WTF_ListHashSet, PrependOrMoveToLastNewItems)
result = list.prependOrMoveToFirst(3);
ASSERT_TRUE(result.isNewEntry);
- ASSERT_EQ(list.size(), 3);
+ ASSERT_EQ(list.size(), 3u);
// The list should be in order 3, 1, 2.
ListHashSet<int>::iterator iterator = list.begin();
@@ -160,11 +160,11 @@ TEST(WTF_ListHashSet, PrependOrMoveToLastWithDuplicates)
ASSERT_TRUE(result.isNewEntry);
result = list.prependOrMoveToFirst(1);
ASSERT_FALSE(result.isNewEntry);
- ASSERT_EQ(1, list.size());
+ ASSERT_EQ(1u, list.size());
list.add(2);
list.add(3);
- ASSERT_EQ(3, list.size());
+ ASSERT_EQ(3u, list.size());
// Prepending 2 move it to the beginning.
ASSERT_EQ(1, list.first());
@@ -179,7 +179,7 @@ TEST(WTF_ListHashSet, PrependOrMoveToLastWithDuplicates)
ASSERT_FALSE(result.isNewEntry);
result = list.prependOrMoveToFirst(3);
ASSERT_FALSE(result.isNewEntry);
- ASSERT_EQ(3, list.size());
+ ASSERT_EQ(3u, list.size());
ListHashSet<int>::iterator iterator = list.begin();
ASSERT_EQ(3, *iterator);
@@ -266,4 +266,86 @@ TEST(WTF_ListHashSet, MoveOnly)
ASSERT_TRUE(list.isEmpty());
}
+TEST(WTF_ListHashSet, MoveConstructor)
+{
+ ListHashSet<int> list;
+ list.add(1);
+ list.add(2);
+ list.add(3);
+
+ ASSERT_EQ(3U, list.size());
+ auto iterator = list.begin();
+ ASSERT_EQ(1, *iterator);
+ ++iterator;
+ ASSERT_EQ(2, *iterator);
+ ++iterator;
+ ASSERT_EQ(3, *iterator);
+ ++iterator;
+
+ ListHashSet<int> list2(WTFMove(list));
+ ASSERT_EQ(3U, list2.size());
+ auto iterator2 = list2.begin();
+ ASSERT_EQ(1, *iterator2);
+ ++iterator2;
+ ASSERT_EQ(2, *iterator2);
+ ++iterator2;
+ ASSERT_EQ(3, *iterator2);
+ ++iterator2;
+
+ ASSERT_EQ(0U, list.size());
+ ASSERT_TRUE(list.begin() == list.end());
+ list.add(4);
+ list.add(5);
+ list.add(6);
+ iterator = list.begin();
+ ASSERT_EQ(4, *iterator);
+ ++iterator;
+ ASSERT_EQ(5, *iterator);
+ ++iterator;
+ ASSERT_EQ(6, *iterator);
+ ++iterator;
+}
+
+TEST(WTF_ListHashSet, MoveAssignment)
+{
+ ListHashSet<int> list;
+ list.add(1);
+ list.add(2);
+ list.add(3);
+
+ ASSERT_EQ(3U, list.size());
+ auto iterator = list.begin();
+ ASSERT_EQ(1, *iterator);
+ ++iterator;
+ ASSERT_EQ(2, *iterator);
+ ++iterator;
+ ASSERT_EQ(3, *iterator);
+ ++iterator;
+
+ ListHashSet<int> list2;
+ list2.add(10);
+ list2 = (WTFMove(list));
+ ASSERT_EQ(3U, list2.size());
+ auto iterator2 = list2.begin();
+ ASSERT_EQ(1, *iterator2);
+ ++iterator2;
+ ASSERT_EQ(2, *iterator2);
+ ++iterator2;
+ ASSERT_EQ(3, *iterator2);
+ ++iterator2;
+
+ ASSERT_EQ(0U, list.size());
+ ASSERT_TRUE(list.begin() == list.end());
+ list.add(4);
+ list.add(5);
+ list.add(6);
+ iterator = list.begin();
+ ASSERT_EQ(4, *iterator);
+ ++iterator;
+ ASSERT_EQ(5, *iterator);
+ ++iterator;
+ ASSERT_EQ(6, *iterator);
+ ++iterator;
+}
+
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/Lock.cpp b/Tools/TestWebKitAPI/Tests/WTF/Lock.cpp
new file mode 100644
index 000000000..5576302d6
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/Lock.cpp
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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.
+ */
+
+#include "config.h"
+#include <wtf/Lock.h>
+#include <wtf/Threading.h>
+#include <wtf/ThreadingPrimitives.h>
+#include <wtf/WordLock.h>
+
+using namespace WTF;
+
+namespace TestWebKitAPI {
+
+struct LockInspector {
+ template<typename LockType>
+ static bool isFullyReset(LockType& lock)
+ {
+ return lock.isFullyReset();
+ }
+};
+
+template<typename LockType>
+void runLockTest(unsigned numThreadGroups, unsigned numThreadsPerGroup, unsigned workPerCriticalSection, unsigned numIterations)
+{
+ std::unique_ptr<LockType[]> locks = std::make_unique<LockType[]>(numThreadGroups);
+ std::unique_ptr<double[]> words = std::make_unique<double[]>(numThreadGroups);
+ std::unique_ptr<ThreadIdentifier[]> threads = std::make_unique<ThreadIdentifier[]>(numThreadGroups * numThreadsPerGroup);
+
+ for (unsigned threadGroupIndex = numThreadGroups; threadGroupIndex--;) {
+ words[threadGroupIndex] = 0;
+
+ for (unsigned threadIndex = numThreadsPerGroup; threadIndex--;) {
+ threads[threadGroupIndex * numThreadsPerGroup + threadIndex] = createThread(
+ "Lock test thread",
+ [threadGroupIndex, &locks, &words, numIterations, workPerCriticalSection] () {
+ for (unsigned i = numIterations; i--;) {
+ locks[threadGroupIndex].lock();
+ for (unsigned j = workPerCriticalSection; j--;)
+ words[threadGroupIndex]++;
+ locks[threadGroupIndex].unlock();
+ }
+ });
+ }
+ }
+
+ for (unsigned threadIndex = numThreadGroups * numThreadsPerGroup; threadIndex--;)
+ waitForThreadCompletion(threads[threadIndex]);
+
+ double expected = 0;
+ for (uint64_t i = static_cast<uint64_t>(numIterations) * workPerCriticalSection * numThreadsPerGroup; i--;)
+ expected++;
+
+ for (unsigned threadGroupIndex = numThreadGroups; threadGroupIndex--;)
+ EXPECT_EQ(expected, words[threadGroupIndex]);
+
+ // Now test that the locks correctly reset themselves. We expect that if a single thread locks
+ // each of the locks twice in a row, then the lock should be in a pristine state.
+ for (unsigned threadGroupIndex = numThreadGroups; threadGroupIndex--;) {
+ for (unsigned i = 2; i--;) {
+ locks[threadGroupIndex].lock();
+ locks[threadGroupIndex].unlock();
+ }
+
+ EXPECT_EQ(true, LockInspector::isFullyReset(locks[threadGroupIndex]));
+ }
+}
+
+bool skipSlow()
+{
+#if PLATFORM(WIN) && !defined(NDEBUG)
+ return true;
+#else
+ return false;
+#endif
+}
+
+TEST(WTF_WordLock, UncontendedShortSection)
+{
+ runLockTest<WordLock>(1, 1, 1, 10000000);
+}
+
+TEST(WTF_WordLock, UncontendedLongSection)
+{
+ runLockTest<WordLock>(1, 1, 10000, 1000);
+}
+
+TEST(WTF_WordLock, ContendedShortSection)
+{
+ if (skipSlow())
+ return;
+ runLockTest<WordLock>(1, 10, 1, 5000000);
+}
+
+TEST(WTF_WordLock, ContendedLongSection)
+{
+ if (skipSlow())
+ return;
+ runLockTest<WordLock>(1, 10, 10000, 10000);
+}
+
+TEST(WTF_WordLock, ManyContendedShortSections)
+{
+ if (skipSlow())
+ return;
+ runLockTest<WordLock>(10, 10, 1, 500000);
+}
+
+TEST(WTF_WordLock, ManyContendedLongSections)
+{
+ if (skipSlow())
+ return;
+ runLockTest<WordLock>(10, 10, 10000, 500);
+}
+
+TEST(WTF_Lock, UncontendedShortSection)
+{
+ runLockTest<Lock>(1, 1, 1, 10000000);
+}
+
+TEST(WTF_Lock, UncontendedLongSection)
+{
+ runLockTest<Lock>(1, 1, 10000, 1000);
+}
+
+TEST(WTF_Lock, ContendedShortSection)
+{
+ if (skipSlow())
+ return;
+ runLockTest<Lock>(1, 10, 1, 10000000);
+}
+
+TEST(WTF_Lock, ContendedLongSection)
+{
+ if (skipSlow())
+ return;
+ runLockTest<Lock>(1, 10, 10000, 10000);
+}
+
+TEST(WTF_Lock, ManyContendedShortSections)
+{
+ if (skipSlow())
+ return;
+ runLockTest<Lock>(10, 10, 1, 500000);
+}
+
+TEST(WTF_Lock, ManyContendedLongSections)
+{
+ if (skipSlow())
+ return;
+ runLockTest<Lock>(10, 10, 10000, 1000);
+}
+
+TEST(WTF_Lock, ManyContendedLongerSections)
+{
+ if (skipSlow())
+ return;
+ runLockTest<Lock>(10, 10, 100000, 1);
+}
+
+TEST(WTF_Lock, SectionAddressCollision)
+{
+ if (skipSlow())
+ return;
+ runLockTest<Lock>(4, 2, 10000, 2000);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp b/Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp
index 8e9b178af..ac8bb1c3a 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp
@@ -10,7 +10,7 @@
* 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
+ * 3. Neither the name of Apple 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.
*
@@ -26,24 +26,14 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#define _USE_MATH_DEFINES 1
#include "config.h"
+#include <limits>
+#include <wtf/MathExtras.h>
#include <wtf/MediaTime.h>
using namespace std;
-#if COMPILER(MSVC)
-// Work around Visual Studio 2008's lack of an INFINITY or NAN definition.
-#include <limits>
-#if !defined(INFINITY)
-#define INFINITY (numeric_limits<double>::infinity())
-#endif
-#if !defined(NAN)
-#define NAN (numeric_limits<double>::quiet_NaN())
-#endif
-#endif
-
namespace WTF {
std::ostream& operator<<(std::ostream& out, const MediaTime& val)
@@ -55,6 +45,8 @@ std::ostream& operator<<(std::ostream& out, const MediaTime& val)
out << "+infinite";
else if (val.isNegativeInfinite())
out << "-infinite";
+ else if (val.hasDoubleValue())
+ out << "double: " << val.toDouble();
else
out << "value: " << val.timeValue() << ", scale: " << val.timeScale();
return out << " }";
@@ -93,6 +85,8 @@ TEST(WTF, MediaTime)
EXPECT_EQ(MediaTime(1, 1) != MediaTime(2, 1), true);
EXPECT_EQ(MediaTime(2, 1) == MediaTime(2, 1), true);
EXPECT_EQ(MediaTime(2, 1) == MediaTime(4, 2), true);
+ EXPECT_TRUE((bool)MediaTime(1, 1));
+ EXPECT_TRUE(!MediaTime(0, 1));
// Addition Operators
EXPECT_EQ(MediaTime::positiveInfiniteTime() + MediaTime::positiveInfiniteTime(), MediaTime::positiveInfiniteTime());
@@ -166,8 +160,6 @@ TEST(WTF, MediaTime)
EXPECT_EQ(abs(MediaTime::invalidTime()), MediaTime::invalidTime());
EXPECT_EQ(abs(MediaTime(1, 1)), MediaTime(1, 1));
EXPECT_EQ(abs(MediaTime(-1, 1)), MediaTime(1, 1));
- EXPECT_EQ(abs(MediaTime(-1, -1)), MediaTime(-1, -1));
- EXPECT_EQ(abs(MediaTime(1, -1)), MediaTime(-1, -1));
// Floating Point Functions
EXPECT_EQ(MediaTime::createWithFloat(1.0f), MediaTime(1, 1));
@@ -180,25 +172,42 @@ TEST(WTF, MediaTime)
EXPECT_EQ(MediaTime(3, 2).toDouble(), 1.5);
EXPECT_EQ(MediaTime(1, 1 << 16).toFloat(), 1 / pow(2.0f, 16.0f));
EXPECT_EQ(MediaTime(1, 1 << 30).toDouble(), 1 / pow(2.0, 30.0));
- EXPECT_EQ(MediaTime::createWithDouble(M_PI, 1 << 30), MediaTime(3373259426U, 1 << 30));
- EXPECT_EQ(MediaTime::createWithFloat(INFINITY), MediaTime::positiveInfiniteTime());
- EXPECT_EQ(MediaTime::createWithFloat(-INFINITY), MediaTime::negativeInfiniteTime());
- EXPECT_EQ(MediaTime::createWithFloat(NAN), MediaTime::invalidTime());
- EXPECT_EQ(MediaTime::createWithDouble(INFINITY), MediaTime::positiveInfiniteTime());
- EXPECT_EQ(MediaTime::createWithDouble(-INFINITY), MediaTime::negativeInfiniteTime());
- EXPECT_EQ(MediaTime::createWithDouble(NAN), MediaTime::invalidTime());
+ EXPECT_EQ(MediaTime::createWithDouble(piDouble, 1 << 30), MediaTime(3373259426U, 1 << 30));
+
+ EXPECT_EQ(MediaTime::createWithFloat(std::numeric_limits<float>::infinity()), MediaTime::positiveInfiniteTime());
+ EXPECT_EQ(MediaTime::createWithFloat(-std::numeric_limits<float>::infinity()), MediaTime::negativeInfiniteTime());
+ EXPECT_EQ(MediaTime::createWithFloat(std::numeric_limits<float>::quiet_NaN()), MediaTime::invalidTime());
+
+ EXPECT_EQ(MediaTime::createWithDouble(std::numeric_limits<double>::infinity()), MediaTime::positiveInfiniteTime());
+ EXPECT_EQ(MediaTime::createWithDouble(-std::numeric_limits<double>::infinity()), MediaTime::negativeInfiniteTime());
+ EXPECT_EQ(MediaTime::createWithDouble(std::numeric_limits<double>::quiet_NaN()), MediaTime::invalidTime());
+
+ // Floating Point Round Trip
+ EXPECT_EQ(10.0123456789f, MediaTime::createWithFloat(10.0123456789f).toFloat());
+ EXPECT_EQ(10.0123456789, MediaTime::createWithDouble(10.0123456789).toDouble());
+ EXPECT_EQ(MediaTime(1, 3), MediaTime::createWithDouble(MediaTime(1, 3).toDouble()));
+
+ // Floating Point Math
+ EXPECT_EQ(1.5 + 3.3, (MediaTime::createWithDouble(1.5) + MediaTime::createWithDouble(3.3)).toDouble());
+ EXPECT_EQ(1.5 - 3.3, (MediaTime::createWithDouble(1.5) - MediaTime::createWithDouble(3.3)).toDouble());
+ EXPECT_EQ(-3.3, (-MediaTime::createWithDouble(3.3)).toDouble());
+ EXPECT_EQ(3.3 * 2, (MediaTime::createWithDouble(3.3) * 2).toDouble());
+
+ // Floating Point and non-Floating Point math
+ EXPECT_EQ(2.0, (MediaTime::createWithDouble(1.5) + MediaTime(1, 2)).toDouble());
+ EXPECT_EQ(1.0, (MediaTime::createWithDouble(1.5) - MediaTime(1, 2)).toDouble());
// Overflow Behavior
EXPECT_EQ(MediaTime::createWithFloat(pow(2.0f, 64.0f)), MediaTime::positiveInfiniteTime());
EXPECT_EQ(MediaTime::createWithFloat(-pow(2.0f, 64.0f)), MediaTime::negativeInfiniteTime());
- EXPECT_EQ(MediaTime::createWithFloat(pow(2.0f, 63.0f), 2).timeScale(), 1);
- EXPECT_EQ(MediaTime::createWithFloat(pow(2.0f, 63.0f), 3).timeScale(), 1);
+ EXPECT_EQ(MediaTime::createWithFloat(pow(2.0f, 63.0f), 2).timeScale(), 1U);
+ EXPECT_EQ(MediaTime::createWithFloat(pow(2.0f, 63.0f), 3).timeScale(), 1U);
EXPECT_EQ(MediaTime::createWithDouble(pow(2.0, 64.0)), MediaTime::positiveInfiniteTime());
EXPECT_EQ(MediaTime::createWithDouble(-pow(2.0, 64.0)), MediaTime::negativeInfiniteTime());
- EXPECT_EQ(MediaTime::createWithDouble(pow(2.0, 63.0), 2).timeScale(), 1);
- EXPECT_EQ(MediaTime::createWithDouble(pow(2.0, 63.0), 3).timeScale(), 1);
- EXPECT_EQ((MediaTime(numeric_limits<int64_t>::max(), 2) + MediaTime(numeric_limits<int64_t>::max(), 2)).timeScale(), 1);
- EXPECT_EQ((MediaTime(numeric_limits<int64_t>::min(), 2) - MediaTime(numeric_limits<int64_t>::max(), 2)).timeScale(), 1);
+ EXPECT_EQ(MediaTime::createWithDouble(pow(2.0, 63.0), 2).timeScale(), 1U);
+ EXPECT_EQ(MediaTime::createWithDouble(pow(2.0, 63.0), 3).timeScale(), 1U);
+ EXPECT_EQ((MediaTime(numeric_limits<int64_t>::max(), 2) + MediaTime(numeric_limits<int64_t>::max(), 2)).timeScale(), 1U);
+ EXPECT_EQ((MediaTime(numeric_limits<int64_t>::min(), 2) - MediaTime(numeric_limits<int64_t>::max(), 2)).timeScale(), 1U);
EXPECT_EQ(MediaTime(numeric_limits<int64_t>::max(), 1) + MediaTime(numeric_limits<int64_t>::max(), 1), MediaTime::positiveInfiniteTime());
EXPECT_EQ(MediaTime(numeric_limits<int64_t>::min(), 1) + MediaTime(numeric_limits<int64_t>::min(), 1), MediaTime::negativeInfiniteTime());
EXPECT_EQ(MediaTime(numeric_limits<int64_t>::min(), 1) - MediaTime(numeric_limits<int64_t>::max(), 1), MediaTime::negativeInfiniteTime());
diff --git a/Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp b/Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp
index 61c16d1ab..59af4f849 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp
@@ -10,7 +10,7 @@
* 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
+ * 3. Neither the name of Apple 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.
*
@@ -31,6 +31,10 @@
#include <wtf/MetaAllocator.h>
#include <wtf/Vector.h>
+#if OS(WINDOWS)
+#undef small
+#endif
+
using namespace WTF;
namespace TestWebKitAPI {
diff --git a/Tools/TestWebKitAPI/Tests/WTF/NakedPtr.cpp b/Tools/TestWebKitAPI/Tests/WTF/NakedPtr.cpp
new file mode 100644
index 000000000..f4b4836cd
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/NakedPtr.cpp
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include "config.h"
+
+#include "RefLogger.h"
+#include <wtf/NakedPtr.h>
+
+namespace TestWebKitAPI {
+
+// For these tests, we need a base class and a derived class. For this purpose,
+// we reuse the RefLogger and DerivedRefLogger classes.
+
+TEST(WTF_NakedPtr, Basic)
+{
+ DerivedRefLogger a("a");
+
+ NakedPtr<RefLogger> empty;
+ ASSERT_EQ(nullptr, empty.get());
+
+ {
+ NakedPtr<RefLogger> ptr(&a);
+ ASSERT_EQ(&a, ptr.get());
+ ASSERT_EQ(&a, &*ptr);
+ ASSERT_EQ(&a.name, &ptr->name);
+ }
+
+ {
+ NakedPtr<RefLogger> ptr = &a;
+ ASSERT_EQ(&a, ptr.get());
+ }
+
+ {
+ NakedPtr<RefLogger> p1 = &a;
+ NakedPtr<RefLogger> p2(p1);
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&a, p2.get());
+ }
+
+ {
+ NakedPtr<RefLogger> p1 = &a;
+ NakedPtr<RefLogger> p2 = p1;
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&a, p2.get());
+ }
+
+ {
+ NakedPtr<RefLogger> p1 = &a;
+ NakedPtr<RefLogger> p2 = WTFMove(p1);
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&a, p2.get());
+ }
+
+ {
+ NakedPtr<RefLogger> p1 = &a;
+ NakedPtr<RefLogger> p2(WTFMove(p1));
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&a, p2.get());
+ }
+
+ {
+ NakedPtr<DerivedRefLogger> p1 = &a;
+ NakedPtr<RefLogger> p2 = p1;
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&a, p2.get());
+ }
+
+ {
+ NakedPtr<DerivedRefLogger> p1 = &a;
+ NakedPtr<RefLogger> p2 = WTFMove(p1);
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&a, p2.get());
+ }
+
+ {
+ NakedPtr<RefLogger> ptr(&a);
+ ASSERT_EQ(&a, ptr.get());
+ ptr.clear();
+ ASSERT_EQ(nullptr, ptr.get());
+ }
+}
+
+TEST(WTF_NakedPtr, Assignment)
+{
+ DerivedRefLogger a("a");
+ RefLogger b("b");
+ DerivedRefLogger c("c");
+
+ {
+ NakedPtr<RefLogger> p1(&a);
+ NakedPtr<RefLogger> p2(&b);
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&b, p2.get());
+ p1 = p2;
+ ASSERT_EQ(&b, p1.get());
+ ASSERT_EQ(&b, p2.get());
+ }
+
+ {
+ NakedPtr<RefLogger> ptr(&a);
+ ASSERT_EQ(&a, ptr.get());
+ ptr = &b;
+ ASSERT_EQ(&b, ptr.get());
+ }
+
+ {
+ NakedPtr<RefLogger> ptr(&a);
+ ASSERT_EQ(&a, ptr.get());
+ ptr = nullptr;
+ ASSERT_EQ(nullptr, ptr.get());
+ }
+
+ {
+ NakedPtr<RefLogger> p1(&a);
+ NakedPtr<RefLogger> p2(&b);
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&b, p2.get());
+ p1 = WTFMove(p2);
+ ASSERT_EQ(&b, p1.get());
+ ASSERT_EQ(&b, p2.get());
+ }
+
+ {
+ NakedPtr<RefLogger> p1(&a);
+ NakedPtr<DerivedRefLogger> p2(&c);
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&c, p2.get());
+ p1 = p2;
+ ASSERT_EQ(&c, p1.get());
+ ASSERT_EQ(&c, p2.get());
+ }
+
+ {
+ NakedPtr<RefLogger> ptr(&a);
+ ASSERT_EQ(&a, ptr.get());
+ ptr = &c;
+ ASSERT_EQ(&c, ptr.get());
+ }
+
+ {
+ NakedPtr<RefLogger> p1(&a);
+ NakedPtr<DerivedRefLogger> p2(&c);
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&c, p2.get());
+ p1 = WTFMove(p2);
+ ASSERT_EQ(&c, p1.get());
+ ASSERT_EQ(&c, p2.get());
+ }
+
+ {
+ NakedPtr<RefLogger> ptr(&a);
+ ASSERT_EQ(&a, ptr.get());
+ ptr = ptr;
+ ASSERT_EQ(&a, ptr.get());
+ }
+
+ {
+ NakedPtr<RefLogger> ptr(&a);
+ ASSERT_EQ(&a, ptr.get());
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wself-move"
+#endif
+ ptr = WTFMove(ptr);
+#if COMPILER(CLANG)
+#pragma clang diagnostic pop
+#endif
+ ASSERT_EQ(&a, ptr.get());
+ }
+}
+
+TEST(WTF_NakedPtr, Swap)
+{
+ RefLogger a("a");
+ RefLogger b("b");
+
+ {
+ NakedPtr<RefLogger> p1(&a);
+ NakedPtr<RefLogger> p2(&b);
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&b, p2.get());
+ p1.swap(p2);
+ ASSERT_EQ(&b, p1.get());
+ ASSERT_EQ(&a, p2.get());
+ }
+
+ {
+ NakedPtr<RefLogger> p1(&a);
+ NakedPtr<RefLogger> p2(&b);
+ ASSERT_EQ(&a, p1.get());
+ ASSERT_EQ(&b, p2.get());
+ std::swap(p1, p2);
+ ASSERT_EQ(&b, p1.get());
+ ASSERT_EQ(&a, p2.get());
+ }
+}
+
+NakedPtr<RefLogger> nakedPtrFoo(RefLogger& logger)
+{
+ return NakedPtr<RefLogger>(&logger);
+}
+
+TEST(WTF_NakedPtr, ReturnValue)
+{
+ DerivedRefLogger a("a");
+
+ {
+ auto ptr = nakedPtrFoo(a);
+ ASSERT_EQ(&a, ptr.get());
+ ASSERT_EQ(&a, &*ptr);
+ ASSERT_EQ(&a.name, &ptr->name);
+ }
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/OptionSet.cpp b/Tools/TestWebKitAPI/Tests/WTF/OptionSet.cpp
new file mode 100644
index 000000000..f0173831b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/OptionSet.cpp
@@ -0,0 +1,297 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include "Test.h"
+#include <wtf/OptionSet.h>
+
+namespace TestWebKitAPI {
+
+enum class ExampleFlags : uint64_t {
+ A = 1 << 0,
+ B = 1 << 1,
+ C = 1 << 2,
+ D = 1ULL << 31,
+ E = 1ULL << 63,
+};
+
+TEST(WTF_OptionSet, EmptySet)
+{
+ OptionSet<ExampleFlags> set;
+ EXPECT_TRUE(set.isEmpty());
+ EXPECT_FALSE(set.contains(ExampleFlags::A));
+ EXPECT_FALSE(set.contains(ExampleFlags::B));
+ EXPECT_FALSE(set.contains(ExampleFlags::C));
+ EXPECT_FALSE(set.contains(ExampleFlags::D));
+ EXPECT_FALSE(set.contains(ExampleFlags::E));
+}
+
+TEST(WTF_OptionSet, ContainsOneFlag)
+{
+ OptionSet<ExampleFlags> set = ExampleFlags::A;
+ EXPECT_FALSE(set.isEmpty());
+ EXPECT_TRUE(set.contains(ExampleFlags::A));
+ EXPECT_FALSE(set.contains(ExampleFlags::B));
+ EXPECT_FALSE(set.contains(ExampleFlags::C));
+ EXPECT_FALSE(set.contains(ExampleFlags::D));
+ EXPECT_FALSE(set.contains(ExampleFlags::E));
+}
+
+TEST(WTF_OptionSet, Equal)
+{
+ OptionSet<ExampleFlags> set { ExampleFlags::A, ExampleFlags::B };
+
+ EXPECT_TRUE((set == OptionSet<ExampleFlags> { ExampleFlags::A, ExampleFlags::B }));
+ EXPECT_TRUE((set == OptionSet<ExampleFlags> { ExampleFlags::B, ExampleFlags::A }));
+ EXPECT_FALSE(set == ExampleFlags::B);
+}
+
+TEST(WTF_OptionSet, NotEqual)
+{
+ OptionSet<ExampleFlags> set = ExampleFlags::A;
+
+ EXPECT_TRUE(set != ExampleFlags::B);
+ EXPECT_FALSE(set != ExampleFlags::A);
+}
+
+TEST(WTF_OptionSet, Minus)
+{
+ OptionSet<ExampleFlags> set { ExampleFlags::A, ExampleFlags::B, ExampleFlags::C };
+
+ EXPECT_TRUE(((set - ExampleFlags::A) == OptionSet<ExampleFlags> { ExampleFlags::B, ExampleFlags::C }));
+ EXPECT_TRUE(((set - ExampleFlags::D) == OptionSet<ExampleFlags> { ExampleFlags::A, ExampleFlags::B, ExampleFlags::C }));
+ EXPECT_TRUE((set - set).isEmpty());
+}
+
+TEST(WTF_OptionSet, ContainsTwoFlags)
+{
+ OptionSet<ExampleFlags> set { ExampleFlags::A, ExampleFlags::B };
+ EXPECT_FALSE(set.isEmpty());
+ EXPECT_TRUE(set.contains(ExampleFlags::A));
+ EXPECT_TRUE(set.contains(ExampleFlags::B));
+ EXPECT_FALSE(set.contains(ExampleFlags::C));
+ EXPECT_FALSE(set.contains(ExampleFlags::D));
+ EXPECT_FALSE(set.contains(ExampleFlags::E));
+}
+
+TEST(WTF_OptionSet, ContainsTwoFlags2)
+{
+ OptionSet<ExampleFlags> set { ExampleFlags::A, ExampleFlags::D };
+ EXPECT_FALSE(set.isEmpty());
+ EXPECT_TRUE(set.contains(ExampleFlags::A));
+ EXPECT_TRUE(set.contains(ExampleFlags::D));
+ EXPECT_FALSE(set.contains(ExampleFlags::B));
+ EXPECT_FALSE(set.contains(ExampleFlags::C));
+ EXPECT_FALSE(set.contains(ExampleFlags::E));
+}
+
+TEST(WTF_OptionSet, ContainsTwoFlags3)
+{
+ OptionSet<ExampleFlags> set { ExampleFlags::D, ExampleFlags::E };
+ EXPECT_FALSE(set.isEmpty());
+ EXPECT_TRUE(set.contains(ExampleFlags::D));
+ EXPECT_TRUE(set.contains(ExampleFlags::E));
+ EXPECT_FALSE(set.contains(ExampleFlags::A));
+ EXPECT_FALSE(set.contains(ExampleFlags::B));
+ EXPECT_FALSE(set.contains(ExampleFlags::C));
+}
+
+TEST(WTF_OptionSet, OperatorBitwiseOr)
+{
+ OptionSet<ExampleFlags> set = ExampleFlags::A;
+ set |= ExampleFlags::C;
+ EXPECT_TRUE(set.contains(ExampleFlags::A));
+ EXPECT_FALSE(set.contains(ExampleFlags::B));
+ EXPECT_TRUE(set.contains(ExampleFlags::C));
+}
+
+TEST(WTF_OptionSet, EmptyOptionSetToRawValueToOptionSet)
+{
+ OptionSet<ExampleFlags> set;
+ EXPECT_TRUE(set.isEmpty());
+ EXPECT_FALSE(set.contains(ExampleFlags::A));
+ EXPECT_FALSE(set.contains(ExampleFlags::B));
+ EXPECT_FALSE(set.contains(ExampleFlags::C));
+
+ auto set2 = OptionSet<ExampleFlags>::fromRaw(set.toRaw());
+ EXPECT_TRUE(set2.isEmpty());
+ EXPECT_FALSE(set2.contains(ExampleFlags::A));
+ EXPECT_FALSE(set2.contains(ExampleFlags::B));
+ EXPECT_FALSE(set2.contains(ExampleFlags::C));
+}
+
+TEST(WTF_OptionSet, OptionSetThatContainsOneFlagToRawValueToOptionSet)
+{
+ OptionSet<ExampleFlags> set = ExampleFlags::A;
+ EXPECT_FALSE(set.isEmpty());
+ EXPECT_TRUE(set.contains(ExampleFlags::A));
+ EXPECT_FALSE(set.contains(ExampleFlags::B));
+ EXPECT_FALSE(set.contains(ExampleFlags::C));
+ EXPECT_FALSE(set.contains(ExampleFlags::D));
+ EXPECT_FALSE(set.contains(ExampleFlags::E));
+
+ auto set2 = OptionSet<ExampleFlags>::fromRaw(set.toRaw());
+ EXPECT_FALSE(set2.isEmpty());
+ EXPECT_TRUE(set2.contains(ExampleFlags::A));
+ EXPECT_FALSE(set2.contains(ExampleFlags::B));
+ EXPECT_FALSE(set2.contains(ExampleFlags::C));
+ EXPECT_FALSE(set2.contains(ExampleFlags::D));
+ EXPECT_FALSE(set2.contains(ExampleFlags::E));
+}
+
+TEST(WTF_OptionSet, OptionSetThatContainsOneFlagToRawValueToOptionSet2)
+{
+ OptionSet<ExampleFlags> set = ExampleFlags::E;
+ EXPECT_FALSE(set.isEmpty());
+ EXPECT_TRUE(set.contains(ExampleFlags::E));
+ EXPECT_FALSE(set.contains(ExampleFlags::A));
+ EXPECT_FALSE(set.contains(ExampleFlags::B));
+ EXPECT_FALSE(set.contains(ExampleFlags::C));
+ EXPECT_FALSE(set.contains(ExampleFlags::D));
+
+ auto set2 = OptionSet<ExampleFlags>::fromRaw(set.toRaw());
+ EXPECT_FALSE(set2.isEmpty());
+ EXPECT_TRUE(set2.contains(ExampleFlags::E));
+ EXPECT_FALSE(set2.contains(ExampleFlags::A));
+ EXPECT_FALSE(set2.contains(ExampleFlags::B));
+ EXPECT_FALSE(set2.contains(ExampleFlags::C));
+ EXPECT_FALSE(set2.contains(ExampleFlags::D));
+}
+
+TEST(WTF_OptionSet, OptionSetThatContainsTwoFlagsToRawValueToOptionSet)
+{
+ OptionSet<ExampleFlags> set { ExampleFlags::A, ExampleFlags::C };
+ EXPECT_FALSE(set.isEmpty());
+ EXPECT_TRUE(set.contains(ExampleFlags::A));
+ EXPECT_TRUE(set.contains(ExampleFlags::C));
+ EXPECT_FALSE(set.contains(ExampleFlags::B));
+
+ auto set2 = OptionSet<ExampleFlags>::fromRaw(set.toRaw());
+ EXPECT_FALSE(set2.isEmpty());
+ EXPECT_TRUE(set2.contains(ExampleFlags::A));
+ EXPECT_TRUE(set2.contains(ExampleFlags::C));
+ EXPECT_FALSE(set2.contains(ExampleFlags::B));
+}
+
+TEST(WTF_OptionSet, OptionSetThatContainsTwoFlagsToRawValueToOptionSet2)
+{
+ OptionSet<ExampleFlags> set { ExampleFlags::D, ExampleFlags::E };
+ EXPECT_FALSE(set.isEmpty());
+ EXPECT_TRUE(set.contains(ExampleFlags::D));
+ EXPECT_TRUE(set.contains(ExampleFlags::E));
+ EXPECT_FALSE(set.contains(ExampleFlags::A));
+ EXPECT_FALSE(set.contains(ExampleFlags::B));
+ EXPECT_FALSE(set.contains(ExampleFlags::C));
+
+ auto set2 = OptionSet<ExampleFlags>::fromRaw(set.toRaw());
+ EXPECT_FALSE(set2.isEmpty());
+ EXPECT_TRUE(set2.contains(ExampleFlags::D));
+ EXPECT_TRUE(set2.contains(ExampleFlags::E));
+ EXPECT_FALSE(set2.contains(ExampleFlags::A));
+ EXPECT_FALSE(set2.contains(ExampleFlags::B));
+ EXPECT_FALSE(set2.contains(ExampleFlags::C));
+}
+
+TEST(WTF_OptionSet, TwoIteratorsIntoSameOptionSet)
+{
+ OptionSet<ExampleFlags> set { ExampleFlags::C, ExampleFlags::B };
+ OptionSet<ExampleFlags>::iterator it1 = set.begin();
+ OptionSet<ExampleFlags>::iterator it2 = it1;
+ ++it1;
+ EXPECT_STRONG_ENUM_EQ(ExampleFlags::C, *it1);
+ EXPECT_STRONG_ENUM_EQ(ExampleFlags::B, *it2);
+}
+
+TEST(WTF_OptionSet, IterateOverOptionSetThatContainsTwoFlags)
+{
+ OptionSet<ExampleFlags> set { ExampleFlags::A, ExampleFlags::C };
+ OptionSet<ExampleFlags>::iterator it = set.begin();
+ OptionSet<ExampleFlags>::iterator end = set.end();
+ EXPECT_TRUE(it != end);
+ EXPECT_STRONG_ENUM_EQ(ExampleFlags::A, *it);
+ ++it;
+ EXPECT_STRONG_ENUM_EQ(ExampleFlags::C, *it);
+ ++it;
+ EXPECT_TRUE(it == end);
+}
+
+TEST(WTF_OptionSet, IterateOverOptionSetThatContainsFlags2)
+{
+ OptionSet<ExampleFlags> set { ExampleFlags::D, ExampleFlags::E };
+ OptionSet<ExampleFlags>::iterator it = set.begin();
+ OptionSet<ExampleFlags>::iterator end = set.end();
+ EXPECT_TRUE(it != end);
+ EXPECT_STRONG_ENUM_EQ(ExampleFlags::D, *it);
+ ++it;
+ EXPECT_STRONG_ENUM_EQ(ExampleFlags::E, *it);
+ ++it;
+ EXPECT_TRUE(it == end);
+}
+
+TEST(WTF_OptionSet, NextItemAfterLargestIn32BitFlagSet)
+{
+ enum class ThirtyTwoBitFlags : uint32_t {
+ A = 1UL << 31,
+ };
+ OptionSet<ThirtyTwoBitFlags> set { ThirtyTwoBitFlags::A };
+ OptionSet<ThirtyTwoBitFlags>::iterator it = set.begin();
+ OptionSet<ThirtyTwoBitFlags>::iterator end = set.end();
+ EXPECT_TRUE(it != end);
+ ++it;
+ EXPECT_TRUE(it == end);
+}
+
+TEST(WTF_OptionSet, NextItemAfterLargestIn64BitFlagSet)
+{
+ enum class SixtyFourBitFlags : uint64_t {
+ A = 1ULL << 63,
+ };
+ OptionSet<SixtyFourBitFlags> set { SixtyFourBitFlags::A };
+ OptionSet<SixtyFourBitFlags>::iterator it = set.begin();
+ OptionSet<SixtyFourBitFlags>::iterator end = set.end();
+ EXPECT_TRUE(it != end);
+ ++it;
+ EXPECT_TRUE(it == end);
+}
+
+TEST(WTF_OptionSet, IterationOrderTheSameRegardlessOfInsertionOrder)
+{
+ OptionSet<ExampleFlags> set1 = ExampleFlags::C;
+ set1 |= ExampleFlags::A;
+
+ OptionSet<ExampleFlags> set2 = ExampleFlags::A;
+ set2 |= ExampleFlags::C;
+
+ OptionSet<ExampleFlags>::iterator it1 = set1.begin();
+ OptionSet<ExampleFlags>::iterator it2 = set2.begin();
+
+ EXPECT_TRUE(*it1 == *it2);
+ ++it1;
+ ++it2;
+ EXPECT_TRUE(*it1 == *it2);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/Optional.cpp b/Tools/TestWebKitAPI/Tests/WTF/Optional.cpp
new file mode 100644
index 000000000..a70881f35
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/Optional.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2014 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <wtf/Optional.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF_Optional, Disengaged)
+{
+ {
+ std::optional<int> optional;
+
+ EXPECT_FALSE(static_cast<bool>(optional));
+ }
+
+ {
+ std::optional<int> optional { std::nullopt };
+
+ EXPECT_FALSE(static_cast<bool>(optional));
+ }
+}
+
+TEST(WTF_Optional, Engaged)
+{
+ std::optional<int> optional { 10 };
+
+ EXPECT_TRUE(static_cast<bool>(optional));
+ EXPECT_EQ(10, optional.value());
+}
+
+TEST(WTF_Optional, Destructor)
+{
+ static bool didCallDestructor = false;
+ struct A {
+ ~A()
+ {
+ EXPECT_FALSE(didCallDestructor);
+ didCallDestructor = true;
+ }
+ };
+
+ {
+ std::optional<A> optional { std::in_place };
+
+ EXPECT_TRUE(static_cast<bool>(optional));
+ }
+
+ EXPECT_TRUE(didCallDestructor);
+}
+
+TEST(WTF_Optional, Callback)
+{
+ bool called = false;
+ std::optional<int> a;
+ int result = valueOrCompute(a, [&] {
+ called = true;
+ return 300;
+ });
+ EXPECT_TRUE(called);
+ EXPECT_EQ(result, 300);
+
+ a = 250;
+ called = false;
+ result = valueOrCompute(a, [&] {
+ called = true;
+ return 300;
+ });
+ EXPECT_FALSE(called);
+ EXPECT_EQ(result, 250);
+}
+
+TEST(WTF_Optional, Equality)
+{
+ std::optional<int> unengaged1;
+ std::optional<int> unengaged2;
+
+ std::optional<int> engaged1 { 1 };
+ std::optional<int> engaged2 { 2 };
+ std::optional<int> engagedx2 { 2 };
+
+ EXPECT_TRUE(unengaged1 == unengaged2);
+ EXPECT_FALSE(engaged1 == engaged2);
+ EXPECT_FALSE(engaged1 == unengaged1);
+ EXPECT_TRUE(engaged2 == engagedx2);
+
+ EXPECT_TRUE(unengaged1 == std::nullopt);
+ EXPECT_FALSE(engaged1 == std::nullopt);
+ EXPECT_TRUE(std::nullopt == unengaged1);
+ EXPECT_FALSE(std::nullopt == engaged1);
+
+ EXPECT_TRUE(engaged1 == 1);
+ EXPECT_TRUE(1 == engaged1);
+ EXPECT_FALSE(unengaged1 == 1);
+ EXPECT_FALSE(1 == unengaged1);
+}
+
+TEST(WTF_Optional, Inequality)
+{
+ std::optional<int> unengaged1;
+ std::optional<int> unengaged2;
+
+ std::optional<int> engaged1 { 1 };
+ std::optional<int> engaged2 { 2 };
+ std::optional<int> engagedx2 { 2 };
+
+ EXPECT_FALSE(unengaged1 != unengaged2);
+ EXPECT_TRUE(engaged1 != engaged2);
+ EXPECT_TRUE(engaged1 != unengaged1);
+ EXPECT_FALSE(engaged2 != engagedx2);
+
+ EXPECT_FALSE(unengaged1 != std::nullopt);
+ EXPECT_TRUE(engaged1 != std::nullopt);
+ EXPECT_FALSE(std::nullopt != unengaged1);
+ EXPECT_TRUE(std::nullopt != engaged1);
+
+ EXPECT_FALSE(engaged1 != 1);
+ EXPECT_TRUE(engaged1 != 2);
+ EXPECT_FALSE(1 != engaged1);
+ EXPECT_TRUE(2 != engaged1);
+
+ EXPECT_TRUE(unengaged1 != 1);
+ EXPECT_TRUE(1 != unengaged1);
+}
+
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/ParkingLot.cpp b/Tools/TestWebKitAPI/Tests/WTF/ParkingLot.cpp
new file mode 100644
index 000000000..c67e1e081
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/ParkingLot.cpp
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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.
+ */
+
+#include "config.h"
+#include <condition_variable>
+#include <mutex>
+#include <thread>
+#include <wtf/DataLog.h>
+#include <wtf/HashSet.h>
+#include <wtf/ListDump.h>
+#include <wtf/ParkingLot.h>
+#include <wtf/Threading.h>
+#include <wtf/ThreadingPrimitives.h>
+
+using namespace WTF;
+
+namespace TestWebKitAPI {
+
+namespace {
+
+struct SingleLatchTest {
+ void initialize(unsigned numThreads)
+ {
+ // This implements a fair (FIFO) semaphore, and it starts out unavailable.
+ semaphore.store(0);
+
+ for (unsigned i = numThreads; i--;) {
+ threads.append(
+ createThread(
+ "Parking Test Thread",
+ [&] () {
+ EXPECT_NE(0u, currentThread());
+
+ down();
+
+ std::lock_guard<std::mutex> locker(lock);
+ awake.add(currentThread());
+ lastAwoken = currentThread();
+ condition.notify_one();
+ }));
+ }
+ }
+
+ void unparkOne(unsigned singleUnparkIndex)
+ {
+ EXPECT_EQ(0u, lastAwoken);
+
+ unsigned numWaitingOnAddress = 0;
+ Vector<ThreadIdentifier, 8> queue;
+ ParkingLot::forEach(
+ [&] (ThreadIdentifier threadIdentifier, const void* address) {
+ if (address != &semaphore)
+ return;
+
+ queue.append(threadIdentifier);
+
+ numWaitingOnAddress++;
+ });
+
+ EXPECT_LE(numWaitingOnAddress, threads.size() - singleUnparkIndex);
+
+ up();
+
+ {
+ std::unique_lock<std::mutex> locker(lock);
+ while (awake.size() < singleUnparkIndex + 1)
+ condition.wait(locker);
+ EXPECT_NE(0u, lastAwoken);
+ if (!queue.isEmpty() && queue[0] != lastAwoken) {
+ dataLog("Woke up wrong thread: queue = ", listDump(queue), ", last awoken = ", lastAwoken, "\n");
+ EXPECT_EQ(queue[0], lastAwoken);
+ }
+ lastAwoken = 0;
+ }
+ }
+
+ void finish(unsigned numSingleUnparks)
+ {
+ unsigned numWaitingOnAddress = 0;
+ ParkingLot::forEach(
+ [&] (ThreadIdentifier, const void* address) {
+ if (address != &semaphore)
+ return;
+
+ numWaitingOnAddress++;
+ });
+
+ EXPECT_LE(numWaitingOnAddress, threads.size() - numSingleUnparks);
+
+ semaphore.store(threads.size() - numSingleUnparks);
+ ParkingLot::unparkAll(&semaphore);
+
+ numWaitingOnAddress = 0;
+ ParkingLot::forEach(
+ [&] (ThreadIdentifier, const void* address) {
+ if (address != &semaphore)
+ return;
+
+ numWaitingOnAddress++;
+ });
+
+ EXPECT_EQ(0u, numWaitingOnAddress);
+
+ {
+ std::unique_lock<std::mutex> locker(lock);
+ while (awake.size() < threads.size())
+ condition.wait(locker);
+ }
+
+ for (ThreadIdentifier threadIdentifier : threads)
+ waitForThreadCompletion(threadIdentifier);
+ }
+
+ // Semaphore operations.
+ void down()
+ {
+ for (;;) {
+ int oldSemaphoreValue = semaphore.load();
+ int newSemaphoreValue = oldSemaphoreValue - 1;
+ if (!semaphore.compareExchangeWeak(oldSemaphoreValue, newSemaphoreValue))
+ continue;
+
+ if (oldSemaphoreValue > 0) {
+ // We acquired the semaphore. Done.
+ return;
+ }
+
+ // We need to wait.
+ if (ParkingLot::compareAndPark(&semaphore, newSemaphoreValue).wasUnparked) {
+ // We did wait, and then got woken up. This means that someone who up'd the semaphore
+ // passed ownership onto us.
+ return;
+ }
+
+ // We never parked, because the semaphore value changed. Undo our decrement and try again.
+ for (;;) {
+ int oldSemaphoreValue = semaphore.load();
+ if (semaphore.compareExchangeWeak(oldSemaphoreValue, oldSemaphoreValue + 1))
+ break;
+ }
+ }
+ }
+ void up()
+ {
+ int oldSemaphoreValue;
+ for (;;) {
+ oldSemaphoreValue = semaphore.load();
+ if (semaphore.compareExchangeWeak(oldSemaphoreValue, oldSemaphoreValue + 1))
+ break;
+ }
+
+ // Check if anyone was waiting on the semaphore. If they were, then pass ownership to them.
+ if (oldSemaphoreValue < 0)
+ ParkingLot::unparkOne(&semaphore);
+ }
+
+ Atomic<int> semaphore;
+ std::mutex lock;
+ std::condition_variable condition;
+ HashSet<ThreadIdentifier> awake;
+ Vector<ThreadIdentifier> threads;
+ ThreadIdentifier lastAwoken { 0 };
+};
+
+void runParkingTest(unsigned numLatches, unsigned delay, unsigned numThreads, unsigned numSingleUnparks)
+{
+ std::unique_ptr<SingleLatchTest[]> tests = std::make_unique<SingleLatchTest[]>(numLatches);
+
+ for (unsigned latchIndex = numLatches; latchIndex--;)
+ tests[latchIndex].initialize(numThreads);
+
+ for (unsigned unparkIndex = 0; unparkIndex < numSingleUnparks; ++unparkIndex) {
+ std::this_thread::sleep_for(std::chrono::microseconds(delay));
+ for (unsigned latchIndex = numLatches; latchIndex--;)
+ tests[latchIndex].unparkOne(unparkIndex);
+ }
+
+ for (unsigned latchIndex = numLatches; latchIndex--;)
+ tests[latchIndex].finish(numSingleUnparks);
+}
+
+void repeatParkingTest(unsigned numRepeats, unsigned numLatches, unsigned delay, unsigned numThreads, unsigned numSingleUnparks)
+{
+ while (numRepeats--)
+ runParkingTest(numLatches, delay, numThreads, numSingleUnparks);
+}
+
+} // anonymous namespace
+
+TEST(WTF_ParkingLot, UnparkAllOneFast)
+{
+ repeatParkingTest(10000, 1, 0, 1, 0);
+}
+
+TEST(WTF_ParkingLot, UnparkAllHundredFast)
+{
+ repeatParkingTest(100, 1, 0, 100, 0);
+}
+
+TEST(WTF_ParkingLot, UnparkOneOneFast)
+{
+ repeatParkingTest(1000, 1, 0, 1, 1);
+}
+
+TEST(WTF_ParkingLot, UnparkOneHundredFast)
+{
+ repeatParkingTest(20, 1, 0, 100, 100);
+}
+
+TEST(WTF_ParkingLot, UnparkOneFiftyThenFiftyAllFast)
+{
+ repeatParkingTest(50, 1, 0, 100, 50);
+}
+
+TEST(WTF_ParkingLot, UnparkAllOne)
+{
+ repeatParkingTest(100, 1, 10000, 1, 0);
+}
+
+TEST(WTF_ParkingLot, UnparkAllHundred)
+{
+ repeatParkingTest(100, 1, 10000, 100, 0);
+}
+
+TEST(WTF_ParkingLot, UnparkOneOne)
+{
+ repeatParkingTest(10, 1, 10000, 1, 1);
+}
+
+TEST(WTF_ParkingLot, UnparkOneFifty)
+{
+ repeatParkingTest(1, 1, 10000, 50, 50);
+}
+
+TEST(WTF_ParkingLot, UnparkOneFiftyThenFiftyAll)
+{
+ repeatParkingTest(2, 1, 10000, 100, 50);
+}
+
+TEST(WTF_ParkingLot, HundredUnparkAllOneFast)
+{
+ repeatParkingTest(100, 100, 0, 1, 0);
+}
+
+TEST(WTF_ParkingLot, HundredUnparkAllOne)
+{
+ repeatParkingTest(1, 100, 10000, 1, 0);
+}
+
+} // namespace TestWebKitAPI
+
diff --git a/Tools/TestWebKitAPI/Tests/WTF/RedBlackTree.cpp b/Tools/TestWebKitAPI/Tests/WTF/RedBlackTree.cpp
index 1a1c9fdfc..5e5c8adc4 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/RedBlackTree.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/RedBlackTree.cpp
@@ -10,7 +10,7 @@
* 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
+ * 3. Neither the name of Apple 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.
*
diff --git a/Tools/TestWebKitAPI/Tests/WTF/Ref.cpp b/Tools/TestWebKitAPI/Tests/WTF/Ref.cpp
index 1b9eef67a..c35606e23 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/Ref.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/Ref.cpp
@@ -26,7 +26,6 @@
#include "config.h"
#include "RefLogger.h"
-#include <wtf/PassRef.h>
#include <wtf/Ref.h>
#include <wtf/RefPtr.h>
@@ -38,14 +37,14 @@ TEST(WTF_Ref, Basic)
{
Ref<RefLogger> ptr(a);
- ASSERT_EQ(&a, &ptr.get());
+ ASSERT_EQ(&a, ptr.ptr());
ASSERT_EQ(&a.name, &ptr->name);
}
ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
{
Ref<RefLogger> ptr(adoptRef(a));
- ASSERT_EQ(&a, &ptr.get());
+ ASSERT_EQ(&a, ptr.ptr());
ASSERT_EQ(&a.name, &ptr->name);
}
ASSERT_STREQ("deref(a) ", takeLogStr().c_str());
@@ -59,51 +58,51 @@ TEST(WTF_Ref, Assignment)
{
Ref<RefLogger> ptr(a);
- ASSERT_EQ(&a, &ptr.get());
+ ASSERT_EQ(&a, ptr.ptr());
log() << "| ";
ptr = b;
- ASSERT_EQ(&b, &ptr.get());
+ ASSERT_EQ(&b, ptr.ptr());
log() << "| ";
}
ASSERT_STREQ("ref(a) | ref(b) deref(a) | deref(b) ", takeLogStr().c_str());
{
Ref<RefLogger> ptr(a);
- ASSERT_EQ(&a, &ptr.get());
+ ASSERT_EQ(&a, ptr.ptr());
log() << "| ";
ptr = c;
- ASSERT_EQ(&c, &ptr.get());
+ ASSERT_EQ(&c, ptr.ptr());
log() << "| ";
}
ASSERT_STREQ("ref(a) | ref(c) deref(a) | deref(c) ", takeLogStr().c_str());
{
Ref<RefLogger> ptr(a);
- ASSERT_EQ(&a, &ptr.get());
+ ASSERT_EQ(&a, ptr.ptr());
log() << "| ";
ptr = adoptRef(b);
- ASSERT_EQ(&b, &ptr.get());
+ ASSERT_EQ(&b, ptr.ptr());
log() << "| ";
}
ASSERT_STREQ("ref(a) | deref(a) | deref(b) ", takeLogStr().c_str());
{
Ref<RefLogger> ptr(a);
- ASSERT_EQ(&a, &ptr.get());
+ ASSERT_EQ(&a, ptr.ptr());
log() << "| ";
ptr = adoptRef(c);
- ASSERT_EQ(&c, &ptr.get());
+ ASSERT_EQ(&c, ptr.ptr());
log() << "| ";
}
ASSERT_STREQ("ref(a) | deref(a) | deref(c) ", takeLogStr().c_str());
}
-PassRef<RefLogger> passWithPassRef(PassRef<RefLogger> reference)
+static Ref<RefLogger> passWithRef(Ref<RefLogger>&& reference)
{
- return reference;
+ return WTFMove(reference);
}
-RefPtr<RefLogger> passWithPassRefPtr(PassRefPtr<RefLogger> reference)
+static RefPtr<RefLogger> passWithPassRefPtr(PassRefPtr<RefLogger> reference)
{
return reference;
}
@@ -115,32 +114,48 @@ TEST(WTF_Ref, ReturnValue)
DerivedRefLogger c("c");
{
- Ref<RefLogger> ptr(passWithPassRef(a));
- ASSERT_EQ(&a, &ptr.get());
+ Ref<RefLogger> ptr(passWithRef(Ref<RefLogger>(a)));
+ ASSERT_EQ(&a, ptr.ptr());
}
ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
{
Ref<RefLogger> ptr(a);
- ASSERT_EQ(&a, &ptr.get());
+ ASSERT_EQ(&a, ptr.ptr());
log() << "| ";
- ptr = passWithPassRef(b);
- ASSERT_EQ(&b, &ptr.get());
+ ptr = passWithRef(b);
+ ASSERT_EQ(&b, ptr.ptr());
log() << "| ";
}
ASSERT_STREQ("ref(a) | ref(b) deref(a) | deref(b) ", takeLogStr().c_str());
{
- RefPtr<RefLogger> ptr(passWithPassRef(a));
+ RefPtr<RefLogger> ptr(passWithRef(a));
ASSERT_EQ(&a, ptr.get());
}
ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
{
- RefPtr<RefLogger> ptr(passWithPassRefPtr(passWithPassRef(a)));
+ RefPtr<RefLogger> ptr(passWithPassRefPtr(passWithRef(a)));
ASSERT_EQ(&a, ptr.get());
}
ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ RefPtr<DerivedRefLogger> ptr(&a);
+ RefPtr<RefLogger> ptr2(WTFMove(ptr));
+ ASSERT_EQ(nullptr, ptr.get());
+ ASSERT_EQ(&a, ptr2.get());
+ }
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ Ref<DerivedRefLogger> derivedReference(a);
+ Ref<RefLogger> baseReference(passWithRef(derivedReference.copyRef()));
+ ASSERT_EQ(&a, derivedReference.ptr());
+ ASSERT_EQ(&a, baseReference.ptr());
+ }
+ ASSERT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str());
}
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/RefCounter.cpp b/Tools/TestWebKitAPI/Tests/WTF/RefCounter.cpp
new file mode 100644
index 000000000..4c0a14b47
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/RefCounter.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2011 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <wtf/Ref.h>
+#include <wtf/RefCounter.h>
+#include <wtf/text/WTFString.h>
+
+namespace TestWebKitAPI {
+
+static const int IncrementExpected = 0xC0FFEE1;
+static const int DecrementExpected = 0xC0FFEE2;
+static const int CallbackNotExpected = 0xDECAF;
+
+enum TestCounterType { };
+typedef RefCounter<TestCounterType> TestCounter;
+typedef TestCounter::Token TokenType;
+
+TEST(WTF, RefCounter)
+{
+ // RefCounter API is pretty simple, containing the following 4 methods to test:
+ //
+ // 1) RefCounter(std::function<void()>);
+ // 2) ~RefCounter();
+ // 3) Ref<Count> token() const;
+ // 4) unsigned value() const;
+ //
+ // We'll test:
+ // 1) Construction:
+ // 1a) with a callback
+ // 1b) without a callback
+ // 2) Destruction where the RefCounter::Count has:
+ // 2a) a non-zero reference count (Count outlives RefCounter).
+ // 2b) a zero reference count (Count is deleted by RefCounter's destructor).
+ // 3) Call count to ref/deref the Count object, where:
+ // 3a) ref with callback from 0 -> 1.
+ // 3b) ref with callback from 1 -> >1.
+ // 3c) deref with callback from >1 -> 1.
+ // 3d) deref with callback from 1 -> 0.
+ // 3d) deref with callback from 1 -> 0.
+ // 3e) ref with callback from 1 -> >1 AFTER RefCounter has been destroyed.
+ // 3f) deref with callback from >1 -> 1 AFTER RefCounter has been destroyed.
+ // 3g) deref with callback from 1 -> 0 AFTER RefCounter has been destroyed.
+ // 3h) ref without callback
+ // 3i) deref without callback
+ // 3j) ref using a Ref rather than a RefPtr (make sure there is no unnecessary reference count churn).
+ // 3k) deref using a Ref rather than a RefPtr (make sure there is no unnecessary reference count churn).
+ // 4) Test the value of the counter:
+ // 4a) at construction.
+ // 4b) as read within the callback.
+ // 4c) as read after the ref/deref.
+
+ // These values will outlive the following block.
+ int callbackValue = CallbackNotExpected;
+ TokenType incTo1Again;
+
+ {
+ // Testing (1a) - Construction with a callback.
+ TestCounter* counterPtr = nullptr;
+ TestCounter counter([&](RefCounterEvent event) {
+ // Check that the callback is called at the expected times, and the correct number of times.
+ if (RefCounterEvent::Increment == event)
+ EXPECT_EQ(callbackValue, IncrementExpected);
+ if (RefCounterEvent::Decrement == event)
+ EXPECT_EQ(callbackValue, DecrementExpected);
+ // return the value of the counter in the callback.
+ callbackValue = counterPtr->value();
+ });
+ counterPtr = &counter;
+ // Testing (4a) - after construction value() is 0.
+ EXPECT_EQ(0, static_cast<int>(counter.value()));
+
+ // Testing (3a) - ref with callback from 0 -> 1.
+ callbackValue = IncrementExpected;
+ TokenType incTo1(counter.count());
+ // Testing (4b) & (4c) - values within & after callback.
+ EXPECT_EQ(1, callbackValue);
+ EXPECT_EQ(1, static_cast<int>(counter.value()));
+
+ // Testing (3b) - ref with callback from 1 -> 2.
+ callbackValue = IncrementExpected;
+ TokenType incTo2(incTo1);
+ // Testing (4b) & (4c) - values within & after callback.
+ EXPECT_EQ(2, callbackValue);
+ EXPECT_EQ(2, static_cast<int>(counter.value()));
+
+ // Testing (3c) - deref with callback from >1 -> 1.
+ callbackValue = DecrementExpected;
+ incTo1 = nullptr;
+ // Testing (4b) & (4c) - values within & after callback.
+ EXPECT_EQ(1, callbackValue);
+ EXPECT_EQ(1, static_cast<int>(counter.value()));
+
+ {
+ // Testing (3j) - ref using a Ref rather than a RefPtr.
+ callbackValue = IncrementExpected;
+ TokenType incTo2Again(counter.count());
+ // Testing (4b) & (4c) - values within & after callback.
+ EXPECT_EQ(2, callbackValue);
+ EXPECT_EQ(2, static_cast<int>(counter.value()));
+ // Testing (3k) - deref using a Ref rather than a RefPtr.
+
+ callbackValue = DecrementExpected;
+ }
+ EXPECT_EQ(1, callbackValue);
+ EXPECT_EQ(1, static_cast<int>(counter.value()));
+ // Testing (4b) & (4c) - values within & after callback.
+
+ // Testing (3d) - deref with callback from 1 -> 0.
+ callbackValue = DecrementExpected;
+ incTo2 = nullptr;
+ // Testing (4b) & (4c) - values within & after callback.
+ EXPECT_EQ(0, callbackValue);
+ EXPECT_EQ(0, static_cast<int>(counter.value()));
+
+ // Testing (2a) - Destruction where the TestCounter::Count has a non-zero reference count.
+ callbackValue = IncrementExpected;
+ incTo1Again = counter.count();
+ EXPECT_EQ(1, callbackValue);
+ EXPECT_EQ(1, static_cast<int>(counter.value()));
+ callbackValue = CallbackNotExpected;
+ }
+
+ // Testing (3e) - ref with callback from 1 -> >1 AFTER RefCounter has been destroyed.
+ TokenType incTo2Again = incTo1Again;
+ // Testing (3f) - deref with callback from >1 -> 1 AFTER RefCounter has been destroyed.
+ incTo1Again = nullptr;
+ // Testing (3g) - deref with callback from 1 -> 0 AFTER RefCounter has been destroyed.
+ incTo2Again = nullptr;
+
+ // Testing (1b) - Construction without a callback.
+ TestCounter counter;
+ // Testing (4a) - after construction value() is 0.
+ EXPECT_EQ(0, static_cast<int>(counter.value()));
+ // Testing (3h) - ref without callback
+ TokenType incTo1(counter.count());
+ // Testing (4c) - value as read after the ref.
+ EXPECT_EQ(1, static_cast<int>(counter.value()));
+ // Testing (3i) - deref without callback
+ incTo1 = nullptr;
+ // Testing (4c) - value as read after the deref.
+ EXPECT_EQ(0, static_cast<int>(counter.value()));
+ // Testing (2b) - Destruction where the RefCounter::Count has a zero reference count.
+ // ... not a lot to test here! - we can at least ensure this code path is run & we don't crash!
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/RefLogger.cpp b/Tools/TestWebKitAPI/Tests/WTF/RefLogger.cpp
new file mode 100644
index 000000000..f468a312c
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/RefLogger.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013, 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. 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 INC. 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.
+ */
+
+#include "config.h"
+#include "RefLogger.h"
+
+namespace TestWebKitAPI {
+
+std::ostringstream& log()
+{
+ static std::ostringstream log;
+ return log;
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WTF/RefLogger.h b/Tools/TestWebKitAPI/Tests/WTF/RefLogger.h
index 2bb5c36fa..02547dfec 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/RefLogger.h
+++ b/Tools/TestWebKitAPI/Tests/WTF/RefLogger.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 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
@@ -27,11 +27,7 @@
namespace TestWebKitAPI {
-inline std::ostringstream& log()
-{
- static std::ostringstream log;
- return log;
-}
+std::ostringstream& log();
inline std::string takeLogStr()
{
@@ -48,7 +44,7 @@ struct RefLogger {
};
struct DerivedRefLogger : RefLogger {
- DerivedRefLogger(const char* name) : RefLogger(name) { }
+ DerivedRefLogger(const char* name) : RefLogger(name) { log().str(""); }
};
}
diff --git a/Tools/TestWebKitAPI/Tests/WTF/RefPtr.cpp b/Tools/TestWebKitAPI/Tests/WTF/RefPtr.cpp
index bc1e1e484..172efa762 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/RefPtr.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/RefPtr.cpp
@@ -26,6 +26,8 @@
#include "config.h"
#include "RefLogger.h"
+#include <wtf/NeverDestroyed.h>
+#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
namespace TestWebKitAPI {
@@ -69,7 +71,7 @@ TEST(WTF_RefPtr, Basic)
{
RefPtr<RefLogger> p1 = &a;
- RefPtr<RefLogger> p2 = std::move(p1);
+ RefPtr<RefLogger> p2 = WTFMove(p1);
ASSERT_EQ(nullptr, p1.get());
ASSERT_EQ(&a, p2.get());
}
@@ -77,7 +79,7 @@ TEST(WTF_RefPtr, Basic)
{
RefPtr<RefLogger> p1 = &a;
- RefPtr<RefLogger> p2(std::move(p1));
+ RefPtr<RefLogger> p2(WTFMove(p1));
ASSERT_EQ(nullptr, p1.get());
ASSERT_EQ(&a, p2.get());
}
@@ -93,7 +95,7 @@ TEST(WTF_RefPtr, Basic)
{
RefPtr<DerivedRefLogger> p1 = &a;
- RefPtr<RefLogger> p2 = std::move(p1);
+ RefPtr<RefLogger> p2 = WTFMove(p1);
ASSERT_EQ(nullptr, p1.get());
ASSERT_EQ(&a, p2.get());
}
@@ -102,7 +104,7 @@ TEST(WTF_RefPtr, Basic)
{
RefPtr<RefLogger> ptr(&a);
ASSERT_EQ(&a, ptr.get());
- ptr.clear();
+ ptr = nullptr;
ASSERT_EQ(nullptr, ptr.get());
}
ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
@@ -120,8 +122,8 @@ TEST(WTF_RefPtr, AssignPassRefToRefPtr)
{
DerivedRefLogger a("a");
{
- PassRef<RefLogger> passRef(a);
- RefPtr<RefLogger> ptr = std::move(passRef);
+ Ref<RefLogger> passRef(a);
+ RefPtr<RefLogger> ptr = WTFMove(passRef);
ASSERT_EQ(&a, ptr.get());
ptr.release();
ASSERT_EQ(nullptr, ptr.get());
@@ -204,7 +206,7 @@ TEST(WTF_RefPtr, Assignment)
ASSERT_EQ(&a, p1.get());
ASSERT_EQ(&b, p2.get());
log() << "| ";
- p1 = std::move(p2);
+ p1 = WTFMove(p2);
ASSERT_EQ(&b, p1.get());
ASSERT_EQ(nullptr, p2.get());
log() << "| ";
@@ -250,7 +252,7 @@ TEST(WTF_RefPtr, Assignment)
ASSERT_EQ(&a, p1.get());
ASSERT_EQ(&c, p2.get());
log() << "| ";
- p1 = std::move(p2);
+ p1 = WTFMove(p2);
ASSERT_EQ(&c, p1.get());
ASSERT_EQ(nullptr, p2.get());
log() << "| ";
@@ -270,7 +272,15 @@ TEST(WTF_RefPtr, Assignment)
{
RefPtr<RefLogger> ptr(&a);
ASSERT_EQ(&a, ptr.get());
- ptr = std::move(ptr);
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Wself-move"
+#endif
+ ptr = WTFMove(ptr);
+#if COMPILER(CLANG)
+#pragma clang diagnostic pop
+#endif
ASSERT_EQ(&a, ptr.get());
}
ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
@@ -395,4 +405,34 @@ TEST(WTF_RefPtr, ReturnValue)
ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
}
+
+struct ConstRefCounted : RefCounted<ConstRefCounted> {
+ static Ref<ConstRefCounted> create() { return adoptRef(*new ConstRefCounted); }
+};
+
+const ConstRefCounted& returnConstRefCountedRef()
+{
+ static NeverDestroyed<ConstRefCounted> instance;
+ return instance.get();
+}
+ConstRefCounted& returnRefCountedRef()
+{
+ static NeverDestroyed<ConstRefCounted> instance;
+ return instance.get();
+}
+
+TEST(WTF_RefPtr, Const)
+{
+ // This test passes if it compiles without an error.
+ auto a = ConstRefCounted::create();
+ Ref<const ConstRefCounted> b = WTFMove(a);
+ RefPtr<const ConstRefCounted> c = b.ptr();
+ Ref<const ConstRefCounted> d = returnConstRefCountedRef();
+ RefPtr<const ConstRefCounted> e = &returnConstRefCountedRef();
+ RefPtr<ConstRefCounted> f = ConstRefCounted::create();
+ RefPtr<const ConstRefCounted> g = f;
+ RefPtr<const ConstRefCounted> h(f);
+ Ref<const ConstRefCounted> i(returnRefCountedRef());
+}
+
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/RunLoop.cpp b/Tools/TestWebKitAPI/Tests/WTF/RunLoop.cpp
new file mode 100644
index 000000000..1dc7e938a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/RunLoop.cpp
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include "Utilities.h"
+#include <wtf/RunLoop.h>
+
+namespace TestWebKitAPI {
+
+static bool testFinished;
+static int count = 100;
+
+TEST(WTF_RunLoop, Deadlock)
+{
+ RunLoop::initializeMainRunLoop();
+
+ struct DispatchFromDestructorTester {
+ ~DispatchFromDestructorTester() {
+ RunLoop::main().dispatch([] {
+ if (!(--count))
+ testFinished = true;
+ });
+ }
+ };
+
+ for (int i = 0; i < count; ++i) {
+ auto capture = std::make_shared<DispatchFromDestructorTester>();
+ RunLoop::main().dispatch([capture] { });
+ }
+
+ Util::run(&testFinished);
+}
+
+TEST(WTF_RunLoop, NestedRunLoop)
+{
+ RunLoop::initializeMainRunLoop();
+
+ bool testFinished = false;
+ RunLoop::current().dispatch([&] {
+ RunLoop::current().dispatch([&] {
+ testFinished = true;
+ });
+ Util::run(&testFinished);
+ });
+
+ Util::run(&testFinished);
+}
+
+TEST(WTF_RunLoop, OneShotTimer)
+{
+ RunLoop::initializeMainRunLoop();
+
+ bool testFinished = false;
+
+ class DerivedTimer : public RunLoop::Timer<DerivedTimer> {
+ public:
+ DerivedTimer(bool& testFinished)
+ : RunLoop::Timer<DerivedTimer>(RunLoop::current(), this, &DerivedTimer::fired)
+ , m_testFinished(testFinished)
+ {
+ }
+
+ void fired()
+ {
+ m_testFinished = true;
+ stop();
+ }
+
+ private:
+ bool& m_testFinished;
+ };
+
+ {
+ DerivedTimer timer(testFinished);
+ timer.startOneShot(0.1);
+ Util::run(&testFinished);
+ }
+}
+
+TEST(WTF_RunLoop, RepeatingTimer)
+{
+ RunLoop::initializeMainRunLoop();
+
+ bool testFinished = false;
+
+ class DerivedTimer : public RunLoop::Timer<DerivedTimer> {
+ public:
+ DerivedTimer(bool& testFinished)
+ : RunLoop::Timer<DerivedTimer>(RunLoop::current(), this, &DerivedTimer::fired)
+ , m_testFinished(testFinished)
+ {
+ }
+
+ void fired()
+ {
+ if (++m_count == 10) {
+ m_testFinished = true;
+ stop();
+ }
+ }
+
+ private:
+ unsigned m_count { 0 };
+ bool& m_testFinished;
+ };
+
+ {
+ DerivedTimer timer(testFinished);
+ timer.startRepeating(0.01);
+ Util::run(&testFinished);
+ }
+}
+
+TEST(WTF_RunLoop, ManyTimes)
+{
+ RunLoop::initializeMainRunLoop();
+
+ class Counter {
+ public:
+ void run()
+ {
+ if (++m_count == 100000) {
+ RunLoop::current().stop();
+ return;
+ }
+ RunLoop::current().dispatch([this] {
+ run();
+ });
+ }
+
+ private:
+ unsigned m_count { 0 };
+ };
+
+ Counter counter;
+
+ RunLoop::current().dispatch([&counter] {
+ counter.run();
+ });
+ RunLoop::run();
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/Scope.cpp b/Tools/TestWebKitAPI/Tests/WTF/Scope.cpp
new file mode 100644
index 000000000..08f5ce327
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/Scope.cpp
@@ -0,0 +1,53 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+#include <wtf/Scope.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF_Scope, ScopeExit)
+{
+ bool isCalled = false;
+ {
+ auto scopeExit = makeScopeExit([&] {
+ EXPECT_FALSE(isCalled);
+ isCalled = true;
+ });
+ EXPECT_FALSE(isCalled);
+ }
+ EXPECT_TRUE(isCalled);
+
+ isCalled = false;
+ {
+ auto scopeExit = makeScopeExit([&] {
+ isCalled = true;
+ });
+ scopeExit.release();
+ }
+ EXPECT_FALSE(isCalled);
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WTF/ScopedLambda.cpp b/Tools/TestWebKitAPI/Tests/WTF/ScopedLambda.cpp
new file mode 100644
index 000000000..3dfee8671
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/ScopedLambda.cpp
@@ -0,0 +1,51 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+#include <wtf/ScopedLambda.h>
+#include <wtf/Vector.h>
+
+using namespace WTF;
+
+namespace TestWebKitAPI {
+
+// This test relies on this module being compiled with -fno-elide-constructors
+TEST(WTF_ScopedLambda, NoRVOLivenessBug)
+{
+ Vector<int> vector;
+ for (unsigned i = 0; i < 10; ++i)
+ vector.append(i);
+
+ auto lambda = scopedLambda<int(size_t)>(
+ [=] (size_t i) -> int {
+ return vector[i];
+ });
+
+ for (unsigned i = 0; i < 10; ++i)
+ EXPECT_EQ(i, static_cast<unsigned>(lambda(i)));
+}
+
+} // namespace TestWebKitAPI
+
diff --git a/Tools/TestWebKitAPI/Tests/WTF/TemporaryChange.cpp b/Tools/TestWebKitAPI/Tests/WTF/SetForScope.cpp
index 3ba0f15bd..92e3494d6 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/TemporaryChange.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/SetForScope.cpp
@@ -25,18 +25,18 @@
#include "config.h"
-#include <wtf/TemporaryChange.h>
+#include <wtf/SetForScope.h>
namespace TestWebKitAPI {
-TEST(WTF, TemporaryChangeNested)
+TEST(WTF, SetForScopeNested)
{
bool originallyFalse = false;
{
- TemporaryChange<bool> change1OriginallyFalse(originallyFalse, true);
+ SetForScope<bool> change1OriginallyFalse(originallyFalse, true);
EXPECT_TRUE(originallyFalse);
{
- TemporaryChange<bool> change2OriginallyFalse(originallyFalse, false);
+ SetForScope<bool> change2OriginallyFalse(originallyFalse, false);
EXPECT_FALSE(originallyFalse);
}
EXPECT_TRUE(originallyFalse);
diff --git a/Tools/TestWebKitAPI/Tests/WTF/StringBuilder.cpp b/Tools/TestWebKitAPI/Tests/WTF/StringBuilder.cpp
index 9ca5d6ee8..11bf3590e 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/StringBuilder.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/StringBuilder.cpp
@@ -38,14 +38,17 @@ static void expectBuilderContent(const String& expected, const StringBuilder& bu
{
// Not using builder.toString() or builder.toStringPreserveCapacity() because they all
// change internal state of builder.
- EXPECT_EQ(expected, String(builder.deprecatedCharacters(), builder.length()));
+ if (builder.is8Bit())
+ EXPECT_EQ(expected, String(builder.characters8(), builder.length()));
+ else
+ EXPECT_EQ(expected, String(builder.characters16(), builder.length()));
}
void expectEmpty(const StringBuilder& builder)
{
EXPECT_EQ(0U, builder.length());
EXPECT_TRUE(builder.isEmpty());
- EXPECT_EQ(0, builder.deprecatedCharacters());
+ EXPECT_EQ(0, builder.characters8());
}
TEST(StringBuilderTest, DefaultConstructor)
@@ -72,20 +75,20 @@ TEST(StringBuilderTest, Append)
StringBuilder builder1;
builder.append("", 0);
expectBuilderContent("0123456789abcdefg#", builder);
- builder1.append(builder.deprecatedCharacters(), builder.length());
+ builder1.append(builder.characters8(), builder.length());
builder1.append("XYZ");
- builder.append(builder1.deprecatedCharacters(), builder1.length());
+ builder.append(builder1.characters8(), builder1.length());
expectBuilderContent("0123456789abcdefg#0123456789abcdefg#XYZ", builder);
StringBuilder builder2;
builder2.reserveCapacity(100);
builder2.append("xyz");
- const UChar* characters = builder2.deprecatedCharacters();
+ const LChar* characters = builder2.characters8();
builder2.append("0123456789");
- ASSERT_EQ(characters, builder2.deprecatedCharacters());
+ ASSERT_EQ(characters, builder2.characters8());
builder2.toStringPreserveCapacity(); // Test after reifyString with buffer preserved.
builder2.append("abcd");
- ASSERT_EQ(characters, builder2.deprecatedCharacters());
+ ASSERT_EQ(characters, builder2.characters8());
// Test appending UChar32 characters to StringBuilder.
StringBuilder builderForUChar32Append;
@@ -140,7 +143,7 @@ TEST(StringBuilderTest, ToStringPreserveCapacity)
ASSERT_EQ(capacity, builder.capacity());
ASSERT_EQ(String("0123456789"), string);
ASSERT_EQ(string.impl(), builder.toStringPreserveCapacity().impl());
- ASSERT_EQ(string.deprecatedCharacters(), builder.deprecatedCharacters());
+ ASSERT_EQ(string.characters8(), builder.characters8());
// Changing the StringBuilder should not affect the original result of toStringPreserveCapacity().
builder.append("abcdefghijklmnopqrstuvwxyz");
@@ -151,7 +154,7 @@ TEST(StringBuilderTest, ToStringPreserveCapacity)
capacity = builder.capacity();
string = builder.toStringPreserveCapacity();
ASSERT_EQ(capacity, builder.capacity());
- ASSERT_EQ(string.deprecatedCharacters(), builder.deprecatedCharacters());
+ ASSERT_EQ(string.characters8(), builder.characters8());
ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyz"), string);
builder.append("ABC");
ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyz"), string);
@@ -160,7 +163,7 @@ TEST(StringBuilderTest, ToStringPreserveCapacity)
capacity = builder.capacity();
String string1 = builder.toStringPreserveCapacity();
ASSERT_EQ(capacity, builder.capacity());
- ASSERT_EQ(string1.deprecatedCharacters(), builder.deprecatedCharacters());
+ ASSERT_EQ(string1.characters8(), builder.characters8());
ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABC"), string1);
string1.append("DEF");
ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABC"), builder.toStringPreserveCapacity());
@@ -170,7 +173,7 @@ TEST(StringBuilderTest, ToStringPreserveCapacity)
capacity = builder.capacity();
string1 = builder.toStringPreserveCapacity();
ASSERT_EQ(capacity, builder.capacity());
- ASSERT_EQ(string.deprecatedCharacters(), builder.deprecatedCharacters());
+ ASSERT_EQ(string.characters8(), builder.characters8());
builder.resize(10);
builder.append("###");
ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABC"), string1);
diff --git a/Tools/TestWebKitAPI/Tests/WTF/StringConcatenate.cpp b/Tools/TestWebKitAPI/Tests/WTF/StringConcatenate.cpp
new file mode 100644
index 000000000..fc25b08f8
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/StringConcatenate.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2017 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include "WTFStringUtilities.h"
+#include <wtf/text/StringConcatenate.h>
+#include <wtf/text/StringConcatenateNumbers.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF, StringConcatenate)
+{
+ EXPECT_EQ("hello world", makeString("hello", " ", "world"));
+}
+
+TEST(WTF, StringConcatenate_Int)
+{
+ EXPECT_EQ(5u, WTF::lengthOfNumberAsStringSigned(17890));
+ EXPECT_EQ("hello 17890 world", makeString("hello ", 17890 , " world"));
+
+ EXPECT_EQ(6u, WTF::lengthOfNumberAsStringSigned(-17890));
+ EXPECT_EQ("hello -17890 world", makeString("hello ", -17890 , " world"));
+
+ EXPECT_EQ(1u, WTF::lengthOfNumberAsStringSigned(0));
+ EXPECT_EQ("hello 0 world", makeString("hello ", 0 , " world"));
+}
+
+TEST(WTF, StringConcatenate_Unsigned)
+{
+ EXPECT_EQ(5u, WTF::lengthOfNumberAsStringUnsigned(17890u));
+ EXPECT_EQ("hello 17890 world", makeString("hello ", 17890u , " world"));
+
+ EXPECT_EQ(1u, WTF::lengthOfNumberAsStringSigned(0u));
+ EXPECT_EQ("hello 0 world", makeString("hello ", 0u , " world"));
+}
+
+TEST(WTF, StringConcatenate_Float)
+{
+ EXPECT_EQ("hello 17890 world", makeString("hello ", 17890.0f , " world"));
+ EXPECT_EQ("hello 17890.5 world", makeString("hello ", 17890.5f , " world"));
+
+ EXPECT_EQ("hello -17890 world", makeString("hello ", -17890.0f , " world"));
+ EXPECT_EQ("hello -17890.5 world", makeString("hello ", -17890.5f , " world"));
+
+ EXPECT_EQ("hello 0 world", makeString("hello ", 0.0f , " world"));
+}
+
+TEST(WTF, StringConcatenate_Double)
+{
+ EXPECT_EQ("hello 17890 world", makeString("hello ", 17890.0 , " world"));
+ EXPECT_EQ("hello 17890.5 world", makeString("hello ", 17890.5 , " world"));
+
+ EXPECT_EQ("hello -17890 world", makeString("hello ", -17890.0 , " world"));
+ EXPECT_EQ("hello -17890.5 world", makeString("hello ", -17890.5 , " world"));
+
+ EXPECT_EQ("hello 0 world", makeString("hello ", 0.0 , " world"));
+}
+
+TEST(WTF, StringConcatenate_FormattedDoubleFixedPrecision)
+{
+ EXPECT_EQ("hello 17890.0 world", makeString("hello ", FormattedNumber::fixedPrecision(17890.0) , " world"));
+ EXPECT_EQ("hello 1.79e+4 world", makeString("hello ", FormattedNumber::fixedPrecision(17890.0, 3) , " world"));
+ EXPECT_EQ("hello 17890.000 world", makeString("hello ", FormattedNumber::fixedPrecision(17890.0, 8) , " world"));
+ EXPECT_EQ("hello 17890 world", makeString("hello ", FormattedNumber::fixedPrecision(17890.0, 8, true) , " world"));
+
+ EXPECT_EQ("hello 17890.5 world", makeString("hello ", FormattedNumber::fixedPrecision(17890.5) , " world"));
+ EXPECT_EQ("hello 1.79e+4 world", makeString("hello ", FormattedNumber::fixedPrecision(17890.5, 3) , " world"));
+ EXPECT_EQ("hello 17890.500 world", makeString("hello ", FormattedNumber::fixedPrecision(17890.5, 8) , " world"));
+ EXPECT_EQ("hello 17890.5 world", makeString("hello ", FormattedNumber::fixedPrecision(17890.5, 8, true) , " world"));
+
+ EXPECT_EQ("hello -17890.0 world", makeString("hello ", FormattedNumber::fixedPrecision(-17890.0) , " world"));
+ EXPECT_EQ("hello -1.79e+4 world", makeString("hello ", FormattedNumber::fixedPrecision(-17890.0, 3) , " world"));
+ EXPECT_EQ("hello -17890.000 world", makeString("hello ", FormattedNumber::fixedPrecision(-17890.0, 8) , " world"));
+ EXPECT_EQ("hello -17890 world", makeString("hello ", FormattedNumber::fixedPrecision(-17890.0, 8, true) , " world"));
+
+ EXPECT_EQ("hello -17890.5 world", makeString("hello ", FormattedNumber::fixedPrecision(-17890.5) , " world"));
+ EXPECT_EQ("hello -1.79e+4 world", makeString("hello ", FormattedNumber::fixedPrecision(-17890.5, 3) , " world"));
+ EXPECT_EQ("hello -17890.500 world", makeString("hello ", FormattedNumber::fixedPrecision(-17890.5, 8) , " world"));
+ EXPECT_EQ("hello -17890.5 world", makeString("hello ", FormattedNumber::fixedPrecision(-17890.5, 8, true) , " world"));
+
+ EXPECT_EQ("hello 0.00000 world", makeString("hello ", FormattedNumber::fixedPrecision(0.0) , " world"));
+ EXPECT_EQ("hello 0.00 world", makeString("hello ", FormattedNumber::fixedPrecision(0.0, 3) , " world"));
+ EXPECT_EQ("hello 0.0000000 world", makeString("hello ", FormattedNumber::fixedPrecision(0.0, 8) , " world"));
+ EXPECT_EQ("hello 0 world", makeString("hello ", FormattedNumber::fixedPrecision(0.0, 8, true) , " world"));
+}
+
+TEST(WTF, StringConcatenate_FormattedDoubleFixedWidth)
+{
+ EXPECT_EQ("hello 17890.000 world", makeString("hello ", FormattedNumber::fixedWidth(17890.0, 3) , " world"));
+ EXPECT_EQ("hello 17890.500 world", makeString("hello ", FormattedNumber::fixedWidth(17890.5, 3) , " world"));
+
+ EXPECT_EQ("hello -17890.000 world", makeString("hello ", FormattedNumber::fixedWidth(-17890.0, 3) , " world"));
+ EXPECT_EQ("hello -17890.500 world", makeString("hello ", FormattedNumber::fixedWidth(-17890.5, 3) , " world"));
+
+ EXPECT_EQ("hello 0.000 world", makeString("hello ", FormattedNumber::fixedWidth(0.0, 3) , " world"));
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WTF/StringHasher.cpp b/Tools/TestWebKitAPI/Tests/WTF/StringHasher.cpp
index a4d223c99..5985b026a 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/StringHasher.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/StringHasher.cpp
@@ -25,7 +25,7 @@
#include "config.h"
-#include <wtf/StringHasher.h>
+#include <wtf/Hasher.h>
namespace TestWebKitAPI {
@@ -264,6 +264,43 @@ TEST(WTF, StringHasher_addCharacters)
hasher.addCharacters(testBUChars + 3);
ASSERT_EQ(testBHash5, hasher.hash());
ASSERT_EQ(testBHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked());
+
+ // Hashing zero characters after hashing other characters.
+ hasher = StringHasher();
+ hasher.addCharacters(nullLChars, 0);
+ hasher.addCharacters(nullLChars, 0);
+ ASSERT_EQ(emptyStringHash, hasher.hash());
+ ASSERT_EQ(emptyStringHash & 0xFFFFFF, hasher.hashWithTop8BitsMasked());
+
+ hasher = StringHasher();
+ hasher.addCharacters(testALChars, 1);
+ hasher.addCharacters(nullLChars, 0);
+ ASSERT_EQ(testAHash1, hasher.hash());
+ ASSERT_EQ(testAHash1 & 0xFFFFFF, hasher.hashWithTop8BitsMasked());
+
+ hasher = StringHasher();
+ hasher.addCharacters(testALChars, 2);
+ hasher.addCharacters(nullLChars, 0);
+ ASSERT_EQ(testAHash2, hasher.hash());
+ ASSERT_EQ(testAHash2 & 0xFFFFFF, hasher.hashWithTop8BitsMasked());
+
+ hasher = StringHasher();
+ hasher.addCharacters(testAUChars, 3);
+ hasher.addCharacters(nullLChars, 0);
+ ASSERT_EQ(testAHash3, hasher.hash());
+ ASSERT_EQ(testAHash3 & 0xFFFFFF, hasher.hashWithTop8BitsMasked());
+
+ hasher = StringHasher();
+ hasher.addCharacters(testALChars, 4);
+ hasher.addCharacters(nullLChars, 0);
+ ASSERT_EQ(testAHash4, hasher.hash());
+ ASSERT_EQ(testAHash4 & 0xFFFFFF, hasher.hashWithTop8BitsMasked());
+
+ hasher = StringHasher();
+ hasher.addCharacters(testALChars, 5);
+ hasher.addCharacters(nullLChars, 0);
+ ASSERT_EQ(testAHash5, hasher.hash());
+ ASSERT_EQ(testAHash5 & 0xFFFFFF, hasher.hashWithTop8BitsMasked());
}
TEST(WTF, StringHasher_addCharactersAssumingAligned)
@@ -427,18 +464,18 @@ TEST(WTF, StringHasher_computeHashAndMaskTop8Bits)
TEST(WTF, StringHasher_hashMemory)
{
- ASSERT_EQ(emptyStringHash & 0xFFFFFF, StringHasher::hashMemory(0, 0));
- ASSERT_EQ(emptyStringHash & 0xFFFFFF, StringHasher::hashMemory(nullUChars, 0));
- ASSERT_EQ(emptyStringHash & 0xFFFFFF, StringHasher::hashMemory<0>(0));
- ASSERT_EQ(emptyStringHash & 0xFFFFFF, StringHasher::hashMemory<0>(nullUChars));
-
- ASSERT_EQ(singleNullCharacterHash & 0xFFFFFF, StringHasher::hashMemory(nullUChars, 2));
- ASSERT_EQ(singleNullCharacterHash & 0xFFFFFF, StringHasher::hashMemory<2>(nullUChars));
-
- ASSERT_EQ(testAHash5 & 0xFFFFFF, StringHasher::hashMemory(testAUChars, 10));
- ASSERT_EQ(testAHash5 & 0xFFFFFF, StringHasher::hashMemory<10>(testAUChars));
- ASSERT_EQ(testBHash5 & 0xFFFFFF, StringHasher::hashMemory(testBUChars, 10));
- ASSERT_EQ(testBHash5 & 0xFFFFFF, StringHasher::hashMemory<10>(testBUChars));
+ ASSERT_EQ(emptyStringHash, StringHasher::hashMemory(0, 0));
+ ASSERT_EQ(emptyStringHash, StringHasher::hashMemory(nullUChars, 0));
+ ASSERT_EQ(emptyStringHash, StringHasher::hashMemory<0>(0));
+ ASSERT_EQ(emptyStringHash, StringHasher::hashMemory<0>(nullUChars));
+
+ ASSERT_EQ(singleNullCharacterHash, StringHasher::hashMemory(nullUChars, 2));
+ ASSERT_EQ(singleNullCharacterHash, StringHasher::hashMemory<2>(nullUChars));
+
+ ASSERT_EQ(testAHash5, StringHasher::hashMemory(testAUChars, 10));
+ ASSERT_EQ(testAHash5, StringHasher::hashMemory<10>(testAUChars));
+ ASSERT_EQ(testBHash5, StringHasher::hashMemory(testBUChars, 10));
+ ASSERT_EQ(testBHash5, StringHasher::hashMemory<10>(testBUChars));
}
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp b/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp
index d5804f6b4..fdb701c90 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 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
@@ -25,7 +25,8 @@
#include "config.h"
-#include <wtf/text/StringImpl.h>
+#include <wtf/Hasher.h>
+#include <wtf/text/SymbolImpl.h>
#include <wtf/text/WTFString.h>
namespace TestWebKitAPI {
@@ -33,14 +34,14 @@ namespace TestWebKitAPI {
TEST(WTF, StringImplCreationFromLiteral)
{
// Constructor using the template to determine the size.
- RefPtr<StringImpl> stringWithTemplate = StringImpl::createFromLiteral("Template Literal");
+ auto stringWithTemplate = StringImpl::createFromLiteral("Template Literal");
ASSERT_EQ(strlen("Template Literal"), stringWithTemplate->length());
ASSERT_TRUE(equal(stringWithTemplate.get(), "Template Literal"));
ASSERT_TRUE(stringWithTemplate->is8Bit());
// Constructor taking the size explicitely.
const char* programmaticStringData = "Explicit Size Literal";
- RefPtr<StringImpl> programmaticString = StringImpl::createFromLiteral(programmaticStringData, strlen(programmaticStringData));
+ auto programmaticString = StringImpl::createFromLiteral(programmaticStringData, strlen(programmaticStringData));
ASSERT_EQ(strlen(programmaticStringData), programmaticString->length());
ASSERT_TRUE(equal(programmaticString.get(), programmaticStringData));
ASSERT_EQ(programmaticStringData, reinterpret_cast<const char*>(programmaticString->characters8()));
@@ -48,27 +49,16 @@ TEST(WTF, StringImplCreationFromLiteral)
// Constructor without explicit size.
const char* stringWithoutLengthLiteral = "No Size Literal";
- RefPtr<StringImpl> programmaticStringNoLength = StringImpl::createFromLiteral(stringWithoutLengthLiteral);
+ auto programmaticStringNoLength = StringImpl::createFromLiteral(stringWithoutLengthLiteral);
ASSERT_EQ(strlen(stringWithoutLengthLiteral), programmaticStringNoLength->length());
ASSERT_TRUE(equal(programmaticStringNoLength.get(), stringWithoutLengthLiteral));
ASSERT_EQ(stringWithoutLengthLiteral, reinterpret_cast<const char*>(programmaticStringNoLength->characters8()));
ASSERT_TRUE(programmaticStringNoLength->is8Bit());
}
-TEST(WTF, StringImplFromLiteralLoop16BitConversion)
-{
- RefPtr<StringImpl> controlString = StringImpl::create("Template Literal");
- for (size_t i = 0; i < 10; ++i) {
- RefPtr<StringImpl> string = StringImpl::createFromLiteral("Template Literal");
-
- ASSERT_EQ(0, memcmp(controlString->deprecatedCharacters(), string->deprecatedCharacters(), controlString->length() * sizeof(UChar)));
- ASSERT_TRUE(string->has16BitShadow());
- }
-}
-
TEST(WTF, StringImplReplaceWithLiteral)
{
- RefPtr<StringImpl> testStringImpl = StringImpl::createFromLiteral("1224");
+ auto testStringImpl = StringImpl::createFromLiteral("1224");
ASSERT_TRUE(testStringImpl->is8Bit());
// Cases for 8Bit source.
@@ -110,4 +100,530 @@ TEST(WTF, StringImplReplaceWithLiteral)
ASSERT_TRUE(equal(testStringImpl.get(), "r555sum555"));
}
+TEST(WTF, StringImplEqualIgnoringASCIICaseBasic)
+{
+ auto a = StringImpl::createFromLiteral("aBcDeFG");
+ auto b = StringImpl::createFromLiteral("ABCDEFG");
+ auto c = StringImpl::createFromLiteral("abcdefg");
+ const char d[] = "aBcDeFG";
+ auto empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ auto shorter = StringImpl::createFromLiteral("abcdef");
+ auto different = StringImpl::createFromLiteral("abcrefg");
+
+ // Identity.
+ ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), a.ptr()));
+ ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), b.ptr()));
+ ASSERT_TRUE(equalIgnoringASCIICase(c.ptr(), c.ptr()));
+ ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), d));
+ ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), d));
+ ASSERT_TRUE(equalIgnoringASCIICase(c.ptr(), d));
+
+ // Transitivity.
+ ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), b.ptr()));
+ ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), c.ptr()));
+ ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), c.ptr()));
+
+ // Negative cases.
+ ASSERT_FALSE(equalIgnoringASCIICase(a.ptr(), empty.ptr()));
+ ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), empty.ptr()));
+ ASSERT_FALSE(equalIgnoringASCIICase(c.ptr(), empty.ptr()));
+ ASSERT_FALSE(equalIgnoringASCIICase(a.ptr(), shorter.ptr()));
+ ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), shorter.ptr()));
+ ASSERT_FALSE(equalIgnoringASCIICase(c.ptr(), shorter.ptr()));
+ ASSERT_FALSE(equalIgnoringASCIICase(a.ptr(), different.ptr()));
+ ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), different.ptr()));
+ ASSERT_FALSE(equalIgnoringASCIICase(c.ptr(), different.ptr()));
+ ASSERT_FALSE(equalIgnoringASCIICase(empty.ptr(), d));
+ ASSERT_FALSE(equalIgnoringASCIICase(shorter.ptr(), d));
+ ASSERT_FALSE(equalIgnoringASCIICase(different.ptr(), d));
+}
+
+TEST(WTF, StringImplEqualIgnoringASCIICaseWithNull)
+{
+ auto reference = StringImpl::createFromLiteral("aBcDeFG");
+ StringImpl* nullStringImpl = nullptr;
+ ASSERT_FALSE(equalIgnoringASCIICase(nullStringImpl, reference.ptr()));
+ ASSERT_FALSE(equalIgnoringASCIICase(reference.ptr(), nullStringImpl));
+ ASSERT_TRUE(equalIgnoringASCIICase(nullStringImpl, nullStringImpl));
+}
+
+TEST(WTF, StringImplEqualIgnoringASCIICaseWithEmpty)
+{
+ auto a = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ auto b = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), b.ptr()));
+ ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), a.ptr()));
+}
+
+static Ref<StringImpl> stringFromUTF8(const char* characters)
+{
+ return String::fromUTF8(characters).releaseImpl().releaseNonNull();
+}
+
+TEST(WTF, StringImplEqualIgnoringASCIICaseWithLatin1Characters)
+{
+ auto a = stringFromUTF8("aBcéeFG");
+ auto b = stringFromUTF8("ABCÉEFG");
+ auto c = stringFromUTF8("ABCéEFG");
+ auto d = stringFromUTF8("abcéefg");
+ const char e[] = "aBcéeFG";
+
+ // Identity.
+ ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), a.ptr()));
+ ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), b.ptr()));
+ ASSERT_TRUE(equalIgnoringASCIICase(c.ptr(), c.ptr()));
+ ASSERT_TRUE(equalIgnoringASCIICase(d.ptr(), d.ptr()));
+
+ // All combination.
+ ASSERT_FALSE(equalIgnoringASCIICase(a.ptr(), b.ptr()));
+ ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), c.ptr()));
+ ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), d.ptr()));
+ ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), c.ptr()));
+ ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), d.ptr()));
+ ASSERT_TRUE(equalIgnoringASCIICase(c.ptr(), d.ptr()));
+ ASSERT_FALSE(equalIgnoringASCIICase(a.ptr(), e));
+ ASSERT_FALSE(equalIgnoringASCIICase(b.ptr(), e));
+ ASSERT_FALSE(equalIgnoringASCIICase(c.ptr(), e));
+ ASSERT_FALSE(equalIgnoringASCIICase(d.ptr(), e));
+}
+
+TEST(WTF, StringImplFindIgnoringASCIICaseBasic)
+{
+ auto referenceA = stringFromUTF8("aBcéeFG");
+ auto referenceB = stringFromUTF8("ABCÉEFG");
+
+ // Search the exact string.
+ EXPECT_EQ(static_cast<size_t>(0), referenceA->findIgnoringASCIICase(referenceA.ptr()));
+ EXPECT_EQ(static_cast<size_t>(0), referenceB->findIgnoringASCIICase(referenceB.ptr()));
+
+ // A and B are distinct by the non-ascii character é/É.
+ EXPECT_EQ(static_cast<size_t>(notFound), referenceA->findIgnoringASCIICase(referenceB.ptr()));
+ EXPECT_EQ(static_cast<size_t>(notFound), referenceB->findIgnoringASCIICase(referenceA.ptr()));
+
+ // Find the prefix.
+ EXPECT_EQ(static_cast<size_t>(0), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("a").ptr()));
+ EXPECT_EQ(static_cast<size_t>(0), referenceA->findIgnoringASCIICase(stringFromUTF8("abcé").ptr()));
+ EXPECT_EQ(static_cast<size_t>(0), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("A").ptr()));
+ EXPECT_EQ(static_cast<size_t>(0), referenceA->findIgnoringASCIICase(stringFromUTF8("ABCé").ptr()));
+ EXPECT_EQ(static_cast<size_t>(0), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("a").ptr()));
+ EXPECT_EQ(static_cast<size_t>(0), referenceB->findIgnoringASCIICase(stringFromUTF8("abcÉ").ptr()));
+ EXPECT_EQ(static_cast<size_t>(0), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("A").ptr()));
+ EXPECT_EQ(static_cast<size_t>(0), referenceB->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr()));
+
+ // Not a prefix.
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("x").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("accé").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("abcÉ").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("X").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ABDé").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("y").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("accÉ").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("abcé").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("Y").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ABdÉ").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ABCé").ptr()));
+
+ // Find the infix.
+ EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("cée").ptr()));
+ EXPECT_EQ(static_cast<size_t>(3), referenceA->findIgnoringASCIICase(stringFromUTF8("ée").ptr()));
+ EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("cé").ptr()));
+ EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("c").ptr()));
+ EXPECT_EQ(static_cast<size_t>(3), referenceA->findIgnoringASCIICase(stringFromUTF8("é").ptr()));
+ EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("Cée").ptr()));
+ EXPECT_EQ(static_cast<size_t>(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éE").ptr()));
+ EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("Cé").ptr()));
+ EXPECT_EQ(static_cast<size_t>(2), referenceA->findIgnoringASCIICase(stringFromUTF8("C").ptr()));
+
+ EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("cÉe").ptr()));
+ EXPECT_EQ(static_cast<size_t>(3), referenceB->findIgnoringASCIICase(stringFromUTF8("Ée").ptr()));
+ EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("cÉ").ptr()));
+ EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("c").ptr()));
+ EXPECT_EQ(static_cast<size_t>(3), referenceB->findIgnoringASCIICase(stringFromUTF8("É").ptr()));
+ EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("CÉe").ptr()));
+ EXPECT_EQ(static_cast<size_t>(3), referenceB->findIgnoringASCIICase(stringFromUTF8("ÉE").ptr()));
+ EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("CÉ").ptr()));
+ EXPECT_EQ(static_cast<size_t>(2), referenceB->findIgnoringASCIICase(stringFromUTF8("C").ptr()));
+
+ // Not an infix.
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("céd").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Ée").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("bé").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("x").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("É").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("CÉe").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("éd").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("CÉ").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Y").ptr()));
+
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("cée").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("Éc").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("cé").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("W").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("é").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("bÉe").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éE").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("BÉ").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("z").ptr()));
+
+ // Find the suffix.
+ EXPECT_EQ(static_cast<size_t>(6), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("g").ptr()));
+ EXPECT_EQ(static_cast<size_t>(4), referenceA->findIgnoringASCIICase(stringFromUTF8("efg").ptr()));
+ EXPECT_EQ(static_cast<size_t>(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éefg").ptr()));
+ EXPECT_EQ(static_cast<size_t>(6), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("G").ptr()));
+ EXPECT_EQ(static_cast<size_t>(4), referenceA->findIgnoringASCIICase(stringFromUTF8("EFG").ptr()));
+ EXPECT_EQ(static_cast<size_t>(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éEFG").ptr()));
+
+ EXPECT_EQ(static_cast<size_t>(6), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("g").ptr()));
+ EXPECT_EQ(static_cast<size_t>(4), referenceB->findIgnoringASCIICase(stringFromUTF8("efg").ptr()));
+ EXPECT_EQ(static_cast<size_t>(3), referenceB->findIgnoringASCIICase(stringFromUTF8("Éefg").ptr()));
+ EXPECT_EQ(static_cast<size_t>(6), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("G").ptr()));
+ EXPECT_EQ(static_cast<size_t>(4), referenceB->findIgnoringASCIICase(stringFromUTF8("EFG").ptr()));
+ EXPECT_EQ(static_cast<size_t>(3), referenceB->findIgnoringASCIICase(stringFromUTF8("ÉEFG").ptr()));
+
+ // Not a suffix.
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("X").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("edg").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Éefg").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("w").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("dFG").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ÉEFG").ptr()));
+
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("Z").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ffg").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éefg").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("r").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("EgG").ptr()));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éEFG").ptr()));
+}
+
+TEST(WTF, StringImplFindIgnoringASCIICaseWithValidOffset)
+{
+ auto reference = stringFromUTF8("ABCÉEFGaBcéeFG");
+ EXPECT_EQ(static_cast<size_t>(0), reference->findIgnoringASCIICase(stringFromUTF8("ABC").ptr(), 0));
+ EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(stringFromUTF8("ABC").ptr(), 1));
+ EXPECT_EQ(static_cast<size_t>(0), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), 0));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), 1));
+ EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(stringFromUTF8("ABCé").ptr(), 0));
+ EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(stringFromUTF8("ABCé").ptr(), 1));
+}
+
+TEST(WTF, StringImplFindIgnoringASCIICaseWithInvalidOffset)
+{
+ auto reference = stringFromUTF8("ABCÉEFGaBcéeFG");
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABC").ptr(), 15));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABC").ptr(), 16));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), 17));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), 42));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), std::numeric_limits<unsigned>::max()));
+}
+
+TEST(WTF, StringImplFindIgnoringASCIICaseOnNull)
+{
+ auto reference = stringFromUTF8("ABCÉEFG");
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 0));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 3));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 7));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 8));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 42));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(nullptr, std::numeric_limits<unsigned>::max()));
+}
+
+TEST(WTF, StringImplFindIgnoringASCIICaseOnEmpty)
+{
+ auto reference = stringFromUTF8("ABCÉEFG");
+ auto empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ EXPECT_EQ(static_cast<size_t>(0), reference->findIgnoringASCIICase(empty.ptr()));
+ EXPECT_EQ(static_cast<size_t>(0), reference->findIgnoringASCIICase(empty.ptr(), 0));
+ EXPECT_EQ(static_cast<size_t>(3), reference->findIgnoringASCIICase(empty.ptr(), 3));
+ EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(empty.ptr(), 7));
+ EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(empty.ptr(), 8));
+ EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(empty.ptr(), 42));
+ EXPECT_EQ(static_cast<size_t>(7), reference->findIgnoringASCIICase(empty.ptr(), std::numeric_limits<unsigned>::max()));
+}
+
+TEST(WTF, StringImplFindIgnoringASCIICaseWithPatternLongerThanReference)
+{
+ auto reference = stringFromUTF8("ABCÉEFG");
+ auto pattern = stringFromUTF8("XABCÉEFG");
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference->findIgnoringASCIICase(pattern.ptr()));
+ EXPECT_EQ(static_cast<size_t>(1), pattern->findIgnoringASCIICase(reference.ptr()));
+}
+
+TEST(WTF, StringImplStartsWithIgnoringASCIICaseBasic)
+{
+ auto reference = stringFromUTF8("aBcéX");
+ auto referenceEquivalent = stringFromUTF8("AbCéx");
+
+ // Identity.
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(reference.ptr()));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*reference.ptr()));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(referenceEquivalent.ptr()));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*referenceEquivalent.ptr()));
+ ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(reference.ptr()));
+ ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(*reference.ptr()));
+ ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(referenceEquivalent.ptr()));
+ ASSERT_TRUE(referenceEquivalent->startsWithIgnoringASCIICase(*referenceEquivalent.ptr()));
+
+ // Proper prefixes.
+ auto aLower = StringImpl::createFromLiteral("a");
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(aLower.ptr()));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*aLower.ptr()));
+ auto aUpper = StringImpl::createFromLiteral("A");
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(aUpper.ptr()));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*aUpper.ptr()));
+
+ auto abcLower = StringImpl::createFromLiteral("abc");
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcLower.ptr()));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcLower.ptr()));
+ auto abcUpper = StringImpl::createFromLiteral("ABC");
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcUpper.ptr()));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcUpper.ptr()));
+
+ auto abcAccentLower = stringFromUTF8("abcé");
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcAccentLower.ptr()));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcAccentLower.ptr()));
+ auto abcAccentUpper = stringFromUTF8("ABCé");
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(abcAccentUpper.ptr()));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*abcAccentUpper.ptr()));
+
+ // Negative cases.
+ auto differentFirstChar = stringFromUTF8("bBcéX");
+ auto differentFirstCharProperPrefix = stringFromUTF8("CBcé");
+ ASSERT_FALSE(reference->startsWithIgnoringASCIICase(differentFirstChar.ptr()));
+ ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*differentFirstChar.ptr()));
+ ASSERT_FALSE(reference->startsWithIgnoringASCIICase(differentFirstCharProperPrefix.ptr()));
+ ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*differentFirstCharProperPrefix.ptr()));
+
+ auto uppercaseAccent = stringFromUTF8("aBcÉX");
+ auto uppercaseAccentProperPrefix = stringFromUTF8("aBcÉX");
+ ASSERT_FALSE(reference->startsWithIgnoringASCIICase(uppercaseAccent.ptr()));
+ ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*uppercaseAccent.ptr()));
+ ASSERT_FALSE(reference->startsWithIgnoringASCIICase(uppercaseAccentProperPrefix.ptr()));
+ ASSERT_FALSE(reference->startsWithIgnoringASCIICase(*uppercaseAccentProperPrefix.ptr()));
+}
+
+TEST(WTF, StringImplStartsWithIgnoringASCIICaseWithNull)
+{
+ auto reference = StringImpl::createFromLiteral("aBcDeFG");
+ ASSERT_FALSE(reference->startsWithIgnoringASCIICase(nullptr));
+
+ auto empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ ASSERT_FALSE(empty->startsWithIgnoringASCIICase(nullptr));
+}
+
+TEST(WTF, StringImplStartsWithIgnoringASCIICaseWithEmpty)
+{
+ auto reference = StringImpl::createFromLiteral("aBcDeFG");
+ auto empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(empty.ptr()));
+ ASSERT_TRUE(reference->startsWithIgnoringASCIICase(*empty.ptr()));
+ ASSERT_TRUE(empty->startsWithIgnoringASCIICase(empty.ptr()));
+ ASSERT_TRUE(empty->startsWithIgnoringASCIICase(*empty.ptr()));
+ ASSERT_FALSE(empty->startsWithIgnoringASCIICase(reference.ptr()));
+ ASSERT_FALSE(empty->startsWithIgnoringASCIICase(*reference.ptr()));
+}
+
+TEST(WTF, StartsWithLettersIgnoringASCIICase)
+{
+ String string("Test tEST");
+ ASSERT_TRUE(startsWithLettersIgnoringASCIICase(string, "test t"));
+ ASSERT_TRUE(startsWithLettersIgnoringASCIICase(string, "test te"));
+ ASSERT_TRUE(startsWithLettersIgnoringASCIICase(string, "test test"));
+ ASSERT_FALSE(startsWithLettersIgnoringASCIICase(string, "test tex"));
+
+ ASSERT_TRUE(startsWithLettersIgnoringASCIICase(string, ""));
+ ASSERT_TRUE(startsWithLettersIgnoringASCIICase(String(""), ""));
+
+ ASSERT_FALSE(startsWithLettersIgnoringASCIICase(String(), "t"));
+ ASSERT_FALSE(startsWithLettersIgnoringASCIICase(String(), ""));
+}
+
+TEST(WTF, StringImplEndsWithIgnoringASCIICaseBasic)
+{
+ auto reference = stringFromUTF8("XÉCbA");
+ auto referenceEquivalent = stringFromUTF8("xÉcBa");
+
+ // Identity.
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(reference.ptr()));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*reference.ptr()));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(referenceEquivalent.ptr()));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*referenceEquivalent.ptr()));
+ ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(reference.ptr()));
+ ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(*reference.ptr()));
+ ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(referenceEquivalent.ptr()));
+ ASSERT_TRUE(referenceEquivalent->endsWithIgnoringASCIICase(*referenceEquivalent.ptr()));
+
+ // Proper suffixes.
+ auto aLower = StringImpl::createFromLiteral("a");
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(aLower.ptr()));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*aLower.ptr()));
+ auto aUpper = StringImpl::createFromLiteral("a");
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(aUpper.ptr()));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*aUpper.ptr()));
+
+ auto abcLower = StringImpl::createFromLiteral("cba");
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcLower.ptr()));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcLower.ptr()));
+ auto abcUpper = StringImpl::createFromLiteral("CBA");
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcUpper.ptr()));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcUpper.ptr()));
+
+ auto abcAccentLower = stringFromUTF8("Écba");
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcAccentLower.ptr()));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcAccentLower.ptr()));
+ auto abcAccentUpper = stringFromUTF8("ÉCBA");
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(abcAccentUpper.ptr()));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*abcAccentUpper.ptr()));
+
+ // Negative cases.
+ auto differentLastChar = stringFromUTF8("XÉCbB");
+ auto differentLastCharProperSuffix = stringFromUTF8("ÉCbb");
+ ASSERT_FALSE(reference->endsWithIgnoringASCIICase(differentLastChar.ptr()));
+ ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*differentLastChar.ptr()));
+ ASSERT_FALSE(reference->endsWithIgnoringASCIICase(differentLastCharProperSuffix.ptr()));
+ ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*differentLastCharProperSuffix.ptr()));
+
+ auto lowercaseAccent = stringFromUTF8("aBcéX");
+ auto loweraseAccentProperSuffix = stringFromUTF8("aBcéX");
+ ASSERT_FALSE(reference->endsWithIgnoringASCIICase(lowercaseAccent.ptr()));
+ ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*lowercaseAccent.ptr()));
+ ASSERT_FALSE(reference->endsWithIgnoringASCIICase(loweraseAccentProperSuffix.ptr()));
+ ASSERT_FALSE(reference->endsWithIgnoringASCIICase(*loweraseAccentProperSuffix.ptr()));
+}
+
+TEST(WTF, StringImplEndsWithIgnoringASCIICaseWithNull)
+{
+ auto reference = StringImpl::createFromLiteral("aBcDeFG");
+ ASSERT_FALSE(reference->endsWithIgnoringASCIICase(nullptr));
+
+ auto empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ ASSERT_FALSE(empty->endsWithIgnoringASCIICase(nullptr));
+}
+
+TEST(WTF, StringImplEndsWithIgnoringASCIICaseWithEmpty)
+{
+ auto reference = StringImpl::createFromLiteral("aBcDeFG");
+ auto empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(empty.ptr()));
+ ASSERT_TRUE(reference->endsWithIgnoringASCIICase(*empty.ptr()));
+ ASSERT_TRUE(empty->endsWithIgnoringASCIICase(empty.ptr()));
+ ASSERT_TRUE(empty->endsWithIgnoringASCIICase(*empty.ptr()));
+ ASSERT_FALSE(empty->endsWithIgnoringASCIICase(reference.ptr()));
+ ASSERT_FALSE(empty->endsWithIgnoringASCIICase(*reference.ptr()));
+}
+
+TEST(WTF, StringImplCreateNullSymbol)
+{
+ auto reference = SymbolImpl::createNullSymbol();
+ ASSERT_TRUE(reference->isSymbol());
+ ASSERT_TRUE(reference->isNullSymbol());
+ ASSERT_FALSE(reference->isAtomic());
+ ASSERT_EQ(0u, reference->length());
+ ASSERT_TRUE(equal(reference.ptr(), ""));
+}
+
+TEST(WTF, StringImplCreateSymbol)
+{
+ auto original = stringFromUTF8("original");
+ auto reference = SymbolImpl::create(original);
+ ASSERT_TRUE(reference->isSymbol());
+ ASSERT_FALSE(reference->isNullSymbol());
+ ASSERT_FALSE(reference->isAtomic());
+ ASSERT_FALSE(original->isSymbol());
+ ASSERT_FALSE(original->isAtomic());
+ ASSERT_EQ(original->length(), reference->length());
+ ASSERT_TRUE(equal(reference.ptr(), "original"));
+
+ auto empty = stringFromUTF8("");
+ auto emptyReference = SymbolImpl::create(empty);
+ ASSERT_TRUE(emptyReference->isSymbol());
+ ASSERT_FALSE(emptyReference->isNullSymbol());
+ ASSERT_FALSE(emptyReference->isAtomic());
+ ASSERT_FALSE(empty->isSymbol());
+ ASSERT_TRUE(empty->isAtomic());
+ ASSERT_EQ(empty->length(), emptyReference->length());
+ ASSERT_TRUE(equal(emptyReference.ptr(), ""));
+}
+
+TEST(WTF, StringImplSymbolToAtomicString)
+{
+ auto original = stringFromUTF8("original");
+ auto reference = SymbolImpl::create(original);
+ ASSERT_TRUE(reference->isSymbol());
+ ASSERT_FALSE(reference->isAtomic());
+
+ auto result = AtomicStringImpl::lookUp(reference.ptr());
+ ASSERT_FALSE(result);
+
+ auto atomic = AtomicStringImpl::add(reference.ptr());
+ ASSERT_TRUE(atomic->isAtomic());
+ ASSERT_FALSE(atomic->isSymbol());
+ ASSERT_TRUE(reference->isSymbol());
+ ASSERT_FALSE(reference->isAtomic());
+
+ auto result2 = AtomicStringImpl::lookUp(reference.ptr());
+ ASSERT_TRUE(result2);
+}
+
+TEST(WTF, StringImplNullSymbolToAtomicString)
+{
+ auto reference = SymbolImpl::createNullSymbol();
+ ASSERT_TRUE(reference->isSymbol());
+ ASSERT_FALSE(reference->isAtomic());
+
+ // Because the substring of the reference is the empty string which is already interned.
+ auto result = AtomicStringImpl::lookUp(reference.ptr());
+ ASSERT_TRUE(result);
+
+ auto atomic = AtomicStringImpl::add(reference.ptr());
+ ASSERT_TRUE(atomic->isAtomic());
+ ASSERT_FALSE(atomic->isSymbol());
+ ASSERT_TRUE(reference->isSymbol());
+ ASSERT_FALSE(reference->isAtomic());
+ ASSERT_EQ(atomic.get(), StringImpl::empty());
+
+ auto result2 = AtomicStringImpl::lookUp(reference.ptr());
+ ASSERT_TRUE(result2);
+}
+
+static StringImpl::StaticStringImpl staticString {"Cocoa"};
+
+TEST(WTF, StringImplStaticToAtomicString)
+{
+ StringImpl& original = staticString;
+ ASSERT_FALSE(original.isSymbol());
+ ASSERT_FALSE(original.isAtomic());
+ ASSERT_TRUE(original.isStatic());
+
+ auto result = AtomicStringImpl::lookUp(&original);
+ ASSERT_FALSE(result);
+
+ auto atomic = AtomicStringImpl::add(&original);
+ ASSERT_TRUE(atomic->isAtomic());
+ ASSERT_FALSE(atomic->isSymbol());
+ ASSERT_FALSE(atomic->isStatic());
+ ASSERT_FALSE(original.isSymbol());
+ ASSERT_FALSE(original.isAtomic());
+ ASSERT_TRUE(original.isStatic());
+
+ auto result2 = AtomicStringImpl::lookUp(&original);
+ ASSERT_TRUE(result2);
+}
+
+TEST(WTF, StringImplConstexprHasher)
+{
+ ASSERT_EQ(stringFromUTF8("")->hash(), StringHasher::computeLiteralHashAndMaskTop8Bits(""));
+ ASSERT_EQ(stringFromUTF8("A")->hash(), StringHasher::computeLiteralHashAndMaskTop8Bits("A"));
+ ASSERT_EQ(stringFromUTF8("AA")->hash(), StringHasher::computeLiteralHashAndMaskTop8Bits("AA"));
+ ASSERT_EQ(stringFromUTF8("Cocoa")->hash(), StringHasher::computeLiteralHashAndMaskTop8Bits("Cocoa"));
+ ASSERT_EQ(stringFromUTF8("Cappuccino")->hash(), StringHasher::computeLiteralHashAndMaskTop8Bits("Cappuccino"));
+}
+
+TEST(WTF, StringImplEmpty)
+{
+ ASSERT_FALSE(StringImpl::empty()->length());
+}
+
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/StringOperators.cpp b/Tools/TestWebKitAPI/Tests/WTF/StringOperators.cpp
index 149b85b21..7a1d9297f 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/StringOperators.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/StringOperators.cpp
@@ -184,4 +184,20 @@ TEST(WTF, StringOperators)
#endif
}
+TEST(WTF, ConcatenateCharacterArrayAndEmptyString)
+{
+ String emptyString;
+ EXPECT_EQ(static_cast<unsigned>(0), emptyString.length());
+
+ UChar ucharArray[] = { 't', 'e', 's', 't', '\0' };
+ String concatenation16 = ucharArray + emptyString;
+ ASSERT_EQ(static_cast<unsigned>(4), concatenation16.length());
+ ASSERT_TRUE(concatenation16 == String(ucharArray));
+
+ LChar lcharArray[] = { 't', 'e', 's', 't', '\0' };
+ String concatenation8 = lcharArray + emptyString;
+ ASSERT_EQ(static_cast<unsigned>(4), concatenation8.length());
+ ASSERT_TRUE(concatenation8 == String(lcharArray));
+}
+
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/StringView.cpp b/Tools/TestWebKitAPI/Tests/WTF/StringView.cpp
new file mode 100644
index 000000000..93592834a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/StringView.cpp
@@ -0,0 +1,928 @@
+/*
+ * Copyright (C) 2014 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <wtf/text/StringBuilder.h>
+#include <wtf/text/StringView.h>
+
+namespace TestWebKitAPI {
+
+StringView stringViewFromLiteral(const char* characters)
+{
+ return StringView(reinterpret_cast<const LChar*>(characters), strlen(characters));
+}
+
+StringView stringViewFromUTF8(String &ref, const char* characters)
+{
+ ref = String::fromUTF8(characters);
+ return ref;
+}
+
+TEST(WTF, StringViewEmptyVsNull)
+{
+ StringView nullView;
+ EXPECT_TRUE(nullView.isNull());
+ EXPECT_TRUE(nullView.isEmpty());
+
+ // Test in a boolean context to test operator bool().
+ if (nullView)
+ FAIL();
+ else
+ SUCCEED();
+
+ if (!nullView)
+ SUCCEED();
+ else
+ FAIL();
+
+ StringView emptyView = StringView::empty();
+ EXPECT_FALSE(emptyView.isNull());
+ EXPECT_TRUE(emptyView.isEmpty());
+
+ // Test in a boolean context to test operator bool().
+ if (emptyView)
+ SUCCEED();
+ else
+ FAIL();
+
+ if (!emptyView)
+ FAIL();
+ else
+ SUCCEED();
+
+ StringView viewWithCharacters(String("hello"));
+ EXPECT_FALSE(viewWithCharacters.isNull());
+ EXPECT_FALSE(viewWithCharacters.isEmpty());
+
+ // Test in a boolean context to test operator bool().
+ if (viewWithCharacters)
+ SUCCEED();
+ else
+ FAIL();
+
+ if (!viewWithCharacters)
+ FAIL();
+ else
+ SUCCEED();
+}
+
+bool compareLoopIterations(StringView::GraphemeClusters graphemeClusters, std::vector<StringView> expected)
+{
+ std::vector<StringView> actual;
+ for (auto graphemeCluster : graphemeClusters)
+ actual.push_back(graphemeCluster);
+ return actual == expected;
+}
+
+bool compareLoopIterations(StringView::CodePoints codePoints, std::vector<UChar32> expected)
+{
+ std::vector<UChar32> actual;
+ for (auto codePoint : codePoints)
+ actual.push_back(codePoint);
+ return actual == expected;
+}
+
+static bool compareLoopIterations(StringView::CodeUnits codeUnits, std::vector<UChar> expected)
+{
+ std::vector<UChar> actual;
+ for (auto codeUnit : codeUnits)
+ actual.push_back(codeUnit);
+ return actual == expected;
+}
+
+static void build(StringBuilder& builder, std::vector<UChar> input)
+{
+ builder.clear();
+ for (auto codeUnit : input)
+ builder.append(codeUnit);
+}
+
+TEST(WTF, StringViewIterators)
+{
+ EXPECT_TRUE(compareLoopIterations(StringView().codePoints(), { }));
+ EXPECT_TRUE(compareLoopIterations(StringView().codeUnits(), { }));
+ EXPECT_TRUE(compareLoopIterations(StringView().graphemeClusters(), { }));
+
+ EXPECT_TRUE(compareLoopIterations(StringView::empty().codePoints(), { }));
+ EXPECT_TRUE(compareLoopIterations(StringView::empty().codeUnits(), { }));
+ EXPECT_TRUE(compareLoopIterations(StringView::empty().graphemeClusters(), { }));
+
+ String helo("helo");
+ StringView heloView(helo);
+
+ auto codePoints = heloView.codePoints();
+ auto codePointsIterator = codePoints.begin();
+ EXPECT_EQ(*codePointsIterator, 'h');
+ EXPECT_EQ(*codePointsIterator, 'h');
+ ++codePointsIterator;
+ ++codePointsIterator;
+ EXPECT_EQ(*codePointsIterator, 'l');
+ auto savedIterator = codePointsIterator;
+ codePointsIterator = codePoints.begin();
+ EXPECT_EQ(*codePointsIterator, 'h');
+ codePointsIterator = savedIterator;
+ EXPECT_EQ(*codePointsIterator, 'l');
+ String webkit("webkit");
+ auto webkitCodePoints = StringView(webkit).codePoints();
+ codePointsIterator = webkitCodePoints.begin();
+ ++codePointsIterator;
+ ++codePointsIterator;
+ EXPECT_EQ(*codePointsIterator, 'b');
+ while (codePointsIterator != webkitCodePoints.end())
+ ++codePointsIterator;
+
+ EXPECT_TRUE(compareLoopIterations(heloView.codePoints(), {'h', 'e', 'l', 'o'}));
+ EXPECT_TRUE(compareLoopIterations(heloView.codeUnits(), {'h', 'e', 'l', 'o'}));
+ EXPECT_TRUE(compareLoopIterations(heloView.graphemeClusters(), {
+ StringView(heloView.characters8(), 1),
+ StringView(heloView.characters8() + 1, 1),
+ StringView(heloView.characters8() + 2, 1),
+ StringView(heloView.characters8() + 3, 1)}));
+
+ StringBuilder b;
+ build(b, {0xD800, 0xDD55}); // Surrogates for unicode code point U+10155
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0x10155}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0xD800, 0xDD55}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {StringView(b.toString())}));
+
+ build(b, {0xD800}); // Leading surrogate only
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0xD800}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0xD800}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {StringView(b.toString())}));
+
+ build(b, {0xD800, 0xD801}); // Two leading surrogates
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0xD800, 0xD801}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0xD800, 0xD801}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {StringView(b.characters16(), 1), StringView(b.characters16() + 1, 1)}));
+
+ build(b, {0xDD55}); // Trailing surrogate only
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0xDD55}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0xDD55}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {StringView(b.toString())}));
+
+ build(b, {0xD800, 'h'}); // Leading surrogate followed by non-surrogate
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0xD800, 'h'}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0xD800, 'h'}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {StringView(b.characters16(), 1), StringView(b.characters16() + 1, 1)}));
+
+ build(b, {0x0306}); // "COMBINING BREVE"
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0x0306}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0x0306}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {StringView(b.toString())}));
+
+ build(b, {0x0306, 0xD800, 0xDD55, 'h', 'e', 'l', 'o'}); // Mix of single code unit and multi code unit code points
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0x0306, 0x10155, 'h', 'e', 'l', 'o'}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0x0306, 0xD800, 0xDD55, 'h', 'e', 'l', 'o'}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {
+ StringView(b.characters16(), 1),
+ StringView(b.characters16() + 1, 2),
+ StringView(b.characters16() + 3, 1),
+ StringView(b.characters16() + 4, 1),
+ StringView(b.characters16() + 5, 1),
+ StringView(b.characters16() + 6, 1)}));
+
+ build(b, {'e', 0x0301}); // "COMBINING ACUTE"
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {'e', 0x0301}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {'e', 0x0301}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {StringView(b.toString())}));
+
+ build(b, {'e', 0x0301, 0x0306, 'a'}); // "COMBINING ACUTE" "COMBINING BREVE"
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {'e', 0x0301, 0x0306, 'a'}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {'e', 0x0301, 0x0306, 'a'}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {
+ StringView(b.characters16(), 3),
+ StringView(b.characters16() + 3, 1),
+ }));
+
+ build(b, {0x1112, 0x116f, 0x11b6, 0x1107, 0x1161, 0x11B8}); // Korean combining Jamo
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codePoints(), {0x1112, 0x116f, 0x11b6, 0x1107, 0x1161, 0x11B8}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0x1112, 0x116f, 0x11b6, 0x1107, 0x1161, 0x11B8}));
+ EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).graphemeClusters(), {
+ StringView(b.characters16(), 3),
+ StringView(b.characters16() + 3, 3)}));
+}
+
+static Vector<String> vectorFromSplitResult(const StringView::SplitResult& substrings)
+{
+ Vector<String> result;
+ for (StringView substring : substrings)
+ result.append(substring.toString());
+ return result;
+}
+
+TEST(WTF, StringViewSplitEmptyAndNullStrings)
+{
+ StringView a = emptyString();
+ auto splitResult = a.split('b');
+ EXPECT_TRUE(splitResult.begin() == splitResult.end());
+
+ a = { String { } };
+ splitResult = a.split('b');
+ EXPECT_TRUE(splitResult.begin() == splitResult.end());
+
+ a = { };
+ splitResult = a.split('b');
+ EXPECT_TRUE(splitResult.begin() == splitResult.end());
+}
+
+TEST(WTF, StringViewSplitBasic)
+{
+ String referenceHolder;
+ StringView a = stringViewFromUTF8(referenceHolder, "This is a sentence.");
+
+ // Simple
+ Vector<String> actual = vectorFromSplitResult(a.split('T'));
+ Vector<String> expected({ "his is a sentence." });
+ ASSERT_EQ(expected.size(), actual.size());
+ for (size_t i = 0; i < actual.size(); ++i)
+ EXPECT_STREQ(expected[i].utf8().data(), actual[i].utf8().data()) << "Vectors differ at index " << i;
+
+ actual = vectorFromSplitResult(a.split('.'));
+ expected = { "This is a sentence" };
+ ASSERT_EQ(expected.size(), actual.size());
+ for (size_t i = 0; i < actual.size(); ++i)
+ EXPECT_STREQ(expected[i].utf8().data(), actual[i].utf8().data()) << "Vectors differ at index " << i;
+
+ actual = vectorFromSplitResult(a.split('a'));
+ expected = { "This is ", " sentence." };
+ ASSERT_EQ(expected.size(), actual.size());
+ for (size_t i = 0; i < actual.size(); ++i)
+ EXPECT_STREQ(expected[i].utf8().data(), actual[i].utf8().data()) << "Vectors differ at index " << i;
+
+ actual = vectorFromSplitResult(a.split(' '));
+ expected = { "This", "is", "a", "sentence." };
+ ASSERT_EQ(expected.size(), actual.size());
+ for (size_t i = 0; i < actual.size(); ++i)
+ EXPECT_STREQ(expected[i].utf8().data(), actual[i].utf8().data()) << "Vectors differ at index " << i;
+
+ // Non-existent separator
+ actual = vectorFromSplitResult(a.split('z'));
+ expected = { "This is a sentence." };
+ ASSERT_EQ(expected.size(), actual.size());
+ for (size_t i = 0; i < actual.size(); ++i)
+ EXPECT_STREQ(expected[i].utf8().data(), actual[i].utf8().data()) << "Vectors differ at index " << i;
+}
+
+TEST(WTF, StringViewSplitWithConsecutiveSeparators)
+{
+ String referenceHolder;
+ StringView a = stringViewFromUTF8(referenceHolder, "This is a sentence.");
+
+ Vector<String> actual = vectorFromSplitResult(a.split(' '));
+ Vector<String> expected({ "This", "is", "a", "sentence." });
+ ASSERT_EQ(expected.size(), actual.size());
+ for (size_t i = 0; i < actual.size(); ++i)
+ EXPECT_STREQ(expected[i].utf8().data(), actual[i].utf8().data()) << "Vectors differ at index " << i;
+}
+
+TEST(WTF, StringViewEqualIgnoringASCIICaseBasic)
+{
+ RefPtr<StringImpl> a = StringImpl::createFromLiteral("aBcDeFG");
+ RefPtr<StringImpl> b = StringImpl::createFromLiteral("ABCDEFG");
+ RefPtr<StringImpl> c = StringImpl::createFromLiteral("abcdefg");
+ const char d[] = "aBcDeFG";
+ RefPtr<StringImpl> empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ RefPtr<StringImpl> shorter = StringImpl::createFromLiteral("abcdef");
+ RefPtr<StringImpl> different = StringImpl::createFromLiteral("abcrefg");
+
+ StringView stringViewA(*a.get());
+ StringView stringViewB(*b.get());
+ StringView stringViewC(*c.get());
+ StringView emptyStringView(*empty.get());
+ StringView shorterStringView(*shorter.get());
+ StringView differentStringView(*different.get());
+
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewB));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewC));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewC));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, d));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, d));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewC, d));
+
+ // Identity.
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewA));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewB));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewC, stringViewC));
+
+ // Transitivity.
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewB));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewC));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewC));
+
+ // Negative cases.
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewA, emptyStringView));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, emptyStringView));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewC, emptyStringView));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewA, shorterStringView));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, shorterStringView));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewC, shorterStringView));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewA, differentStringView));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, differentStringView));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewC, differentStringView));
+ ASSERT_FALSE(equalIgnoringASCIICase(emptyStringView, d));
+ ASSERT_FALSE(equalIgnoringASCIICase(shorterStringView, d));
+ ASSERT_FALSE(equalIgnoringASCIICase(differentStringView, d));
+}
+
+TEST(WTF, StringViewEqualIgnoringASCIICaseWithEmpty)
+{
+ RefPtr<StringImpl> a = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ RefPtr<StringImpl> b = StringImpl::create(reinterpret_cast<const LChar*>(""));
+ StringView stringViewA(*a.get());
+ StringView stringViewB(*b.get());
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewB));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewA));
+}
+
+TEST(WTF, StringViewEqualIgnoringASCIICaseWithLatin1Characters)
+{
+ RefPtr<StringImpl> a = StringImpl::create(reinterpret_cast<const LChar*>("aBcéeFG"));
+ RefPtr<StringImpl> b = StringImpl::create(reinterpret_cast<const LChar*>("ABCÉEFG"));
+ RefPtr<StringImpl> c = StringImpl::create(reinterpret_cast<const LChar*>("ABCéEFG"));
+ RefPtr<StringImpl> d = StringImpl::create(reinterpret_cast<const LChar*>("abcéefg"));
+ const char e[] = "aBcéeFG";
+ StringView stringViewA(*a.get());
+ StringView stringViewB(*b.get());
+ StringView stringViewC(*c.get());
+ StringView stringViewD(*d.get());
+
+ // Identity.
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewA));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewB));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewC, stringViewC));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewD, stringViewD));
+
+ // All combination.
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewA, stringViewB));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewC));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewD));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, stringViewC));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, stringViewD));
+ ASSERT_TRUE(equalIgnoringASCIICase(stringViewC, stringViewD));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewA, e));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, e));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewC, e));
+ ASSERT_FALSE(equalIgnoringASCIICase(stringViewD, e));
+}
+
+TEST(WTF, StringViewFindIgnoringASCIICaseBasic)
+{
+ String referenceAHolder;
+ StringView referenceA = stringViewFromUTF8(referenceAHolder, "aBcéeFG");
+ String referenceBHolder;
+ StringView referenceB = stringViewFromUTF8(referenceBHolder, "ABCÉEFG");
+
+ // Search the exact string.
+ EXPECT_EQ(static_cast<size_t>(0), referenceA.findIgnoringASCIICase(referenceA));
+ EXPECT_EQ(static_cast<size_t>(0), referenceB.findIgnoringASCIICase(referenceB));
+
+ // A and B are distinct by the non-ascii character é/É.
+ EXPECT_EQ(static_cast<size_t>(notFound), referenceA.findIgnoringASCIICase(referenceB));
+ EXPECT_EQ(static_cast<size_t>(notFound), referenceB.findIgnoringASCIICase(referenceA));
+
+ String tempStringHolder;
+ // Find the prefix.
+ EXPECT_EQ(static_cast<size_t>(0), referenceA.findIgnoringASCIICase(stringViewFromLiteral("a")));
+ EXPECT_EQ(static_cast<size_t>(0), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "abcé")));
+ EXPECT_EQ(static_cast<size_t>(0), referenceA.findIgnoringASCIICase(stringViewFromLiteral("A")));
+ EXPECT_EQ(static_cast<size_t>(0), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCé")));
+ EXPECT_EQ(static_cast<size_t>(0), referenceB.findIgnoringASCIICase(stringViewFromLiteral("a")));
+ EXPECT_EQ(static_cast<size_t>(0), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "abcÉ")));
+ EXPECT_EQ(static_cast<size_t>(0), referenceB.findIgnoringASCIICase(stringViewFromLiteral("A")));
+ EXPECT_EQ(static_cast<size_t>(0), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ")));
+
+ // Not a prefix.
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromLiteral("x")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "accé")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "abcÉ")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromLiteral("X")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABDé")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromLiteral("y")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "accÉ")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "abcé")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromLiteral("Y")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABdÉ")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCé")));
+
+ // Find the infix.
+ EXPECT_EQ(static_cast<size_t>(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cée")));
+ EXPECT_EQ(static_cast<size_t>(3), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ée")));
+ EXPECT_EQ(static_cast<size_t>(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cé")));
+ EXPECT_EQ(static_cast<size_t>(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "c")));
+ EXPECT_EQ(static_cast<size_t>(3), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "é")));
+ EXPECT_EQ(static_cast<size_t>(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Cée")));
+ EXPECT_EQ(static_cast<size_t>(3), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éE")));
+ EXPECT_EQ(static_cast<size_t>(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Cé")));
+ EXPECT_EQ(static_cast<size_t>(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "C")));
+
+ EXPECT_EQ(static_cast<size_t>(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cÉe")));
+ EXPECT_EQ(static_cast<size_t>(3), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Ée")));
+ EXPECT_EQ(static_cast<size_t>(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cÉ")));
+ EXPECT_EQ(static_cast<size_t>(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "c")));
+ EXPECT_EQ(static_cast<size_t>(3), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "É")));
+ EXPECT_EQ(static_cast<size_t>(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "CÉe")));
+ EXPECT_EQ(static_cast<size_t>(3), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ÉE")));
+ EXPECT_EQ(static_cast<size_t>(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "CÉ")));
+ EXPECT_EQ(static_cast<size_t>(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "C")));
+
+ // Not an infix.
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "céd")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Ée")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "bé")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "x")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "É")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "CÉe")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éd")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "CÉ")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Y")));
+
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cée")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Éc")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cé")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "W")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "é")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "bÉe")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éE")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "BÉ")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "z")));
+
+ // Find the suffix.
+ EXPECT_EQ(static_cast<size_t>(6), referenceA.findIgnoringASCIICase(stringViewFromLiteral("g")));
+ EXPECT_EQ(static_cast<size_t>(4), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "efg")));
+ EXPECT_EQ(static_cast<size_t>(3), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éefg")));
+ EXPECT_EQ(static_cast<size_t>(6), referenceA.findIgnoringASCIICase(stringViewFromLiteral("G")));
+ EXPECT_EQ(static_cast<size_t>(4), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "EFG")));
+ EXPECT_EQ(static_cast<size_t>(3), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éEFG")));
+
+ EXPECT_EQ(static_cast<size_t>(6), referenceB.findIgnoringASCIICase(stringViewFromLiteral("g")));
+ EXPECT_EQ(static_cast<size_t>(4), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "efg")));
+ EXPECT_EQ(static_cast<size_t>(3), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Éefg")));
+ EXPECT_EQ(static_cast<size_t>(6), referenceB.findIgnoringASCIICase(stringViewFromLiteral("G")));
+ EXPECT_EQ(static_cast<size_t>(4), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "EFG")));
+ EXPECT_EQ(static_cast<size_t>(3), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ÉEFG")));
+
+ // Not a suffix.
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromLiteral("X")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "edg")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Éefg")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromLiteral("w")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "dFG")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ÉEFG")));
+
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromLiteral("Z")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ffg")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éefg")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromLiteral("r")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "EgG")));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éEFG")));
+}
+
+TEST(WTF, StringViewFindIgnoringASCIICaseWithValidOffset)
+{
+ String referenceHolder;
+ StringView reference = stringViewFromUTF8(referenceHolder, "ABCÉEFGaBcéeFG");
+ String tempStringHolder;
+
+ EXPECT_EQ(static_cast<size_t>(0), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABC"), 0));
+ EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABC"), 1));
+ EXPECT_EQ(static_cast<size_t>(0), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"), 0));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"), 1));
+ EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCé"), 0));
+ EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCé"), 1));
+}
+
+TEST(WTF, StringViewFindIgnoringASCIICaseWithInvalidOffset)
+{
+ String referenceHolder;
+ StringView reference = stringViewFromUTF8(referenceHolder, "ABCÉEFGaBcéeFG");
+ String tempStringHolder;
+
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABC"), 15));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABC"), 16));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"), 17));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"), 42));
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"), std::numeric_limits<unsigned>::max()));
+}
+
+TEST(WTF, StringViewFindIgnoringASCIICaseOnEmpty)
+{
+ String referenceHolder;
+ StringView reference = stringViewFromUTF8(referenceHolder, "ABCÉEFG");
+ StringView empty = stringViewFromLiteral("");
+ EXPECT_EQ(static_cast<size_t>(0), reference.findIgnoringASCIICase(empty));
+ EXPECT_EQ(static_cast<size_t>(0), reference.findIgnoringASCIICase(empty, 0));
+ EXPECT_EQ(static_cast<size_t>(3), reference.findIgnoringASCIICase(empty, 3));
+ EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(empty, 7));
+ EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(empty, 8));
+ EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(empty, 42));
+ EXPECT_EQ(static_cast<size_t>(7), reference.findIgnoringASCIICase(empty, std::numeric_limits<unsigned>::max()));
+}
+
+TEST(WTF, StringViewFindIgnoringASCIICaseWithPatternLongerThanReference)
+{
+ String referenceHolder;
+ StringView reference = stringViewFromUTF8(referenceHolder, "ABCÉEFG");
+ String patternHolder;
+ StringView pattern = stringViewFromUTF8(patternHolder, "ABCÉEFGA");
+
+ EXPECT_EQ(static_cast<size_t>(WTF::notFound), reference.findIgnoringASCIICase(pattern));
+ EXPECT_EQ(static_cast<size_t>(0), pattern.findIgnoringASCIICase(reference));
+}
+
+TEST(WTF, StringViewStartsWithBasic)
+{
+ StringView reference = stringViewFromLiteral("abcdefg");
+ String referenceUTF8Ref;
+ StringView referenceUTF8 = stringViewFromUTF8(referenceUTF8Ref, "àîûèô");
+
+ StringView oneLetterPrefix = stringViewFromLiteral("a");
+ StringView shortPrefix = stringViewFromLiteral("abc");
+ StringView longPrefix = stringViewFromLiteral("abcdef");
+ StringView upperCasePrefix = stringViewFromLiteral("ABC");
+ StringView empty = stringViewFromLiteral("");
+ StringView notPrefix = stringViewFromLiteral("bc");
+
+ String oneLetterPrefixUTF8Ref;
+ StringView oneLetterPrefixUTF8 = stringViewFromUTF8(oneLetterPrefixUTF8Ref, "à");
+ String shortPrefixUTF8Ref;
+ StringView shortPrefixUTF8 = stringViewFromUTF8(shortPrefixUTF8Ref, "àî");
+ String longPrefixUTF8Ref;
+ StringView longPrefixUTF8 = stringViewFromUTF8(longPrefixUTF8Ref, "àîûè");
+ String upperCasePrefixUTF8Ref;
+ StringView upperCasePrefixUTF8 = stringViewFromUTF8(upperCasePrefixUTF8Ref, "ÀÎ");
+ String notPrefixUTF8Ref;
+ StringView notPrefixUTF8 = stringViewFromUTF8(notPrefixUTF8Ref, "îû");
+
+ EXPECT_TRUE(reference.startsWith(reference));
+ EXPECT_TRUE(reference.startsWith(oneLetterPrefix));
+ EXPECT_TRUE(reference.startsWith(shortPrefix));
+ EXPECT_TRUE(reference.startsWith(longPrefix));
+ EXPECT_TRUE(reference.startsWith(empty));
+
+ EXPECT_TRUE(referenceUTF8.startsWith(referenceUTF8));
+ EXPECT_TRUE(referenceUTF8.startsWith(oneLetterPrefixUTF8));
+ EXPECT_TRUE(referenceUTF8.startsWith(shortPrefixUTF8));
+ EXPECT_TRUE(referenceUTF8.startsWith(longPrefixUTF8));
+ EXPECT_TRUE(referenceUTF8.startsWith(empty));
+
+ EXPECT_FALSE(reference.startsWith(notPrefix));
+ EXPECT_FALSE(reference.startsWith(upperCasePrefix));
+ EXPECT_FALSE(reference.startsWith(notPrefixUTF8));
+ EXPECT_FALSE(reference.startsWith(upperCasePrefixUTF8));
+ EXPECT_FALSE(referenceUTF8.startsWith(notPrefix));
+ EXPECT_FALSE(referenceUTF8.startsWith(upperCasePrefix));
+ EXPECT_FALSE(referenceUTF8.startsWith(notPrefixUTF8));
+ EXPECT_FALSE(referenceUTF8.startsWith(upperCasePrefixUTF8));
+}
+
+TEST(WTF, StringViewStartsWithEmpty)
+{
+ StringView a = stringViewFromLiteral("");
+ String refB;
+ StringView b = stringViewFromUTF8(refB, "");
+
+ EXPECT_TRUE(a.startsWith(a));
+ EXPECT_TRUE(a.startsWith(b));
+ EXPECT_TRUE(b.startsWith(a));
+ EXPECT_TRUE(b.startsWith(b));
+}
+
+TEST(WTF, StringViewStartsWithIgnoringASCIICaseBasic)
+{
+ StringView reference = stringViewFromLiteral("abcdefg");
+
+ String referenceUTF8Ref;
+ StringView referenceUTF8 = stringViewFromUTF8(referenceUTF8Ref, "àîûèô");
+
+ StringView oneLetterPrefix = stringViewFromLiteral("a");
+ StringView shortPrefix = stringViewFromLiteral("abc");
+ StringView longPrefix = stringViewFromLiteral("abcdef");
+ StringView upperCasePrefix = stringViewFromLiteral("ABC");
+ StringView mixedCasePrefix = stringViewFromLiteral("aBcDe");
+ StringView empty = stringViewFromLiteral("");
+ StringView notPrefix = stringViewFromLiteral("bc");
+
+ String oneLetterPrefixUTF8Ref;
+ StringView oneLetterPrefixUTF8 = stringViewFromUTF8(oneLetterPrefixUTF8Ref, "à");
+ String shortPrefixUTF8Ref;
+ StringView shortPrefixUTF8 = stringViewFromUTF8(shortPrefixUTF8Ref, "àî");
+ String longPrefixUTF8Ref;
+ StringView longPrefixUTF8 = stringViewFromUTF8(longPrefixUTF8Ref, "àîûè");
+ String upperCasePrefixUTF8Ref;
+ StringView upperCasePrefixUTF8 = stringViewFromUTF8(upperCasePrefixUTF8Ref, "ÀÎ");
+ String notPrefixUTF8Ref;
+ StringView notPrefixUTF8 = stringViewFromUTF8(notPrefixUTF8Ref, "îû");
+
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(reference));
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(oneLetterPrefix));
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(shortPrefix));
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(longPrefix));
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(empty));
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(upperCasePrefix));
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(mixedCasePrefix));
+
+ EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(referenceUTF8));
+ EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(oneLetterPrefixUTF8));
+ EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(shortPrefixUTF8));
+ EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(longPrefixUTF8));
+ EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(empty));
+
+ EXPECT_FALSE(reference.startsWithIgnoringASCIICase(notPrefix));
+ EXPECT_FALSE(reference.startsWithIgnoringASCIICase(notPrefixUTF8));
+ EXPECT_FALSE(reference.startsWithIgnoringASCIICase(upperCasePrefixUTF8));
+ EXPECT_FALSE(referenceUTF8.startsWithIgnoringASCIICase(notPrefix));
+ EXPECT_FALSE(referenceUTF8.startsWithIgnoringASCIICase(notPrefixUTF8));
+ EXPECT_FALSE(referenceUTF8.startsWithIgnoringASCIICase(upperCasePrefix));
+ EXPECT_FALSE(referenceUTF8.startsWithIgnoringASCIICase(upperCasePrefixUTF8));
+}
+
+
+TEST(WTF, StringViewStartsWithIgnoringASCIICaseEmpty)
+{
+ StringView a = stringViewFromLiteral("");
+ String refB;
+ StringView b = stringViewFromUTF8(refB, "");
+
+ EXPECT_TRUE(a.startsWithIgnoringASCIICase(a));
+ EXPECT_TRUE(a.startsWithIgnoringASCIICase(b));
+ EXPECT_TRUE(b.startsWithIgnoringASCIICase(a));
+ EXPECT_TRUE(b.startsWithIgnoringASCIICase(b));
+}
+
+TEST(WTF, StringViewStartsWithIgnoringASCIICaseWithLatin1Characters)
+{
+ StringView reference = stringViewFromLiteral("aBcéeFG");
+ String referenceUTF8Ref;
+ StringView referenceUTF8 = stringViewFromUTF8(referenceUTF8Ref, "aBcéeFG");
+
+ StringView a = stringViewFromLiteral("aBcéeF");
+ StringView b = stringViewFromLiteral("ABCéEF");
+ StringView c = stringViewFromLiteral("abcéef");
+ StringView d = stringViewFromLiteral("Abcéef");
+
+ String refE;
+ StringView e = stringViewFromUTF8(refE, "aBcéeF");
+ String refF;
+ StringView f = stringViewFromUTF8(refF, "ABCéEF");
+ String refG;
+ StringView g = stringViewFromUTF8(refG, "abcéef");
+ String refH;
+ StringView h = stringViewFromUTF8(refH, "Abcéef");
+
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(a));
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(b));
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(c));
+ EXPECT_TRUE(reference.startsWithIgnoringASCIICase(d));
+
+ EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(e));
+ EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(f));
+ EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(g));
+ EXPECT_TRUE(referenceUTF8.startsWithIgnoringASCIICase(h));
+
+ EXPECT_FALSE(reference.endsWithIgnoringASCIICase(referenceUTF8));
+ EXPECT_FALSE(referenceUTF8.endsWithIgnoringASCIICase(reference));
+}
+
+TEST(WTF, StringViewEndsWithBasic)
+{
+ StringView reference = stringViewFromLiteral("abcdefg");
+ String referenceUTF8Ref;
+ StringView referenceUTF8 = stringViewFromUTF8(referenceUTF8Ref, "àîûèô");
+
+ StringView oneLetterSuffix = stringViewFromLiteral("g");
+ StringView shortSuffix = stringViewFromLiteral("efg");
+ StringView longSuffix = stringViewFromLiteral("cdefg");
+ StringView upperCaseSuffix = stringViewFromLiteral("EFG");
+ StringView empty = stringViewFromLiteral("");
+ StringView notSuffix = stringViewFromLiteral("bc");
+
+ String oneLetterSuffixUTF8Ref;
+ StringView oneLetterSuffixUTF8 = stringViewFromUTF8(oneLetterSuffixUTF8Ref, "ô");
+ String shortSuffixUTF8Ref;
+ StringView shortSuffixUTF8 = stringViewFromUTF8(shortSuffixUTF8Ref, "èô");
+ String longSuffixUTF8Ref;
+ StringView longSuffixUTF8 = stringViewFromUTF8(longSuffixUTF8Ref, "îûèô");
+ String upperCaseSuffixUTF8Ref;
+ StringView upperCaseSuffixUTF8 = stringViewFromUTF8(upperCaseSuffixUTF8Ref, "ÈÔ");
+ String notSuffixUTF8Ref;
+ StringView notSuffixUTF8 = stringViewFromUTF8(notSuffixUTF8Ref, "îû");
+
+ EXPECT_TRUE(reference.endsWith(reference));
+ EXPECT_TRUE(reference.endsWith(oneLetterSuffix));
+ EXPECT_TRUE(reference.endsWith(shortSuffix));
+ EXPECT_TRUE(reference.endsWith(longSuffix));
+ EXPECT_TRUE(reference.endsWith(empty));
+
+ EXPECT_TRUE(referenceUTF8.endsWith(referenceUTF8));
+ EXPECT_TRUE(referenceUTF8.endsWith(oneLetterSuffixUTF8));
+ EXPECT_TRUE(referenceUTF8.endsWith(shortSuffixUTF8));
+ EXPECT_TRUE(referenceUTF8.endsWith(longSuffixUTF8));
+ EXPECT_TRUE(referenceUTF8.endsWith(empty));
+
+ EXPECT_FALSE(reference.endsWith(notSuffix));
+ EXPECT_FALSE(reference.endsWith(upperCaseSuffix));
+ EXPECT_FALSE(reference.endsWith(notSuffixUTF8));
+ EXPECT_FALSE(reference.endsWith(upperCaseSuffixUTF8));
+ EXPECT_FALSE(referenceUTF8.endsWith(notSuffix));
+ EXPECT_FALSE(referenceUTF8.endsWith(upperCaseSuffix));
+ EXPECT_FALSE(referenceUTF8.endsWith(notSuffixUTF8));
+ EXPECT_FALSE(referenceUTF8.endsWith(upperCaseSuffixUTF8));
+}
+
+TEST(WTF, StringViewEndsWithEmpty)
+{
+ StringView a = stringViewFromLiteral("");
+ String refB;
+ StringView b = stringViewFromUTF8(refB, "");
+
+ EXPECT_TRUE(a.endsWith(a));
+ EXPECT_TRUE(a.endsWith(b));
+ EXPECT_TRUE(b.endsWith(a));
+ EXPECT_TRUE(b.endsWith(b));
+}
+
+TEST(WTF, StringViewEndsWithIgnoringASCIICaseBasic)
+{
+ StringView reference = stringViewFromLiteral("abcdefg");
+ String referenceUTF8Ref;
+ StringView referenceUTF8 = stringViewFromUTF8(referenceUTF8Ref, "àîûèô");
+
+ StringView oneLetterSuffix = stringViewFromLiteral("g");
+ StringView shortSuffix = stringViewFromLiteral("efg");
+ StringView longSuffix = stringViewFromLiteral("bcdefg");
+ StringView upperCaseSuffix = stringViewFromLiteral("EFG");
+ StringView mixedCaseSuffix = stringViewFromLiteral("bCdeFg");
+ StringView empty = stringViewFromLiteral("");
+ StringView notSuffix = stringViewFromLiteral("bc");
+
+ String oneLetterSuffixUTF8Ref;
+ StringView oneLetterSuffixUTF8 = stringViewFromUTF8(oneLetterSuffixUTF8Ref, "ô");
+ String shortSuffixUTF8Ref;
+ StringView shortSuffixUTF8 = stringViewFromUTF8(shortSuffixUTF8Ref, "èô");
+ String longSuffixUTF8Ref;
+ StringView longSuffixUTF8 = stringViewFromUTF8(longSuffixUTF8Ref, "îûèô");
+ String upperCaseSuffixUTF8Ref;
+ StringView upperCaseSuffixUTF8 = stringViewFromUTF8(upperCaseSuffixUTF8Ref, "ÈÔ");
+ String notSuffixUTF8Ref;
+ StringView notSuffixUTF8 = stringViewFromUTF8(notSuffixUTF8Ref, "îû");
+
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(reference));
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(oneLetterSuffix));
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(shortSuffix));
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(longSuffix));
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(empty));
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(upperCaseSuffix));
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(mixedCaseSuffix));
+
+ EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(referenceUTF8));
+ EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(oneLetterSuffixUTF8));
+ EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(shortSuffixUTF8));
+ EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(longSuffixUTF8));
+ EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(empty));
+
+ EXPECT_FALSE(reference.endsWithIgnoringASCIICase(notSuffix));
+ EXPECT_FALSE(reference.endsWithIgnoringASCIICase(notSuffixUTF8));
+ EXPECT_FALSE(reference.endsWithIgnoringASCIICase(upperCaseSuffixUTF8));
+ EXPECT_FALSE(referenceUTF8.endsWithIgnoringASCIICase(notSuffix));
+ EXPECT_FALSE(referenceUTF8.endsWithIgnoringASCIICase(notSuffixUTF8));
+ EXPECT_FALSE(referenceUTF8.endsWithIgnoringASCIICase(upperCaseSuffix));
+ EXPECT_FALSE(referenceUTF8.endsWithIgnoringASCIICase(upperCaseSuffixUTF8));
+}
+
+TEST(WTF, StringViewEndsWithIgnoringASCIICaseEmpty)
+{
+ StringView a = stringViewFromLiteral("");
+ String refB;
+ StringView b = stringViewFromUTF8(refB, "");
+
+ EXPECT_TRUE(a.endsWithIgnoringASCIICase(a));
+ EXPECT_TRUE(a.endsWithIgnoringASCIICase(b));
+ EXPECT_TRUE(b.endsWithIgnoringASCIICase(a));
+ EXPECT_TRUE(b.endsWithIgnoringASCIICase(b));
+}
+
+TEST(WTF, StringViewEndsWithIgnoringASCIICaseWithLatin1Characters)
+{
+ StringView reference = stringViewFromLiteral("aBcéeFG");
+ String referenceUTF8Ref;
+ StringView referenceUTF8 = stringViewFromUTF8(referenceUTF8Ref, "aBcéeFG");
+
+ StringView a = stringViewFromLiteral("BcéeFG");
+ StringView b = stringViewFromLiteral("BCéEFG");
+ StringView c = stringViewFromLiteral("bcéefG");
+ StringView d = stringViewFromLiteral("bcéefg");
+
+ String refE;
+ StringView e = stringViewFromUTF8(refE, "bcéefG");
+ String refF;
+ StringView f = stringViewFromUTF8(refF, "BCéEFG");
+ String refG;
+ StringView g = stringViewFromUTF8(refG, "bcéefG");
+ String refH;
+ StringView h = stringViewFromUTF8(refH, "bcéefg");
+
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(a));
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(b));
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(c));
+ EXPECT_TRUE(reference.endsWithIgnoringASCIICase(d));
+
+ EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(e));
+ EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(f));
+ EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(g));
+ EXPECT_TRUE(referenceUTF8.endsWithIgnoringASCIICase(h));
+
+ EXPECT_FALSE(reference.endsWithIgnoringASCIICase(referenceUTF8));
+ EXPECT_FALSE(referenceUTF8.endsWithIgnoringASCIICase(reference));
+}
+
+TEST(WTF, StringView8Bit)
+{
+ StringView nullView;
+ EXPECT_TRUE(StringView().is8Bit());
+ EXPECT_TRUE(StringView::empty().is8Bit());
+
+ LChar* lcharPtr = nullptr;
+ UChar* ucharPtr = nullptr;
+ EXPECT_TRUE(StringView(lcharPtr, 0).is8Bit());
+ EXPECT_FALSE(StringView(ucharPtr, 0).is8Bit());
+
+ EXPECT_TRUE(StringView(String(lcharPtr, 0)).is8Bit());
+ EXPECT_TRUE(StringView(String(ucharPtr, 0)).is8Bit());
+
+ EXPECT_TRUE(StringView(String().impl()).is8Bit());
+ EXPECT_TRUE(StringView(emptyString().impl()).is8Bit());
+}
+
+TEST(WTF, StringViewRightBasic)
+{
+ auto reference = stringViewFromLiteral("Cappuccino");
+ EXPECT_TRUE(reference.right(0) == stringViewFromLiteral(""));
+ EXPECT_TRUE(reference.right(1) == stringViewFromLiteral("o"));
+ EXPECT_TRUE(reference.right(2) == stringViewFromLiteral("no"));
+ EXPECT_TRUE(reference.right(3) == stringViewFromLiteral("ino"));
+ EXPECT_TRUE(reference.right(4) == stringViewFromLiteral("cino"));
+ EXPECT_TRUE(reference.right(5) == stringViewFromLiteral("ccino"));
+ EXPECT_TRUE(reference.right(6) == stringViewFromLiteral("uccino"));
+ EXPECT_TRUE(reference.right(7) == stringViewFromLiteral("puccino"));
+ EXPECT_TRUE(reference.right(8) == stringViewFromLiteral("ppuccino"));
+ EXPECT_TRUE(reference.right(9) == stringViewFromLiteral("appuccino"));
+ EXPECT_TRUE(reference.right(10) == stringViewFromLiteral("Cappuccino"));
+}
+
+TEST(WTF, StringViewLeftBasic)
+{
+ auto reference = stringViewFromLiteral("Cappuccino");
+ EXPECT_TRUE(reference.left(0) == stringViewFromLiteral(""));
+ EXPECT_TRUE(reference.left(1) == stringViewFromLiteral("C"));
+ EXPECT_TRUE(reference.left(2) == stringViewFromLiteral("Ca"));
+ EXPECT_TRUE(reference.left(3) == stringViewFromLiteral("Cap"));
+ EXPECT_TRUE(reference.left(4) == stringViewFromLiteral("Capp"));
+ EXPECT_TRUE(reference.left(5) == stringViewFromLiteral("Cappu"));
+ EXPECT_TRUE(reference.left(6) == stringViewFromLiteral("Cappuc"));
+ EXPECT_TRUE(reference.left(7) == stringViewFromLiteral("Cappucc"));
+ EXPECT_TRUE(reference.left(8) == stringViewFromLiteral("Cappucci"));
+ EXPECT_TRUE(reference.left(9) == stringViewFromLiteral("Cappuccin"));
+ EXPECT_TRUE(reference.left(10) == stringViewFromLiteral("Cappuccino"));
+}
+
+TEST(WTF, StringViewReverseFindBasic)
+{
+ auto reference = stringViewFromLiteral("Cappuccino");
+ EXPECT_EQ(reference.reverseFind('o'), 9U);
+ EXPECT_EQ(reference.reverseFind('n'), 8U);
+ EXPECT_EQ(reference.reverseFind('c'), 6U);
+ EXPECT_EQ(reference.reverseFind('p'), 3U);
+ EXPECT_EQ(reference.reverseFind('k'), notFound);
+
+ EXPECT_EQ(reference.reverseFind('o', 8), notFound);
+ EXPECT_EQ(reference.reverseFind('c', 8), 6U);
+ EXPECT_EQ(reference.reverseFind('c', 6), 6U);
+ EXPECT_EQ(reference.reverseFind('c', 5), 5U);
+ EXPECT_EQ(reference.reverseFind('c', 4), notFound);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp b/Tools/TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp
new file mode 100644
index 000000000..31436bc22
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp
@@ -0,0 +1,229 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <chrono>
+#include <thread>
+
+#include <wtf/ASCIICType.h>
+#include <wtf/SynchronizedFixedQueue.h>
+#include <wtf/WorkQueue.h>
+#include <wtf/text/CString.h>
+#include <wtf/threads/BinarySemaphore.h>
+
+namespace TestWebKitAPI {
+
+static char const* textItem(size_t index)
+{
+ static char const* items[] = { "first", "second", "third", "fourth", "fifth", "sixth" };
+ return index < sizeof(items) / sizeof(items[0]) ? items[index] : nullptr;
+}
+
+static CString toUpper(const CString& lower)
+{
+ CString upper = lower;
+
+ for (char* buffer = upper.mutableData(); *buffer; ++buffer)
+ *buffer = toASCIIUpper(*buffer);
+
+ return upper;
+}
+
+template <size_t BufferSize>
+class ToUpperConverter {
+public:
+ ToUpperConverter()
+ {
+ }
+
+ WorkQueue* produceQueue()
+ {
+ if (!m_produceQueue)
+ m_produceQueue = WorkQueue::create("org.webkit.Produce");
+ return m_produceQueue.get();
+ }
+
+ WorkQueue* consumeQueue()
+ {
+ if (!m_consumeQueue)
+ m_consumeQueue = WorkQueue::create("org.webkit.Consume");
+ return m_consumeQueue.get();
+ }
+
+ void startProducing()
+ {
+ if (isProducing())
+ return;
+
+ produceQueue()->dispatch([this] {
+ CString lower;
+ while (m_lowerQueue.dequeue(lower)) {
+ m_upperQueue.enqueue(toUpper(lower));
+ EXPECT_TRUE(lower == textItem(m_produceCount++));
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ }
+ m_produceCloseSemaphore.signal();
+ });
+ }
+
+ void startConsuming()
+ {
+ if (isConsuming())
+ return;
+
+ consumeQueue()->dispatch([this] {
+ CString upper;
+ while (m_upperQueue.dequeue(upper)) {
+ EXPECT_TRUE(upper == toUpper(textItem(m_consumeCount++)));
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
+ }
+ m_consumeCloseSemaphore.signal();
+ });
+ }
+
+ void start()
+ {
+ startProducing();
+ startConsuming();
+ }
+
+ void stopProducing()
+ {
+ if (!isProducing())
+ return;
+
+ m_lowerQueue.close();
+ m_produceCloseSemaphore.wait(WallTime::infinity());
+ m_produceQueue = nullptr;
+ }
+
+ void stopConsuming()
+ {
+ if (!isConsuming())
+ return;
+
+ m_upperQueue.close();
+ m_consumeCloseSemaphore.wait(WallTime::infinity());
+ m_consumeQueue = nullptr;
+ }
+
+ void stop()
+ {
+ stopProducing();
+ stopConsuming();
+ }
+
+ void enqueueLower(const CString& lower)
+ {
+ m_lowerQueue.enqueue(lower);
+ }
+
+ bool isProducing() { return m_produceQueue; }
+ bool isConsuming() { return m_consumeQueue; }
+
+ size_t produceCount() const { return m_produceCount; }
+ size_t consumeCount() const { return m_consumeCount; }
+
+private:
+ SynchronizedFixedQueue<CString, BufferSize> m_lowerQueue;
+ SynchronizedFixedQueue<CString, BufferSize> m_upperQueue;
+ RefPtr<WorkQueue> m_produceQueue;
+ RefPtr<WorkQueue> m_consumeQueue;
+ BinarySemaphore m_produceCloseSemaphore;
+ BinarySemaphore m_consumeCloseSemaphore;
+ size_t m_produceCount { 0 };
+ size_t m_consumeCount { 0 };
+};
+
+TEST(WTF_SynchronizedFixedQueue, Basic)
+{
+ ToUpperConverter<4U> converter;
+
+ converter.start();
+ EXPECT_TRUE(converter.isProducing() && converter.isConsuming());
+
+ converter.stop();
+ EXPECT_FALSE(converter.isProducing() || converter.isConsuming());
+
+ EXPECT_EQ(converter.produceCount(), 0U);
+ EXPECT_EQ(converter.consumeCount(), 0U);
+}
+
+TEST(WTF_SynchronizedFixedQueue, ProduceOnly)
+{
+ ToUpperConverter<4U> converter;
+
+ converter.startProducing();
+ EXPECT_TRUE(converter.isProducing() && !converter.isConsuming());
+
+ size_t count = 0;
+ while (char const* item = textItem(count)) {
+ converter.enqueueLower(item);
+ ++count;
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ }
+
+ converter.stop();
+ EXPECT_FALSE(converter.isProducing() || converter.isConsuming());
+}
+
+TEST(WTF_SynchronizedFixedQueue, ConsumeOnly)
+{
+ ToUpperConverter<4U> converter;
+
+ converter.startConsuming();
+ EXPECT_TRUE(!converter.isProducing() && converter.isConsuming());
+
+ converter.stop();
+ EXPECT_FALSE(converter.isProducing() || converter.isConsuming());
+}
+
+TEST(WTF_SynchronizedFixedQueue, Limits)
+{
+ ToUpperConverter<4U> converter;
+
+ converter.start();
+ EXPECT_TRUE(converter.isProducing() && converter.isConsuming());
+
+ size_t count = 0;
+ while (char const* item = textItem(count)) {
+ converter.enqueueLower(item);
+ ++count;
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ }
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(400));
+
+ converter.stop();
+ EXPECT_FALSE(converter.isProducing() || converter.isConsuming());
+
+ EXPECT_EQ(converter.produceCount(), count);
+ EXPECT_EQ(converter.consumeCount(), count);
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WTF/TextBreakIterator.cpp b/Tools/TestWebKitAPI/Tests/WTF/TextBreakIterator.cpp
new file mode 100644
index 000000000..c2f84e3d7
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/TextBreakIterator.cpp
@@ -0,0 +1,146 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <wtf/text/TextBreakIterator.h>
+
+namespace TestWebKitAPI {
+
+static String makeUTF16(std::vector<UChar> input)
+{
+ return { input.data(), static_cast<unsigned>(input.size()) };
+}
+
+TEST(WTF, TextBreakIteratorNumGraphemeClusters)
+{
+ EXPECT_EQ(0U, numGraphemeClusters(StringView { }));
+ EXPECT_EQ(0U, numGraphemeClusters(StringView { "" }));
+ EXPECT_EQ(0U, numGraphemeClusters(makeUTF16({ })));
+
+ EXPECT_EQ(1U, numGraphemeClusters(StringView { "a" }));
+ EXPECT_EQ(1U, numGraphemeClusters(makeUTF16({ 'a' })));
+ EXPECT_EQ(1U, numGraphemeClusters(StringView { "\r\n" }));
+ EXPECT_EQ(1U, numGraphemeClusters(StringView { "\n" }));
+ EXPECT_EQ(1U, numGraphemeClusters(StringView { "\r" }));
+ EXPECT_EQ(1U, numGraphemeClusters(makeUTF16({ '\r', '\n' })));
+ EXPECT_EQ(1U, numGraphemeClusters(makeUTF16({ '\n' })));
+ EXPECT_EQ(1U, numGraphemeClusters(makeUTF16({ '\r' })));
+
+ EXPECT_EQ(2U, numGraphemeClusters(StringView { "\n\r" }));
+ EXPECT_EQ(2U, numGraphemeClusters(makeUTF16({ '\n', '\r' })));
+
+ EXPECT_EQ(2U, numGraphemeClusters(StringView { "\r\n\r" }));
+ EXPECT_EQ(2U, numGraphemeClusters(makeUTF16({ '\r', '\n', '\r' })));
+
+ EXPECT_EQ(1U, numGraphemeClusters(makeUTF16({ 'g', 0x308 })));
+ EXPECT_EQ(1U, numGraphemeClusters(makeUTF16({ 0x1100, 0x1161, 0x11A8 })));
+ EXPECT_EQ(1U, numGraphemeClusters(makeUTF16({ 0x0BA8, 0x0BBF })));
+
+ EXPECT_EQ(2U, numGraphemeClusters(makeUTF16({ 0x308, 'g' })));
+
+ EXPECT_EQ(3U, numGraphemeClusters(StringView { "\r\nbc" }));
+ EXPECT_EQ(3U, numGraphemeClusters(makeUTF16({ 'g', 0x308, 'b', 'c' })));
+}
+
+TEST(WTF, TextBreakIteratorNumCharactersInGraphemeClusters)
+{
+ EXPECT_EQ(0U, numCharactersInGraphemeClusters(StringView { }, 0));
+ EXPECT_EQ(0U, numCharactersInGraphemeClusters(StringView { }, 1));
+
+ EXPECT_EQ(0U, numCharactersInGraphemeClusters(StringView { "" }, 0));
+ EXPECT_EQ(0U, numCharactersInGraphemeClusters(StringView { "" }, 1));
+
+ EXPECT_EQ(0U, numCharactersInGraphemeClusters(makeUTF16({ }), 0));
+ EXPECT_EQ(0U, numCharactersInGraphemeClusters(makeUTF16({ }), 1));
+
+ EXPECT_EQ(1U, numCharactersInGraphemeClusters(StringView { "a" }, 1));
+ EXPECT_EQ(1U, numCharactersInGraphemeClusters(makeUTF16({ 'a' }), 1));
+ EXPECT_EQ(1U, numCharactersInGraphemeClusters(StringView { "\n" }, 1));
+ EXPECT_EQ(1U, numCharactersInGraphemeClusters(StringView { "\r" }, 1));
+ EXPECT_EQ(1U, numCharactersInGraphemeClusters(makeUTF16({ '\n' }), 1));
+ EXPECT_EQ(1U, numCharactersInGraphemeClusters(makeUTF16({ '\r' }), 1));
+
+ EXPECT_EQ(0U, numCharactersInGraphemeClusters(StringView { "abc" }, 0));
+ EXPECT_EQ(1U, numCharactersInGraphemeClusters(StringView { "abc" }, 1));
+ EXPECT_EQ(2U, numCharactersInGraphemeClusters(StringView { "abc" }, 2));
+ EXPECT_EQ(3U, numCharactersInGraphemeClusters(StringView { "abc" }, 3));
+ EXPECT_EQ(3U, numCharactersInGraphemeClusters(StringView { "abc" }, 4));
+
+ EXPECT_EQ(0U, numCharactersInGraphemeClusters(makeUTF16({ 'a', 'b', 'c' }), 0));
+ EXPECT_EQ(1U, numCharactersInGraphemeClusters(makeUTF16({ 'a', 'b', 'c' }), 1));
+ EXPECT_EQ(2U, numCharactersInGraphemeClusters(makeUTF16({ 'a', 'b', 'c' }), 2));
+ EXPECT_EQ(3U, numCharactersInGraphemeClusters(makeUTF16({ 'a', 'b', 'c' }), 3));
+ EXPECT_EQ(3U, numCharactersInGraphemeClusters(makeUTF16({ 'a', 'b', 'c' }), 4));
+
+ EXPECT_EQ(0U, numCharactersInGraphemeClusters(StringView { "\r\n" }, 0));
+ EXPECT_EQ(2U, numCharactersInGraphemeClusters(StringView { "\r\n" }, 1));
+ EXPECT_EQ(2U, numCharactersInGraphemeClusters(StringView { "\r\n" }, 2));
+ EXPECT_EQ(2U, numCharactersInGraphemeClusters(StringView { "\r\n" }, 3));
+
+ EXPECT_EQ(0U, numCharactersInGraphemeClusters(makeUTF16({ '\r', '\n' }), 0));
+ EXPECT_EQ(2U, numCharactersInGraphemeClusters(makeUTF16({ '\r', '\n' }), 1));
+ EXPECT_EQ(2U, numCharactersInGraphemeClusters(makeUTF16({ '\r', '\n' }), 2));
+ EXPECT_EQ(2U, numCharactersInGraphemeClusters(makeUTF16({ '\r', '\n' }), 3));
+
+ EXPECT_EQ(0U, numCharactersInGraphemeClusters(StringView { "\n\r" }, 0));
+ EXPECT_EQ(1U, numCharactersInGraphemeClusters(StringView { "\n\r" }, 1));
+ EXPECT_EQ(2U, numCharactersInGraphemeClusters(StringView { "\n\r" }, 2));
+
+ EXPECT_EQ(1U, numCharactersInGraphemeClusters(makeUTF16({ '\n', '\r' }), 1));
+ EXPECT_EQ(2U, numCharactersInGraphemeClusters(makeUTF16({ '\n', '\r' }), 2));
+
+ EXPECT_EQ(0U, numCharactersInGraphemeClusters(StringView { "\r\n\r" }, 0));
+ EXPECT_EQ(2U, numCharactersInGraphemeClusters(StringView { "\r\n\r" }, 1));
+ EXPECT_EQ(3U, numCharactersInGraphemeClusters(StringView { "\r\n\r" }, 2));
+ EXPECT_EQ(3U, numCharactersInGraphemeClusters(StringView { "\r\n\r" }, 3));
+
+ EXPECT_EQ(0U, numCharactersInGraphemeClusters(makeUTF16({ '\r', '\n', '\r' }), 0));
+ EXPECT_EQ(2U, numCharactersInGraphemeClusters(makeUTF16({ '\r', '\n', '\r' }), 1));
+ EXPECT_EQ(3U, numCharactersInGraphemeClusters(makeUTF16({ '\r', '\n', '\r' }), 2));
+ EXPECT_EQ(3U, numCharactersInGraphemeClusters(makeUTF16({ '\r', '\n', '\r' }), 3));
+
+ EXPECT_EQ(2U, numCharactersInGraphemeClusters(makeUTF16({ 'g', 0x308 }), 1));
+ EXPECT_EQ(3U, numCharactersInGraphemeClusters(makeUTF16({ 0x1100, 0x1161, 0x11A8 }), 1));
+ EXPECT_EQ(2U, numCharactersInGraphemeClusters(makeUTF16({ 0x0BA8, 0x0BBF }), 1));
+
+ EXPECT_EQ(1U, numCharactersInGraphemeClusters(makeUTF16({ 0x308, 'g' }), 1));
+
+ EXPECT_EQ(0U, numCharactersInGraphemeClusters(StringView { "\r\nbc" }, 0));
+ EXPECT_EQ(2U, numCharactersInGraphemeClusters(StringView { "\r\nbc" }, 1));
+ EXPECT_EQ(3U, numCharactersInGraphemeClusters(StringView { "\r\nbc" }, 2));
+ EXPECT_EQ(4U, numCharactersInGraphemeClusters(StringView { "\r\nbc" }, 3));
+ EXPECT_EQ(4U, numCharactersInGraphemeClusters(StringView { "\r\nbc" }, 4));
+ EXPECT_EQ(4U, numCharactersInGraphemeClusters(StringView { "\r\nbc" }, 5));
+
+ EXPECT_EQ(0U, numCharactersInGraphemeClusters(makeUTF16({ 'g', 0x308, 'b', 'c' }), 0));
+ EXPECT_EQ(2U, numCharactersInGraphemeClusters(makeUTF16({ 'g', 0x308, 'b', 'c' }), 1));
+ EXPECT_EQ(3U, numCharactersInGraphemeClusters(makeUTF16({ 'g', 0x308, 'b', 'c' }), 2));
+ EXPECT_EQ(4U, numCharactersInGraphemeClusters(makeUTF16({ 'g', 0x308, 'b', 'c' }), 3));
+ EXPECT_EQ(4U, numCharactersInGraphemeClusters(makeUTF16({ 'g', 0x308, 'b', 'c' }), 4));
+ EXPECT_EQ(4U, numCharactersInGraphemeClusters(makeUTF16({ 'g', 0x308, 'b', 'c' }), 5));
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/Time.cpp b/Tools/TestWebKitAPI/Tests/WTF/Time.cpp
new file mode 100644
index 000000000..52e71494b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/Time.cpp
@@ -0,0 +1,318 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+#include <wtf/ClockType.h>
+#include <wtf/MonotonicTime.h>
+#include <wtf/Seconds.h>
+#include <wtf/StringPrintStream.h>
+#include <wtf/TimeWithDynamicClockType.h>
+#include <wtf/WallTime.h>
+
+namespace WTF {
+
+std::basic_ostream<char>& operator<<(std::basic_ostream<char>& out, Seconds value)
+{
+ out << toCString(value).data();
+ return out;
+}
+
+std::basic_ostream<char>& operator<<(std::basic_ostream<char>& out, WallTime value)
+{
+ out << toCString(value).data();
+ return out;
+}
+
+std::basic_ostream<char>& operator<<(std::basic_ostream<char>& out, MonotonicTime value)
+{
+ out << toCString(value).data();
+ return out;
+}
+
+std::basic_ostream<char>& operator<<(std::basic_ostream<char>& out, TimeWithDynamicClockType value)
+{
+ out << toCString(value).data();
+ return out;
+}
+
+} // namespace WTF
+
+using namespace WTF;
+
+namespace TestWebKitAPI {
+
+namespace {
+
+Seconds s(double value)
+{
+ return Seconds(value);
+}
+
+WallTime wt(double value)
+{
+ return WallTime::fromRawSeconds(value);
+}
+
+MonotonicTime mt(double value)
+{
+ return MonotonicTime::fromRawSeconds(value);
+}
+
+TimeWithDynamicClockType dt(double value, ClockType type)
+{
+ return TimeWithDynamicClockType::fromRawSeconds(value, type);
+}
+
+TimeWithDynamicClockType dtw(double value)
+{
+ return dt(value, ClockType::Wall);
+}
+
+TimeWithDynamicClockType dtm(double value)
+{
+ return dt(value, ClockType::Monotonic);
+}
+
+} // anonymous namespace
+
+TEST(WTF_Time, units)
+{
+ EXPECT_EQ(s(60), Seconds::fromMinutes(1));
+ EXPECT_EQ(s(0.001), Seconds::fromMilliseconds(1));
+ EXPECT_EQ(s(0.000001), Seconds::fromMicroseconds(1));
+ EXPECT_EQ(s(0.0000005), Seconds::fromNanoseconds(500));
+
+ EXPECT_EQ(s(120).minutes(), 2);
+ EXPECT_EQ(s(2).seconds(), 2);
+ EXPECT_EQ(s(2).milliseconds(), 2000);
+ EXPECT_EQ(s(2).microseconds(), 2000000);
+ EXPECT_EQ(s(2).nanoseconds(), 2000000000);
+}
+
+TEST(WTF_Time, plus)
+{
+ EXPECT_EQ(s(6), s(1) + s(5));
+ EXPECT_EQ(s(6), s(5) + s(1));
+ EXPECT_EQ(wt(6), s(1) + wt(5));
+ EXPECT_EQ(wt(6), s(5) + wt(1));
+ EXPECT_EQ(wt(6), wt(1) + s(5));
+ EXPECT_EQ(wt(6), wt(5) + s(1));
+ EXPECT_EQ(mt(6), s(1) + mt(5));
+ EXPECT_EQ(mt(6), s(5) + mt(1));
+ EXPECT_EQ(mt(6), mt(1) + s(5));
+ EXPECT_EQ(mt(6), mt(5) + s(1));
+ EXPECT_EQ(dtw(6), s(1) + dtw(5));
+ EXPECT_EQ(dtw(6), s(5) + dtw(1));
+ EXPECT_EQ(dtw(6), dtw(1) + s(5));
+ EXPECT_EQ(dtw(6), dtw(5) + s(1));
+ EXPECT_EQ(dtm(6), s(1) + dtm(5));
+ EXPECT_EQ(dtm(6), s(5) + dtm(1));
+ EXPECT_EQ(dtm(6), dtm(1) + s(5));
+ EXPECT_EQ(dtm(6), dtm(5) + s(1));
+}
+
+TEST(WTF_Time, minus)
+{
+ EXPECT_EQ(s(-4), s(1) - s(5));
+ EXPECT_EQ(s(4), s(5) - s(1));
+ EXPECT_EQ(wt(-4), s(1) - wt(5));
+ EXPECT_EQ(wt(4), s(5) - wt(1));
+ EXPECT_EQ(wt(-4), wt(1) - s(5));
+ EXPECT_EQ(wt(4), wt(5) - s(1));
+ EXPECT_EQ(mt(-4), s(1) - mt(5));
+ EXPECT_EQ(mt(4), s(5) - mt(1));
+ EXPECT_EQ(mt(-4), mt(1) - s(5));
+ EXPECT_EQ(mt(4), mt(5) - s(1));
+ EXPECT_EQ(dtw(-4), s(1) - dtw(5));
+ EXPECT_EQ(dtw(4), s(5) - dtw(1));
+ EXPECT_EQ(dtw(-4), dtw(1) - s(5));
+ EXPECT_EQ(dtw(4), dtw(5) - s(1));
+ EXPECT_EQ(dtm(-4), s(1) - dtm(5));
+ EXPECT_EQ(dtm(4), s(5) - dtm(1));
+ EXPECT_EQ(dtm(-4), dtm(1) - s(5));
+ EXPECT_EQ(dtm(4), dtm(5) - s(1));
+}
+
+TEST(WTF_Time, negate)
+{
+ EXPECT_EQ(s(-7), -s(7));
+ EXPECT_EQ(s(7), -s(-7));
+ EXPECT_EQ(wt(-7), -wt(7));
+ EXPECT_EQ(wt(7), -wt(-7));
+ EXPECT_EQ(mt(-7), -mt(7));
+ EXPECT_EQ(mt(7), -mt(-7));
+ EXPECT_EQ(dtw(-7), -dtw(7));
+ EXPECT_EQ(dtw(7), -dtw(-7));
+ EXPECT_EQ(dtm(-7), -dtm(7));
+ EXPECT_EQ(dtm(7), -dtm(-7));
+}
+
+TEST(WTF_Time, times)
+{
+ EXPECT_EQ(s(15), s(3) * 5);
+}
+
+TEST(WTF_Time, divide)
+{
+ EXPECT_EQ(s(3), s(15) / 5);
+}
+
+TEST(WTF_Time, less)
+{
+ EXPECT_FALSE(s(2) < s(1));
+ EXPECT_FALSE(s(2) < s(2));
+ EXPECT_TRUE(s(2) < s(3));
+ EXPECT_FALSE(wt(2) < wt(1));
+ EXPECT_FALSE(wt(2) < wt(2));
+ EXPECT_TRUE(wt(2) < wt(3));
+ EXPECT_FALSE(mt(2) < mt(1));
+ EXPECT_FALSE(mt(2) < mt(2));
+ EXPECT_TRUE(mt(2) < mt(3));
+ EXPECT_FALSE(dtw(2) < dtw(1));
+ EXPECT_FALSE(dtw(2) < dtw(2));
+ EXPECT_TRUE(dtw(2) < dtw(3));
+ EXPECT_FALSE(dtm(2) < dtm(1));
+ EXPECT_FALSE(dtm(2) < dtm(2));
+ EXPECT_TRUE(dtm(2) < dtm(3));
+}
+
+TEST(WTF_Time, lessEqual)
+{
+ EXPECT_FALSE(s(2) <= s(1));
+ EXPECT_TRUE(s(2) <= s(2));
+ EXPECT_TRUE(s(2) <= s(3));
+ EXPECT_FALSE(wt(2) <= wt(1));
+ EXPECT_TRUE(wt(2) <= wt(2));
+ EXPECT_TRUE(wt(2) <= wt(3));
+ EXPECT_FALSE(mt(2) <= mt(1));
+ EXPECT_TRUE(mt(2) <= mt(2));
+ EXPECT_TRUE(mt(2) <= mt(3));
+ EXPECT_FALSE(dtw(2) <= dtw(1));
+ EXPECT_TRUE(dtw(2) <= dtw(2));
+ EXPECT_TRUE(dtw(2) <= dtw(3));
+ EXPECT_FALSE(dtm(2) <= dtm(1));
+ EXPECT_TRUE(dtm(2) <= dtm(2));
+ EXPECT_TRUE(dtm(2) <= dtm(3));
+}
+
+TEST(WTF_Time, greater)
+{
+ EXPECT_TRUE(s(2) > s(1));
+ EXPECT_FALSE(s(2) > s(2));
+ EXPECT_FALSE(s(2) > s(3));
+ EXPECT_TRUE(wt(2) > wt(1));
+ EXPECT_FALSE(wt(2) > wt(2));
+ EXPECT_FALSE(wt(2) > wt(3));
+ EXPECT_TRUE(mt(2) > mt(1));
+ EXPECT_FALSE(mt(2) > mt(2));
+ EXPECT_FALSE(mt(2) > mt(3));
+ EXPECT_TRUE(dtw(2) > dtw(1));
+ EXPECT_FALSE(dtw(2) > dtw(2));
+ EXPECT_FALSE(dtw(2) > dtw(3));
+ EXPECT_TRUE(dtm(2) > dtm(1));
+ EXPECT_FALSE(dtm(2) > dtm(2));
+ EXPECT_FALSE(dtm(2) > dtm(3));
+}
+
+TEST(WTF_Time, greaterEqual)
+{
+ EXPECT_TRUE(s(2) >= s(1));
+ EXPECT_TRUE(s(2) >= s(2));
+ EXPECT_FALSE(s(2) >= s(3));
+ EXPECT_TRUE(wt(2) >= wt(1));
+ EXPECT_TRUE(wt(2) >= wt(2));
+ EXPECT_FALSE(wt(2) >= wt(3));
+ EXPECT_TRUE(mt(2) >= mt(1));
+ EXPECT_TRUE(mt(2) >= mt(2));
+ EXPECT_FALSE(mt(2) >= mt(3));
+ EXPECT_TRUE(dtw(2) >= dtw(1));
+ EXPECT_TRUE(dtw(2) >= dtw(2));
+ EXPECT_FALSE(dtw(2) >= dtw(3));
+ EXPECT_TRUE(dtm(2) >= dtm(1));
+ EXPECT_TRUE(dtm(2) >= dtm(2));
+ EXPECT_FALSE(dtm(2) >= dtm(3));
+}
+
+TEST(WTF_Time, equal)
+{
+ EXPECT_FALSE(s(2) == s(1));
+ EXPECT_TRUE(s(2) == s(2));
+ EXPECT_FALSE(s(2) == s(3));
+ EXPECT_FALSE(wt(2) == wt(1));
+ EXPECT_TRUE(wt(2) == wt(2));
+ EXPECT_FALSE(wt(2) == wt(3));
+ EXPECT_FALSE(mt(2) == mt(1));
+ EXPECT_TRUE(mt(2) == mt(2));
+ EXPECT_FALSE(mt(2) == mt(3));
+ EXPECT_FALSE(dtw(2) == dtw(1));
+ EXPECT_TRUE(dtw(2) == dtw(2));
+ EXPECT_FALSE(dtw(2) == dtw(3));
+ EXPECT_FALSE(dtm(2) == dtm(1));
+ EXPECT_TRUE(dtm(2) == dtm(2));
+ EXPECT_FALSE(dtm(2) == dtm(3));
+}
+
+TEST(WTF_Time, notEqual)
+{
+ EXPECT_TRUE(s(2) != s(1));
+ EXPECT_FALSE(s(2) != s(2));
+ EXPECT_TRUE(s(2) != s(3));
+ EXPECT_TRUE(wt(2) != wt(1));
+ EXPECT_FALSE(wt(2) != wt(2));
+ EXPECT_TRUE(wt(2) != wt(3));
+ EXPECT_TRUE(mt(2) != mt(1));
+ EXPECT_FALSE(mt(2) != mt(2));
+ EXPECT_TRUE(mt(2) != mt(3));
+ EXPECT_TRUE(dtw(2) != dtw(1));
+ EXPECT_FALSE(dtw(2) != dtw(2));
+ EXPECT_TRUE(dtw(2) != dtw(3));
+ EXPECT_TRUE(dtm(2) != dtm(1));
+ EXPECT_FALSE(dtm(2) != dtm(2));
+ EXPECT_TRUE(dtm(2) != dtm(3));
+}
+
+TEST(WTF_Time, literals)
+{
+ EXPECT_TRUE(s(120) == 2_min);
+ EXPECT_TRUE(s(2) == 2_s);
+ EXPECT_TRUE(s(2) == 2000_ms);
+ EXPECT_TRUE(s(2) - 1000_ms == s(1));
+ EXPECT_TRUE(2_s - s(1) == 1000_ms);
+
+ EXPECT_TRUE(Seconds::fromMinutes(2) == 2_min);
+ EXPECT_TRUE(Seconds(2) == 2_s);
+ EXPECT_TRUE(Seconds::fromMilliseconds(2) == 2_ms);
+ EXPECT_TRUE(Seconds::fromMicroseconds(2) == 2_us);
+ EXPECT_TRUE(Seconds::fromNanoseconds(2) == 2_ns);
+
+ EXPECT_TRUE(Seconds::fromMinutes(2.5) == 2.5_min);
+ EXPECT_TRUE(Seconds(2.5) == 2.5_s);
+ EXPECT_TRUE(Seconds::fromMilliseconds(2.5) == 2.5_ms);
+ EXPECT_TRUE(Seconds::fromMicroseconds(2.5) == 2.5_us);
+ EXPECT_TRUE(Seconds::fromNanoseconds(2.5) == 2.5_ns);
+}
+
+} // namespace TestWebKitAPI
+
diff --git a/Tools/TestWebKitAPI/Tests/WTF/UniqueRef.cpp b/Tools/TestWebKitAPI/Tests/WTF/UniqueRef.cpp
new file mode 100644
index 000000000..4d2b22aa5
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/UniqueRef.cpp
@@ -0,0 +1,93 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <wtf/UniqueRef.h>
+#include <wtf/Vector.h>
+
+namespace TestWebKitAPI {
+
+class A { };
+class B {
+public:
+ B(int a, int b, int c)
+ : a(a)
+ , b(b)
+ , c(c)
+ { };
+ int a;
+ int b;
+ int c;
+};
+class C {
+public:
+ C(UniqueRef<A>&& a)
+ : a(WTFMove(a))
+ { }
+ UniqueRef<A> a;
+};
+class D : public A { };
+
+void function(const UniqueRef<A> a)
+{
+ const A& b = a.get();
+ const A* c = &a;
+ UNUSED_PARAM(b);
+ UNUSED_PARAM(c);
+}
+
+TEST(WTF, UniqueRef)
+{
+ UniqueRef<A> a = makeUniqueRef<A>();
+ UniqueRef<B> b = makeUniqueRef<B>(1, 2, 3);
+ B& c = b.get();
+ const B& d = b.get();
+ B* e = &b;
+ const B* f = &b;
+ UniqueRef<A> j = WTFMove(a);
+
+ Vector<UniqueRef<B>> v;
+ v.append(makeUniqueRef<B>(4, 5, 6));
+ v.append(makeUniqueRef<B>(7, 8, 9));
+ UniqueRef<B> g = v.takeLast();
+ ASSERT_EQ(g->b, 8);
+ ASSERT_EQ(v.last()->b, 5);
+
+ C h(makeUniqueRef<A>());
+ C i(makeUniqueRef<D>());
+
+ UNUSED_PARAM(b);
+ UNUSED_PARAM(c);
+ UNUSED_PARAM(d);
+ UNUSED_PARAM(e);
+ UNUSED_PARAM(f);
+ UNUSED_PARAM(g);
+ UNUSED_PARAM(h);
+ UNUSED_PARAM(i);
+ UNUSED_PARAM(j);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/Variant.cpp b/Tools/TestWebKitAPI/Tests/WTF/Variant.cpp
new file mode 100644
index 000000000..b68156179
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/Variant.cpp
@@ -0,0 +1,228 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include "Counters.h"
+#include "RefLogger.h"
+#include <wtf/Ref.h>
+#include <wtf/RefPtr.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/Variant.h>
+#include <wtf/text/WTFString.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF_Variant, Initial)
+{
+ Variant<int, double> v1;
+ EXPECT_TRUE(v1.index() == 0);
+ EXPECT_TRUE(WTF::get<int>(v1) == 0);
+
+ struct T {
+ T() : value(15) { }
+ int value;
+ };
+
+ Variant<T, int> v2;
+ EXPECT_TRUE(v2.index() == 0);
+ EXPECT_TRUE(WTF::get<T>(v2).value == 15);
+}
+
+TEST(WTF_Variant, Basic)
+{
+ Variant<int, double> variant = 1;
+ EXPECT_TRUE(variant.index() == 0);
+ EXPECT_TRUE(WTF::get<int>(variant) == 1);
+ EXPECT_TRUE(*WTF::get_if<int>(variant) == 1);
+ EXPECT_TRUE(WTF::get_if<double>(variant) == nullptr);
+ EXPECT_TRUE(WTF::holds_alternative<int>(variant));
+ EXPECT_FALSE(WTF::holds_alternative<double>(variant));
+
+ variant = 1.0;
+ EXPECT_TRUE(variant.index() == 1);
+ EXPECT_TRUE(WTF::get<double>(variant) == 1);
+ EXPECT_TRUE(*WTF::get_if<double>(variant) == 1.0);
+ EXPECT_TRUE(WTF::get_if<int>(variant) == nullptr);
+ EXPECT_TRUE(WTF::holds_alternative<double>(variant));
+ EXPECT_FALSE(WTF::holds_alternative<int>(variant));
+}
+
+TEST(WTF_Variant, BasicVisitor)
+{
+ enum class Type {
+ None,
+ Int,
+ Float,
+ String,
+ };
+
+ struct Visitor {
+ Visitor(Type& t)
+ : type(t)
+ {
+ }
+
+ Type& type;
+
+ void operator()(int) const { type = Type::Int; }
+ void operator()(float) const { type = Type::Float; }
+ void operator()(String) const { type = Type::String; }
+ };
+
+ Type type = Type::None;
+
+ Variant<int, float, String> variant = 8;
+ WTF::visit(Visitor(type), variant);
+ EXPECT_TRUE(Type::Int == type);
+
+
+ variant = 1.0f;
+ WTF::visit(Visitor(type), variant);
+ EXPECT_TRUE(Type::Float == type);
+
+
+ variant = "hello";
+ WTF::visit(Visitor(type), variant);
+ EXPECT_TRUE(Type::String == type);
+}
+
+TEST(WTF_Variant, VisitorUsingMakeVisitor)
+{
+ enum class Type {
+ None,
+ Int,
+ Float,
+ String,
+ };
+
+ Type type = Type::None;
+
+ auto visitor = WTF::makeVisitor(
+ [&](int) { type = Type::Int; },
+ [&](float) { type = Type::Float; },
+ [&](String) { type = Type::String; }
+ );
+
+ Variant<int, float, String> variant = 8;
+ WTF::visit(visitor, variant);
+ EXPECT_TRUE(Type::Int == type);
+
+
+ variant = 1.0f;
+ WTF::visit(visitor, variant);
+ EXPECT_TRUE(Type::Float == type);
+
+
+ variant = "hello";
+ WTF::visit(visitor, variant);
+ EXPECT_TRUE(Type::String == type);
+}
+
+TEST(WTF_Variant, VisitorUsingSwitchOn)
+{
+ enum class Type {
+ None,
+ Int,
+ Float,
+ String,
+ };
+
+ Type type = Type::None;
+
+ Variant<int, float, String> variant = 8;
+ type = WTF::switchOn(variant,
+ [](int) { return Type::Int; },
+ [](float) { return Type::Float; },
+ [](String) { return Type::String; }
+ );
+ EXPECT_TRUE(Type::Int == type);
+
+
+ variant = 1.0f;
+ type = WTF::switchOn(variant,
+ [](int) { return Type::Int; },
+ [](float) { return Type::Float; },
+ [](String) { return Type::String; }
+ );
+ EXPECT_TRUE(Type::Float == type);
+
+
+ variant = "hello";
+ type = WTF::switchOn(variant,
+ [](int) { return Type::Int; },
+ [](float) { return Type::Float; },
+ [](String) { return Type::String; }
+ );
+ EXPECT_TRUE(Type::String == type);
+}
+
+TEST(WTF_Variant, ConstructorDestructor)
+{
+ ConstructorDestructorCounter::TestingScope scope;
+
+ {
+ auto uniquePtr = std::make_unique<ConstructorDestructorCounter>();
+ Variant<std::unique_ptr<ConstructorDestructorCounter>, int> v = WTFMove(uniquePtr);
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount);
+ }
+
+ EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount);
+ EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount);
+}
+
+TEST(WTF_Variant, RefPtr)
+{
+ {
+ RefLogger a("a");
+ RefPtr<RefLogger> ref(&a);
+ Variant<RefPtr<RefLogger>, int> v = ref;
+ }
+
+ ASSERT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str());
+
+ {
+ RefLogger a("a");
+ RefPtr<RefLogger> ref(&a);
+ Variant<RefPtr<RefLogger>, int> v = WTFMove(ref);
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+TEST(WTF_Variant, Ref)
+{
+ {
+ RefLogger a("a");
+ Ref<RefLogger> ref(a);
+ Variant<Ref<RefLogger>, int> v = WTFMove(ref);
+ }
+
+ ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str());
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WTF/Vector.cpp b/Tools/TestWebKitAPI/Tests/WTF/Vector.cpp
index 2278784c4..48235b1fc 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/Vector.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/Vector.cpp
@@ -27,6 +27,7 @@
#include "MoveOnly.h"
#include <wtf/Vector.h>
+#include <wtf/text/CString.h>
namespace TestWebKitAPI {
@@ -34,8 +35,8 @@ TEST(WTF_Vector, Basic)
{
Vector<int> intVector;
EXPECT_TRUE(intVector.isEmpty());
- EXPECT_EQ(0ul, intVector.size());
- EXPECT_EQ(0ul, intVector.capacity());
+ EXPECT_EQ(0U, intVector.size());
+ EXPECT_EQ(0U, intVector.capacity());
}
TEST(WTF_Vector, Iterator)
@@ -66,7 +67,7 @@ TEST(WTF_Vector, OverloadedOperatorAmpersand)
{
struct Test {
private:
- Test* operator&();
+ Test* operator&() = delete;
};
Vector<Test> vector;
@@ -94,6 +95,103 @@ TEST(WTF_Vector, InitializerList)
EXPECT_EQ(4, vector[3]);
}
+TEST(WTF_Vector, InitializeFromOtherInitialCapacity)
+{
+ Vector<int, 3> vector = { 1, 3, 2, 4 };
+ Vector<int, 5> vectorCopy(vector);
+ EXPECT_EQ(4U, vector.size());
+ EXPECT_EQ(4U, vectorCopy.size());
+ EXPECT_EQ(5U, vectorCopy.capacity());
+
+ EXPECT_EQ(1, vectorCopy[0]);
+ EXPECT_EQ(3, vectorCopy[1]);
+ EXPECT_EQ(2, vectorCopy[2]);
+ EXPECT_EQ(4, vectorCopy[3]);
+}
+
+TEST(WTF_Vector, CopyFromOtherInitialCapacity)
+{
+ Vector<int, 3> vector = { 1, 3, 2, 4 };
+ Vector<int, 5> vectorCopy { 0 };
+ EXPECT_EQ(4U, vector.size());
+ EXPECT_EQ(1U, vectorCopy.size());
+
+ vectorCopy = vector;
+
+ EXPECT_EQ(4U, vector.size());
+ EXPECT_EQ(4U, vectorCopy.size());
+ EXPECT_EQ(5U, vectorCopy.capacity());
+
+ EXPECT_EQ(1, vectorCopy[0]);
+ EXPECT_EQ(3, vectorCopy[1]);
+ EXPECT_EQ(2, vectorCopy[2]);
+ EXPECT_EQ(4, vectorCopy[3]);
+}
+
+TEST(WTF_Vector, InitializeFromOtherOverflowBehavior)
+{
+ Vector<int, 7, WTF::CrashOnOverflow> vector = { 4, 3, 2, 1 };
+ Vector<int, 7, UnsafeVectorOverflow> vectorCopy(vector);
+ EXPECT_EQ(4U, vector.size());
+ EXPECT_EQ(4U, vectorCopy.size());
+
+ EXPECT_EQ(4, vectorCopy[0]);
+ EXPECT_EQ(3, vectorCopy[1]);
+ EXPECT_EQ(2, vectorCopy[2]);
+ EXPECT_EQ(1, vectorCopy[3]);
+}
+
+TEST(WTF_Vector, CopyFromOtherOverflowBehavior)
+{
+ Vector<int, 7, WTF::CrashOnOverflow> vector = { 4, 3, 2, 1 };
+ Vector<int, 7, UnsafeVectorOverflow> vectorCopy = { 0, 0, 0 };
+
+ EXPECT_EQ(4U, vector.size());
+ EXPECT_EQ(3U, vectorCopy.size());
+
+ vectorCopy = vector;
+
+ EXPECT_EQ(4U, vector.size());
+ EXPECT_EQ(4U, vectorCopy.size());
+
+ EXPECT_EQ(4, vectorCopy[0]);
+ EXPECT_EQ(3, vectorCopy[1]);
+ EXPECT_EQ(2, vectorCopy[2]);
+ EXPECT_EQ(1, vectorCopy[3]);
+}
+
+TEST(WTF_Vector, InitializeFromOtherMinCapacity)
+{
+ Vector<int, 7, WTF::CrashOnOverflow, 1> vector = { 3, 4, 2, 1 };
+ Vector<int, 7, WTF::CrashOnOverflow, 50> vectorCopy(vector);
+ EXPECT_EQ(4U, vector.size());
+ EXPECT_EQ(4U, vectorCopy.size());
+
+ EXPECT_EQ(3, vectorCopy[0]);
+ EXPECT_EQ(4, vectorCopy[1]);
+ EXPECT_EQ(2, vectorCopy[2]);
+ EXPECT_EQ(1, vectorCopy[3]);
+}
+
+TEST(WTF_Vector, CopyFromOtherMinCapacity)
+{
+ Vector<int, 7, WTF::CrashOnOverflow, 1> vector = { 3, 4, 2, 1 };
+ Vector<int, 7, WTF::CrashOnOverflow, 50> vectorCopy;
+
+ EXPECT_EQ(4U, vector.size());
+ EXPECT_EQ(0U, vectorCopy.size());
+
+ vectorCopy = vector;
+
+ EXPECT_EQ(4U, vector.size());
+ EXPECT_EQ(4U, vectorCopy.size());
+
+ EXPECT_EQ(3, vectorCopy[0]);
+ EXPECT_EQ(4, vectorCopy[1]);
+ EXPECT_EQ(2, vectorCopy[2]);
+ EXPECT_EQ(1, vectorCopy[3]);
+}
+
TEST(WTF_Vector, Reverse)
{
Vector<int> intVector;
@@ -149,12 +247,12 @@ TEST(WTF_Vector, MoveOnly_UncheckedAppend)
vector.reserveInitialCapacity(100);
for (size_t i = 0; i < 100; ++i) {
MoveOnly moveOnly(i);
- vector.uncheckedAppend(std::move(moveOnly));
- EXPECT_EQ(moveOnly.value(), 0U);
+ vector.uncheckedAppend(WTFMove(moveOnly));
+ EXPECT_EQ(0U, moveOnly.value());
}
for (size_t i = 0; i < 100; ++i)
- EXPECT_EQ(vector[i].value(), i);
+ EXPECT_EQ(i, vector[i].value());
}
TEST(WTF_Vector, MoveOnly_Append)
@@ -163,12 +261,12 @@ TEST(WTF_Vector, MoveOnly_Append)
for (size_t i = 0; i < 100; ++i) {
MoveOnly moveOnly(i);
- vector.append(std::move(moveOnly));
- EXPECT_EQ(moveOnly.value(), 0U);
+ vector.append(WTFMove(moveOnly));
+ EXPECT_EQ(0U, moveOnly.value());
}
for (size_t i = 0; i < 100; ++i)
- EXPECT_EQ(vector[i].value(), i);
+ EXPECT_EQ(i, vector[i].value());
for (size_t i = 0; i < 16; ++i) {
Vector<MoveOnly> vector;
@@ -177,13 +275,13 @@ TEST(WTF_Vector, MoveOnly_Append)
for (size_t j = 0; j < i; ++j)
vector.append(j);
- vector.append(std::move(vector[0]));
+ vector.append(WTFMove(vector[0]));
- EXPECT_EQ(vector[0].value(), 0U);
+ EXPECT_EQ(0U, vector[0].value());
for (size_t j = 0; j < i; ++j)
- EXPECT_EQ(vector[j + 1].value(), j);
- EXPECT_EQ(vector.last().value(), i);
+ EXPECT_EQ(j, vector[j + 1].value());
+ EXPECT_EQ(i, vector.last().value());
}
}
@@ -193,7 +291,7 @@ TEST(WTF_Vector, MoveOnly_Insert)
for (size_t i = 0; i < 100; ++i) {
MoveOnly moveOnly(i);
- vector.insert(0, std::move(moveOnly));
+ vector.insert(0, WTFMove(moveOnly));
EXPECT_EQ(0U, moveOnly.value());
}
@@ -203,11 +301,11 @@ TEST(WTF_Vector, MoveOnly_Insert)
for (size_t i = 0; i < 200; i += 2) {
MoveOnly moveOnly(1000 + i);
- vector.insert(i, std::move(moveOnly));
+ vector.insert(i, WTFMove(moveOnly));
EXPECT_EQ(0U, moveOnly.value());
}
- EXPECT_EQ(vector.size(), 200U);
+ EXPECT_EQ(200U, vector.size());
for (size_t i = 0; i < 200; ++i) {
if (i % 2)
EXPECT_EQ(99 - i / 2, vector[i].value());
@@ -216,4 +314,304 @@ TEST(WTF_Vector, MoveOnly_Insert)
}
}
+TEST(WTF_Vector, MoveOnly_TakeLast)
+{
+ Vector<MoveOnly> vector;
+
+ for (size_t i = 0; i < 100; ++i) {
+ MoveOnly moveOnly(i);
+ vector.append(WTFMove(moveOnly));
+ EXPECT_EQ(0U, moveOnly.value());
+ }
+
+ EXPECT_EQ(100U, vector.size());
+ for (size_t i = 0; i < 100; ++i)
+ EXPECT_EQ(99 - i, vector.takeLast().value());
+
+ EXPECT_EQ(0U, vector.size());
+}
+
+TEST(WTF_Vector, VectorOfVectorsOfVectorsInlineCapacitySwap)
+{
+ Vector<Vector<Vector<int, 1>, 1>, 1> a;
+ Vector<Vector<Vector<int, 1>, 1>, 1> b;
+ Vector<Vector<Vector<int, 1>, 1>, 1> c;
+
+ EXPECT_EQ(0U, a.size());
+ EXPECT_EQ(0U, b.size());
+ EXPECT_EQ(0U, c.size());
+
+ Vector<int, 1> x;
+ x.append(42);
+
+ EXPECT_EQ(1U, x.size());
+ EXPECT_EQ(42, x[0]);
+
+ Vector<Vector<int, 1>, 1> y;
+ y.append(x);
+
+ EXPECT_EQ(1U, x.size());
+ EXPECT_EQ(42, x[0]);
+ EXPECT_EQ(1U, y.size());
+ EXPECT_EQ(1U, y[0].size());
+ EXPECT_EQ(42, y[0][0]);
+
+ a.append(y);
+
+ EXPECT_EQ(1U, x.size());
+ EXPECT_EQ(42, x[0]);
+ EXPECT_EQ(1U, y.size());
+ EXPECT_EQ(1U, y[0].size());
+ EXPECT_EQ(42, y[0][0]);
+ EXPECT_EQ(1U, a.size());
+ EXPECT_EQ(1U, a[0].size());
+ EXPECT_EQ(1U, a[0][0].size());
+ EXPECT_EQ(42, a[0][0][0]);
+
+ a.swap(b);
+
+ EXPECT_EQ(0U, a.size());
+ EXPECT_EQ(1U, x.size());
+ EXPECT_EQ(42, x[0]);
+ EXPECT_EQ(1U, y.size());
+ EXPECT_EQ(1U, y[0].size());
+ EXPECT_EQ(42, y[0][0]);
+ EXPECT_EQ(1U, b.size());
+ EXPECT_EQ(1U, b[0].size());
+ EXPECT_EQ(1U, b[0][0].size());
+ EXPECT_EQ(42, b[0][0][0]);
+
+ b.swap(c);
+
+ EXPECT_EQ(0U, a.size());
+ EXPECT_EQ(0U, b.size());
+ EXPECT_EQ(1U, x.size());
+ EXPECT_EQ(42, x[0]);
+ EXPECT_EQ(1U, y.size());
+ EXPECT_EQ(1U, y[0].size());
+ EXPECT_EQ(42, y[0][0]);
+ EXPECT_EQ(1U, c.size());
+ EXPECT_EQ(1U, c[0].size());
+ EXPECT_EQ(1U, c[0][0].size());
+ EXPECT_EQ(42, c[0][0][0]);
+
+ y[0][0] = 24;
+
+ EXPECT_EQ(1U, x.size());
+ EXPECT_EQ(42, x[0]);
+ EXPECT_EQ(1U, y.size());
+ EXPECT_EQ(1U, y[0].size());
+ EXPECT_EQ(24, y[0][0]);
+
+ a.append(y);
+
+ EXPECT_EQ(1U, x.size());
+ EXPECT_EQ(42, x[0]);
+ EXPECT_EQ(1U, y.size());
+ EXPECT_EQ(1U, y[0].size());
+ EXPECT_EQ(24, y[0][0]);
+ EXPECT_EQ(1U, a.size());
+ EXPECT_EQ(1U, a[0].size());
+ EXPECT_EQ(1U, a[0][0].size());
+ EXPECT_EQ(24, a[0][0][0]);
+ EXPECT_EQ(1U, c.size());
+ EXPECT_EQ(1U, c[0].size());
+ EXPECT_EQ(1U, c[0][0].size());
+ EXPECT_EQ(42, c[0][0][0]);
+ EXPECT_EQ(0U, b.size());
+}
+
+TEST(WTF_Vector, RemoveFirst)
+{
+ Vector<int> v;
+ EXPECT_TRUE(v.isEmpty());
+ EXPECT_FALSE(v.removeFirst(1));
+ EXPECT_FALSE(v.removeFirst(-1));
+ EXPECT_TRUE(v.isEmpty());
+
+ v.fill(2, 10);
+ EXPECT_EQ(10U, v.size());
+ EXPECT_FALSE(v.removeFirst(1));
+ EXPECT_EQ(10U, v.size());
+ v.clear();
+
+ v.fill(1, 10);
+ EXPECT_EQ(10U, v.size());
+ EXPECT_TRUE(v.removeFirst(1));
+ EXPECT_TRUE(v == Vector<int>({1, 1, 1, 1, 1, 1, 1, 1, 1}));
+ EXPECT_EQ(9U, v.size());
+ EXPECT_FALSE(v.removeFirst(2));
+ EXPECT_EQ(9U, v.size());
+ EXPECT_TRUE(v == Vector<int>({1, 1, 1, 1, 1, 1, 1, 1, 1}));
+
+ unsigned removed = 0;
+ while (v.removeFirst(1))
+ ++removed;
+ EXPECT_EQ(9U, removed);
+ EXPECT_TRUE(v.isEmpty());
+
+ v.resize(1);
+ EXPECT_EQ(1U, v.size());
+ EXPECT_TRUE(v.removeFirst(1));
+ EXPECT_EQ(0U, v.size());
+ EXPECT_TRUE(v.isEmpty());
+}
+
+TEST(WTF_Vector, RemoveAll)
+{
+ // Using a memcpy-able type.
+ static_assert(VectorTraits<int>::canMoveWithMemcpy, "Should use a memcpy-able type");
+ Vector<int> v;
+ EXPECT_TRUE(v.isEmpty());
+ EXPECT_FALSE(v.removeAll(1));
+ EXPECT_FALSE(v.removeAll(-1));
+ EXPECT_TRUE(v.isEmpty());
+
+ v.fill(1, 10);
+ EXPECT_EQ(10U, v.size());
+ EXPECT_EQ(10U, v.removeAll(1));
+ EXPECT_TRUE(v.isEmpty());
+
+ v.fill(2, 10);
+ EXPECT_EQ(10U, v.size());
+ EXPECT_EQ(0U, v.removeAll(1));
+ EXPECT_EQ(10U, v.size());
+
+ v = {1, 2, 1, 2, 1, 2, 2, 1, 1, 1};
+ EXPECT_EQ(10U, v.size());
+ EXPECT_EQ(6U, v.removeAll(1));
+ EXPECT_EQ(4U, v.size());
+ EXPECT_TRUE(v == Vector<int>({2, 2, 2, 2}));
+ EXPECT_TRUE(v.find(1) == notFound);
+ EXPECT_EQ(4U, v.removeAll(2));
+ EXPECT_TRUE(v.isEmpty());
+
+ v = {3, 1, 2, 1, 2, 1, 2, 2, 1, 1, 1, 3};
+ EXPECT_EQ(12U, v.size());
+ EXPECT_EQ(6U, v.removeAll(1));
+ EXPECT_EQ(6U, v.size());
+ EXPECT_TRUE(v.find(1) == notFound);
+ EXPECT_TRUE(v == Vector<int>({3, 2, 2, 2, 2, 3}));
+
+ EXPECT_EQ(4U, v.removeAll(2));
+ EXPECT_EQ(2U, v.size());
+ EXPECT_TRUE(v.find(2) == notFound);
+ EXPECT_TRUE(v == Vector<int>({3, 3}));
+
+ EXPECT_EQ(2U, v.removeAll(3));
+ EXPECT_TRUE(v.isEmpty());
+
+ v = {1, 1, 1, 3, 2, 4, 2, 2, 2, 4, 4, 3};
+ EXPECT_EQ(12U, v.size());
+ EXPECT_EQ(3U, v.removeAll(1));
+ EXPECT_EQ(9U, v.size());
+ EXPECT_TRUE(v.find(1) == notFound);
+ EXPECT_TRUE(v == Vector<int>({3, 2, 4, 2, 2, 2, 4, 4, 3}));
+
+ // Using a non memcpy-able type.
+ static_assert(!VectorTraits<CString>::canMoveWithMemcpy, "Should use a non memcpy-able type");
+ Vector<CString> vExpected;
+ Vector<CString> v2;
+ EXPECT_TRUE(v2.isEmpty());
+ EXPECT_FALSE(v2.removeAll("1"));
+ EXPECT_TRUE(v2.isEmpty());
+
+ v2.fill("1", 10);
+ EXPECT_EQ(10U, v2.size());
+ EXPECT_EQ(10U, v2.removeAll("1"));
+ EXPECT_TRUE(v2.isEmpty());
+
+ v2.fill("2", 10);
+ EXPECT_EQ(10U, v2.size());
+ EXPECT_EQ(0U, v2.removeAll("1"));
+ EXPECT_EQ(10U, v2.size());
+
+ v2 = {"1", "2", "1", "2", "1", "2", "2", "1", "1", "1"};
+ EXPECT_EQ(10U, v2.size());
+ EXPECT_EQ(6U, v2.removeAll("1"));
+ EXPECT_EQ(4U, v2.size());
+ EXPECT_TRUE(v2.find("1") == notFound);
+ EXPECT_EQ(4U, v2.removeAll("2"));
+ EXPECT_TRUE(v2.isEmpty());
+
+ v2 = {"3", "1", "2", "1", "2", "1", "2", "2", "1", "1", "1", "3"};
+ EXPECT_EQ(12U, v2.size());
+ EXPECT_EQ(6U, v2.removeAll("1"));
+ EXPECT_EQ(6U, v2.size());
+ EXPECT_TRUE(v2.find("1") == notFound);
+ vExpected = {"3", "2", "2", "2", "2", "3"};
+ EXPECT_TRUE(v2 == vExpected);
+
+ EXPECT_EQ(4U, v2.removeAll("2"));
+ EXPECT_EQ(2U, v2.size());
+ EXPECT_TRUE(v2.find("2") == notFound);
+ vExpected = {"3", "3"};
+ EXPECT_TRUE(v2 == vExpected);
+
+ EXPECT_EQ(2U, v2.removeAll("3"));
+ EXPECT_TRUE(v2.isEmpty());
+
+ v2 = {"1", "1", "1", "3", "2", "4", "2", "2", "2", "4", "4", "3"};
+ EXPECT_EQ(12U, v2.size());
+ EXPECT_EQ(3U, v2.removeAll("1"));
+ EXPECT_EQ(9U, v2.size());
+ EXPECT_TRUE(v2.find("1") == notFound);
+ vExpected = {"3", "2", "4", "2", "2", "2", "4", "4", "3"};
+ EXPECT_TRUE(v2 == vExpected);
+}
+
+TEST(WTF_Vector, RemoveFirstMatching)
+{
+ Vector<int> v;
+ EXPECT_TRUE(v.isEmpty());
+ EXPECT_FALSE(v.removeFirstMatching([] (int value) { return value > 0; }));
+ EXPECT_FALSE(v.removeFirstMatching([] (int) { return true; }));
+ EXPECT_FALSE(v.removeFirstMatching([] (int) { return false; }));
+
+ v = {3, 1, 2, 1, 2, 1, 2, 2, 1, 1, 1, 3};
+ EXPECT_EQ(12U, v.size());
+ EXPECT_FALSE(v.removeFirstMatching([] (int) { return false; }));
+ EXPECT_EQ(12U, v.size());
+ EXPECT_FALSE(v.removeFirstMatching([] (int value) { return value < 0; }));
+ EXPECT_EQ(12U, v.size());
+ EXPECT_TRUE(v.removeFirstMatching([] (int value) { return value < 3; }));
+ EXPECT_EQ(11U, v.size());
+ EXPECT_TRUE(v == Vector<int>({3, 2, 1, 2, 1, 2, 2, 1, 1, 1, 3}));
+ EXPECT_TRUE(v.removeFirstMatching([] (int value) { return value > 2; }));
+ EXPECT_EQ(10U, v.size());
+ EXPECT_TRUE(v == Vector<int>({2, 1, 2, 1, 2, 2, 1, 1, 1, 3}));
+ EXPECT_TRUE(v.removeFirstMatching([] (int value) { return value > 2; }));
+ EXPECT_EQ(9U, v.size());
+ EXPECT_TRUE(v == Vector<int>({2, 1, 2, 1, 2, 2, 1, 1, 1}));
+}
+
+TEST(WTF_Vector, RemoveAllMatching)
+{
+ Vector<int> v;
+ EXPECT_TRUE(v.isEmpty());
+ EXPECT_FALSE(v.removeAllMatching([] (int value) { return value > 0; }));
+ EXPECT_FALSE(v.removeAllMatching([] (int) { return true; }));
+ EXPECT_FALSE(v.removeAllMatching([] (int) { return false; }));
+
+ v = {3, 1, 2, 1, 2, 1, 2, 2, 1, 1, 1, 3};
+ EXPECT_EQ(12U, v.size());
+ EXPECT_EQ(0U, v.removeAllMatching([] (int) { return false; }));
+ EXPECT_EQ(12U, v.size());
+ EXPECT_EQ(0U, v.removeAllMatching([] (int value) { return value < 0; }));
+ EXPECT_EQ(12U, v.size());
+ EXPECT_EQ(12U, v.removeAllMatching([] (int value) { return value > 0; }));
+ EXPECT_TRUE(v.isEmpty());
+
+ v = {3, 1, 2, 1, 2, 1, 3, 2, 2, 1, 1, 1, 3};
+ EXPECT_EQ(13U, v.size());
+ EXPECT_EQ(3U, v.removeAllMatching([] (int value) { return value > 2; }));
+ EXPECT_EQ(10U, v.size());
+ EXPECT_TRUE(v == Vector<int>({1, 2, 1, 2, 1, 2, 2, 1, 1, 1}));
+ EXPECT_EQ(6U, v.removeAllMatching([] (int value) { return value != 2; }));
+ EXPECT_EQ(4U, v.size());
+ EXPECT_TRUE(v == Vector<int>({2, 2, 2, 2}));
+ EXPECT_EQ(4U, v.removeAllMatching([] (int value) { return value == 2; }));
+ EXPECT_TRUE(v.isEmpty());
+}
+
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp b/Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp
new file mode 100644
index 000000000..27649658c
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2012 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <limits>
+#include <wtf/MathExtras.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF, StringCreationFromLiteral)
+{
+ String stringFromLiteral(ASCIILiteral("Explicit construction syntax"));
+ ASSERT_EQ(strlen("Explicit construction syntax"), stringFromLiteral.length());
+ ASSERT_TRUE(stringFromLiteral == "Explicit construction syntax");
+ ASSERT_TRUE(stringFromLiteral.is8Bit());
+ ASSERT_TRUE(String("Explicit construction syntax") == stringFromLiteral);
+
+ String stringWithTemplate("Template Literal", String::ConstructFromLiteral);
+ ASSERT_EQ(strlen("Template Literal"), stringWithTemplate.length());
+ ASSERT_TRUE(stringWithTemplate == "Template Literal");
+ ASSERT_TRUE(stringWithTemplate.is8Bit());
+ ASSERT_TRUE(String("Template Literal") == stringWithTemplate);
+}
+
+TEST(WTF, StringASCII)
+{
+ CString output;
+
+ // Null String.
+ output = String().ascii();
+ ASSERT_STREQ("", output.data());
+
+ // Empty String.
+ output = emptyString().ascii();
+ ASSERT_STREQ("", output.data());
+
+ // Regular String.
+ output = String(ASCIILiteral("foobar")).ascii();
+ ASSERT_STREQ("foobar", output.data());
+}
+
+static void testNumberToStringECMAScript(double number, const char* reference)
+{
+ CString numberString = String::numberToStringECMAScript(number).latin1();
+ ASSERT_STREQ(reference, numberString.data());
+}
+
+TEST(WTF, StringNumberToStringECMAScriptBoundaries)
+{
+ typedef std::numeric_limits<double> Limits;
+
+ // Infinity.
+ testNumberToStringECMAScript(Limits::infinity(), "Infinity");
+ testNumberToStringECMAScript(-Limits::infinity(), "-Infinity");
+
+ // NaN.
+ testNumberToStringECMAScript(-Limits::quiet_NaN(), "NaN");
+
+ // Zeros.
+ testNumberToStringECMAScript(0, "0");
+ testNumberToStringECMAScript(-0, "0");
+
+ // Min-Max.
+ testNumberToStringECMAScript(Limits::min(), "2.2250738585072014e-308");
+ testNumberToStringECMAScript(Limits::max(), "1.7976931348623157e+308");
+}
+
+TEST(WTF, StringNumberToStringECMAScriptRegularNumbers)
+{
+ // Pi.
+ testNumberToStringECMAScript(piDouble, "3.141592653589793");
+ testNumberToStringECMAScript(piFloat, "3.1415927410125732");
+ testNumberToStringECMAScript(piOverTwoDouble, "1.5707963267948966");
+ testNumberToStringECMAScript(piOverTwoFloat, "1.5707963705062866");
+ testNumberToStringECMAScript(piOverFourDouble, "0.7853981633974483");
+ testNumberToStringECMAScript(piOverFourFloat, "0.7853981852531433");
+
+ // e.
+ const double e = 2.71828182845904523536028747135266249775724709369995;
+ testNumberToStringECMAScript(e, "2.718281828459045");
+
+ // c, speed of light in m/s.
+ const double c = 299792458;
+ testNumberToStringECMAScript(c, "299792458");
+
+ // Golen ratio.
+ const double phi = 1.6180339887498948482;
+ testNumberToStringECMAScript(phi, "1.618033988749895");
+}
+
+TEST(WTF, StringReplaceWithLiteral)
+{
+ // Cases for 8Bit source.
+ String testString = "1224";
+ ASSERT_TRUE(testString.is8Bit());
+ testString.replaceWithLiteral('2', "");
+ ASSERT_STREQ("14", testString.utf8().data());
+
+ testString = "1224";
+ ASSERT_TRUE(testString.is8Bit());
+ testString.replaceWithLiteral('2', "3");
+ ASSERT_STREQ("1334", testString.utf8().data());
+
+ testString = "1224";
+ ASSERT_TRUE(testString.is8Bit());
+ testString.replaceWithLiteral('2', "555");
+ ASSERT_STREQ("15555554", testString.utf8().data());
+
+ testString = "1224";
+ ASSERT_TRUE(testString.is8Bit());
+ testString.replaceWithLiteral('3', "NotFound");
+ ASSERT_STREQ("1224", testString.utf8().data());
+
+ // Cases for 16Bit source.
+ testString = String::fromUTF8("résumé");
+ ASSERT_FALSE(testString.is8Bit());
+ testString.replaceWithLiteral(UChar(0x00E9 /*U+00E9 is 'é'*/), "e");
+ ASSERT_STREQ("resume", testString.utf8().data());
+
+ testString = String::fromUTF8("résumé");
+ ASSERT_FALSE(testString.is8Bit());
+ testString.replaceWithLiteral(UChar(0x00E9 /*U+00E9 is 'é'*/), "");
+ ASSERT_STREQ("rsum", testString.utf8().data());
+
+ testString = String::fromUTF8("résumé");
+ ASSERT_FALSE(testString.is8Bit());
+ testString.replaceWithLiteral('3', "NotFound");
+ ASSERT_STREQ("résumé", testString.utf8().data());
+}
+
+TEST(WTF, StringIsolatedCopy)
+{
+ String original = "1234";
+ auto copy = WTFMove(original).isolatedCopy();
+ ASSERT_FALSE(original.impl() == copy.impl());
+}
+
+TEST(WTF, StringToInt)
+{
+ bool ok = false;
+
+ EXPECT_EQ(0, String().toInt());
+ EXPECT_EQ(0, String().toInt(&ok));
+ EXPECT_FALSE(ok);
+
+ EXPECT_EQ(0, emptyString().toInt());
+ EXPECT_EQ(0, emptyString().toInt(&ok));
+ EXPECT_FALSE(ok);
+
+ EXPECT_EQ(0, String("0").toInt());
+ EXPECT_EQ(0, String("0").toInt(&ok));
+ EXPECT_TRUE(ok);
+
+ EXPECT_EQ(1, String("1").toInt());
+ EXPECT_EQ(1, String("1").toInt(&ok));
+ EXPECT_TRUE(ok);
+
+ EXPECT_EQ(2147483647, String("2147483647").toInt());
+ EXPECT_EQ(2147483647, String("2147483647").toInt(&ok));
+ EXPECT_TRUE(ok);
+
+ EXPECT_EQ(0, String("2147483648").toInt());
+ EXPECT_EQ(0, String("2147483648").toInt(&ok));
+ EXPECT_FALSE(ok);
+
+ EXPECT_EQ(-2147483648, String("-2147483648").toInt());
+ EXPECT_EQ(-2147483648, String("-2147483648").toInt(&ok));
+ EXPECT_TRUE(ok);
+
+ EXPECT_EQ(0, String("-2147483649").toInt());
+ EXPECT_EQ(0, String("-2147483649").toInt(&ok));
+ EXPECT_FALSE(ok);
+
+ // fail if we see leading junk
+ EXPECT_EQ(0, String("x1").toInt());
+ EXPECT_EQ(0, String("x1").toInt(&ok));
+ EXPECT_FALSE(ok);
+
+ // succeed if we see leading spaces
+ EXPECT_EQ(1, String(" 1").toInt());
+ EXPECT_EQ(1, String(" 1").toInt(&ok));
+ EXPECT_TRUE(ok);
+
+ // silently ignore trailing junk
+ EXPECT_EQ(1, String("1x").toInt());
+ EXPECT_EQ(1, String("1x").toInt(&ok));
+ EXPECT_TRUE(ok);
+}
+
+TEST(WTF, StringToDouble)
+{
+ bool ok = false;
+
+ EXPECT_EQ(0.0, String().toDouble());
+ EXPECT_EQ(0.0, String().toDouble(&ok));
+ EXPECT_FALSE(ok);
+
+ EXPECT_EQ(0.0, emptyString().toDouble());
+ EXPECT_EQ(0.0, emptyString().toDouble(&ok));
+ EXPECT_FALSE(ok);
+
+ EXPECT_EQ(0.0, String("0").toDouble());
+ EXPECT_EQ(0.0, String("0").toDouble(&ok));
+ EXPECT_TRUE(ok);
+
+ EXPECT_EQ(1.0, String("1").toDouble());
+ EXPECT_EQ(1.0, String("1").toDouble(&ok));
+ EXPECT_TRUE(ok);
+
+ // fail if we see leading junk
+ EXPECT_EQ(0.0, String("x1").toDouble());
+ EXPECT_EQ(0.0, String("x1").toDouble(&ok));
+ EXPECT_FALSE(ok);
+
+ // succeed if we see leading spaces
+ EXPECT_EQ(1.0, String(" 1").toDouble());
+ EXPECT_EQ(1.0, String(" 1").toDouble(&ok));
+ EXPECT_TRUE(ok);
+
+ // ignore trailing junk, but return false for "ok"
+ // FIXME: This is an inconsistency with toInt, which always guarantees
+ // it will return 0 if it's also going to return false for ok.
+ EXPECT_EQ(1.0, String("1x").toDouble());
+ EXPECT_EQ(1.0, String("1x").toDouble(&ok));
+ EXPECT_FALSE(ok);
+
+ // parse only numbers, not special values such as "infinity"
+ EXPECT_EQ(0.0, String("infinity").toDouble());
+ EXPECT_EQ(0.0, String("infinity").toDouble(&ok));
+ EXPECT_FALSE(ok);
+
+ // parse only numbers, not special values such as "nan"
+ EXPECT_EQ(0.0, String("nan").toDouble());
+ EXPECT_EQ(0.0, String("nan").toDouble(&ok));
+ EXPECT_FALSE(ok);
+}
+
+TEST(WTF, StringhasInfixStartingAt)
+{
+ EXPECT_TRUE(String("Test").is8Bit());
+ EXPECT_TRUE(String("Te").is8Bit());
+ EXPECT_TRUE(String("st").is8Bit());
+ EXPECT_TRUE(String("Test").hasInfixStartingAt(String("Te"), 0));
+ EXPECT_FALSE(String("Test").hasInfixStartingAt(String("Te"), 2));
+ EXPECT_TRUE(String("Test").hasInfixStartingAt(String("st"), 2));
+ EXPECT_FALSE(String("Test").hasInfixStartingAt(String("ST"), 2));
+
+ EXPECT_FALSE(String::fromUTF8("中国").is8Bit());
+ EXPECT_FALSE(String::fromUTF8("中").is8Bit());
+ EXPECT_FALSE(String::fromUTF8("国").is8Bit());
+ EXPECT_TRUE(String::fromUTF8("中国").hasInfixStartingAt(String::fromUTF8("中"), 0));
+ EXPECT_FALSE(String::fromUTF8("中国").hasInfixStartingAt(String::fromUTF8("中"), 1));
+ EXPECT_TRUE(String::fromUTF8("中国").hasInfixStartingAt(String::fromUTF8("国"), 1));
+
+ EXPECT_FALSE(String::fromUTF8("中国").hasInfixStartingAt(String("Te"), 0));
+ EXPECT_FALSE(String("Test").hasInfixStartingAt(String::fromUTF8("中"), 2));
+}
+
+TEST(WTF, StringExistingHash)
+{
+ String string1("Template Literal");
+ ASSERT_FALSE(string1.isNull());
+ ASSERT_FALSE(string1.impl()->hasHash());
+ string1.impl()->hash();
+ ASSERT_EQ(string1.existingHash(), string1.impl()->existingHash());
+ String string2;
+ ASSERT_EQ(string2.existingHash(), 0u);
+}
+
+TEST(WTF, StringUnicodeEqualUCharArray)
+{
+ String string1("abc");
+ ASSERT_FALSE(string1.isNull());
+ ASSERT_TRUE(string1.is8Bit());
+ UChar ab[] = { 'a', 'b' };
+ UChar abc[] = { 'a', 'b', 'c' };
+ UChar abcd[] = { 'a', 'b', 'c', 'd' };
+ UChar aBc[] = { 'a', 'B', 'c' };
+ ASSERT_FALSE(equal(string1, ab));
+ ASSERT_TRUE(equal(string1, abc));
+ ASSERT_FALSE(equal(string1, abcd));
+ ASSERT_FALSE(equal(string1, aBc));
+
+ String string2(abc, 3);
+ ASSERT_FALSE(equal(string2, ab));
+ ASSERT_TRUE(equal(string2, abc));
+ ASSERT_FALSE(equal(string2, abcd));
+ ASSERT_FALSE(equal(string2, aBc));
+}
+
+TEST(WTF, StringRightBasic)
+{
+ auto reference = String::fromUTF8("Cappuccino");
+ EXPECT_TRUE(reference.right(0) == String::fromUTF8(""));
+ EXPECT_TRUE(reference.right(1) == String::fromUTF8("o"));
+ EXPECT_TRUE(reference.right(2) == String::fromUTF8("no"));
+ EXPECT_TRUE(reference.right(3) == String::fromUTF8("ino"));
+ EXPECT_TRUE(reference.right(4) == String::fromUTF8("cino"));
+ EXPECT_TRUE(reference.right(5) == String::fromUTF8("ccino"));
+ EXPECT_TRUE(reference.right(6) == String::fromUTF8("uccino"));
+ EXPECT_TRUE(reference.right(7) == String::fromUTF8("puccino"));
+ EXPECT_TRUE(reference.right(8) == String::fromUTF8("ppuccino"));
+ EXPECT_TRUE(reference.right(9) == String::fromUTF8("appuccino"));
+ EXPECT_TRUE(reference.right(10) == String::fromUTF8("Cappuccino"));
+}
+
+TEST(WTF, StringLeftBasic)
+{
+ auto reference = String::fromUTF8("Cappuccino");
+ EXPECT_TRUE(reference.left(0) == String::fromUTF8(""));
+ EXPECT_TRUE(reference.left(1) == String::fromUTF8("C"));
+ EXPECT_TRUE(reference.left(2) == String::fromUTF8("Ca"));
+ EXPECT_TRUE(reference.left(3) == String::fromUTF8("Cap"));
+ EXPECT_TRUE(reference.left(4) == String::fromUTF8("Capp"));
+ EXPECT_TRUE(reference.left(5) == String::fromUTF8("Cappu"));
+ EXPECT_TRUE(reference.left(6) == String::fromUTF8("Cappuc"));
+ EXPECT_TRUE(reference.left(7) == String::fromUTF8("Cappucc"));
+ EXPECT_TRUE(reference.left(8) == String::fromUTF8("Cappucci"));
+ EXPECT_TRUE(reference.left(9) == String::fromUTF8("Cappuccin"));
+ EXPECT_TRUE(reference.left(10) == String::fromUTF8("Cappuccino"));
+}
+
+TEST(WTF, StringReverseFindBasic)
+{
+ auto reference = String::fromUTF8("Cappuccino");
+ EXPECT_EQ(reference.reverseFind('o'), 9U);
+ EXPECT_EQ(reference.reverseFind('n'), 8U);
+ EXPECT_EQ(reference.reverseFind('c'), 6U);
+ EXPECT_EQ(reference.reverseFind('p'), 3U);
+ EXPECT_EQ(reference.reverseFind('k'), notFound);
+
+ EXPECT_EQ(reference.reverseFind('o', 8), notFound);
+ EXPECT_EQ(reference.reverseFind('c', 8), 6U);
+ EXPECT_EQ(reference.reverseFind('c', 6), 6U);
+ EXPECT_EQ(reference.reverseFind('c', 5), 5U);
+ EXPECT_EQ(reference.reverseFind('c', 4), notFound);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/WeakPtr.cpp b/Tools/TestWebKitAPI/Tests/WTF/WeakPtr.cpp
new file mode 100644
index 000000000..745aadd2b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/WeakPtr.cpp
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include "Test.h"
+#include <wtf/WeakPtr.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF_WeakPtr, Basic)
+{
+ int dummy = 5;
+ WeakPtrFactory<int>* factory = new WeakPtrFactory<int>(&dummy);
+ WeakPtr<int> weakPtr1 = factory->createWeakPtr();
+ WeakPtr<int> weakPtr2 = factory->createWeakPtr();
+ WeakPtr<int> weakPtr3 = factory->createWeakPtr();
+ EXPECT_EQ(weakPtr1.get(), &dummy);
+ EXPECT_EQ(weakPtr2.get(), &dummy);
+ EXPECT_EQ(weakPtr3.get(), &dummy);
+ EXPECT_TRUE(weakPtr1);
+ EXPECT_TRUE(weakPtr2);
+ EXPECT_TRUE(weakPtr3);
+ EXPECT_TRUE(weakPtr1 == weakPtr2);
+ EXPECT_TRUE(weakPtr1 == &dummy);
+ EXPECT_TRUE(&dummy == weakPtr2);
+ delete factory;
+ EXPECT_NULL(weakPtr1.get());
+ EXPECT_NULL(weakPtr2.get());
+ EXPECT_NULL(weakPtr3.get());
+ EXPECT_FALSE(weakPtr1);
+ EXPECT_FALSE(weakPtr2);
+ EXPECT_FALSE(weakPtr3);
+}
+
+TEST(WTF_WeakPtr, Assignment)
+{
+ int dummy = 5;
+ WeakPtr<int> weakPtr;
+ {
+ WeakPtrFactory<int> factory(&dummy);
+ EXPECT_NULL(weakPtr.get());
+ weakPtr = factory.createWeakPtr();
+ EXPECT_EQ(weakPtr.get(), &dummy);
+ }
+ EXPECT_NULL(weakPtr.get());
+}
+
+TEST(WTF_WeakPtr, MultipleFactories)
+{
+ int dummy1 = 5;
+ int dummy2 = 7;
+ WeakPtrFactory<int>* factory1 = new WeakPtrFactory<int>(&dummy1);
+ WeakPtrFactory<int>* factory2 = new WeakPtrFactory<int>(&dummy2);
+ WeakPtr<int> weakPtr1 = factory1->createWeakPtr();
+ WeakPtr<int> weakPtr2 = factory2->createWeakPtr();
+ EXPECT_EQ(weakPtr1.get(), &dummy1);
+ EXPECT_EQ(weakPtr2.get(), &dummy2);
+ EXPECT_TRUE(weakPtr1 != weakPtr2);
+ EXPECT_TRUE(weakPtr1 != &dummy2);
+ EXPECT_TRUE(&dummy1 != weakPtr2);
+ delete factory1;
+ EXPECT_NULL(weakPtr1.get());
+ EXPECT_EQ(weakPtr2.get(), &dummy2);
+ delete factory2;
+ EXPECT_NULL(weakPtr2.get());
+}
+
+TEST(WTF_WeakPtr, RevokeAll)
+{
+ int dummy = 5;
+ WeakPtrFactory<int> factory(&dummy);
+ WeakPtr<int> weakPtr1 = factory.createWeakPtr();
+ WeakPtr<int> weakPtr2 = factory.createWeakPtr();
+ WeakPtr<int> weakPtr3 = factory.createWeakPtr();
+ EXPECT_EQ(weakPtr1.get(), &dummy);
+ EXPECT_EQ(weakPtr2.get(), &dummy);
+ EXPECT_EQ(weakPtr3.get(), &dummy);
+ factory.revokeAll();
+ EXPECT_NULL(weakPtr1.get());
+ EXPECT_NULL(weakPtr2.get());
+ EXPECT_NULL(weakPtr3.get());
+}
+
+TEST(WTF_WeakPtr, NullFactory)
+{
+ WeakPtrFactory<int> factory(nullptr);
+ WeakPtr<int> weakPtr = factory.createWeakPtr();
+ EXPECT_NULL(weakPtr.get());
+ factory.revokeAll();
+ EXPECT_NULL(weakPtr.get());
+}
+
+struct Foo {
+ void bar() { };
+};
+
+TEST(WTF_WeakPtr, Dereference)
+{
+ Foo f;
+ WeakPtrFactory<Foo> factory(&f);
+ WeakPtr<Foo> weakPtr = factory.createWeakPtr();
+ weakPtr->bar();
+}
+
+TEST(WTF_WeakPtr, Forget)
+{
+ int dummy = 5;
+ int dummy2 = 7;
+
+ WeakPtrFactory<int> outerFactory(&dummy2);
+ WeakPtr<int> weakPtr1, weakPtr2, weakPtr3, weakPtr4;
+ {
+ WeakPtrFactory<int> innerFactory(&dummy);
+ weakPtr1 = innerFactory.createWeakPtr();
+ weakPtr2 = innerFactory.createWeakPtr();
+ weakPtr3 = innerFactory.createWeakPtr();
+ EXPECT_EQ(weakPtr1.get(), &dummy);
+ EXPECT_EQ(weakPtr2.get(), &dummy);
+ EXPECT_EQ(weakPtr3.get(), &dummy);
+ weakPtr1.clear();
+ weakPtr3 = nullptr;
+ EXPECT_NULL(weakPtr1.get());
+ EXPECT_EQ(weakPtr2.get(), &dummy);
+ EXPECT_NULL(weakPtr3.get());
+ weakPtr1.clear();
+ weakPtr3.clear();
+ EXPECT_NULL(weakPtr1.get());
+ EXPECT_EQ(weakPtr2.get(), &dummy);
+ EXPECT_NULL(weakPtr3.get());
+ weakPtr3 = nullptr;
+ EXPECT_NULL(weakPtr1.get());
+ EXPECT_EQ(weakPtr2.get(), &dummy);
+ EXPECT_NULL(weakPtr3.get());
+
+ weakPtr4 = weakPtr2;
+ EXPECT_EQ(weakPtr2.get(), &dummy);
+ EXPECT_EQ(weakPtr4.get(), &dummy);
+
+ WeakPtr<int> weakPtr5 = weakPtr2;
+ EXPECT_EQ(weakPtr2.get(), &dummy);
+ EXPECT_EQ(weakPtr5.get(), &dummy);
+ weakPtr5.clear();
+ EXPECT_NULL(weakPtr5.get());
+ EXPECT_EQ(weakPtr2.get(), &dummy);
+
+ weakPtr4 = outerFactory.createWeakPtr();
+ EXPECT_EQ(weakPtr2.get(), &dummy);
+ EXPECT_EQ(weakPtr4.get(), &dummy2);
+ }
+
+ EXPECT_NULL(weakPtr1.get());
+ EXPECT_NULL(weakPtr2.get());
+ EXPECT_EQ(weakPtr4.get(), &dummy2);
+
+ WeakPtr<int> weakPtr5 = weakPtr4;
+ EXPECT_EQ(weakPtr4.get(), &dummy2);
+ EXPECT_EQ(weakPtr5.get(), &dummy2);
+ weakPtr5.clear();
+ EXPECT_NULL(weakPtr5.get());
+ WeakPtr<int> weakPtr6 = weakPtr5;
+ EXPECT_NULL(weakPtr6.get());
+ EXPECT_EQ(weakPtr5.get(), weakPtr6.get());
+
+ WeakPtr<int> weakPtr7 = outerFactory.createWeakPtr();
+ EXPECT_EQ(weakPtr7.get(), &dummy2);
+ weakPtr7 = nullptr;
+ EXPECT_NULL(weakPtr7.get());
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/WorkQueue.cpp b/Tools/TestWebKitAPI/Tests/WTF/WorkQueue.cpp
new file mode 100644
index 000000000..7e277e94c
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/WorkQueue.cpp
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include "Test.h"
+#include <wtf/Condition.h>
+#include <wtf/Lock.h>
+#include <wtf/Vector.h>
+#include <wtf/WorkQueue.h>
+#include <string>
+#include <thread>
+
+namespace TestWebKitAPI {
+
+static const char* simpleTestLabel = "simpleTest";
+static const char* longTestLabel = "longTest";
+static const char* thirdTestLabel = "thirdTest";
+static const char* dispatchAfterLabel = "dispatchAfter";
+
+TEST(WTF_WorkQueue, Simple)
+{
+ Lock m_lock;
+ Condition m_testCompleted;
+ Vector<std::string> m_functionCallOrder;
+
+ bool calledSimpleTest = false;
+ bool calledLongTest = false;
+ bool calledThirdTest = false;
+
+ static const char* simpleTestLabel = "simpleTest";
+ static const char* longTestLabel = "longTest";
+ static const char* thirdTestLabel = "thirdTest";
+
+ auto queue = WorkQueue::create("com.apple.WebKit.Test.simple");
+ int initialRefCount = queue->refCount();
+ EXPECT_EQ(1, initialRefCount);
+
+ LockHolder locker(m_lock);
+ queue->dispatch([&](void) {
+ m_functionCallOrder.append(simpleTestLabel);
+ calledSimpleTest = true;
+ });
+
+ queue->dispatch([&](void) {
+ m_functionCallOrder.append(longTestLabel);
+ std::this_thread::sleep_for(std::chrono::nanoseconds(100));
+ calledLongTest = true;
+ });
+
+ queue->dispatch([&](void) {
+ LockHolder locker(m_lock);
+ m_functionCallOrder.append(thirdTestLabel);
+ calledThirdTest = true;
+
+ EXPECT_TRUE(calledSimpleTest);
+ EXPECT_TRUE(calledLongTest);
+ EXPECT_TRUE(calledThirdTest);
+
+ m_testCompleted.notifyOne();
+ });
+
+ EXPECT_GT(queue->refCount(), 1);
+
+ m_testCompleted.wait(m_lock);
+
+ EXPECT_TRUE(calledSimpleTest);
+ EXPECT_TRUE(calledLongTest);
+ EXPECT_TRUE(calledThirdTest);
+
+ EXPECT_EQ(static_cast<size_t>(3), m_functionCallOrder.size());
+ EXPECT_STREQ(simpleTestLabel, m_functionCallOrder[0].c_str());
+ EXPECT_STREQ(longTestLabel, m_functionCallOrder[1].c_str());
+ EXPECT_STREQ(thirdTestLabel, m_functionCallOrder[2].c_str());
+}
+
+TEST(WTF_WorkQueue, TwoQueues)
+{
+ Lock m_lock;
+ Condition m_testQueue1Completed, m_testQueue2Completed;
+ Vector<std::string> m_functionCallOrder;
+
+ bool calledSimpleTest = false;
+ bool calledLongTest = false;
+ bool calledThirdTest = false;
+
+ auto queue1 = WorkQueue::create("com.apple.WebKit.Test.twoQueues1");
+ auto queue2 = WorkQueue::create("com.apple.WebKit.Test.twoQueues2");
+
+ EXPECT_EQ(1, queue1->refCount());
+ EXPECT_EQ(1, queue2->refCount());
+
+ LockHolder locker(m_lock);
+
+ queue1->dispatch([&](void) {
+ m_functionCallOrder.append(simpleTestLabel);
+ calledSimpleTest = true;
+ });
+
+ queue2->dispatch([&](void) {
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
+
+ LockHolder locker(m_lock);
+
+ // Will fail if queue2 took the mutex before queue1.
+ EXPECT_TRUE(calledThirdTest);
+
+ m_functionCallOrder.append(longTestLabel);
+ calledLongTest = true;
+ m_testQueue2Completed.notifyOne();
+ });
+
+ queue1->dispatch([&](void) {
+ LockHolder locker(m_lock);
+ m_functionCallOrder.append(thirdTestLabel);
+ calledThirdTest = true;
+
+ m_testQueue1Completed.notifyOne();
+ });
+
+ m_testQueue1Completed.wait(m_lock);
+
+ EXPECT_TRUE(calledSimpleTest);
+ EXPECT_FALSE(calledLongTest);
+ EXPECT_TRUE(calledThirdTest);
+
+ m_testQueue2Completed.wait(m_lock);
+
+ EXPECT_TRUE(calledSimpleTest);
+ EXPECT_TRUE(calledLongTest);
+ EXPECT_TRUE(calledThirdTest);
+
+ EXPECT_EQ(static_cast<size_t>(3), m_functionCallOrder.size());
+ EXPECT_STREQ(simpleTestLabel, m_functionCallOrder[0].c_str());
+ EXPECT_STREQ(thirdTestLabel, m_functionCallOrder[1].c_str());
+ EXPECT_STREQ(longTestLabel, m_functionCallOrder[2].c_str());
+}
+
+TEST(WTF_WorkQueue, DispatchAfter)
+{
+ Lock m_lock;
+ Condition m_testCompleted, m_dispatchAfterTestCompleted;
+ Vector<std::string> m_functionCallOrder;
+
+ bool calledSimpleTest = false;
+ bool calledDispatchAfterTest = false;
+
+ auto queue = WorkQueue::create("com.apple.WebKit.Test.dispatchAfter");
+
+ LockHolder locker(m_lock);
+
+ queue->dispatch([&](void) {
+ LockHolder locker(m_lock);
+ m_functionCallOrder.append(simpleTestLabel);
+ calledSimpleTest = true;
+ m_testCompleted.notifyOne();
+ });
+
+ queue->dispatchAfter(std::chrono::milliseconds(500), [&](void) {
+ LockHolder locker(m_lock);
+ m_functionCallOrder.append(dispatchAfterLabel);
+ calledDispatchAfterTest = true;
+ m_dispatchAfterTestCompleted.notifyOne();
+ });
+
+ m_testCompleted.wait(m_lock);
+
+ EXPECT_TRUE(calledSimpleTest);
+ EXPECT_FALSE(calledDispatchAfterTest);
+
+ m_dispatchAfterTestCompleted.wait(m_lock);
+
+ EXPECT_TRUE(calledSimpleTest);
+ EXPECT_TRUE(calledDispatchAfterTest);
+
+ EXPECT_EQ(static_cast<size_t>(2), m_functionCallOrder.size());
+ EXPECT_STREQ(simpleTestLabel, m_functionCallOrder[0].c_str());
+ EXPECT_STREQ(dispatchAfterLabel, m_functionCallOrder[1].c_str());
+}
+
+TEST(WTF_WorkQueue, DestroyOnSelf)
+{
+ Lock lock;
+ Condition dispatchAfterTestStarted;
+ Condition dispatchAfterTestCompleted;
+ bool started = false;
+ bool completed = false;
+
+ {
+ LockHolder locker(lock);
+ {
+ auto queue = WorkQueue::create("com.apple.WebKit.Test.dispatchAfter");
+ queue->dispatchAfter(std::chrono::milliseconds(500), [&](void) {
+ LockHolder locker(lock);
+ dispatchAfterTestStarted.wait(lock, [&] {
+ return started;
+ });
+ completed = true;
+ dispatchAfterTestCompleted.notifyOne();
+ });
+ }
+ started = true;
+ dispatchAfterTestStarted.notifyOne();
+ }
+ {
+ LockHolder locker(lock);
+ dispatchAfterTestCompleted.wait(lock, [&] {
+ return completed;
+ });
+ WTF::sleep(0.1);
+ }
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/darwin/OSObjectPtr.cpp b/Tools/TestWebKitAPI/Tests/WTF/darwin/OSObjectPtr.cpp
new file mode 100644
index 000000000..5389dcbc8
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/darwin/OSObjectPtr.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2014 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <wtf/OSObjectPtr.h>
+
+#include <dispatch/dispatch.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+namespace TestWebKitAPI {
+
+TEST(OSObjectPtr, AdoptOSObject)
+{
+ OSObjectPtr<dispatch_queue_t> foo = adoptOSObject(dispatch_queue_create(0, DISPATCH_QUEUE_SERIAL));
+
+ EXPECT_EQ(1, CFGetRetainCount(foo.get()));
+}
+
+TEST(OSObjectPtr, RetainRelease)
+{
+ dispatch_queue_t foo = dispatch_queue_create(0, DISPATCH_QUEUE_SERIAL);
+ EXPECT_EQ(1, CFGetRetainCount(foo));
+
+ WTF::retainOSObject(foo);
+ EXPECT_EQ(2, CFGetRetainCount(foo));
+
+ WTF::releaseOSObject(foo);
+ EXPECT_EQ(1, CFGetRetainCount(foo));
+}
+
+TEST(OSObjectPtr, LeakRef)
+{
+ OSObjectPtr<dispatch_queue_t> foo = adoptOSObject(dispatch_queue_create(0, DISPATCH_QUEUE_SERIAL));
+ EXPECT_EQ(1, CFGetRetainCount(foo.get()));
+
+ dispatch_queue_t queue = foo.leakRef();
+ EXPECT_EQ(nullptr, foo.get());
+ EXPECT_EQ(1, CFGetRetainCount(queue));
+
+ WTF::releaseOSObject(queue);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WTF/gobject/GUniquePtr.cpp b/Tools/TestWebKitAPI/Tests/WTF/glib/GUniquePtr.cpp
index 8942f8657..11f02c7b0 100644
--- a/Tools/TestWebKitAPI/Tests/WTF/gobject/GUniquePtr.cpp
+++ b/Tools/TestWebKitAPI/Tests/WTF/glib/GUniquePtr.cpp
@@ -80,7 +80,7 @@ static void (* _g_key_file_free)(GKeyFile*) = g_key_file_free;
log() << "g_key_file_free(" << ptr << ");"; \
_g_key_file_free(x);
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GUniquePtr.h>
namespace TestWebKitAPI {
diff --git a/Tools/TestWebKitAPI/Tests/WTF/glib/WorkQueueGLib.cpp b/Tools/TestWebKitAPI/Tests/WTF/glib/WorkQueueGLib.cpp
new file mode 100644
index 000000000..9923d6580
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WTF/glib/WorkQueueGLib.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 Igalia S.L.
+ *
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include "Test.h"
+#include <gio/gio.h>
+#include <thread>
+#include <wtf/Condition.h>
+#include <wtf/Lock.h>
+#include <wtf/WorkQueue.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/glib/GUniquePtr.h>
+
+namespace TestWebKitAPI {
+
+TEST(WTF_WorkQueue, AsyncIO)
+{
+ struct TestingContext {
+ Lock m_lock;
+ Condition m_testCompleted;
+ GMainContext* m_mainContext;
+ } context;
+
+ auto queue = WorkQueue::create("com.apple.WebKit.Test.AsyncIO");
+ context.m_mainContext = g_main_context_default();
+ EXPECT_FALSE(g_main_context_get_thread_default());
+
+ GUniquePtr<char> currentDirectory(g_get_current_dir());
+ GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(currentDirectory.get()));
+
+ LockHolder locker(context.m_lock);
+ queue->dispatch([&](void) {
+ EXPECT_TRUE(g_main_context_get_thread_default());
+ EXPECT_TRUE(g_main_context_get_thread_default() != context.m_mainContext);
+ context.m_mainContext = g_main_context_get_thread_default();
+ g_file_query_info_async(file.get(), G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT, nullptr,
+ [](GObject*, GAsyncResult*, gpointer userData) {
+ TestingContext* context = static_cast<TestingContext*>(userData);
+ LockHolder locker(context->m_lock);
+ EXPECT_EQ(g_main_context_get_thread_default(), context->m_mainContext);
+ context->m_testCompleted.notifyOne();
+ }, &context);
+ });
+
+ context.m_testCompleted.wait(context.m_lock);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/AffineTransform.cpp b/Tools/TestWebKitAPI/Tests/WebCore/AffineTransform.cpp
new file mode 100644
index 000000000..9bcd1a4de
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/AffineTransform.cpp
@@ -0,0 +1,1024 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <WebCore/AffineTransform.h>
+#include <WebCore/FloatPoint.h>
+#include <WebCore/FloatQuad.h>
+#include <WebCore/FloatRect.h>
+#include <WebCore/FloatSize.h>
+#include <WebCore/IntPoint.h>
+#include <WebCore/IntRect.h>
+#include <WebCore/IntSize.h>
+#include <WebCore/TransformationMatrix.h>
+
+#if USE(CG)
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
+namespace TestWebKitAPI {
+
+static void testGetAndSet(WebCore::AffineTransform& affineTransform)
+{
+ affineTransform.setA(1.1);
+ EXPECT_DOUBLE_EQ(1.1, affineTransform.a());
+ affineTransform.setB(2.2);
+ EXPECT_DOUBLE_EQ(2.2, affineTransform.b());
+ affineTransform.setC(3.3);
+ EXPECT_DOUBLE_EQ(3.3, affineTransform.c());
+ affineTransform.setD(4.4);
+ EXPECT_DOUBLE_EQ(4.4, affineTransform.d());
+ affineTransform.setE(5.5);
+ EXPECT_DOUBLE_EQ(5.5, affineTransform.e());
+ affineTransform.setF(6.6);
+ EXPECT_DOUBLE_EQ(6.6, affineTransform.f());
+}
+
+static void testIdentity(const WebCore::AffineTransform& transform)
+{
+ EXPECT_DOUBLE_EQ(1.0, transform.a());
+ EXPECT_DOUBLE_EQ(0.0, transform.b());
+ EXPECT_DOUBLE_EQ(0.0, transform.c());
+ EXPECT_DOUBLE_EQ(1.0, transform.d());
+ EXPECT_DOUBLE_EQ(0.0, transform.e());
+ EXPECT_DOUBLE_EQ(0.0, transform.f());
+}
+
+TEST(AffineTransform, DefaultConstruction)
+{
+ WebCore::AffineTransform test;
+
+ testIdentity(test);
+ testGetAndSet(test);
+
+ ASSERT_FALSE(test.isIdentity());
+}
+
+static void testValueConstruction(const WebCore::AffineTransform& transform)
+{
+ EXPECT_DOUBLE_EQ(6.0, transform.a());
+ EXPECT_DOUBLE_EQ(5.0, transform.b());
+ EXPECT_DOUBLE_EQ(4.0, transform.c());
+ EXPECT_DOUBLE_EQ(3.0, transform.d());
+ EXPECT_DOUBLE_EQ(2.0, transform.e());
+ EXPECT_DOUBLE_EQ(1.0, transform.f());
+}
+
+static void testDoubled(const WebCore::AffineTransform& transform)
+{
+ EXPECT_DOUBLE_EQ(12.0, transform.a());
+ EXPECT_DOUBLE_EQ(10.0, transform.b());
+ EXPECT_DOUBLE_EQ(8.0, transform.c());
+ EXPECT_DOUBLE_EQ(6.0, transform.d());
+ EXPECT_DOUBLE_EQ(2.0, transform.e());
+ EXPECT_DOUBLE_EQ(1.0, transform.f());
+}
+
+static void testHalved(const WebCore::AffineTransform& transform)
+{
+ EXPECT_DOUBLE_EQ(3.0, transform.a());
+ EXPECT_DOUBLE_EQ(2.5, transform.b());
+ EXPECT_DOUBLE_EQ(2.0, transform.c());
+ EXPECT_DOUBLE_EQ(1.5, transform.d());
+ EXPECT_DOUBLE_EQ(2.0, transform.e());
+ EXPECT_DOUBLE_EQ(1.0, transform.f());
+}
+
+TEST(AffineTransform, ValueConstruction)
+{
+ WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ testValueConstruction(test);
+ testGetAndSet(test);
+
+ ASSERT_FALSE(test.isIdentity());
+ ASSERT_FALSE(test.preservesAxisAlignment());
+}
+
+#if USE(CG)
+TEST(AffineTransform, CGAffineTransformConstruction)
+{
+ CGAffineTransform cgTransform = CGAffineTransformMake(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+ WebCore::AffineTransform test(cgTransform);
+
+ testValueConstruction(test);
+ testGetAndSet(test);
+
+ ASSERT_FALSE(test.isIdentity());
+}
+#endif
+
+#if PLATFORM(WIN)
+TEST(AffineTransform, D2D1MatrixConstruction)
+{
+ D2D1_MATRIX_3X2_F d2dTransform = D2D1::Matrix3x2F(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+ WebCore::AffineTransform test(d2dTransform);
+
+ testValueConstruction(test);
+ testGetAndSet(test);
+
+ ASSERT_FALSE(test.isIdentity());
+}
+#endif
+
+TEST(AffineTransform, Identity)
+{
+ WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ ASSERT_FALSE(test.isIdentity());
+ ASSERT_FALSE(test.isIdentityOrTranslation());
+ ASSERT_FALSE(test.isIdentityOrTranslationOrFlipped());
+ ASSERT_FALSE(test.preservesAxisAlignment());
+
+ test.makeIdentity();
+
+ ASSERT_TRUE(test.isIdentity());
+ ASSERT_TRUE(test.isIdentityOrTranslation());
+ ASSERT_TRUE(test.isIdentityOrTranslationOrFlipped());
+ ASSERT_TRUE(test.preservesAxisAlignment());
+
+ testIdentity(test);
+}
+
+TEST(AffineTransform, MapFloatPoint)
+{
+ WebCore::AffineTransform test;
+ WebCore::FloatPoint point(100.0f, 50.0f);
+
+ auto mappedPoint = test.mapPoint(point);
+
+ ASSERT_FLOAT_EQ(100.0f, mappedPoint.x());
+ ASSERT_FLOAT_EQ(50.0f, mappedPoint.y());
+
+ test.setD(2.0);
+
+ auto mappedPoint2 = test.mapPoint(point);
+
+ ASSERT_FLOAT_EQ(100.0f, mappedPoint2.x());
+ ASSERT_FLOAT_EQ(100.0f, mappedPoint2.y());
+
+ test.setA(0.5);
+
+ auto mappedPoint3 = test.mapPoint(point);
+
+ ASSERT_FLOAT_EQ(50.0f, mappedPoint3.x());
+ ASSERT_FLOAT_EQ(100.0f, mappedPoint3.y());
+}
+
+TEST(AffineTransform, MapIntPoint)
+{
+ WebCore::AffineTransform test;
+ WebCore::IntPoint point(100, 50);
+
+ auto mappedPoint = test.mapPoint(point);
+
+ ASSERT_EQ(100, mappedPoint.x());
+ ASSERT_EQ(50, mappedPoint.y());
+
+ test.setD(2.0);
+
+ auto mappedPoint2 = test.mapPoint(point);
+
+ ASSERT_EQ(100, mappedPoint2.x());
+ ASSERT_EQ(100, mappedPoint2.y());
+
+ test.setA(0.5);
+
+ auto mappedPoint3 = test.mapPoint(point);
+
+ ASSERT_EQ(50, mappedPoint3.x());
+ ASSERT_EQ(100, mappedPoint3.y());
+}
+
+TEST(AffineTransform, MapIntSize)
+{
+ WebCore::AffineTransform test;
+ WebCore::IntSize size(200, 300);
+
+ auto mappedSize = test.mapSize(size);
+
+ ASSERT_EQ(200, mappedSize.width());
+ ASSERT_EQ(300, mappedSize.height());
+
+ test.setD(2.0);
+
+ auto mappedSize2 = test.mapSize(size);
+
+ ASSERT_EQ(200, mappedSize2.width());
+ ASSERT_EQ(600, mappedSize2.height());
+
+ test.setA(0.5);
+
+ auto mappedSize3 = test.mapSize(size);
+
+ ASSERT_EQ(100, mappedSize3.width());
+ ASSERT_EQ(600, mappedSize3.height());
+}
+
+TEST(AffineTransform, MapFloatSize)
+{
+ WebCore::AffineTransform test;
+ WebCore::FloatSize size(200.0f, 300.0f);
+
+ auto mappedSize = test.mapSize(size);
+
+ ASSERT_EQ(200.0f, mappedSize.width());
+ ASSERT_EQ(300.0f, mappedSize.height());
+
+ test.setD(2.0);
+
+ auto mappedSize2 = test.mapSize(size);
+
+ ASSERT_EQ(200.0f, mappedSize2.width());
+ ASSERT_EQ(600.0f, mappedSize2.height());
+
+ test.setA(0.5);
+
+ auto mappedSize3 = test.mapSize(size);
+
+ ASSERT_EQ(100.0f, mappedSize3.width());
+ ASSERT_EQ(600.0f, mappedSize3.height());
+}
+
+TEST(AffineTransform, MapIntRect)
+{
+ WebCore::AffineTransform test;
+ WebCore::IntRect rect(10, 20, 200, 300);
+
+ auto mappedRect = test.mapRect(rect);
+
+ ASSERT_EQ(10, mappedRect.x());
+ ASSERT_EQ(20, mappedRect.y());
+ ASSERT_EQ(200, mappedRect.width());
+ ASSERT_EQ(300, mappedRect.height());
+
+ test.setD(2.0);
+
+ auto mappedRect2 = test.mapRect(rect);
+
+ ASSERT_EQ(10, mappedRect2.x());
+ ASSERT_EQ(40, mappedRect2.y());
+ ASSERT_EQ(200, mappedRect2.width());
+ ASSERT_EQ(600, mappedRect2.height());
+
+ test.setA(0.5);
+
+ auto mappedRect3 = test.mapRect(rect);
+
+ ASSERT_EQ(5, mappedRect3.x());
+ ASSERT_EQ(40, mappedRect3.y());
+ ASSERT_EQ(100, mappedRect3.width());
+ ASSERT_EQ(600, mappedRect3.height());
+}
+
+TEST(AffineTransform, MapFloatRect)
+{
+ WebCore::AffineTransform test;
+ WebCore::FloatRect rect(10.f, 20.0f, 200.0f, 300.0f);
+
+ auto mappedRect = test.mapRect(rect);
+
+ ASSERT_FLOAT_EQ(10.0f, mappedRect.x());
+ ASSERT_FLOAT_EQ(20.0f, mappedRect.y());
+ ASSERT_FLOAT_EQ(200.0f, mappedRect.width());
+ ASSERT_FLOAT_EQ(300.0f, mappedRect.height());
+
+ test.setD(2.0);
+
+ auto mappedRect2 = test.mapRect(rect);
+
+ ASSERT_FLOAT_EQ(10.0f, mappedRect2.x());
+ ASSERT_FLOAT_EQ(40.0f, mappedRect2.y());
+ ASSERT_FLOAT_EQ(200.0f, mappedRect2.width());
+ ASSERT_FLOAT_EQ(600.0f, mappedRect2.height());
+
+ test.setA(0.5);
+
+ auto mappedRect3 = test.mapRect(rect);
+
+ ASSERT_FLOAT_EQ(5.0f, mappedRect3.x());
+ ASSERT_FLOAT_EQ(40.0f, mappedRect3.y());
+ ASSERT_FLOAT_EQ(100.0f, mappedRect3.width());
+ ASSERT_FLOAT_EQ(600.0f, mappedRect3.height());
+}
+
+TEST(AffineTransform, MapFloatQuad)
+{
+ WebCore::FloatRect rect(100.0f, 100.0f, 100.0f, 50.0f);
+ WebCore::FloatQuad quad(rect);
+
+ ASSERT_FLOAT_EQ(100.0f, quad.p1().x());
+ ASSERT_FLOAT_EQ(100.0f, quad.p1().y());
+ ASSERT_FLOAT_EQ(200.0f, quad.p2().x());
+ ASSERT_FLOAT_EQ(100.0f, quad.p2().y());
+ ASSERT_FLOAT_EQ(200.0f, quad.p3().x());
+ ASSERT_FLOAT_EQ(150.0f, quad.p3().y());
+ ASSERT_FLOAT_EQ(100.0f, quad.p4().x());
+ ASSERT_FLOAT_EQ(150.0f, quad.p4().y());
+
+ WebCore::AffineTransform test;
+ auto mappedQuad = test.mapQuad(quad);
+
+ ASSERT_FLOAT_EQ(100.0f, mappedQuad.p1().x());
+ ASSERT_FLOAT_EQ(100.0f, mappedQuad.p1().y());
+ ASSERT_FLOAT_EQ(200.0f, mappedQuad.p2().x());
+ ASSERT_FLOAT_EQ(100.0f, mappedQuad.p2().y());
+ ASSERT_FLOAT_EQ(200.0f, mappedQuad.p3().x());
+ ASSERT_FLOAT_EQ(150.0f, mappedQuad.p3().y());
+ ASSERT_FLOAT_EQ(100.0f, mappedQuad.p4().x());
+ ASSERT_FLOAT_EQ(150.0f, mappedQuad.p4().y());
+
+ test.setD(2.0);
+
+ auto mappedQuad2 = test.mapQuad(quad);
+
+ ASSERT_FLOAT_EQ(100.0f, mappedQuad2.p1().x());
+ ASSERT_FLOAT_EQ(200.0f, mappedQuad2.p1().y());
+ ASSERT_FLOAT_EQ(200.0f, mappedQuad2.p2().x());
+ ASSERT_FLOAT_EQ(200.0f, mappedQuad2.p2().y());
+ ASSERT_FLOAT_EQ(200.0f, mappedQuad2.p3().x());
+ ASSERT_FLOAT_EQ(300.0f, mappedQuad2.p3().y());
+ ASSERT_FLOAT_EQ(100.0f, mappedQuad2.p4().x());
+ ASSERT_FLOAT_EQ(300.0f, mappedQuad2.p4().y());
+
+ test.setA(0.5);
+
+ auto mappedQuad3 = test.mapQuad(quad);
+
+ ASSERT_FLOAT_EQ(50.0f, mappedQuad3.p1().x());
+ ASSERT_FLOAT_EQ(200.0f, mappedQuad3.p1().y());
+ ASSERT_FLOAT_EQ(100.0f, mappedQuad3.p2().x());
+ ASSERT_FLOAT_EQ(200.0f, mappedQuad3.p2().y());
+ ASSERT_FLOAT_EQ(100.0f, mappedQuad3.p3().x());
+ ASSERT_FLOAT_EQ(300.0f, mappedQuad3.p3().y());
+ ASSERT_FLOAT_EQ(50.0f, mappedQuad3.p4().x());
+ ASSERT_FLOAT_EQ(300.0f, mappedQuad3.p4().y());
+}
+
+TEST(AffineTransform, Multiply)
+{
+ WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+ WebCore::AffineTransform identity;
+
+ testValueConstruction(test);
+
+ test.multiply(identity);
+
+ testValueConstruction(test);
+
+ WebCore::AffineTransform doubler(2.0, 0.0, 0.0, 2.0, 0.0, 0.0);
+
+ test.multiply(doubler);
+
+ testDoubled(test);
+
+ WebCore::AffineTransform halver(0.5, 0.0, 0.0, 0.5, 0.0, 0.0);
+
+ test.multiply(halver);
+
+ testValueConstruction(test);
+
+ test.multiply(halver);
+
+ testHalved(test);
+}
+
+TEST(AffineTransform, Scale)
+{
+ WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ testValueConstruction(test);
+
+ test.scale(1.0);
+
+ testValueConstruction(test);
+
+ test.scale(2.0);
+
+ testDoubled(test);
+
+ test.scale(0.5);
+
+ testValueConstruction(test);
+
+ test.scale(0.5);
+
+ testHalved(test);
+}
+
+TEST(AffineTransform, ScaleUniformNonUniform)
+{
+ WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ testValueConstruction(test);
+
+ test.scaleNonUniform(1.0, 1.0);
+
+ testValueConstruction(test);
+
+ test.scaleNonUniform(2.0, 2.0);
+
+ testDoubled(test);
+
+ test.scaleNonUniform(0.5, 0.5);
+
+ testValueConstruction(test);
+
+ test.scaleNonUniform(0.5, 0.5);
+
+ testHalved(test);
+}
+
+TEST(AffineTransform, ScaleNonUniform)
+{
+ WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ testValueConstruction(test);
+
+ test.scaleNonUniform(1.0, 2.0);
+
+ EXPECT_DOUBLE_EQ(6.0, test.a());
+ EXPECT_DOUBLE_EQ(5.0, test.b());
+ EXPECT_DOUBLE_EQ(8.0, test.c());
+ EXPECT_DOUBLE_EQ(6.0, test.d());
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ test.scaleNonUniform(1.0, 0.5);
+
+ testValueConstruction(test);
+
+ test.scaleNonUniform(2.0, 1.0);
+
+ EXPECT_DOUBLE_EQ(12.0, test.a());
+ EXPECT_DOUBLE_EQ(10.0, test.b());
+ EXPECT_DOUBLE_EQ(4.0, test.c());
+ EXPECT_DOUBLE_EQ(3.0, test.d());
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ test.scaleNonUniform(0.5, 1.0);
+
+ testValueConstruction(test);
+
+ test.scaleNonUniform(0.5, 2.0);
+
+ EXPECT_DOUBLE_EQ(3.0, test.a());
+ EXPECT_DOUBLE_EQ(2.5, test.b());
+ EXPECT_DOUBLE_EQ(8.0, test.c());
+ EXPECT_DOUBLE_EQ(6.0, test.d());
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+}
+
+TEST(AffineTransform, ScaleFloatSize)
+{
+ WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ testValueConstruction(test);
+
+ WebCore::FloatSize first(1.0f, 2.0f);
+
+ test.scale(first);
+
+ EXPECT_DOUBLE_EQ(6.0, test.a());
+ EXPECT_DOUBLE_EQ(5.0, test.b());
+ EXPECT_DOUBLE_EQ(8.0, test.c());
+ EXPECT_DOUBLE_EQ(6.0, test.d());
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ WebCore::FloatSize second(1.0f, 0.5f);
+
+ test.scale(second);
+
+ testValueConstruction(test);
+
+ WebCore::FloatSize third(2.0f, 1.0f);
+
+ test.scale(third);
+
+ EXPECT_DOUBLE_EQ(12.0, test.a());
+ EXPECT_DOUBLE_EQ(10.0, test.b());
+ EXPECT_DOUBLE_EQ(4.0, test.c());
+ EXPECT_DOUBLE_EQ(3.0, test.d());
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ WebCore::FloatSize fourth(0.5f, 1.0f);
+
+ test.scale(fourth);
+
+ testValueConstruction(test);
+
+ WebCore::FloatSize fifth(0.5f, 2.0f);
+
+ test.scale(fifth);
+
+ EXPECT_DOUBLE_EQ(3.0, test.a());
+ EXPECT_DOUBLE_EQ(2.5, test.b());
+ EXPECT_DOUBLE_EQ(8.0, test.c());
+ EXPECT_DOUBLE_EQ(6.0, test.d());
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+}
+
+TEST(AffineTransform, Rotate)
+{
+ WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ test.rotate(360.0);
+
+ testValueConstruction(test);
+
+ test.rotate(180.0);
+
+ static double epsilon = 0.0001;
+
+ EXPECT_NEAR(-6.0, test.a(), epsilon);
+ EXPECT_NEAR(-5.0, test.b(), epsilon);
+ EXPECT_NEAR(-4.0, test.c(), epsilon);
+ EXPECT_NEAR(-3.0, test.d(), epsilon);
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ test.rotate(-180.0);
+
+ testValueConstruction(test);
+
+ test.rotate(90.0);
+
+ EXPECT_NEAR(4.0, test.a(), epsilon);
+ EXPECT_NEAR(3.0, test.b(), epsilon);
+ EXPECT_NEAR(-6.0, test.c(), epsilon);
+ EXPECT_NEAR(-5.0, test.d(), epsilon);
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ test.rotate(-90.0);
+
+ testValueConstruction(test);
+}
+
+TEST(AffineTransform, TranslateXY)
+{
+ WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ test.translate(0.0, 0.0);
+
+ testValueConstruction(test);
+
+ test.translate(5.0, 0.0);
+
+ EXPECT_DOUBLE_EQ(6.0, test.a());
+ EXPECT_DOUBLE_EQ(5.0, test.b());
+ EXPECT_DOUBLE_EQ(4.0, test.c());
+ EXPECT_DOUBLE_EQ(3.0, test.d());
+ EXPECT_DOUBLE_EQ(32.0, test.e());
+ EXPECT_DOUBLE_EQ(26.0, test.f());
+
+ test.translate(0.0, -1.2);
+
+ EXPECT_DOUBLE_EQ(6.0, test.a());
+ EXPECT_DOUBLE_EQ(5.0, test.b());
+ EXPECT_DOUBLE_EQ(4.0, test.c());
+ EXPECT_DOUBLE_EQ(3.0, test.d());
+ EXPECT_DOUBLE_EQ(27.2, test.e());
+ EXPECT_DOUBLE_EQ(22.4, test.f());
+}
+
+TEST(AffineTransform, TranslateFloatPoint)
+{
+ WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ WebCore::FloatPoint none;
+ test.translate(none);
+
+ testValueConstruction(test);
+
+ WebCore::FloatPoint first(5.0f, 0.0f);
+
+ test.translate(first);
+
+ EXPECT_DOUBLE_EQ(6.0, test.a());
+ EXPECT_DOUBLE_EQ(5.0, test.b());
+ EXPECT_DOUBLE_EQ(4.0, test.c());
+ EXPECT_DOUBLE_EQ(3.0, test.d());
+ EXPECT_DOUBLE_EQ(32.0, test.e());
+ EXPECT_DOUBLE_EQ(26.0, test.f());
+
+ WebCore::FloatPoint second(0.0f, -1.2f);
+
+ test.translate(second);
+
+ static double epsilon = 0.0001;
+
+ EXPECT_DOUBLE_EQ(6.0, test.a());
+ EXPECT_DOUBLE_EQ(5.0, test.b());
+ EXPECT_DOUBLE_EQ(4.0, test.c());
+ EXPECT_DOUBLE_EQ(3.0, test.d());
+ EXPECT_NEAR(27.2, test.e(), epsilon);
+ EXPECT_NEAR(22.4, test.f(), epsilon);
+
+ WebCore::AffineTransform test2;
+
+ ASSERT_TRUE(test2.isIdentity());
+ ASSERT_TRUE(test2.isIdentityOrTranslation());
+ ASSERT_TRUE(test2.isIdentityOrTranslationOrFlipped());
+
+ test2.translate(second);
+
+ ASSERT_FALSE(test2.isIdentity());
+ ASSERT_TRUE(test2.isIdentityOrTranslation());
+ ASSERT_TRUE(test2.isIdentityOrTranslationOrFlipped());
+}
+
+TEST(AffineTransform, Shear)
+{
+ WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ test.shear(0.0, 0.0);
+
+ testValueConstruction(test);
+
+ test.shear(2.0, 2.0);
+
+ EXPECT_DOUBLE_EQ(14.0, test.a());
+ EXPECT_DOUBLE_EQ(11.0, test.b());
+ EXPECT_DOUBLE_EQ(16.0, test.c());
+ EXPECT_DOUBLE_EQ(13.0, test.d());
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ test.shear(-1.0, 2.0);
+
+ EXPECT_DOUBLE_EQ(46.0, test.a());
+ EXPECT_DOUBLE_EQ(37.0, test.b());
+ EXPECT_DOUBLE_EQ(2.0, test.c());
+ EXPECT_DOUBLE_EQ(2.0, test.d());
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+}
+
+TEST(AffineTransform, FlipX)
+{
+ WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ testValueConstruction(test);
+
+ test.flipX();
+
+ EXPECT_DOUBLE_EQ(-6.0, test.a());
+ EXPECT_DOUBLE_EQ(-5.0, test.b());
+ EXPECT_DOUBLE_EQ(4.0, test.c());
+ EXPECT_DOUBLE_EQ(3.0, test.d());
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ test.flipX();
+
+ testValueConstruction(test);
+
+ WebCore::AffineTransform test2;
+
+ testIdentity(test2);
+
+ ASSERT_TRUE(test2.isIdentity());
+ ASSERT_TRUE(test2.isIdentityOrTranslation());
+ ASSERT_TRUE(test2.isIdentityOrTranslationOrFlipped());
+
+ test2.flipX();
+
+ EXPECT_DOUBLE_EQ(-1.0, test2.a());
+ EXPECT_DOUBLE_EQ(0.0, test2.b());
+ EXPECT_DOUBLE_EQ(0.0, test2.c());
+ EXPECT_DOUBLE_EQ(1.0, test2.d());
+ EXPECT_DOUBLE_EQ(0.0, test2.e());
+ EXPECT_DOUBLE_EQ(0.0, test2.f());
+
+ ASSERT_FALSE(test2.isIdentity());
+ ASSERT_FALSE(test2.isIdentityOrTranslation());
+ // 'Flipped' just means in the Y direction
+ ASSERT_FALSE(test2.isIdentityOrTranslationOrFlipped());
+
+ test2.flipX();
+
+ ASSERT_TRUE(test2.isIdentity());
+ ASSERT_TRUE(test2.isIdentityOrTranslation());
+ ASSERT_TRUE(test2.isIdentityOrTranslationOrFlipped());
+}
+
+TEST(AffineTransform, FlipY)
+{
+ WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ testValueConstruction(test);
+
+ test.flipY();
+
+ EXPECT_DOUBLE_EQ(6.0, test.a());
+ EXPECT_DOUBLE_EQ(5.0, test.b());
+ EXPECT_DOUBLE_EQ(-4.0, test.c());
+ EXPECT_DOUBLE_EQ(-3.0, test.d());
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ test.flipY();
+
+ testValueConstruction(test);
+
+ WebCore::AffineTransform test2;
+
+ testIdentity(test2);
+
+ ASSERT_TRUE(test2.isIdentity());
+ ASSERT_TRUE(test2.isIdentityOrTranslation());
+ ASSERT_TRUE(test2.isIdentityOrTranslationOrFlipped());
+
+ test2.flipY();
+
+ EXPECT_DOUBLE_EQ(1.0, test2.a());
+ EXPECT_DOUBLE_EQ(0.0, test2.b());
+ EXPECT_DOUBLE_EQ(0.0, test2.c());
+ EXPECT_DOUBLE_EQ(-1.0, test2.d());
+ EXPECT_DOUBLE_EQ(0.0, test2.e());
+ EXPECT_DOUBLE_EQ(0.0, test2.f());
+
+ ASSERT_FALSE(test2.isIdentity());
+ ASSERT_FALSE(test2.isIdentityOrTranslation());
+ ASSERT_TRUE(test2.isIdentityOrTranslationOrFlipped());
+
+ test2.flipY();
+
+ ASSERT_TRUE(test2.isIdentity());
+ ASSERT_TRUE(test2.isIdentityOrTranslation());
+ ASSERT_TRUE(test2.isIdentityOrTranslationOrFlipped());
+}
+
+TEST(AffineTransform, FlipXandFlipY)
+{
+ WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ testValueConstruction(test);
+
+ test.flipX();
+
+ EXPECT_DOUBLE_EQ(-6.0, test.a());
+ EXPECT_DOUBLE_EQ(-5.0, test.b());
+ EXPECT_DOUBLE_EQ(4.0, test.c());
+ EXPECT_DOUBLE_EQ(3.0, test.d());
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ test.flipY();
+
+ EXPECT_DOUBLE_EQ(-6.0, test.a());
+ EXPECT_DOUBLE_EQ(-5.0, test.b());
+ EXPECT_DOUBLE_EQ(-4.0, test.c());
+ EXPECT_DOUBLE_EQ(-3.0, test.d());
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ test.flipX();
+
+ EXPECT_DOUBLE_EQ(6.0, test.a());
+ EXPECT_DOUBLE_EQ(5.0, test.b());
+ EXPECT_DOUBLE_EQ(-4.0, test.c());
+ EXPECT_DOUBLE_EQ(-3.0, test.d());
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ test.flipY();
+
+ testValueConstruction(test);
+
+ WebCore::AffineTransform test2;
+
+ ASSERT_TRUE(test2.isIdentity());
+ ASSERT_TRUE(test2.isIdentityOrTranslation());
+ ASSERT_TRUE(test2.isIdentityOrTranslationOrFlipped());
+
+ test2.flipX();
+
+ ASSERT_FALSE(test2.isIdentity());
+ ASSERT_FALSE(test2.isIdentityOrTranslation());
+ ASSERT_FALSE(test2.isIdentityOrTranslationOrFlipped());
+
+ test2.flipY();
+
+ ASSERT_FALSE(test2.isIdentity());
+ ASSERT_FALSE(test2.isIdentityOrTranslation());
+ // False here because X is also flipped.
+ ASSERT_FALSE(test2.isIdentityOrTranslationOrFlipped());
+
+ test2.flipX();
+
+ ASSERT_FALSE(test2.isIdentity());
+ ASSERT_FALSE(test2.isIdentityOrTranslation());
+ ASSERT_TRUE(test2.isIdentityOrTranslationOrFlipped());
+
+ test2.flipY();
+
+ ASSERT_TRUE(test2.isIdentity());
+ ASSERT_TRUE(test2.isIdentityOrTranslation());
+ ASSERT_TRUE(test2.isIdentityOrTranslationOrFlipped());
+}
+
+TEST(AffineTransform, Skew)
+{
+ WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ testValueConstruction(test);
+
+ test.skew(360.0, 360.0);
+
+ testValueConstruction(test);
+
+ test.skew(0.0, 0.0);
+
+ testValueConstruction(test);
+
+ test.skew(180.0, 180.0);
+
+ static double epsilon = 0.0001;
+
+ EXPECT_DOUBLE_EQ(6.0, test.a());
+ EXPECT_DOUBLE_EQ(5.0, test.b());
+ EXPECT_NEAR(4.0, test.c(), epsilon);
+ EXPECT_DOUBLE_EQ(3.0, test.d());
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ test.skew(-180.0, -180.0);
+
+ testValueConstruction(test);
+}
+
+TEST(AffineTransform, XandYScale)
+{
+ WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ EXPECT_NEAR(7.8102, test.xScale(), 0.0001);
+ EXPECT_NEAR(5.0, test.yScale(), 0.0001);
+}
+
+TEST(AffineTransform, Equality)
+{
+ WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+ WebCore::AffineTransform test2;
+
+ ASSERT_FALSE(test == test2);
+ ASSERT_TRUE(test != test2);
+
+ test.makeIdentity();
+
+ ASSERT_TRUE(test == test2);
+ ASSERT_FALSE(test != test2);
+}
+
+TEST(AffineTransform, Inverse)
+{
+ WebCore::AffineTransform test;
+
+ auto inverse = test.inverse();
+
+ ASSERT(inverse);
+
+ EXPECT_DOUBLE_EQ(1.0, inverse->a());
+ EXPECT_DOUBLE_EQ(0.0, inverse->b());
+ EXPECT_DOUBLE_EQ(0.0, inverse->c());
+ EXPECT_DOUBLE_EQ(1.0, inverse->d());
+ EXPECT_DOUBLE_EQ(0.0, inverse->e());
+ EXPECT_DOUBLE_EQ(0.0, inverse->f());
+
+ auto test2 = test * inverse.value();
+
+ testIdentity(test2);
+}
+
+TEST(AffineTransform, Blend)
+{
+ WebCore::AffineTransform test;
+
+ WebCore::AffineTransform test2;
+ test2.scale(2.0);
+
+ test.blend(test2, 50);
+
+ EXPECT_DOUBLE_EQ(-48.0, test.a());
+ EXPECT_DOUBLE_EQ(0.0, test.b());
+ EXPECT_DOUBLE_EQ(0.0, test.c());
+ EXPECT_DOUBLE_EQ(-48.0, test.d());
+ EXPECT_DOUBLE_EQ(0.0, test.e());
+ EXPECT_DOUBLE_EQ(0.0, test.f());
+}
+
+TEST(AffineTransform, Translation)
+{
+ auto test = WebCore::AffineTransform::translation(-5.0, -7.0);
+ EXPECT_DOUBLE_EQ(1.0, test.a());
+ EXPECT_DOUBLE_EQ(0.0, test.b());
+ EXPECT_DOUBLE_EQ(0.0, test.c());
+ EXPECT_DOUBLE_EQ(1.0, test.d());
+ EXPECT_DOUBLE_EQ(-5.0, test.e());
+ EXPECT_DOUBLE_EQ(-7.0, test.f());
+}
+
+TEST(AffineTransform, ToTransformationMatrix)
+{
+ WebCore::AffineTransform transform;
+ WebCore::TransformationMatrix matrix = transform.toTransformationMatrix();
+
+ EXPECT_DOUBLE_EQ(1.0, matrix.m11());
+ EXPECT_DOUBLE_EQ(0.0, matrix.m12());
+ EXPECT_DOUBLE_EQ(0.0, matrix.m13());
+ EXPECT_DOUBLE_EQ(0.0, matrix.m14());
+ EXPECT_DOUBLE_EQ(0.0, matrix.m21());
+ EXPECT_DOUBLE_EQ(1.0, matrix.m22());
+ EXPECT_DOUBLE_EQ(0.0, matrix.m23());
+ EXPECT_DOUBLE_EQ(0.0, matrix.m24());
+ EXPECT_DOUBLE_EQ(0.0, matrix.m31());
+ EXPECT_DOUBLE_EQ(0.0, matrix.m32());
+ EXPECT_DOUBLE_EQ(1.0, matrix.m33());
+ EXPECT_DOUBLE_EQ(0.0, matrix.m34());
+}
+
+TEST(AffineTransform, MakeMapBetweenRects)
+{
+ WebCore::AffineTransform transform;
+
+ WebCore::FloatRect fromRect(10.0f, 10.0f, 100.0f, 100.0f);
+ WebCore::FloatRect toRect(70.0f, 70.0f, 200.0f, 50.0f);
+
+ auto mapBetween = WebCore::makeMapBetweenRects(fromRect, toRect);
+
+ EXPECT_DOUBLE_EQ(2.0, mapBetween.a());
+ EXPECT_DOUBLE_EQ(0.0, mapBetween.b());
+ EXPECT_DOUBLE_EQ(0.0, mapBetween.c());
+ EXPECT_DOUBLE_EQ(0.5, mapBetween.d());
+ EXPECT_DOUBLE_EQ(60.0, mapBetween.e());
+ EXPECT_DOUBLE_EQ(60.0, mapBetween.f());
+}
+
+#if USE(CG)
+TEST(AffineTransform, CoreGraphicsCasting)
+{
+ WebCore::AffineTransform test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ CGAffineTransform test2 = CGAffineTransformMake(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ ASSERT_TRUE(CGAffineTransformEqualToTransform(test, test2));
+
+ WebCore::AffineTransform test3;
+
+ ASSERT_FALSE(CGAffineTransformEqualToTransform(test, test3));
+}
+#endif
+
+#if PLATFORM(WIN)
+TEST(AffineTransform, Direct2DCasting)
+{
+ WebCore::AffineTransform transform(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ D2D1_MATRIX_3X2_F test = transform;
+ D2D1_MATRIX_3X2_F test2 = D2D1::Matrix3x2F(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ static const double epsilon = 0.0000001;
+
+ EXPECT_NEAR(test._11, test2._11, epsilon);
+ EXPECT_NEAR(test._12, test2._12, epsilon);
+ EXPECT_NEAR(test._21, test2._21, epsilon);
+ EXPECT_NEAR(test._22, test2._22, epsilon);
+ EXPECT_NEAR(test._31, test2._31, epsilon);
+ EXPECT_NEAR(test._32, test2._32, epsilon);
+}
+#endif
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/CARingBuffer.cpp b/Tools/TestWebKitAPI/Tests/WebCore/CARingBuffer.cpp
new file mode 100644
index 000000000..2aab65dd8
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/CARingBuffer.cpp
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2017 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if PLATFORM(MAC)
+
+#include "Test.h"
+#include <WebCore/CARingBuffer.h>
+#include <wtf/MainThread.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+class CARingBufferTest : public testing::Test {
+public:
+
+ virtual void SetUp()
+ {
+ WTF::initializeMainThread();
+ m_ringBuffer = std::make_unique<CARingBuffer>();
+ }
+
+ // CAAudioStreamDescription(double sampleRate, UInt32 numChannels, PCMFormat format, bool isInterleaved, size_t capacity)
+ void setup(double sampleRate, UInt32 numChannels, CAAudioStreamDescription::PCMFormat format, bool isInterleaved, size_t capacity)
+ {
+ m_description = CAAudioStreamDescription(sampleRate, numChannels, format, isInterleaved);
+ m_capacity = capacity;
+ size_t listSize = offsetof(AudioBufferList, mBuffers) + (sizeof(AudioBuffer) * std::max<uint32_t>(1, m_description.numberOfChannelStreams()));
+ m_bufferList = std::unique_ptr<AudioBufferList>(static_cast<AudioBufferList*>(::operator new (listSize)));
+ m_ringBuffer->allocate(m_description, capacity);
+ }
+
+ void setListDataBuffer(uint8_t* bufferData, size_t sampleCount)
+ {
+ size_t bufferCount = m_description.numberOfChannelStreams();
+ size_t channelCount = m_description.numberOfInterleavedChannels();
+ size_t bytesPerChannel = sampleCount * m_description.bytesPerFrame();
+
+ m_bufferList->mNumberBuffers = bufferCount;
+ for (unsigned i = 0; i < bufferCount; ++i) {
+ m_bufferList->mBuffers[i].mNumberChannels = channelCount;
+ m_bufferList->mBuffers[i].mDataByteSize = bytesPerChannel;
+ m_bufferList->mBuffers[i].mData = bufferData;
+ if (bufferData)
+ bufferData = bufferData + bytesPerChannel;
+ }
+ }
+
+ const CAAudioStreamDescription& description() const { return m_description; }
+ AudioBufferList& bufferList() const { return *m_bufferList.get(); }
+ CARingBuffer& ringBuffer() const { return *m_ringBuffer.get(); }
+ size_t capacity() const { return m_capacity; }
+
+private:
+ size_t audioBufferListSizeForStream(const CAAudioStreamDescription& format)
+ {
+ return offsetof(AudioBufferList, mBuffers) + (sizeof(AudioBuffer) * std::max<uint32_t>(1, format.numberOfChannelStreams()));
+ }
+
+ void configureBufferListForStream(AudioBufferList& bufferList, const CAAudioStreamDescription& format, uint8_t* bufferData, size_t sampleCount)
+ {
+ size_t bufferCount = format.numberOfChannelStreams();
+ size_t channelCount = format.numberOfInterleavedChannels();
+ size_t bytesPerChannel = sampleCount * format.bytesPerFrame();
+
+ bufferList.mNumberBuffers = bufferCount;
+ for (unsigned i = 0; i < bufferCount; ++i) {
+ bufferList.mBuffers[i].mNumberChannels = channelCount;
+ bufferList.mBuffers[i].mDataByteSize = bytesPerChannel;
+ bufferList.mBuffers[i].mData = bufferData;
+ if (bufferData)
+ bufferData = bufferData + bytesPerChannel;
+ }
+ }
+
+ std::unique_ptr<AudioBufferList> m_bufferList;
+ std::unique_ptr<CARingBuffer> m_ringBuffer;
+ CAAudioStreamDescription m_description = { };
+ size_t m_capacity = { 0 };
+};
+
+TEST_F(CARingBufferTest, Basics)
+{
+ const int capacity = 32;
+
+ setup(44100, 1, CAAudioStreamDescription::PCMFormat::Float32, true, capacity);
+
+ float sourceBuffer[capacity];
+ for (int i = 0; i < capacity; i++)
+ sourceBuffer[i] = i + 0.5;
+
+ setListDataBuffer(reinterpret_cast<uint8_t*>(sourceBuffer), capacity);
+
+ // Fill the first half of the buffer ...
+ int sampleCount = capacity / 2;
+ CARingBuffer::Error err = ringBuffer().store(&bufferList(), sampleCount, 0);
+ EXPECT_EQ(err, CARingBuffer::Error::Ok);
+
+ uint64_t startTime;
+ uint64_t endTime;
+ ringBuffer().getCurrentFrameBounds(startTime, endTime);
+ EXPECT_EQ(0, (int)startTime);
+ EXPECT_EQ((int)sampleCount, (int)endTime);
+
+ float scratchBuffer[capacity];
+ setListDataBuffer(reinterpret_cast<uint8_t*>(scratchBuffer), capacity);
+
+ err = ringBuffer().fetch(&bufferList(), sampleCount, 0);
+ EXPECT_EQ(err, CARingBuffer::Error::Ok);
+ EXPECT_TRUE(!memcmp(sourceBuffer, scratchBuffer, sampleCount * description().sampleWordSize()));
+
+ // ... and the second half.
+ err = ringBuffer().store(&bufferList(), capacity / 2, capacity / 2);
+ EXPECT_EQ(err, CARingBuffer::Error::Ok);
+
+ ringBuffer().getCurrentFrameBounds(startTime, endTime);
+ EXPECT_EQ(0, (int)startTime);
+ EXPECT_EQ(capacity, (int)endTime);
+
+ memset(scratchBuffer, 0, sampleCount * description().sampleWordSize());
+ err = ringBuffer().fetch(&bufferList(), sampleCount, 0);
+ EXPECT_EQ(err, CARingBuffer::Error::Ok);
+ EXPECT_TRUE(!memcmp(sourceBuffer, scratchBuffer, sampleCount * description().sampleWordSize()));
+
+ // Force the buffer to wrap around
+ err = ringBuffer().store(&bufferList(), capacity, capacity - 1);
+ EXPECT_EQ(err, CARingBuffer::Error::Ok);
+
+ ringBuffer().getCurrentFrameBounds(startTime, endTime);
+ EXPECT_EQ((int)capacity - 1, (int)startTime);
+ EXPECT_EQ(capacity - 1 + capacity, (int)endTime);
+
+ // Make sure it returns an error when asked to store too much ...
+ err = ringBuffer().store(&bufferList(), capacity * 3, capacity / 2);
+ EXPECT_EQ(err, CARingBuffer::Error::TooMuch);
+
+ // ... and doesn't modify the buffer
+ ringBuffer().getCurrentFrameBounds(startTime, endTime);
+ EXPECT_EQ((int)capacity - 1, (int)startTime);
+ EXPECT_EQ(capacity - 1 + capacity, (int)endTime);
+
+ ringBuffer().flush();
+ ringBuffer().getCurrentFrameBounds(startTime, endTime);
+ EXPECT_EQ(0, (int)startTime);
+ EXPECT_EQ(0, (int)endTime);
+}
+
+template <typename type>
+class MixingTest {
+public:
+ static void run(CARingBufferTest& test)
+ {
+ const int sampleCount = 64;
+
+ CAAudioStreamDescription::PCMFormat format;
+ if (std::is_same<type, float>::value)
+ format = CAAudioStreamDescription::PCMFormat::Float32;
+ else if (std::is_same<type, double>::value)
+ format = CAAudioStreamDescription::PCMFormat::Float64;
+ else if (std::is_same<type, int32_t>::value)
+ format = CAAudioStreamDescription::PCMFormat::Int32;
+ else if (std::is_same<type, int16_t>::value)
+ format = CAAudioStreamDescription::PCMFormat::Int16;
+ else
+ ASSERT_NOT_REACHED();
+
+ test.setup(44100, 1, format, true, sampleCount);
+
+ type referenceBuffer[sampleCount];
+ type sourceBuffer[sampleCount];
+ type readBuffer[sampleCount];
+
+ for (int i = 0; i < sampleCount; i++) {
+ sourceBuffer[i] = i * 0.5;
+ referenceBuffer[i] = sourceBuffer[i];
+ }
+
+ test.setListDataBuffer(reinterpret_cast<uint8_t*>(sourceBuffer), sampleCount);
+ CARingBuffer::Error err = test.ringBuffer().store(&test.bufferList(), sampleCount, 0);
+ EXPECT_EQ(err, CARingBuffer::Error::Ok);
+
+ memset(readBuffer, 0, sampleCount * test.description().sampleWordSize());
+ test.setListDataBuffer(reinterpret_cast<uint8_t*>(readBuffer), sampleCount);
+ err = test.ringBuffer().fetch(&test.bufferList(), sampleCount, 0, CARingBuffer::FetchMode::Mix);
+ EXPECT_EQ(err, CARingBuffer::Error::Ok);
+
+ for (int i = 0; i < sampleCount; i++)
+ EXPECT_EQ(readBuffer[i], referenceBuffer[i]) << "Ring buffer value differs at index " << i;
+
+ err = test.ringBuffer().fetch(&test.bufferList(), sampleCount, 0, CARingBuffer::FetchMode::Mix);
+ EXPECT_EQ(err, CARingBuffer::Error::Ok);
+ err = test.ringBuffer().fetch(&test.bufferList(), sampleCount, 0, CARingBuffer::FetchMode::Mix);
+ EXPECT_EQ(err, CARingBuffer::Error::Ok);
+ err = test.ringBuffer().fetch(&test.bufferList(), sampleCount, 0, CARingBuffer::FetchMode::Mix);
+ EXPECT_EQ(err, CARingBuffer::Error::Ok);
+
+ for (int i = 0; i < sampleCount; i++)
+ referenceBuffer[i] += sourceBuffer[i] * 3;
+
+ for (int i = 0; i < sampleCount; i++)
+ EXPECT_EQ(readBuffer[i], referenceBuffer[i]) << "Ring buffer value differs at index " << i;
+ }
+};
+
+TEST_F(CARingBufferTest, FloatMixing)
+{
+ MixingTest<float>::run(*this);
+}
+
+TEST_F(CARingBufferTest, DoubleMixing)
+{
+ MixingTest<double>::run(*this);
+}
+
+TEST_F(CARingBufferTest, Int32Mixing)
+{
+ MixingTest<int32_t>::run(*this);
+}
+
+TEST_F(CARingBufferTest, Int16Mixing)
+{
+ MixingTest<int16_t>::run(*this);
+}
+
+}
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/CSSParser.cpp b/Tools/TestWebKitAPI/Tests/WebCore/CSSParser.cpp
new file mode 100644
index 000000000..edc7dcd91
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/CSSParser.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2014 Igalia, S.L. 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <WebCore/CSSParser.h>
+#include <WebCore/CSSValueList.h>
+#include <WebCore/StyleProperties.h>
+
+namespace TestWebKitAPI {
+
+using namespace WebCore;
+
+static unsigned computeNumberOfTracks(CSSValueList& valueList)
+{
+ unsigned numberOfTracks = 0;
+ for (const auto& value : valueList) {
+ if (value->isGridLineNamesValue())
+ continue;
+ ++numberOfTracks;
+ }
+ return numberOfTracks;
+}
+
+TEST(CSSPropertyParserTest, GridTrackLimits)
+{
+ struct {
+ const CSSPropertyID propertyID;
+ const char* input;
+ const size_t output;
+ } testCases[] = {
+ {CSSPropertyGridTemplateColumns, "grid-template-columns: repeat(999999, 20px);", 999999},
+ {CSSPropertyGridTemplateRows, "grid-template-rows: repeat(999999, 20px);", 999999},
+ {CSSPropertyGridTemplateColumns, "grid-template-columns: repeat(1000000, 10%);", 1000000},
+ {CSSPropertyGridTemplateRows, "grid-template-rows: repeat(1000000, 10%);", 1000000},
+ {CSSPropertyGridTemplateColumns, "grid-template-columns: repeat(1000000, [first] -webkit-min-content [last]);", 1000000},
+ {CSSPropertyGridTemplateRows, "grid-template-rows: repeat(1000000, [first] -webkit-min-content [last]);", 1000000},
+ {CSSPropertyGridTemplateColumns, "grid-template-columns: repeat(1000001, auto);", 1000000},
+ {CSSPropertyGridTemplateRows, "grid-template-rows: repeat(1000001, auto);", 1000000},
+ {CSSPropertyGridTemplateColumns, "grid-template-columns: repeat(400000, 2em minmax(10px, -webkit-max-content) 0.5fr);", 999999},
+ {CSSPropertyGridTemplateRows, "grid-template-rows: repeat(400000, 2em minmax(10px, -webkit-max-content) 0.5fr);", 999999},
+ {CSSPropertyGridTemplateColumns, "grid-template-columns: repeat(600000, [first] 3vh 10% 2fr [nav] 10px auto 1fr 6em [last]);", 999999},
+ {CSSPropertyGridTemplateRows, "grid-template-rows: repeat(600000, [first] 3vh 10% 2fr [nav] 10px auto 1fr 6em [last]);", 999999},
+ {CSSPropertyGridTemplateColumns, "grid-template-columns: repeat(100000000000000000000, 10% 1fr);", 1000000},
+ {CSSPropertyGridTemplateRows, "grid-template-rows: repeat(100000000000000000000, 10% 1fr);", 1000000},
+ {CSSPropertyGridTemplateColumns, "grid-template-columns: repeat(100000000000000000000, 10% 5em 1fr auto auto 15px -webkit-min-content);", 999999},
+ {CSSPropertyGridTemplateRows, "grid-template-rows: repeat(100000000000000000000, 10% 5em 1fr auto auto 15px -webkit-min-content);", 999999},
+ };
+
+ CSSParser parser(strictCSSParserContext());
+ auto properties = MutableStyleProperties::create();
+
+ for (auto& testCase : testCases) {
+ ASSERT_TRUE(parser.parseDeclaration(properties, testCase.input));
+ RefPtr<CSSValue> value = properties->getPropertyCSSValue(testCase.propertyID);
+
+ ASSERT_TRUE(value->isValueList());
+ EXPECT_EQ(computeNumberOfTracks(*downcast<CSSValueList>(value.get())), testCase.output);
+ }
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/CalculationValue.cpp b/Tools/TestWebKitAPI/Tests/WebCore/CalculationValue.cpp
new file mode 100644
index 000000000..07fbdce00
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/CalculationValue.cpp
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2014 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <WebCore/CalculationValue.h>
+
+namespace TestWebKitAPI {
+
+static unsigned deletionCount;
+
+class CalculationDeletionTestNode : public WebCore::CalcExpressionNode {
+public:
+ virtual ~CalculationDeletionTestNode()
+ {
+ ++deletionCount;
+ }
+
+ float evaluate(float) const override { return 0; }
+ bool operator==(const CalcExpressionNode&) const override { ASSERT_NOT_REACHED(); return false; }
+};
+
+static Ref<WebCore::CalculationValue> createTestValue()
+{
+ auto node = std::make_unique<CalculationDeletionTestNode>();
+ return WebCore::CalculationValue::create(WTFMove(node), WebCore::ValueRangeAll);
+}
+
+TEST(CalculationValue, LengthConstruction)
+{
+ RefPtr<WebCore::CalculationValue> value = createTestValue();
+
+ EXPECT_EQ(1U, value->refCount());
+
+ {
+ WebCore::Length length(*value);
+ EXPECT_EQ(2U, value->refCount());
+ }
+
+ EXPECT_EQ(1U, value->refCount());
+
+ {
+ WebCore::Length lengthA(*value);
+ EXPECT_EQ(2U, value->refCount());
+ WebCore::Length lengthB(lengthA);
+ EXPECT_EQ(2U, value->refCount());
+ }
+
+ EXPECT_EQ(1U, value->refCount());
+
+ {
+ WebCore::Length lengthC(*value);
+ EXPECT_EQ(2U, value->refCount());
+ WebCore::Length lengthD(WTFMove(lengthC));
+ EXPECT_EQ(2U, value->refCount());
+ }
+
+ EXPECT_EQ(1U, value->refCount());
+
+ EXPECT_EQ(0U, deletionCount);
+ value = nullptr;
+ EXPECT_EQ(1U, deletionCount);
+ deletionCount = 0;
+}
+
+TEST(CalculationValue, LengthConstructionReleasedValue)
+{
+ RefPtr<WebCore::CalculationValue> value = createTestValue();
+
+ EXPECT_EQ(1U, value->refCount());
+
+ {
+ auto* rawValue = value.get();
+ WebCore::Length length(value.releaseNonNull());
+ EXPECT_EQ(1U, rawValue->refCount());
+
+ EXPECT_EQ(0U, deletionCount);
+ }
+
+ EXPECT_EQ(1U, deletionCount);
+ deletionCount = 0;
+
+ value = createTestValue();
+
+ {
+ auto* rawValue = value.get();
+ WebCore::Length lengthA(value.releaseNonNull());
+ EXPECT_EQ(1U, rawValue->refCount());
+ WebCore::Length lengthB(lengthA);
+ EXPECT_EQ(1U, rawValue->refCount());
+
+ EXPECT_EQ(0U, deletionCount);
+ }
+
+ EXPECT_EQ(1U, deletionCount);
+ deletionCount = 0;
+
+ value = createTestValue();
+
+ {
+ auto* rawValue = value.get();
+ WebCore::Length lengthC(value.releaseNonNull());
+ EXPECT_EQ(1U, rawValue->refCount());
+ WebCore::Length lengthD(WTFMove(lengthC));
+ EXPECT_EQ(1U, rawValue->refCount());
+
+ EXPECT_EQ(0U, deletionCount);
+ }
+
+ EXPECT_EQ(1U, deletionCount);
+ deletionCount = 0;
+}
+
+TEST(CalculationValue, LengthAssignment)
+{
+ RefPtr<WebCore::CalculationValue> value = createTestValue();
+
+ EXPECT_EQ(1U, value->refCount());
+
+ {
+ WebCore::Length lengthA(*value);
+ EXPECT_EQ(2U, value->refCount());
+ WebCore::Length lengthB;
+ lengthB = lengthA;
+ EXPECT_EQ(2U, value->refCount());
+ }
+
+ EXPECT_EQ(1U, value->refCount());
+
+ {
+ WebCore::Length lengthC(*value);
+ EXPECT_EQ(2U, value->refCount());
+ WebCore::Length lengthD;
+ lengthD = WTFMove(lengthC);
+ EXPECT_EQ(2U, value->refCount());
+ }
+
+ EXPECT_EQ(1U, value->refCount());
+
+ EXPECT_EQ(0U, deletionCount);
+ value = nullptr;
+ EXPECT_EQ(1U, deletionCount);
+ deletionCount = 0;
+
+ value = createTestValue();
+ RefPtr<WebCore::CalculationValue> value2 = createTestValue();
+
+ EXPECT_EQ(1U, value->refCount());
+ EXPECT_EQ(1U, value2->refCount());
+
+ {
+ WebCore::Length lengthE(*value);
+ EXPECT_EQ(2U, value->refCount());
+ WebCore::Length lengthF(*value2);
+ EXPECT_EQ(2U, value2->refCount());
+ lengthE = lengthF;
+ EXPECT_EQ(1U, value->refCount());
+ EXPECT_EQ(2U, value2->refCount());
+ }
+
+ EXPECT_EQ(1U, value->refCount());
+ EXPECT_EQ(1U, value2->refCount());
+
+ {
+ WebCore::Length lengthG(*value);
+ EXPECT_EQ(2U, value->refCount());
+ WebCore::Length lengthH(*value2);
+ EXPECT_EQ(2U, value2->refCount());
+ lengthG = WTFMove(lengthH);
+ EXPECT_EQ(1U, value->refCount());
+ EXPECT_EQ(2U, value2->refCount());
+ }
+
+ EXPECT_EQ(0U, deletionCount);
+ value = nullptr;
+ EXPECT_EQ(1U, deletionCount);
+ value2 = nullptr;
+ EXPECT_EQ(2U, deletionCount);
+ deletionCount = 0;
+}
+
+TEST(CalculationValue, LengthAssignmentReleasedValue)
+{
+ RefPtr<WebCore::CalculationValue> value = createTestValue();
+
+ {
+ auto* rawValue = value.get();
+ WebCore::Length lengthA(value.releaseNonNull());
+ EXPECT_EQ(1U, rawValue->refCount());
+ WebCore::Length lengthB;
+ lengthB = lengthA;
+ EXPECT_EQ(1U, rawValue->refCount());
+
+ EXPECT_EQ(0U, deletionCount);
+ }
+
+ EXPECT_EQ(1U, deletionCount);
+ deletionCount = 0;
+
+ value = createTestValue();
+
+ {
+ auto* rawValue = value.get();
+ WebCore::Length lengthC(value.releaseNonNull());
+ EXPECT_EQ(1U, rawValue->refCount());
+ WebCore::Length lengthD;
+ lengthD = WTFMove(lengthC);
+ EXPECT_EQ(1U, rawValue->refCount());
+
+ EXPECT_EQ(0U, deletionCount);
+ }
+
+ EXPECT_EQ(1U, deletionCount);
+ deletionCount = 0;
+
+ value = createTestValue();
+ RefPtr<WebCore::CalculationValue> value2 = createTestValue();
+
+ EXPECT_EQ(1U, value->refCount());
+ EXPECT_EQ(1U, value2->refCount());
+
+ {
+ auto* rawValue = value.get();
+ WebCore::Length lengthE(value.releaseNonNull());
+ EXPECT_EQ(1U, rawValue->refCount());
+ auto* rawValue2 = value2.get();
+ WebCore::Length lengthF(value2.releaseNonNull());
+ EXPECT_EQ(1U, rawValue2->refCount());
+
+ lengthE = lengthF;
+ EXPECT_EQ(1U, deletionCount);
+ EXPECT_EQ(1U, rawValue2->refCount());
+ }
+
+ EXPECT_EQ(2U, deletionCount);
+ deletionCount = 0;
+
+ value = createTestValue();
+ value2 = createTestValue();
+
+ EXPECT_EQ(1U, value->refCount());
+ EXPECT_EQ(1U, value2->refCount());
+
+ {
+ auto* rawValue = value.get();
+ WebCore::Length lengthG(value.releaseNonNull());
+ EXPECT_EQ(1U, rawValue->refCount());
+ auto* rawValue2 = value2.get();
+ WebCore::Length lengthH(value2.releaseNonNull());
+ EXPECT_EQ(1U, rawValue2->refCount());
+
+ lengthG = WTFMove(lengthH);
+ EXPECT_EQ(1U, deletionCount);
+ EXPECT_EQ(1U, rawValue2->refCount());
+ }
+
+ EXPECT_EQ(2U, deletionCount);
+ deletionCount = 0;
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/Color.cpp b/Tools/TestWebKitAPI/Tests/WebCore/Color.cpp
new file mode 100644
index 000000000..61af1c660
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/Color.cpp
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2011, 2012 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include "Test.h"
+#include <WebCore/Color.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+TEST(Color, RGBToHSV_White)
+{
+ Color color = Color::white;
+
+ double h = 0;
+ double s = 0;
+ double v = 0;
+ color.getHSV(h, s, v);
+
+ EXPECT_DOUBLE_EQ(0, h);
+ EXPECT_DOUBLE_EQ(0, s);
+ EXPECT_DOUBLE_EQ(1, v);
+}
+
+TEST(Color, RGBToHSV_Black)
+{
+ Color color = Color::black;
+
+ double h = 0;
+ double s = 0;
+ double v = 0;
+ color.getHSV(h, s, v);
+
+ EXPECT_DOUBLE_EQ(0, h);
+ EXPECT_DOUBLE_EQ(0, s);
+ EXPECT_DOUBLE_EQ(0, v);
+}
+
+TEST(Color, RGBToHSV_Red)
+{
+ Color color(255, 0, 0);
+
+ double h = 0;
+ double s = 0;
+ double v = 0;
+ color.getHSV(h, s, v);
+
+ EXPECT_DOUBLE_EQ(0, h);
+ EXPECT_DOUBLE_EQ(1, s);
+ EXPECT_DOUBLE_EQ(1, v);
+}
+
+TEST(Color, RGBToHSV_Green)
+{
+ Color color(0, 255, 0);
+
+ double h = 0;
+ double s = 0;
+ double v = 0;
+ color.getHSV(h, s, v);
+
+ EXPECT_DOUBLE_EQ(0.33333333333333331, h);
+ EXPECT_DOUBLE_EQ(1, s);
+ EXPECT_DOUBLE_EQ(1, v);
+}
+
+TEST(Color, RGBToHSV_Blue)
+{
+ Color color(0, 0, 255);
+
+ double h = 0;
+ double s = 0;
+ double v = 0;
+ color.getHSV(h, s, v);
+
+ EXPECT_DOUBLE_EQ(0.66666666666666663, h);
+ EXPECT_DOUBLE_EQ(1, s);
+ EXPECT_DOUBLE_EQ(1, v);
+}
+
+TEST(Color, RGBToHSV_DarkGray)
+{
+ Color color = Color::darkGray;
+
+ double h = 0;
+ double s = 0;
+ double v = 0;
+ color.getHSV(h, s, v);
+
+ EXPECT_DOUBLE_EQ(0, h);
+ EXPECT_DOUBLE_EQ(0, s);
+ EXPECT_DOUBLE_EQ(0.50196078431372548, v);
+}
+
+TEST(Color, RGBToHSV_Gray)
+{
+ Color color = Color::gray;
+
+ double h = 0;
+ double s = 0;
+ double v = 0;
+ color.getHSV(h, s, v);
+
+ EXPECT_DOUBLE_EQ(0, h);
+ EXPECT_DOUBLE_EQ(0, s);
+ EXPECT_DOUBLE_EQ(0.62745098039215685, v);
+}
+
+TEST(Color, RGBToHSV_LightGray)
+{
+ Color color = Color::lightGray;
+
+ double h = 0;
+ double s = 0;
+ double v = 0;
+ color.getHSV(h, s, v);
+
+ EXPECT_DOUBLE_EQ(0, h);
+ EXPECT_DOUBLE_EQ(0, s);
+ EXPECT_DOUBLE_EQ(0.75294117647058822, v);
+}
+
+TEST(Color, Validity)
+{
+ Color invalidColor;
+ EXPECT_FALSE(invalidColor.isValid());
+ EXPECT_FALSE(invalidColor.isExtended());
+
+ Color otherInvalidColor = invalidColor;
+ EXPECT_FALSE(otherInvalidColor.isValid());
+ EXPECT_FALSE(otherInvalidColor.isExtended());
+
+ Color validColor(255, 0, 0);
+ EXPECT_TRUE(validColor.isValid());
+ EXPECT_FALSE(validColor.isExtended());
+
+ Color otherValidColor = validColor;
+ EXPECT_TRUE(otherValidColor.isValid());
+ EXPECT_FALSE(otherValidColor.isExtended());
+
+ validColor = Color(1, 2, 3, 4);
+ EXPECT_TRUE(validColor.isValid());
+ EXPECT_FALSE(validColor.isExtended());
+ EXPECT_EQ(validColor.red(), 1);
+ EXPECT_EQ(validColor.green(), 2);
+ EXPECT_EQ(validColor.blue(), 3);
+ EXPECT_EQ(validColor.alpha(), 4);
+
+ Color yetAnotherValidColor(WTFMove(validColor));
+ EXPECT_TRUE(yetAnotherValidColor.isValid());
+ EXPECT_FALSE(yetAnotherValidColor.isExtended());
+ EXPECT_EQ(yetAnotherValidColor.red(), 1);
+ EXPECT_EQ(yetAnotherValidColor.green(), 2);
+ EXPECT_EQ(yetAnotherValidColor.blue(), 3);
+ EXPECT_EQ(yetAnotherValidColor.alpha(), 4);
+
+ otherValidColor = WTFMove(yetAnotherValidColor);
+ EXPECT_TRUE(otherValidColor.isValid());
+ EXPECT_FALSE(otherValidColor.isExtended());
+ EXPECT_EQ(otherValidColor.red(), 1);
+ EXPECT_EQ(otherValidColor.green(), 2);
+ EXPECT_EQ(otherValidColor.blue(), 3);
+ EXPECT_EQ(otherValidColor.alpha(), 4);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/ComplexTextController.cpp b/Tools/TestWebKitAPI/Tests/WebCore/ComplexTextController.cpp
new file mode 100644
index 000000000..680dac0be
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/ComplexTextController.cpp
@@ -0,0 +1,391 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <JavaScriptCore/InitializeThreading.h>
+#include <WebCore/ComplexTextController.h>
+#include <WebCore/FontCascade.h>
+#include <wtf/MainThread.h>
+#include <wtf/RunLoop.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+class ComplexTextControllerTest : public testing::Test {
+public:
+ virtual void SetUp()
+ {
+ JSC::initializeThreading();
+ RunLoop::initializeMainRunLoop();
+ }
+};
+
+TEST_F(ComplexTextControllerTest, InitialAdvanceWithLeftRunInRTL)
+{
+ FontCascadeDescription description;
+ description.setOneFamily("Times");
+ description.setComputedSize(80);
+ FontCascade font(description);
+ font.update();
+ auto spaceWidth = font.primaryFont().spaceWidth();
+
+#if USE_LAYOUT_SPECIFIC_ADVANCES
+ Vector<FloatSize> advances = { FloatSize(), FloatSize(21.640625, 0.0), FloatSize(42.3046875, 0.0), FloatSize(55.8984375, 0.0), FloatSize(22.34375, 0.0) };
+ Vector<FloatPoint> origins = { FloatPoint(-15.15625, 18.046875), FloatPoint(), FloatPoint(), FloatPoint(), FloatPoint() };
+#else
+ Vector<FloatSize> advances = { FloatSize(15.15625, -18.046875), FloatSize(21.640625, 0.0), FloatSize(42.3046875, 0.0), FloatSize(55.8984375, 0.0), FloatSize(22.34375, 0.0) };
+ Vector<FloatPoint> origins = { };
+#endif
+
+ FloatSize initialAdvance = FloatSize(-15.15625, 18.046875);
+
+ UChar characters[] = { 0x644, 0x637, 0x641, 0x627, 0x64b, 0x20 };
+ size_t charactersLength = WTF_ARRAY_LENGTH(characters);
+ TextRun textRun(StringView(characters, charactersLength));
+ auto run1 = ComplexTextController::ComplexTextRun::create({ FloatSize(21.875, 0) }, { FloatPoint() }, { 5 }, { 5 }, FloatSize(), font.primaryFont(), characters, 0, charactersLength, 5, 6, false);
+ auto run2 = ComplexTextController::ComplexTextRun::create(advances, origins, { 193, 377, 447, 431, 458 }, { 4, 3, 2, 1, 0 }, initialAdvance, font.primaryFont(), characters, 0, charactersLength, 0, 5, false);
+ Vector<Ref<ComplexTextController::ComplexTextRun>> runs;
+ runs.append(WTFMove(run1));
+ runs.append(WTFMove(run2));
+ ComplexTextController controller(font, textRun, runs);
+
+ float totalWidth = 0;
+ for (size_t i = 1; i < advances.size(); ++i)
+ totalWidth += advances[i].width();
+ EXPECT_NEAR(controller.totalWidth(), spaceWidth + totalWidth, 0.0001);
+ GlyphBuffer glyphBuffer;
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(0, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(1, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), advances[4].width(), 0.0001);
+ controller.advance(6, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), spaceWidth + totalWidth, 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().width(), 0, 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().height(), 0, 0.0001);
+ EXPECT_EQ(glyphBuffer.size(), 6U);
+ EXPECT_NEAR(glyphBuffer.advanceAt(0).width(), advances[4].width(), 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(1).width(), advances[3].width(), 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(2).width(), advances[2].width(), 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(3).width(), advances[1].width(), 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(4).width(), -initialAdvance.width(), 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(5).width(), spaceWidth + initialAdvance.width(), 0.0001);
+}
+
+TEST_F(ComplexTextControllerTest, InitialAdvanceInRTL)
+{
+ FontCascadeDescription description;
+ description.setOneFamily("Times");
+ description.setComputedSize(80);
+ FontCascade font(description);
+ font.update();
+
+#if USE_LAYOUT_SPECIFIC_ADVANCES
+ Vector<FloatSize> advances = { FloatSize(), FloatSize(21.640625, 0.0), FloatSize(42.3046875, 0.0), FloatSize(55.8984375, 0.0), FloatSize(22.34375, 0.0) };
+ Vector<FloatPoint> origins = { FloatPoint(-15.15625, 18.046875), FloatPoint(), FloatPoint(), FloatPoint(), FloatPoint() };
+#else
+ Vector<FloatSize> advances = { FloatSize(15.15625, -18.046875), FloatSize(21.640625, 0.0), FloatSize(42.3046875, 0.0), FloatSize(55.8984375, 0.0), FloatSize(22.34375, 0.0) };
+ Vector<FloatPoint> origins = { };
+#endif
+
+ FloatSize initialAdvance = FloatSize(-15.15625, 18.046875);
+
+ UChar characters[] = { 0x644, 0x637, 0x641, 0x627, 0x64b };
+ size_t charactersLength = WTF_ARRAY_LENGTH(characters);
+ TextRun textRun(StringView(characters, charactersLength));
+ auto run = ComplexTextController::ComplexTextRun::create(advances, origins, { 193, 377, 447, 431, 458 }, { 4, 3, 2, 1, 0 }, initialAdvance, font.primaryFont(), characters, 0, charactersLength, 0, 5, false);
+ Vector<Ref<ComplexTextController::ComplexTextRun>> runs;
+ runs.append(WTFMove(run));
+ ComplexTextController controller(font, textRun, runs);
+
+ float totalWidth = 0;
+ for (size_t i = 1; i < advances.size(); ++i)
+ totalWidth += advances[i].width();
+ EXPECT_NEAR(controller.totalWidth(), totalWidth, 0.0001);
+ GlyphBuffer glyphBuffer;
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(0, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(1, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), advances[4].width(), 0.0001);
+ controller.advance(5, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), totalWidth, 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().width(), initialAdvance.width(), 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().height(), initialAdvance.height(), 0.0001);
+ EXPECT_EQ(glyphBuffer.size(), 5U);
+ EXPECT_NEAR(glyphBuffer.advanceAt(0).width(), advances[4].width(), 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(1).width(), advances[3].width(), 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(2).width(), advances[2].width(), 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(3).width(), advances[1].width(), 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(4).width(), -initialAdvance.width(), 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(4).height(), initialAdvance.height(), 0.0001);
+}
+
+TEST_F(ComplexTextControllerTest, InitialAdvanceWithLeftRunInLTR)
+{
+ FontCascadeDescription description;
+ description.setOneFamily("LucidaGrande");
+ description.setComputedSize(80);
+ FontCascade font(description);
+ font.update();
+ auto spaceWidth = font.primaryFont().spaceWidth();
+
+#if USE_LAYOUT_SPECIFIC_ADVANCES
+ Vector<FloatSize> advances = { FloatSize(76.347656, 0.000000), FloatSize(0.000000, 0.000000) };
+ Vector<FloatPoint> origins = { FloatPoint(), FloatPoint(-23.281250, -8.398438) };
+#else
+ Vector<FloatSize> advances = { FloatSize(53.066406, -8.398438), FloatSize(23.281250, 8.398438) };
+ Vector<FloatPoint> origins = { };
+#endif
+
+ FloatSize initialAdvance = FloatSize(28.144531, 0);
+
+ UChar characters[] = { 0x20, 0x61, 0x20e3 };
+ size_t charactersLength = WTF_ARRAY_LENGTH(characters);
+ TextRun textRun(StringView(characters, charactersLength));
+ auto run1 = ComplexTextController::ComplexTextRun::create({ FloatSize(spaceWidth, 0) }, { FloatPoint() }, { 5 }, { 0 }, FloatSize(), font.primaryFont(), characters, 0, charactersLength, 0, 1, true);
+ auto run2 = ComplexTextController::ComplexTextRun::create(advances, origins, { 68, 1471 }, { 1, 2 }, initialAdvance, font.primaryFont(), characters, 0, charactersLength, 1, 3, true);
+ Vector<Ref<ComplexTextController::ComplexTextRun>> runs;
+ runs.append(WTFMove(run1));
+ runs.append(WTFMove(run2));
+ ComplexTextController controller(font, textRun, runs);
+
+ EXPECT_NEAR(controller.totalWidth(), spaceWidth + 76.347656 + initialAdvance.width(), 0.0001);
+ GlyphBuffer glyphBuffer;
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(0, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(1, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), spaceWidth, 0.0001);
+ controller.advance(2, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), spaceWidth + advances[0].width() + initialAdvance.width(), 0.0001);
+ controller.advance(3, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), spaceWidth + 76.347656 + initialAdvance.width(), 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().width(), 0, 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().height(), 0, 0.0001);
+ EXPECT_EQ(glyphBuffer.size(), 3U);
+ EXPECT_NEAR(glyphBuffer.advanceAt(0).width(), spaceWidth + initialAdvance.width(), 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(1).width(), 53.066406, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(2).width(), 23.281250, 0.0001);
+}
+
+TEST_F(ComplexTextControllerTest, InitialAdvanceInLTR)
+{
+ FontCascadeDescription description;
+ description.setOneFamily("LucidaGrande");
+ description.setComputedSize(80);
+ FontCascade font(description);
+ font.update();
+
+#if USE_LAYOUT_SPECIFIC_ADVANCES
+ Vector<FloatSize> advances = { FloatSize(76.347656, 0.000000), FloatSize(0.000000, 0.000000) };
+ Vector<FloatPoint> origins = { FloatPoint(), FloatPoint(-23.281250, -8.398438) };
+#else
+ Vector<FloatSize> advances = { FloatSize(53.066406, -8.398438), FloatSize(23.281250, 8.398438) };
+ Vector<FloatPoint> origins = { };
+#endif
+
+ FloatSize initialAdvance = FloatSize(28.144531, 0);
+
+ UChar characters[] = { 0x61, 0x20e3 };
+ size_t charactersLength = WTF_ARRAY_LENGTH(characters);
+ TextRun textRun(StringView(characters, charactersLength));
+ auto run = ComplexTextController::ComplexTextRun::create(advances, origins, { 68, 1471 }, { 0, 1 }, initialAdvance, font.primaryFont(), characters, 0, charactersLength, 0, 2, true);
+ Vector<Ref<ComplexTextController::ComplexTextRun>> runs;
+ runs.append(WTFMove(run));
+ ComplexTextController controller(font, textRun, runs);
+
+ EXPECT_NEAR(controller.totalWidth(), 76.347656 + initialAdvance.width(), 0.0001);
+ GlyphBuffer glyphBuffer;
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(0, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(1, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), advances[0].width() + initialAdvance.width(), 0.0001);
+ controller.advance(2, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), 76.347656 + initialAdvance.width(), 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().width(), initialAdvance.width(), 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().height(), initialAdvance.height(), 0.0001);
+ EXPECT_EQ(glyphBuffer.size(), 2U);
+ EXPECT_NEAR(glyphBuffer.advanceAt(0).width(), 53.066406, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(1).width(), 23.281250, 0.0001);
+}
+
+TEST_F(ComplexTextControllerTest, InitialAdvanceInRTLNoOrigins)
+{
+ FontCascadeDescription description;
+ description.setOneFamily("Times");
+ description.setComputedSize(48);
+ FontCascade font(description);
+ font.update();
+
+ FloatSize initialAdvance = FloatSize(4.33996383363472, 12.368896925859);
+
+ UChar characters[] = { 0x633, 0x20, 0x627, 0x650 };
+ size_t charactersLength = WTF_ARRAY_LENGTH(characters);
+ TextRun textRun(StringView(characters, charactersLength));
+ auto run1 = ComplexTextController::ComplexTextRun::create({ FloatSize(-4.33996383363472, -12.368896925859), FloatSize(14.0397830018083, 0) }, { }, { 884, 240 }, { 3, 2 }, initialAdvance, font.primaryFont(), characters, 0, charactersLength, 2, 4, false);
+ auto run2 = ComplexTextController::ComplexTextRun::create({ FloatSize(12.0, 0) }, { }, { 3 }, { 1 }, FloatSize(), font.primaryFont(), characters, 0, charactersLength, 1, 2, false);
+ auto run3 = ComplexTextController::ComplexTextRun::create({ FloatSize(43.8119349005425, 0) }, { }, { 276 }, { 0 }, FloatSize(), font.primaryFont(), characters, 0, charactersLength, 0, 1, false);
+ Vector<Ref<ComplexTextController::ComplexTextRun>> runs;
+ runs.append(WTFMove(run1));
+ runs.append(WTFMove(run2));
+ runs.append(WTFMove(run3));
+ ComplexTextController controller(font, textRun, runs);
+
+ float totalWidth = 14.0397830018083 + 12.0 + 43.8119349005425;
+ EXPECT_NEAR(controller.totalWidth(), totalWidth, 0.0001);
+ GlyphBuffer glyphBuffer;
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(0, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(1, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), 43.8119349005425, 0.0001);
+ controller.advance(2, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), 43.8119349005425 + 12.0, 0.0001);
+ controller.advance(3, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), totalWidth, 0.0001);
+ controller.advance(4, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), totalWidth, 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().width(), initialAdvance.width(), 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().height(), initialAdvance.height(), 0.0001);
+ EXPECT_EQ(glyphBuffer.size(), 4U);
+ EXPECT_NEAR(glyphBuffer.advanceAt(0).width(), 43.8119349005425, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(1).width(), 12.0, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(2).width(), 14.0397830018083, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(3).width(), -4.33996383363472, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(3).height(), 12.368896925859, 0.0001);
+}
+
+TEST_F(ComplexTextControllerTest, LeadingExpansion)
+{
+ FontCascadeDescription description;
+ description.setOneFamily("Times");
+ description.setComputedSize(48);
+ FontCascade font(description);
+ font.update();
+
+ UChar characters[] = { 'a' };
+ size_t charactersLength = WTF_ARRAY_LENGTH(characters);
+ TextRun textRun(StringView(characters, charactersLength), 0, 100, ForceLeadingExpansion);
+ auto run = ComplexTextController::ComplexTextRun::create({ FloatSize(24, 0) }, { }, { 16 }, { 0 }, FloatSize(), font.primaryFont(), characters, 0, charactersLength, 0, 1, true);
+ Vector<Ref<ComplexTextController::ComplexTextRun>> runs;
+ runs.append(WTFMove(run));
+ ComplexTextController controller(font, textRun, runs);
+
+ float totalWidth = 100 + 24;
+ EXPECT_NEAR(controller.totalWidth(), totalWidth, 0.0001);
+ GlyphBuffer glyphBuffer;
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(0, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(1, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), totalWidth, 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().width(), 100, 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().height(), 0, 0.0001);
+ EXPECT_EQ(glyphBuffer.size(), 1U);
+ EXPECT_NEAR(glyphBuffer.advanceAt(0).width(), 24, 0.0001);
+}
+
+TEST_F(ComplexTextControllerTest, VerticalAdvances)
+{
+ FontCascadeDescription description;
+ description.setOneFamily("Times");
+ description.setComputedSize(48);
+ FontCascade font(description);
+ font.update();
+
+ UChar characters[] = { 'a', 'b', 'c', 'd' };
+ size_t charactersLength = WTF_ARRAY_LENGTH(characters);
+ TextRun textRun(StringView(characters, charactersLength));
+ auto run1 = ComplexTextController::ComplexTextRun::create({ FloatSize(0, 1), FloatSize(0, 2) }, { FloatPoint(0, 4), FloatPoint(0, 8) }, { 16, 17 }, { 0, 1 }, FloatSize(0, 16), font.primaryFont(), characters, 0, charactersLength, 0, 2, true);
+ auto run2 = ComplexTextController::ComplexTextRun::create({ FloatSize(0, 32), FloatSize(0, 64) }, { FloatPoint(0, 128), FloatPoint(0, 256) }, { 18, 19 }, { 2, 3 }, FloatSize(0, 512), font.primaryFont(), characters, 0, charactersLength, 2, 4, true);
+ Vector<Ref<ComplexTextController::ComplexTextRun>> runs;
+ runs.append(WTFMove(run1));
+ runs.append(WTFMove(run2));
+ ComplexTextController controller(font, textRun, runs);
+
+ EXPECT_NEAR(controller.totalWidth(), 0, 0.0001);
+ GlyphBuffer glyphBuffer;
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(0, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(1, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(2, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(3, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(4, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().width(), 0, 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().height(), 16, 0.0001);
+ EXPECT_EQ(glyphBuffer.size(), 4U);
+ EXPECT_NEAR(glyphBuffer.advanceAt(0).width(), 0, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(0).height(), 4 - 1 -8, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(1).width(), 0, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(1).height(), 8 - 2 - 512, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(2).width(), 0, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(2).height(), 128 - 32 - 256, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(3).width(), 0, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(3).height(), 256 - 64, 0.0001);
+}
+
+TEST_F(ComplexTextControllerTest, TotalWidthWithJustification)
+{
+ FontCascadeDescription description;
+ description.setOneFamily("Times");
+ description.setComputedSize(80);
+ FontCascade font(description);
+ font.update();
+
+ Vector<FloatSize> advances = { FloatSize(1, 0), FloatSize(2, 0), FloatSize(4, 0), FloatSize(8, 0), FloatSize(16, 0) };
+#if USE_LAYOUT_SPECIFIC_ADVANCES
+ Vector<FloatPoint> origins = { FloatPoint(), FloatPoint(), FloatPoint(), FloatPoint(), FloatPoint() };
+#else
+ Vector<FloatPoint> origins = { };
+#endif
+
+ FloatSize initialAdvance = FloatSize();
+
+ UChar characters[] = { 0x644, ' ', 0x644, ' ', 0x644 };
+ size_t charactersLength = WTF_ARRAY_LENGTH(characters);
+ TextRun textRun(StringView(characters, charactersLength), 0, 14, DefaultExpansion, RTL);
+ auto run = ComplexTextController::ComplexTextRun::create(advances, origins, { 5, 6, 7, 8, 9 }, { 4, 3, 2, 1, 0 }, initialAdvance, font.primaryFont(), characters, 0, charactersLength, 0, 5, false);
+ Vector<Ref<ComplexTextController::ComplexTextRun>> runs;
+ runs.append(WTFMove(run));
+ ComplexTextController controller(font, textRun, runs);
+
+ EXPECT_NEAR(controller.totalWidth(), 1 + 20 + 7 + 4 + 20 + 7 + 16, 0.0001);
+ GlyphBuffer glyphBuffer;
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(5, &glyphBuffer);
+ EXPECT_EQ(glyphBuffer.size(), 5U);
+ EXPECT_NEAR(glyphBuffer.advanceAt(0).width() + glyphBuffer.advanceAt(1).width() + glyphBuffer.advanceAt(2).width() + glyphBuffer.advanceAt(3).width() + glyphBuffer.advanceAt(4).width(), controller.totalWidth(), 0.0001);
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp b/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp
new file mode 100644
index 000000000..40950c273
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp
@@ -0,0 +1,2795 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include "PlatformUtilities.h"
+#include <JavaScriptCore/InitializeThreading.h>
+#include <WebCore/CombinedURLFilters.h>
+#include <WebCore/ContentExtensionCompiler.h>
+#include <WebCore/ContentExtensionError.h>
+#include <WebCore/ContentExtensionsBackend.h>
+#include <WebCore/DFA.h>
+#include <WebCore/DFABytecodeCompiler.h>
+#include <WebCore/DFABytecodeInterpreter.h>
+#include <WebCore/NFA.h>
+#include <WebCore/NFAToDFA.h>
+#include <WebCore/ResourceLoadInfo.h>
+#include <WebCore/URL.h>
+#include <WebCore/URLFilterParser.h>
+#include <wtf/MainThread.h>
+#include <wtf/RunLoop.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+namespace ContentExtensions {
+inline std::ostream& operator<<(std::ostream& os, const ActionType& action)
+{
+ switch (action) {
+ case ActionType::BlockLoad:
+ return os << "ActionType::BlockLoad";
+ case ActionType::BlockCookies:
+ return os << "ActionType::BlockCookies";
+ case ActionType::CSSDisplayNoneSelector:
+ return os << "ActionType::CSSDisplayNone";
+ case ActionType::CSSDisplayNoneStyleSheet:
+ return os << "ActionType::CSSDisplayNoneStyleSheet";
+ case ActionType::IgnorePreviousRules:
+ return os << "ActionType::IgnorePreviousRules";
+ case ActionType::MakeHTTPS:
+ return os << "ActionType::MakeHTTPS";
+ case ActionType::InvalidAction:
+ return os << "ActionType::InvalidAction";
+ }
+}
+}
+}
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+class ContentExtensionTest : public testing::Test {
+public:
+ virtual void SetUp()
+ {
+ JSC::initializeThreading();
+ RunLoop::initializeMainRunLoop();
+ }
+};
+
+struct CompiledContentExtensionData {
+ Vector<ContentExtensions::SerializedActionByte> actions;
+ Vector<ContentExtensions::DFABytecode> filtersWithoutDomains;
+ Vector<ContentExtensions::DFABytecode> filtersWithDomains;
+ Vector<ContentExtensions::DFABytecode> domainFilters;
+};
+
+class InMemoryContentExtensionCompilationClient final : public ContentExtensions::ContentExtensionCompilationClient {
+public:
+ InMemoryContentExtensionCompilationClient(CompiledContentExtensionData& data)
+ : m_data(data)
+ {
+ EXPECT_EQ(data.actions.size(), 0ull);
+ EXPECT_EQ(data.filtersWithoutDomains.size(), 0ull);
+ EXPECT_EQ(data.filtersWithDomains.size(), 0ull);
+ EXPECT_EQ(data.domainFilters.size(), 0ull);
+ }
+
+ void writeActions(Vector<ContentExtensions::SerializedActionByte>&& actions) override
+ {
+ EXPECT_FALSE(finalized);
+ EXPECT_EQ(m_data.actions.size(), 0ull);
+ EXPECT_EQ(m_data.filtersWithoutDomains.size(), 0ull);
+ EXPECT_EQ(m_data.filtersWithDomains.size(), 0ull);
+ EXPECT_EQ(m_data.domainFilters.size(), 0ull);
+ m_data.actions.appendVector(actions);
+ }
+
+ void writeFiltersWithoutDomainsBytecode(Vector<ContentExtensions::DFABytecode>&& bytecode) override
+ {
+ EXPECT_FALSE(finalized);
+ EXPECT_EQ(m_data.filtersWithDomains.size(), 0ull);
+ EXPECT_EQ(m_data.domainFilters.size(), 0ull);
+ m_data.filtersWithoutDomains.appendVector(bytecode);
+ }
+
+ void writeFiltersWithDomainsBytecode(Vector<ContentExtensions::DFABytecode>&& bytecode) override
+ {
+ EXPECT_FALSE(finalized);
+ EXPECT_EQ(m_data.domainFilters.size(), 0ull);
+ m_data.filtersWithDomains.appendVector(bytecode);
+ }
+
+ void writeDomainFiltersBytecode(Vector<ContentExtensions::DFABytecode>&& bytecode) override
+ {
+ EXPECT_FALSE(finalized);
+ m_data.domainFilters.appendVector(bytecode);
+ }
+
+ void finalize() override
+ {
+ finalized = true;
+ }
+
+private:
+ CompiledContentExtensionData& m_data;
+ bool finalized { false };
+};
+
+class InMemoryCompiledContentExtension : public ContentExtensions::CompiledContentExtension {
+public:
+ static RefPtr<InMemoryCompiledContentExtension> createFromFilter(String&& filter)
+ {
+ CompiledContentExtensionData extensionData;
+ InMemoryContentExtensionCompilationClient client(extensionData);
+ auto compilerError = ContentExtensions::compileRuleList(client, WTFMove(filter));
+ if (compilerError) {
+ // Compiling should always succeed here. We have other tests for compile failures.
+ EXPECT_TRUE(false);
+ return nullptr;
+ }
+
+ return InMemoryCompiledContentExtension::create(WTFMove(extensionData));
+ }
+
+ static RefPtr<InMemoryCompiledContentExtension> create(CompiledContentExtensionData&& data)
+ {
+ return adoptRef(new InMemoryCompiledContentExtension(WTFMove(data)));
+ }
+
+ virtual ~InMemoryCompiledContentExtension()
+ {
+ }
+
+ const ContentExtensions::SerializedActionByte* actions() const override { return m_data.actions.data(); }
+ unsigned actionsLength() const override { return m_data.actions.size(); }
+ const ContentExtensions::DFABytecode* filtersWithoutDomainsBytecode() const override { return m_data.filtersWithoutDomains.data(); }
+ unsigned filtersWithoutDomainsBytecodeLength() const override { return m_data.filtersWithoutDomains.size(); }
+ const ContentExtensions::DFABytecode* filtersWithDomainsBytecode() const override { return m_data.filtersWithDomains.data(); }
+ unsigned filtersWithDomainsBytecodeLength() const override { return m_data.filtersWithDomains.size(); }
+ const ContentExtensions::DFABytecode* domainFiltersBytecode() const override { return m_data.domainFilters.data(); }
+ unsigned domainFiltersBytecodeLength() const override { return m_data.domainFilters.size(); }
+
+private:
+ InMemoryCompiledContentExtension(CompiledContentExtensionData&& data)
+ : m_data(WTFMove(data))
+ {
+ }
+
+ CompiledContentExtensionData m_data;
+};
+
+void static testRequest(ContentExtensions::ContentExtensionsBackend contentExtensionsBackend, const ResourceLoadInfo& resourceLoadInfo, Vector<ContentExtensions::ActionType> expectedActions, bool ignorePreviousRules = false)
+{
+ auto actions = contentExtensionsBackend.actionsForResourceLoad(resourceLoadInfo);
+ unsigned expectedSize = actions.size();
+ if (!ignorePreviousRules)
+ expectedSize--; // The last action is applying the compiled stylesheet.
+
+ EXPECT_EQ(expectedActions.size(), expectedSize);
+ if (expectedActions.size() != expectedSize)
+ return;
+
+ for (unsigned i = 0; i < expectedActions.size(); ++i)
+ EXPECT_EQ(expectedActions[i], actions[i].type());
+ if (!ignorePreviousRules)
+ EXPECT_EQ(actions[actions.size() - 1].type(), ContentExtensions::ActionType::CSSDisplayNoneStyleSheet);
+}
+
+static ResourceLoadInfo mainDocumentRequest(const char* url, ResourceType resourceType = ResourceType::Document)
+{
+ return { URL(URL(), url), URL(URL(), url), resourceType };
+}
+
+static ResourceLoadInfo subResourceRequest(const char* url, const char* mainDocumentURL, ResourceType resourceType = ResourceType::Document)
+{
+ return { URL(URL(), url), URL(URL(), mainDocumentURL), resourceType };
+}
+
+ContentExtensions::ContentExtensionsBackend makeBackend(const char* json)
+{
+ AtomicString::init();
+ auto extension = InMemoryCompiledContentExtension::createFromFilter(json);
+ ContentExtensions::ContentExtensionsBackend backend;
+ backend.addContentExtension("testFilter", extension);
+ return backend;
+}
+
+static Vector<ContentExtensions::NFA> createNFAs(ContentExtensions::CombinedURLFilters& combinedURLFilters)
+{
+ Vector<ContentExtensions::NFA> nfas;
+
+ combinedURLFilters.processNFAs(std::numeric_limits<size_t>::max(), [&](ContentExtensions::NFA&& nfa) {
+ nfas.append(WTFMove(nfa));
+ });
+
+ return nfas;
+}
+
+TEST_F(ContentExtensionTest, Basic)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+}
+
+TEST_F(ContentExtensionTest, SingleCharacter)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^z\"}}]");
+ testRequest(matchBackend, mainDocumentRequest("http://webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("zttp://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"y\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("http://webkit.org/"), { });
+ testRequest(searchBackend, mainDocumentRequest("http://webkit.org/ywebkit"), { ContentExtensions::ActionType::BlockLoad });
+}
+
+TEST_F(ContentExtensionTest, SingleCharacterDisjunction)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^z\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^c\"}}]");
+ testRequest(matchBackend, mainDocumentRequest("http://webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("bttp://webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("cttp://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("dttp://webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("zttp://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"x\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"y\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("http://webkit.org/"), { });
+ testRequest(searchBackend, mainDocumentRequest("http://webkit.org/dwebkit"), { });
+ testRequest(searchBackend, mainDocumentRequest("http://webkit.org/xwebkit"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("http://webkit.org/ywebkit"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("http://webkit.org/zwebkit"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeBasic)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"w[0-9]c\", \"url-filter-is-case-sensitive\":true}},"
+ "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"[A-H][a-z]cko\", \"url-filter-is-case-sensitive\":true}}]");
+
+ testRequest(backend, mainDocumentRequest("http://w3c.org"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("w2c://whatwg.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/w0c"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/wac"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/wAc"), { });
+
+ // Note: URL parsing and canonicalization lowercase the scheme and hostname.
+ testRequest(backend, mainDocumentRequest("Aacko://webkit.org"), { });
+ testRequest(backend, mainDocumentRequest("aacko://webkit.org"), { });
+ testRequest(backend, mainDocumentRequest("http://gCcko.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://gccko.org/"), { });
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/Gecko"), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/gecko"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/GEcko"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeExclusionGeneratingUniversalTransition)
+{
+ // Transition of the type ([^X]X) effictively transition on every input.
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[^a]+afoobar\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://w3c.org"), { });
+
+ testRequest(backend, mainDocumentRequest("http://w3c.org/foobafoobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://w3c.org/foobarfoobar"), { });
+ testRequest(backend, mainDocumentRequest("http://w3c.org/FOOBAFOOBAR"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://w3c.org/FOOBARFOOBAR"), { });
+
+ // The character before the "a" prefix cannot be another "a".
+ testRequest(backend, mainDocumentRequest("http://w3c.org/aafoobar"), { });
+ testRequest(backend, mainDocumentRequest("http://w3c.org/Aafoobar"), { });
+ testRequest(backend, mainDocumentRequest("http://w3c.org/aAfoobar"), { });
+ testRequest(backend, mainDocumentRequest("http://w3c.org/AAfoobar"), { });
+}
+
+TEST_F(ContentExtensionTest, PatternStartingWithGroup)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(http://whatwg\\\\.org/)?webkit\134\134.org\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://whatwg.org/webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://whatwg.org/webkit.org"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://whatwg.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://whatwg.org"), { });
+}
+
+TEST_F(ContentExtensionTest, PatternNestedGroups)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://webkit\\\\.org/(foo(bar)*)+\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobarbar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foofoobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobarfoobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foob"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foor"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/bar"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/fobar"), { });
+}
+
+TEST_F(ContentExtensionTest, EmptyGroups)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://webkit\\\\.org/foo()bar\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://webkit\\\\.org/((me)()(too))\"}}]");
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foo"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/bar"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/me"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/too"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/metoo"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foome"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foomebar"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/mefoo"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/mefootoo"), { });
+}
+
+TEST_F(ContentExtensionTest, QuantifiedEmptyGroups)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://webkit\\\\.org/foo()+bar\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://webkit\\\\.org/(()*()?(target)()+)\"}}]");
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foo"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/bar"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/me"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/too"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/target"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foome"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foomebar"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/mefoo"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/mefootoo"), { });
+}
+
+TEST_F(ContentExtensionTest, MatchPastEndOfString)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".+\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobarbar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foofoobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobarfoobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foob"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foor"), { ContentExtensions::ActionType::BlockLoad });
+}
+
+TEST_F(ContentExtensionTest, StartOfLineAssertion)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^foobar\"}}]");
+
+ testRequest(backend, mainDocumentRequest("foobar://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("foobars:///foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("foobarfoobar:///foobarfoobarfoobar"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobarfoo"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobarf"), { });
+ testRequest(backend, mainDocumentRequest("http://foobar.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://foobar.org/"), { });
+}
+
+TEST_F(ContentExtensionTest, EndOfLineAssertion)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"foobar$\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("file:///foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("file:///foobarfoobarfoobar"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobarfoo"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobarf"), { });
+}
+
+TEST_F(ContentExtensionTest, EndOfLineAssertionWithInvertedCharacterSet)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[^y]$\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/a"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/Ya"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/yFoobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/y"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/Y"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobary"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foobarY"), { });
+}
+
+TEST_F(ContentExtensionTest, DotDoesNotIncludeEndOfLine)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"https://webkit\\\\.org/.\"}}]");
+
+ testRequest(backend, mainDocumentRequest("https://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/A"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/z"), { ContentExtensions::ActionType::BlockLoad });
+}
+
+TEST_F(ContentExtensionTest, PrefixInfixSuffixExactMatch)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"infix\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^prefix\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"suffix$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://exact\\\\.org/$\"}}]");
+
+ testRequest(backend, mainDocumentRequest("infix://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://infix.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/infix"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("prefix://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://prefix.org/"), { });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/prefix"), { });
+
+ testRequest(backend, mainDocumentRequest("https://webkit.org/suffix"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://suffix.org/"), { });
+ testRequest(backend, mainDocumentRequest("suffix://webkit.org/"), { });
+
+ testRequest(backend, mainDocumentRequest("http://exact.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://exact.org/oops"), { });
+}
+
+TEST_F(ContentExtensionTest, DuplicatedMatchAllTermsInVariousFormat)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*.*(.)*(.*)(.+)*(.?)*infix\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"pre(.?)+(.+)?post\"}}]");
+
+ testRequest(backend, mainDocumentRequest("infix://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://infix.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/infix"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("pre://webkit.org/post"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://prepost.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://pre.org/posttail"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://pre.pre/posttail"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://pre.org/posttailpost"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("https://post.org/pre"), { });
+ testRequest(backend, mainDocumentRequest("https://pre.org/pre"), { });
+ testRequest(backend, mainDocumentRequest("https://post.org/post"), { });
+}
+
+TEST_F(ContentExtensionTest, UndistinguishableActionInsidePrefixTree)
+{
+ // In this case, the two actions are undistinguishable. The actions of "prefix" appear inside the prefixtree
+ // ending at "suffix".
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"prefix\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"prefixsuffix\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://prefix.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/prefix"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/aaaprefixaaa"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://prefixsuffix.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/prefixsuffix"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/bbbprefixsuffixbbb"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("http://suffix.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/suffix"), { });
+}
+
+TEST_F(ContentExtensionTest, DistinguishableActionInsidePrefixTree)
+{
+ // In this case, the two actions are distinguishable.
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"prefix\"}},"
+ "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"prefixsuffix\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://prefix.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/prefix"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/aaaprefixaaa"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://prefixsuffix.org/"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/prefixsuffix"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/bbbprefixsuffixbbb"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("http://suffix.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/suffix"), { });
+}
+
+TEST_F(ContentExtensionTest, DistinguishablePrefixAreNotMerged)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"foo\\\\.org\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"bar\\\\.org\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://foo.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://bar.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("http://foor.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://fooar.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://fooba.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://foob.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://foor.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://foar.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://foba.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://fob.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://barf.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://barfo.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://baroo.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://baro.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://baf.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://bafo.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://baoo.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://bao.org/"), { });
+
+ testRequest(backend, mainDocumentRequest("http://foo.orgbar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://oo.orgbar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://o.orgbar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://.orgbar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://rgbar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://gbar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://foo.orgar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://foo.orgr.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://foo.org.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://foo.orgorg/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://foo.orgrg/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://foo.orgg/"), { ContentExtensions::ActionType::BlockLoad });
+}
+
+static void compareContents(const ContentExtensions::DFABytecodeInterpreter::Actions& a, const Vector<uint64_t>& b)
+{
+ EXPECT_EQ(a.size(), b.size());
+ for (unsigned i = 0; i < b.size(); ++i)
+ EXPECT_TRUE(a.contains(b[i]));
+}
+
+TEST_F(ContentExtensionTest, SearchSuffixesWithIdenticalActionAreMerged)
+{
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("foo\\.org", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("ba\\.org", false, 0));
+
+ Vector<ContentExtensions::NFA> nfas = createNFAs(combinedURLFilters);
+ EXPECT_EQ(1ul, nfas.size());
+ EXPECT_EQ(12ul, nfas.first().nodes.size());
+
+ ContentExtensions::DFA dfa = ContentExtensions::NFAToDFA::convert(nfas.first());
+ Vector<ContentExtensions::DFABytecode> bytecode;
+ ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode);
+ compiler.compile();
+ ContentExtensions::DFABytecodeInterpreter interpreter(bytecode.data(), bytecode.size());
+ compareContents(interpreter.interpret("foo.org", 0), { 0 });
+ compareContents(interpreter.interpret("ba.org", 0), { 0 });
+ compareContents(interpreter.interpret("bar.org", 0), { });
+
+ compareContents(interpreter.interpret("paddingfoo.org", 0), { 0 });
+ compareContents(interpreter.interpret("paddingba.org", 0), { 0 });
+ compareContents(interpreter.interpret("paddingbar.org", 0), { });
+}
+
+TEST_F(ContentExtensionTest, SearchSuffixesWithDistinguishableActionAreNotMerged)
+{
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("foo\\.org", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("ba\\.org", false, 1));
+
+ Vector<ContentExtensions::NFA> nfas = createNFAs(combinedURLFilters);
+
+ EXPECT_EQ(1ul, nfas.size());
+ EXPECT_EQ(17ul, nfas.first().nodes.size());
+
+ ContentExtensions::DFA dfa = ContentExtensions::NFAToDFA::convert(nfas.first());
+ Vector<ContentExtensions::DFABytecode> bytecode;
+ ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode);
+ compiler.compile();
+ ContentExtensions::DFABytecodeInterpreter interpreter(bytecode.data(), bytecode.size());
+ compareContents(interpreter.interpret("foo.org", 0), { 0 });
+ compareContents(interpreter.interpret("ba.org", 0), { 1 });
+ compareContents(interpreter.interpret("bar.org", 0), { });
+
+ compareContents(interpreter.interpret("paddingfoo.org", 0), { 0 });
+ compareContents(interpreter.interpret("paddingba.org", 0), { 1 });
+ compareContents(interpreter.interpret("paddingba.orgfoo.org", 0), { 1, 0 });
+ compareContents(interpreter.interpret("paddingbar.org", 0), { });
+}
+
+TEST_F(ContentExtensionTest, DomainTriggers)
+{
+ auto ifDomainBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"webkit.org\"]}}]");
+ testRequest(ifDomainBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
+ testRequest(ifDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.htm"), { });
+ testRequest(ifDomainBackend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(ifDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { });
+ testRequest(ifDomainBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { });
+ testRequest(ifDomainBackend, mainDocumentRequest("http://not_webkit.org/test.htm"), { });
+ testRequest(ifDomainBackend, mainDocumentRequest("http://webkit.organization/test.htm"), { });
+ testRequest(ifDomainBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { });
+ testRequest(ifDomainBackend, mainDocumentRequest("http://webkit.organization/test.html"), { });
+
+ auto unlessDomainBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"unless-domain\":[\"webkit.org\"]}}]");
+ testRequest(unlessDomainBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
+ testRequest(unlessDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.htm"), { });
+ testRequest(unlessDomainBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
+ testRequest(unlessDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(unlessDomainBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(unlessDomainBackend, mainDocumentRequest("http://not_webkit.org/test.htm"), { });
+ testRequest(unlessDomainBackend, mainDocumentRequest("http://webkit.organization/test.htm"), { });
+ testRequest(unlessDomainBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(unlessDomainBackend, mainDocumentRequest("http://webkit.organization/test.html"), { ContentExtensions::ActionType::BlockLoad });
+
+ auto ifDomainStarBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"*webkit.org\"]}}]");
+ testRequest(ifDomainStarBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
+ testRequest(ifDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.htm"), { });
+ testRequest(ifDomainStarBackend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(ifDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(ifDomainStarBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(ifDomainStarBackend, mainDocumentRequest("http://not_webkit.org/test.htm"), { });
+ testRequest(ifDomainStarBackend, mainDocumentRequest("http://webkit.organization/test.htm"), { });
+ testRequest(ifDomainStarBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { });
+ testRequest(ifDomainStarBackend, mainDocumentRequest("http://webkit.organization/test.html"), { });
+
+ auto unlessDomainStarBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"unless-domain\":[\"*webkit.org\"]}}]");
+ testRequest(unlessDomainStarBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
+ testRequest(unlessDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.htm"), { });
+ testRequest(unlessDomainStarBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
+ testRequest(unlessDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { });
+ testRequest(unlessDomainStarBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { });
+ testRequest(unlessDomainStarBackend, mainDocumentRequest("http://not_webkit.org/test.htm"), { });
+ testRequest(unlessDomainStarBackend, mainDocumentRequest("http://webkit.organization/test.htm"), { });
+ testRequest(unlessDomainStarBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(unlessDomainStarBackend, mainDocumentRequest("http://webkit.organization/test.html"), { ContentExtensions::ActionType::BlockLoad });
+
+ auto ifSubDomainBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"sub1.webkit.org\"]}}]");
+ testRequest(ifSubDomainBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
+ testRequest(ifSubDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { });
+ testRequest(ifSubDomainBackend, mainDocumentRequest("http://sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(ifSubDomainBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { });
+
+ auto ifSubDomainStarBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"*sub1.webkit.org\"]}}]");
+ testRequest(ifSubDomainStarBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
+ testRequest(ifSubDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { });
+ testRequest(ifSubDomainStarBackend, mainDocumentRequest("http://sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(ifSubDomainStarBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+
+ auto unlessSubDomainBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"unless-domain\":[\"sub1.webkit.org\"]}}]");
+ testRequest(unlessSubDomainBackend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(unlessSubDomainBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(unlessSubDomainBackend, mainDocumentRequest("http://sub1.webkit.org/test.html"), { });
+ testRequest(unlessSubDomainBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+
+ auto unlessSubDomainStarBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"unless-domain\":[\"*sub1.webkit.org\"]}}]");
+ testRequest(unlessSubDomainStarBackend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(unlessSubDomainStarBackend, mainDocumentRequest("http://bugs.webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(unlessSubDomainStarBackend, mainDocumentRequest("http://sub1.webkit.org/test.html"), { });
+ testRequest(unlessSubDomainStarBackend, mainDocumentRequest("http://sub2.sub1.webkit.org/test.html"), { });
+
+ auto combinedBackend1 = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test_block_load\", \"if-domain\":[\"webkit.org\"]}},"
+ "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"test_block_cookies\", \"unless-domain\":[\"webkit.org\"]}}]");
+ testRequest(combinedBackend1, mainDocumentRequest("http://webkit.org"), { });
+ testRequest(combinedBackend1, mainDocumentRequest("http://not_webkit.org"), { });
+ testRequest(combinedBackend1, mainDocumentRequest("http://webkit.org/test_block_load.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/test_block_load.html", "http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/shouldnt_match.html", "http://webkit.org/"), { });
+ testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/test_block_load.html", "http://not_webkit.org/"), { });
+ testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/shouldnt_match.html", "http://not_webkit.org/"), { });
+ testRequest(combinedBackend1, mainDocumentRequest("http://webkit.org/test_block_cookies.html"), { });
+ testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/test_block_cookies.html", "http://webkit.org/"), { });
+ testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/shouldnt_match.html", "http://webkit.org/"), { });
+ testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/test_block_cookies.html", "http://not_webkit.org/path/to/main/document.html"), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(combinedBackend1, subResourceRequest("http://whatwg.org/shouldnt_match.html", "http://not_webkit.org/"), { });
+
+ auto combinedBackend2 = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test_block_load\\\\.html\", \"if-domain\":[\"webkit.org\"]}},"
+ "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"test_block_cookies\\\\.html\", \"unless-domain\":[\"w3c.org\"]}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"test_css\\\\.html\"}}]");
+ testRequest(combinedBackend2, mainDocumentRequest("http://webkit.org/test_css.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(combinedBackend2, mainDocumentRequest("http://webkit.org/test_css.htm"), { });
+ testRequest(combinedBackend2, mainDocumentRequest("http://webkit.org/test_block_load.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(combinedBackend2, mainDocumentRequest("http://not_webkit.org/test_block_load.html"), { });
+ testRequest(combinedBackend2, mainDocumentRequest("http://not_webkit.org/test_css.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(combinedBackend2, mainDocumentRequest("http://webkit.org/TEST_CSS.hTmL/test_block_load.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad});
+ testRequest(combinedBackend2, mainDocumentRequest("http://w3c.org/test_css.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(combinedBackend2, mainDocumentRequest("http://w3c.org/test_block_load.html"), { });
+ testRequest(combinedBackend2, mainDocumentRequest("http://w3c.org/test_block_cookies.html"), { });
+ testRequest(combinedBackend2, mainDocumentRequest("http://w3c.org/test_css.html/test_block_cookies.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(combinedBackend2, mainDocumentRequest("http://not_w3c.org/test_block_cookies.html"), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(combinedBackend2, mainDocumentRequest("http://not_w3c.org/test_css.html/test_block_cookies.html"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockCookies });
+
+ auto ifDomainWithFlagsBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\", \"if-domain\":[\"webkit.org\"],\"resource-type\":[\"image\"]}}]");
+ testRequest(ifDomainWithFlagsBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
+ testRequest(ifDomainWithFlagsBackend, mainDocumentRequest("http://webkit.org/test.png", ResourceType::Image), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(ifDomainWithFlagsBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { });
+ testRequest(ifDomainWithFlagsBackend, mainDocumentRequest("http://not_webkit.org/test.png", ResourceType::Image), { });
+
+ auto unlessDomainWithFlagsBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\", \"unless-domain\":[\"webkit.org\"],\"resource-type\":[\"image\"]}}]");
+ testRequest(unlessDomainWithFlagsBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
+ testRequest(unlessDomainWithFlagsBackend, mainDocumentRequest("http://webkit.org/test.png", ResourceType::Image), { });
+ testRequest(unlessDomainWithFlagsBackend, mainDocumentRequest("http://not_webkit.org/test.html"), { });
+ testRequest(unlessDomainWithFlagsBackend, mainDocumentRequest("http://not_webkit.org/test.png", ResourceType::Image), { ContentExtensions::ActionType::BlockLoad });
+
+ // Domains should not be interepted as regular expressions.
+ auto domainRegexBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"we?bkit.org\"]}}]");
+ testRequest(domainRegexBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
+ testRequest(domainRegexBackend, mainDocumentRequest("http://wbkit.org/test.html"), { });
+
+ auto multipleIfDomainsBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"webkit.org\", \"w3c.org\"]}}]");
+ testRequest(multipleIfDomainsBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
+ testRequest(multipleIfDomainsBackend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(multipleIfDomainsBackend, mainDocumentRequest("http://w3c.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(multipleIfDomainsBackend, mainDocumentRequest("http://whatwg.org/test.html"), { });
+
+ auto multipleUnlessDomainsBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"unless-domain\":[\"webkit.org\", \"w3c.org\"]}}]");
+ testRequest(multipleUnlessDomainsBackend, mainDocumentRequest("http://webkit.org/test.htm"), { });
+ testRequest(multipleUnlessDomainsBackend, mainDocumentRequest("http://webkit.org/test.html"), { });
+ testRequest(multipleUnlessDomainsBackend, mainDocumentRequest("http://w3c.org/test.html"), { });
+ testRequest(multipleUnlessDomainsBackend, mainDocumentRequest("http://whatwg.org/test.html"), { ContentExtensions::ActionType::BlockLoad });
+
+ // FIXME: Add and test domain-specific popup-only blocking (with layout tests).
+}
+
+TEST_F(ContentExtensionTest, DomainTriggersAlongMergedActions)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"test\\\\.html\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"test\\\\.html\", \"if-domain\":[\"webkit.org\"]}},"
+ "{\"action\":{\"type\":\"css-display-none\", \"selector\": \"*\"},\"trigger\":{\"url-filter\":\"trigger-on-scripts\\\\.html\",\"resource-type\":[\"script\"]}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"ignore-previous\",\"resource-type\":[\"image\"]}},"
+ "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"except-this\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/test.htm"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/test.html"), { ContentExtensions::ActionType::BlockLoad, ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/test.html"), { ContentExtensions::ActionType::BlockCookies });
+
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/trigger-on-scripts.html"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/trigger-on-scripts.html"), { });
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/trigger-on-scripts.html", ResourceType::Script), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/trigger-on-scripts.html", ResourceType::Script), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/trigger-on-scripts.html.test.html", ResourceType::Script), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/trigger-on-scripts.html.test.html", ResourceType::Script), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad, ContentExtensions::ActionType::BlockCookies });
+
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/ignore-previous-trigger-on-scripts.html"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ignore-previous-trigger-on-scripts.html"), { });
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/ignore-previous-trigger-on-scripts.html", ResourceType::Script), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ignore-previous-trigger-on-scripts.html", ResourceType::Script), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/ignore-previous-trigger-on-scripts.html.test.html", ResourceType::Script), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ignore-previous-trigger-on-scripts.html.test.html", ResourceType::Script), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad, ContentExtensions::ActionType::BlockCookies });
+
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/ignore-previous-trigger-on-scripts.html", ResourceType::Image), { }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ignore-previous-trigger-on-scripts.html", ResourceType::Image), { }, true);
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/ignore-previous-trigger-on-scripts.html.test.html", ResourceType::Image), { }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ignore-previous-trigger-on-scripts.html.test.html", ResourceType::Image), { }, true);
+
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/except-this-ignore-previous-trigger-on-scripts.html"), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/except-this-ignore-previous-trigger-on-scripts.html"), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/except-this-ignore-previous-trigger-on-scripts.html.test.html"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/except-this-ignore-previous-trigger-on-scripts.html.test.html"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockLoad, ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/except-this-ignore-previous-trigger-on-scripts.html", ResourceType::Image), { ContentExtensions::ActionType::BlockCookies }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/except-this-ignore-previous-trigger-on-scripts.html", ResourceType::Image), { ContentExtensions::ActionType::BlockCookies }, true);
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/except-this-ignore-previous-trigger-on-scripts.html.test.html", ResourceType::Image), { ContentExtensions::ActionType::BlockCookies }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/except-this-ignore-previous-trigger-on-scripts.html.test.html", ResourceType::Image), { ContentExtensions::ActionType::BlockCookies }, true);
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/except-this-ignore-previous-trigger-on-scripts.html", ResourceType::Script), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/except-this-ignore-previous-trigger-on-scripts.html", ResourceType::Script), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(backend, mainDocumentRequest("http://notwebkit.org/except-this-ignore-previous-trigger-on-scripts.html.test.html", ResourceType::Script), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/except-this-ignore-previous-trigger-on-scripts.html.test.html", ResourceType::Script), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad, ContentExtensions::ActionType::BlockCookies });
+
+}
+
+TEST_F(ContentExtensionTest, MultipleExtensions)
+{
+ auto extension1 = InMemoryCompiledContentExtension::createFromFilter("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"block_load\"}}]");
+ auto extension2 = InMemoryCompiledContentExtension::createFromFilter("[{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"block_cookies\"}}]");
+ ContentExtensions::ContentExtensionsBackend backend;
+ backend.addContentExtension("testFilter1", extension1);
+ backend.addContentExtension("testFilter2", extension2);
+
+ // These each have two display:none stylesheets. The second one is implied by using the default parameter ignorePreviousRules = false.
+ testRequest(backend, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneStyleSheet });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/block_load.html"), { ContentExtensions::ActionType::CSSDisplayNoneStyleSheet, ContentExtensions::ActionType::BlockLoad});
+ testRequest(backend, mainDocumentRequest("http://webkit.org/block_cookies.html"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet});
+ testRequest(backend, mainDocumentRequest("http://webkit.org/block_load/block_cookies.html"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet, ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/block_cookies/block_load.html"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet, ContentExtensions::ActionType::BlockLoad });
+
+ auto ignoreExtension1 = InMemoryCompiledContentExtension::createFromFilter("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"block_load\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"ignore1\"}}]");
+ auto ignoreExtension2 = InMemoryCompiledContentExtension::createFromFilter("[{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"block_cookies\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"ignore2\"}}]");
+ ContentExtensions::ContentExtensionsBackend backendWithIgnore;
+ backendWithIgnore.addContentExtension("testFilter1", ignoreExtension1);
+ backendWithIgnore.addContentExtension("testFilter2", ignoreExtension2);
+
+ testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneStyleSheet, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet }, true);
+ testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org/block_load/ignore1.html"), { ContentExtensions::ActionType::CSSDisplayNoneStyleSheet }, true);
+ testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org/block_cookies/ignore1.html"), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet}, true);
+ testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org/block_load/ignore2.html"), { ContentExtensions::ActionType::BlockLoad, ContentExtensions::ActionType::CSSDisplayNoneStyleSheet }, true);
+ testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org/block_cookies/ignore2.html"), { ContentExtensions::ActionType::CSSDisplayNoneStyleSheet}, true);
+ testRequest(backendWithIgnore, mainDocumentRequest("http://webkit.org/block_load/block_cookies/ignore1/ignore2.html"), { }, true);
+}
+
+TEST_F(ContentExtensionTest, TermsKnownToMatchAnything)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre1.*post1$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre2(.*)post2$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre3(.*)?post3$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre4(.*)+post4$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre5(.*)*post5$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre6(.)*post6$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre7(.+)*post7$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre8(.?)*post8$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre9(.+)?post9$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^pre0(.?)+post0$\"}}]");
+
+ testRequest(backend, mainDocumentRequest("pre1://webkit.org/post1"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("pre2://webkit.org/post2"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("pre3://webkit.org/post3"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("pre4://webkit.org/post4"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("pre5://webkit.org/post5"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("pre6://webkit.org/post6"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("pre7://webkit.org/post7"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("pre8://webkit.org/post8"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("pre9://webkit.org/post9"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("pre0://webkit.org/post0"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("pre1://webkit.org/post2"), { });
+ testRequest(backend, mainDocumentRequest("pre2://webkit.org/post3"), { });
+ testRequest(backend, mainDocumentRequest("pre3://webkit.org/post4"), { });
+ testRequest(backend, mainDocumentRequest("pre4://webkit.org/post5"), { });
+ testRequest(backend, mainDocumentRequest("pre5://webkit.org/post6"), { });
+ testRequest(backend, mainDocumentRequest("pre6://webkit.org/post7"), { });
+ testRequest(backend, mainDocumentRequest("pre7://webkit.org/post8"), { });
+ testRequest(backend, mainDocumentRequest("pre8://webkit.org/post9"), { });
+ testRequest(backend, mainDocumentRequest("pre9://webkit.org/post0"), { });
+ testRequest(backend, mainDocumentRequest("pre0://webkit.org/post1"), { });
+
+ testRequest(backend, mainDocumentRequest("pre0://webkit.org/post1"), { });
+ testRequest(backend, mainDocumentRequest("pre1://webkit.org/post2"), { });
+ testRequest(backend, mainDocumentRequest("pre2://webkit.org/post3"), { });
+ testRequest(backend, mainDocumentRequest("pre3://webkit.org/post4"), { });
+ testRequest(backend, mainDocumentRequest("pre4://webkit.org/post5"), { });
+ testRequest(backend, mainDocumentRequest("pre5://webkit.org/post6"), { });
+ testRequest(backend, mainDocumentRequest("pre6://webkit.org/post7"), { });
+ testRequest(backend, mainDocumentRequest("pre7://webkit.org/post8"), { });
+ testRequest(backend, mainDocumentRequest("pre8://webkit.org/post9"), { });
+ testRequest(backend, mainDocumentRequest("pre9://webkit.org/post0"), { });
+}
+
+TEST_F(ContentExtensionTest, TrailingDotStar)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"foo.*$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"bar(.*)$\"}}]");
+
+ testRequest(backend, mainDocumentRequest("https://webkit.org/"), { });
+
+ testRequest(backend, mainDocumentRequest("foo://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://foo.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.foo/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("bar://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://bar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.bar/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/bar"), { ContentExtensions::ActionType::BlockLoad });
+}
+
+TEST_F(ContentExtensionTest, TrailingTermsCarryingNoData)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"foob?a?r?\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"bazo(ok)?a?$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"cats*$\"}}]");
+
+ testRequest(backend, mainDocumentRequest("https://webkit.org/"), { });
+
+ // Anything is fine after foo.
+ testRequest(backend, mainDocumentRequest("https://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/foob"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/fooc"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/fooba"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/foobar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/foobar-stuff"), { ContentExtensions::ActionType::BlockLoad });
+
+ // Bazooka has to be at the tail without any character not defined by the filter.
+ testRequest(backend, mainDocumentRequest("https://webkit.org/baz"), { });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/bazo"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/bazoa"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/bazob"), { });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/bazoo"), { });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/bazook"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/bazookb"), { });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/bazooka"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/bazookaa"), { });
+
+ // The pattern must finish with cat, with any number of 's' following it, but no other character.
+ testRequest(backend, mainDocumentRequest("https://cat.org/"), { });
+ testRequest(backend, mainDocumentRequest("https://cats.org/"), { });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/cat"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/cats"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/catss"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/catsss"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/catso"), { });
+}
+
+TEST_F(ContentExtensionTest, UselessTermsMatchingEverythingAreEliminated)
+{
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern(".*web", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(.*)web", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(.)*web", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(.+)*web", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(.?)*web", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(.+)?web", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(.?)+web", false, 0));
+
+ Vector<ContentExtensions::NFA> nfas = createNFAs(combinedURLFilters);
+ EXPECT_EQ(1ul, nfas.size());
+ EXPECT_EQ(7ul, nfas.first().nodes.size());
+
+ ContentExtensions::DFA dfa = ContentExtensions::NFAToDFA::convert(nfas.first());
+ Vector<ContentExtensions::DFABytecode> bytecode;
+ ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode);
+ compiler.compile();
+ ContentExtensions::DFABytecodeInterpreter interpreter(bytecode.data(), bytecode.size());
+ compareContents(interpreter.interpret("eb", 0), { });
+ compareContents(interpreter.interpret("we", 0), { });
+ compareContents(interpreter.interpret("weeb", 0), { });
+ compareContents(interpreter.interpret("web", 0), { 0 });
+ compareContents(interpreter.interpret("wweb", 0), { 0 });
+ compareContents(interpreter.interpret("wwebb", 0), { 0 });
+ compareContents(interpreter.interpret("http://theweb.com/", 0), { 0 });
+}
+
+TEST_F(ContentExtensionTest, LoadType)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":[\"third-party\"]}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"whatwg.org\",\"load-type\":[\"first-party\"]}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"alwaysblock.pdf\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org"), { });
+ testRequest(backend, {URL(URL(), "http://webkit.org"), URL(URL(), "http://not_webkit.org"), ResourceType::Document}, { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("http://whatwg.org"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, {URL(URL(), "http://whatwg.org"), URL(URL(), "http://not_whatwg.org"), ResourceType::Document}, { });
+
+ testRequest(backend, mainDocumentRequest("http://foobar.org/alwaysblock.pdf"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, {URL(URL(), "http://foobar.org/alwaysblock.pdf"), URL(URL(), "http://not_foobar.org/alwaysblock.pdf"), ResourceType::Document}, { ContentExtensions::ActionType::BlockLoad });
+}
+
+TEST_F(ContentExtensionTest, ResourceType)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"block_all_types.org\",\"resource-type\":[\"document\",\"image\",\"style-sheet\",\"script\",\"font\",\"raw\",\"svg-document\",\"media\",\"popup\"]}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"block_only_images\",\"resource-type\":[\"image\"]}}]");
+
+ testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Document), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Image), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::StyleSheet), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Script), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Font), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Raw), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::SVGDocument), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Media), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://block_all_types.org", ResourceType::Popup), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://block_only_images.org", ResourceType::Image), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://block_only_images.org", ResourceType::Document), { });
+}
+
+TEST_F(ContentExtensionTest, ResourceAndLoadType)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"BlockOnlyIfThirdPartyAndScript\",\"resource-type\":[\"script\"],\"load-type\":[\"third-party\"]}}]");
+
+ testRequest(backend, subResourceRequest("http://webkit.org/BlockOnlyIfThirdPartyAndScript.js", "http://webkit.org", ResourceType::Script), { });
+ testRequest(backend, subResourceRequest("http://webkit.org/BlockOnlyIfThirdPartyAndScript.png", "http://not_webkit.org", ResourceType::Image), { });
+ testRequest(backend, subResourceRequest("http://webkit.org/BlockOnlyIfThirdPartyAndScript.js", "http://not_webkit.org", ResourceType::Script), { ContentExtensions::ActionType::BlockLoad });
+}
+
+TEST_F(ContentExtensionTest, ResourceOrLoadTypeMatchingEverything)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*\",\"resource-type\":[\"image\"]}},"
+ "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\".*\",\"load-type\":[\"third-party\"]}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\".*\",\"load-type\":[\"first-party\"]}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org"), { }, true);
+ testRequest(backend, {URL(URL(), "http://webkit.org"), URL(URL(), "http://not_webkit.org"), ResourceType::Document}, { ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, {URL(URL(), "http://webkit.org"), URL(URL(), "http://not_webkit.org"), ResourceType::Image}, { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockLoad });
+}
+
+TEST_F(ContentExtensionTest, WideNFA)
+{
+ // Make an NFA with about 1400 nodes that won't be combined.
+ StringBuilder ruleList;
+ ruleList.append('[');
+ for (char c1 = 'A'; c1 <= 'Z'; ++c1) {
+ for (char c2 = 'A'; c2 <= 'C'; ++c2) {
+ for (char c3 = 'A'; c3 <= 'C'; ++c3) {
+ if (c1 != 'A' || c2 != 'A' || c3 != 'A')
+ ruleList.append(',');
+ ruleList.append("{\"action\":{\"type\":\"");
+
+ // Make every other rule ignore-previous-rules to not combine actions.
+ if (!((c1 + c2 + c3) % 2))
+ ruleList.append("ignore-previous-rules");
+ else {
+ ruleList.append("css-display-none");
+ ruleList.append("\",\"selector\":\"");
+ ruleList.append(c1);
+ ruleList.append(c2);
+ ruleList.append(c3);
+ }
+ ruleList.append("\"},\"trigger\":{\"url-filter\":\".*");
+ ruleList.append(c1);
+ ruleList.append(c2);
+ ruleList.append(c3);
+ ruleList.append("\", \"url-filter-is-case-sensitive\":true}}");
+ }
+ }
+ }
+ ruleList.append(']');
+
+ auto backend = makeBackend(ruleList.toString().utf8().data());
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/AAA"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/YAA"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ZAA"), { }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/LAA/AAA"), { }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/LAA/MAA"), { ContentExtensions::ActionType::CSSDisplayNoneSelector }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
+}
+
+#ifdef NDEBUG
+static uint64_t expectedIndex(char c, unsigned position)
+{
+ uint64_t index = c - 'A';
+ for (unsigned i = 1; i < position; ++i)
+ index *= (i == 1) ? ('C' - 'A' + 1) : ('Z' - 'A' + 1);
+ return index;
+}
+#endif
+
+TEST_F(ContentExtensionTest, LargeJumps)
+{
+// A large test like this is necessary to test 24 and 32 bit jumps, but it's so large it times out in debug builds.
+#ifdef NDEBUG
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+
+ uint64_t patternId = 0;
+ for (char c1 = 'A'; c1 <= 'Z'; ++c1) {
+ for (char c2 = 'A'; c2 <= 'Z'; ++c2) {
+ for (char c3 = 'A'; c3 <= 'Z'; ++c3) {
+ for (char c4 = 'A'; c4 <= 'C'; ++c4) {
+ StringBuilder pattern;
+ pattern.append(c1);
+ pattern.append(c2);
+ pattern.append(c3);
+ pattern.append(c4);
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern(pattern.toString(), true, patternId++));
+ }
+ }
+ }
+ }
+
+ Vector<ContentExtensions::NFA> nfas;
+ combinedURLFilters.processNFAs(std::numeric_limits<size_t>::max(), [&](ContentExtensions::NFA&& nfa) {
+ nfas.append(WTFMove(nfa));
+ });
+ EXPECT_EQ(nfas.size(), 1ull);
+
+ Vector<ContentExtensions::DFA> dfas;
+ for (auto& nfa : nfas)
+ dfas.append(ContentExtensions::NFAToDFA::convert(nfa));
+ EXPECT_EQ(dfas.size(), 1ull);
+
+ Vector<ContentExtensions::DFABytecode> combinedBytecode;
+ for (const auto& dfa : dfas) {
+ Vector<ContentExtensions::DFABytecode> bytecode;
+ ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode);
+ compiler.compile();
+ combinedBytecode.appendVector(bytecode);
+ }
+
+ ContentExtensions::DFABytecodeInterpreter interpreter(&combinedBytecode[0], combinedBytecode.size());
+
+ patternId = 0;
+ for (char c1 = 'A'; c1 <= 'Z'; ++c1) {
+ for (char c2 = 'A'; c2 <= 'Z'; ++c2) {
+ for (char c3 = 'A'; c3 <= 'Z'; ++c3) {
+ for (char c4 = 'A'; c4 <= 'C'; ++c4) {
+ StringBuilder pattern;
+ pattern.append(c1);
+ pattern.append(c2);
+ pattern.append(c3);
+ // Test different jumping patterns distributed throughout the DFA:
+ switch ((c1 + c2 + c3 + c4) % 4) {
+ case 0:
+ // This should not match.
+ pattern.append('x');
+ pattern.append(c4);
+ break;
+ case 1:
+ // This should jump back to the root, then match.
+ pattern.append('x');
+ pattern.append(c1);
+ pattern.append(c2);
+ pattern.append(c3);
+ pattern.append(c4);
+ break;
+ case 2:
+ // This should match at the end of the string.
+ pattern.append(c4);
+ break;
+ case 3:
+ // This should match then jump back to the root.
+ pattern.append(c4);
+ pattern.append('x');
+ break;
+ }
+ auto matches = interpreter.interpret(pattern.toString().utf8(), 0);
+ switch ((c1 + c2 + c3 + c4) % 4) {
+ case 0:
+ compareContents(matches, { });
+ break;
+ case 1:
+ case 2:
+ case 3:
+ compareContents(matches, {patternId});
+ break;
+ }
+ patternId++;
+ }
+ }
+ }
+ }
+
+ compareContents(interpreter.interpret("CAAAAx", 0), {expectedIndex('C', 4), expectedIndex('A', 1)});
+ compareContents(interpreter.interpret("KAAAAx", 0), {expectedIndex('K', 4), expectedIndex('A', 1)});
+ compareContents(interpreter.interpret("AKAAAx", 0), {expectedIndex('K', 3), expectedIndex('K', 4)});
+ compareContents(interpreter.interpret("AKxAAAAx", 0), {expectedIndex('A', 1)});
+ compareContents(interpreter.interpret("AKAxAAAAx", 0), {expectedIndex('A', 1)});
+ compareContents(interpreter.interpret("AKAxZKAxZKZxAAAAx", 0), {expectedIndex('A', 1)});
+ compareContents(interpreter.interpret("ZAAAA", 0), {expectedIndex('Z', 4), expectedIndex('A', 1)});
+ compareContents(interpreter.interpret("ZZxZAAAB", 0), {expectedIndex('Z', 4), expectedIndex('B', 1)});
+#endif
+}
+
+TEST_F(ContentExtensionTest, DeepNFA)
+{
+ const unsigned size = 100000;
+
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+
+ // FIXME: DFAToNFA::convert takes way too long on these deep NFAs. We should optimize for that case.
+
+ StringBuilder lotsOfAs;
+ for (unsigned i = 0; i < size; ++i)
+ lotsOfAs.append('A');
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern(lotsOfAs.toString().utf8().data(), false, 0));
+
+ // FIXME: Yarr ought to be able to handle 2MB regular expressions.
+ StringBuilder tooManyAs;
+ for (unsigned i = 0; i < size * 20; ++i)
+ tooManyAs.append('A');
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::YarrError, parser.addPattern(tooManyAs.toString().utf8().data(), false, 0));
+
+ StringBuilder nestedGroups;
+ for (unsigned i = 0; i < size; ++i)
+ nestedGroups.append('(');
+ for (unsigned i = 0; i < size; ++i)
+ nestedGroups.append("B)");
+ // FIXME: Add nestedGroups. Right now it also takes too long. It should be optimized.
+
+ // This should not crash and not timeout.
+ EXPECT_EQ(1ul, createNFAs(combinedURLFilters).size());
+}
+
+void checkCompilerError(const char* json, std::error_code expectedError)
+{
+ CompiledContentExtensionData extensionData;
+ InMemoryContentExtensionCompilationClient client(extensionData);
+ std::error_code compilerError = ContentExtensions::compileRuleList(client, json);
+ EXPECT_EQ(compilerError.value(), expectedError.value());
+ if (compilerError.value())
+ EXPECT_STREQ(compilerError.category().name(), expectedError.category().name());
+}
+
+TEST_F(ContentExtensionTest, MatchesEverything)
+{
+ // Only css-display-none rules with triggers that match everything, no domain rules, and no flags
+ // should go in the global display:none stylesheet. css-display-none rules with domain rules or flags
+ // are applied separately on pages where they apply.
+ auto backend1 = makeBackend("[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\"}}]");
+ EXPECT_TRUE(nullptr != backend1.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
+ testRequest(backend1, mainDocumentRequest("http://webkit.org"), { }); // Selector is in global stylesheet.
+
+ auto backend2 = makeBackend("[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\",\"if-domain\":[\"webkit.org\"]}}]");
+ EXPECT_EQ(nullptr, backend2.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
+ testRequest(backend2, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(backend2, mainDocumentRequest("http://w3c.org"), { });
+
+ auto backend3 = makeBackend("[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\",\"unless-domain\":[\"webkit.org\"]}}]");
+ EXPECT_EQ(nullptr, backend3.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
+ testRequest(backend3, mainDocumentRequest("http://webkit.org"), { });
+ testRequest(backend3, mainDocumentRequest("http://w3c.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+
+ auto backend4 = makeBackend("[{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\",\"load-type\":[\"third-party\"]}}]");
+ EXPECT_EQ(nullptr, backend4.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
+ testRequest(backend4, mainDocumentRequest("http://webkit.org"), { });
+ testRequest(backend4, subResourceRequest("http://not_webkit.org", "http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+
+ // css-display-none rules after ignore-previous-rules should not be put in the default stylesheet.
+ auto backend5 = makeBackend("[{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\".*\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\"}}]");
+ EXPECT_EQ(nullptr, backend5.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
+ testRequest(backend5, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::CSSDisplayNoneSelector }, true);
+
+ auto backend6 = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*\",\"if-domain\":[\"webkit.org\",\"*w3c.org\"],\"resource-type\":[\"document\",\"script\"]}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"ignore\",\"if-domain\":[\"*webkit.org\",\"w3c.org\"]}},"
+ "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\".*\",\"unless-domain\":[\"webkit.org\",\"whatwg.org\"],\"resource-type\":[\"script\",\"image\"],\"load-type\":[\"third-party\"]}}]");
+ EXPECT_EQ(nullptr, backend6.globalDisplayNoneStyleSheet(ASCIILiteral("testFilter")));
+ testRequest(backend6, mainDocumentRequest("http://webkit.org"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend6, mainDocumentRequest("http://w3c.org"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend6, mainDocumentRequest("http://whatwg.org"), { });
+ testRequest(backend6, mainDocumentRequest("http://sub.webkit.org"), { });
+ testRequest(backend6, mainDocumentRequest("http://sub.w3c.org"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend6, mainDocumentRequest("http://sub.whatwg.org"), { });
+ testRequest(backend6, mainDocumentRequest("http://webkit.org/ignore"), { }, true);
+ testRequest(backend6, mainDocumentRequest("http://w3c.org/ignore"), { }, true);
+ testRequest(backend6, mainDocumentRequest("http://whatwg.org/ignore"), { });
+ testRequest(backend6, mainDocumentRequest("http://sub.webkit.org/ignore"), { }, true);
+ testRequest(backend6, mainDocumentRequest("http://sub.w3c.org/ignore"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend6, mainDocumentRequest("http://sub.whatwg.org/ignore"), { });
+ testRequest(backend6, subResourceRequest("http://example.com/image.png", "http://webkit.org/", ResourceType::Image), { });
+ testRequest(backend6, subResourceRequest("http://example.com/image.png", "http://w3c.org/", ResourceType::Image), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend6, subResourceRequest("http://example.com/doc.html", "http://webkit.org/", ResourceType::Document), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend6, subResourceRequest("http://example.com/script.js", "http://webkit.org/", ResourceType::Script), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend6, subResourceRequest("http://example.com/script.js", "http://w3c.org/", ResourceType::Script), { ContentExtensions::ActionType::BlockCookies, ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend6, subResourceRequest("http://example.com/script.js", "http://example.com/", ResourceType::Script), { });
+ testRequest(backend6, subResourceRequest("http://example.com/ignore/image.png", "http://webkit.org/", ResourceType::Image), { }, true);
+ testRequest(backend6, subResourceRequest("http://example.com/ignore/image.png", "http://example.com/", ResourceType::Image), { });
+ testRequest(backend6, subResourceRequest("http://example.com/ignore/image.png", "http://example.org/", ResourceType::Image), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend6, subResourceRequest("http://example.com/doc.html", "http://example.org/", ResourceType::Document), { });
+ testRequest(backend6, subResourceRequest("http://example.com/", "http://example.com/", ResourceType::Font), { });
+ testRequest(backend6, subResourceRequest("http://example.com/ignore", "http://webkit.org/", ResourceType::Image), { }, true);
+ testRequest(backend6, subResourceRequest("http://example.com/ignore", "http://webkit.org/", ResourceType::Font), { }, true);
+ testRequest(backend6, subResourceRequest("http://example.com/", "http://example.com/", ResourceType::Script), { });
+ testRequest(backend6, subResourceRequest("http://example.com/ignore", "http://example.com/", ResourceType::Script), { });
+}
+
+TEST_F(ContentExtensionTest, InvalidJSON)
+{
+ checkCompilerError("[", ContentExtensions::ContentExtensionError::JSONInvalid);
+ checkCompilerError("123", ContentExtensions::ContentExtensionError::JSONTopLevelStructureNotAnObject);
+ checkCompilerError("{}", ContentExtensions::ContentExtensionError::JSONTopLevelStructureNotAnArray);
+ // FIXME: Add unit test for JSONInvalidRule if that is possible to hit.
+ checkCompilerError("[]", ContentExtensions::ContentExtensionError::JSONContainsNoRules);
+
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":5}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTrigger);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"\"}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidURLFilterInTrigger);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":{}}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidURLFilterInTrigger);
+
+ // FIXME: Add unit test for JSONInvalidObjectInTriggerFlagsArray if that is possible to hit.
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":{}}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":[\"invalid\"]}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidStringInTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":[5]}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidStringInTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":5}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":\"first-party\"}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":null}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"load-type\":false}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":{}}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":[\"invalid\"]}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidStringInTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":[5]}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidStringInTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":5}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":\"document\"}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":null}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"resource-type\":false}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidTriggerFlagsArray);
+
+ StringBuilder rules;
+ rules.append("[");
+ for (unsigned i = 0; i < 49999; ++i)
+ rules.append("{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"a\"}},");
+ String rules50000 = rules.toString();
+ String rules50001 = rules.toString();
+ rules50000.append("{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"a\"}}]");
+ rules50001.append("{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"a\"}},{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"a\"}}]");
+ checkCompilerError(rules50000.utf8().data(), { });
+ checkCompilerError(rules50001.utf8().data(), ContentExtensions::ContentExtensionError::JSONTooManyRules);
+
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":{}}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[5]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[\"a\"]}}]", { });
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":\"a\"}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":false}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":null}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":{}}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[5]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[\"\"]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":\"a\"}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":null}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":false}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[\"A\"]}}]", ContentExtensions::ContentExtensionError::JSONDomainNotLowerCaseASCII);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[\"\\u00DC\"]}}]", ContentExtensions::ContentExtensionError::JSONDomainNotLowerCaseASCII);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[\"0\"]}}]", { });
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[\"a\"]}}]", { });
+
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[],\"unless-domain\":[\"a\"]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":[]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":5}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"unless-domain\":5}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":5,\"unless-domain\":5}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[]}}]", ContentExtensions::ContentExtensionError::JSONInvalidDomainList);
+
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[\"a\"],\"unless-domain\":[]}}]", ContentExtensions::ContentExtensionError::JSONUnlessAndIfDomain);
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\",\"if-domain\":[\"a\"],\"unless-domain\":[\"a\"]}}]", ContentExtensions::ContentExtensionError::JSONUnlessAndIfDomain);
+
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"webkit.org\", \"unexpected-identifier-should-be-ignored\":5}}]", { });
+
+ checkCompilerError("[{\"action\":5,\"trigger\":{\"url-filter\":\"webkit.org\"}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidAction);
+ checkCompilerError("[{\"action\":{\"type\":\"invalid\"},\"trigger\":{\"url-filter\":\"webkit.org\"}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidActionType);
+ checkCompilerError("[{\"action\":{\"type\":\"css-display-none\"},\"trigger\":{\"url-filter\":\"webkit.org\"}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidCSSDisplayNoneActionType);
+
+ checkCompilerError("[{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"webkit.org\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\".*\"}}]", { });
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*\",\"if-domain\":[\"a\"]}}]", { });
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*\",\"unless-domain\":[\"a\"]}}]", { });
+ checkCompilerError("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[\"}}]",
+ ContentExtensions::ContentExtensionError::JSONInvalidRegex);
+}
+
+TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines1)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^.*foo\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"bar$\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[ab]+bang\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/foo"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("foo://webkit.org/bar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/bar"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bar://webkit.org/bar"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("abang://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bbang://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("cbang://webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/bang"), { });
+ testRequest(backend, mainDocumentRequest("bang://webkit.org/"), { });
+}
+
+TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines1Partitioning)
+{
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+
+ // Those two share a prefix.
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("^.*foo", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("bar$", false, 1));
+
+ // Not this one.
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("^[ab]+bang", false, 0));
+
+ EXPECT_EQ(2ul, createNFAs(combinedURLFilters).size());
+}
+
+TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines2)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^foo\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^.*[a-c]+bar\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^webkit:\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[a-c]+b+oom\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("foo://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("webkit://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("http://bar.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://abar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://bbar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://cbar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://abcbar.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://dbar.org/"), { });
+}
+
+TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines2Partitioning)
+{
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("^foo", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("^.*[a-c]+bar", false, 1));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("^webkit:", false, 2));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("[a-c]+b+oom", false, 3));
+
+ // "^foo" and "^webkit:" can be grouped, the other two have a variable prefix.
+ EXPECT_EQ(3ul, createNFAs(combinedURLFilters).size());
+}
+
+TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines3)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"A*D\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"A*BA+\"}},"
+ "{\"action\":{\"type\":\"make-https\"},\"trigger\":{\"url-filter\":\"A*BC\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/D"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/AAD"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/AB"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ABA"), { }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ABAD"), { }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/BC"), { ContentExtensions::ActionType::MakeHTTPS });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ABC"), { ContentExtensions::ActionType::MakeHTTPS });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ABABC"), { ContentExtensions::ActionType::MakeHTTPS }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ABABCAD"), { ContentExtensions::ActionType::MakeHTTPS }, true);
+ testRequest(backend, mainDocumentRequest("http://webkit.org/ABCAD"), { ContentExtensions::ActionType::MakeHTTPS, ContentExtensions::ActionType::BlockLoad });
+}
+
+TEST_F(ContentExtensionTest, StrictPrefixSeparatedMachines3Partitioning)
+{
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A*D", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A*BA+", false, 1));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A*BC", false, 2));
+
+ // "A*A" and "A*BC" can be grouped, "A*BA+" should not.
+ EXPECT_EQ(2ul, createNFAs(combinedURLFilters).size());
+}
+
+TEST_F(ContentExtensionTest, SplittingLargeNFAs)
+{
+ const size_t expectedNFACounts[16] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1};
+
+ for (size_t i = 0; i < 16; i++) {
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A+BBB", false, 1));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A+CCC", false, 2));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("A+DDD", false, 2));
+
+ Vector<ContentExtensions::NFA> nfas;
+ combinedURLFilters.processNFAs(i, [&](ContentExtensions::NFA&& nfa) {
+ nfas.append(WTFMove(nfa));
+ });
+ EXPECT_EQ(nfas.size(), expectedNFACounts[i]);
+
+ Vector<ContentExtensions::DFA> dfas;
+ for (auto& nfa : nfas)
+ dfas.append(ContentExtensions::NFAToDFA::convert(nfa));
+
+ Vector<ContentExtensions::DFABytecode> combinedBytecode;
+ for (const auto& dfa : dfas) {
+ Vector<ContentExtensions::DFABytecode> bytecode;
+ ContentExtensions::DFABytecodeCompiler compiler(dfa, bytecode);
+ compiler.compile();
+ combinedBytecode.appendVector(bytecode);
+ }
+
+ ContentExtensions::DFABytecodeInterpreter interpreter(&combinedBytecode[0], combinedBytecode.size());
+
+ EXPECT_EQ(interpreter.interpret("ABBBX", 0).size(), 1ull);
+ EXPECT_EQ(interpreter.interpret("ACCCX", 0).size(), 1ull);
+ EXPECT_EQ(interpreter.interpret("ADDDX", 0).size(), 1ull);
+ EXPECT_EQ(interpreter.interpret("XBBBX", 0).size(), 0ull);
+ EXPECT_EQ(interpreter.interpret("ABBX", 0).size(), 0ull);
+ EXPECT_EQ(interpreter.interpret("ACCX", 0).size(), 0ull);
+ EXPECT_EQ(interpreter.interpret("ADDX", 0).size(), 0ull);
+ }
+}
+
+TEST_F(ContentExtensionTest, QuantifierInGroup)
+{
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A+)B)C)", false, 0));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A)B+)C)", false, 1));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A)B+)C)D", false, 2));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A)B)C+)", false, 3));
+ EXPECT_EQ(ContentExtensions::URLFilterParser::ParseStatus::Ok, parser.addPattern("(((A)B)C)", false, 4));
+
+ // (((A)B+)C) and (((A)B+)C)D should be in the same NFA.
+ EXPECT_EQ(4ul, createNFAs(combinedURLFilters).size());
+}
+
+static void testPatternStatus(String pattern, ContentExtensions::URLFilterParser::ParseStatus status)
+{
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+ EXPECT_EQ(status, parser.addPattern(pattern, false, 0));
+}
+
+TEST_F(ContentExtensionTest, ParsingFailures)
+{
+ testPatternStatus("a*b?.*.?[a-z]?[a-z]*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("a*b?.*.?[a-z]?[a-z]+", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("a*b?.*.?[a-z]?[a-z]", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus(".*?a", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus(".*a", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+
+ testPatternStatus("(?!)", ContentExtensions::URLFilterParser::ParseStatus::Group);
+ testPatternStatus("(?=)", ContentExtensions::URLFilterParser::ParseStatus::Group);
+ testPatternStatus("(?!a)", ContentExtensions::URLFilterParser::ParseStatus::Group);
+ testPatternStatus("(?=a)", ContentExtensions::URLFilterParser::ParseStatus::Group);
+ testPatternStatus("(regex)", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("(regex", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
+ testPatternStatus("((regex)", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
+ testPatternStatus("(?:regex)", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("(?:regex", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
+ testPatternStatus("[^.]+", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+
+ testPatternStatus("a++", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
+ testPatternStatus("[a]++", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
+ testPatternStatus("+", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
+
+ testPatternStatus("[", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
+ testPatternStatus("[a}", ContentExtensions::URLFilterParser::ParseStatus::YarrError);
+
+ // FIXME: Look into why these do not cause YARR parsing errors. They probably should.
+ testPatternStatus("a]", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("{", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("{[a]", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("{0", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("{0,", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("{0,1", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("a{0,1", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("a{a,b}", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+
+ const char nonASCII[2] = {-1, '\0'};
+ testPatternStatus(nonASCII, ContentExtensions::URLFilterParser::ParseStatus::NonASCII);
+ testPatternStatus("\\xff", ContentExtensions::URLFilterParser::ParseStatus::NonASCII);
+
+ testPatternStatus("\\x\\r\\n", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("\\b", ContentExtensions::URLFilterParser::ParseStatus::WordBoundary);
+ testPatternStatus("[\\d]", ContentExtensions::URLFilterParser::ParseStatus::AtomCharacter);
+ testPatternStatus("\\d\\D\\w\\s\\v\\h\\i\\c", ContentExtensions::URLFilterParser::ParseStatus::UnsupportedCharacterClass);
+
+ testPatternStatus("this|that", ContentExtensions::URLFilterParser::ParseStatus::Disjunction);
+ testPatternStatus("a{0,1}b", ContentExtensions::URLFilterParser::ParseStatus::Ok);
+ testPatternStatus("a{0,2}b", ContentExtensions::URLFilterParser::ParseStatus::InvalidQuantifier);
+ testPatternStatus("", ContentExtensions::URLFilterParser::ParseStatus::EmptyPattern);
+ testPatternStatus("$$", ContentExtensions::URLFilterParser::ParseStatus::MisplacedEndOfLine);
+ testPatternStatus("a^", ContentExtensions::URLFilterParser::ParseStatus::MisplacedStartOfLine);
+ testPatternStatus("(^)", ContentExtensions::URLFilterParser::ParseStatus::MisplacedStartOfLine);
+
+ testPatternStatus("(a)\\1", ContentExtensions::URLFilterParser::ParseStatus::Ok); // This should be BackReference, right?
+}
+
+TEST_F(ContentExtensionTest, PatternMatchingTheEmptyString)
+{
+ // Simple atoms.
+ testPatternStatus(".*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("a*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus(".?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("a?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+
+ // Character sets.
+ testPatternStatus("[a-z]*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("[a-z]?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+
+ // Groups.
+ testPatternStatus("(foobar)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("(foobar)?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("(.*)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("(a*)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("(.?)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("(a?)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("([a-z]*)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("([a-z]?)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+
+ testPatternStatus("(.)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("(.+)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("(.?)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("(.*)*", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("(.+)?", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+ testPatternStatus("(.?)+", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+
+ // Nested groups.
+ testPatternStatus("((foo)?((.)*)(bar)*)", ContentExtensions::URLFilterParser::ParseStatus::MatchesEverything);
+}
+
+TEST_F(ContentExtensionTest, MinimizingWithMoreFinalStatesThanNonFinalStates)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^h[a-z://]+\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://foo.com/\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://bar.com/\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://foo.com/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("http://bar.com/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("attp://foo.com/"), { });
+ testRequest(backend, mainDocumentRequest("attp://bar.com/"), { });
+
+ testRequest(backend, mainDocumentRequest("http://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bttp://webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("bttps://webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("http://webkit.org/b"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://webkit.org/b"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("cttp://webkit.org/B"), { });
+ testRequest(backend, mainDocumentRequest("cttps://webkit.org/B"), { });
+}
+
+TEST_F(ContentExtensionTest, StatesWithDifferentActionsAreNotUnified1)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://www.webkit.org/\"}},"
+ "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"^https://www.webkit.org/\"}},"
+ "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"^attps://www.webkit.org/\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://www.webkit.org/"), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("attps://www.webkit.org/"), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://www.webkit.org/a"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://www.webkit.org/B"), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("attps://www.webkit.org/c"), { ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("http://www.whatwg.org/"), { });
+ testRequest(backend, mainDocumentRequest("https://www.whatwg.org/"), { });
+ testRequest(backend, mainDocumentRequest("attps://www.whatwg.org/"), { });
+}
+
+TEST_F(ContentExtensionTest, StatesWithDifferentActionsAreNotUnified2)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^http://www.webkit.org/\"}},"
+ "{\"action\":{\"type\":\"block-cookies\"},\"trigger\":{\"url-filter\":\"^https://www.webkit.org/\"}},"
+ "{\"action\":{\"type\":\"css-display-none\", \"selector\":\"#foo\"},\"trigger\":{\"url-filter\":\"^https://www.webkit.org/\"}}]");
+
+ testRequest(backend, mainDocumentRequest("http://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("https://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockCookies });
+ testRequest(backend, mainDocumentRequest("https://www.whatwg.org/"), { });
+ testRequest(backend, mainDocumentRequest("attps://www.whatwg.org/"), { });
+}
+
+// The order in which transitions from the root will be processed is unpredictable.
+// To exercises the various options, this test exists in various version exchanging the transition to the final state.
+TEST_F(ContentExtensionTest, FallbackTransitionsWithDifferentiatorDoNotMerge1)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.a\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.a\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bac\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bbc\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^BCC\"}}]");
+
+ testRequest(backend, mainDocumentRequest("aza://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bac://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bbc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bcc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("aac://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("abc://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("acc://www.webkit.org/"), { });
+
+ testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
+}
+TEST_F(ContentExtensionTest, FallbackTransitionsWithDifferentiatorDoNotMerge2)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bac\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bbc\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^BCC\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.a\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.a\"}}]");
+
+ testRequest(backend, mainDocumentRequest("aza://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bac://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bbc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bcc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("aac://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("abc://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("acc://www.webkit.org/"), { });
+
+ testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { });
+}
+TEST_F(ContentExtensionTest, FallbackTransitionsWithDifferentiatorDoNotMerge3)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.c\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.c\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^baa\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bba\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^BCA\"}}]");
+
+ testRequest(backend, mainDocumentRequest("azc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("baa://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bba://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bca://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("aaa://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("aba://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("aca://www.webkit.org/"), { });
+
+ testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
+}
+TEST_F(ContentExtensionTest, FallbackTransitionsWithDifferentiatorDoNotMerge4)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^baa\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^bba\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^BCA\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.c\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.c\"}}]");
+
+ testRequest(backend, mainDocumentRequest("azc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bzc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("baa://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bba://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bca://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("aaa://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("aba://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("aca://www.webkit.org/"), { });
+
+ testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("bza://www.webkit.org/"), { });
+}
+
+TEST_F(ContentExtensionTest, FallbackTransitionsToOtherNodeInSameGroupDoesNotDifferentiateGroup)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^aac\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.c\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^b.c\"}}]");
+
+ testRequest(backend, mainDocumentRequest("aac://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("abc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("bac://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("abc://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("aaa://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("aca://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("baa://www.webkit.org/"), { });
+}
+
+TEST_F(ContentExtensionTest, SimpleFallBackTransitionDifferentiator1)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.bc.de\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^a.bd.ef\"}}]");
+
+ testRequest(backend, mainDocumentRequest("abbccde://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("aabcdde://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("aabddef://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("aabddef://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("abcde://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("abdef://www.webkit.org/"), { });
+}
+
+TEST_F(ContentExtensionTest, SimpleFallBackTransitionDifferentiator2)
+{
+ auto backend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^cb.\"}},"
+ "{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^db.b\"}}]");
+
+ testRequest(backend, mainDocumentRequest("cba://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("cbb://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("dbab://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(backend, mainDocumentRequest("dbxb://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+
+ testRequest(backend, mainDocumentRequest("cca://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("dddd://www.webkit.org/"), { });
+ testRequest(backend, mainDocumentRequest("bbbb://www.webkit.org/"), { });
+}
+
+// *** We have the following ranges intersections: ***
+// Full overlap.
+// 1)
+// A: |-----|
+// B: |---|
+// 2)
+// A: |-----|
+// B: |
+// 3)
+// A: |---|
+// B: |-----|
+// 4)
+// A: |
+// B: |-----|
+// One edge in common
+// 5)
+// A: |-|
+// B: |-|
+// 6)
+// A: |
+// B: |-|
+// 7)
+// A: |-|
+// B: |
+// 8)
+// A: |-|
+// B: |-|
+// 9)
+// A: |
+// B: |-|
+// 10)
+// A: |-|
+// B: |
+// B overlap on the left side of A.
+// 11)
+// A: |---|
+// B: |---|
+// 12)
+// A: |---|
+// B: |-----|
+// A overlap on the left side of B
+// 13)
+// A: |---|
+// B: |---|
+// 14)
+// A: |-----|
+// B: |---|
+// Equal ranges
+// 15)
+// A: |---|
+// B: |---|
+// 16)
+// A: |
+// B: |
+
+TEST_F(ContentExtensionTest, RangeOverlapCase1)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[a-m]\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"^[c-e]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { }, true);
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { }, true);
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { }, true);
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[a-m]\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"[c-e]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { }, true);
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { }, true);
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { }, true);
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase2)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[a-m]\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"^b\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { }, true);
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[a-m]\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"l\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.k.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.l.xxx/"), { }, true);
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase3)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[b-d]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[a-m]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[b-d]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[a-m]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase4)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^l\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[a-m]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("k://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("l://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"l\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[a-m]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.k.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.l.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase5)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[a-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[e-h]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[a-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[e-h]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase6)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^e\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[e-h]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"e\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[e-h]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase7)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[a-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^e\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[a-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"e\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase8)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[e-h]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[a-e]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[e-h]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[a-e]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase9)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^e\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[a-e]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"e\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[a-e]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase10)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[e-h]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^e\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[e-h]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"e\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase11)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[e-g]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[d-f]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[e-g]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[d-f]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
+}
+
+
+TEST_F(ContentExtensionTest, RangeOverlapCase12)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[e-g]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[d-g]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[e-g]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[d-g]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase13)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[b-d]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[c-e]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[b-d]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[c-e]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase14)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[b-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[c-e]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[b-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[c-e]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase15)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^[c-f]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^[c-f]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[c-f]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[c-f]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, RangeOverlapCase16)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^c\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^c\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"c\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"c\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, QuantifiedOneOrMoreRangesCase11And13)
+{
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"[c-e]+[g-i]+YYY\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[b-d]+[h-j]+YYY\"}}]");
+
+ // The interesting ranges only match between 'b' and 'k', plus a gap in 'f'.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.abyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.acyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.adyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aeyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.afyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.agyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ahyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aiyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ajyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.akyyy.xxx/"), { });
+
+ // 'b' is the first character of the second rule.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.byyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bbyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bcyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bdyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.beyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bfyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bgyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.biyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bkyyy.xxx/"), { });
+
+ // 'c' is the first character of the first rule, and it overlaps the first character of the second rule.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cbyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ccyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cdyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ceyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cfyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.chyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ciyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ckyyy.xxx/"), { });
+
+ // 'd' is in the first range of both rule. This series cover overlaps between the two rules.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.degyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dehyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dfgyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dfhyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.djyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+}
+
+TEST_F(ContentExtensionTest, QuantifiedOneOrMoreRangesCase11And13InGroups)
+{
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"([c-e])+([g-i]+YYY)\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"[b-d]+[h-j]+YYY\"}}]");
+
+ // The interesting ranges only match between 'b' and 'k', plus a gap in 'f'.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.abyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.acyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.adyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aeyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.afyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.agyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ahyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aiyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ajyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.akyyy.xxx/"), { });
+
+ // 'b' is the first character of the second rule.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.byyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bbyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bcyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bdyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.beyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bfyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bgyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.biyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bkyyy.xxx/"), { });
+
+ // 'c' is the first character of the first rule, and it overlaps the first character of the second rule.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cbyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ccyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cdyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ceyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cfyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.chyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ciyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ckyyy.xxx/"), { });
+
+ // 'd' is in the first range of both rule. This series cover overlaps between the two rules.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.degyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dehyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dfgyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dfhyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.djyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase1)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[a-m]\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"^(bar)*[c-e]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { }, true);
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { }, true);
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { }, true);
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[a-m]\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"(bar)*[c-e]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { }, true);
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { }, true);
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { }, true);
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
+}
+
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase2)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[a-m]\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"^(bar)*b\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { }, true);
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[a-m]\"}},"
+ "{\"action\":{\"type\":\"ignore-previous-rules\"},\"trigger\":{\"url-filter\":\"(bar)*l\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.k.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.l.xxx/"), { }, true);
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase3)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[b-d]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[a-m]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[b-d]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[a-m]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase4)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*l\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[a-m]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("k://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("l://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("m://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("n://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*l\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[a-m]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.k.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.l.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.m.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.n.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase5)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[a-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[e-h]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[a-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[e-h]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase6)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*e\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[e-h]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*e\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[e-h]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase7)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[a-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*e\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[a-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*e\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase8)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[e-h]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[a-e]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[e-h]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[a-e]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase9)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*e\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[a-e]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*e\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[a-e]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase10)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[e-h]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*e\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("i://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[e-h]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*e\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.i.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase11)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[e-g]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[d-f]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[e-g]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[d-f]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
+}
+
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase12)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[e-g]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[d-g]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[e-g]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[d-g]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase13)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[b-d]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[c-e]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[b-d]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[c-e]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase14)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[b-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[c-e]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("h://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[b-e]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[c-e]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.h.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase15)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*[c-f]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*[c-f]\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("f://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("g://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[c-f]\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[c-f]\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.f.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.g.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedRangeOverlapCase16)
+{
+ auto matchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"^(foo)*c\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"^(bar)*c\"}}]");
+
+ testRequest(matchBackend, mainDocumentRequest("a://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("b://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("c://www.webkit.org/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(matchBackend, mainDocumentRequest("d://www.webkit.org/"), { });
+ testRequest(matchBackend, mainDocumentRequest("e://www.webkit.org/"), { });
+
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*c\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*c\"}}]");
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.a.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.b.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.c.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.d.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.e.xxx/"), { });
+}
+
+TEST_F(ContentExtensionTest, CombinedQuantifiedOneOrMoreRangesCase11And13)
+{
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*[c-e]+[g-i]+YYY\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[b-d]+[h-j]+YYY\"}}]");
+
+ // The interesting ranges only match between 'b' and 'k', plus a gap in 'f'.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.abyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.acyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.adyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aeyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.afyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.agyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ahyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aiyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ajyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.akyyy.xxx/"), { });
+
+ // 'b' is the first character of the second rule.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.byyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bbyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bcyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bdyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.beyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bfyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bgyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.biyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bkyyy.xxx/"), { });
+
+ // 'c' is the first character of the first rule, and it overlaps the first character of the second rule.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cbyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ccyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cdyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ceyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cfyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.chyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ciyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ckyyy.xxx/"), { });
+
+ // 'd' is in the first range of both rule. This series cover overlaps between the two rules.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.degyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dehyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dfgyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dfhyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.djyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+}
+
+TEST_F(ContentExtensionTest, CombinedQuantifiedOneOrMoreRangesCase11And13InGroups)
+{
+ auto searchBackend = makeBackend("[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\"(foo)*([c-e])+([g-i]+YYY)\"}},"
+ "{\"action\":{\"type\":\"css-display-none\",\"selector\":\".hidden\"},\"trigger\":{\"url-filter\":\"(bar)*[b-d]+[h-j]+YYY\"}}]");
+
+ // The interesting ranges only match between 'b' and 'k', plus a gap in 'f'.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.abyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.acyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.adyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aeyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.afyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.agyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ahyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.aiyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ajyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.akyyy.xxx/"), { });
+
+ // 'b' is the first character of the second rule.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.byyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bbyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bcyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bdyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.beyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bfyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bgyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.biyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.bkyyy.xxx/"), { });
+
+ // 'c' is the first character of the first rule, and it overlaps the first character of the second rule.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cayyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cbyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ccyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cdyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ceyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cfyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.chyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ciyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.cjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ckyyy.xxx/"), { });
+
+ // 'd' is in the first range of both rule. This series cover overlaps between the two rules.
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddgyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddhhyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector, ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.degyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dehyyy.xxx/"), { ContentExtensions::ActionType::BlockLoad });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dfgyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.dfhyyy.xxx/"), { });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.djyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+ testRequest(searchBackend, mainDocumentRequest("zzz://www.ddjjyyy.xxx/"), { ContentExtensions::ActionType::CSSDisplayNoneSelector });
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/DFACombiner.cpp b/Tools/TestWebKitAPI/Tests/WebCore/DFACombiner.cpp
new file mode 100644
index 000000000..d53ebb75a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/DFACombiner.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include "DFAHelpers.h"
+#include <WebCore/DFACombiner.h>
+#include <wtf/MainThread.h>
+
+using namespace WebCore;
+using namespace ContentExtensions;
+
+namespace TestWebKitAPI {
+
+class DFACombinerTest : public testing::Test {
+public:
+ virtual void SetUp()
+ {
+ WTF::initializeMainThread();
+ }
+};
+
+Vector<DFA> combine(Vector<DFA> dfas, unsigned minimumSize)
+{
+ DFACombiner combiner;
+ for (DFA& dfa : dfas)
+ combiner.addDFA(WTFMove(dfa));
+
+ Vector<DFA> output;
+ combiner.combineDFAs(minimumSize, [&output](DFA&& dfa) {
+ output.append(dfa);
+ });
+ return output;
+}
+
+TEST_F(DFACombinerTest, Basic)
+{
+ Vector<DFA> dfas = { buildDFAFromPatterns({ "foo"}), buildDFAFromPatterns({ "bar"}) };
+ Vector<DFA> combinedDFAs = combine(dfas, 10000);
+ EXPECT_EQ(static_cast<size_t>(1), combinedDFAs.size());
+
+ DFA reference = buildDFAFromPatterns({ "foo", "bar"});
+ reference.minimize();
+ EXPECT_EQ(countLiveNodes(reference), countLiveNodes(combinedDFAs.first()));
+}
+
+
+TEST_F(DFACombinerTest, IdenticalDFAs)
+{
+ Vector<DFA> dfas = { buildDFAFromPatterns({ "foo"}), buildDFAFromPatterns({ "foo"}) };
+ Vector<DFA> combinedDFAs = combine(dfas, 10000);
+ EXPECT_EQ(static_cast<size_t>(1), combinedDFAs.size());
+
+ // The result should have the exact same size as the minimized input.
+ DFA reference = buildDFAFromPatterns({ "foo"});
+ reference.minimize();
+ EXPECT_EQ(countLiveNodes(reference), countLiveNodes(combinedDFAs.first()));
+}
+
+TEST_F(DFACombinerTest, NoInput)
+{
+ DFACombiner combiner;
+ unsigned counter = 0;
+ combiner.combineDFAs(100000, [&counter](DFA&& dfa) {
+ ++counter;
+ });
+ EXPECT_EQ(static_cast<unsigned>(0), counter);
+}
+
+TEST_F(DFACombinerTest, SingleInput)
+{
+ Vector<DFA> dfas = { buildDFAFromPatterns({ "WebKit"}) };
+ Vector<DFA> combinedDFAs = combine(dfas, 10000);
+ EXPECT_EQ(static_cast<size_t>(1), combinedDFAs.size());
+
+ DFA reference = buildDFAFromPatterns({ "WebKit"});
+ reference.minimize();
+ EXPECT_EQ(countLiveNodes(reference), countLiveNodes(combinedDFAs.first()));
+}
+
+TEST_F(DFACombinerTest, InputTooLargeForMinimumSize)
+{
+ Vector<DFA> dfas = { buildDFAFromPatterns({ "foo"}), buildDFAFromPatterns({ "bar"}) };
+ Vector<DFA> combinedDFAs = combine(dfas, 2);
+ EXPECT_EQ(static_cast<size_t>(2), combinedDFAs.size());
+ EXPECT_EQ(static_cast<size_t>(4), countLiveNodes(combinedDFAs[0]));
+ EXPECT_EQ(static_cast<size_t>(4), countLiveNodes(combinedDFAs[1]));
+}
+
+TEST_F(DFACombinerTest, CombinedInputReachesMinimumSize)
+{
+ Vector<DFA> dfas = { buildDFAFromPatterns({ "foo"}), buildDFAFromPatterns({ "bar"}), buildDFAFromPatterns({ "WebKit"}) };
+ Vector<DFA> combinedDFAs = combine(dfas, 5);
+ EXPECT_EQ(static_cast<size_t>(2), combinedDFAs.size());
+ EXPECT_EQ(static_cast<size_t>(7), countLiveNodes(combinedDFAs[0]));
+ EXPECT_EQ(static_cast<size_t>(6), countLiveNodes(combinedDFAs[1]));
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/DFAHelpers.h b/Tools/TestWebKitAPI/Tests/WebCore/DFAHelpers.h
new file mode 100644
index 000000000..8c6402760
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/DFAHelpers.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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.
+ */
+
+#include <WebCore/CombinedURLFilters.h>
+#include <WebCore/NFA.h>
+#include <WebCore/NFAToDFA.h>
+#include <WebCore/URLFilterParser.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+static unsigned countLiveNodes(const ContentExtensions::DFA& dfa)
+{
+ unsigned counter = 0;
+ for (const auto& node : dfa.nodes) {
+ if (!node.isKilled())
+ ++counter;
+ }
+ return counter;
+}
+
+static Vector<ContentExtensions::NFA> createNFAs(ContentExtensions::CombinedURLFilters& combinedURLFilters)
+{
+ Vector<ContentExtensions::NFA> nfas;
+
+ combinedURLFilters.processNFAs(std::numeric_limits<size_t>::max(), [&](ContentExtensions::NFA&& nfa) {
+ nfas.append(WTFMove(nfa));
+ });
+
+ return nfas;
+}
+
+static ContentExtensions::DFA buildDFAFromPatterns(Vector<const char*> patterns)
+{
+ ContentExtensions::CombinedURLFilters combinedURLFilters;
+ ContentExtensions::URLFilterParser parser(combinedURLFilters);
+
+ for (const char* pattern : patterns)
+ parser.addPattern(pattern, false, 0);
+ Vector<ContentExtensions::NFA> nfas = createNFAs(combinedURLFilters);
+ return ContentExtensions::NFAToDFA::convert(nfas[0]);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/DFAMinimizer.cpp b/Tools/TestWebKitAPI/Tests/WebCore/DFAMinimizer.cpp
new file mode 100644
index 000000000..bb3ac2e2a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/DFAMinimizer.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include "DFAHelpers.h"
+#include <wtf/MainThread.h>
+
+namespace TestWebKitAPI {
+
+class DFAMinimizerTest : public testing::Test {
+public:
+ virtual void SetUp()
+ {
+ WTF::initializeMainThread();
+ }
+};
+
+TEST_F(DFAMinimizerTest, BasicSearch)
+{
+ ContentExtensions::DFA dfa = buildDFAFromPatterns({ ".*foo", ".*bar", ".*bang"});
+ EXPECT_EQ(static_cast<size_t>(8), countLiveNodes(dfa));
+ dfa.minimize();
+ EXPECT_EQ(static_cast<size_t>(7), countLiveNodes(dfa));
+}
+
+TEST_F(DFAMinimizerTest, MergeSuffixes)
+{
+ ContentExtensions::DFA dfa = buildDFAFromPatterns({ ".*aaa", ".*aab", ".*aba", ".*abb", ".*baa", ".*bab", ".*bba", ".*bbb"});
+ EXPECT_EQ(static_cast<size_t>(12), countLiveNodes(dfa));
+ dfa.minimize();
+ EXPECT_EQ(static_cast<size_t>(4), countLiveNodes(dfa));
+}
+
+TEST_F(DFAMinimizerTest, MergeInfixes)
+{
+ ContentExtensions::DFA dfa = buildDFAFromPatterns({ ".*aaakit", ".*aabkit", ".*abakit", ".*abbkit", ".*baakit", ".*babkit", ".*bbakit", ".*bbbkit"});
+ EXPECT_EQ(static_cast<size_t>(15), countLiveNodes(dfa));
+ dfa.minimize();
+ EXPECT_EQ(static_cast<size_t>(7), countLiveNodes(dfa));
+}
+
+TEST_F(DFAMinimizerTest, FallbackTransitionsWithDifferentiatorDoNotMerge1)
+{
+ ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^a.a", "^b.a", "^bac", "^bbc", "^BCC"});
+ EXPECT_EQ(static_cast<size_t>(6), countLiveNodes(dfa));
+ dfa.minimize();
+ EXPECT_EQ(static_cast<size_t>(6), countLiveNodes(dfa));
+}
+
+TEST_F(DFAMinimizerTest, FallbackTransitionsWithDifferentiatorDoNotMerge2)
+{
+ ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^bbc", "^BCC", "^a.a", "^b.a"});
+ EXPECT_EQ(static_cast<size_t>(6), countLiveNodes(dfa));
+ dfa.minimize();
+ EXPECT_EQ(static_cast<size_t>(6), countLiveNodes(dfa));
+}
+
+TEST_F(DFAMinimizerTest, FallbackTransitionsWithDifferentiatorDoNotMerge3)
+{
+ ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^a.c", "^b.c", "^baa", "^bba", "^BCA"});
+ EXPECT_EQ(static_cast<size_t>(6), countLiveNodes(dfa));
+ dfa.minimize();
+ EXPECT_EQ(static_cast<size_t>(6), countLiveNodes(dfa));
+}
+
+TEST_F(DFAMinimizerTest, FallbackTransitionsWithDifferentiatorDoNotMerge4)
+{
+ ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^baa", "^bba", "^BCA", "^a.c", "^b.c"});
+ EXPECT_EQ(static_cast<size_t>(6), countLiveNodes(dfa));
+ dfa.minimize();
+ EXPECT_EQ(static_cast<size_t>(6), countLiveNodes(dfa));
+}
+
+TEST_F(DFAMinimizerTest, FallbackTransitionsToOtherNodeInSameGroupDoesNotDifferentiateGroup)
+{
+ ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^aac", "^a.c", "^b.c"});
+ EXPECT_EQ(static_cast<size_t>(5), countLiveNodes(dfa));
+ dfa.minimize();
+ EXPECT_EQ(static_cast<size_t>(4), countLiveNodes(dfa));
+}
+
+TEST_F(DFAMinimizerTest, SimpleFallBackTransitionDifferentiator1)
+{
+ ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^a.bc.de", "^a.bd.ef"});
+ EXPECT_EQ(static_cast<size_t>(11), countLiveNodes(dfa));
+ dfa.minimize();
+ EXPECT_EQ(static_cast<size_t>(11), countLiveNodes(dfa));
+}
+
+TEST_F(DFAMinimizerTest, SimpleFallBackTransitionDifferentiator2)
+{
+ ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^cb.", "^db.b"});
+ EXPECT_EQ(static_cast<size_t>(7), countLiveNodes(dfa));
+ dfa.minimize();
+ EXPECT_EQ(static_cast<size_t>(7), countLiveNodes(dfa));
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/ExtendedColor.cpp b/Tools/TestWebKitAPI/Tests/WebCore/ExtendedColor.cpp
new file mode 100644
index 000000000..607777dc8
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/ExtendedColor.cpp
@@ -0,0 +1,162 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include "Test.h"
+#include "WTFStringUtilities.h"
+#include <WebCore/Color.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+TEST(ExtendedColor, Constructor)
+{
+ Color c1(1.0, 0.5, 0.25, 1.0, ColorSpaceDisplayP3);
+ EXPECT_TRUE(c1.isExtended());
+ EXPECT_FLOAT_EQ(1.0, c1.asExtended().red());
+ EXPECT_FLOAT_EQ(0.5, c1.asExtended().green());
+ EXPECT_FLOAT_EQ(0.25, c1.asExtended().blue());
+ EXPECT_FLOAT_EQ(1.0, c1.asExtended().alpha());
+ EXPECT_EQ(1u, c1.asExtended().refCount());
+ EXPECT_EQ(c1.cssText(), "color(display-p3 1 0.5 0.25)");
+}
+
+TEST(ExtendedColor, CopyConstructor)
+{
+ Color c1(1.0, 0.5, 0.25, 1.0, ColorSpaceDisplayP3);
+ EXPECT_TRUE(c1.isExtended());
+
+ Color c2(c1);
+
+ EXPECT_FLOAT_EQ(1.0, c2.asExtended().red());
+ EXPECT_FLOAT_EQ(0.5, c2.asExtended().green());
+ EXPECT_FLOAT_EQ(0.25, c2.asExtended().blue());
+ EXPECT_FLOAT_EQ(1.0, c2.asExtended().alpha());
+ EXPECT_EQ(2u, c1.asExtended().refCount());
+ EXPECT_EQ(2u, c2.asExtended().refCount());
+ EXPECT_EQ(c2.cssText(), "color(display-p3 1 0.5 0.25)");
+}
+
+TEST(ExtendedColor, Assignment)
+{
+ Color c1(1.0, 0.5, 0.25, 1.0, ColorSpaceDisplayP3);
+ EXPECT_TRUE(c1.isExtended());
+
+ Color c2 = c1;
+
+ EXPECT_FLOAT_EQ(1.0, c2.asExtended().red());
+ EXPECT_FLOAT_EQ(0.5, c2.asExtended().green());
+ EXPECT_FLOAT_EQ(0.25, c2.asExtended().blue());
+ EXPECT_FLOAT_EQ(1.0, c2.asExtended().alpha());
+ EXPECT_EQ(2u, c1.asExtended().refCount());
+ EXPECT_EQ(2u, c2.asExtended().refCount());
+ EXPECT_EQ(c2.cssText(), "color(display-p3 1 0.5 0.25)");
+}
+
+TEST(ExtendedColor, MoveConstructor)
+{
+ Color c1(1.0, 0.5, 0.25, 1.0, ColorSpaceDisplayP3);
+ EXPECT_TRUE(c1.isExtended());
+
+ Color c2(WTFMove(c1));
+ // We should have moved the extended color pointer into c2,
+ // and set c1 to invalid so that it doesn't cause deletion.
+ EXPECT_FALSE(c1.isExtended());
+ EXPECT_FALSE(c1.isValid());
+
+ EXPECT_FLOAT_EQ(1.0, c2.asExtended().red());
+ EXPECT_FLOAT_EQ(0.5, c2.asExtended().green());
+ EXPECT_FLOAT_EQ(0.25, c2.asExtended().blue());
+ EXPECT_FLOAT_EQ(1.0, c2.asExtended().alpha());
+ EXPECT_EQ(1u, c2.asExtended().refCount());
+ EXPECT_EQ(c2.cssText(), "color(display-p3 1 0.5 0.25)");
+}
+
+TEST(ExtendedColor, MoveAssignment)
+{
+ Color c1(1.0, 0.5, 0.25, 1.0, ColorSpaceDisplayP3);
+ EXPECT_TRUE(c1.isExtended());
+
+ Color c2 = WTFMove(c1);
+
+ // We should have moved the extended color pointer into c2,
+ // and set c1 to invalid so that it doesn't cause deletion.
+ EXPECT_FALSE(c1.isExtended());
+ EXPECT_FALSE(c1.isValid());
+
+ EXPECT_FLOAT_EQ(1.0, c2.asExtended().red());
+ EXPECT_FLOAT_EQ(0.5, c2.asExtended().green());
+ EXPECT_FLOAT_EQ(0.25, c2.asExtended().blue());
+ EXPECT_FLOAT_EQ(1.0, c2.asExtended().alpha());
+ EXPECT_EQ(1u, c2.asExtended().refCount());
+ EXPECT_EQ(c2.cssText(), "color(display-p3 1 0.5 0.25)");
+}
+
+TEST(ExtendedColor, BasicReferenceCounting)
+{
+ Color* c1 = new Color(1.0, 0.5, 0.25, 1.0, ColorSpaceDisplayP3);
+ EXPECT_TRUE(c1->isExtended());
+
+ Color* c2 = new Color(*c1);
+ Color* c3 = new Color(*c2);
+
+ EXPECT_FLOAT_EQ(1.0, c2->asExtended().red());
+ EXPECT_FLOAT_EQ(0.5, c2->asExtended().green());
+ EXPECT_FLOAT_EQ(0.25, c2->asExtended().blue());
+ EXPECT_FLOAT_EQ(1.0, c2->asExtended().alpha());
+ EXPECT_EQ(3u, c2->asExtended().refCount());
+ EXPECT_EQ(c2->cssText(), "color(display-p3 1 0.5 0.25)");
+
+ delete c1;
+ EXPECT_EQ(2u, c2->asExtended().refCount());
+
+ delete c2;
+ EXPECT_EQ(1u, c3->asExtended().refCount());
+
+ delete c3;
+}
+
+Color makeColor()
+{
+ Color c1(1.0, 0.5, 0.25, 1.0, ColorSpaceDisplayP3);
+ EXPECT_TRUE(c1.isExtended());
+ EXPECT_EQ(1u, c1.asExtended().refCount());
+
+ return c1;
+}
+
+TEST(ExtendedColor, ReturnValues)
+{
+ Color c2 = makeColor();
+ EXPECT_TRUE(c2.isExtended());
+
+ EXPECT_EQ(1u, c2.asExtended().refCount());
+ EXPECT_EQ(c2.cssText(), "color(display-p3 1 0.5 0.25)");
+}
+
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/FileSystem.cpp b/Tools/TestWebKitAPI/Tests/WebCore/FileSystem.cpp
new file mode 100644
index 000000000..8a4a78c65
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/FileSystem.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2015 Canon Inc. All rights reserved.
+ * Copyright (C) 2017 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include "Test.h"
+#include <WebCore/FileSystem.h>
+#include <wtf/MainThread.h>
+#include <wtf/StringExtras.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+const char* FileSystemTestData = "This is a test";
+
+// FIXME: Refactor FileSystemTest and SharedBufferTest as a single class.
+class FileSystemTest : public testing::Test {
+public:
+ void SetUp() override
+ {
+ WTF::initializeMainThread();
+
+ // create temp file
+ PlatformFileHandle handle;
+ m_tempFilePath = openTemporaryFile("tempTestFile", handle);
+ writeToFile(handle, FileSystemTestData, strlen(FileSystemTestData));
+ closeFile(handle);
+
+ m_tempEmptyFilePath = openTemporaryFile("tempEmptyTestFile", handle);
+ closeFile(handle);
+
+ m_spaceContainingFilePath = openTemporaryFile("temp Empty Test File", handle);
+ closeFile(handle);
+
+ m_bangContainingFilePath = openTemporaryFile("temp!Empty!Test!File", handle);
+ closeFile(handle);
+
+ m_quoteContainingFilePath = openTemporaryFile("temp\"Empty\"TestFile", handle);
+ closeFile(handle);
+ }
+
+ void TearDown() override
+ {
+ deleteFile(m_tempFilePath);
+ deleteFile(m_tempEmptyFilePath);
+ deleteFile(m_spaceContainingFilePath);
+ deleteFile(m_bangContainingFilePath);
+ deleteFile(m_quoteContainingFilePath);
+ }
+
+ const String& tempFilePath() { return m_tempFilePath; }
+ const String& tempEmptyFilePath() { return m_tempEmptyFilePath; }
+ const String& spaceContainingFilePath() { return m_spaceContainingFilePath; }
+ const String& bangContainingFilePath() { return m_bangContainingFilePath; }
+ const String& quoteContainingFilePath() { return m_quoteContainingFilePath; }
+
+private:
+ String m_tempFilePath;
+ String m_tempEmptyFilePath;
+ String m_spaceContainingFilePath;
+ String m_bangContainingFilePath;
+ String m_quoteContainingFilePath;
+};
+
+TEST_F(FileSystemTest, MappingMissingFile)
+{
+ bool success;
+ MappedFileData mappedFileData(String("not_existing_file"), success);
+ EXPECT_FALSE(success);
+ EXPECT_TRUE(!mappedFileData);
+}
+
+TEST_F(FileSystemTest, MappingExistingFile)
+{
+ bool success;
+ MappedFileData mappedFileData(tempFilePath(), success);
+ EXPECT_TRUE(success);
+ EXPECT_TRUE(!!mappedFileData);
+ EXPECT_TRUE(mappedFileData.size() == strlen(FileSystemTestData));
+ EXPECT_TRUE(strnstr(FileSystemTestData, static_cast<const char*>(mappedFileData.data()), mappedFileData.size()));
+}
+
+TEST_F(FileSystemTest, MappingExistingEmptyFile)
+{
+ bool success;
+ MappedFileData mappedFileData(tempEmptyFilePath(), success);
+ EXPECT_TRUE(success);
+ EXPECT_TRUE(!mappedFileData);
+}
+
+TEST_F(FileSystemTest, FilesHaveSameVolume)
+{
+ EXPECT_TRUE(filesHaveSameVolume(tempFilePath(), spaceContainingFilePath()));
+ EXPECT_TRUE(filesHaveSameVolume(spaceContainingFilePath(), bangContainingFilePath()));
+ EXPECT_TRUE(filesHaveSameVolume(bangContainingFilePath(), quoteContainingFilePath()));
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/FloatPoint.cpp b/Tools/TestWebKitAPI/Tests/WebCore/FloatPoint.cpp
new file mode 100644
index 000000000..24c0ff9e3
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/FloatPoint.cpp
@@ -0,0 +1,598 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <WebCore/AffineTransform.h>
+#include <WebCore/FloatPoint.h>
+#include <WebCore/FloatSize.h>
+#include <WebCore/IntPoint.h>
+#include <WebCore/IntSize.h>
+#include <WebCore/TransformationMatrix.h>
+
+#if USE(CG)
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
+namespace TestWebKitAPI {
+
+static void testGetAndSet(WebCore::FloatPoint point)
+{
+ point.setX(1.1f);
+ EXPECT_FLOAT_EQ(1.1f, point.x());
+ point.setY(2.2f);
+ EXPECT_FLOAT_EQ(2.2f, point.y());
+
+ point.set(9.9f, 8.8f);
+ EXPECT_FLOAT_EQ(9.9f, point.x());
+ EXPECT_FLOAT_EQ(8.8f, point.y());
+}
+
+TEST(FloatPoint, DefaultConstruction)
+{
+ WebCore::FloatPoint test;
+
+ EXPECT_FLOAT_EQ(0, test.x());
+ EXPECT_FLOAT_EQ(0, test.y());
+
+ testGetAndSet(test);
+}
+
+TEST(FloatPoint, ValueConstruction)
+{
+ WebCore::FloatPoint test(9.9f, 8.8f);
+
+ EXPECT_FLOAT_EQ(9.9f, test.x());
+ EXPECT_FLOAT_EQ(8.8f, test.y());
+
+ testGetAndSet(test);
+}
+
+TEST(FloatPoint, ZeroConstruction)
+{
+ WebCore::FloatPoint test = WebCore::FloatPoint::zero();
+
+ EXPECT_FLOAT_EQ(0, test.x());
+ EXPECT_FLOAT_EQ(0, test.y());
+}
+
+TEST(FloatPoint, IntPointConstruction)
+{
+ WebCore::IntPoint testInput(2003, 1997);
+ WebCore::FloatPoint test = WebCore::FloatPoint(testInput);
+
+ EXPECT_FLOAT_EQ(2003.0f, test.x());
+ EXPECT_FLOAT_EQ(1997.0f, test.y());
+}
+
+TEST(FloatPoint, FloatSizeConstruction)
+{
+ WebCore::FloatSize testInput(500.7f, 300.2f);
+ WebCore::FloatPoint test = WebCore::FloatPoint(testInput);
+
+ EXPECT_FLOAT_EQ(500.7, test.x());
+ EXPECT_FLOAT_EQ(300.2, test.y());
+}
+
+TEST(FloatPoint, MoveByFloat)
+{
+ WebCore::FloatPoint test(100.0f, 200.0f);
+
+ EXPECT_FLOAT_EQ(100.0f, test.x());
+ EXPECT_FLOAT_EQ(200.0f, test.y());
+
+ test.move(20.2f, 30.3f);
+
+ EXPECT_FLOAT_EQ(120.2f, test.x());
+ EXPECT_FLOAT_EQ(230.3f, test.y());
+
+ test.move(-81.3f, 10.0f);
+
+ EXPECT_FLOAT_EQ(38.9f, test.x());
+ EXPECT_FLOAT_EQ(240.3f, test.y());
+
+ test.move(11.1f, -33.2f);
+
+ EXPECT_FLOAT_EQ(50.0f, test.x());
+ EXPECT_FLOAT_EQ(207.1f, test.y());
+
+ test.move(-5.6f, -9.8f);
+
+ EXPECT_FLOAT_EQ(44.4f, test.x());
+ EXPECT_FLOAT_EQ(197.3f, test.y());
+}
+
+TEST(FloatPoint, MoveByIntSize)
+{
+ WebCore::FloatPoint test(100.0f, 200.0f);
+
+ EXPECT_FLOAT_EQ(100.0f, test.x());
+ EXPECT_FLOAT_EQ(200.0f, test.y());
+
+ WebCore::IntSize first(20, 30);
+
+ test.move(first);
+
+ EXPECT_FLOAT_EQ(120.0f, test.x());
+ EXPECT_FLOAT_EQ(230.0f, test.y());
+
+ WebCore::IntSize second(-81, 10);
+
+ test.move(second);
+
+ EXPECT_FLOAT_EQ(39.0f, test.x());
+ EXPECT_FLOAT_EQ(240.0f, test.y());
+
+ WebCore::IntSize third(11, -33);
+
+ test.move(third);
+
+ EXPECT_FLOAT_EQ(50.0f, test.x());
+ EXPECT_FLOAT_EQ(207.0f, test.y());
+
+ WebCore::IntSize fourth(-6, -10);
+
+ test.move(fourth);
+
+ EXPECT_FLOAT_EQ(44.0f, test.x());
+ EXPECT_FLOAT_EQ(197.0f, test.y());
+}
+
+TEST(FloatPoint, MoveByFloatSize)
+{
+ WebCore::FloatPoint test(100.0f, 200.0f);
+
+ EXPECT_FLOAT_EQ(100.0f, test.x());
+ EXPECT_FLOAT_EQ(200.0f, test.y());
+
+ WebCore::FloatSize first(20.2f, 30.3f);
+
+ test.move(first);
+
+ EXPECT_FLOAT_EQ(120.2f, test.x());
+ EXPECT_FLOAT_EQ(230.3f, test.y());
+
+ WebCore::FloatSize second(-81.3f, 10.0f);
+
+ test.move(second);
+
+ EXPECT_FLOAT_EQ(38.9f, test.x());
+ EXPECT_FLOAT_EQ(240.3f, test.y());
+
+ WebCore::FloatSize third(11.1f, -33.2f);
+
+ test.move(third);
+
+ EXPECT_FLOAT_EQ(50.0f, test.x());
+ EXPECT_FLOAT_EQ(207.1f, test.y());
+
+ WebCore::FloatSize fourth(-5.6f, -9.8f);
+
+ test.move(fourth);
+
+ EXPECT_FLOAT_EQ(44.4f, test.x());
+ EXPECT_FLOAT_EQ(197.3f, test.y());
+}
+
+TEST(FloatPoint, MoveByIntPoint)
+{
+ WebCore::FloatPoint test(100.0f, 200.0f);
+
+ EXPECT_FLOAT_EQ(100.0f, test.x());
+ EXPECT_FLOAT_EQ(200.0f, test.y());
+
+ WebCore::IntPoint first(20, 30);
+
+ test.moveBy(first);
+
+ EXPECT_FLOAT_EQ(120.0f, test.x());
+ EXPECT_FLOAT_EQ(230.0f, test.y());
+
+ WebCore::IntPoint second(-81, 10);
+
+ test.moveBy(second);
+
+ EXPECT_FLOAT_EQ(39.0f, test.x());
+ EXPECT_FLOAT_EQ(240.0f, test.y());
+
+ WebCore::IntPoint third(11, -33);
+
+ test.moveBy(third);
+
+ EXPECT_FLOAT_EQ(50.0f, test.x());
+ EXPECT_FLOAT_EQ(207.0f, test.y());
+
+ WebCore::IntPoint fourth(-6, -10);
+
+ test.moveBy(fourth);
+
+ EXPECT_FLOAT_EQ(44.0f, test.x());
+ EXPECT_FLOAT_EQ(197.0f, test.y());
+}
+
+TEST(FloatPoint, MoveByFloatPoint)
+{
+ WebCore::FloatPoint test(100.0f, 200.0f);
+
+ EXPECT_FLOAT_EQ(100.0f, test.x());
+ EXPECT_FLOAT_EQ(200.0f, test.y());
+
+ WebCore::FloatPoint first(20.2f, 30.3f);
+
+ test.moveBy(first);
+
+ EXPECT_FLOAT_EQ(120.2f, test.x());
+ EXPECT_FLOAT_EQ(230.3f, test.y());
+
+ WebCore::FloatPoint second(-81.3f, 10.0f);
+
+ test.moveBy(second);
+
+ EXPECT_FLOAT_EQ(38.9f, test.x());
+ EXPECT_FLOAT_EQ(240.3f, test.y());
+
+ WebCore::FloatPoint third(11.1f, -33.2f);
+
+ test.moveBy(third);
+
+ EXPECT_FLOAT_EQ(50.0f, test.x());
+ EXPECT_FLOAT_EQ(207.1f, test.y());
+
+ WebCore::FloatPoint fourth(-5.6f, -9.8f);
+
+ test.moveBy(fourth);
+
+ EXPECT_FLOAT_EQ(44.4f, test.x());
+ EXPECT_FLOAT_EQ(197.3f, test.y());
+}
+
+TEST(FloatPoint, Scale)
+{
+ WebCore::FloatPoint test(100.0f, 200.0f);
+
+ EXPECT_FLOAT_EQ(100.0f, test.x());
+ EXPECT_FLOAT_EQ(200.0f, test.y());
+
+ test.scale(2.0f, 2.0f);
+
+ EXPECT_FLOAT_EQ(200.0f, test.x());
+ EXPECT_FLOAT_EQ(400.0f, test.y());
+
+ test.scale(0.5f, 0.5f);
+
+ EXPECT_FLOAT_EQ(100.0f, test.x());
+ EXPECT_FLOAT_EQ(200.0f, test.y());
+
+ test.scale(2);
+
+ EXPECT_FLOAT_EQ(200.0f, test.x());
+ EXPECT_FLOAT_EQ(400.0f, test.y());
+
+ test.scale(1.0f, 0.5f);
+
+ EXPECT_FLOAT_EQ(200.0f, test.x());
+ EXPECT_FLOAT_EQ(200.0f, test.y());
+}
+
+TEST(FloatPoint, Normalize)
+{
+ WebCore::FloatPoint a(30.0f, 40.0f);
+
+ a.normalize();
+
+ EXPECT_FLOAT_EQ(0.6, a.x());
+ EXPECT_FLOAT_EQ(0.8, a.y());
+}
+
+TEST(FloatPoint, Dot)
+{
+ WebCore::FloatPoint a(100.0f, 200.0f);
+ WebCore::FloatPoint b(2.0f, 4.0f);
+ WebCore::FloatPoint c(1.0f, 0.5f);
+
+ EXPECT_NEAR(1000.0f, a.dot(b), 0.0001f);
+ EXPECT_NEAR(200.0f, a.dot(c), 0.0001f);
+}
+
+TEST(FloatPoint, LengthSquared)
+{
+ WebCore::FloatPoint test(100.0f, 200.0f);
+
+ EXPECT_FLOAT_EQ(100.0f, test.x());
+ EXPECT_FLOAT_EQ(200.0f, test.y());
+
+ EXPECT_FLOAT_EQ(50000.0f, test.lengthSquared());
+}
+
+TEST(FloatPoint, ConstrainedBetween)
+{
+ WebCore::FloatPoint left(10.0f, 20.0f);
+ WebCore::FloatPoint right(100.0f, 200.0f);
+
+ WebCore::FloatPoint test1(50.0f, 80.0f);
+ WebCore::FloatPoint test2(8.0f, 80.0f);
+ WebCore::FloatPoint test3(50.0f, 220.0f);
+
+ auto constrained1 = test1.constrainedBetween(left, right);
+ EXPECT_FLOAT_EQ(50.0f, constrained1.x());
+ EXPECT_FLOAT_EQ(80.0f, constrained1.y());
+
+ auto constrained2 = test2.constrainedBetween(left, right);
+ EXPECT_FLOAT_EQ(10.0f, constrained2.x());
+ EXPECT_FLOAT_EQ(80.0f, constrained2.y());
+
+ auto constrained3 = test3.constrainedBetween(left, right);
+ EXPECT_FLOAT_EQ(50.0f, constrained3.x());
+ EXPECT_FLOAT_EQ(200.0f, constrained3.y());
+}
+
+TEST(FloatPoint, ShrunkTo)
+{
+ WebCore::FloatPoint big(100.0f, 200.0f);
+ WebCore::FloatPoint smaller(10.0f, 80.0f);
+
+ auto shrunkTo = big.shrunkTo(smaller);
+
+ EXPECT_FLOAT_EQ(10.0f, shrunkTo.x());
+ EXPECT_FLOAT_EQ(80.0f, shrunkTo.y());
+
+ WebCore::FloatPoint bigish(8.0f, 200.0f);
+
+ auto shrunkTo2 = bigish.shrunkTo(smaller);
+
+ EXPECT_FLOAT_EQ(8.0f, shrunkTo2.x());
+ EXPECT_FLOAT_EQ(80.0f, shrunkTo2.y());
+}
+
+TEST(FloatPoint, ExpandedTo)
+{
+ WebCore::FloatPoint big(100.0f, 200.0f);
+ WebCore::FloatPoint smaller(10.0f, 80.0f);
+
+ auto expandedTo = smaller.expandedTo(big);
+
+ EXPECT_FLOAT_EQ(100.0f, expandedTo.x());
+ EXPECT_FLOAT_EQ(200.0f, expandedTo.y());
+
+ WebCore::FloatPoint bigish(8.0f, 300.0f);
+
+ auto expandedTo2 = bigish.expandedTo(big);
+
+ EXPECT_FLOAT_EQ(100.0f, expandedTo2.x());
+ EXPECT_FLOAT_EQ(300.0f, expandedTo2.y());
+}
+
+TEST(FloatPoint, Transpose)
+{
+ WebCore::FloatPoint test(100.0f, 200.0f);
+
+ EXPECT_FLOAT_EQ(100.0f, test.x());
+ EXPECT_FLOAT_EQ(200.0f, test.y());
+
+ auto transposed = test.transposedPoint();
+
+ EXPECT_FLOAT_EQ(200.0f, transposed.x());
+ EXPECT_FLOAT_EQ(100.0f, transposed.y());
+}
+
+TEST(FloatPoint, Transforms)
+{
+ WebCore::FloatPoint test(100.0f, 200.0f);
+
+ WebCore::AffineTransform affine;
+
+ auto transformed1 = test.matrixTransform(affine);
+
+ EXPECT_FLOAT_EQ(100.0f, transformed1.x());
+ EXPECT_FLOAT_EQ(200.0f, transformed1.y());
+
+ WebCore::AffineTransform affine2(2.0, 0.0, 0.0, 2.0, 0.0, 0.0);
+
+ auto transformed2 = test.matrixTransform(affine2);
+
+ EXPECT_FLOAT_EQ(200.0f, transformed2.x());
+ EXPECT_FLOAT_EQ(400.0f, transformed2.y());
+
+ WebCore::TransformationMatrix matrix;
+
+ auto transformed3 = test.matrixTransform(matrix);
+
+ EXPECT_FLOAT_EQ(100.0f, transformed3.x());
+ EXPECT_FLOAT_EQ(200.0f, transformed3.y());
+
+ auto transformed4 = test.matrixTransform(affine2.toTransformationMatrix());
+
+ EXPECT_FLOAT_EQ(200.0f, transformed4.x());
+ EXPECT_FLOAT_EQ(400.0f, transformed4.y());
+}
+
+TEST(FloatPoint, Math)
+{
+ WebCore::FloatPoint a(100.0f, 200.0f);
+ WebCore::FloatPoint b(100.0f, 200.0f);
+
+ a += b;
+
+ EXPECT_FLOAT_EQ(200.0f, a.x());
+ EXPECT_FLOAT_EQ(400.0f, a.y());
+
+ WebCore::FloatSize c(50.0f, 50.0f);
+
+ a += c;
+
+ EXPECT_FLOAT_EQ(250.0f, a.x());
+ EXPECT_FLOAT_EQ(450.0f, a.y());
+
+ WebCore::FloatSize d(10.0f, 200.0f);
+
+ a -= d;
+
+ EXPECT_FLOAT_EQ(240.0f, a.x());
+ EXPECT_FLOAT_EQ(250.0f, a.y());
+
+ WebCore::FloatSize e(100.0f, 200.0f);
+
+ auto f = b + e;
+
+ EXPECT_FLOAT_EQ(200.0f, f.x());
+ EXPECT_FLOAT_EQ(400.0f, f.y());
+
+ WebCore::FloatPoint g(10.0f, 20.0f);
+
+ auto h = b + g;
+
+ EXPECT_FLOAT_EQ(110.0f, h.x());
+ EXPECT_FLOAT_EQ(220.0f, h.y());
+
+ WebCore::FloatSize i = b - g;
+
+ EXPECT_FLOAT_EQ(90.0f, i.width());
+ EXPECT_FLOAT_EQ(180.0f, i.height());
+
+ WebCore::FloatPoint j = b - e;
+
+ EXPECT_FLOAT_EQ(0.0f, j.x());
+ EXPECT_FLOAT_EQ(0.0f, j.y());
+
+ WebCore::FloatPoint negated = -b;
+
+ EXPECT_FLOAT_EQ(-100.0f, negated.x());
+ EXPECT_FLOAT_EQ(-200.0f, negated.y());
+
+ float value = b * g;
+
+ EXPECT_FLOAT_EQ(5000.0f, value);
+}
+
+TEST(FloatPoint, Equality)
+{
+ WebCore::FloatPoint a(100.0f, 200.0f);
+ WebCore::FloatPoint b(100.0f, 200.0f);
+ WebCore::FloatPoint c(10.0f, 20.0f);
+
+ ASSERT_TRUE(a == b);
+ ASSERT_FALSE(a == c);
+ ASSERT_FALSE(a != b);
+ ASSERT_TRUE(a != c);
+
+ ASSERT_TRUE(WebCore::areEssentiallyEqual(a, b));
+ ASSERT_FALSE(WebCore::areEssentiallyEqual(a, c));
+}
+
+TEST(FloatPoint, Floors)
+{
+ WebCore::FloatPoint a(100.6f, 199.9f);
+
+ WebCore::IntSize flooredSize = WebCore::flooredIntSize(a);
+ EXPECT_FLOAT_EQ(100, flooredSize.width());
+ EXPECT_FLOAT_EQ(199, flooredSize.height());
+
+ WebCore::IntPoint flooredPoint = WebCore::flooredIntPoint(a);
+ EXPECT_FLOAT_EQ(100, flooredPoint.x());
+ EXPECT_FLOAT_EQ(199, flooredPoint.y());
+
+ WebCore::FloatPoint flooredPoint1x = WebCore::floorPointToDevicePixels(a, 1.0);
+ EXPECT_FLOAT_EQ(100.0f, flooredPoint1x.x());
+ EXPECT_FLOAT_EQ(199.0f, flooredPoint1x.y());
+
+ WebCore::FloatPoint flooredPoint2x = WebCore::floorPointToDevicePixels(a, 2.0);
+ EXPECT_FLOAT_EQ(100.5f, flooredPoint2x.x());
+ EXPECT_FLOAT_EQ(199.5f, flooredPoint2x.y());
+}
+
+TEST(FloatPoint, Rounding)
+{
+ WebCore::FloatPoint a(100.4f, 199.9f);
+
+ WebCore::IntPoint roundedPoint = WebCore::roundedIntPoint(a);
+ EXPECT_FLOAT_EQ(100, roundedPoint.x());
+ EXPECT_FLOAT_EQ(200, roundedPoint.y());
+}
+
+TEST(FloatPoint, Ceiling)
+{
+ WebCore::FloatPoint a(100.4f, 199.9f);
+
+ WebCore::IntPoint ceilingPoint = WebCore::ceiledIntPoint(a);
+ EXPECT_FLOAT_EQ(101, ceilingPoint.x());
+ EXPECT_FLOAT_EQ(200, ceilingPoint.y());
+
+ WebCore::FloatPoint ceilingPoint1x = WebCore::ceilPointToDevicePixels(a, 1.0);
+ EXPECT_FLOAT_EQ(101.0f, ceilingPoint1x.x());
+ EXPECT_FLOAT_EQ(200.0f, ceilingPoint1x.y());
+
+ WebCore::FloatPoint ceilingPoint2x = WebCore::ceilPointToDevicePixels(a, 2.0);
+ EXPECT_FLOAT_EQ(100.5f, ceilingPoint2x.x());
+ EXPECT_FLOAT_EQ(200.0f, ceilingPoint2x.y());
+}
+
+TEST(FloatPoint, Casting)
+{
+ WebCore::FloatPoint a(100.4f, 199.9f);
+
+ WebCore::FloatSize floatSize = WebCore::toFloatSize(a);
+ EXPECT_FLOAT_EQ(100.4f, floatSize.width());
+ EXPECT_FLOAT_EQ(199.9f, floatSize.height());
+
+ WebCore::FloatSize b(99.6f, 299.1f);
+
+ WebCore::FloatPoint floatPoint = WebCore::toFloatPoint(b);
+ EXPECT_FLOAT_EQ(99.6f, floatPoint.x());
+ EXPECT_FLOAT_EQ(299.1f, floatPoint.y());
+
+#if USE(CG)
+ CGPoint cgPoint = a;
+
+ EXPECT_FLOAT_EQ(100.4f, cgPoint.x);
+ EXPECT_FLOAT_EQ(199.9f, cgPoint.y);
+
+ CGPoint cgPoint2 = CGPointMake(-22.3f, 14.2f);
+
+ WebCore::FloatPoint testCG(cgPoint2);
+
+ EXPECT_FLOAT_EQ(-22.3f, testCG.x());
+ EXPECT_FLOAT_EQ(14.2f, testCG.y());
+#endif
+
+#if PLATFORM(WIN)
+ D2D_POINT_2F d2dPoint = a;
+
+ EXPECT_FLOAT_EQ(100.4f, d2dPoint.x);
+ EXPECT_FLOAT_EQ(199.9f, d2dPoint.y);
+
+ D2D_POINT_2F d2dPoint2 = D2D1::Point2F(-22.3f, 14.2f);
+
+ WebCore::FloatPoint testD2D(d2dPoint2);
+
+ EXPECT_FLOAT_EQ(-22.3f, testD2D.x());
+ EXPECT_FLOAT_EQ(14.2f, testD2D.y());
+#endif
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/FloatRect.cpp b/Tools/TestWebKitAPI/Tests/WebCore/FloatRect.cpp
new file mode 100644
index 000000000..b7e100e06
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/FloatRect.cpp
@@ -0,0 +1,783 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <WebCore/FloatPoint.h>
+#include <WebCore/FloatRect.h>
+#include <WebCore/FloatSize.h>
+#include <WebCore/IntRect.h>
+
+#if USE(CG)
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
+namespace TestWebKitAPI {
+
+static void testGetAndSet(WebCore::FloatRect rect)
+{
+ rect.setX(1.1f);
+ EXPECT_FLOAT_EQ(1.1f, rect.x());
+ rect.setY(2.2f);
+ EXPECT_FLOAT_EQ(2.2f, rect.y());
+ rect.setWidth(203.2f);
+ EXPECT_FLOAT_EQ(203.2f, rect.width());
+ rect.setHeight(72.9f);
+ EXPECT_FLOAT_EQ(72.9f, rect.height());
+}
+
+static void testEmptyRect(const WebCore::FloatRect& rect)
+{
+ EXPECT_FLOAT_EQ(0, rect.x());
+ EXPECT_FLOAT_EQ(0, rect.y());
+ EXPECT_FLOAT_EQ(0, rect.width());
+ EXPECT_FLOAT_EQ(0, rect.height());
+ EXPECT_FLOAT_EQ(0, rect.maxX());
+ EXPECT_FLOAT_EQ(0, rect.maxY());
+ EXPECT_TRUE(rect.isEmpty());
+ EXPECT_TRUE(rect.isZero());
+ EXPECT_FALSE(rect.isInfinite());
+}
+
+TEST(FloatRect, DefaultConstruction)
+{
+ WebCore::FloatRect test;
+
+ testEmptyRect(test);
+
+ testGetAndSet(test);
+
+ auto location = test.location();
+ EXPECT_FLOAT_EQ(0, location.x());
+ EXPECT_FLOAT_EQ(0, location.y());
+
+ auto size = test.size();
+ EXPECT_FLOAT_EQ(0, size.width());
+ EXPECT_FLOAT_EQ(0, size.height());
+}
+
+TEST(FloatRect, ValueConstruction)
+{
+ WebCore::FloatRect test(10.0f, 20.0f, 100.0f, 50.0f);
+
+ EXPECT_FLOAT_EQ(10.0f, test.x());
+ EXPECT_FLOAT_EQ(20.0f, test.y());
+ EXPECT_FLOAT_EQ(100.0f, test.width());
+ EXPECT_FLOAT_EQ(50.0f, test.height());
+ EXPECT_FLOAT_EQ(110.0f, test.maxX());
+ EXPECT_FLOAT_EQ(70.0f, test.maxY());
+ EXPECT_FALSE(test.isEmpty());
+ EXPECT_FALSE(test.isZero());
+ EXPECT_FALSE(test.isInfinite());
+
+ auto location = test.location();
+ EXPECT_FLOAT_EQ(10.0f, location.x());
+ EXPECT_FLOAT_EQ(20.0f, location.y());
+
+ auto size = test.size();
+ EXPECT_FLOAT_EQ(100.0f, size.width());
+ EXPECT_FLOAT_EQ(50.0f, size.height());
+}
+
+TEST(FloatRect, PointSizeConstruction)
+{
+ WebCore::FloatPoint location(20.0f, 30.0f);
+ WebCore::FloatSize size(100.0f, 50.0f);
+
+ WebCore::FloatRect test(location, size);
+
+ EXPECT_FLOAT_EQ(20.0f, test.x());
+ EXPECT_FLOAT_EQ(30.0f, test.y());
+ EXPECT_FLOAT_EQ(100.0f, test.width());
+ EXPECT_FLOAT_EQ(50.0f, test.height());
+ EXPECT_FLOAT_EQ(120.0f, test.maxX());
+ EXPECT_FLOAT_EQ(80.0f, test.maxY());
+ EXPECT_FALSE(test.isEmpty());
+ EXPECT_FALSE(test.isZero());
+ EXPECT_FALSE(test.isInfinite());
+
+ auto location2 = test.location();
+ EXPECT_FLOAT_EQ(20.0f, location2.x());
+ EXPECT_FLOAT_EQ(30.0f, location2.y());
+
+ auto size2 = test.size();
+ EXPECT_FLOAT_EQ(100.0f, size2.width());
+ EXPECT_FLOAT_EQ(50.0f, size2.height());
+}
+
+TEST(FloatRect, TwoPointConstruction)
+{
+ WebCore::FloatPoint point1(20.0f, 30.0f);
+ WebCore::FloatPoint point2(150.0f, 250.0f);
+
+ WebCore::FloatRect test(point1, point2);
+
+ EXPECT_FLOAT_EQ(20.0f, test.x());
+ EXPECT_FLOAT_EQ(30.0f, test.y());
+ EXPECT_FLOAT_EQ(130.0f, test.width());
+ EXPECT_FLOAT_EQ(220.0f, test.height());
+ EXPECT_FLOAT_EQ(150.0f, test.maxX());
+ EXPECT_FLOAT_EQ(250.0f, test.maxY());
+ EXPECT_FALSE(test.isEmpty());
+ EXPECT_FALSE(test.isZero());
+ EXPECT_FALSE(test.isInfinite());
+
+ auto location = test.location();
+ EXPECT_FLOAT_EQ(20.0f, location.x());
+ EXPECT_FLOAT_EQ(30.0f, location.y());
+
+ auto size = test.size();
+ EXPECT_FLOAT_EQ(130.0f, size.width());
+ EXPECT_FLOAT_EQ(220.0f, size.height());
+}
+
+TEST(FloatRect, IntRectConstruction)
+{
+ WebCore::IntRect rect(20, 30, 150, 300);
+
+ WebCore::FloatRect test(rect);
+
+ EXPECT_FLOAT_EQ(20.0f, test.x());
+ EXPECT_FLOAT_EQ(30.0f, test.y());
+ EXPECT_FLOAT_EQ(150.0f, test.width());
+ EXPECT_FLOAT_EQ(300.0f, test.height());
+ EXPECT_FLOAT_EQ(170.0f, test.maxX());
+ EXPECT_FLOAT_EQ(330.0f, test.maxY());
+ EXPECT_FALSE(test.isEmpty());
+ EXPECT_FALSE(test.isZero());
+ EXPECT_FALSE(test.isInfinite());
+
+ auto location = test.location();
+ EXPECT_FLOAT_EQ(20.0f, location.x());
+ EXPECT_FLOAT_EQ(30.0f, location.y());
+
+ auto size = test.size();
+ EXPECT_FLOAT_EQ(150.0f, size.width());
+ EXPECT_FLOAT_EQ(300.0f, size.height());
+}
+
+TEST(FloatRect, SetLocationAndSize)
+{
+ WebCore::FloatRect rect;
+
+ testEmptyRect(rect);
+
+ WebCore::FloatPoint location(10.0f, 20.0f);
+
+ rect.setLocation(location);
+
+ EXPECT_FLOAT_EQ(10.0f, rect.x());
+ EXPECT_FLOAT_EQ(20.0f, rect.y());
+ EXPECT_FLOAT_EQ(0.0f, rect.width());
+ EXPECT_FLOAT_EQ(0.0f, rect.height());
+ EXPECT_FLOAT_EQ(10.0f, rect.maxX());
+ EXPECT_FLOAT_EQ(20.0f, rect.maxY());
+ EXPECT_TRUE(rect.isEmpty());
+ EXPECT_TRUE(rect.isZero());
+ EXPECT_FALSE(rect.isInfinite());
+
+ WebCore::FloatSize size(100.0f, 200.0f);
+
+ rect.setSize(size);
+
+ EXPECT_FLOAT_EQ(10.0f, rect.x());
+ EXPECT_FLOAT_EQ(20.0f, rect.y());
+ EXPECT_FLOAT_EQ(100.0f, rect.width());
+ EXPECT_FLOAT_EQ(200.0f, rect.height());
+ EXPECT_FLOAT_EQ(110.0f, rect.maxX());
+ EXPECT_FLOAT_EQ(220.0f, rect.maxY());
+ EXPECT_FALSE(rect.isEmpty());
+ EXPECT_FALSE(rect.isZero());
+ EXPECT_FALSE(rect.isInfinite());
+}
+
+TEST(FloatRect, Center)
+{
+ WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+ auto center = rect.center();
+
+ EXPECT_FLOAT_EQ(70.0f, center.x());
+ EXPECT_FLOAT_EQ(130.0f, center.y());
+}
+
+TEST(FloatRect, Move)
+{
+ WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+ WebCore::FloatSize delta(10.0f, 20.0f);
+
+ rect.move(delta);
+
+ EXPECT_FLOAT_EQ(30.0f, rect.x());
+ EXPECT_FLOAT_EQ(50.0f, rect.y());
+
+ WebCore::FloatPoint deltaPoint(-20.0f, -40.0f);
+
+ rect.moveBy(deltaPoint);
+
+ EXPECT_FLOAT_EQ(10.0f, rect.x());
+ EXPECT_FLOAT_EQ(10.0f, rect.y());
+
+ rect.move(-10.0f, 22.0f);
+
+ EXPECT_FLOAT_EQ(0.0f, rect.x());
+ EXPECT_FLOAT_EQ(32.0f, rect.y());
+}
+
+TEST(FloatRect, Expand)
+{
+ WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+ WebCore::FloatSize size(100.0f, 100.0f);
+
+ rect.expand(size);
+
+ EXPECT_FLOAT_EQ(200.0f, rect.width());
+ EXPECT_FLOAT_EQ(300.0f, rect.height());
+
+ rect.expand(55.0f, 22.0f);
+
+ EXPECT_FLOAT_EQ(255.0f, rect.width());
+ EXPECT_FLOAT_EQ(322.0f, rect.height());
+
+ WebCore::FloatSize size2(-10.0f, -20.0f);
+
+ rect.expand(size2);
+
+ EXPECT_FLOAT_EQ(245.0f, rect.width());
+ EXPECT_FLOAT_EQ(302.0f, rect.height());
+
+ rect.expand(-5.0f, -2.0f);
+
+ EXPECT_FLOAT_EQ(240.0f, rect.width());
+ EXPECT_FLOAT_EQ(300.0f, rect.height());
+
+ EXPECT_FALSE(rect.isInfinite());
+}
+
+TEST(FloatRect, Contract)
+{
+ WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+ WebCore::FloatSize size(50.0f, 100.0f);
+
+ rect.contract(size);
+
+ EXPECT_FLOAT_EQ(50.0f, rect.width());
+ EXPECT_FLOAT_EQ(100.0f, rect.height());
+
+ rect.contract(25.0f, 22.0f);
+
+ EXPECT_FLOAT_EQ(25.0f, rect.width());
+ EXPECT_FLOAT_EQ(78.0f, rect.height());
+
+ WebCore::FloatSize size2(-10.0f, -20.0f);
+
+ rect.contract(size2);
+
+ EXPECT_FLOAT_EQ(35.0f, rect.width());
+ EXPECT_FLOAT_EQ(98.0f, rect.height());
+
+ rect.contract(-5.0f, -2.0f);
+
+ EXPECT_FLOAT_EQ(40.0f, rect.width());
+ EXPECT_FLOAT_EQ(100.0f, rect.height());
+
+ EXPECT_FALSE(rect.isInfinite());
+}
+
+TEST(FloatRect, ShiftXEdge)
+{
+ WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+ rect.shiftXEdgeTo(77.0f);
+
+ EXPECT_FLOAT_EQ(77.0f, rect.x());
+ EXPECT_FLOAT_EQ(120.0f, rect.maxX());
+ EXPECT_FLOAT_EQ(30.0f, rect.y());
+ EXPECT_FLOAT_EQ(230.0f, rect.maxY());
+ EXPECT_FLOAT_EQ(43.0f, rect.width());
+ EXPECT_FLOAT_EQ(200.0f, rect.height());
+
+ rect.shiftMaxXEdgeTo(200.0f);
+
+ EXPECT_FLOAT_EQ(77.0f, rect.x());
+ EXPECT_FLOAT_EQ(200.0f, rect.maxX());
+ EXPECT_FLOAT_EQ(30.0f, rect.y());
+ EXPECT_FLOAT_EQ(230.0f, rect.maxY());
+ EXPECT_FLOAT_EQ(123.0f, rect.width());
+ EXPECT_FLOAT_EQ(200.0f, rect.height());
+}
+
+TEST(FloatRect, ShiftYEdge)
+{
+ WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+ rect.shiftYEdgeTo(59.0f);
+
+ EXPECT_FLOAT_EQ(20.0f, rect.x());
+ EXPECT_FLOAT_EQ(120.0f, rect.maxX());
+ EXPECT_FLOAT_EQ(59.0f, rect.y());
+ EXPECT_FLOAT_EQ(230.0f, rect.maxY());
+ EXPECT_FLOAT_EQ(100.0f, rect.width());
+ EXPECT_FLOAT_EQ(171.0f, rect.height());
+
+ rect.shiftMaxYEdgeTo(270.0f);
+
+ EXPECT_FLOAT_EQ(20.0f, rect.x());
+ EXPECT_FLOAT_EQ(120.0f, rect.maxX());
+ EXPECT_FLOAT_EQ(59.0f, rect.y());
+ EXPECT_FLOAT_EQ(270.0f, rect.maxY());
+ EXPECT_FLOAT_EQ(100.0f, rect.width());
+ EXPECT_FLOAT_EQ(211.0f, rect.height());
+}
+
+TEST(FloatRect, Inflate)
+{
+ WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+ rect.inflateX(5.0f);
+
+ EXPECT_FLOAT_EQ(15.0f, rect.x());
+ EXPECT_FLOAT_EQ(125.0f, rect.maxX());
+
+ rect.inflateY(4.0f);
+
+ EXPECT_FLOAT_EQ(26.0f, rect.y());
+ EXPECT_FLOAT_EQ(234.0f, rect.maxY());
+
+ rect.inflate(10.0f);
+
+ EXPECT_FLOAT_EQ(5.0f, rect.x());
+ EXPECT_FLOAT_EQ(135.0f, rect.maxX());
+ EXPECT_FLOAT_EQ(16.0f, rect.y());
+ EXPECT_FLOAT_EQ(244.0f, rect.maxY());
+
+ EXPECT_FALSE(rect.isInfinite());
+}
+
+TEST(FloatRect, Corners)
+{
+ WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+ WebCore::FloatPoint topLeft = rect.minXMinYCorner();
+ EXPECT_FLOAT_EQ(20.0f, topLeft.x());
+ EXPECT_FLOAT_EQ(30.0f, topLeft.y());
+
+ WebCore::FloatPoint topRight = rect.maxXMinYCorner();
+ EXPECT_FLOAT_EQ(120.0f, topRight.x());
+ EXPECT_FLOAT_EQ(30.0f, topRight.y());
+
+ WebCore::FloatPoint bottomLeft = rect.minXMaxYCorner();
+ EXPECT_FLOAT_EQ(20.0f, bottomLeft.x());
+ EXPECT_FLOAT_EQ(230.0f, bottomLeft.y());
+
+ WebCore::FloatPoint bottomRight = rect.maxXMaxYCorner();
+ EXPECT_FLOAT_EQ(120.0f, bottomRight.x());
+ EXPECT_FLOAT_EQ(230.0f, bottomRight.y());
+}
+
+TEST(FloatRect, Contains)
+{
+ WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+ WebCore::FloatRect contained(30.0f, 40.0f, 50.0f, 100.0f);
+
+ ASSERT_TRUE(rect.contains(contained));
+
+ WebCore::FloatRect outside(120.0f, 230.0f, 50.0f, 100.0f);
+
+ ASSERT_FALSE(rect.contains(outside));
+
+ WebCore::FloatRect intersects(10.0f, 20.0f, 90.0f, 180.0f);
+
+ ASSERT_FALSE(rect.contains(intersects));
+
+ WebCore::FloatPoint pointInside(60.0f, 70.0f);
+
+ ASSERT_TRUE(rect.contains(pointInside));
+ ASSERT_TRUE(rect.contains(pointInside, WebCore::FloatRect::InsideButNotOnStroke));
+
+ WebCore::FloatPoint pointOutside(160.0f, 270.0f);
+
+ ASSERT_FALSE(rect.contains(pointOutside));
+ ASSERT_FALSE(rect.contains(pointOutside, WebCore::FloatRect::InsideButNotOnStroke));
+
+ WebCore::FloatPoint pointOnLine(20.0f, 30.0f);
+
+ ASSERT_TRUE(rect.contains(pointOnLine));
+ ASSERT_FALSE(rect.contains(pointOutside, WebCore::FloatRect::InsideButNotOnStroke));
+
+ ASSERT_TRUE(rect.contains(60.0f, 70.0f));
+ ASSERT_FALSE(rect.contains(160.0f, 270.0f));
+}
+
+TEST(FloatRect, Intersects)
+{
+ WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+ WebCore::FloatRect contained(30.0f, 40.0f, 50.0f, 100.0f);
+
+ ASSERT_TRUE(rect.intersects(contained));
+
+ WebCore::FloatRect outside(120.0f, 230.0f, 50.0f, 100.0f);
+
+ ASSERT_FALSE(rect.intersects(outside));
+
+ WebCore::FloatRect intersects(10.0f, 20.0f, 90.0f, 180.0f);
+
+ ASSERT_TRUE(rect.intersects(intersects));
+}
+
+static void testIntersectResult(const WebCore::FloatRect& rect)
+{
+ EXPECT_FLOAT_EQ(70.0f, rect.x());
+ EXPECT_FLOAT_EQ(120.0f, rect.maxX());
+ EXPECT_FLOAT_EQ(80.0f, rect.y());
+ EXPECT_FLOAT_EQ(230.0f, rect.maxY());
+}
+
+TEST(FloatRect, Intersect)
+{
+ WebCore::FloatRect rectA(20.0f, 30.0f, 100.0f, 200.0f);
+ WebCore::FloatRect rectB(70.0f, 80.0f, 100.0f, 200.0f);
+
+ rectA.intersect(rectB);
+
+ testIntersectResult(rectA);
+
+ WebCore::FloatRect rectC(20.0f, 30.0f, 100.0f, 200.0f);
+
+ auto intersected = WebCore::intersection(rectC, rectB);
+
+ testIntersectResult(intersected);
+}
+
+static void testUnitedRects(const WebCore::FloatRect& united)
+{
+ EXPECT_FLOAT_EQ(20.0f, united.x());
+ EXPECT_FLOAT_EQ(170.0f, united.maxX());
+ EXPECT_FLOAT_EQ(30.0f, united.y());
+ EXPECT_FLOAT_EQ(280.0f, united.maxY());
+}
+
+TEST(FloatRect, Unite)
+{
+ WebCore::FloatRect rectA(20.0f, 30.0f, 100.0f, 200.0f);
+ WebCore::FloatRect rectB(70.0f, 80.0f, 100.0f, 200.0f);
+
+ rectA.unite(rectB);
+
+ testUnitedRects(rectA);
+
+ WebCore::FloatRect rectC(20.0f, 30.0f, 100.0f, 200.0f);
+
+ auto united = WebCore::unionRect(rectC, rectB);
+
+ testUnitedRects(united);
+}
+
+TEST(FloatRect, Extend)
+{
+ WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+ WebCore::FloatPoint point(170.0f, 280.0f);
+
+ rect.extend(point);
+
+ EXPECT_FLOAT_EQ(20.0f, rect.x());
+ EXPECT_FLOAT_EQ(170.0f, rect.maxX());
+ EXPECT_FLOAT_EQ(30.0f, rect.y());
+ EXPECT_FLOAT_EQ(280.0f, rect.maxY());
+}
+
+TEST(FloatRect, Overlaps)
+{
+ WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+ ASSERT_FALSE(rect.overlapsXRange(0.0f, 10.0f));
+ ASSERT_TRUE(rect.overlapsXRange(10.0f, 30.0f));
+ ASSERT_TRUE(rect.overlapsXRange(40.0f, 70.0f));
+ ASSERT_TRUE(rect.overlapsXRange(110.0f, 130.0f));
+ ASSERT_FALSE(rect.overlapsXRange(140.0f, 600.0f));
+
+ ASSERT_FALSE(rect.overlapsYRange(0.0f, 10.0f));
+ ASSERT_TRUE(rect.overlapsYRange(10.0f, 40.0f));
+ ASSERT_TRUE(rect.overlapsYRange(40.0f, 70.0f));
+ ASSERT_TRUE(rect.overlapsYRange(220.0f, 250.0f));
+ ASSERT_FALSE(rect.overlapsYRange(250.0f, 600.0f));
+}
+
+TEST(FloatRect, Scale)
+{
+ WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+ rect.scale(2.0f);
+
+ EXPECT_FLOAT_EQ(40.0f, rect.x());
+ EXPECT_FLOAT_EQ(240.0f, rect.maxX());
+ EXPECT_FLOAT_EQ(60.0f, rect.y());
+ EXPECT_FLOAT_EQ(460.0f, rect.maxY());
+
+ rect.scale(0.5f, 2.0f);
+
+ EXPECT_FLOAT_EQ(20.0f, rect.x());
+ EXPECT_FLOAT_EQ(120.0f, rect.maxX());
+ EXPECT_FLOAT_EQ(120.0f, rect.y());
+ EXPECT_FLOAT_EQ(920.0f, rect.maxY());
+
+ rect.scale(1.0f, 0.25f);
+
+ EXPECT_FLOAT_EQ(20.0f, rect.x());
+ EXPECT_FLOAT_EQ(120.0f, rect.maxX());
+ EXPECT_FLOAT_EQ(30.0f, rect.y());
+ EXPECT_FLOAT_EQ(230.0f, rect.maxY());
+}
+
+TEST(FloatRect, Transpose)
+{
+ WebCore::FloatRect rect(20.0f, 30.0f, 100.0f, 200.0f);
+
+ auto transposed = rect.transposedRect();
+
+ EXPECT_FLOAT_EQ(30.0f, transposed.x());
+ EXPECT_FLOAT_EQ(230.0f, transposed.maxX());
+ EXPECT_FLOAT_EQ(20.0f, transposed.y());
+ EXPECT_FLOAT_EQ(120.0f, transposed.maxY());
+}
+
+TEST(FloatRect, FitToPoints)
+{
+ WebCore::FloatRect rect(10.0f, 20.0f, 30.0f, 40.0f);
+
+ WebCore::FloatPoint p0(20.0f, 30.0f);
+ WebCore::FloatPoint p1(70.0f, 130.0f);
+ WebCore::FloatPoint p2(50.0f, 20.0f);
+ WebCore::FloatPoint p3(90.0f, 190.0f);
+
+ rect.fitToPoints(p0, p1);
+
+ EXPECT_FLOAT_EQ(20.0f, rect.x());
+ EXPECT_FLOAT_EQ(70.0f, rect.maxX());
+ EXPECT_FLOAT_EQ(30.0f, rect.y());
+ EXPECT_FLOAT_EQ(130.0f, rect.maxY());
+
+ rect.fitToPoints(p0, p1, p2);
+
+ EXPECT_FLOAT_EQ(20.0f, rect.x());
+ EXPECT_FLOAT_EQ(70.0f, rect.maxX());
+ EXPECT_FLOAT_EQ(20.0f, rect.y());
+ EXPECT_FLOAT_EQ(130.0f, rect.maxY());
+
+ rect.fitToPoints(p0, p1, p2, p3);
+
+ EXPECT_FLOAT_EQ(20.0f, rect.x());
+ EXPECT_FLOAT_EQ(90.0f, rect.maxX());
+ EXPECT_FLOAT_EQ(20.0f, rect.y());
+ EXPECT_FLOAT_EQ(190.0f, rect.maxY());
+}
+
+static void checkCastRect(const WebCore::FloatRect& rect)
+{
+ EXPECT_FLOAT_EQ(10.0f, rect.x());
+ EXPECT_FLOAT_EQ(40.0f, rect.maxX());
+ EXPECT_FLOAT_EQ(20.0f, rect.y());
+ EXPECT_FLOAT_EQ(60.0f, rect.maxY());
+ EXPECT_FLOAT_EQ(30.0f, rect.width());
+ EXPECT_FLOAT_EQ(40.0f, rect.height());
+}
+
+TEST(FloatRect, Casting)
+{
+ WebCore::FloatRect rect(10.0f, 20.0f, 30.0f, 40.0f);
+
+#if USE(CG)
+ CGRect cgRect = rect;
+
+ EXPECT_FLOAT_EQ(10.0f, cgRect.origin.x);
+ EXPECT_FLOAT_EQ(20.0f, cgRect.origin.y);
+ EXPECT_FLOAT_EQ(30.0f, cgRect.size.width);
+ EXPECT_FLOAT_EQ(40.0f, cgRect.size.height);
+
+ WebCore::FloatRect rectFromCGRect(cgRect);
+
+ checkCastRect(rectFromCGRect);
+#endif
+
+#if PLATFORM(WIN)
+ D2D1_RECT_F d2dRect = rect;
+
+ EXPECT_FLOAT_EQ(10.0f, d2dRect.left);
+ EXPECT_FLOAT_EQ(20.0f, d2dRect.top);
+ EXPECT_FLOAT_EQ(40.0f, d2dRect.right);
+ EXPECT_FLOAT_EQ(60.0f, d2dRect.bottom);
+
+ WebCore::FloatRect rectFromD2DRect(d2dRect);
+
+ checkCastRect(rectFromD2DRect);
+#endif
+}
+
+static void checkAdditionResult1(const WebCore::FloatRect& rect)
+{
+ EXPECT_FLOAT_EQ(10.0f, rect.x());
+ EXPECT_FLOAT_EQ(130.0f, rect.maxX());
+ EXPECT_FLOAT_EQ(20.0f, rect.y());
+ EXPECT_FLOAT_EQ(220.0f, rect.maxY());
+ EXPECT_FLOAT_EQ(120.0f, rect.width());
+ EXPECT_FLOAT_EQ(200.0f, rect.height());
+}
+
+static void checkAdditionResult2(const WebCore::FloatRect& rect)
+{
+ EXPECT_FLOAT_EQ(10.0f, rect.x());
+ EXPECT_FLOAT_EQ(250.0f, rect.maxX());
+ EXPECT_FLOAT_EQ(20.0f, rect.y());
+ EXPECT_FLOAT_EQ(240.0f, rect.maxY());
+ EXPECT_FLOAT_EQ(240.0f, rect.width());
+ EXPECT_FLOAT_EQ(220.0f, rect.height());
+}
+
+TEST(FloatRect, Addition)
+{
+ WebCore::FloatRect rect(10.0f, 20.0f, 100.0f, 100.0f);
+ WebCore::FloatRect rightSide(0.0f, 0.0f, 20.0f, 100.0f);
+ WebCore::FloatRect bottom(0.0f, 0.0f, 120.0f, 20.0f);
+
+ auto combined = rect + rightSide;
+
+ checkAdditionResult1(combined);
+
+ auto combined2 = combined + bottom;
+
+ checkAdditionResult2(combined2);
+
+ rect += rightSide;
+ rect += bottom;
+
+ checkAdditionResult2(rect);
+}
+
+TEST(FloatRect, Equality)
+{
+ WebCore::FloatRect rect(10.0f, 20.0f, 100.0f, 100.0f);
+ WebCore::FloatRect rect2(10.0f, 20.0f, 100.0f, 100.0f);
+ WebCore::FloatRect rightSide(110.0f, 20.0f, 20.0f, 100.0f);
+
+ ASSERT_TRUE(rect == rect2);
+ ASSERT_FALSE(rect != rect2);
+ ASSERT_TRUE(rect != rightSide);
+ ASSERT_FALSE(rect == rightSide);
+}
+
+TEST(FloatRect, InfiniteRect)
+{
+ WebCore::FloatRect infinite = WebCore::FloatRect::infiniteRect();
+
+ EXPECT_FLOAT_EQ(-std::numeric_limits<float>::max() / 2, infinite.x());
+ EXPECT_FLOAT_EQ(-std::numeric_limits<float>::max() / 2, infinite.y());
+ EXPECT_FLOAT_EQ(std::numeric_limits<float>::max(), infinite.width());
+ EXPECT_FLOAT_EQ(std::numeric_limits<float>::max(), infinite.height());
+
+ // FIXME: We have an unusual representation for our infinite rect.
+ // WebCore::Float::infiniteRect is (negative infinity)/2 for the upper left corner,
+ // while CoreGraphics and D2D use (negative infinity).
+
+#if USE(CG)
+ CGRect cgInfiniteRect = CGRectInfinite;
+
+#if PLATFORM(WIN)
+ EXPECT_FLOAT_EQ(-std::numeric_limits<float>::max() / 2, cgInfiniteRect.origin.x);
+ EXPECT_FLOAT_EQ(-std::numeric_limits<float>::max() / 2, cgInfiniteRect.origin.y);
+ EXPECT_FLOAT_EQ(std::numeric_limits<float>::max(), cgInfiniteRect.size.width);
+ EXPECT_FLOAT_EQ(std::numeric_limits<float>::max(), cgInfiniteRect.size.height);
+#else
+ EXPECT_FLOAT_EQ(-std::numeric_limits<float>::max(), cgInfiniteRect.origin.x);
+ EXPECT_FLOAT_EQ(-std::numeric_limits<float>::max(), cgInfiniteRect.origin.y);
+ EXPECT_FLOAT_EQ(std::numeric_limits<float>::max(), cgInfiniteRect.origin.x + cgInfiniteRect.size.width);
+ EXPECT_FLOAT_EQ(std::numeric_limits<float>::max(), cgInfiniteRect.origin.y + cgInfiniteRect.size.height);
+#endif
+ // ASSERT_TRUE(infinite == cgInfiniteRect);
+#endif
+
+#if PLATFORM(WIN)
+ D2D1_RECT_F d2dInfiniteRect = D2D1::InfiniteRect();
+
+ EXPECT_FLOAT_EQ(-std::numeric_limits<float>::max(), d2dInfiniteRect.left);
+ EXPECT_FLOAT_EQ(-std::numeric_limits<float>::max(), d2dInfiniteRect.top);
+ EXPECT_FLOAT_EQ(std::numeric_limits<float>::max(), d2dInfiniteRect.right);
+ EXPECT_FLOAT_EQ(std::numeric_limits<float>::max(), d2dInfiniteRect.bottom);
+ // ASSERT_TRUE(infinite == d2dInfiniteRect);
+#endif
+}
+
+TEST(FloatRect, EnclosingAndRounding)
+{
+ WebCore::FloatRect rect(10.0f, 20.0f, 1024.3f, 768.3f);
+
+ auto enclosed = WebCore::encloseRectToDevicePixels(rect, 1.0f);
+
+ EXPECT_FLOAT_EQ(10.0f, enclosed.x());
+ EXPECT_FLOAT_EQ(20.0f, enclosed.y());
+ EXPECT_FLOAT_EQ(1035.0f, enclosed.maxX());
+ EXPECT_FLOAT_EQ(789.0f, enclosed.maxY());
+
+ auto enclosed2 = WebCore::encloseRectToDevicePixels(rect, 2.0f);
+
+ EXPECT_FLOAT_EQ(10.0f, enclosed2.x());
+ EXPECT_FLOAT_EQ(20.0f, enclosed2.y());
+ EXPECT_FLOAT_EQ(1034.5f, enclosed2.maxX());
+ EXPECT_FLOAT_EQ(788.5f, enclosed2.maxY());
+}
+
+TEST(FloatRect, EnclosingIntRect)
+{
+ WebCore::FloatRect rect(10.0f, 20.0f, 1024.3f, 768.6f);
+
+ auto enclosed = WebCore::enclosingIntRect(rect);
+
+ EXPECT_FLOAT_EQ(10, enclosed.x());
+ EXPECT_FLOAT_EQ(20, enclosed.y());
+ EXPECT_FLOAT_EQ(1035, enclosed.maxX());
+ EXPECT_FLOAT_EQ(789, enclosed.maxY());
+}
+
+TEST(FloatRect, RoundedIntRect)
+{
+ WebCore::FloatRect rect(10.0f, 20.0f, 1024.3f, 768.6f);
+
+ auto enclosed = WebCore::roundedIntRect(rect);
+
+ EXPECT_FLOAT_EQ(10, enclosed.x());
+ EXPECT_FLOAT_EQ(20, enclosed.y());
+ EXPECT_FLOAT_EQ(1034, enclosed.maxX());
+ EXPECT_FLOAT_EQ(789, enclosed.maxY());
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/FloatSize.cpp b/Tools/TestWebKitAPI/Tests/WebCore/FloatSize.cpp
new file mode 100644
index 000000000..756e76f1d
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/FloatSize.cpp
@@ -0,0 +1,328 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <WebCore/FloatSize.h>
+#include <WebCore/IntPoint.h>
+#include <WebCore/IntSize.h>
+
+#if USE(CG)
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
+namespace TestWebKitAPI {
+
+static void testGetAndSet(WebCore::FloatSize size)
+{
+ size.setWidth(101.1f);
+ EXPECT_FLOAT_EQ(101.1f, size.width());
+ size.setHeight(218.2f);
+ EXPECT_FLOAT_EQ(218.2f, size.height());
+}
+
+TEST(FloatSize, DefaultConstruction)
+{
+ WebCore::FloatSize test;
+
+ EXPECT_FLOAT_EQ(0, test.width());
+ EXPECT_FLOAT_EQ(0, test.height());
+
+ ASSERT_TRUE(test.isEmpty());
+ ASSERT_TRUE(test.isZero());
+
+ testGetAndSet(test);
+}
+
+TEST(FloatSize, ValueConstruction)
+{
+ WebCore::FloatSize test(1024.0f, 768.0f);
+
+ EXPECT_FLOAT_EQ(1024.0f, test.width());
+ EXPECT_FLOAT_EQ(768.0f, test.height());
+
+ ASSERT_FALSE(test.isEmpty());
+ ASSERT_FALSE(test.isZero());
+
+ static const float epsilon = 0.0001f;
+ EXPECT_NEAR(1.3333f, test.aspectRatio(), epsilon);
+
+ testGetAndSet(test);
+}
+
+TEST(FloatSize, IntSizeConstruction)
+{
+ WebCore::IntSize size(1024, 768);
+ WebCore::FloatSize test(size);
+
+ EXPECT_FLOAT_EQ(1024.0f, test.width());
+ EXPECT_FLOAT_EQ(768.0f, test.height());
+
+ ASSERT_FALSE(test.isEmpty());
+ ASSERT_FALSE(test.isZero());
+
+ static const double epsilon = 0.0001;
+ EXPECT_NEAR(1.3333f, test.aspectRatio(), epsilon);
+
+ testGetAndSet(test);
+}
+
+TEST(FloatSize, Scale)
+{
+ WebCore::FloatSize test(1024.0f, 768.0f);
+
+ test.scale(2.0f);
+
+ EXPECT_FLOAT_EQ(2048.0f, test.width());
+ EXPECT_FLOAT_EQ(1536.0f, test.height());
+
+ test.scale(0.5f);
+
+ EXPECT_FLOAT_EQ(1024.0f, test.width());
+ EXPECT_FLOAT_EQ(768.0f, test.height());
+
+ test.scale(2.0f, 0.5f);
+
+ EXPECT_FLOAT_EQ(2048.0f, test.width());
+ EXPECT_FLOAT_EQ(384.0f, test.height());
+}
+
+TEST(FloatSize, Expand)
+{
+ WebCore::FloatSize test(1024.0f, 768.0f);
+
+ EXPECT_FLOAT_EQ(1024.0f, test.width());
+ EXPECT_FLOAT_EQ(768.0f, test.height());
+
+ test.expand(100.0f, 50.0f);
+
+ EXPECT_FLOAT_EQ(1124.0f, test.width());
+ EXPECT_FLOAT_EQ(818.0f, test.height());
+
+ WebCore::FloatSize other(2048.0f, 700.0f);
+
+ auto expanded = test.expandedTo(other);
+
+ EXPECT_FLOAT_EQ(2048.0f, expanded.width());
+ EXPECT_FLOAT_EQ(818.0f, expanded.height());
+}
+
+TEST(FloatSize, Shrink)
+{
+ WebCore::FloatSize test(1024.0f, 768.0f);
+ WebCore::FloatSize other(1000.0f, 700.0f);
+
+ auto shrunken = test.shrunkTo(other);
+
+ EXPECT_FLOAT_EQ(1000.0f, shrunken.width());
+ EXPECT_FLOAT_EQ(700.0f, shrunken.height());
+
+ WebCore::FloatSize other2(2000.0f, 700.0f);
+
+ auto shrunken2 = test.shrunkTo(other2);
+
+ EXPECT_FLOAT_EQ(1024.0f, shrunken2.width());
+ EXPECT_FLOAT_EQ(700.0f, shrunken2.height());
+}
+
+TEST(FloatSize, DiagonalLengthAndArea)
+{
+ WebCore::FloatSize test(1024.0f, 768.0f);
+
+ EXPECT_FLOAT_EQ(1280.0f, test.diagonalLength());
+ EXPECT_FLOAT_EQ(1638400.0f, test.diagonalLengthSquared());
+ EXPECT_FLOAT_EQ(786432.0f, test.area());
+}
+
+TEST(FloatSize, TransposedSize)
+{
+ WebCore::FloatSize test(1024.0f, 768.0f);
+
+ auto transposedSize = test.transposedSize();
+
+ EXPECT_FLOAT_EQ(768.0f, transposedSize.width());
+ EXPECT_FLOAT_EQ(1024.0f, transposedSize.height());
+}
+
+TEST(FloatSize, Casting)
+{
+ WebCore::FloatSize test(1024.0f, 768.0f);
+
+#if USE(CG)
+ CGSize cgSize = test;
+
+ EXPECT_FLOAT_EQ(1024.0f, cgSize.width);
+ EXPECT_FLOAT_EQ(768.0f, cgSize.height);
+
+ CGSize cgSize2 = CGSizeMake(-22.3f, 14.2f);
+
+ WebCore::FloatSize testCG(cgSize2);
+
+ EXPECT_FLOAT_EQ(-22.3f, testCG.width());
+ EXPECT_FLOAT_EQ(14.2f, testCG.height());
+#endif
+
+#if PLATFORM(WIN)
+ D2D1_SIZE_F d2dSize = test;
+
+ EXPECT_FLOAT_EQ(1024.0f, d2dSize.width);
+ EXPECT_FLOAT_EQ(768.0f, d2dSize.height);
+
+ D2D1_SIZE_F d2dSize2 = D2D1::SizeF(-22.3f, 14.2f);
+
+ WebCore::FloatSize testD2D(d2dSize2);
+
+ EXPECT_FLOAT_EQ(-22.3f, testD2D.width());
+ EXPECT_FLOAT_EQ(14.2f, testD2D.height());
+#endif
+}
+
+TEST(FloatSize, AddSubtract)
+{
+ WebCore::FloatSize a(512.0f, 384.0f);
+ WebCore::FloatSize b(100.0f, 100.0f);
+
+ WebCore::FloatSize c = a + b;
+
+ EXPECT_FLOAT_EQ(612.0f, c.width());
+ EXPECT_FLOAT_EQ(484.0f, c.height());
+
+ a += b;
+
+ EXPECT_FLOAT_EQ(612.0f, a.width());
+ EXPECT_FLOAT_EQ(484.0f, a.height());
+
+ WebCore::FloatSize a2(512.0f, 384.0f);
+
+ WebCore::FloatSize d = a2 - b;
+
+ EXPECT_FLOAT_EQ(412.0f, d.width());
+ EXPECT_FLOAT_EQ(284.0f, d.height());
+
+ a2 -= b;
+
+ EXPECT_FLOAT_EQ(412.0f, a2.width());
+ EXPECT_FLOAT_EQ(284.0f, a2.height());
+}
+
+TEST(FloatSize, Negation)
+{
+ WebCore::FloatSize a(512.0f, 384.0f);
+
+ WebCore::FloatSize negated = -a;
+
+ EXPECT_FLOAT_EQ(-512.0f, negated.width());
+ EXPECT_FLOAT_EQ(-384.0f, negated.height());
+}
+
+TEST(FloatSize, Multiply)
+{
+ WebCore::FloatSize a(512.0f, 384.0f);
+
+ WebCore::FloatSize multiplied = a * 2.0f;
+
+ EXPECT_FLOAT_EQ(1024.0f, multiplied.width());
+ EXPECT_FLOAT_EQ(768.0f, multiplied.height());
+
+ WebCore::FloatSize multiplied2 = 3.0f * a;
+
+ EXPECT_FLOAT_EQ(1536.0f, multiplied2.width());
+ EXPECT_FLOAT_EQ(1152.0f, multiplied2.height());
+
+ WebCore::FloatSize b(1024.0f, 768.0f);
+
+ WebCore::FloatSize multiplied3 = a * b;
+
+ EXPECT_FLOAT_EQ(524288.0f, multiplied3.width());
+ EXPECT_FLOAT_EQ(294912.0f, multiplied3.height());
+}
+
+TEST(FloatSize, Divide)
+{
+ WebCore::FloatSize a(1024.0f, 768.0f);
+
+ WebCore::FloatSize divided = a / 2.0f;
+
+ EXPECT_FLOAT_EQ(512.0f, divided.width());
+ EXPECT_FLOAT_EQ(384.0f, divided.height());
+
+ WebCore::FloatSize b(512.0f, 256.0f);
+
+ WebCore::FloatSize divided2 = 1024.0f / b;
+
+ EXPECT_FLOAT_EQ(2.0f, divided2.width());
+ EXPECT_FLOAT_EQ(4.0f, divided2.height());
+}
+
+TEST(FloatSize, Equality)
+{
+ WebCore::FloatSize a(1024.0f, 768.0f);
+ WebCore::FloatSize b(1024.0f, 768.0f);
+ WebCore::FloatSize c(768.0f, 534.0F);
+
+ ASSERT_TRUE(a == b);
+ ASSERT_FALSE(a != b);
+ ASSERT_FALSE(a == c);
+ ASSERT_TRUE(a != c);
+
+ ASSERT_TRUE(WebCore::areEssentiallyEqual(a, b));
+ ASSERT_FALSE(WebCore::areEssentiallyEqual(a, c));
+}
+
+TEST(FloatSize, Floors)
+{
+ WebCore::FloatSize a(1024.4f, 768.8f);
+
+ WebCore::IntSize floorSize = WebCore::flooredIntSize(a);
+
+ EXPECT_EQ(1024, floorSize.width());
+ EXPECT_EQ(768, floorSize.height());
+
+ WebCore::IntPoint floorPoint = WebCore::flooredIntPoint(a);
+
+ EXPECT_EQ(1024, floorPoint.x());
+ EXPECT_EQ(768, floorPoint.y());
+}
+
+TEST(FloatSize, Rounded)
+{
+ WebCore::FloatSize a(1024.4f, 768.8f);
+
+ WebCore::IntSize roundedSize = WebCore::roundedIntSize(a);
+
+ EXPECT_EQ(1024, roundedSize.width());
+ EXPECT_EQ(769, roundedSize.height());
+
+ WebCore::IntSize expandedSize = WebCore::expandedIntSize(a);
+
+ EXPECT_EQ(1025, expandedSize.width());
+ EXPECT_EQ(769, expandedSize.height());
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/GridPosition.cpp b/Tools/TestWebKitAPI/Tests/WebCore/GridPosition.cpp
new file mode 100644
index 000000000..416ebd1f7
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/GridPosition.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2017 Igalia, S.L. 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <WebCore/GridPosition.h>
+
+namespace TestWebKitAPI {
+
+TEST(GridPositionTest, GridPositionLimits)
+{
+
+ WebCore::GridPosition gridPosition;
+
+ gridPosition.setExplicitPosition(999999, "");
+ EXPECT_EQ(gridPosition.integerPosition(), 999999);
+ gridPosition.setExplicitPosition(1000000, "");
+ EXPECT_EQ(gridPosition.integerPosition(), 1000000);
+ gridPosition.setExplicitPosition(1000001, "");
+ EXPECT_EQ(gridPosition.integerPosition(), 1000000);
+ gridPosition.setExplicitPosition(INT_MAX, "");
+ EXPECT_EQ(gridPosition.integerPosition(), 1000000);
+ gridPosition.setExplicitPosition(-999999, "");
+ EXPECT_EQ(gridPosition.integerPosition(), -999999);
+ gridPosition.setExplicitPosition(-1000000, "");
+ EXPECT_EQ(gridPosition.integerPosition(), -1000000);
+ gridPosition.setExplicitPosition(-1000001, "");
+ EXPECT_EQ(gridPosition.integerPosition(), -1000000);
+ gridPosition.setExplicitPosition(INT_MIN, "");
+ EXPECT_EQ(gridPosition.integerPosition(), -1000000);
+
+ gridPosition.setSpanPosition(999999, "");
+ EXPECT_EQ(gridPosition.spanPosition(), 999999);
+ gridPosition.setSpanPosition(1000000, "");
+ EXPECT_EQ(gridPosition.spanPosition(), 1000000);
+ gridPosition.setSpanPosition(1000001, "");
+ EXPECT_EQ(gridPosition.spanPosition(), 1000000);
+ gridPosition.setSpanPosition(INT_MAX, "");
+ EXPECT_EQ(gridPosition.spanPosition(), 1000000);
+ gridPosition.setSpanPosition(-999999, "");
+ EXPECT_EQ(gridPosition.spanPosition(), -999999);
+ gridPosition.setSpanPosition(-1000000, "");
+ EXPECT_EQ(gridPosition.spanPosition(), -1000000);
+ gridPosition.setSpanPosition(-1000001, "");
+ EXPECT_EQ(gridPosition.spanPosition(), -1000000);
+ gridPosition.setSpanPosition(INT_MIN, "");
+ EXPECT_EQ(gridPosition.spanPosition(), -1000000);
+
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/HTMLParserIdioms.cpp b/Tools/TestWebKitAPI/Tests/WebCore/HTMLParserIdioms.cpp
new file mode 100644
index 000000000..6e9e738ab
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/HTMLParserIdioms.cpp
@@ -0,0 +1,164 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include "Test.h"
+#include <WebCore/HTMLParserIdioms.h>
+#include <wtf/text/WTFString.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+static int testParseHTMLInteger(const String& input)
+{
+ auto optionalResult = parseHTMLInteger(input);
+ EXPECT_TRUE(!!optionalResult);
+ return optionalResult.value_or(0);
+}
+
+static bool parseHTMLIntegerFails(const String& input)
+{
+ return !parseHTMLInteger(input);
+}
+
+TEST(WebCoreHTMLParserIdioms, parseHTMLInteger)
+{
+ EXPECT_EQ(0, testParseHTMLInteger("0"));
+ EXPECT_EQ(0, testParseHTMLInteger("-0"));
+ EXPECT_EQ(0, testParseHTMLInteger("+0"));
+ EXPECT_EQ(123, testParseHTMLInteger("123"));
+ EXPECT_EQ(123, testParseHTMLInteger("+123"));
+ EXPECT_EQ(-123, testParseHTMLInteger("-123"));
+ EXPECT_EQ(123, testParseHTMLInteger(" 123"));
+ EXPECT_EQ(123, testParseHTMLInteger("123 "));
+ EXPECT_EQ(123, testParseHTMLInteger(" 123 "));
+ EXPECT_EQ(123, testParseHTMLInteger("123abc"));
+ EXPECT_EQ(-123, testParseHTMLInteger("-123abc"));
+ EXPECT_EQ(123, testParseHTMLInteger(" +123"));
+ EXPECT_EQ(-123, testParseHTMLInteger(" -123"));
+ EXPECT_EQ(12, testParseHTMLInteger(" 12 3"));
+ EXPECT_EQ(1, testParseHTMLInteger("1.0"));
+ EXPECT_EQ(1, testParseHTMLInteger("1."));
+ EXPECT_EQ(1, testParseHTMLInteger("1e1"));
+
+ // All HTML whitespaces.
+ EXPECT_EQ(123, testParseHTMLInteger(" \t\r\n\f123"));
+
+ // Boundaries.
+ EXPECT_EQ(-2147483648, testParseHTMLInteger("-2147483648"));
+ EXPECT_EQ(2147483647, testParseHTMLInteger("2147483647"));
+
+ // Failure cases.
+ EXPECT_TRUE(parseHTMLIntegerFails("-2147483649"));
+ EXPECT_TRUE(parseHTMLIntegerFails("2147483648"));
+ EXPECT_TRUE(parseHTMLIntegerFails("111111111111111111"));
+ EXPECT_TRUE(parseHTMLIntegerFails(""));
+ EXPECT_TRUE(parseHTMLIntegerFails(" "));
+ EXPECT_TRUE(parseHTMLIntegerFails(" "));
+ EXPECT_TRUE(parseHTMLIntegerFails("+"));
+ EXPECT_TRUE(parseHTMLIntegerFails("+ 123"));
+ EXPECT_TRUE(parseHTMLIntegerFails("-"));
+ EXPECT_TRUE(parseHTMLIntegerFails("- 123"));
+ EXPECT_TRUE(parseHTMLIntegerFails("a"));
+ EXPECT_TRUE(parseHTMLIntegerFails("-a"));
+ EXPECT_TRUE(parseHTMLIntegerFails("+-123"));
+ EXPECT_TRUE(parseHTMLIntegerFails("-+123"));
+ EXPECT_TRUE(parseHTMLIntegerFails("++123"));
+ EXPECT_TRUE(parseHTMLIntegerFails("--123"));
+ EXPECT_TRUE(parseHTMLIntegerFails("\v123")); // '\v' is an ASCII space but not an HTML whitespace.
+ EXPECT_TRUE(parseHTMLIntegerFails("a123"));
+ EXPECT_TRUE(parseHTMLIntegerFails("+a123"));
+ EXPECT_TRUE(parseHTMLIntegerFails("-a123"));
+ EXPECT_TRUE(parseHTMLIntegerFails(".1"));
+ EXPECT_TRUE(parseHTMLIntegerFails("infinity"));
+}
+
+static unsigned testParseHTMLNonNegativeInteger(const String& input)
+{
+ auto optionalResult = parseHTMLNonNegativeInteger(input);
+ EXPECT_TRUE(!!optionalResult);
+ return optionalResult.value_or(0);
+}
+
+static bool parseHTMLNonNegativeIntegerFails(const String& input)
+{
+ return !parseHTMLNonNegativeInteger(input);
+}
+
+TEST(WebCoreHTMLParserIdioms, parseHTMLNonNegativeInteger)
+{
+ EXPECT_EQ(123u, testParseHTMLNonNegativeInteger("123"));
+ EXPECT_EQ(123u, testParseHTMLNonNegativeInteger("+123"));
+ EXPECT_EQ(123u, testParseHTMLNonNegativeInteger(" 123"));
+ EXPECT_EQ(123u, testParseHTMLNonNegativeInteger("123 "));
+ EXPECT_EQ(123u, testParseHTMLNonNegativeInteger(" 123 "));
+ EXPECT_EQ(123u, testParseHTMLNonNegativeInteger("123abc"));
+ EXPECT_EQ(123u, testParseHTMLNonNegativeInteger(" +123"));
+ EXPECT_EQ(12u, testParseHTMLNonNegativeInteger(" 12 3"));
+ EXPECT_EQ(1u, testParseHTMLNonNegativeInteger("1.0"));
+ EXPECT_EQ(1u, testParseHTMLNonNegativeInteger("1."));
+ EXPECT_EQ(1u, testParseHTMLNonNegativeInteger("1e1"));
+
+ // All HTML whitespaces.
+ EXPECT_EQ(123u, testParseHTMLNonNegativeInteger(" \t\r\n\f123"));
+
+ // Boundaries.
+ EXPECT_EQ(0u, testParseHTMLNonNegativeInteger("+0"));
+ EXPECT_EQ(0u, testParseHTMLNonNegativeInteger("0"));
+ EXPECT_EQ(0u, testParseHTMLNonNegativeInteger("-0"));
+ EXPECT_EQ(2147483647u, testParseHTMLNonNegativeInteger("2147483647"));
+
+ // Failure cases.
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("-1"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("2147483648"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("2147483649"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("111111111111111111"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails(" -123"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("-123"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("-123abc"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails(""));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails(" "));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails(" "));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("+"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("+ 123"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("-"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("- 123"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("a"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("-a"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("+-123"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("-+123"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("++123"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("--123"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("\v123")); // '\v' is an ASCII space but not an HTML whitespace.
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("a123"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("+a123"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("-a123"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails(".1"));
+ EXPECT_TRUE(parseHTMLNonNegativeIntegerFails("infinity"));
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/IntPoint.cpp b/Tools/TestWebKitAPI/Tests/WebCore/IntPoint.cpp
new file mode 100644
index 000000000..aa332e5c3
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/IntPoint.cpp
@@ -0,0 +1,283 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <WebCore/FloatPoint.h>
+#include <WebCore/IntPoint.h>
+#include <WebCore/IntSize.h>
+
+#if USE(CG)
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
+namespace TestWebKitAPI {
+
+static void testGetAndSet(WebCore::IntPoint point)
+{
+ point.setX(1);
+ EXPECT_EQ(1, point.x());
+ point.setY(2);
+ EXPECT_EQ(2, point.y());
+}
+
+TEST(IntPoint, DefaultConstruction)
+{
+ WebCore::IntPoint test;
+
+ EXPECT_EQ(0, test.x());
+ EXPECT_EQ(0, test.y());
+ ASSERT_TRUE(test.isZero());
+
+ testGetAndSet(test);
+}
+
+TEST(IntPoint, ValueConstruction)
+{
+ WebCore::IntPoint test(10, 9);
+
+ EXPECT_EQ(10, test.x());
+ EXPECT_EQ(9, test.y());
+
+ testGetAndSet(test);
+}
+
+TEST(IntPoint, ZeroConstruction)
+{
+ WebCore::IntPoint test = WebCore::IntPoint::zero();
+
+ EXPECT_EQ(0, test.x());
+ EXPECT_EQ(0, test.y());
+ ASSERT_TRUE(test.isZero());
+}
+
+TEST(IntPoint, IntSizeConstruction)
+{
+ WebCore::IntSize testInput(2003, 1997);
+ WebCore::IntPoint test(testInput);
+
+ EXPECT_EQ(2003, test.x());
+ EXPECT_EQ(1997, test.y());
+ ASSERT_FALSE(test.isZero());
+}
+
+TEST(IntPoint, FloatPointConstruction)
+{
+ WebCore::FloatPoint testInput(2003.2f, 1997.3f);
+ WebCore::IntPoint test(testInput);
+
+ EXPECT_EQ(2003, test.x());
+ EXPECT_EQ(1997, test.y());
+ ASSERT_FALSE(test.isZero());
+}
+
+TEST(IntPoint, Move)
+{
+ WebCore::IntPoint test(10, 20);
+ WebCore::IntSize size(30, 50);
+
+ test.move(size);
+
+ EXPECT_EQ(40, test.x());
+ EXPECT_EQ(70, test.y());
+
+ test.move(-2, 8);
+
+ EXPECT_EQ(38, test.x());
+ EXPECT_EQ(78, test.y());
+
+ WebCore::IntPoint offset(100, 100);
+
+ test.moveBy(offset);
+
+ EXPECT_EQ(138, test.x());
+ EXPECT_EQ(178, test.y());
+}
+
+TEST(IntPoint, Scale)
+{
+ WebCore::IntPoint test(10, 20);
+
+ test.scale(2.0);
+
+ EXPECT_EQ(20, test.x());
+ EXPECT_EQ(40, test.y());
+
+ test.scale(3.0, 1.5);
+
+ EXPECT_EQ(60, test.x());
+ EXPECT_EQ(60, test.y());
+}
+
+TEST(IntPoint, Expand)
+{
+ WebCore::IntPoint a(10, 20);
+ WebCore::IntPoint b(20, 40);
+
+ auto c = a.expandedTo(b);
+
+ EXPECT_EQ(20, c.x());
+ EXPECT_EQ(40, c.y());
+}
+
+TEST(IntPoint, Shrink)
+{
+ WebCore::IntPoint a(10, 20);
+ WebCore::IntPoint b(20, 40);
+
+ auto c = b.shrunkTo(a);
+
+ EXPECT_EQ(10, c.x());
+ EXPECT_EQ(20, c.y());
+}
+
+TEST(IntPoint, Transpose)
+{
+ WebCore::IntPoint a(10, 20);
+
+ auto b = a.transposedPoint();
+
+ EXPECT_EQ(20, b.x());
+ EXPECT_EQ(10, b.y());
+}
+
+TEST(IntPoint, Cast)
+{
+ WebCore::IntPoint a(10, 20);
+
+ WebCore::IntSize as = WebCore::toIntSize(a);
+ EXPECT_EQ(10, as.width());
+ EXPECT_EQ(20, as.height());
+
+#if USE(CG)
+ CGPoint cgPoint = a;
+
+ ASSERT_FLOAT_EQ(10.0f, cgPoint.x);
+ ASSERT_FLOAT_EQ(20.0f, cgPoint.y);
+
+ WebCore::IntPoint fromCGPoint(cgPoint);
+ EXPECT_EQ(10, fromCGPoint.x());
+ EXPECT_EQ(20, fromCGPoint.y());
+ ASSERT_TRUE(a == fromCGPoint);
+#endif
+
+#if PLATFORM(WIN)
+ POINT gdiPoint = a;
+
+ ASSERT_FLOAT_EQ(10.0f, gdiPoint.x);
+ ASSERT_FLOAT_EQ(20.0f, gdiPoint.y);
+
+ WebCore::IntPoint fromGDIPoint(gdiPoint);
+ EXPECT_EQ(10, fromGDIPoint.x());
+ EXPECT_EQ(20, fromGDIPoint.y());
+ ASSERT_TRUE(a == fromGDIPoint);
+
+ D2D1_POINT_2F d2dPointF = a;
+
+ ASSERT_FLOAT_EQ(10.0f, d2dPointF.x);
+ ASSERT_FLOAT_EQ(20.0f, d2dPointF.y);
+
+ WebCore::IntPoint fromD2DPointF(d2dPointF);
+ EXPECT_EQ(10, fromD2DPointF.x());
+ EXPECT_EQ(20, fromD2DPointF.y());
+ ASSERT_TRUE(a == fromD2DPointF);
+
+ D2D1_POINT_2U d2dPointU = a;
+
+ ASSERT_FLOAT_EQ(10.0f, d2dPointU.x);
+ ASSERT_FLOAT_EQ(20.0f, d2dPointU.y);
+
+ WebCore::IntPoint fromD2DPointU(d2dPointU);
+ EXPECT_EQ(10, fromD2DPointU.x());
+ EXPECT_EQ(20, fromD2DPointU.y());
+ ASSERT_TRUE(a == fromD2DPointU);
+#endif
+}
+
+TEST(IntPoint, Addition)
+{
+ WebCore::IntPoint a(10, 20);
+ WebCore::IntPoint b(50, 60);
+ WebCore::IntSize bs(50, 60);
+
+ auto c = a + b;
+
+ EXPECT_EQ(60, c.x());
+ EXPECT_EQ(80, c.y());
+
+ a += bs;
+
+ EXPECT_EQ(60, a.x());
+ EXPECT_EQ(80, a.y());
+}
+
+TEST(IntPoint, Subtraction)
+{
+ WebCore::IntPoint a(100, 80);
+ WebCore::IntPoint b(50, 60);
+ WebCore::IntSize bs(50, 60);
+
+ WebCore::IntSize c = a - b;
+
+ EXPECT_EQ(50, c.width());
+ EXPECT_EQ(20, c.height());
+
+ WebCore::IntPoint d = a - bs;
+
+ EXPECT_EQ(50, d.x());
+ EXPECT_EQ(20, d.y());
+
+ a -= bs;
+
+ EXPECT_EQ(50, a.x());
+ EXPECT_EQ(20, a.y());
+}
+
+TEST(IntPoint, Negation)
+{
+ WebCore::IntPoint a(100, 80);
+ auto b = -a;
+
+ EXPECT_EQ(-100, b.x());
+ EXPECT_EQ(-80, b.y());
+}
+
+TEST(IntPoint, Equality)
+{
+ WebCore::IntPoint a(100, 80);
+ WebCore::IntPoint b(70, 50);
+ WebCore::IntPoint c(100, 80);
+
+ ASSERT_TRUE(a == c);
+ ASSERT_FALSE(a == b);
+ ASSERT_FALSE(a != c);
+ ASSERT_TRUE(a != b);
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/IntRect.cpp b/Tools/TestWebKitAPI/Tests/WebCore/IntRect.cpp
new file mode 100644
index 000000000..7392f06a7
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/IntRect.cpp
@@ -0,0 +1,615 @@
+/*
+ * Copyright (C) 2014-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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <WebCore/FloatRect.h>
+#include <WebCore/IntPoint.h>
+#include <WebCore/IntRect.h>
+#include <WebCore/IntSize.h>
+
+#if USE(CG)
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
+namespace TestWebKitAPI {
+
+static void testGetAndSet(WebCore::IntRect rect)
+{
+ rect.setX(1);
+ EXPECT_EQ(1, rect.x());
+ rect.setY(2);
+ EXPECT_EQ(2, rect.y());
+ rect.setWidth(203);
+ EXPECT_EQ(203, rect.width());
+ rect.setHeight(73);
+ EXPECT_EQ(73, rect.height());
+}
+
+static void testEmptyRect(const WebCore::IntRect& rect)
+{
+ EXPECT_EQ(0, rect.x());
+ EXPECT_EQ(0, rect.y());
+ EXPECT_EQ(0, rect.width());
+ EXPECT_EQ(0, rect.height());
+ EXPECT_EQ(0, rect.maxX());
+ EXPECT_EQ(0, rect.maxY());
+ EXPECT_TRUE(rect.isEmpty());
+}
+
+TEST(IntRect, DefaultConstruction)
+{
+ WebCore::IntRect test;
+
+ testEmptyRect(test);
+
+ testGetAndSet(test);
+
+ auto location = test.location();
+ EXPECT_EQ(0, location.x());
+ EXPECT_EQ(0, location.y());
+
+ auto size = test.size();
+ EXPECT_EQ(0, size.width());
+ EXPECT_EQ(0, size.height());
+}
+
+TEST(IntRect, ValueConstruction)
+{
+ WebCore::IntRect test(10, 20, 100, 50);
+
+ EXPECT_EQ(10, test.x());
+ EXPECT_EQ(20, test.y());
+ EXPECT_EQ(100, test.width());
+ EXPECT_EQ(50, test.height());
+ EXPECT_EQ(110, test.maxX());
+ EXPECT_EQ(70, test.maxY());
+ EXPECT_FALSE(test.isEmpty());
+
+ auto location = test.location();
+ EXPECT_EQ(10, location.x());
+ EXPECT_EQ(20, location.y());
+
+ auto size = test.size();
+ EXPECT_EQ(100, size.width());
+ EXPECT_EQ(50, size.height());
+}
+
+TEST(IntRect, PointSizeConstruction)
+{
+ WebCore::IntPoint location(20, 30);
+ WebCore::IntSize size(100, 50);
+
+ WebCore::IntRect test(location, size);
+
+ EXPECT_EQ(20, test.x());
+ EXPECT_EQ(30, test.y());
+ EXPECT_EQ(100, test.width());
+ EXPECT_EQ(50, test.height());
+ EXPECT_EQ(120, test.maxX());
+ EXPECT_EQ(80, test.maxY());
+ EXPECT_FALSE(test.isEmpty());
+
+ auto location2 = test.location();
+ EXPECT_EQ(20, location2.x());
+ EXPECT_EQ(30, location2.y());
+
+ auto size2 = test.size();
+ EXPECT_EQ(100, size2.width());
+ EXPECT_EQ(50, size2.height());
+}
+
+TEST(IntRect, FloatRectConstruction)
+{
+ WebCore::FloatRect rect(20.0f, 30.0f, 150.0f, 300.0f);
+
+ WebCore::IntRect test(rect);
+
+ EXPECT_EQ(20, test.x());
+ EXPECT_EQ(30, test.y());
+ EXPECT_EQ(150, test.width());
+ EXPECT_EQ(300, test.height());
+ EXPECT_EQ(170, test.maxX());
+ EXPECT_EQ(330, test.maxY());
+ EXPECT_FALSE(test.isEmpty());
+
+ auto location = test.location();
+ EXPECT_EQ(20, location.x());
+ EXPECT_EQ(30, location.y());
+
+ auto size = test.size();
+ EXPECT_EQ(150, size.width());
+ EXPECT_EQ(300, size.height());
+}
+
+TEST(IntRect, SetLocationAndSize)
+{
+ WebCore::IntRect rect;
+
+ testEmptyRect(rect);
+
+ WebCore::IntPoint location(10, 20);
+
+ rect.setLocation(location);
+
+ EXPECT_EQ(10, rect.x());
+ EXPECT_EQ(20, rect.y());
+ EXPECT_EQ(0, rect.width());
+ EXPECT_EQ(0, rect.height());
+ EXPECT_EQ(10, rect.maxX());
+ EXPECT_EQ(20, rect.maxY());
+ EXPECT_TRUE(rect.isEmpty());
+
+ WebCore::IntSize size(100, 200);
+
+ rect.setSize(size);
+
+ EXPECT_EQ(10, rect.x());
+ EXPECT_EQ(20, rect.y());
+ EXPECT_EQ(100, rect.width());
+ EXPECT_EQ(200, rect.height());
+ EXPECT_EQ(110, rect.maxX());
+ EXPECT_EQ(220, rect.maxY());
+ EXPECT_FALSE(rect.isEmpty());
+}
+
+TEST(IntRect, Center)
+{
+ WebCore::IntRect rect(20, 40, 100, 200);
+
+ auto center = rect.center();
+
+ EXPECT_EQ(70, center.x());
+ EXPECT_EQ(140, center.y());
+}
+
+TEST(IntRect, Move)
+{
+ WebCore::IntRect rect(20, 30, 100, 200);
+
+ WebCore::IntSize delta(10, 20);
+
+ rect.move(delta);
+
+ EXPECT_EQ(30, rect.x());
+ EXPECT_EQ(50, rect.y());
+
+ WebCore::IntPoint deltaPoint(-20, -40);
+
+ rect.moveBy(deltaPoint);
+
+ EXPECT_EQ(10, rect.x());
+ EXPECT_EQ(10, rect.y());
+
+ rect.move(-10, 22);
+
+ EXPECT_EQ(0, rect.x());
+ EXPECT_EQ(32, rect.y());
+}
+
+TEST(IntRect, Expand)
+{
+ WebCore::IntRect rect(20, 30, 100, 200);
+
+ WebCore::IntSize size(100, 100);
+
+ rect.expand(size);
+
+ EXPECT_EQ(200, rect.width());
+ EXPECT_EQ(300, rect.height());
+
+ rect.expand(55, 22);
+
+ EXPECT_EQ(255, rect.width());
+ EXPECT_EQ(322, rect.height());
+
+ WebCore::IntSize size2(-10, -20);
+
+ rect.expand(size2);
+
+ EXPECT_EQ(245, rect.width());
+ EXPECT_EQ(302, rect.height());
+
+ rect.expand(-5, -2);
+
+ EXPECT_EQ(240, rect.width());
+ EXPECT_EQ(300, rect.height());
+}
+
+TEST(IntRect, Contract)
+{
+ WebCore::IntRect rect(20, 30, 100, 200);
+
+ WebCore::IntSize size(50, 100);
+
+ rect.contract(size);
+
+ EXPECT_EQ(50, rect.width());
+ EXPECT_EQ(100, rect.height());
+
+ rect.contract(25, 22);
+
+ EXPECT_EQ(25, rect.width());
+ EXPECT_EQ(78, rect.height());
+
+ WebCore::IntSize size2(-10, -20);
+
+ rect.contract(size2);
+
+ EXPECT_EQ(35, rect.width());
+ EXPECT_EQ(98, rect.height());
+
+ rect.contract(-5, -2);
+
+ EXPECT_EQ(40, rect.width());
+ EXPECT_EQ(100, rect.height());
+}
+
+TEST(IntRect, ShiftXEdge)
+{
+ WebCore::IntRect rect(20, 30, 100, 200);
+
+ rect.shiftXEdgeTo(77);
+
+ EXPECT_EQ(77, rect.x());
+ EXPECT_EQ(120, rect.maxX());
+ EXPECT_EQ(30, rect.y());
+ EXPECT_EQ(230, rect.maxY());
+ EXPECT_EQ(43, rect.width());
+ EXPECT_EQ(200, rect.height());
+
+ rect.shiftMaxXEdgeTo(200);
+
+ EXPECT_EQ(77, rect.x());
+ EXPECT_EQ(200, rect.maxX());
+ EXPECT_EQ(30, rect.y());
+ EXPECT_EQ(230, rect.maxY());
+ EXPECT_EQ(123, rect.width());
+ EXPECT_EQ(200, rect.height());
+}
+
+TEST(IntRect, ShiftYEdge)
+{
+ WebCore::IntRect rect(20, 30, 100, 200);
+
+ rect.shiftYEdgeTo(59.0f);
+
+ EXPECT_EQ(20, rect.x());
+ EXPECT_EQ(120, rect.maxX());
+ EXPECT_EQ(59, rect.y());
+ EXPECT_EQ(230, rect.maxY());
+ EXPECT_EQ(100, rect.width());
+ EXPECT_EQ(171, rect.height());
+
+ rect.shiftMaxYEdgeTo(270.0f);
+
+ EXPECT_EQ(20, rect.x());
+ EXPECT_EQ(120, rect.maxX());
+ EXPECT_EQ(59, rect.y());
+ EXPECT_EQ(270, rect.maxY());
+ EXPECT_EQ(100, rect.width());
+ EXPECT_EQ(211, rect.height());
+}
+
+TEST(IntRect, Inflate)
+{
+ WebCore::IntRect rect(20, 30, 100, 200);
+
+ rect.inflateX(5);
+
+ EXPECT_EQ(15, rect.x());
+ EXPECT_EQ(125, rect.maxX());
+
+ rect.inflateY(4);
+
+ EXPECT_EQ(26, rect.y());
+ EXPECT_EQ(234, rect.maxY());
+
+ rect.inflate(10);
+
+ EXPECT_EQ(5, rect.x());
+ EXPECT_EQ(135, rect.maxX());
+ EXPECT_EQ(16, rect.y());
+ EXPECT_EQ(244, rect.maxY());
+}
+
+TEST(IntRect, Corners)
+{
+ WebCore::IntRect rect(20, 30, 100, 200);
+
+ WebCore::FloatPoint topLeft = rect.minXMinYCorner();
+ EXPECT_EQ(20, topLeft.x());
+ EXPECT_EQ(30, topLeft.y());
+
+ WebCore::FloatPoint topRight = rect.maxXMinYCorner();
+ EXPECT_EQ(120, topRight.x());
+ EXPECT_EQ(30, topRight.y());
+
+ WebCore::FloatPoint bottomLeft = rect.minXMaxYCorner();
+ EXPECT_EQ(20, bottomLeft.x());
+ EXPECT_EQ(230, bottomLeft.y());
+
+ WebCore::FloatPoint bottomRight = rect.maxXMaxYCorner();
+ EXPECT_EQ(120, bottomRight.x());
+ EXPECT_EQ(230, bottomRight.y());
+}
+
+TEST(IntRect, Contains)
+{
+ WebCore::IntRect rect(20, 30, 100, 200);
+
+ WebCore::IntRect contained(30, 40, 50, 100);
+
+ ASSERT_TRUE(rect.contains(contained));
+
+ WebCore::IntRect outside(120, 230, 50, 100);
+
+ ASSERT_FALSE(rect.contains(outside));
+
+ WebCore::IntRect intersects(10, 20, 90, 180);
+
+ ASSERT_FALSE(rect.contains(intersects));
+
+ WebCore::IntPoint pointInside(60, 70);
+
+ ASSERT_TRUE(rect.contains(pointInside));
+
+ WebCore::IntPoint pointOutside(160, 270);
+
+ ASSERT_FALSE(rect.contains(pointOutside));
+
+ WebCore::IntPoint pointOnLine(20, 30);
+
+ ASSERT_TRUE(rect.contains(pointOnLine));
+
+ ASSERT_TRUE(rect.contains(60, 70));
+ ASSERT_FALSE(rect.contains(160, 270));
+}
+
+TEST(IntRect, Intersects)
+{
+ WebCore::IntRect rect(20, 30, 100, 200);
+
+ WebCore::IntRect contained(30, 40, 50, 100);
+
+ ASSERT_TRUE(rect.intersects(contained));
+
+ WebCore::IntRect outside(120, 230, 50, 100);
+
+ ASSERT_FALSE(rect.intersects(outside));
+
+ WebCore::IntRect intersects(10, 20, 90, 180);
+
+ ASSERT_TRUE(rect.intersects(intersects));
+}
+
+static void testIntersectResult(const WebCore::IntRect& rect)
+{
+ EXPECT_EQ(70, rect.x());
+ EXPECT_EQ(120, rect.maxX());
+ EXPECT_EQ(80, rect.y());
+ EXPECT_EQ(230, rect.maxY());
+}
+
+TEST(IntRect, Intersect)
+{
+ WebCore::IntRect rectA(20, 30, 100, 200);
+ WebCore::IntRect rectB(70, 80, 100, 200);
+
+ rectA.intersect(rectB);
+
+ testIntersectResult(rectA);
+
+ WebCore::IntRect rectC(20, 30, 100, 200);
+
+ auto intersected = WebCore::intersection(rectC, rectB);
+
+ testIntersectResult(intersected);
+}
+
+static void testUnitedRects(const WebCore::IntRect& united)
+{
+ EXPECT_EQ(20, united.x());
+ EXPECT_EQ(170, united.maxX());
+ EXPECT_EQ(30, united.y());
+ EXPECT_EQ(280, united.maxY());
+}
+
+TEST(IntRect, Unite)
+{
+ WebCore::IntRect rectA(20, 30, 100, 200);
+ WebCore::IntRect rectB(70, 80, 100, 200);
+
+ rectA.unite(rectB);
+
+ testUnitedRects(rectA);
+
+ WebCore::IntRect rectC(20, 30, 100, 200);
+
+ auto united = WebCore::unionRect(rectC, rectB);
+
+ testUnitedRects(united);
+}
+
+TEST(IntRect, Scale)
+{
+ WebCore::IntRect rect(20, 30, 100, 200);
+
+ rect.scale(2.0f);
+
+ EXPECT_EQ(40, rect.x());
+ EXPECT_EQ(240, rect.maxX());
+ EXPECT_EQ(60, rect.y());
+ EXPECT_EQ(460, rect.maxY());
+}
+
+TEST(IntRect, Transpose)
+{
+ WebCore::IntRect rect(20, 30, 100, 200);
+
+ auto transposed = rect.transposedRect();
+
+ EXPECT_EQ(30, transposed.x());
+ EXPECT_EQ(230, transposed.maxX());
+ EXPECT_EQ(20, transposed.y());
+ EXPECT_EQ(120, transposed.maxY());
+}
+
+static void checkCastRect(const WebCore::IntRect& rect)
+{
+ EXPECT_EQ(10, rect.x());
+ EXPECT_EQ(40, rect.maxX());
+ EXPECT_EQ(20, rect.y());
+ EXPECT_EQ(60, rect.maxY());
+ EXPECT_EQ(30, rect.width());
+ EXPECT_EQ(40, rect.height());
+}
+
+TEST(IntRect, Casting)
+{
+ WebCore::IntRect rect(10, 20, 30, 40);
+
+#if USE(CG)
+ CGRect cgRect = CGRectMake(10.0, 20.0, 30.0, 40.0);
+
+ WebCore::IntRect rectFromCGRect(cgRect);
+
+ checkCastRect(rectFromCGRect);
+#endif
+
+#if PLATFORM(WIN)
+ RECT gdiRect = rect;
+
+ EXPECT_EQ(10, gdiRect.left);
+ EXPECT_EQ(20, gdiRect.top);
+ EXPECT_EQ(40, gdiRect.right);
+ EXPECT_EQ(60, gdiRect.bottom);
+
+ WebCore::IntRect rectFromGDIRect(gdiRect);
+
+ checkCastRect(rectFromGDIRect);
+
+ D2D1_RECT_U d2dRectU = rect;
+
+ EXPECT_EQ(10, d2dRectU.left);
+ EXPECT_EQ(20, d2dRectU.top);
+ EXPECT_EQ(40, d2dRectU.right);
+ EXPECT_EQ(60, d2dRectU.bottom);
+
+ WebCore::IntRect rectFromD2DRectU(d2dRectU);
+
+ checkCastRect(rectFromD2DRectU);
+
+ D2D1_RECT_F d2dRectF = rect;
+
+ EXPECT_FLOAT_EQ(10.0f, d2dRectF.left);
+ EXPECT_FLOAT_EQ(20.0f, d2dRectF.top);
+ EXPECT_FLOAT_EQ(40.0f, d2dRectF.right);
+ EXPECT_FLOAT_EQ(60.0f, d2dRectF.bottom);
+
+ WebCore::IntRect rectFromD2DRectF(d2dRectF);
+
+ checkCastRect(rectFromD2DRectF);
+#endif
+}
+
+static void checkSubtractionResult1(const WebCore::IntRect& rect)
+{
+ EXPECT_EQ(-10, rect.x());
+ EXPECT_EQ(90, rect.maxX());
+ EXPECT_EQ(-10, rect.y());
+ EXPECT_EQ(90, rect.maxY());
+ EXPECT_EQ(100, rect.width());
+ EXPECT_EQ(100, rect.height());
+}
+
+static void checkSubtractionResult2(const WebCore::IntRect& rect)
+{
+ EXPECT_EQ(-40, rect.x());
+ EXPECT_EQ(60, rect.maxX());
+ EXPECT_EQ(-50, rect.y());
+ EXPECT_EQ(50, rect.maxY());
+ EXPECT_EQ(100, rect.width());
+ EXPECT_EQ(100, rect.height());
+}
+
+TEST(IntRect, Subtraction)
+{
+ WebCore::IntRect rect(10, 20, 100, 100);
+ WebCore::IntPoint rightSide(20, 30);
+
+ rect -= rightSide;
+
+ checkSubtractionResult1(rect);
+
+ auto rect2 = rect - WebCore::IntPoint(30, 40);
+ checkSubtractionResult2(rect2);
+}
+
+TEST(IntRect, Equality)
+{
+ WebCore::IntRect rect(10, 20, 100, 100);
+ WebCore::IntRect rect2(10, 20, 100, 100);
+ WebCore::IntRect rightSide(110, 20, 20, 100);
+
+ ASSERT_TRUE(rect == rect2);
+ ASSERT_FALSE(rect != rect2);
+ ASSERT_TRUE(rect != rightSide);
+ ASSERT_FALSE(rect == rightSide);
+}
+
+static void checkEnclosingIntRect(const WebCore::IntRect& rect)
+{
+ EXPECT_EQ(10, rect.x());
+ EXPECT_EQ(41, rect.maxX());
+ EXPECT_EQ(21, rect.y());
+ EXPECT_EQ(62, rect.maxY());
+ EXPECT_EQ(31, rect.width());
+ EXPECT_EQ(41, rect.height());
+}
+
+TEST(IntRect, EnclosingIntRect)
+{
+#if USE(CG)
+ CGRect cgRect = CGRectMake(10.5, 21.3, 30.1, 40.0);
+
+ WebCore::IntRect enclosingCG = WebCore::enclosingIntRect(cgRect);
+
+ checkEnclosingIntRect(enclosingCG);
+#endif
+}
+
+TEST(IntRect, AreaAndDistances)
+{
+ WebCore::IntRect rect(10, 20, 100, 100);
+
+ EXPECT_EQ(10000U, rect.area().unsafeGet());
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/IntSize.cpp b/Tools/TestWebKitAPI/Tests/WebCore/IntSize.cpp
new file mode 100644
index 000000000..a55942f74
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/IntSize.cpp
@@ -0,0 +1,332 @@
+/*
+ * Copyright (C) 2014-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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <WebCore/FloatSize.h>
+#include <WebCore/IntSize.h>
+
+#if USE(CG)
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
+namespace TestWebKitAPI {
+
+static void testGetAndSet(WebCore::IntSize rect)
+{
+ rect.setWidth(203);
+ EXPECT_EQ(203, rect.width());
+ rect.setHeight(73);
+ EXPECT_EQ(73, rect.height());
+}
+
+static void testEmptySize(const WebCore::IntSize& rect)
+{
+ EXPECT_EQ(0, rect.width());
+ EXPECT_EQ(0, rect.height());
+ EXPECT_TRUE(rect.isEmpty());
+ EXPECT_TRUE(rect.isZero());
+}
+
+TEST(IntSize, DefaultConstruction)
+{
+ WebCore::IntSize test;
+
+ testEmptySize(test);
+
+ testGetAndSet(test);
+}
+
+TEST(IntSize, ValueConstruction)
+{
+ WebCore::IntSize test(100, 200);
+
+ EXPECT_EQ(100, test.width());
+ EXPECT_EQ(200, test.height());
+ EXPECT_FALSE(test.isEmpty());
+ EXPECT_FALSE(test.isZero());
+
+ static const float epsilon = 0.0001f;
+ EXPECT_NEAR(0.5f, test.aspectRatio(), epsilon);
+}
+
+TEST(IntSize, FloatSizeConstruction)
+{
+ WebCore::FloatSize size(1024.2, 767.8);
+ WebCore::IntSize test(size);
+
+ EXPECT_EQ(1024, test.width());
+ EXPECT_EQ(767, test.height());
+
+ ASSERT_FALSE(test.isEmpty());
+ ASSERT_FALSE(test.isZero());
+
+ static const double epsilon = 0.001;
+ EXPECT_NEAR(1.335f, test.aspectRatio(), epsilon);
+
+ testGetAndSet(test);
+}
+
+TEST(IntSize, DiagonalLengthAndArea)
+{
+ WebCore::IntSize test(1024, 768);
+
+ EXPECT_EQ(1638400, test.diagonalLengthSquared());
+ EXPECT_EQ(786432U, test.area().unsafeGet());
+}
+
+TEST(IntSize, Scale)
+{
+ WebCore::IntSize test(1024, 768);
+
+ test.scale(2.0f);
+
+ EXPECT_EQ(2048, test.width());
+ EXPECT_EQ(1536, test.height());
+
+ test.scale(0.5f);
+
+ EXPECT_EQ(1024, test.width());
+ EXPECT_EQ(768, test.height());
+
+ test.scale(2.0f, 0.5f);
+
+ EXPECT_EQ(2048, test.width());
+ EXPECT_EQ(384, test.height());
+}
+
+TEST(IntSize, Expand)
+{
+ WebCore::IntSize test(1024, 768);
+
+ EXPECT_EQ(1024, test.width());
+ EXPECT_EQ(768, test.height());
+
+ test.expand(100, 50);
+
+ EXPECT_EQ(1124, test.width());
+ EXPECT_EQ(818, test.height());
+
+ WebCore::IntSize other(2048, 700);
+
+ auto expanded = test.expandedTo(other);
+
+ EXPECT_EQ(2048, expanded.width());
+ EXPECT_EQ(818, expanded.height());
+}
+
+TEST(IntSize, Shrink)
+{
+ WebCore::IntSize test(1024, 768);
+ WebCore::IntSize other(1000, 700);
+
+ auto shrunken = test.shrunkTo(other);
+
+ EXPECT_EQ(1000, shrunken.width());
+ EXPECT_EQ(700, shrunken.height());
+
+ WebCore::IntSize other2(2000.0f, 700.0f);
+
+ auto shrunken2 = test.shrunkTo(other2);
+
+ EXPECT_EQ(1024, shrunken2.width());
+ EXPECT_EQ(700, shrunken2.height());
+}
+
+TEST(IntSize, TransposedSize)
+{
+ WebCore::IntSize test(1024, 768);
+
+ auto transposedSize = test.transposedSize();
+
+ EXPECT_EQ(768, transposedSize.width());
+ EXPECT_EQ(1024, transposedSize.height());
+}
+
+TEST(IntSize, Casting)
+{
+ WebCore::IntSize test(1024, 768);
+
+#if USE(CG)
+ CGSize cgSize = test;
+
+ EXPECT_FLOAT_EQ(1024.0f, cgSize.width);
+ EXPECT_FLOAT_EQ(768.0f, cgSize.height);
+
+ CGSize cgSize2 = CGSizeMake(-22.3f, 14.6f);
+
+ WebCore::IntSize testCG(cgSize2);
+
+ EXPECT_EQ(-22, testCG.width());
+ EXPECT_EQ(14, testCG.height());
+#endif
+
+#if PLATFORM(WIN)
+ D2D1_SIZE_U d2dSizeU = test;
+ EXPECT_EQ(1024, d2dSizeU.width);
+ EXPECT_EQ(768, d2dSizeU.height);
+
+ D2D1_SIZE_F d2dSizeF = test;
+ EXPECT_FLOAT_EQ(1024.0f, d2dSizeF.width);
+ EXPECT_FLOAT_EQ(768.0f, d2dSizeF.height);
+
+ D2D1_SIZE_F d2dSizeF2 = D2D1::SizeF(-22.3f, 14.6f);
+
+ WebCore::IntSize testD2D(d2dSizeF2);
+
+ EXPECT_EQ(-22, testD2D.width());
+ EXPECT_EQ(14, testD2D.height());
+
+ D2D1_SIZE_F d2dSizeU2 = D2D1::SizeF(-23, 16);
+
+ WebCore::IntSize testD2D2(d2dSizeU2);
+
+ EXPECT_EQ(-23, testD2D2.width());
+ EXPECT_EQ(16, testD2D2.height());
+#endif
+}
+
+TEST(IntSize, AddSubtract)
+{
+ WebCore::IntSize a(512, 384);
+ WebCore::IntSize b(100, 100);
+
+ WebCore::IntSize c = a + b;
+
+ EXPECT_EQ(612, c.width());
+ EXPECT_EQ(484, c.height());
+
+ a += b;
+
+ EXPECT_EQ(612, a.width());
+ EXPECT_EQ(484, a.height());
+
+ WebCore::IntSize a2(512, 384);
+
+ WebCore::IntSize d = a2 - b;
+
+ EXPECT_EQ(412, d.width());
+ EXPECT_EQ(284, d.height());
+
+ a2 -= b;
+
+ EXPECT_EQ(412, a2.width());
+ EXPECT_EQ(284, a2.height());
+}
+
+TEST(IntSize, Negation)
+{
+ WebCore::IntSize a(512, 384);
+
+ WebCore::IntSize negated = -a;
+
+ EXPECT_EQ(-512, negated.width());
+ EXPECT_EQ(-384, negated.height());
+}
+
+TEST(IntSize, Equality)
+{
+ WebCore::IntSize a(1024, 768);
+ WebCore::IntSize b(1024, 768);
+ WebCore::IntSize c(768, 534);
+
+ ASSERT_TRUE(a == b);
+ ASSERT_FALSE(a != b);
+ ASSERT_FALSE(a == c);
+ ASSERT_TRUE(a != c);
+}
+
+TEST(IntSize, Contract)
+{
+ WebCore::IntSize a(1024, 768);
+
+ a.contract(100, 50);
+
+ EXPECT_EQ(924, a.width());
+ EXPECT_EQ(718, a.height());
+}
+
+TEST(IntSize, Clamp)
+{
+ WebCore::IntSize a(1024, 768);
+
+ a.clampNegativeToZero();
+
+ EXPECT_EQ(1024, a.width());
+ EXPECT_EQ(768, a.height());
+
+ WebCore::IntSize b(-1024, -768);
+
+ b.clampNegativeToZero();
+
+ EXPECT_EQ(0, b.width());
+ EXPECT_EQ(0, b.height());
+
+ WebCore::IntSize minimumSize(1024, 1000);
+
+ a.clampToMinimumSize(minimumSize);
+
+ EXPECT_EQ(1024, a.width());
+ EXPECT_EQ(1000, a.height());
+}
+
+TEST(IntSize, ConstrainedBetween)
+{
+ WebCore::IntSize minimumSize(384, 256);
+ WebCore::IntSize maximumSize(2048, 1536);
+
+ WebCore::IntSize a(1024, 768);
+
+ auto constrained1 = a.constrainedBetween(minimumSize, maximumSize);
+
+ EXPECT_EQ(1024, constrained1.width());
+ EXPECT_EQ(768, constrained1.height());
+
+ WebCore::IntSize b(200, 100);
+
+ auto constrained2 = b.constrainedBetween(minimumSize, maximumSize);
+
+ EXPECT_EQ(384, constrained2.width());
+ EXPECT_EQ(256, constrained2.height());
+
+ WebCore::IntSize c(5000, 2000);
+
+ auto constrained3 = c.constrainedBetween(minimumSize, maximumSize);
+
+ EXPECT_EQ(2048, constrained3.width());
+ EXPECT_EQ(1536, constrained3.height());
+}
+
+/*
+
+IntSize constrainedBetween(const IntSize& min, const IntSize& max) const;
+
+*/
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/LayoutUnit.cpp b/Tools/TestWebKitAPI/Tests/WebCore/LayoutUnit.cpp
index ceafb039c..f904c96a1 100644
--- a/Tools/TestWebKitAPI/Tests/WebCore/LayoutUnit.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebCore/LayoutUnit.cpp
@@ -28,8 +28,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#define ENABLE_SUBPIXEL_LAYOUT 1
-#define ENABLE_SATURATED_LAYOUT_ARITHMETIC 1
#include "config.h"
#include <WebCore/LayoutUnit.h>
@@ -77,6 +75,10 @@ TEST(WebCoreLayoutUnit, LayoutUnitFloat)
ASSERT_NEAR(LayoutUnit(345634.12335f).toFloat(), 345634.12335f, tolerance);
ASSERT_NEAR(LayoutUnit(-345634.12335f).toFloat(), -345634.12335f, tolerance);
ASSERT_NEAR(LayoutUnit(-345634).toFloat(), -345634.0f, tolerance);
+ ASSERT_NEAR(LayoutUnit(33554432.f).toFloat(), 33554432.f, tolerance);
+ ASSERT_NEAR(LayoutUnit(-33554432.f).toFloat(), -33554432.f, tolerance);
+ ASSERT_NEAR(LayoutUnit(33554432.f).toDouble(), 33554432.f, tolerance);
+ ASSERT_NEAR(LayoutUnit(-33554432.f).toDouble(), -33554432.f, tolerance);
}
TEST(WebCoreLayoutUnit, LayoutUnitRounding)
@@ -104,28 +106,6 @@ TEST(WebCoreLayoutUnit, LayoutUnitRounding)
ASSERT_EQ(LayoutUnit::fromFloatRound(1.51f).round(), 2);
}
-TEST(WebCoreLayoutUnit, LayoutUnitSnapSizeToPixel)
-{
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1), LayoutUnit(0)), 1);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1), LayoutUnit(0.5)), 1);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(0)), 2);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(0.49)), 2);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(0.5)), 1);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(0.75)), 1);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(0.99)), 1);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(1)), 2);
-
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(0.5), LayoutUnit(1.5)), 0);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(0.99), LayoutUnit(1.5)), 0);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1.0), LayoutUnit(1.5)), 1);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1.49), LayoutUnit(1.5)), 1);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(1.5), LayoutUnit(1.5)), 1);
-
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(100.5), LayoutUnit(100)), 101);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(intMaxForLayoutUnit), LayoutUnit(0.3)), intMaxForLayoutUnit);
- ASSERT_EQ(snapSizeToPixel(LayoutUnit(intMinForLayoutUnit), LayoutUnit(-0.3)), intMinForLayoutUnit);
-}
-
TEST(WebCoreLayoutUnit, LayoutUnitMultiplication)
{
ASSERT_EQ((LayoutUnit(1) * LayoutUnit(1)).toInt(), 1);
@@ -250,5 +230,19 @@ TEST(WebCoreLayoutUnit, LayoutUnitFloor)
ASSERT_EQ((LayoutUnit(intMinForLayoutUnit) + LayoutUnit(1)).floor(), intMinForLayoutUnit + 1);
}
+TEST(WebCoreLayoutUnit, LayoutUnitPixelSnapping)
+{
+ for (int i = -100000; i <= 100000; ++i) {
+ ASSERT_EQ(roundToDevicePixel(LayoutUnit(i), 1), i);
+ ASSERT_EQ(roundToDevicePixel(LayoutUnit(i), 2), i);
+ ASSERT_EQ(roundToDevicePixel(LayoutUnit(i), 3), i);
+ }
+
+ for (float i = -10000; i < 0; i = i + 0.5)
+ ASSERT_FLOAT_EQ(roundToDevicePixel(LayoutUnit(i), 2), i);
+
+ for (float i = -10000.25; i < 0; i = i + 0.5)
+ ASSERT_FLOAT_EQ(roundToDevicePixel(LayoutUnit(i), 2), i + 0.25);
+}
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/ParsedContentRange.cpp b/Tools/TestWebKitAPI/Tests/WebCore/ParsedContentRange.cpp
new file mode 100644
index 000000000..986388302
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/ParsedContentRange.cpp
@@ -0,0 +1,98 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <WebCore/ParsedContentRange.h>
+#include <wtf/text/WTFString.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+TEST(WebCore, ParsedContentRangeFromString)
+{
+ // Basic parsing
+ ASSERT_TRUE(ParsedContentRange("bytes 0-1/2").isValid());
+ ASSERT_TRUE(ParsedContentRange("bytes 0-1/*").isValid());
+ ASSERT_EQ(0, ParsedContentRange("bytes 0-1/2").firstBytePosition());
+ ASSERT_EQ(1, ParsedContentRange("bytes 0-1/2").lastBytePosition());
+ ASSERT_EQ(2, ParsedContentRange("bytes 0-1/2").instanceLength());
+ ASSERT_EQ(ParsedContentRange::UnknownLength, ParsedContentRange("bytes 0-1/*").instanceLength());
+
+ // Whitespace errors
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/*").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0 -1/*").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0- 1/*").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1 /*").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/ *").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/* ").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/ 2").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/2 ").isValid());
+
+ // Non-digit errors
+ ASSERT_FALSE(ParsedContentRange("bytes abcd-1/2").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-abcd/2").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/abcd").isValid());
+
+ // Range requirement errors
+ ASSERT_FALSE(ParsedContentRange("bytes 1-0/2").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-2/1").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 2/0-1").isValid());
+ ASSERT_FALSE(ParsedContentRange("abcd 0/1-2").isValid());
+
+ // Negative value errors
+ ASSERT_FALSE(ParsedContentRange("bytes -0-1/*").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes -1/*").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0--0/2").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 0-1/-2").isValid());
+
+ // Edge cases
+ ASSERT_TRUE(ParsedContentRange("bytes 9223372036854775805-9223372036854775806/9223372036854775807").isValid());
+ ASSERT_FALSE(ParsedContentRange("bytes 9223372036854775808-9223372036854775809/9223372036854775810").isValid());
+}
+
+TEST(WebCore, ParsedContentRangeFromValues)
+{
+ ASSERT_TRUE(ParsedContentRange(0, 1, 2).isValid());
+ ASSERT_TRUE(ParsedContentRange(0, 1, ParsedContentRange::UnknownLength).isValid());
+ ASSERT_FALSE(ParsedContentRange().isValid());
+ ASSERT_FALSE(ParsedContentRange(1, 0, 2).isValid());
+ ASSERT_FALSE(ParsedContentRange(0, 2, 1).isValid());
+ ASSERT_FALSE(ParsedContentRange(0, 0, 0).isValid());
+ ASSERT_FALSE(ParsedContentRange(-1, 1, 2).isValid());
+ ASSERT_FALSE(ParsedContentRange(0, -1, 2).isValid());
+ ASSERT_FALSE(ParsedContentRange(0, 1, -2).isValid());
+ ASSERT_FALSE(ParsedContentRange(-2, -1, 2).isValid());
+}
+
+TEST(WebCore, ParsedContentRangeToString)
+{
+ ASSERT_STREQ("bytes 0-1/2", ParsedContentRange(0, 1, 2).headerValue().utf8().data());
+ ASSERT_STREQ("bytes 0-1/*", ParsedContentRange(0, 1, ParsedContentRange::UnknownLength).headerValue().utf8().data());
+ ASSERT_STREQ("", ParsedContentRange().headerValue().utf8().data());
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/PublicSuffix.cpp b/Tools/TestWebKitAPI/Tests/WebCore/PublicSuffix.cpp
new file mode 100644
index 000000000..f87ba63eb
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/PublicSuffix.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2012 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if ENABLE(PUBLIC_SUFFIX_LIST)
+
+#include "WTFStringUtilities.h"
+#include <WebCore/PublicSuffix.h>
+#include <wtf/MainThread.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+class PublicSuffix: public testing::Test {
+public:
+ virtual void SetUp()
+ {
+ WTF::initializeMainThread();
+ }
+};
+
+TEST_F(PublicSuffix, IsPublicSuffix)
+{
+ EXPECT_TRUE(isPublicSuffix("com"));
+ EXPECT_FALSE(isPublicSuffix("test.com"));
+ EXPECT_FALSE(isPublicSuffix("com.com"));
+ EXPECT_TRUE(isPublicSuffix("net"));
+ EXPECT_TRUE(isPublicSuffix("org"));
+ EXPECT_TRUE(isPublicSuffix("co.uk"));
+ EXPECT_FALSE(isPublicSuffix("bl.uk"));
+ EXPECT_FALSE(isPublicSuffix("test.co.uk"));
+ EXPECT_TRUE(isPublicSuffix("xn--zf0ao64a.tw"));
+}
+
+TEST_F(PublicSuffix, TopPrivatelyControlledDomain)
+{
+ EXPECT_EQ(String("test.com"), topPrivatelyControlledDomain("test.com"));
+ EXPECT_EQ(String("test.com"), topPrivatelyControlledDomain("com.test.com"));
+ EXPECT_EQ(String("test.com"), topPrivatelyControlledDomain("subdomain.test.com"));
+ EXPECT_EQ(String("com.com"), topPrivatelyControlledDomain("www.com.com"));
+ EXPECT_EQ(String("test.co.uk"), topPrivatelyControlledDomain("test.co.uk"));
+ EXPECT_EQ(String("test.co.uk"), topPrivatelyControlledDomain("subdomain.test.co.uk"));
+ EXPECT_EQ(String("bl.uk"), topPrivatelyControlledDomain("bl.uk"));
+ EXPECT_EQ(String("bl.uk"), topPrivatelyControlledDomain("subdomain.bl.uk"));
+ EXPECT_EQ(String("test.xn--zf0ao64a.tw"), topPrivatelyControlledDomain("test.xn--zf0ao64a.tw"));
+ EXPECT_EQ(String("test.xn--zf0ao64a.tw"), topPrivatelyControlledDomain("www.test.xn--zf0ao64a.tw"));
+ EXPECT_EQ(String("127.0.0.1"), topPrivatelyControlledDomain("127.0.0.1"));
+ EXPECT_EQ(String(), topPrivatelyControlledDomain("1"));
+ EXPECT_EQ(String(), topPrivatelyControlledDomain("com"));
+}
+
+}
+
+#endif // ENABLE(PUBLIC_SUFFIX_LIST)
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/SampleMap.cpp b/Tools/TestWebKitAPI/Tests/WebCore/SampleMap.cpp
new file mode 100644
index 000000000..f7e91c6fd
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/SampleMap.cpp
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2017 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if ENABLE(MEDIA_SOURCE)
+
+#include "Test.h"
+#include <WebCore/MediaSample.h>
+#include <WebCore/SampleMap.h>
+
+namespace WTF {
+inline std::ostream& operator<<(std::ostream& os, const MediaTime& time)
+{
+ if (time.hasDoubleValue())
+ os << "{ " << time.toDouble() << " }";
+ else
+ os << "{ " << time.timeValue() << " / " << time.timeScale() << ", " << time.toDouble() << " }";
+ return os;
+}
+}
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+class TestSample : public MediaSample {
+public:
+ static Ref<TestSample> create(const MediaTime& presentationTime, const MediaTime& decodeTime, const MediaTime& duration, SampleFlags flags)
+ {
+ return adoptRef(*new TestSample(presentationTime, decodeTime, duration, flags));
+ }
+
+ MediaTime presentationTime() const final { return m_presentationTime; }
+ MediaTime decodeTime() const final { return m_decodeTime; }
+ MediaTime duration() const final { return m_duration; }
+ AtomicString trackID() const final { return m_trackID; }
+ void setTrackID(const String& trackID) final { m_trackID = trackID; }
+ size_t sizeInBytes() const final { return m_sizeInBytes; }
+ FloatSize presentationSize() const final { return m_presentationSize; }
+ void offsetTimestampsBy(const MediaTime& offset) final { m_presentationTime += offset; m_decodeTime += offset; }
+ void setTimestamps(const MediaTime& presentationTime, const MediaTime& decodeTime) final {
+ m_presentationTime = presentationTime;
+ m_decodeTime = decodeTime;
+ };
+ bool isDivisable() const final { return false; }
+ std::pair<RefPtr<MediaSample>, RefPtr<MediaSample>> divide(const MediaTime& presentationTime) final { return { }; }
+ Ref<MediaSample> createNonDisplayingCopy() const final {
+ return create(m_presentationTime, m_decodeTime, m_duration, static_cast<SampleFlags>(m_flags | IsNonDisplaying));
+ }
+ SampleFlags flags() const final { return m_flags; }
+ PlatformSample platformSample() final { return { PlatformSample::None, {nullptr}}; }
+ void dump(PrintStream&) const final { }
+
+private:
+ TestSample(const MediaTime& presentationTime, const MediaTime& decodeTime, const MediaTime& duration, SampleFlags flags)
+ : m_presentationTime(presentationTime)
+ , m_decodeTime(decodeTime)
+ , m_duration(duration)
+ , m_flags(flags)
+ {
+ }
+
+ MediaTime m_presentationTime;
+ MediaTime m_decodeTime;
+ MediaTime m_duration;
+ FloatSize m_presentationSize;
+ AtomicString m_trackID;
+ size_t m_sizeInBytes { 0 };
+ SampleFlags m_flags { None };
+};
+
+class SampleMapTest : public testing::Test {
+public:
+ void SetUp() final {
+ map.addSample(TestSample::create(MediaTime(0, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::IsSync));
+ map.addSample(TestSample::create(MediaTime(1, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(2, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(3, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(4, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(5, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::IsSync));
+ map.addSample(TestSample::create(MediaTime(6, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(7, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(8, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(9, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ // Gap at MediaTime(10, 1) -> MediaTime(11, 1);
+ map.addSample(TestSample::create(MediaTime(11, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::IsSync));
+ map.addSample(TestSample::create(MediaTime(12, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(13, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(14, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(15, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::IsSync));
+ map.addSample(TestSample::create(MediaTime(16, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(17, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(18, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ map.addSample(TestSample::create(MediaTime(19, 1), MediaTime(0, 1), MediaTime(1, 1), MediaSample::None));
+ }
+
+ SampleMap map;
+};
+
+TEST_F(SampleMapTest, findSampleWithPresentationTime)
+{
+ auto& presentationMap = map.presentationOrder();
+ EXPECT_EQ(MediaTime(0, 1), presentationMap.findSampleWithPresentationTime(MediaTime(0, 1))->second->presentationTime());
+ EXPECT_EQ(MediaTime(19, 1), presentationMap.findSampleWithPresentationTime(MediaTime(19, 1))->second->presentationTime());
+ EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleWithPresentationTime(MediaTime(-1, 1)));
+ EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleWithPresentationTime(MediaTime(10, 1)));
+ EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleWithPresentationTime(MediaTime(20, 1)));
+ EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleWithPresentationTime(MediaTime(1, 2)));
+}
+
+TEST_F(SampleMapTest, findSampleContainingPresentationTime)
+{
+ auto& presentationMap = map.presentationOrder();
+ EXPECT_EQ(MediaTime(0, 1), presentationMap.findSampleContainingPresentationTime(MediaTime(0, 1))->second->presentationTime());
+ EXPECT_EQ(MediaTime(19, 1), presentationMap.findSampleContainingPresentationTime(MediaTime(19, 1))->second->presentationTime());
+ EXPECT_EQ(MediaTime(0, 1), presentationMap.findSampleContainingPresentationTime(MediaTime(1, 2))->second->presentationTime());
+ EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleContainingPresentationTime(MediaTime(-1, 1)));
+ EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleContainingPresentationTime(MediaTime(10, 1)));
+ EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleContainingPresentationTime(MediaTime(20, 1)));
+}
+
+TEST_F(SampleMapTest, findSampleStartingOnOrAfterPresentationTime)
+{
+ auto& presentationMap = map.presentationOrder();
+ EXPECT_EQ(MediaTime(0, 1), presentationMap.findSampleStartingOnOrAfterPresentationTime(MediaTime(0, 1))->second->presentationTime());
+ EXPECT_EQ(MediaTime(19, 1), presentationMap.findSampleStartingOnOrAfterPresentationTime(MediaTime(19, 1))->second->presentationTime());
+ EXPECT_EQ(MediaTime(1, 1), presentationMap.findSampleStartingOnOrAfterPresentationTime(MediaTime(1, 2))->second->presentationTime());
+ EXPECT_EQ(MediaTime(0, 1), presentationMap.findSampleStartingOnOrAfterPresentationTime(MediaTime(-1, 1))->second->presentationTime());
+ EXPECT_EQ(MediaTime(11, 1), presentationMap.findSampleStartingOnOrAfterPresentationTime(MediaTime(10, 1))->second->presentationTime());
+ EXPECT_TRUE(presentationMap.end() == presentationMap.findSampleContainingPresentationTime(MediaTime(20, 1)));
+}
+
+TEST_F(SampleMapTest, findSamplesBetweenPresentationTimes)
+{
+ auto& presentationMap = map.presentationOrder();
+ auto iterator_range = presentationMap.findSamplesBetweenPresentationTimes(MediaTime(0, 1), MediaTime(1, 1));
+ EXPECT_EQ(MediaTime(0, 1), iterator_range.first->second->presentationTime());
+ EXPECT_EQ(MediaTime(1, 1), iterator_range.second->second->presentationTime());
+
+ iterator_range = presentationMap.findSamplesBetweenPresentationTimes(MediaTime(1, 2), MediaTime(3, 2));
+ EXPECT_EQ(MediaTime(1, 1), iterator_range.first->second->presentationTime());
+ EXPECT_EQ(MediaTime(2, 1), iterator_range.second->second->presentationTime());
+
+ iterator_range = presentationMap.findSamplesBetweenPresentationTimes(MediaTime(9, 1), MediaTime(21, 1));
+ EXPECT_EQ(MediaTime(9, 1), iterator_range.first->second->presentationTime());
+ EXPECT_TRUE(presentationMap.end() == iterator_range.second);
+
+ iterator_range = presentationMap.findSamplesBetweenPresentationTimes(MediaTime(-1, 1), MediaTime(0, 1));
+ EXPECT_TRUE(presentationMap.end() == iterator_range.first);
+ EXPECT_TRUE(presentationMap.end() == iterator_range.second);
+
+ iterator_range = presentationMap.findSamplesBetweenPresentationTimes(MediaTime(19, 2), MediaTime(10, 1));
+ EXPECT_TRUE(presentationMap.end() == iterator_range.first);
+ EXPECT_TRUE(presentationMap.end() == iterator_range.second);
+
+ iterator_range = presentationMap.findSamplesBetweenPresentationTimes(MediaTime(20, 1), MediaTime(21, 1));
+ EXPECT_TRUE(presentationMap.end() == iterator_range.first);
+ EXPECT_TRUE(presentationMap.end() == iterator_range.second);
+}
+
+TEST_F(SampleMapTest, findSamplesWithinPresentationRange)
+{
+ auto& presentationMap = map.presentationOrder();
+ auto iterator_range = presentationMap.findSamplesWithinPresentationRange(MediaTime(0, 1), MediaTime(1, 1));
+ EXPECT_EQ(MediaTime(1, 1), iterator_range.first->second->presentationTime());
+ EXPECT_EQ(MediaTime(2, 1), iterator_range.second->second->presentationTime());
+
+ iterator_range = presentationMap.findSamplesWithinPresentationRange(MediaTime(1, 2), MediaTime(3, 2));
+ EXPECT_EQ(MediaTime(1, 1), iterator_range.first->second->presentationTime());
+ EXPECT_EQ(MediaTime(2, 1), iterator_range.second->second->presentationTime());
+
+ iterator_range = presentationMap.findSamplesWithinPresentationRange(MediaTime(9, 1), MediaTime(21, 1));
+ EXPECT_EQ(MediaTime(11, 1), iterator_range.first->second->presentationTime());
+ EXPECT_TRUE(presentationMap.end() == iterator_range.second);
+
+ iterator_range = presentationMap.findSamplesWithinPresentationRange(MediaTime(-1, 1), MediaTime(0, 1));
+ EXPECT_EQ(MediaTime(0, 1), iterator_range.first->second->presentationTime());
+ EXPECT_EQ(MediaTime(1, 1), iterator_range.second->second->presentationTime());
+
+ iterator_range = presentationMap.findSamplesWithinPresentationRange(MediaTime(10, 1), MediaTime(21, 2));
+ EXPECT_TRUE(presentationMap.end() == iterator_range.first);
+ EXPECT_TRUE(presentationMap.end() == iterator_range.second);
+
+ iterator_range = presentationMap.findSamplesWithinPresentationRange(MediaTime(20, 1), MediaTime(21, 1));
+ EXPECT_TRUE(presentationMap.end() == iterator_range.first);
+ EXPECT_TRUE(presentationMap.end() == iterator_range.second);
+}
+
+TEST_F(SampleMapTest, reverseFindSampleBeforePresentationTime)
+{
+ auto& presentationMap = map.presentationOrder();
+ EXPECT_EQ(MediaTime(0, 1), presentationMap.reverseFindSampleBeforePresentationTime(MediaTime(0, 1))->second->presentationTime());
+ EXPECT_EQ(MediaTime(9, 1), presentationMap.reverseFindSampleBeforePresentationTime(MediaTime(10, 1))->second->presentationTime());
+ EXPECT_EQ(MediaTime(19, 1), presentationMap.reverseFindSampleBeforePresentationTime(MediaTime(19, 1))->second->presentationTime());
+ EXPECT_EQ(MediaTime(19, 1), presentationMap.reverseFindSampleBeforePresentationTime(MediaTime(21, 1))->second->presentationTime());
+ EXPECT_TRUE(presentationMap.rend() == presentationMap.reverseFindSampleBeforePresentationTime(MediaTime(-1, 1)));
+}
+
+}
+
+#endif // ENABLE(MEDIA_SOURCE)
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/SecurityOrigin.cpp b/Tools/TestWebKitAPI/Tests/WebCore/SecurityOrigin.cpp
new file mode 100644
index 000000000..9f9cc9cca
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/SecurityOrigin.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2016 Igalia S.L.
+ *
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+#include "WTFStringUtilities.h"
+#include <WebCore/FileSystem.h>
+#include <WebCore/SecurityOrigin.h>
+#include <WebCore/URL.h>
+#include <wtf/MainThread.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+class SecurityOriginTest : public testing::Test {
+public:
+ void SetUp() final {
+ WTF::initializeMainThread();
+
+ // create temp file
+ PlatformFileHandle handle;
+ m_tempFilePath = openTemporaryFile("tempTestFile", handle);
+ closeFile(handle);
+
+ m_spaceContainingFilePath = openTemporaryFile("temp Empty Test File", handle);
+ closeFile(handle);
+
+ m_bangContainingFilePath = openTemporaryFile("temp!Empty!Test!File", handle);
+ closeFile(handle);
+
+ m_quoteContainingFilePath = openTemporaryFile("temp\"Empty\"TestFile", handle);
+ closeFile(handle);
+ }
+
+ void TearDown() override
+ {
+ deleteFile(m_tempFilePath);
+ deleteFile(m_spaceContainingFilePath);
+ deleteFile(m_bangContainingFilePath);
+ deleteFile(m_quoteContainingFilePath);
+ }
+
+ const String& tempFilePath() { return m_tempFilePath; }
+ const String& spaceContainingFilePath() { return m_spaceContainingFilePath; }
+ const String& bangContainingFilePath() { return m_bangContainingFilePath; }
+ const String& quoteContainingFilePath() { return m_quoteContainingFilePath; }
+
+private:
+ String m_tempFilePath;
+ String m_spaceContainingFilePath;
+ String m_bangContainingFilePath;
+ String m_quoteContainingFilePath;
+};
+
+TEST_F(SecurityOriginTest, SecurityOriginConstructors)
+{
+ Ref<SecurityOrigin> o1 = SecurityOrigin::create("http", "example.com", std::optional<uint16_t>(80));
+ Ref<SecurityOrigin> o2 = SecurityOrigin::create("http", "example.com", std::optional<uint16_t>());
+ Ref<SecurityOrigin> o3 = SecurityOrigin::createFromString("http://example.com");
+ Ref<SecurityOrigin> o4 = SecurityOrigin::createFromString("http://example.com:80");
+ Ref<SecurityOrigin> o5 = SecurityOrigin::create(URL(URL(), "http://example.com"));
+ Ref<SecurityOrigin> o6 = SecurityOrigin::create(URL(URL(), "http://example.com:80"));
+
+ EXPECT_EQ(String("http"), o1->protocol());
+ EXPECT_EQ(String("http"), o2->protocol());
+ EXPECT_EQ(String("http"), o3->protocol());
+ EXPECT_EQ(String("http"), o4->protocol());
+ EXPECT_EQ(String("http"), o5->protocol());
+ EXPECT_EQ(String("http"), o6->protocol());
+
+ EXPECT_EQ(String("example.com"), o1->host());
+ EXPECT_EQ(String("example.com"), o2->host());
+ EXPECT_EQ(String("example.com"), o3->host());
+ EXPECT_EQ(String("example.com"), o4->host());
+ EXPECT_EQ(String("example.com"), o5->host());
+ EXPECT_EQ(String("example.com"), o6->host());
+
+ EXPECT_FALSE(o1->port());
+ EXPECT_FALSE(o2->port());
+ EXPECT_FALSE(o3->port());
+ EXPECT_FALSE(o4->port());
+ EXPECT_FALSE(o5->port());
+ EXPECT_FALSE(o6->port());
+
+ EXPECT_EQ("http://example.com", o1->toString());
+ EXPECT_EQ("http://example.com", o2->toString());
+ EXPECT_EQ("http://example.com", o3->toString());
+ EXPECT_EQ("http://example.com", o4->toString());
+ EXPECT_EQ("http://example.com", o5->toString());
+ EXPECT_EQ("http://example.com", o6->toString());
+
+ EXPECT_TRUE(o1->isSameOriginAs(o2.get()));
+ EXPECT_TRUE(o1->isSameOriginAs(o3.get()));
+ EXPECT_TRUE(o1->isSameOriginAs(o4.get()));
+ EXPECT_TRUE(o1->isSameOriginAs(o5.get()));
+ EXPECT_TRUE(o1->isSameOriginAs(o6.get()));
+}
+
+TEST_F(SecurityOriginTest, SecurityOriginFileBasedConstructors)
+{
+ auto tempFileOrigin = SecurityOrigin::create(URL(URL(), "file:///" + tempFilePath()));
+ auto spaceContainingOrigin = SecurityOrigin::create(URL(URL(), "file:///" + spaceContainingFilePath()));
+ auto bangContainingOrigin = SecurityOrigin::create(URL(URL(), "file:///" + bangContainingFilePath()));
+ auto quoteContainingOrigin = SecurityOrigin::create(URL(URL(), "file:///" + quoteContainingFilePath()));
+
+ EXPECT_EQ(String("file"), tempFileOrigin->protocol());
+ EXPECT_EQ(String("file"), spaceContainingOrigin->protocol());
+ EXPECT_EQ(String("file"), bangContainingOrigin->protocol());
+ EXPECT_EQ(String("file"), quoteContainingOrigin->protocol());
+
+ EXPECT_TRUE(tempFileOrigin->isSameOriginAs(spaceContainingOrigin.get()));
+ EXPECT_TRUE(tempFileOrigin->isSameOriginAs(bangContainingOrigin.get()));
+ EXPECT_TRUE(tempFileOrigin->isSameOriginAs(quoteContainingOrigin.get()));
+
+ EXPECT_TRUE(tempFileOrigin->isSameSchemeHostPort(spaceContainingOrigin.get()));
+ EXPECT_TRUE(tempFileOrigin->isSameSchemeHostPort(bangContainingOrigin.get()));
+ EXPECT_TRUE(tempFileOrigin->isSameSchemeHostPort(quoteContainingOrigin.get()));
+
+ EXPECT_TRUE(tempFileOrigin->canAccess(spaceContainingOrigin.get()));
+ EXPECT_TRUE(tempFileOrigin->canAccess(bangContainingOrigin.get()));
+ EXPECT_TRUE(tempFileOrigin->canAccess(quoteContainingOrigin.get()));
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/SharedBuffer.cpp b/Tools/TestWebKitAPI/Tests/WebCore/SharedBuffer.cpp
new file mode 100644
index 000000000..543ef2316
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/SharedBuffer.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2015 Canon Inc. All rights reserved.
+ * Copyright (C) 2013 Google 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include "SharedBufferTest.h"
+#include "Test.h"
+#include <WebCore/SharedBuffer.h>
+#include <wtf/MainThread.h>
+#include <wtf/StringExtras.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+TEST_F(SharedBufferTest, createWithContentsOfMissingFile)
+{
+ RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(String("not_existing_file"));
+ ASSERT_NULL(buffer);
+}
+
+TEST_F(SharedBufferTest, createWithContentsOfExistingFile)
+{
+ RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(tempFilePath());
+ ASSERT_NOT_NULL(buffer);
+ EXPECT_TRUE(buffer->size() == strlen(SharedBufferTest::testData()));
+ EXPECT_TRUE(String(SharedBufferTest::testData()) == String(buffer->data(), buffer->size()));
+}
+
+TEST_F(SharedBufferTest, createWithContentsOfExistingEmptyFile)
+{
+ RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(tempEmptyFilePath());
+ ASSERT_NOT_NULL(buffer);
+ EXPECT_TRUE(buffer->isEmpty());
+}
+
+TEST_F(SharedBufferTest, copyBufferCreatedWithContentsOfExistingFile)
+{
+ RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(tempFilePath());
+ ASSERT_NOT_NULL(buffer);
+ RefPtr<SharedBuffer> copy = buffer->copy();
+ EXPECT_GT(buffer->size(), 0U);
+ EXPECT_TRUE(buffer->size() == copy->size());
+ EXPECT_TRUE(!memcmp(buffer->data(), copy->data(), buffer->size()));
+}
+
+TEST_F(SharedBufferTest, clearBufferCreatedWithContentsOfExistingFile)
+{
+ RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(tempFilePath());
+ ASSERT_NOT_NULL(buffer);
+ buffer->clear();
+ EXPECT_TRUE(!buffer->size());
+ EXPECT_TRUE(!buffer->data());
+}
+
+TEST_F(SharedBufferTest, appendBufferCreatedWithContentsOfExistingFile)
+{
+ RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(tempFilePath());
+ ASSERT_NOT_NULL(buffer);
+ buffer->append("a", 1);
+ EXPECT_TRUE(buffer->size() == (strlen(SharedBufferTest::testData()) + 1));
+ EXPECT_TRUE(!memcmp(buffer->data(), SharedBufferTest::testData(), strlen(SharedBufferTest::testData())));
+ EXPECT_EQ('a', buffer->data()[strlen(SharedBufferTest::testData())]);
+}
+
+TEST_F(SharedBufferTest, createArrayBuffer)
+{
+ char testData0[] = "Hello";
+ char testData1[] = "World";
+ char testData2[] = "Goodbye";
+ RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(testData0, strlen(testData0));
+ sharedBuffer->append(testData1, strlen(testData1));
+ sharedBuffer->append(testData2, strlen(testData2));
+ RefPtr<ArrayBuffer> arrayBuffer = sharedBuffer->createArrayBuffer();
+ char expectedConcatenation[] = "HelloWorldGoodbye";
+ ASSERT_EQ(strlen(expectedConcatenation), arrayBuffer->byteLength());
+ EXPECT_EQ(0, memcmp(expectedConcatenation, arrayBuffer->data(), strlen(expectedConcatenation)));
+}
+
+TEST_F(SharedBufferTest, createArrayBufferLargeSegments)
+{
+ Vector<char> vector0(0x4000, 'a');
+ Vector<char> vector1(0x4000, 'b');
+ Vector<char> vector2(0x4000, 'c');
+
+ RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::adoptVector(vector0);
+ sharedBuffer->append(vector1);
+ sharedBuffer->append(vector2);
+ RefPtr<ArrayBuffer> arrayBuffer = sharedBuffer->createArrayBuffer();
+ ASSERT_EQ(0x4000U + 0x4000U + 0x4000U, arrayBuffer->byteLength());
+ int position = 0;
+ for (int i = 0; i < 0x4000; ++i) {
+ EXPECT_EQ('a', static_cast<char*>(arrayBuffer->data())[position]);
+ ++position;
+ }
+ for (int i = 0; i < 0x4000; ++i) {
+ EXPECT_EQ('b', static_cast<char*>(arrayBuffer->data())[position]);
+ ++position;
+ }
+ for (int i = 0; i < 0x4000; ++i) {
+ EXPECT_EQ('c', static_cast<char*>(arrayBuffer->data())[position]);
+ ++position;
+ }
+}
+
+TEST_F(SharedBufferTest, copy)
+{
+ char testData[] = "Habitasse integer eros tincidunt a scelerisque! Enim elit? Scelerisque magnis,"
+ "et montes ultrices tristique a! Pid. Velit turpis, dapibus integer rhoncus sociis amet facilisis,"
+ "adipiscing pulvinar nascetur magnis tempor sit pulvinar, massa urna enim porttitor sociis sociis proin enim?"
+ "Lectus, platea dolor, integer a. A habitasse hac nunc, nunc, nec placerat vut in sit nunc nec, sed. Sociis,"
+ "vut! Hac, velit rhoncus facilisis. Rhoncus et, enim, sed et in tristique nunc montes,"
+ "natoque nunc sagittis elementum parturient placerat dolor integer? Pulvinar,"
+ "magnis dignissim porttitor ac pulvinar mid tempor. A risus sed mid! Magnis elit duis urna,"
+ "cras massa, magna duis. Vut magnis pid a! Penatibus aliquet porttitor nunc, adipiscing massa odio lundium,"
+ "risus elementum ac turpis massa pellentesque parturient augue. Purus amet turpis pid aliquam?"
+ "Dolor est tincidunt? Dolor? Dignissim porttitor sit in aliquam! Tincidunt, non nunc, rhoncus dictumst!"
+ "Porta augue etiam. Cursus augue nunc lacus scelerisque. Rhoncus lectus, integer hac, nec pulvinar augue massa,"
+ "integer amet nisi facilisis? A! A, enim velit pulvinar elit in non scelerisque in et ultricies amet est!"
+ "in porttitor montes lorem et, hac aliquet pellentesque a sed? Augue mid purus ridiculus vel dapibus,"
+ "sagittis sed, tortor auctor nascetur rhoncus nec, rhoncus, magna integer. Sit eu massa vut?"
+ "Porta augue porttitor elementum, enim, rhoncus pulvinar duis integer scelerisque rhoncus natoque,"
+ "mattis dignissim massa ac pulvinar urna, nunc ut. Sagittis, aliquet penatibus proin lorem, pulvinar lectus,"
+ "augue proin! Ac, arcu quis. Placerat habitasse, ridiculus ridiculus.";
+ unsigned length = strlen(testData);
+ RefPtr<SharedBuffer> sharedBuffer = SharedBuffer::create(testData, length);
+ sharedBuffer->append(testData, length);
+ sharedBuffer->append(testData, length);
+ sharedBuffer->append(testData, length);
+ // sharedBuffer must contain data more than segmentSize (= 0x1000) to check copy().
+ ASSERT_EQ(length * 4, sharedBuffer->size());
+ RefPtr<SharedBuffer> clone = sharedBuffer->copy();
+ ASSERT_EQ(length * 4, clone->size());
+ ASSERT_EQ(0, memcmp(clone->data(), sharedBuffer->data(), clone->size()));
+ clone->append(testData, length);
+ ASSERT_EQ(length * 5, clone->size());
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/SharedBufferTest.cpp b/Tools/TestWebKitAPI/Tests/WebCore/SharedBufferTest.cpp
new file mode 100644
index 000000000..a297a55b8
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/SharedBufferTest.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 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. 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 INC. 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.
+ */
+
+#include "config.h"
+#include "SharedBufferTest.h"
+
+#include <WebCore/FileSystem.h>
+#include <wtf/MainThread.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+void SharedBufferTest::SetUp()
+{
+ WTF::initializeMainThread();
+
+ // create temp file
+ PlatformFileHandle handle;
+ m_tempFilePath = openTemporaryFile("tempTestFile", handle);
+ writeToFile(handle, testData(), strlen(testData()));
+ closeFile(handle);
+
+ m_tempEmptyFilePath = openTemporaryFile("tempEmptyTestFile", handle);
+ closeFile(handle);
+}
+
+void SharedBufferTest::TearDown()
+{
+ deleteFile(m_tempFilePath);
+ deleteFile(m_tempEmptyFilePath);
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/SharedBufferTest.h b/Tools/TestWebKitAPI/Tests/WebCore/SharedBufferTest.h
new file mode 100644
index 000000000..e5d90935d
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/SharedBufferTest.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 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. 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 INC. 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.
+ */
+
+#pragma once
+
+#include <wtf/text/WTFString.h>
+
+namespace TestWebKitAPI {
+
+class SharedBufferTest : public testing::Test {
+public:
+ void SetUp() override;
+ void TearDown() override;
+
+ static const char* testData() { return "This is a test"; }
+ const String& tempFilePath() { return m_tempFilePath; }
+ const String& tempEmptyFilePath() { return m_tempEmptyFilePath; }
+
+private:
+ String m_tempFilePath;
+ String m_tempEmptyFilePath;
+};
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/TimeRanges.cpp b/Tools/TestWebKitAPI/Tests/WebCore/TimeRanges.cpp
new file mode 100644
index 000000000..c6dca0115
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/TimeRanges.cpp
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2013, Google 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:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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.
+ */
+
+#include "config.h"
+#include <WebCore/TimeRanges.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+static std::string ToString(const TimeRanges& ranges)
+{
+ std::stringstream ss;
+ ss << "{";
+ for (unsigned i = 0; i < ranges.length(); ++i)
+ ss << " [" << ranges.start(i).releaseReturnValue() << "," << ranges.end(i).releaseReturnValue() << ")";
+ ss << " }";
+
+ return ss.str();
+}
+
+#define ASSERT_RANGE(expected, range) EXPECT_EQ(expected, ToString(*range))
+
+TEST(TimeRanges, Empty)
+{
+ ASSERT_RANGE("{ }", TimeRanges::create().ptr());
+}
+
+TEST(TimeRanges, SingleRange)
+{
+ ASSERT_RANGE("{ [1,2) }", TimeRanges::create(1, 2).ptr());
+}
+
+TEST(TimeRanges, AddOrder)
+{
+ RefPtr<TimeRanges> rangeA = TimeRanges::create();
+ RefPtr<TimeRanges> rangeB = TimeRanges::create();
+
+ rangeA->add(0, 2);
+ rangeA->add(3, 4);
+ rangeA->add(5, 100);
+
+ std::string expected = "{ [0,2) [3,4) [5,100) }";
+ ASSERT_RANGE(expected, rangeA);
+
+ // Add the values in rangeA to rangeB in reverse order.
+ for (int i = rangeA->length() - 1; i >= 0; --i)
+ rangeB->add(rangeA->start(i).releaseReturnValue(), rangeA->end(i).releaseReturnValue());
+
+ ASSERT_RANGE(expected, rangeB);
+}
+
+TEST(TimeRanges, OverlappingAdds)
+{
+ RefPtr<TimeRanges> ranges = TimeRanges::create();
+
+ ranges->add(0, 2);
+ ranges->add(10, 11);
+ ASSERT_RANGE("{ [0,2) [10,11) }", ranges);
+
+ ranges->add(0, 2);
+ ASSERT_RANGE("{ [0,2) [10,11) }", ranges);
+
+ ranges->add(2, 3);
+ ASSERT_RANGE("{ [0,3) [10,11) }", ranges);
+
+ ranges->add(2, 6);
+ ASSERT_RANGE("{ [0,6) [10,11) }", ranges);
+
+ ranges->add(9, 10);
+ ASSERT_RANGE("{ [0,6) [9,11) }", ranges);
+
+ ranges->add(8, 10);
+ ASSERT_RANGE("{ [0,6) [8,11) }", ranges);
+
+ ranges->add(-1, 7);
+ ASSERT_RANGE("{ [-1,7) [8,11) }", ranges);
+
+ ranges->add(6, 9);
+ ASSERT_RANGE("{ [-1,11) }", ranges);
+}
+
+TEST(TimeRanges, IntersectWith_Self)
+{
+ RefPtr<TimeRanges> ranges = TimeRanges::create(0, 2);
+
+ ASSERT_RANGE("{ [0,2) }", ranges);
+
+ ranges->intersectWith(*ranges.get());
+
+ ASSERT_RANGE("{ [0,2) }", ranges);
+}
+
+TEST(TimeRanges, IntersectWith_IdenticalRange)
+{
+ RefPtr<TimeRanges> rangesA = TimeRanges::create(0, 2);
+ RefPtr<TimeRanges> rangesB = rangesA->copy();
+
+ ASSERT_RANGE("{ [0,2) }", rangesA);
+ ASSERT_RANGE("{ [0,2) }", rangesB);
+
+ rangesA->intersectWith(*rangesB.get());
+
+ ASSERT_RANGE("{ [0,2) }", rangesA);
+ ASSERT_RANGE("{ [0,2) }", rangesB);
+}
+
+TEST(TimeRanges, IntersectWith_Empty)
+{
+ RefPtr<TimeRanges> rangesA = TimeRanges::create(0, 2);
+ RefPtr<TimeRanges> rangesB = TimeRanges::create();
+
+ ASSERT_RANGE("{ [0,2) }", rangesA);
+ ASSERT_RANGE("{ }", rangesB);
+
+ rangesA->intersectWith(*rangesB.get());
+
+ ASSERT_RANGE("{ }", rangesA);
+ ASSERT_RANGE("{ }", rangesB);
+}
+
+TEST(TimeRanges, IntersectWith_DisjointRanges1)
+{
+
+ RefPtr<TimeRanges> rangesA = TimeRanges::create();
+ RefPtr<TimeRanges> rangesB = TimeRanges::create();
+
+ rangesA->add(0, 1);
+ rangesA->add(4, 5);
+
+ rangesB->add(2, 3);
+ rangesB->add(6, 7);
+
+ ASSERT_RANGE("{ [0,1) [4,5) }", rangesA);
+ ASSERT_RANGE("{ [2,3) [6,7) }", rangesB);
+
+ rangesA->intersectWith(*rangesB.get());
+
+ ASSERT_RANGE("{ }", rangesA);
+ ASSERT_RANGE("{ [2,3) [6,7) }", rangesB);
+}
+
+TEST(TimeRanges, IntersectWith_DisjointRanges2)
+{
+ RefPtr<TimeRanges> rangesA = TimeRanges::create();
+ RefPtr<TimeRanges> rangesB = TimeRanges::create();
+
+ rangesA->add(0, 1);
+ rangesA->add(4, 5);
+
+ rangesB->add(1, 4);
+ rangesB->add(5, 7);
+
+ ASSERT_RANGE("{ [0,1) [4,5) }", rangesA);
+ ASSERT_RANGE("{ [1,4) [5,7) }", rangesB);
+
+ rangesA->intersectWith(*rangesB.get());
+
+ ASSERT_RANGE("{ }", rangesA);
+ ASSERT_RANGE("{ [1,4) [5,7) }", rangesB);
+}
+
+TEST(TimeRanges, IntersectWith_CompleteOverlap1)
+{
+ RefPtr<TimeRanges> rangesA = TimeRanges::create();
+ RefPtr<TimeRanges> rangesB = TimeRanges::create();
+
+ rangesA->add(1, 3);
+ rangesA->add(4, 5);
+ rangesA->add(6, 9);
+
+ rangesB->add(0, 10);
+
+ ASSERT_RANGE("{ [1,3) [4,5) [6,9) }", rangesA);
+ ASSERT_RANGE("{ [0,10) }", rangesB);
+
+ rangesA->intersectWith(*rangesB.get());
+
+ ASSERT_RANGE("{ [1,3) [4,5) [6,9) }", rangesA);
+ ASSERT_RANGE("{ [0,10) }", rangesB);
+}
+
+TEST(TimeRanges, IntersectWith_CompleteOverlap2)
+{
+ RefPtr<TimeRanges> rangesA = TimeRanges::create();
+ RefPtr<TimeRanges> rangesB = TimeRanges::create();
+
+ rangesA->add(1, 3);
+ rangesA->add(4, 5);
+ rangesA->add(6, 9);
+
+ rangesB->add(1, 9);
+
+ ASSERT_RANGE("{ [1,3) [4,5) [6,9) }", rangesA);
+ ASSERT_RANGE("{ [1,9) }", rangesB);
+
+ rangesA->intersectWith(*rangesB.get());
+
+ ASSERT_RANGE("{ [1,3) [4,5) [6,9) }", rangesA);
+ ASSERT_RANGE("{ [1,9) }", rangesB);
+}
+
+TEST(TimeRanges, IntersectWith_Gaps1)
+{
+ RefPtr<TimeRanges> rangesA = TimeRanges::create();
+ RefPtr<TimeRanges> rangesB = TimeRanges::create();
+
+ rangesA->add(0, 2);
+ rangesA->add(4, 6);
+
+ rangesB->add(1, 5);
+
+ ASSERT_RANGE("{ [0,2) [4,6) }", rangesA);
+ ASSERT_RANGE("{ [1,5) }", rangesB);
+
+ rangesA->intersectWith(*rangesB.get());
+
+ ASSERT_RANGE("{ [1,2) [4,5) }", rangesA);
+ ASSERT_RANGE("{ [1,5) }", rangesB);
+}
+
+TEST(TimeRanges, IntersectWith_Gaps2)
+{
+ RefPtr<TimeRanges> rangesA = TimeRanges::create();
+ RefPtr<TimeRanges> rangesB = TimeRanges::create();
+
+ rangesA->add(0, 2);
+ rangesA->add(4, 6);
+ rangesA->add(8, 10);
+
+ rangesB->add(1, 9);
+
+ ASSERT_RANGE("{ [0,2) [4,6) [8,10) }", rangesA);
+ ASSERT_RANGE("{ [1,9) }", rangesB);
+
+ rangesA->intersectWith(*rangesB.get());
+
+ ASSERT_RANGE("{ [1,2) [4,6) [8,9) }", rangesA);
+ ASSERT_RANGE("{ [1,9) }", rangesB);
+}
+
+TEST(TimeRanges, IntersectWith_Gaps3)
+{
+ RefPtr<TimeRanges> rangesA = TimeRanges::create();
+ RefPtr<TimeRanges> rangesB = TimeRanges::create();
+
+ rangesA->add(0, 2);
+ rangesA->add(4, 7);
+ rangesA->add(8, 10);
+
+ rangesB->add(1, 5);
+ rangesB->add(6, 9);
+
+ ASSERT_RANGE("{ [0,2) [4,7) [8,10) }", rangesA);
+ ASSERT_RANGE("{ [1,5) [6,9) }", rangesB);
+
+ rangesA->intersectWith(*rangesB.get());
+
+ ASSERT_RANGE("{ [1,2) [4,5) [6,7) [8,9) }", rangesA);
+ ASSERT_RANGE("{ [1,5) [6,9) }", rangesB);
+}
+
+}
+
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/TransformationMatrix.cpp b/Tools/TestWebKitAPI/Tests/WebCore/TransformationMatrix.cpp
new file mode 100644
index 000000000..9315b75a5
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/TransformationMatrix.cpp
@@ -0,0 +1,1317 @@
+/*
+ * Copyright (c) 2013, Google Inc. All rights reserved.
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <WebCore/AffineTransform.h>
+#include <WebCore/FloatPoint.h>
+#include <WebCore/FloatQuad.h>
+#include <WebCore/FloatRect.h>
+#include <WebCore/IntPoint.h>
+#include <WebCore/IntRect.h>
+#include <WebCore/TransformationMatrix.h>
+
+#if USE(CG)
+#include <CoreGraphics/CoreGraphics.h>
+#endif
+
+#if USE(CA)
+#include <QuartzCore/QuartzCore.h>
+#endif
+
+#if PLATFORM(WIN)
+#include <d2d1.h>
+#endif
+
+namespace TestWebKitAPI {
+
+static void testIdentity(const WebCore::TransformationMatrix& transform)
+{
+ EXPECT_DOUBLE_EQ(1.0, transform.m11());
+ EXPECT_DOUBLE_EQ(0.0, transform.m12());
+ EXPECT_DOUBLE_EQ(0.0, transform.m13());
+ EXPECT_DOUBLE_EQ(0.0, transform.m14());
+ EXPECT_DOUBLE_EQ(0.0, transform.m21());
+ EXPECT_DOUBLE_EQ(1.0, transform.m22());
+ EXPECT_DOUBLE_EQ(0.0, transform.m23());
+ EXPECT_DOUBLE_EQ(0.0, transform.m24());
+ EXPECT_DOUBLE_EQ(0.0, transform.m31());
+ EXPECT_DOUBLE_EQ(0.0, transform.m32());
+ EXPECT_DOUBLE_EQ(1.0, transform.m33());
+ EXPECT_DOUBLE_EQ(0.0, transform.m34());
+ EXPECT_DOUBLE_EQ(0.0, transform.m41());
+ EXPECT_DOUBLE_EQ(0.0, transform.m42());
+ EXPECT_DOUBLE_EQ(0.0, transform.m43());
+ EXPECT_DOUBLE_EQ(1.0, transform.m44());
+}
+
+static void testGetAndSet(WebCore::TransformationMatrix& transform)
+{
+ transform.setA(1.1);
+ EXPECT_DOUBLE_EQ(1.1, transform.a());
+ transform.setB(2.2);
+ EXPECT_DOUBLE_EQ(2.2, transform.b());
+ transform.setC(3.3);
+ EXPECT_DOUBLE_EQ(3.3, transform.c());
+ transform.setD(4.4);
+ EXPECT_DOUBLE_EQ(4.4, transform.d());
+ transform.setE(5.5);
+ EXPECT_DOUBLE_EQ(5.5, transform.e());
+ transform.setF(6.6);
+ EXPECT_DOUBLE_EQ(6.6, transform.f());
+
+ transform.setM11(1.1);
+ EXPECT_DOUBLE_EQ(1.1, transform.m11());
+ transform.setM12(2.2);
+ EXPECT_DOUBLE_EQ(2.2, transform.m12());
+ transform.setM13(3.3);
+ EXPECT_DOUBLE_EQ(3.3, transform.m13());
+ transform.setM14(4.4);
+ EXPECT_DOUBLE_EQ(4.4, transform.m14());
+ transform.setM21(5.5);
+ EXPECT_DOUBLE_EQ(5.5, transform.m21());
+ transform.setM22(6.6);
+ EXPECT_DOUBLE_EQ(6.6, transform.m22());
+ transform.setM23(7.7);
+ EXPECT_DOUBLE_EQ(7.7, transform.m23());
+ transform.setM24(8.8);
+ EXPECT_DOUBLE_EQ(8.8, transform.m24());
+ transform.setM31(9.9);
+ EXPECT_DOUBLE_EQ(9.9, transform.m31());
+ transform.setM32(10.10);
+ EXPECT_DOUBLE_EQ(10.10, transform.m32());
+ transform.setM33(11.11);
+ EXPECT_DOUBLE_EQ(11.11, transform.m33());
+ transform.setM34(12.12);
+ EXPECT_DOUBLE_EQ(12.12, transform.m34());
+ transform.setM41(13.13);
+ EXPECT_DOUBLE_EQ(13.13, transform.m41());
+ transform.setM42(14.14);
+ EXPECT_DOUBLE_EQ(14.14, transform.m42());
+ transform.setM43(15.15);
+ EXPECT_DOUBLE_EQ(15.15, transform.m43());
+ transform.setM44(16.16);
+ EXPECT_DOUBLE_EQ(16.16, transform.m44());
+}
+
+TEST(TransformationMatrix, DefaultConstruction)
+{
+ WebCore::TransformationMatrix test;
+
+ testIdentity(test);
+
+ testGetAndSet(test);
+
+ ASSERT_FALSE(test.isIdentity());
+}
+
+static void testAffineLikeConstruction(const WebCore::TransformationMatrix& transform)
+{
+ EXPECT_DOUBLE_EQ(6.0, transform.a());
+ EXPECT_DOUBLE_EQ(5.0, transform.b());
+ EXPECT_DOUBLE_EQ(4.0, transform.c());
+ EXPECT_DOUBLE_EQ(3.0, transform.d());
+ EXPECT_DOUBLE_EQ(2.0, transform.e());
+ EXPECT_DOUBLE_EQ(1.0, transform.f());
+}
+
+static void testValueConstruction(const WebCore::TransformationMatrix& transform)
+{
+ EXPECT_DOUBLE_EQ(16.0, transform.m11());
+ EXPECT_DOUBLE_EQ(15.0, transform.m12());
+ EXPECT_DOUBLE_EQ(14.0, transform.m13());
+ EXPECT_DOUBLE_EQ(13.0, transform.m14());
+ EXPECT_DOUBLE_EQ(12.0, transform.m21());
+ EXPECT_DOUBLE_EQ(11.0, transform.m22());
+ EXPECT_DOUBLE_EQ(10.0, transform.m23());
+ EXPECT_DOUBLE_EQ(9.0, transform.m24());
+ EXPECT_DOUBLE_EQ(8.0, transform.m31());
+ EXPECT_DOUBLE_EQ(7.0, transform.m32());
+ EXPECT_DOUBLE_EQ(6.0, transform.m33());
+ EXPECT_DOUBLE_EQ(5.0, transform.m34());
+ EXPECT_DOUBLE_EQ(4.0, transform.m41());
+ EXPECT_DOUBLE_EQ(3.0, transform.m42());
+ EXPECT_DOUBLE_EQ(2.0, transform.m43());
+ EXPECT_DOUBLE_EQ(1.0, transform.m44());
+ ASSERT_FALSE(transform.isAffine());
+}
+
+TEST(TransformationMatrix, ValueConstruction)
+{
+ WebCore::TransformationMatrix test1(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ testAffineLikeConstruction(test1);
+
+ ASSERT_FALSE(test1.isIdentity());
+ ASSERT_TRUE(test1.isAffine());
+
+ WebCore::TransformationMatrix test2(16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0,
+ 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ testValueConstruction(test2);
+
+ testGetAndSet(test2);
+
+ ASSERT_FALSE(test2.isIdentity());
+ ASSERT_FALSE(test2.isAffine());
+
+ test2.makeIdentity();
+
+ testIdentity(test2);
+
+ ASSERT_TRUE(test2.isIdentity());
+}
+
+#if USE(CG)
+TEST(TransformationMatrix, CGAffineTransformConstruction)
+{
+ CGAffineTransform cgTransform = CGAffineTransformMake(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+ WebCore::TransformationMatrix test(cgTransform);
+
+ testAffineLikeConstruction(test);
+ testGetAndSet(test);
+
+ ASSERT_FALSE(test.isIdentity());
+}
+#endif
+
+#if PLATFORM(WIN)
+TEST(TransformationMatrix, D2D1MatrixConstruction)
+{
+ D2D1_MATRIX_3X2_F d2dTransform = D2D1::Matrix3x2F(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+ WebCore::TransformationMatrix test(d2dTransform);
+
+ testAffineLikeConstruction(test);
+ testGetAndSet(test);
+
+ ASSERT_FALSE(test.isIdentity());
+}
+#endif
+
+TEST(TransformationMatrix, AffineTransformConstruction)
+{
+ WebCore::AffineTransform affineTransform(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+ WebCore::TransformationMatrix test(affineTransform);
+
+ testAffineLikeConstruction(test);
+ testGetAndSet(test);
+
+ ASSERT_FALSE(test.isIdentity());
+}
+
+TEST(TransformationMatrix, TransformMatrixConstruction)
+{
+ WebCore::TransformationMatrix matrix(16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0,
+ 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+ WebCore::TransformationMatrix test(matrix);
+
+ testValueConstruction(test);
+}
+
+TEST(TransformationMatrix, Assignment)
+{
+ WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+ WebCore::TransformationMatrix matrix(16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0,
+ 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ testAffineLikeConstruction(test);
+
+ test = matrix;
+
+ testValueConstruction(test);
+}
+
+TEST(TransformationMatrix, Identity)
+{
+ WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ ASSERT_FALSE(test.isIdentity());
+ ASSERT_FALSE(test.isIdentityOrTranslation());
+
+ test.makeIdentity();
+
+ ASSERT_TRUE(test.isIdentity());
+ ASSERT_TRUE(test.isIdentityOrTranslation());
+
+ testIdentity(test);
+}
+
+static void testAffineVersion(WebCore::TransformationMatrix affineTransformMatrix)
+{
+ ASSERT_FALSE(affineTransformMatrix.isIdentity());
+ ASSERT_FALSE(affineTransformMatrix.isIdentityOrTranslation());
+ ASSERT_TRUE(affineTransformMatrix.isAffine());
+
+ EXPECT_DOUBLE_EQ(16.0, affineTransformMatrix.m11());
+ EXPECT_DOUBLE_EQ(15.0, affineTransformMatrix.m12());
+ EXPECT_DOUBLE_EQ(0.0, affineTransformMatrix.m13());
+ EXPECT_DOUBLE_EQ(0.0, affineTransformMatrix.m14());
+ EXPECT_DOUBLE_EQ(12.0, affineTransformMatrix.m21());
+ EXPECT_DOUBLE_EQ(11.0, affineTransformMatrix.m22());
+ EXPECT_DOUBLE_EQ(0.0, affineTransformMatrix.m23());
+ EXPECT_DOUBLE_EQ(0.0, affineTransformMatrix.m24());
+ EXPECT_DOUBLE_EQ(0.0, affineTransformMatrix.m31());
+ EXPECT_DOUBLE_EQ(0.0, affineTransformMatrix.m32());
+ EXPECT_DOUBLE_EQ(1.0, affineTransformMatrix.m33());
+ EXPECT_DOUBLE_EQ(0.0, affineTransformMatrix.m34());
+ EXPECT_DOUBLE_EQ(4.0, affineTransformMatrix.m41());
+ EXPECT_DOUBLE_EQ(3.0, affineTransformMatrix.m42());
+ EXPECT_DOUBLE_EQ(0.0, affineTransformMatrix.m43());
+ EXPECT_DOUBLE_EQ(1.0, affineTransformMatrix.m44());
+}
+
+TEST(TransformationMatrix, AffineVersion)
+{
+ WebCore::TransformationMatrix test(16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0,
+ 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ ASSERT_FALSE(test.isIdentity());
+ ASSERT_FALSE(test.isIdentityOrTranslation());
+ ASSERT_FALSE(test.isAffine());
+
+ auto affineCopy = test.toAffineTransform();
+
+ testAffineVersion(affineCopy);
+
+ test.makeAffine();
+
+ testAffineVersion(test);
+}
+
+TEST(TransformationMatrix, MapFloatPoint)
+{
+ WebCore::TransformationMatrix test;
+ WebCore::FloatPoint point(100.0f, 50.0f);
+
+ auto mappedPoint = test.mapPoint(point);
+
+ ASSERT_FLOAT_EQ(100.0f, mappedPoint.x());
+ ASSERT_FLOAT_EQ(50.0f, mappedPoint.y());
+
+ test.setD(2.0);
+
+ auto mappedPoint2 = test.mapPoint(point);
+
+ ASSERT_FLOAT_EQ(100.0f, mappedPoint2.x());
+ ASSERT_FLOAT_EQ(100.0f, mappedPoint2.y());
+
+ test.setA(0.5);
+
+ auto mappedPoint3 = test.mapPoint(point);
+
+ ASSERT_FLOAT_EQ(50.0f, mappedPoint3.x());
+ ASSERT_FLOAT_EQ(100.0f, mappedPoint3.y());
+
+ test.setM22(0.5);
+
+ auto mappedPoint4 = test.mapPoint(point);
+
+ ASSERT_FLOAT_EQ(50.0f, mappedPoint4.x());
+ ASSERT_FLOAT_EQ(25.0f, mappedPoint4.y());
+
+ test.setM11(2.0);
+
+ auto mappedPoint5 = test.mapPoint(point);
+
+ ASSERT_FLOAT_EQ(200.0f, mappedPoint5.x());
+ ASSERT_FLOAT_EQ(25.0f, mappedPoint5.y());
+}
+
+TEST(TransformationMatrix, MapIntPoint)
+{
+ WebCore::TransformationMatrix test;
+ WebCore::IntPoint point(100, 50);
+
+ auto mappedPoint = test.mapPoint(point);
+
+ ASSERT_EQ(100, mappedPoint.x());
+ ASSERT_EQ(50, mappedPoint.y());
+
+ test.setD(2.0);
+
+ auto mappedPoint2 = test.mapPoint(point);
+
+ ASSERT_EQ(100, mappedPoint2.x());
+ ASSERT_EQ(100, mappedPoint2.y());
+
+ test.setA(0.5);
+
+ auto mappedPoint3 = test.mapPoint(point);
+
+ ASSERT_EQ(50, mappedPoint3.x());
+ ASSERT_EQ(100, mappedPoint3.y());
+
+ test.setM22(0.5);
+
+ auto mappedPoint4 = test.mapPoint(point);
+
+ ASSERT_EQ(50, mappedPoint4.x());
+ ASSERT_EQ(25, mappedPoint4.y());
+
+ test.setM11(2.0);
+
+ auto mappedPoint5 = test.mapPoint(point);
+
+ ASSERT_EQ(200, mappedPoint5.x());
+ ASSERT_EQ(25, mappedPoint5.y());
+}
+
+TEST(TransformationMatrix, MapIntRect)
+{
+ WebCore::TransformationMatrix test;
+ WebCore::IntRect rect(10, 20, 200, 300);
+
+ auto mappedRect = test.mapRect(rect);
+
+ ASSERT_EQ(10, mappedRect.x());
+ ASSERT_EQ(20, mappedRect.y());
+ ASSERT_EQ(200, mappedRect.width());
+ ASSERT_EQ(300, mappedRect.height());
+
+ test.setD(2.0);
+
+ auto mappedRect2 = test.mapRect(rect);
+
+ ASSERT_EQ(10, mappedRect2.x());
+ ASSERT_EQ(40, mappedRect2.y());
+ ASSERT_EQ(200, mappedRect2.width());
+ ASSERT_EQ(600, mappedRect2.height());
+
+ test.setA(0.5);
+
+ auto mappedRect3 = test.mapRect(rect);
+
+ ASSERT_EQ(5, mappedRect3.x());
+ ASSERT_EQ(40, mappedRect3.y());
+ ASSERT_EQ(100, mappedRect3.width());
+ ASSERT_EQ(600, mappedRect3.height());
+
+ test.setM22(0.5);
+
+ auto mappedRect4 = test.mapRect(rect);
+
+ ASSERT_EQ(5, mappedRect4.x());
+ ASSERT_EQ(10, mappedRect4.y());
+ ASSERT_EQ(100, mappedRect4.width());
+ ASSERT_EQ(150, mappedRect4.height());
+
+ test.setM11(2.0);
+
+ auto mappedRect5 = test.mapRect(rect);
+
+ ASSERT_EQ(20, mappedRect5.x());
+ ASSERT_EQ(10, mappedRect5.y());
+ ASSERT_EQ(100, mappedRect4.width());
+ ASSERT_EQ(150, mappedRect4.height());
+}
+
+TEST(TransformationMatrix, MapFloatRect)
+{
+ WebCore::TransformationMatrix test;
+ WebCore::FloatRect rect(10.f, 20.0f, 200.0f, 300.0f);
+
+ auto mappedRect = test.mapRect(rect);
+
+ ASSERT_FLOAT_EQ(10.0f, mappedRect.x());
+ ASSERT_FLOAT_EQ(20.0f, mappedRect.y());
+ ASSERT_FLOAT_EQ(200.0f, mappedRect.width());
+ ASSERT_FLOAT_EQ(300.0f, mappedRect.height());
+
+ test.setD(2.0);
+
+ auto mappedRect2 = test.mapRect(rect);
+
+ ASSERT_FLOAT_EQ(10.0f, mappedRect2.x());
+ ASSERT_FLOAT_EQ(40.0f, mappedRect2.y());
+ ASSERT_FLOAT_EQ(200.0f, mappedRect2.width());
+ ASSERT_FLOAT_EQ(600.0f, mappedRect2.height());
+
+ test.setA(0.5);
+
+ auto mappedRect3 = test.mapRect(rect);
+
+ ASSERT_FLOAT_EQ(5.0f, mappedRect3.x());
+ ASSERT_FLOAT_EQ(40.0f, mappedRect3.y());
+ ASSERT_FLOAT_EQ(100.0f, mappedRect3.width());
+ ASSERT_FLOAT_EQ(600.0f, mappedRect3.height());
+
+ test.setM22(0.5);
+
+ auto mappedRect4 = test.mapRect(rect);
+
+ ASSERT_FLOAT_EQ(5.0f, mappedRect4.x());
+ ASSERT_FLOAT_EQ(10.0f, mappedRect4.y());
+ ASSERT_FLOAT_EQ(100.0f, mappedRect4.width());
+ ASSERT_FLOAT_EQ(150.0f, mappedRect4.height());
+
+ test.setM11(2.0);
+
+ auto mappedRect5 = test.mapRect(rect);
+
+ ASSERT_FLOAT_EQ(20.0f, mappedRect5.x());
+ ASSERT_FLOAT_EQ(10.0f, mappedRect5.y());
+ ASSERT_FLOAT_EQ(100.0f, mappedRect4.width());
+ ASSERT_FLOAT_EQ(150.0f, mappedRect4.height());
+}
+
+TEST(TransformationMatrix, MapFloatQuad)
+{
+ WebCore::FloatRect rect(100.0f, 100.0f, 100.0f, 50.0f);
+ WebCore::FloatQuad quad(rect);
+
+ ASSERT_FLOAT_EQ(100.0f, quad.p1().x());
+ ASSERT_FLOAT_EQ(100.0f, quad.p1().y());
+ ASSERT_FLOAT_EQ(200.0f, quad.p2().x());
+ ASSERT_FLOAT_EQ(100.0f, quad.p2().y());
+ ASSERT_FLOAT_EQ(200.0f, quad.p3().x());
+ ASSERT_FLOAT_EQ(150.0f, quad.p3().y());
+ ASSERT_FLOAT_EQ(100.0f, quad.p4().x());
+ ASSERT_FLOAT_EQ(150.0f, quad.p4().y());
+
+ WebCore::TransformationMatrix test;
+ auto mappedQuad = test.mapQuad(quad);
+
+ ASSERT_FLOAT_EQ(100.0f, mappedQuad.p1().x());
+ ASSERT_FLOAT_EQ(100.0f, mappedQuad.p1().y());
+ ASSERT_FLOAT_EQ(200.0f, mappedQuad.p2().x());
+ ASSERT_FLOAT_EQ(100.0f, mappedQuad.p2().y());
+ ASSERT_FLOAT_EQ(200.0f, mappedQuad.p3().x());
+ ASSERT_FLOAT_EQ(150.0f, mappedQuad.p3().y());
+ ASSERT_FLOAT_EQ(100.0f, mappedQuad.p4().x());
+ ASSERT_FLOAT_EQ(150.0f, mappedQuad.p4().y());
+
+ test.setD(2.0);
+
+ auto mappedQuad2 = test.mapQuad(quad);
+
+ ASSERT_FLOAT_EQ(100.0f, mappedQuad2.p1().x());
+ ASSERT_FLOAT_EQ(200.0f, mappedQuad2.p1().y());
+ ASSERT_FLOAT_EQ(200.0f, mappedQuad2.p2().x());
+ ASSERT_FLOAT_EQ(200.0f, mappedQuad2.p2().y());
+ ASSERT_FLOAT_EQ(200.0f, mappedQuad2.p3().x());
+ ASSERT_FLOAT_EQ(300.0f, mappedQuad2.p3().y());
+ ASSERT_FLOAT_EQ(100.0f, mappedQuad2.p4().x());
+ ASSERT_FLOAT_EQ(300.0f, mappedQuad2.p4().y());
+
+ test.setA(0.5);
+
+ auto mappedQuad3 = test.mapQuad(quad);
+
+ ASSERT_FLOAT_EQ(50.0f, mappedQuad3.p1().x());
+ ASSERT_FLOAT_EQ(200.0f, mappedQuad3.p1().y());
+ ASSERT_FLOAT_EQ(100.0f, mappedQuad3.p2().x());
+ ASSERT_FLOAT_EQ(200.0f, mappedQuad3.p2().y());
+ ASSERT_FLOAT_EQ(100.0f, mappedQuad3.p3().x());
+ ASSERT_FLOAT_EQ(300.0f, mappedQuad3.p3().y());
+ ASSERT_FLOAT_EQ(50.0f, mappedQuad3.p4().x());
+ ASSERT_FLOAT_EQ(300.0f, mappedQuad3.p4().y());
+
+ test.setM22(0.5);
+
+ auto mappedQuad4 = test.mapQuad(quad);
+
+ ASSERT_FLOAT_EQ(50.0f, mappedQuad4.p1().x());
+ ASSERT_FLOAT_EQ(50.0f, mappedQuad4.p1().y());
+ ASSERT_FLOAT_EQ(100.0f, mappedQuad4.p2().x());
+ ASSERT_FLOAT_EQ(50.0f, mappedQuad4.p2().y());
+ ASSERT_FLOAT_EQ(100.0f, mappedQuad4.p3().x());
+ ASSERT_FLOAT_EQ(75.0f, mappedQuad4.p3().y());
+ ASSERT_FLOAT_EQ(50.0f, mappedQuad4.p4().x());
+ ASSERT_FLOAT_EQ(75.0f, mappedQuad4.p4().y());
+
+ test.setM11(2.0);
+
+ auto mappedQuad5 = test.mapQuad(quad);
+
+ ASSERT_FLOAT_EQ(200.0f, mappedQuad5.p1().x());
+ ASSERT_FLOAT_EQ(50.0f, mappedQuad5.p1().y());
+ ASSERT_FLOAT_EQ(400.0f, mappedQuad5.p2().x());
+ ASSERT_FLOAT_EQ(50.0f, mappedQuad5.p2().y());
+ ASSERT_FLOAT_EQ(400.0f, mappedQuad5.p3().x());
+ ASSERT_FLOAT_EQ(75.0f, mappedQuad5.p3().y());
+ ASSERT_FLOAT_EQ(200.0f, mappedQuad5.p4().x());
+ ASSERT_FLOAT_EQ(75.0f, mappedQuad5.p4().y());
+}
+
+static void testDoubled(const WebCore::TransformationMatrix& transform)
+{
+ EXPECT_DOUBLE_EQ(12.0, transform.a());
+ EXPECT_DOUBLE_EQ(10.0, transform.b());
+ EXPECT_DOUBLE_EQ(8.0, transform.c());
+ EXPECT_DOUBLE_EQ(6.0, transform.d());
+ EXPECT_DOUBLE_EQ(2.0, transform.e());
+ EXPECT_DOUBLE_EQ(1.0, transform.f());
+}
+
+static void testHalved(const WebCore::TransformationMatrix& transform)
+{
+ EXPECT_DOUBLE_EQ(3.0, transform.a());
+ EXPECT_DOUBLE_EQ(2.5, transform.b());
+ EXPECT_DOUBLE_EQ(2.0, transform.c());
+ EXPECT_DOUBLE_EQ(1.5, transform.d());
+ EXPECT_DOUBLE_EQ(2.0, transform.e());
+ EXPECT_DOUBLE_EQ(1.0, transform.f());
+}
+
+static void testDoubled2(const WebCore::TransformationMatrix& transform)
+{
+ EXPECT_DOUBLE_EQ(32.0, transform.m11());
+ EXPECT_DOUBLE_EQ(30.0, transform.m12());
+ EXPECT_DOUBLE_EQ(28.0, transform.m13());
+ EXPECT_DOUBLE_EQ(26.0, transform.m14());
+ EXPECT_DOUBLE_EQ(24.0, transform.m21());
+ EXPECT_DOUBLE_EQ(22.0, transform.m22());
+ EXPECT_DOUBLE_EQ(20.0, transform.m23());
+ EXPECT_DOUBLE_EQ(18.0, transform.m24());
+ EXPECT_DOUBLE_EQ(16.0, transform.m31());
+ EXPECT_DOUBLE_EQ(14.0, transform.m32());
+ EXPECT_DOUBLE_EQ(12.0, transform.m33());
+ EXPECT_DOUBLE_EQ(10.0, transform.m34());
+ EXPECT_DOUBLE_EQ(8.0, transform.m41());
+ EXPECT_DOUBLE_EQ(6.0, transform.m42());
+ EXPECT_DOUBLE_EQ(4.0, transform.m43());
+ EXPECT_DOUBLE_EQ(2.0, transform.m44());
+}
+
+static void testHalved2(const WebCore::TransformationMatrix& transform)
+{
+ EXPECT_DOUBLE_EQ(8.0, transform.m11());
+ EXPECT_DOUBLE_EQ(7.5, transform.m12());
+ EXPECT_DOUBLE_EQ(7.0, transform.m13());
+ EXPECT_DOUBLE_EQ(6.5, transform.m14());
+ EXPECT_DOUBLE_EQ(6.0, transform.m21());
+ EXPECT_DOUBLE_EQ(5.5, transform.m22());
+ EXPECT_DOUBLE_EQ(5.0, transform.m23());
+ EXPECT_DOUBLE_EQ(4.5, transform.m24());
+ EXPECT_DOUBLE_EQ(4.0, transform.m31());
+ EXPECT_DOUBLE_EQ(3.5, transform.m32());
+ EXPECT_DOUBLE_EQ(3.0, transform.m33());
+ EXPECT_DOUBLE_EQ(2.5, transform.m34());
+ EXPECT_DOUBLE_EQ(2.0, transform.m41());
+ EXPECT_DOUBLE_EQ(1.5, transform.m42());
+ EXPECT_DOUBLE_EQ(1.0, transform.m43());
+ EXPECT_DOUBLE_EQ(0.5, transform.m44());
+}
+
+TEST(TransformationMatrix, Multiply)
+{
+ WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+ WebCore::TransformationMatrix identity;
+
+ testAffineLikeConstruction(test);
+
+ test.multiply(identity);
+
+ testAffineLikeConstruction(test);
+
+ WebCore::TransformationMatrix doubler(2.0, 0.0, 0.0, 2.0, 0.0, 0.0);
+
+ test.multiply(doubler);
+
+ testDoubled(test);
+
+ WebCore::TransformationMatrix halver(0.5, 0.0, 0.0, 0.5, 0.0, 0.0);
+
+ test.multiply(halver);
+
+ testAffineLikeConstruction(test);
+
+ test.multiply(halver);
+
+ testHalved(test);
+
+ WebCore::TransformationMatrix test2(16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0,
+ 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ testValueConstruction(test2);
+
+ test2.multiply(identity);
+
+ testValueConstruction(test2);
+
+ WebCore::TransformationMatrix doubler2(2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0,
+ 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0);
+
+ test2.multiply(doubler2);
+
+ testDoubled2(test2);
+
+ WebCore::TransformationMatrix halver2(0.5, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0,
+ 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.5);
+
+ test2.multiply(halver2);
+
+ testValueConstruction(test2);
+
+ test2.multiply(halver2);
+
+ testHalved2(test2);
+
+ WebCore::TransformationMatrix test3(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ test3 *= identity;
+
+ testAffineLikeConstruction(test3);
+
+ test3 *= doubler;
+
+ testDoubled(test3);
+
+ const WebCore::TransformationMatrix test4(16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0,
+ 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ auto result1 = test4 * identity;
+
+ testValueConstruction(result1);
+
+ auto result2 = test4 * doubler2;
+
+ testDoubled2(result2);
+}
+
+static void testScaledByTwo(const WebCore::TransformationMatrix& transform)
+{
+ EXPECT_DOUBLE_EQ(32.0, transform.m11());
+ EXPECT_DOUBLE_EQ(30.0, transform.m12());
+ EXPECT_DOUBLE_EQ(28.0, transform.m13());
+ EXPECT_DOUBLE_EQ(26.0, transform.m14());
+ EXPECT_DOUBLE_EQ(24.0, transform.m21());
+ EXPECT_DOUBLE_EQ(22.0, transform.m22());
+ EXPECT_DOUBLE_EQ(20.0, transform.m23());
+ EXPECT_DOUBLE_EQ(18.0, transform.m24());
+ EXPECT_DOUBLE_EQ(8.0, transform.m31());
+ EXPECT_DOUBLE_EQ(7.0, transform.m32());
+ EXPECT_DOUBLE_EQ(6.0, transform.m33());
+ EXPECT_DOUBLE_EQ(5.0, transform.m34());
+ EXPECT_DOUBLE_EQ(4.0, transform.m41());
+ EXPECT_DOUBLE_EQ(3.0, transform.m42());
+ EXPECT_DOUBLE_EQ(2.0, transform.m43());
+ EXPECT_DOUBLE_EQ(1.0, transform.m44());
+}
+
+static void testScaledByHalf(const WebCore::TransformationMatrix& transform)
+{
+ EXPECT_DOUBLE_EQ(8.0, transform.m11());
+ EXPECT_DOUBLE_EQ(7.5, transform.m12());
+ EXPECT_DOUBLE_EQ(7.0, transform.m13());
+ EXPECT_DOUBLE_EQ(6.5, transform.m14());
+ EXPECT_DOUBLE_EQ(6.0, transform.m21());
+ EXPECT_DOUBLE_EQ(5.5, transform.m22());
+ EXPECT_DOUBLE_EQ(5.0, transform.m23());
+ EXPECT_DOUBLE_EQ(4.5, transform.m24());
+ EXPECT_DOUBLE_EQ(8.0, transform.m31());
+ EXPECT_DOUBLE_EQ(7.0, transform.m32());
+ EXPECT_DOUBLE_EQ(6.0, transform.m33());
+ EXPECT_DOUBLE_EQ(5.0, transform.m34());
+ EXPECT_DOUBLE_EQ(4.0, transform.m41());
+ EXPECT_DOUBLE_EQ(3.0, transform.m42());
+ EXPECT_DOUBLE_EQ(2.0, transform.m43());
+ EXPECT_DOUBLE_EQ(1.0, transform.m44());
+}
+
+
+TEST(TransformationMatrix, Scale)
+{
+ WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ testAffineLikeConstruction(test);
+
+ test.scale(1.0);
+
+ testAffineLikeConstruction(test);
+
+ test.scale(2.0);
+
+ testDoubled(test);
+
+ test.scale(0.5);
+
+ testAffineLikeConstruction(test);
+
+ test.scale(0.5);
+
+ testHalved(test);
+
+ WebCore::TransformationMatrix test2(16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0,
+ 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ testValueConstruction(test2);
+
+ test2.scale(2.0);
+
+ testScaledByTwo(test2);
+
+ test2.scale(0.5);
+
+ testValueConstruction(test2);
+
+ test2.scale(0.5);
+
+ testScaledByHalf(test2);
+}
+
+TEST(TransformationMatrix, ScaleUniformNonUniform)
+{
+ WebCore::TransformationMatrix test(16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0,
+ 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ testValueConstruction(test);
+
+ test.scaleNonUniform(1.0, 1.0);
+
+ testValueConstruction(test);
+
+ test.scaleNonUniform(2.0, 2.0);
+
+ testScaledByTwo(test);
+
+ test.scaleNonUniform(0.5, 0.5);
+
+ testValueConstruction(test);
+
+ test.scaleNonUniform(0.5, 0.5);
+
+ testScaledByHalf(test);
+}
+
+TEST(TransformationMatrix, Rotate)
+{
+ WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ test.rotate(360.0);
+
+ testAffineLikeConstruction(test);
+
+ test.rotate(180.0);
+
+ static double epsilon = 0.0001;
+
+ EXPECT_NEAR(-6.0, test.a(), epsilon);
+ EXPECT_NEAR(-5.0, test.b(), epsilon);
+ EXPECT_NEAR(-4.0, test.c(), epsilon);
+ EXPECT_NEAR(-3.0, test.d(), epsilon);
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ test.rotate(-180.0);
+
+ testAffineLikeConstruction(test);
+
+ test.rotate(90.0);
+
+ EXPECT_NEAR(4.0, test.a(), epsilon);
+ EXPECT_NEAR(3.0, test.b(), epsilon);
+ EXPECT_NEAR(-6.0, test.c(), epsilon);
+ EXPECT_NEAR(-5.0, test.d(), epsilon);
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ test.rotate(-90.0);
+
+ testAffineLikeConstruction(test);
+}
+
+TEST(TransformationMatrix, TranslateXY)
+{
+ WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ test.translate(0.0, 0.0);
+
+ testAffineLikeConstruction(test);
+
+ test.translate(5.0, 0.0);
+
+ EXPECT_DOUBLE_EQ(6.0, test.a());
+ EXPECT_DOUBLE_EQ(5.0, test.b());
+ EXPECT_DOUBLE_EQ(4.0, test.c());
+ EXPECT_DOUBLE_EQ(3.0, test.d());
+ EXPECT_DOUBLE_EQ(32.0, test.e());
+ EXPECT_DOUBLE_EQ(26.0, test.f());
+
+ test.translate(0.0, -1.2);
+
+ EXPECT_DOUBLE_EQ(6.0, test.a());
+ EXPECT_DOUBLE_EQ(5.0, test.b());
+ EXPECT_DOUBLE_EQ(4.0, test.c());
+ EXPECT_DOUBLE_EQ(3.0, test.d());
+ EXPECT_DOUBLE_EQ(27.2, test.e());
+ EXPECT_DOUBLE_EQ(22.4, test.f());
+}
+
+TEST(TransformationMatrix, FlipX)
+{
+ WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ testAffineLikeConstruction(test);
+
+ test.flipX();
+
+ EXPECT_DOUBLE_EQ(-6.0, test.a());
+ EXPECT_DOUBLE_EQ(-5.0, test.b());
+ EXPECT_DOUBLE_EQ(4.0, test.c());
+ EXPECT_DOUBLE_EQ(3.0, test.d());
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ test.flipX();
+
+ testAffineLikeConstruction(test);
+
+ WebCore::TransformationMatrix test2;
+
+ testIdentity(test2);
+
+ ASSERT_TRUE(test2.isIdentity());
+ ASSERT_TRUE(test2.isIdentityOrTranslation());
+
+ test2.flipX();
+
+ EXPECT_DOUBLE_EQ(-1.0, test2.a());
+ EXPECT_DOUBLE_EQ(0.0, test2.b());
+ EXPECT_DOUBLE_EQ(0.0, test2.c());
+ EXPECT_DOUBLE_EQ(1.0, test2.d());
+ EXPECT_DOUBLE_EQ(0.0, test2.e());
+ EXPECT_DOUBLE_EQ(0.0, test2.f());
+
+ ASSERT_FALSE(test2.isIdentity());
+ ASSERT_FALSE(test2.isIdentityOrTranslation());
+
+ test2.flipX();
+
+ ASSERT_TRUE(test2.isIdentity());
+ ASSERT_TRUE(test2.isIdentityOrTranslation());
+}
+
+TEST(TransformationMatrix, FlipY)
+{
+ WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ testAffineLikeConstruction(test);
+
+ test.flipY();
+
+ EXPECT_DOUBLE_EQ(6.0, test.a());
+ EXPECT_DOUBLE_EQ(5.0, test.b());
+ EXPECT_DOUBLE_EQ(-4.0, test.c());
+ EXPECT_DOUBLE_EQ(-3.0, test.d());
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ test.flipY();
+
+ testAffineLikeConstruction(test);
+
+ WebCore::TransformationMatrix test2;
+
+ testIdentity(test2);
+
+ ASSERT_TRUE(test2.isIdentity());
+ ASSERT_TRUE(test2.isIdentityOrTranslation());
+
+ test2.flipY();
+
+ EXPECT_DOUBLE_EQ(1.0, test2.a());
+ EXPECT_DOUBLE_EQ(0.0, test2.b());
+ EXPECT_DOUBLE_EQ(0.0, test2.c());
+ EXPECT_DOUBLE_EQ(-1.0, test2.d());
+ EXPECT_DOUBLE_EQ(0.0, test2.e());
+ EXPECT_DOUBLE_EQ(0.0, test2.f());
+
+ ASSERT_FALSE(test2.isIdentity());
+ ASSERT_FALSE(test2.isIdentityOrTranslation());
+
+ test2.flipY();
+
+ ASSERT_TRUE(test2.isIdentity());
+ ASSERT_TRUE(test2.isIdentityOrTranslation());
+}
+
+TEST(TransformationMatrix, FlipXandFlipY)
+{
+ WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ testAffineLikeConstruction(test);
+
+ test.flipX();
+
+ EXPECT_DOUBLE_EQ(-6.0, test.a());
+ EXPECT_DOUBLE_EQ(-5.0, test.b());
+ EXPECT_DOUBLE_EQ(4.0, test.c());
+ EXPECT_DOUBLE_EQ(3.0, test.d());
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ test.flipY();
+
+ EXPECT_DOUBLE_EQ(-6.0, test.a());
+ EXPECT_DOUBLE_EQ(-5.0, test.b());
+ EXPECT_DOUBLE_EQ(-4.0, test.c());
+ EXPECT_DOUBLE_EQ(-3.0, test.d());
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ test.flipX();
+
+ EXPECT_DOUBLE_EQ(6.0, test.a());
+ EXPECT_DOUBLE_EQ(5.0, test.b());
+ EXPECT_DOUBLE_EQ(-4.0, test.c());
+ EXPECT_DOUBLE_EQ(-3.0, test.d());
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ test.flipY();
+
+ testAffineLikeConstruction(test);
+
+ WebCore::TransformationMatrix test2;
+
+ ASSERT_TRUE(test2.isIdentity());
+ ASSERT_TRUE(test2.isIdentityOrTranslation());
+
+ test2.flipX();
+
+ ASSERT_FALSE(test2.isIdentity());
+ ASSERT_FALSE(test2.isIdentityOrTranslation());
+
+ test2.flipY();
+
+ ASSERT_FALSE(test2.isIdentity());
+ ASSERT_FALSE(test2.isIdentityOrTranslation());
+
+ test2.flipX();
+
+ ASSERT_FALSE(test2.isIdentity());
+ ASSERT_FALSE(test2.isIdentityOrTranslation());
+
+ test2.flipY();
+
+ ASSERT_TRUE(test2.isIdentity());
+ ASSERT_TRUE(test2.isIdentityOrTranslation());
+}
+
+TEST(TransformationMatrix, Skew)
+{
+ WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+ testAffineLikeConstruction(test);
+
+ test.skew(360.0, 360.0);
+
+ testAffineLikeConstruction(test);
+
+ test.skew(0.0, 0.0);
+
+ testAffineLikeConstruction(test);
+
+ test.skew(180.0, 180.0);
+
+ static double epsilon = 0.0001;
+
+ EXPECT_DOUBLE_EQ(6.0, test.a());
+ EXPECT_DOUBLE_EQ(5.0, test.b());
+ EXPECT_NEAR(4.0, test.c(), epsilon);
+ EXPECT_DOUBLE_EQ(3.0, test.d());
+ EXPECT_DOUBLE_EQ(2.0, test.e());
+ EXPECT_DOUBLE_EQ(1.0, test.f());
+
+ test.skew(-180.0, -180.0);
+
+ testAffineLikeConstruction(test);
+}
+
+TEST(TransformationMatrix, Inverse)
+{
+ WebCore::TransformationMatrix test;
+
+ auto inverse = test.inverse();
+
+ ASSERT(inverse);
+
+ EXPECT_DOUBLE_EQ(1.0, inverse->a());
+ EXPECT_DOUBLE_EQ(0.0, inverse->b());
+ EXPECT_DOUBLE_EQ(0.0, inverse->c());
+ EXPECT_DOUBLE_EQ(1.0, inverse->d());
+ EXPECT_DOUBLE_EQ(0.0, inverse->e());
+ EXPECT_DOUBLE_EQ(0.0, inverse->f());
+
+ auto test2 = test * inverse.value();
+
+ testIdentity(test2);
+}
+
+TEST(TransformationMatrix, NonInvertableBlend)
+{
+ WebCore::TransformationMatrix from;
+ WebCore::TransformationMatrix to(2.7133590938, 0.0, 0.0, 0.0, 0.0, 2.4645137761, 0.0, 0.0, 0.0, 0.0, 0.00, 0.01, 0.02, 0.03, 0.04, 0.05);
+ WebCore::TransformationMatrix result;
+
+ result = to;
+ result.blend(from, 0.25);
+ EXPECT_TRUE(result == from);
+
+ result = to;
+ result.blend(from, 0.75);
+ EXPECT_TRUE(result == to);
+}
+
+TEST(TransformationMatrix, Blend)
+{
+ WebCore::TransformationMatrix transform;
+
+ WebCore::TransformationMatrix scaled;
+ scaled.scale(2.0);
+
+ transform.blend(scaled, 50);
+
+ static const double epsilon = 0.0001;
+ EXPECT_NEAR(-48.0, transform.m11(), epsilon);
+ EXPECT_NEAR(0.0, transform.m12(), epsilon);
+ EXPECT_NEAR(0.0, transform.m13(), epsilon);
+ EXPECT_NEAR(0.0, transform.m14(), epsilon);
+ EXPECT_NEAR(0.0, transform.m21(), epsilon);
+ EXPECT_NEAR(-48.0, transform.m22(), epsilon);
+ EXPECT_NEAR(0.0, transform.m23(), epsilon);
+ EXPECT_NEAR(0.0, transform.m24(), epsilon);
+ EXPECT_NEAR(0.0, transform.m31(), epsilon);
+ EXPECT_NEAR(0.0, transform.m32(), epsilon);
+ EXPECT_NEAR(1.0, transform.m33(), epsilon);
+ EXPECT_NEAR(0.0, transform.m34(), epsilon);
+ EXPECT_NEAR(0.0, transform.m41(), epsilon);
+ EXPECT_NEAR(0.0, transform.m42(), epsilon);
+ EXPECT_NEAR(0.0, transform.m43(), epsilon);
+ EXPECT_NEAR(1.0, transform.m44(), epsilon);
+}
+
+TEST(TransformationMatrix, Blend2)
+{
+ WebCore::TransformationMatrix transform;
+
+ WebCore::TransformationMatrix scaled;
+ scaled.scale(2.0);
+
+ transform.blend2(scaled, 20);
+
+ static const double epsilon = 0.0001;
+ EXPECT_NEAR(-18.0, transform.m11(), epsilon);
+ EXPECT_NEAR(0.0, transform.m12(), epsilon);
+ EXPECT_NEAR(0.0, transform.m13(), epsilon);
+ EXPECT_NEAR(0.0, transform.m14(), epsilon);
+ EXPECT_NEAR(0.0, transform.m21(), epsilon);
+ EXPECT_NEAR(-18.0, transform.m22(), epsilon);
+ EXPECT_NEAR(0.0, transform.m23(), epsilon);
+ EXPECT_NEAR(0.0, transform.m24(), epsilon);
+ EXPECT_NEAR(0.0, transform.m31(), epsilon);
+ EXPECT_NEAR(0.0, transform.m32(), epsilon);
+ EXPECT_NEAR(1.0, transform.m33(), epsilon);
+ EXPECT_NEAR(0.0, transform.m34(), epsilon);
+ EXPECT_NEAR(0.0, transform.m41(), epsilon);
+ EXPECT_NEAR(0.0, transform.m42(), epsilon);
+ EXPECT_NEAR(0.0, transform.m43(), epsilon);
+ EXPECT_NEAR(1.0, transform.m44(), epsilon);
+}
+
+TEST(TransformationMatrix, Blend4)
+{
+ WebCore::TransformationMatrix transform;
+
+ WebCore::TransformationMatrix scaled;
+ scaled.scale(2.0);
+
+ transform.blend4(scaled, 30);
+
+ static const double epsilon = 0.0001;
+ EXPECT_NEAR(-28.0, transform.m11(), epsilon);
+ EXPECT_NEAR(0.0, transform.m12(), epsilon);
+ EXPECT_NEAR(0.0, transform.m13(), epsilon);
+ EXPECT_NEAR(0.0, transform.m14(), epsilon);
+ EXPECT_NEAR(0.0, transform.m21(), epsilon);
+ EXPECT_NEAR(-28.0, transform.m22(), epsilon);
+ EXPECT_NEAR(0.0, transform.m23(), epsilon);
+ EXPECT_NEAR(0.0, transform.m24(), epsilon);
+ EXPECT_NEAR(0.0, transform.m31(), epsilon);
+ EXPECT_NEAR(0.0, transform.m32(), epsilon);
+ EXPECT_NEAR(1.0, transform.m33(), epsilon);
+ EXPECT_NEAR(0.0, transform.m34(), epsilon);
+ EXPECT_NEAR(0.0, transform.m41(), epsilon);
+ EXPECT_NEAR(0.0, transform.m42(), epsilon);
+ EXPECT_NEAR(0.0, transform.m43(), epsilon);
+ EXPECT_NEAR(1.0, transform.m44(), epsilon);
+}
+
+TEST(TransformationMatrix, Equality)
+{
+ WebCore::TransformationMatrix test(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+ WebCore::TransformationMatrix test2;
+
+ ASSERT_FALSE(test == test2);
+ ASSERT_TRUE(test != test2);
+
+ test.makeIdentity();
+
+ ASSERT_TRUE(test == test2);
+ ASSERT_FALSE(test != test2);
+
+ WebCore::TransformationMatrix test3(16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0,
+ 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+ WebCore::TransformationMatrix test4(test3);
+
+ ASSERT_TRUE(test3 == test4);
+ ASSERT_FALSE(test3 != test4);
+
+ test4.setM43(1002.22);
+
+ ASSERT_FALSE(test3 == test4);
+ ASSERT_TRUE(test3 != test4);
+}
+
+static void testTranslationMatrix(const WebCore::TransformationMatrix& matrix)
+{
+ EXPECT_DOUBLE_EQ(1.0, matrix.m11());
+ EXPECT_DOUBLE_EQ(0.0, matrix.m12());
+ EXPECT_DOUBLE_EQ(0.0, matrix.m13());
+ EXPECT_DOUBLE_EQ(0.0, matrix.m14());
+ EXPECT_DOUBLE_EQ(0.0, matrix.m21());
+ EXPECT_DOUBLE_EQ(1.0, matrix.m22());
+ EXPECT_DOUBLE_EQ(0.0, matrix.m23());
+ EXPECT_DOUBLE_EQ(0.0, matrix.m24());
+ EXPECT_DOUBLE_EQ(0.0, matrix.m31());
+ EXPECT_DOUBLE_EQ(0.0, matrix.m32());
+ EXPECT_DOUBLE_EQ(1.0, matrix.m33());
+ EXPECT_DOUBLE_EQ(0.0, matrix.m34());
+ EXPECT_DOUBLE_EQ(10.0, matrix.m41());
+ EXPECT_DOUBLE_EQ(15.0, matrix.m42());
+ EXPECT_DOUBLE_EQ(30.0, matrix.m43());
+ EXPECT_DOUBLE_EQ(1.0, matrix.m44());
+}
+
+TEST(TransformationMatrix, Casting)
+{
+ WebCore::TransformationMatrix test(16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0,
+ 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+
+#if USE(CA)
+ CATransform3D caTransform = CATransform3DMakeTranslation(10.0f, 15.0f, 30.0f);
+
+ WebCore::TransformationMatrix fromCATransform(caTransform);
+
+ testTranslationMatrix(fromCATransform);
+
+ CATransform3D caFromWK = test;
+
+ EXPECT_DOUBLE_EQ(16.0, caFromWK.m11);
+ EXPECT_DOUBLE_EQ(15.0, caFromWK.m12);
+ EXPECT_DOUBLE_EQ(14.0, caFromWK.m13);
+ EXPECT_DOUBLE_EQ(13.0, caFromWK.m14);
+ EXPECT_DOUBLE_EQ(12.0, caFromWK.m21);
+ EXPECT_DOUBLE_EQ(11.0, caFromWK.m22);
+ EXPECT_DOUBLE_EQ(10.0, caFromWK.m23);
+ EXPECT_DOUBLE_EQ(9.0, caFromWK.m24);
+ EXPECT_DOUBLE_EQ(8.0, caFromWK.m31);
+ EXPECT_DOUBLE_EQ(7.0, caFromWK.m32);
+ EXPECT_DOUBLE_EQ(6.0, caFromWK.m33);
+ EXPECT_DOUBLE_EQ(5.0, caFromWK.m34);
+ EXPECT_DOUBLE_EQ(4.0, caFromWK.m41);
+ EXPECT_DOUBLE_EQ(3.0, caFromWK.m42);
+ EXPECT_DOUBLE_EQ(2.0, caFromWK.m43);
+ EXPECT_DOUBLE_EQ(1.0, caFromWK.m44);
+#endif
+
+#if USE(CG)
+ CGAffineTransform cgTransform = CGAffineTransformMake(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+ WebCore::TransformationMatrix fromCGTransform(cgTransform);
+
+ testAffineLikeConstruction(fromCGTransform);
+
+ CGAffineTransform cgFromWK = test;
+ EXPECT_DOUBLE_EQ(16.0, cgFromWK.a);
+ EXPECT_DOUBLE_EQ(15.0, cgFromWK.b);
+ EXPECT_DOUBLE_EQ(12.0, cgFromWK.c);
+ EXPECT_DOUBLE_EQ(11.0, cgFromWK.d);
+ EXPECT_DOUBLE_EQ(4.0, cgFromWK.tx);
+ EXPECT_DOUBLE_EQ(3.0, cgFromWK.ty);
+#endif
+
+#if PLATFORM(WIN) || (PLATFORM(GTK) && OS(WINDOWS))
+ XFORM gdiFromWK = test;
+ EXPECT_DOUBLE_EQ(16.0, gdiFromWK.eM11);
+ EXPECT_DOUBLE_EQ(15.0, gdiFromWK.eM12);
+ EXPECT_DOUBLE_EQ(12.0, gdiFromWK.eM21);
+ EXPECT_DOUBLE_EQ(11.0, gdiFromWK.eM22);
+ EXPECT_DOUBLE_EQ(4.0, gdiFromWK.eDx);
+ EXPECT_DOUBLE_EQ(3.0, gdiFromWK.eDy);
+#endif
+
+#if PLATFORM(WIN)
+ D2D1_MATRIX_3X2_F d2dTransform = D2D1::Matrix3x2F(6.0, 5.0, 4.0, 3.0, 2.0, 1.0);
+ WebCore::TransformationMatrix fromD2DTransform(d2dTransform);
+
+ testAffineLikeConstruction(fromD2DTransform);
+
+ D2D1_MATRIX_3X2_F d2dFromWK = test;
+ EXPECT_DOUBLE_EQ(16.0, d2dFromWK._11);
+ EXPECT_DOUBLE_EQ(15.0, d2dFromWK._12);
+ EXPECT_DOUBLE_EQ(12.0, d2dFromWK._21);
+ EXPECT_DOUBLE_EQ(11.0, d2dFromWK._22);
+ EXPECT_DOUBLE_EQ(4.0, d2dFromWK._31);
+ EXPECT_DOUBLE_EQ(3.0, d2dFromWK._32);
+#endif
+}
+
+TEST(TransformationMatrix, MakeMapBetweenRects)
+{
+ WebCore::TransformationMatrix transform;
+
+ WebCore::FloatRect fromRect(10.0f, 10.0f, 100.0f, 100.0f);
+ WebCore::FloatRect toRect(70.0f, 70.0f, 200.0f, 50.0f);
+
+ auto mapBetween = WebCore::TransformationMatrix::rectToRect(fromRect, toRect);
+
+ EXPECT_DOUBLE_EQ(2.0, mapBetween.a());
+ EXPECT_DOUBLE_EQ(0.0, mapBetween.b());
+ EXPECT_DOUBLE_EQ(0.0, mapBetween.c());
+ EXPECT_DOUBLE_EQ(0.5, mapBetween.d());
+ EXPECT_DOUBLE_EQ(60.0, mapBetween.e());
+ EXPECT_DOUBLE_EQ(60.0, mapBetween.f());
+
+ EXPECT_DOUBLE_EQ(2.0, mapBetween.m11());
+ EXPECT_DOUBLE_EQ(0.0, mapBetween.m12());
+ EXPECT_DOUBLE_EQ(0.0, mapBetween.m13());
+ EXPECT_DOUBLE_EQ(0.0, mapBetween.m14());
+ EXPECT_DOUBLE_EQ(0.0, mapBetween.m21());
+ EXPECT_DOUBLE_EQ(0.5, mapBetween.m22());
+ EXPECT_DOUBLE_EQ(0.0, mapBetween.m23());
+ EXPECT_DOUBLE_EQ(0.0, mapBetween.m24());
+ EXPECT_DOUBLE_EQ(0.0, mapBetween.m31());
+ EXPECT_DOUBLE_EQ(0.0, mapBetween.m32());
+ EXPECT_DOUBLE_EQ(1.0, mapBetween.m33());
+ EXPECT_DOUBLE_EQ(0.0, mapBetween.m34());
+ EXPECT_DOUBLE_EQ(60.0, mapBetween.m41());
+ EXPECT_DOUBLE_EQ(60.0, mapBetween.m42());
+ EXPECT_DOUBLE_EQ(0.0, mapBetween.m43());
+ EXPECT_DOUBLE_EQ(1.0, mapBetween.m44());
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/URL.cpp b/Tools/TestWebKitAPI/Tests/WebCore/URL.cpp
index 4a7f53977..30a7e301e 100644
--- a/Tools/TestWebKitAPI/Tests/WebCore/URL.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebCore/URL.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "WTFStringUtilities.h"
#include <WebCore/URL.h>
+#include <WebCore/URLParser.h>
#include <wtf/MainThread.h>
using namespace WebCore;
@@ -57,10 +58,10 @@ TEST_F(URLTest, URLConstructorConstChar)
EXPECT_FALSE(kurl.isNull());
EXPECT_TRUE(kurl.isValid());
- EXPECT_EQ(String("http"), kurl.protocol());
+ EXPECT_EQ(kurl.protocol() == "http", true);
EXPECT_EQ(String("www.example.com"), kurl.host());
- EXPECT_TRUE(kurl.hasPort());
- EXPECT_EQ(8080, kurl.port());
+ EXPECT_TRUE(!!kurl.port());
+ EXPECT_EQ(8080, kurl.port().value());
EXPECT_EQ(String("username"), kurl.user());
EXPECT_EQ(String("password"), kurl.pass());
EXPECT_EQ(String("/index.html"), kurl.path());
@@ -70,6 +71,53 @@ TEST_F(URLTest, URLConstructorConstChar)
EXPECT_EQ(String("fragment"), kurl.fragmentIdentifier());
}
+TEST_F(URLTest, URLProtocolHostAndPort)
+{
+ auto createURL = [](const char* urlAsString) {
+ URLParser parser(urlAsString);
+ return parser.result();
+ };
+
+ auto url = createURL("http://username:password@www.example.com:8080/index.html?var=val#fragment");
+ EXPECT_EQ(String("http://www.example.com:8080"), url.protocolHostAndPort());
+
+ url = createURL("http://username:@www.example.com:8080/index.html?var=val#fragment");
+ EXPECT_EQ(String("http://www.example.com:8080"), url.protocolHostAndPort());
+
+ url = createURL("http://:password@www.example.com:8080/index.html?var=val#fragment");
+ EXPECT_EQ(String("http://www.example.com:8080"), url.protocolHostAndPort());
+
+ url = createURL("http://username@www.example.com:8080/index.html?var=val#fragment");
+ EXPECT_EQ(String("http://www.example.com:8080"), url.protocolHostAndPort());
+
+ url = createURL("http://www.example.com:8080/index.html?var=val#fragment");
+ EXPECT_EQ(String("http://www.example.com:8080"), url.protocolHostAndPort());
+
+ url = createURL("http://www.example.com:/index.html?var=val#fragment");
+ EXPECT_EQ(String("http://www.example.com"), url.protocolHostAndPort());
+
+ url = createURL("http://www.example.com/index.html?var=val#fragment");
+ EXPECT_EQ(String("http://www.example.com"), url.protocolHostAndPort());
+
+ url = createURL("file:///a/b/c");
+ EXPECT_EQ(String("file://"), url.protocolHostAndPort());
+
+ url = createURL("file:///a/b");
+ EXPECT_EQ(String("file://"), url.protocolHostAndPort());
+
+ url = createURL("file:///a");
+ EXPECT_EQ(String("file://"), url.protocolHostAndPort());
+
+ url = createURL("file:///a");
+ EXPECT_EQ(String("file://"), url.protocolHostAndPort());
+
+ url = createURL("asdf://username:password@www.example.com:8080/index.html?var=val#fragment");
+ EXPECT_EQ(String("asdf://www.example.com:8080"), url.protocolHostAndPort());
+
+ url = createURL("asdf:///a/b/c");
+ EXPECT_EQ(String("asdf://"), url.protocolHostAndPort());
+}
+
TEST_F(URLTest, URLDataURIStringSharing)
{
URL baseURL(ParsedURLString, "http://www.webkit.org/");
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp b/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp
new file mode 100644
index 000000000..043e9c21d
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp
@@ -0,0 +1,1305 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+#include "WTFStringUtilities.h"
+#include <WebCore/URLParser.h>
+#include <wtf/MainThread.h>
+#include <wtf/text/StringBuilder.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+class URLParserTest : public testing::Test {
+public:
+ void SetUp() final {
+ WTF::initializeMainThread();
+ }
+};
+
+struct ExpectedParts {
+ String protocol;
+ String user;
+ String password;
+ String host;
+ unsigned short port;
+ String path;
+ String query;
+ String fragment;
+ String string;
+
+ bool isInvalid() const
+ {
+ return protocol.isEmpty()
+ && user.isEmpty()
+ && password.isEmpty()
+ && host.isEmpty()
+ && !port
+ && path.isEmpty()
+ && query.isEmpty()
+ && fragment.isEmpty();
+ }
+};
+
+static bool eq(const String& s1, const String& s2)
+{
+ EXPECT_STREQ(s1.utf8().data(), s2.utf8().data());
+ return s1.utf8() == s2.utf8();
+}
+
+static String insertTabAtLocation(const String& string, size_t location)
+{
+ ASSERT(location <= string.length());
+ return makeString(string.substring(0, location), "\t", string.substring(location));
+}
+
+static ExpectedParts invalidParts(const String& urlStringWithTab)
+{
+ return {"", "", "", "", 0, "" , "", "", urlStringWithTab};
+}
+
+enum class TestTabs { No, Yes };
+
+// Inserting tabs between surrogate pairs changes the encoded value instead of being skipped by the URLParser.
+const TestTabs testTabsValueForSurrogatePairs = TestTabs::No;
+
+static void checkURL(const String& urlString, const ExpectedParts& parts, TestTabs testTabs = TestTabs::Yes)
+{
+ auto url = URL(URL(), urlString);
+
+ EXPECT_TRUE(eq(parts.protocol, url.protocol().toString()));
+ EXPECT_TRUE(eq(parts.user, url.user()));
+ EXPECT_TRUE(eq(parts.password, url.pass()));
+ EXPECT_TRUE(eq(parts.host, url.host()));
+ EXPECT_EQ(parts.port, url.port().value_or(0));
+ EXPECT_TRUE(eq(parts.path, url.path()));
+ EXPECT_TRUE(eq(parts.query, url.query()));
+ EXPECT_TRUE(eq(parts.fragment, url.fragmentIdentifier()));
+ EXPECT_TRUE(eq(parts.string, url.string()));
+
+ EXPECT_TRUE(URLParser::internalValuesConsistent(url));
+
+ if (testTabs == TestTabs::No)
+ return;
+
+ for (size_t i = 0; i < urlString.length(); ++i) {
+ String urlStringWithTab = insertTabAtLocation(urlString, i);
+ checkURL(urlStringWithTab,
+ parts.isInvalid() ? invalidParts(urlStringWithTab) : parts,
+ TestTabs::No);
+ }
+}
+
+static void checkRelativeURL(const String& urlString, const String& baseURLString, const ExpectedParts& parts, TestTabs testTabs = TestTabs::Yes)
+{
+ auto url = URL(URL(URL(), baseURLString), urlString);
+
+ EXPECT_TRUE(eq(parts.protocol, url.protocol().toString()));
+ EXPECT_TRUE(eq(parts.user, url.user()));
+ EXPECT_TRUE(eq(parts.password, url.pass()));
+ EXPECT_TRUE(eq(parts.host, url.host()));
+ EXPECT_EQ(parts.port, url.port().value_or(0));
+ EXPECT_TRUE(eq(parts.path, url.path()));
+ EXPECT_TRUE(eq(parts.query, url.query()));
+ EXPECT_TRUE(eq(parts.fragment, url.fragmentIdentifier()));
+ EXPECT_TRUE(eq(parts.string, url.string()));
+
+ EXPECT_TRUE(URLParser::internalValuesConsistent(url));
+
+ if (testTabs == TestTabs::No)
+ return;
+
+ for (size_t i = 0; i < urlString.length(); ++i) {
+ String urlStringWithTab = insertTabAtLocation(urlString, i);
+ checkRelativeURL(urlStringWithTab,
+ baseURLString,
+ parts.isInvalid() ? invalidParts(urlStringWithTab) : parts,
+ TestTabs::No);
+ }
+}
+
+static void checkURLDifferences(const String& urlString, const ExpectedParts& partsNew, const ExpectedParts& partsOld, TestTabs testTabs = TestTabs::Yes)
+{
+ UNUSED_PARAM(partsOld); // FIXME: Remove all the old expected parts.
+ auto url = URL(URL(), urlString);
+
+ EXPECT_TRUE(eq(partsNew.protocol, url.protocol().toString()));
+ EXPECT_TRUE(eq(partsNew.user, url.user()));
+ EXPECT_TRUE(eq(partsNew.password, url.pass()));
+ EXPECT_TRUE(eq(partsNew.host, url.host()));
+ EXPECT_EQ(partsNew.port, url.port().value_or(0));
+ EXPECT_TRUE(eq(partsNew.path, url.path()));
+ EXPECT_TRUE(eq(partsNew.query, url.query()));
+ EXPECT_TRUE(eq(partsNew.fragment, url.fragmentIdentifier()));
+ EXPECT_TRUE(eq(partsNew.string, url.string()));
+
+ EXPECT_TRUE(URLParser::internalValuesConsistent(url));
+
+ if (testTabs == TestTabs::No)
+ return;
+
+ for (size_t i = 0; i < urlString.length(); ++i) {
+ String urlStringWithTab = insertTabAtLocation(urlString, i);
+ checkURLDifferences(urlStringWithTab,
+ partsNew.isInvalid() ? invalidParts(urlStringWithTab) : partsNew,
+ partsOld.isInvalid() ? invalidParts(urlStringWithTab) : partsOld,
+ TestTabs::No);
+ }
+}
+
+static void checkRelativeURLDifferences(const String& urlString, const String& baseURLString, const ExpectedParts& partsNew, const ExpectedParts& partsOld, TestTabs testTabs = TestTabs::Yes)
+{
+ UNUSED_PARAM(partsOld); // FIXME: Remove all the old expected parts.
+ auto url = URL(URL(URL(), baseURLString), urlString);
+
+ EXPECT_TRUE(eq(partsNew.protocol, url.protocol().toString()));
+ EXPECT_TRUE(eq(partsNew.user, url.user()));
+ EXPECT_TRUE(eq(partsNew.password, url.pass()));
+ EXPECT_TRUE(eq(partsNew.host, url.host()));
+ EXPECT_EQ(partsNew.port, url.port().value_or(0));
+ EXPECT_TRUE(eq(partsNew.path, url.path()));
+ EXPECT_TRUE(eq(partsNew.query, url.query()));
+ EXPECT_TRUE(eq(partsNew.fragment, url.fragmentIdentifier()));
+ EXPECT_TRUE(eq(partsNew.string, url.string()));
+
+ EXPECT_TRUE(URLParser::internalValuesConsistent(url));
+
+ if (testTabs == TestTabs::No)
+ return;
+
+ for (size_t i = 0; i < urlString.length(); ++i) {
+ String urlStringWithTab = insertTabAtLocation(urlString, i);
+ checkRelativeURLDifferences(urlStringWithTab, baseURLString,
+ partsNew.isInvalid() ? invalidParts(urlStringWithTab) : partsNew,
+ partsOld.isInvalid() ? invalidParts(urlStringWithTab) : partsOld,
+ TestTabs::No);
+ }
+}
+
+static void shouldFail(const String& urlString)
+{
+ checkURL(urlString, {"", "", "", "", 0, "", "", "", urlString});
+}
+
+static void shouldFail(const String& urlString, const String& baseString)
+{
+ checkRelativeURL(urlString, baseString, {"", "", "", "", 0, "", "", "", urlString});
+}
+
+static void checkURL(const String& urlString, const TextEncoding& encoding, const ExpectedParts& parts, TestTabs testTabs = TestTabs::Yes)
+{
+ URLParser parser(urlString, { }, encoding);
+ auto url = parser.result();
+ EXPECT_TRUE(eq(parts.protocol, url.protocol().toString()));
+ EXPECT_TRUE(eq(parts.user, url.user()));
+ EXPECT_TRUE(eq(parts.password, url.pass()));
+ EXPECT_TRUE(eq(parts.host, url.host()));
+ EXPECT_EQ(parts.port, url.port().value_or(0));
+ EXPECT_TRUE(eq(parts.path, url.path()));
+ EXPECT_TRUE(eq(parts.query, url.query()));
+ EXPECT_TRUE(eq(parts.fragment, url.fragmentIdentifier()));
+ EXPECT_TRUE(eq(parts.string, url.string()));
+
+ if (testTabs == TestTabs::No)
+ return;
+
+ for (size_t i = 0; i < urlString.length(); ++i) {
+ String urlStringWithTab = insertTabAtLocation(urlString, i);
+ checkURL(urlStringWithTab, encoding,
+ parts.isInvalid() ? invalidParts(urlStringWithTab) : parts,
+ TestTabs::No);
+ }
+}
+
+static void checkURL(const String& urlString, const String& baseURLString, const TextEncoding& encoding, const ExpectedParts& parts, TestTabs testTabs = TestTabs::Yes)
+{
+ URLParser baseParser(baseURLString, { }, encoding);
+ URLParser parser(urlString, baseParser.result(), encoding);
+ auto url = parser.result();
+ EXPECT_TRUE(eq(parts.protocol, url.protocol().toString()));
+ EXPECT_TRUE(eq(parts.user, url.user()));
+ EXPECT_TRUE(eq(parts.password, url.pass()));
+ EXPECT_TRUE(eq(parts.host, url.host()));
+ EXPECT_EQ(parts.port, url.port().value_or(0));
+ EXPECT_TRUE(eq(parts.path, url.path()));
+ EXPECT_TRUE(eq(parts.query, url.query()));
+ EXPECT_TRUE(eq(parts.fragment, url.fragmentIdentifier()));
+ EXPECT_TRUE(eq(parts.string, url.string()));
+
+ if (testTabs == TestTabs::No)
+ return;
+
+ for (size_t i = 0; i < urlString.length(); ++i) {
+ String urlStringWithTab = insertTabAtLocation(urlString, i);
+ checkURL(urlStringWithTab, baseURLString, encoding,
+ parts.isInvalid() ? invalidParts(urlStringWithTab) : parts,
+ TestTabs::No);
+ }
+}
+
+TEST_F(URLParserTest, Basic)
+{
+ checkURL("http://user:pass@webkit.org:123/path?query#fragment", {"http", "user", "pass", "webkit.org", 123, "/path", "query", "fragment", "http://user:pass@webkit.org:123/path?query#fragment"});
+ checkURL("http://user:pass@webkit.org:123/path?query", {"http", "user", "pass", "webkit.org", 123, "/path", "query", "", "http://user:pass@webkit.org:123/path?query"});
+ checkURL("http://user:pass@webkit.org:123/path", {"http", "user", "pass", "webkit.org", 123, "/path", "", "", "http://user:pass@webkit.org:123/path"});
+ checkURL("http://user:pass@webkit.org:123/", {"http", "user", "pass", "webkit.org", 123, "/", "", "", "http://user:pass@webkit.org:123/"});
+ checkURL("http://user:pass@webkit.org:123", {"http", "user", "pass", "webkit.org", 123, "/", "", "", "http://user:pass@webkit.org:123/"});
+ checkURL("http://user:pass@webkit.org", {"http", "user", "pass", "webkit.org", 0, "/", "", "", "http://user:pass@webkit.org/"});
+ checkURL("http://user:\t\t\tpass@webkit.org", {"http", "user", "pass", "webkit.org", 0, "/", "", "", "http://user:pass@webkit.org/"});
+ checkURL("http://us\ter:pass@webkit.org", {"http", "user", "pass", "webkit.org", 0, "/", "", "", "http://user:pass@webkit.org/"});
+ checkURL("http://user:pa\tss@webkit.org", {"http", "user", "pass", "webkit.org", 0, "/", "", "", "http://user:pass@webkit.org/"});
+ checkURL("http://user:pass\t@webkit.org", {"http", "user", "pass", "webkit.org", 0, "/", "", "", "http://user:pass@webkit.org/"});
+ checkURL("http://\tuser:pass@webkit.org", {"http", "user", "pass", "webkit.org", 0, "/", "", "", "http://user:pass@webkit.org/"});
+ checkURL("http://user\t:pass@webkit.org", {"http", "user", "pass", "webkit.org", 0, "/", "", "", "http://user:pass@webkit.org/"});
+ checkURL("http://webkit.org", {"http", "", "", "webkit.org", 0, "/", "", "", "http://webkit.org/"});
+ checkURL("http://127.0.0.1", {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"});
+ checkURL("http://webkit.org/", {"http", "", "", "webkit.org", 0, "/", "", "", "http://webkit.org/"});
+ checkURL("http://webkit.org/path1/path2/index.html", {"http", "", "", "webkit.org", 0, "/path1/path2/index.html", "", "", "http://webkit.org/path1/path2/index.html"});
+ checkURL("about:blank", {"about", "", "", "", 0, "blank", "", "", "about:blank"});
+ checkURL("about:blank?query", {"about", "", "", "", 0, "blank", "query", "", "about:blank?query"});
+ checkURL("about:blank#fragment", {"about", "", "", "", 0, "blank", "", "fragment", "about:blank#fragment"});
+ checkURL("http://[0:f::f:f:0:0]", {"http", "", "", "[0:f::f:f:0:0]", 0, "/", "", "", "http://[0:f::f:f:0:0]/"});
+ checkURL("http://[0:f:0:0:f::]", {"http", "", "", "[0:f:0:0:f::]", 0, "/", "", "", "http://[0:f:0:0:f::]/"});
+ checkURL("http://[::f:0:0:f:0:0]", {"http", "", "", "[::f:0:0:f:0:0]", 0, "/", "", "", "http://[::f:0:0:f:0:0]/"});
+ checkURL("http://[0:f:0:0:f::]:", {"http", "", "", "[0:f:0:0:f::]", 0, "/", "", "", "http://[0:f:0:0:f::]/"});
+ checkURL("http://[0:f:0:0:f::]:\t", {"http", "", "", "[0:f:0:0:f::]", 0, "/", "", "", "http://[0:f:0:0:f::]/"});
+ checkURL("http://[0:f:0:0:f::]\t:", {"http", "", "", "[0:f:0:0:f::]", 0, "/", "", "", "http://[0:f:0:0:f::]/"});
+ checkURL("http://\t[::f:0:0:f:0:0]", {"http", "", "", "[::f:0:0:f:0:0]", 0, "/", "", "", "http://[::f:0:0:f:0:0]/"});
+ checkURL("http://[\t::f:0:0:f:0:0]", {"http", "", "", "[::f:0:0:f:0:0]", 0, "/", "", "", "http://[::f:0:0:f:0:0]/"});
+ checkURL("http://[:\t:f:0:0:f:0:0]", {"http", "", "", "[::f:0:0:f:0:0]", 0, "/", "", "", "http://[::f:0:0:f:0:0]/"});
+ checkURL("http://[::\tf:0:0:f:0:0]", {"http", "", "", "[::f:0:0:f:0:0]", 0, "/", "", "", "http://[::f:0:0:f:0:0]/"});
+ checkURL("http://[::f\t:0:0:f:0:0]", {"http", "", "", "[::f:0:0:f:0:0]", 0, "/", "", "", "http://[::f:0:0:f:0:0]/"});
+ checkURL("http://[::f:\t0:0:f:0:0]", {"http", "", "", "[::f:0:0:f:0:0]", 0, "/", "", "", "http://[::f:0:0:f:0:0]/"});
+ checkURL("http://example.com/path1/path2/.", {"http", "", "", "example.com", 0, "/path1/path2/", "", "", "http://example.com/path1/path2/"});
+ checkURL("http://example.com/path1/path2/..", {"http", "", "", "example.com", 0, "/path1/", "", "", "http://example.com/path1/"});
+ checkURL("http://example.com/path1/path2/./path3", {"http", "", "", "example.com", 0, "/path1/path2/path3", "", "", "http://example.com/path1/path2/path3"});
+ checkURL("http://example.com/path1/path2/.\\path3", {"http", "", "", "example.com", 0, "/path1/path2/path3", "", "", "http://example.com/path1/path2/path3"});
+ checkURL("http://example.com/path1/path2/../path3", {"http", "", "", "example.com", 0, "/path1/path3", "", "", "http://example.com/path1/path3"});
+ checkURL("http://example.com/path1/path2/..\\path3", {"http", "", "", "example.com", 0, "/path1/path3", "", "", "http://example.com/path1/path3"});
+ checkURL("http://example.com/.", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
+ checkURL("http://example.com/..", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
+ checkURL("http://example.com/./path1", {"http", "", "", "example.com", 0, "/path1", "", "", "http://example.com/path1"});
+ checkURL("http://example.com/../path1", {"http", "", "", "example.com", 0, "/path1", "", "", "http://example.com/path1"});
+ checkURL("http://example.com/../path1/../../path2/path3/../path4", {"http", "", "", "example.com", 0, "/path2/path4", "", "", "http://example.com/path2/path4"});
+ checkURL("http://example.com/path1/.%2", {"http", "", "", "example.com", 0, "/path1/.%2", "", "", "http://example.com/path1/.%2"});
+ checkURL("http://example.com/path1/%2", {"http", "", "", "example.com", 0, "/path1/%2", "", "", "http://example.com/path1/%2"});
+ checkURL("http://example.com/path1/%", {"http", "", "", "example.com", 0, "/path1/%", "", "", "http://example.com/path1/%"});
+ checkURL("http://example.com/path1/.%", {"http", "", "", "example.com", 0, "/path1/.%", "", "", "http://example.com/path1/.%"});
+ checkURL("http://example.com//.", {"http", "", "", "example.com", 0, "//", "", "", "http://example.com//"});
+ checkURL("http://example.com//./", {"http", "", "", "example.com", 0, "//", "", "", "http://example.com//"});
+ checkURL("http://example.com//.//", {"http", "", "", "example.com", 0, "///", "", "", "http://example.com///"});
+ checkURL("http://example.com//..", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
+ checkURL("http://example.com//../", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
+ checkURL("http://example.com//..//", {"http", "", "", "example.com", 0, "//", "", "", "http://example.com//"});
+ checkURL("http://example.com//..", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
+ checkURL("http://example.com/.//", {"http", "", "", "example.com", 0, "//", "", "", "http://example.com//"});
+ checkURL("http://example.com/..//", {"http", "", "", "example.com", 0, "//", "", "", "http://example.com//"});
+ checkURL("http://example.com/./", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
+ checkURL("http://example.com/../", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
+ checkURL("http://example.com/path1/.../path3", {"http", "", "", "example.com", 0, "/path1/.../path3", "", "", "http://example.com/path1/.../path3"});
+ checkURL("http://example.com/path1/...", {"http", "", "", "example.com", 0, "/path1/...", "", "", "http://example.com/path1/..."});
+ checkURL("http://example.com/path1/.../", {"http", "", "", "example.com", 0, "/path1/.../", "", "", "http://example.com/path1/.../"});
+ checkURL("http://example.com/.path1/", {"http", "", "", "example.com", 0, "/.path1/", "", "", "http://example.com/.path1/"});
+ checkURL("http://example.com/..path1/", {"http", "", "", "example.com", 0, "/..path1/", "", "", "http://example.com/..path1/"});
+ checkURL("http://example.com/path1/.path2", {"http", "", "", "example.com", 0, "/path1/.path2", "", "", "http://example.com/path1/.path2"});
+ checkURL("http://example.com/path1/..path2", {"http", "", "", "example.com", 0, "/path1/..path2", "", "", "http://example.com/path1/..path2"});
+ checkURL("http://example.com/path1/path2/.?query", {"http", "", "", "example.com", 0, "/path1/path2/", "query", "", "http://example.com/path1/path2/?query"});
+ checkURL("http://example.com/path1/path2/..?query", {"http", "", "", "example.com", 0, "/path1/", "query", "", "http://example.com/path1/?query"});
+ checkURL("http://example.com/path1/path2/.#fragment", {"http", "", "", "example.com", 0, "/path1/path2/", "", "fragment", "http://example.com/path1/path2/#fragment"});
+ checkURL("http://example.com/path1/path2/..#fragment", {"http", "", "", "example.com", 0, "/path1/", "", "fragment", "http://example.com/path1/#fragment"});
+
+ checkURL("file:", {"file", "", "", "", 0, "/", "", "", "file:///"});
+ checkURL("file:/", {"file", "", "", "", 0, "/", "", "", "file:///"});
+ checkURL("file://", {"file", "", "", "", 0, "/", "", "", "file:///"});
+ checkURL("file:///", {"file", "", "", "", 0, "/", "", "", "file:///"});
+ checkURL("file:////", {"file", "", "", "", 0, "//", "", "", "file:////"}); // This matches Firefox and URL::parse which I believe are correct, but not Chrome.
+ checkURL("file:/path", {"file", "", "", "", 0, "/path", "", "", "file:///path"});
+ checkURL("file://host/path", {"file", "", "", "host", 0, "/path", "", "", "file://host/path"});
+ checkURL("file://host", {"file", "", "", "host", 0, "/", "", "", "file://host/"});
+ checkURL("file://host/", {"file", "", "", "host", 0, "/", "", "", "file://host/"});
+ checkURL("file:///path", {"file", "", "", "", 0, "/path", "", "", "file:///path"});
+ checkURL("file:////path", {"file", "", "", "", 0, "//path", "", "", "file:////path"});
+ checkURL("file://localhost/path", {"file", "", "", "", 0, "/path", "", "", "file:///path"});
+ checkURL("file://localhost/", {"file", "", "", "", 0, "/", "", "", "file:///"});
+ checkURL("file://localhost", {"file", "", "", "", 0, "/", "", "", "file:///"});
+ checkURL("file://lOcAlHoSt", {"file", "", "", "", 0, "/", "", "", "file:///"});
+ checkURL("file://lOcAlHoSt/", {"file", "", "", "", 0, "/", "", "", "file:///"});
+ checkURL("file:/pAtH/", {"file", "", "", "", 0, "/pAtH/", "", "", "file:///pAtH/"});
+ checkURL("file:/pAtH", {"file", "", "", "", 0, "/pAtH", "", "", "file:///pAtH"});
+ checkURL("file:?query", {"file", "", "", "", 0, "/", "query", "", "file:///?query"});
+ checkURL("file:#fragment", {"file", "", "", "", 0, "/", "", "fragment", "file:///#fragment"});
+ checkURL("file:?query#fragment", {"file", "", "", "", 0, "/", "query", "fragment", "file:///?query#fragment"});
+ checkURL("file:#fragment?notquery", {"file", "", "", "", 0, "/", "", "fragment?notquery", "file:///#fragment?notquery"});
+ checkURL("file:/?query", {"file", "", "", "", 0, "/", "query", "", "file:///?query"});
+ checkURL("file:/#fragment", {"file", "", "", "", 0, "/", "", "fragment", "file:///#fragment"});
+ checkURL("file://?query", {"file", "", "", "", 0, "/", "query", "", "file:///?query"});
+ checkURL("file://#fragment", {"file", "", "", "", 0, "/", "", "fragment", "file:///#fragment"});
+ checkURL("file:///?query", {"file", "", "", "", 0, "/", "query", "", "file:///?query"});
+ checkURL("file:///#fragment", {"file", "", "", "", 0, "/", "", "fragment", "file:///#fragment"});
+ checkURL("file:////?query", {"file", "", "", "", 0, "//", "query", "", "file:////?query"});
+ checkURL("file:////#fragment", {"file", "", "", "", 0, "//", "", "fragment", "file:////#fragment"});
+ checkURL("http://host/A b", {"http", "", "", "host", 0, "/A%20b", "", "", "http://host/A%20b"});
+ checkURL("http://host/a%20B", {"http", "", "", "host", 0, "/a%20B", "", "", "http://host/a%20B"});
+ checkURL("http://host?q=@ <>!#fragment", {"http", "", "", "host", 0, "/", "q=@%20%3C%3E!", "fragment", "http://host/?q=@%20%3C%3E!#fragment"});
+ checkURL("http://user:@host", {"http", "user", "", "host", 0, "/", "", "", "http://user@host/"});
+ checkURL("http://user:@\thost", {"http", "user", "", "host", 0, "/", "", "", "http://user@host/"});
+ checkURL("http://user:\t@host", {"http", "user", "", "host", 0, "/", "", "", "http://user@host/"});
+ checkURL("http://user\t:@host", {"http", "user", "", "host", 0, "/", "", "", "http://user@host/"});
+ checkURL("http://use\tr:@host", {"http", "user", "", "host", 0, "/", "", "", "http://user@host/"});
+ checkURL("http://127.0.0.1:10100/path", {"http", "", "", "127.0.0.1", 10100, "/path", "", "", "http://127.0.0.1:10100/path"});
+ checkURL("http://127.0.0.1:/path", {"http", "", "", "127.0.0.1", 0, "/path", "", "", "http://127.0.0.1/path"});
+ checkURL("http://127.0.0.1\t:/path", {"http", "", "", "127.0.0.1", 0, "/path", "", "", "http://127.0.0.1/path"});
+ checkURL("http://127.0.0.1:\t/path", {"http", "", "", "127.0.0.1", 0, "/path", "", "", "http://127.0.0.1/path"});
+ checkURL("http://127.0.0.1:/\tpath", {"http", "", "", "127.0.0.1", 0, "/path", "", "", "http://127.0.0.1/path"});
+ checkURL("http://127.0.0.1:123", {"http", "", "", "127.0.0.1", 123, "/", "", "", "http://127.0.0.1:123/"});
+ checkURL("http://127.0.0.1:", {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"});
+ checkURL("http://[0:f::f:f:0:0]:123/path", {"http", "", "", "[0:f::f:f:0:0]", 123, "/path", "", "", "http://[0:f::f:f:0:0]:123/path"});
+ checkURL("http://[0:f::f:f:0:0]:123", {"http", "", "", "[0:f::f:f:0:0]", 123, "/", "", "", "http://[0:f::f:f:0:0]:123/"});
+ checkURL("http://[0:f:0:0:f:\t:]:123", {"http", "", "", "[0:f:0:0:f::]", 123, "/", "", "", "http://[0:f:0:0:f::]:123/"});
+ checkURL("http://[0:f:0:0:f::\t]:123", {"http", "", "", "[0:f:0:0:f::]", 123, "/", "", "", "http://[0:f:0:0:f::]:123/"});
+ checkURL("http://[0:f:0:0:f::]\t:123", {"http", "", "", "[0:f:0:0:f::]", 123, "/", "", "", "http://[0:f:0:0:f::]:123/"});
+ checkURL("http://[0:f:0:0:f::]:\t123", {"http", "", "", "[0:f:0:0:f::]", 123, "/", "", "", "http://[0:f:0:0:f::]:123/"});
+ checkURL("http://[0:f:0:0:f::]:1\t23", {"http", "", "", "[0:f:0:0:f::]", 123, "/", "", "", "http://[0:f:0:0:f::]:123/"});
+ checkURL("http://[0:f::f:f:0:0]:/path", {"http", "", "", "[0:f::f:f:0:0]", 0, "/path", "", "", "http://[0:f::f:f:0:0]/path"});
+ checkURL("http://[0:f::f:f:0:0]:", {"http", "", "", "[0:f::f:f:0:0]", 0, "/", "", "", "http://[0:f::f:f:0:0]/"});
+ checkURL("http://host:10100/path", {"http", "", "", "host", 10100, "/path", "", "", "http://host:10100/path"});
+ checkURL("http://host:/path", {"http", "", "", "host", 0, "/path", "", "", "http://host/path"});
+ checkURL("http://host:123", {"http", "", "", "host", 123, "/", "", "", "http://host:123/"});
+ checkURL("http://host:", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
+ checkURL("http://hos\tt\n:\t1\n2\t3\t/\npath", {"http", "", "", "host", 123, "/path", "", "", "http://host:123/path"});
+ checkURL("http://user@example.org/path3", {"http", "user", "", "example.org", 0, "/path3", "", "", "http://user@example.org/path3"});
+ checkURL("sc:/pa/pa", {"sc", "", "", "", 0, "/pa/pa", "", "", "sc:/pa/pa"});
+ checkURL("sc:/pa", {"sc", "", "", "", 0, "/pa", "", "", "sc:/pa"});
+ checkURL("sc:/pa/", {"sc", "", "", "", 0, "/pa/", "", "", "sc:/pa/"});
+ checkURL("notspecial:/notuser:notpassword@nothost", {"notspecial", "", "", "", 0, "/notuser:notpassword@nothost", "", "", "notspecial:/notuser:notpassword@nothost"});
+ checkURL("sc://pa/", {"sc", "", "", "pa", 0, "/", "", "", "sc://pa/"});
+ checkURL("sc://\tpa/", {"sc", "", "", "pa", 0, "/", "", "", "sc://pa/"});
+ checkURL("sc:/\t/pa/", {"sc", "", "", "pa", 0, "/", "", "", "sc://pa/"});
+ checkURL("sc:\t//pa/", {"sc", "", "", "pa", 0, "/", "", "", "sc://pa/"});
+ checkURL("http://host \a ", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
+ checkURL("notspecial:/a", {"notspecial", "", "", "", 0, "/a", "", "", "notspecial:/a"});
+ checkURL("notspecial:", {"notspecial", "", "", "", 0, "", "", "", "notspecial:"});
+ checkURL("http:/a", {"http", "", "", "a", 0, "/", "", "", "http://a/"});
+ checkURL("http://256../", {"http", "", "", "256..", 0, "/", "", "", "http://256../"});
+ checkURL("http://256..", {"http", "", "", "256..", 0, "/", "", "", "http://256../"});
+ checkURL("http://127..1/", {"http", "", "", "127..1", 0, "/", "", "", "http://127..1/"});
+ checkURL("http://127.a.0.1/", {"http", "", "", "127.a.0.1", 0, "/", "", "", "http://127.a.0.1/"});
+ checkURL("http://127.0.0.1/", {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"});
+ checkURL("http://12\t7.0.0.1/", {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"});
+ checkURL("http://127.\t0.0.1/", {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"});
+ checkURL("http://./", {"http", "", "", ".", 0, "/", "", "", "http://./"});
+ checkURL("http://.", {"http", "", "", ".", 0, "/", "", "", "http://./"});
+ checkURL("notspecial:/a", {"notspecial", "", "", "", 0, "/a", "", "", "notspecial:/a"});
+ checkURL("notspecial:", {"notspecial", "", "", "", 0, "", "", "", "notspecial:"});
+ checkURL("notspecial:/", {"notspecial", "", "", "", 0, "/", "", "", "notspecial:/"});
+ checkURL("data:image/png;base64,encoded-data-follows-here", {"data", "", "", "", 0, "image/png;base64,encoded-data-follows-here", "", "", "data:image/png;base64,encoded-data-follows-here"});
+ checkURL("data:image/png;base64,encoded/data-with-slash", {"data", "", "", "", 0, "image/png;base64,encoded/data-with-slash", "", "", "data:image/png;base64,encoded/data-with-slash"});
+ checkURL("about:~", {"about", "", "", "", 0, "~", "", "", "about:~"});
+ checkURL("https://@test@test@example:800\\path@end", {"", "", "", "", 0, "", "", "", "https://@test@test@example:800\\path@end"});
+ checkURL("http://www.example.com/#a\nb\rc\td", {"http", "", "", "www.example.com", 0, "/", "", "abcd", "http://www.example.com/#abcd"});
+ checkURL("http://[A:b:c:DE:fF:0:1:aC]/", {"http", "", "", "[a:b:c:de:ff:0:1:ac]", 0, "/", "", "", "http://[a:b:c:de:ff:0:1:ac]/"});
+ checkURL("http:////////user:@webkit.org:99?foo", {"http", "user", "", "webkit.org", 99, "/", "foo", "", "http://user@webkit.org:99/?foo"});
+ checkURL("http:////////user:@webkit.org:99#foo", {"http", "user", "", "webkit.org", 99, "/", "", "foo", "http://user@webkit.org:99/#foo"});
+ checkURL("http:////\t////user:@webkit.org:99?foo", {"http", "user", "", "webkit.org", 99, "/", "foo", "", "http://user@webkit.org:99/?foo"});
+ checkURL("http://\t//\\///user:@webkit.org:99?foo", {"http", "user", "", "webkit.org", 99, "/", "foo", "", "http://user@webkit.org:99/?foo"});
+ checkURL("http:/\\user:@webkit.org:99?foo", {"http", "user", "", "webkit.org", 99, "/", "foo", "", "http://user@webkit.org:99/?foo"});
+ checkURL("http://127.0.0.1", {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"});
+ checkURLDifferences("http://127.0.0.1.",
+ {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"},
+ {"http", "", "", "127.0.0.1.", 0, "/", "", "", "http://127.0.0.1./"});
+ checkURLDifferences("http://127.0.0.1./",
+ {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"},
+ {"http", "", "", "127.0.0.1.", 0, "/", "", "", "http://127.0.0.1./"});
+ checkURL("http://127.0.0.1../", {"http", "", "", "127.0.0.1..", 0, "/", "", "", "http://127.0.0.1../"});
+ checkURLDifferences("http://0x100.0/",
+ {"", "", "", "", 0, "", "", "", "http://0x100.0/"},
+ {"http", "", "", "0x100.0", 0, "/", "", "", "http://0x100.0/"});
+ checkURLDifferences("http://0.0.0x100.0/",
+ {"", "", "", "", 0, "", "", "", "http://0.0.0x100.0/"},
+ {"http", "", "", "0.0.0x100.0", 0, "/", "", "", "http://0.0.0x100.0/"});
+ checkURLDifferences("http://0.0.0.0x100/",
+ {"", "", "", "", 0, "", "", "", "http://0.0.0.0x100/"},
+ {"http", "", "", "0.0.0.0x100", 0, "/", "", "", "http://0.0.0.0x100/"});
+ checkURL("http://host:123?", {"http", "", "", "host", 123, "/", "", "", "http://host:123/?"});
+ checkURL("http://host:123?query", {"http", "", "", "host", 123, "/", "query", "", "http://host:123/?query"});
+ checkURL("http://host:123#", {"http", "", "", "host", 123, "/", "", "", "http://host:123/#"});
+ checkURL("http://host:123#fragment", {"http", "", "", "host", 123, "/", "", "fragment", "http://host:123/#fragment"});
+ checkURLDifferences("foo:////",
+ {"foo", "", "", "", 0, "//", "", "", "foo:////"},
+ {"foo", "", "", "", 0, "////", "", "", "foo:////"});
+ checkURLDifferences("foo:///?",
+ {"foo", "", "", "", 0, "/", "", "", "foo:///?"},
+ {"foo", "", "", "", 0, "///", "", "", "foo:///?"});
+ checkURLDifferences("foo:///#",
+ {"foo", "", "", "", 0, "/", "", "", "foo:///#"},
+ {"foo", "", "", "", 0, "///", "", "", "foo:///#"});
+ checkURLDifferences("foo:///",
+ {"foo", "", "", "", 0, "/", "", "", "foo:///"},
+ {"foo", "", "", "", 0, "///", "", "", "foo:///"});
+ checkURLDifferences("foo://?",
+ {"foo", "", "", "", 0, "", "", "", "foo://?"},
+ {"foo", "", "", "", 0, "//", "", "", "foo://?"});
+ checkURLDifferences("foo://#",
+ {"foo", "", "", "", 0, "", "", "", "foo://#"},
+ {"foo", "", "", "", 0, "//", "", "", "foo://#"});
+ checkURLDifferences("foo://",
+ {"foo", "", "", "", 0, "", "", "", "foo://"},
+ {"foo", "", "", "", 0, "//", "", "", "foo://"});
+ checkURL("foo:/?", {"foo", "", "", "", 0, "/", "", "", "foo:/?"});
+ checkURL("foo:/#", {"foo", "", "", "", 0, "/", "", "", "foo:/#"});
+ checkURL("foo:/", {"foo", "", "", "", 0, "/", "", "", "foo:/"});
+ checkURL("foo:?", {"foo", "", "", "", 0, "", "", "", "foo:?"});
+ checkURL("foo:#", {"foo", "", "", "", 0, "", "", "", "foo:#"});
+ checkURLDifferences("A://",
+ {"a", "", "", "", 0, "", "", "", "a://"},
+ {"a", "", "", "", 0, "//", "", "", "a://"});
+ checkURLDifferences("aA://",
+ {"aa", "", "", "", 0, "", "", "", "aa://"},
+ {"aa", "", "", "", 0, "//", "", "", "aa://"});
+ checkURL(utf16String(u"foo://host/#ПП\u0007 a</"), {"foo", "", "", "host", 0, "/", "", "%D0%9F%D0%9F%07 a</", "foo://host/#%D0%9F%D0%9F%07 a</"});
+ checkURL(utf16String(u"foo://host/#\u0007 a</"), {"foo", "", "", "host", 0, "/", "", "%07 a</", "foo://host/#%07 a</"});
+ checkURL(utf16String(u"http://host?ß😍#ß😍"), {"http", "", "", "host", 0, "/", "%C3%9F%F0%9F%98%8D", "%C3%9F%F0%9F%98%8D", "http://host/?%C3%9F%F0%9F%98%8D#%C3%9F%F0%9F%98%8D"}, testTabsValueForSurrogatePairs);
+ checkURL(utf16String(u"http://host/path#💩\t💩"), {"http", "", "", "host", 0, "/path", "", "%F0%9F%92%A9%F0%9F%92%A9", "http://host/path#%F0%9F%92%A9%F0%9F%92%A9"}, testTabsValueForSurrogatePairs);
+ checkURL(utf16String(u"http://host/#ПП\u0007 a</"), {"http", "", "", "host", 0, "/", "", "%D0%9F%D0%9F%07 a</", "http://host/#%D0%9F%D0%9F%07 a</"});
+ checkURL(utf16String(u"http://host/#\u0007 a</"), {"http", "", "", "host", 0, "/", "", "%07 a</", "http://host/#%07 a</"});
+
+ // This disagrees with the web platform test for http://:@www.example.com but agrees with Chrome and URL::parse,
+ // and Firefox fails the web platform test differently. Maybe the web platform test ought to be changed.
+ checkURL("http://:@host", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
+}
+
+TEST_F(URLParserTest, ParseRelative)
+{
+ checkRelativeURL("/index.html", "http://webkit.org/path1/path2/", {"http", "", "", "webkit.org", 0, "/index.html", "", "", "http://webkit.org/index.html"});
+ checkRelativeURL("http://whatwg.org/index.html", "http://webkit.org/path1/path2/", {"http", "", "", "whatwg.org", 0, "/index.html", "", "", "http://whatwg.org/index.html"});
+ checkRelativeURL("index.html", "http://webkit.org/path1/path2/page.html?query#fragment", {"http", "", "", "webkit.org", 0, "/path1/path2/index.html", "", "", "http://webkit.org/path1/path2/index.html"});
+ checkRelativeURL("//whatwg.org/index.html", "https://www.webkit.org/path", {"https", "", "", "whatwg.org", 0, "/index.html", "", "", "https://whatwg.org/index.html"});
+ checkRelativeURL("http://example\t.\norg", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/", "", "", "http://example.org/"});
+ checkRelativeURL("test", "file:///path1/path2", {"file", "", "", "", 0, "/path1/test", "", "", "file:///path1/test"});
+ checkRelativeURL(utf16String(u"http://www.foo。bar.com"), "http://other.com/", {"http", "", "", "www.foo.bar.com", 0, "/", "", "", "http://www.foo.bar.com/"});
+ checkRelativeURLDifferences(utf16String(u"sc://ñ.test/"), "about:blank",
+ {"sc", "", "", "%C3%B1.test", 0, "/", "", "", "sc://%C3%B1.test/"},
+ {"sc", "", "", "xn--ida.test", 0, "/", "", "", "sc://xn--ida.test/"});
+ checkRelativeURL("#fragment", "http://host/path", {"http", "", "", "host", 0, "/path", "", "fragment", "http://host/path#fragment"});
+ checkRelativeURL("#fragment", "file:///path", {"file", "", "", "", 0, "/path", "", "fragment", "file:///path#fragment"});
+ checkRelativeURL("#fragment", "file:///path#old", {"file", "", "", "", 0, "/path", "", "fragment", "file:///path#fragment"});
+ checkRelativeURL("#", "file:///path#old", {"file", "", "", "", 0, "/path", "", "", "file:///path#"});
+ checkRelativeURL(" ", "file:///path#old", {"file", "", "", "", 0, "/path", "", "", "file:///path"});
+ checkRelativeURL("#", "file:///path", {"file", "", "", "", 0, "/path", "", "", "file:///path#"});
+ checkRelativeURL("#", "file:///path?query", {"file", "", "", "", 0, "/path", "query", "", "file:///path?query#"});
+ checkRelativeURL("#", "file:///path?query#old", {"file", "", "", "", 0, "/path", "query", "", "file:///path?query#"});
+ checkRelativeURL("?query", "http://host/path", {"http", "", "", "host", 0, "/path", "query", "", "http://host/path?query"});
+ checkRelativeURL("?query#fragment", "http://host/path", {"http", "", "", "host", 0, "/path", "query", "fragment", "http://host/path?query#fragment"});
+ checkRelativeURL("?new", "file:///path?old#fragment", {"file", "", "", "", 0, "/path", "new", "", "file:///path?new"});
+ checkRelativeURL("?", "file:///path?old#fragment", {"file", "", "", "", 0, "/path", "", "", "file:///path?"});
+ checkRelativeURL("?", "file:///path", {"file", "", "", "", 0, "/path", "", "", "file:///path?"});
+ checkRelativeURL("?query", "file:///path", {"file", "", "", "", 0, "/path", "query", "", "file:///path?query"});
+ checkRelativeURL(utf16String(u"?β"), "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "%CE%B2", "", "http://example.org/foo/bar?%CE%B2"});
+ checkRelativeURL("?", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "", "", "http://example.org/foo/bar?"});
+ checkRelativeURL("#", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "", "", "http://example.org/foo/bar#"});
+ checkRelativeURL("?#", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "", "", "http://example.org/foo/bar?#"});
+ checkRelativeURL("#?", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "", "?", "http://example.org/foo/bar#?"});
+ checkRelativeURL("/", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/", "", "", "http://example.org/"});
+ checkRelativeURL("http://@host", "about:blank", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
+ checkRelativeURL("http://:@host", "about:blank", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
+ checkRelativeURL("http://foo.com/\\@", "http://example.org/foo/bar", {"http", "", "", "foo.com", 0, "//@", "", "", "http://foo.com//@"});
+ checkRelativeURL("\\@", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/@", "", "", "http://example.org/@"});
+ checkRelativeURL("/path3", "http://user@example.org/path1/path2", {"http", "user", "", "example.org", 0, "/path3", "", "", "http://user@example.org/path3"});
+ checkRelativeURL("", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "", "", "http://example.org/foo/bar"});
+ checkRelativeURL("\t", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "", "", "http://example.org/foo/bar"});
+ checkRelativeURL(" ", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "", "", "http://example.org/foo/bar"});
+ checkRelativeURL(" \a \t\n", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "", "", "http://example.org/foo/bar"});
+ checkRelativeURL(":foo.com\\", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/:foo.com/", "", "", "http://example.org/foo/:foo.com/"});
+ checkRelativeURL("http:/example.com/", "about:blank", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
+ checkRelativeURL("http:example.com/", "about:blank", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
+ checkRelativeURL("http:\\\\foo.com\\", "http://example.org/foo/bar", {"http", "", "", "foo.com", 0, "/", "", "", "http://foo.com/"});
+ checkRelativeURL("http:\\\\foo.com/", "http://example.org/foo/bar", {"http", "", "", "foo.com", 0, "/", "", "", "http://foo.com/"});
+ checkRelativeURL("http:\\\\foo.com", "http://example.org/foo/bar", {"http", "", "", "foo.com", 0, "/", "", "", "http://foo.com/"});
+ checkRelativeURL("http://ExAmPlE.CoM", "http://other.com", {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
+ checkRelativeURL("http:", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "", "", "http://example.org/foo/bar"});
+ checkRelativeURL("#x", "data:,", {"data", "", "", "", 0, ",", "", "x", "data:,#x"});
+ checkRelativeURL("#x", "about:blank", {"about", "", "", "", 0, "blank", "", "x", "about:blank#x"});
+ checkRelativeURL(" foo.com ", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/foo.com", "", "", "http://example.org/foo/foo.com"});
+ checkRelativeURL(" \a baz", "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/baz", "", "", "http://example.org/foo/baz"});
+ checkRelativeURL("~", "http://example.org", {"http", "", "", "example.org", 0, "/~", "", "", "http://example.org/~"});
+ checkRelativeURL("notspecial:", "about:blank", {"notspecial", "", "", "", 0, "", "", "", "notspecial:"});
+ checkRelativeURL("notspecial:", "http://host", {"notspecial", "", "", "", 0, "", "", "", "notspecial:"});
+ checkRelativeURL("http:", "http://host", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
+ checkRelativeURL("i", "sc:/pa/po", {"sc", "", "", "", 0, "/pa/i", "", "", "sc:/pa/i"});
+ checkRelativeURL("i ", "sc:/pa/po", {"sc", "", "", "", 0, "/pa/i", "", "", "sc:/pa/i"});
+ checkRelativeURL("i\t\n ", "sc:/pa/po", {"sc", "", "", "", 0, "/pa/i", "", "", "sc:/pa/i"});
+ checkRelativeURL("i", "sc://ho/pa", {"sc", "", "", "ho", 0, "/i", "", "", "sc://ho/i"});
+ checkRelativeURL("!", "sc://ho/pa", {"sc", "", "", "ho", 0, "/!", "", "", "sc://ho/!"});
+ checkRelativeURL("!", "sc:/ho/pa", {"sc", "", "", "", 0, "/ho/!", "", "", "sc:/ho/!"});
+ checkRelativeURL("notspecial:/", "about:blank", {"notspecial", "", "", "", 0, "/", "", "", "notspecial:/"});
+ checkRelativeURL("notspecial:/", "http://host", {"notspecial", "", "", "", 0, "/", "", "", "notspecial:/"});
+ checkRelativeURL("foo:/", "http://example.org/foo/bar", {"foo", "", "", "", 0, "/", "", "", "foo:/"});
+ checkRelativeURL("://:0/", "http://webkit.org/", {"http", "", "", "webkit.org", 0, "/://:0/", "", "", "http://webkit.org/://:0/"});
+ checkRelativeURL(String(), "http://webkit.org/", {"http", "", "", "webkit.org", 0, "/", "", "", "http://webkit.org/"});
+ checkRelativeURL("https://@test@test@example:800\\path@end", "http://doesnotmatter/", {"", "", "", "", 0, "", "", "", "https://@test@test@example:800\\path@end"});
+ checkRelativeURL("http://f:0/c", "http://example.org/foo/bar", {"http", "", "", "f", 0, "/c", "", "", "http://f:0/c"});
+ checkRelativeURL(String(), "http://host/#fragment", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
+ checkRelativeURL("", "http://host/#fragment", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
+ checkRelativeURL(" ", "http://host/#fragment", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
+ checkRelativeURL(" ", "http://host/path?query#fra#gment", {"http", "", "", "host", 0, "/path", "query", "", "http://host/path?query"});
+ checkRelativeURL(" \a ", "http://host/#fragment", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
+ checkRelativeURLDifferences("foo://", "http://example.org/foo/bar",
+ {"foo", "", "", "", 0, "", "", "", "foo://"},
+ {"foo", "", "", "", 0, "//", "", "", "foo://"});
+ checkRelativeURL(utf16String(u"#β"), "http://example.org/foo/bar", {"http", "", "", "example.org", 0, "/foo/bar", "", "%CE%B2", "http://example.org/foo/bar#%CE%B2"});
+ checkRelativeURL("index.html", "applewebdata://Host/", {"applewebdata", "", "", "Host", 0, "/index.html", "", "", "applewebdata://Host/index.html"});
+ checkRelativeURL("index.html", "applewebdata://Host", {"applewebdata", "", "", "Host", 0, "/index.html", "", "", "applewebdata://Host/index.html"});
+ checkRelativeURL("", "applewebdata://Host", {"applewebdata", "", "", "Host", 0, "", "", "", "applewebdata://Host"});
+ checkRelativeURL("?query", "applewebdata://Host", {"applewebdata", "", "", "Host", 0, "", "query", "", "applewebdata://Host?query"});
+ checkRelativeURL("#fragment", "applewebdata://Host", {"applewebdata", "", "", "Host", 0, "", "", "fragment", "applewebdata://Host#fragment"});
+ checkRelativeURL("notspecial://something?", "file:////var//containers//stuff/", {"notspecial", "", "", "something", 0, "", "", "", "notspecial://something?"}, TestTabs::No);
+ checkRelativeURL("notspecial://something#", "file:////var//containers//stuff/", {"notspecial", "", "", "something", 0, "", "", "", "notspecial://something#"}, TestTabs::No);
+ checkRelativeURL("http://something?", "file:////var//containers//stuff/", {"http", "", "", "something", 0, "/", "", "", "http://something/?"}, TestTabs::No);
+ checkRelativeURL("http://something#", "file:////var//containers//stuff/", {"http", "", "", "something", 0, "/", "", "", "http://something/#"}, TestTabs::No);
+ checkRelativeURL("file:", "file:///path?query#fragment", {"file", "", "", "", 0, "/path", "query", "", "file:///path?query"});
+ checkRelativeURL("/", "file:///C:/a/b", {"file", "", "", "", 0, "/C:/", "", "", "file:///C:/"});
+ checkRelativeURL("/abc", "file:///C:/a/b", {"file", "", "", "", 0, "/C:/abc", "", "", "file:///C:/abc"});
+ checkRelativeURL("/abc", "file:///C:", {"file", "", "", "", 0, "/C:/abc", "", "", "file:///C:/abc"});
+ checkRelativeURL("/abc", "file:///", {"file", "", "", "", 0, "/abc", "", "", "file:///abc"});
+ checkRelativeURL("//d:", "file:///C:/a/b", {"file", "", "", "", 0, "/d:", "", "", "file:///d:"}, TestTabs::No);
+ checkRelativeURL("//d|", "file:///C:/a/b", {"file", "", "", "", 0, "/d:", "", "", "file:///d:"}, TestTabs::No);
+ checkRelativeURL("//A|", "file:///C:/a/b", {"file", "", "", "", 0, "/A:", "", "", "file:///A:"}, TestTabs::No);
+
+ // The checking of slashes in SpecialAuthoritySlashes needed to get this to pass contradicts what is in the spec,
+ // but it is included in the web platform tests.
+ checkRelativeURL("http:\\\\host\\foo", "about:blank", {"http", "", "", "host", 0, "/foo", "", "", "http://host/foo"});
+}
+
+// These are differences between the new URLParser and the old URL::parse which make URLParser more standards compliant.
+TEST_F(URLParserTest, ParserDifferences)
+{
+ checkURLDifferences("http://127.0.1",
+ {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"},
+ {"http", "", "", "127.0.1", 0, "/", "", "", "http://127.0.1/"});
+ checkURLDifferences("http://011.11.0X11.0x011",
+ {"http", "", "", "9.11.17.17", 0, "/", "", "", "http://9.11.17.17/"},
+ {"http", "", "", "011.11.0x11.0x011", 0, "/", "", "", "http://011.11.0x11.0x011/"});
+ checkURLDifferences("http://[1234:0078:90AB:CdEf:0123:0007:89AB:0000]",
+ {"http", "", "", "[1234:78:90ab:cdef:123:7:89ab:0]", 0, "/", "", "", "http://[1234:78:90ab:cdef:123:7:89ab:0]/"},
+ {"http", "", "", "[1234:0078:90ab:cdef:0123:0007:89ab:0000]", 0, "/", "", "", "http://[1234:0078:90ab:cdef:0123:0007:89ab:0000]/"});
+ checkURLDifferences("http://[0:f:0:0:f:f:0:0]",
+ {"http", "", "", "[0:f::f:f:0:0]", 0, "/", "", "", "http://[0:f::f:f:0:0]/"},
+ {"http", "", "", "[0:f:0:0:f:f:0:0]", 0, "/", "", "", "http://[0:f:0:0:f:f:0:0]/"});
+ checkURLDifferences("http://[0:f:0:0:f:0:0:0]",
+ {"http", "", "", "[0:f:0:0:f::]", 0, "/", "", "", "http://[0:f:0:0:f::]/"},
+ {"http", "", "", "[0:f:0:0:f:0:0:0]", 0, "/", "", "", "http://[0:f:0:0:f:0:0:0]/"});
+ checkURLDifferences("http://[0:0:f:0:0:f:0:0]",
+ {"http", "", "", "[::f:0:0:f:0:0]", 0, "/", "", "", "http://[::f:0:0:f:0:0]/"},
+ {"http", "", "", "[0:0:f:0:0:f:0:0]", 0, "/", "", "", "http://[0:0:f:0:0:f:0:0]/"});
+ checkURLDifferences("http://[a:0:0:0:b:c::d]",
+ {"http", "", "", "[a::b:c:0:d]", 0, "/", "", "", "http://[a::b:c:0:d]/"},
+ {"http", "", "", "[a:0:0:0:b:c::d]", 0, "/", "", "", "http://[a:0:0:0:b:c::d]/"});
+ checkURLDifferences("http://[::7f00:0001]/",
+ {"http", "", "", "[::7f00:1]", 0, "/", "", "", "http://[::7f00:1]/"},
+ {"http", "", "", "[::7f00:0001]", 0, "/", "", "", "http://[::7f00:0001]/"});
+ checkURLDifferences("http://[::7f00:00]/",
+ {"http", "", "", "[::7f00:0]", 0, "/", "", "", "http://[::7f00:0]/"},
+ {"http", "", "", "[::7f00:00]", 0, "/", "", "", "http://[::7f00:00]/"});
+ checkURLDifferences("http://[::0:7f00:0001]/",
+ {"http", "", "", "[::7f00:1]", 0, "/", "", "", "http://[::7f00:1]/"},
+ {"http", "", "", "[::0:7f00:0001]", 0, "/", "", "", "http://[::0:7f00:0001]/"});
+ checkURLDifferences("http://127.00.0.1/",
+ {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"},
+ {"http", "", "", "127.00.0.1", 0, "/", "", "", "http://127.00.0.1/"});
+ checkURLDifferences("http://127.0.0.01/",
+ {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"},
+ {"http", "", "", "127.0.0.01", 0, "/", "", "", "http://127.0.0.01/"});
+ checkURLDifferences("http://example.com/path1/.%2e",
+ {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"},
+ {"http", "", "", "example.com", 0, "/path1/.%2e", "", "", "http://example.com/path1/.%2e"});
+ checkURLDifferences("http://example.com/path1/.%2E",
+ {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"},
+ {"http", "", "", "example.com", 0, "/path1/.%2E", "", "", "http://example.com/path1/.%2E"});
+ checkURLDifferences("http://example.com/path1/.%2E/",
+ {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"},
+ {"http", "", "", "example.com", 0, "/path1/.%2E/", "", "", "http://example.com/path1/.%2E/"});
+ checkURLDifferences("http://example.com/path1/%2e.",
+ {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"},
+ {"http", "", "", "example.com", 0, "/path1/%2e.", "", "", "http://example.com/path1/%2e."});
+ checkURLDifferences("http://example.com/path1/%2E%2e",
+ {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"},
+ {"http", "", "", "example.com", 0, "/path1/%2E%2e", "", "", "http://example.com/path1/%2E%2e"});
+ checkURLDifferences("http://example.com/path1/%2e",
+ {"http", "", "", "example.com", 0, "/path1/", "", "", "http://example.com/path1/"},
+ {"http", "", "", "example.com", 0, "/path1/%2e", "", "", "http://example.com/path1/%2e"});
+ checkURLDifferences("http://example.com/path1/%2E",
+ {"http", "", "", "example.com", 0, "/path1/", "", "", "http://example.com/path1/"},
+ {"http", "", "", "example.com", 0, "/path1/%2E", "", "", "http://example.com/path1/%2E"});
+ checkURLDifferences("http://example.com/path1/%2E/",
+ {"http", "", "", "example.com", 0, "/path1/", "", "", "http://example.com/path1/"},
+ {"http", "", "", "example.com", 0, "/path1/%2E/", "", "", "http://example.com/path1/%2E/"});
+ checkURLDifferences("http://example.com/path1/path2/%2e?query",
+ {"http", "", "", "example.com", 0, "/path1/path2/", "query", "", "http://example.com/path1/path2/?query"},
+ {"http", "", "", "example.com", 0, "/path1/path2/%2e", "query", "", "http://example.com/path1/path2/%2e?query"});
+ checkURLDifferences("http://example.com/path1/path2/%2e%2e?query",
+ {"http", "", "", "example.com", 0, "/path1/", "query", "", "http://example.com/path1/?query"},
+ {"http", "", "", "example.com", 0, "/path1/path2/%2e%2e", "query", "", "http://example.com/path1/path2/%2e%2e?query"});
+ checkURLDifferences("http://example.com/path1/path2/%2e#fragment",
+ {"http", "", "", "example.com", 0, "/path1/path2/", "", "fragment", "http://example.com/path1/path2/#fragment"},
+ {"http", "", "", "example.com", 0, "/path1/path2/%2e", "", "fragment", "http://example.com/path1/path2/%2e#fragment"});
+ checkURLDifferences("http://example.com/path1/path2/%2e%2e#fragment",
+ {"http", "", "", "example.com", 0, "/path1/", "", "fragment", "http://example.com/path1/#fragment"},
+ {"http", "", "", "example.com", 0, "/path1/path2/%2e%2e", "", "fragment", "http://example.com/path1/path2/%2e%2e#fragment"});
+ checkURL("http://example.com/path1/path2/A%2e%2e#fragment", {"http", "", "", "example.com", 0, "/path1/path2/A%2e%2e", "", "fragment", "http://example.com/path1/path2/A%2e%2e#fragment"});
+ checkURLDifferences("file://[0:a:0:0:b:c:0:0]/path",
+ {"file", "", "", "[0:a::b:c:0:0]", 0, "/path", "", "", "file://[0:a::b:c:0:0]/path"},
+ {"file", "", "", "[0:a:0:0:b:c:0:0]", 0, "/path", "", "", "file://[0:a:0:0:b:c:0:0]/path"});
+ checkURLDifferences("http://",
+ {"", "", "", "", 0, "", "", "", "http://"},
+ {"http", "", "", "", 0, "/", "", "", "http:/"});
+ checkRelativeURLDifferences("//", "https://www.webkit.org/path",
+ {"", "", "", "", 0, "", "", "", "//"},
+ {"https", "", "", "", 0, "/", "", "", "https:/"});
+ checkURLDifferences("http://127.0.0.1:65536/path",
+ {"", "", "", "", 0, "", "", "", "http://127.0.0.1:65536/path"},
+ {"http", "", "", "127.0.0.1", 0, "/path", "", "", "http://127.0.0.1:65536/path"});
+ checkURLDifferences("http://host:65536",
+ {"", "", "", "", 0, "", "", "", "http://host:65536"},
+ {"http", "", "", "host", 0, "/", "", "", "http://host:65536/"});
+ checkURLDifferences("http://127.0.0.1:65536",
+ {"", "", "", "", 0, "", "", "", "http://127.0.0.1:65536"},
+ {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1:65536/"});
+ checkURLDifferences("http://[0:f::f:f:0:0]:65536",
+ {"", "", "", "", 0, "", "", "", "http://[0:f::f:f:0:0]:65536"},
+ {"http", "", "", "[0:f::f:f:0:0]", 0, "/", "", "", "http://[0:f::f:f:0:0]:65536/"});
+ checkRelativeURLDifferences(":foo.com\\", "notspecial://example.org/foo/bar",
+ {"notspecial", "", "", "example.org", 0, "/foo/:foo.com\\", "", "", "notspecial://example.org/foo/:foo.com\\"},
+ {"notspecial", "", "", "example.org", 0, "/foo/:foo.com/", "", "", "notspecial://example.org/foo/:foo.com/"});
+ checkURL("sc://pa", {"sc", "", "", "pa", 0, "", "", "", "sc://pa"});
+ checkRelativeURLDifferences("notspecial:\\\\foo.com\\", "http://example.org/foo/bar",
+ {"notspecial", "", "", "", 0, "\\\\foo.com\\", "", "", "notspecial:\\\\foo.com\\"},
+ {"notspecial", "", "", "foo.com", 0, "/", "", "", "notspecial://foo.com/"});
+ checkRelativeURLDifferences("notspecial:\\\\foo.com/", "http://example.org/foo/bar",
+ {"notspecial", "", "", "", 0, "\\\\foo.com/", "", "", "notspecial:\\\\foo.com/"},
+ {"notspecial", "", "", "foo.com", 0, "/", "", "", "notspecial://foo.com/"});
+ checkRelativeURLDifferences("notspecial:\\\\foo.com", "http://example.org/foo/bar",
+ {"notspecial", "", "", "", 0, "\\\\foo.com", "", "", "notspecial:\\\\foo.com"},
+ {"notspecial", "", "", "foo.com", 0, "", "", "", "notspecial://foo.com"});
+ checkURLDifferences("file://notuser:notpassword@test",
+ {"", "", "", "", 0, "", "", "", "file://notuser:notpassword@test"},
+ {"file", "notuser", "notpassword", "test", 0, "/", "", "", "file://notuser:notpassword@test/"});
+ checkURLDifferences("file://notuser:notpassword@test/",
+ {"", "", "", "", 0, "", "", "", "file://notuser:notpassword@test/"},
+ {"file", "notuser", "notpassword", "test", 0, "/", "", "", "file://notuser:notpassword@test/"});
+ checkRelativeURLDifferences("http:/", "about:blank",
+ {"", "", "", "", 0, "", "", "", "http:/"},
+ {"http", "", "", "", 0, "/", "", "", "http:/"});
+ checkRelativeURLDifferences("http:", "about:blank",
+ {"http", "", "", "", 0, "", "", "", "http:"},
+ {"http", "", "", "", 0, "/", "", "", "http:/"});
+ checkRelativeURLDifferences("http:/", "http://host",
+ {"", "", "", "", 0, "", "", "", "http:/"},
+ {"http", "", "", "", 0, "/", "", "", "http:/"});
+ checkURLDifferences("http:/",
+ {"", "", "", "", 0, "", "", "", "http:/"},
+ {"http", "", "", "", 0, "/", "", "", "http:/"});
+ checkURLDifferences("http:",
+ {"http", "", "", "", 0, "", "", "", "http:"},
+ {"http", "", "", "", 0, "/", "", "", "http:/"});
+ checkRelativeURLDifferences("http:/example.com/", "http://example.org/foo/bar",
+ {"http", "", "", "example.org", 0, "/example.com/", "", "", "http://example.org/example.com/"},
+ {"http", "", "", "example.com", 0, "/", "", "", "http://example.com/"});
+
+ // This behavior matches Chrome and Firefox, but not WebKit using URL::parse.
+ // The behavior of URL::parse is clearly wrong because reparsing file://path would make path the host.
+ // The spec is unclear.
+ checkURLDifferences("file:path",
+ {"file", "", "", "", 0, "/path", "", "", "file:///path"},
+ {"file", "", "", "", 0, "path", "", "", "file://path"});
+ checkURLDifferences("file:pAtH",
+ {"file", "", "", "", 0, "/pAtH", "", "", "file:///pAtH"},
+ {"file", "", "", "", 0, "pAtH", "", "", "file://pAtH"});
+ checkURLDifferences("file:pAtH/",
+ {"file", "", "", "", 0, "/pAtH/", "", "", "file:///pAtH/"},
+ {"file", "", "", "", 0, "pAtH/", "", "", "file://pAtH/"});
+ checkURLDifferences("http://example.com%A0",
+ {"", "", "", "", 0, "", "", "", "http://example.com%A0"},
+ {"http", "", "", "example.com%a0", 0, "/", "", "", "http://example.com%a0/"});
+ checkURLDifferences("http://%E2%98%83",
+ {"http", "", "", "xn--n3h", 0, "/", "", "", "http://xn--n3h/"},
+ {"http", "", "", "%e2%98%83", 0, "/", "", "", "http://%e2%98%83/"});
+ checkURLDifferences("http://host%73",
+ {"http", "", "", "hosts", 0, "/", "", "", "http://hosts/"},
+ {"http", "", "", "host%73", 0, "/", "", "", "http://host%73/"});
+ checkURLDifferences("http://host%53",
+ {"http", "", "", "hosts", 0, "/", "", "", "http://hosts/"},
+ {"http", "", "", "host%53", 0, "/", "", "", "http://host%53/"});
+ checkURLDifferences("http://%",
+ {"", "", "", "", 0, "", "", "", "http://%"},
+ {"http", "", "", "%", 0, "/", "", "", "http://%/"});
+ checkURLDifferences("http://%7",
+ {"", "", "", "", 0, "", "", "", "http://%7"},
+ {"http", "", "", "%7", 0, "/", "", "", "http://%7/"});
+ checkURLDifferences("http://%7s",
+ {"", "", "", "", 0, "", "", "", "http://%7s"},
+ {"http", "", "", "%7s", 0, "/", "", "", "http://%7s/"});
+ checkURLDifferences("http://%73",
+ {"http", "", "", "s", 0, "/", "", "", "http://s/"},
+ {"http", "", "", "%73", 0, "/", "", "", "http://%73/"});
+ checkURLDifferences("http://abcdefg%",
+ {"", "", "", "", 0, "", "", "", "http://abcdefg%"},
+ {"http", "", "", "abcdefg%", 0, "/", "", "", "http://abcdefg%/"});
+ checkURLDifferences("http://abcd%7Xefg",
+ {"", "", "", "", 0, "", "", "", "http://abcd%7Xefg"},
+ {"http", "", "", "abcd%7xefg", 0, "/", "", "", "http://abcd%7xefg/"});
+
+
+ // URLParser matches Chrome and the spec, but not URL::parse or Firefox.
+ checkURLDifferences(utf16String(u"http://0Xc0.0250.01"),
+ {"http", "", "", "192.168.0.1", 0, "/", "", "", "http://192.168.0.1/"},
+ {"http", "", "", "0xc0.0250.01", 0, "/", "", "", "http://0xc0.0250.01/"});
+
+ checkURL("http://host/path%2e.%2E", {"http", "", "", "host", 0, "/path%2e.%2E", "", "", "http://host/path%2e.%2E"});
+
+ checkRelativeURLDifferences(utf16String(u"http://foo:💩@example.com/bar"), "http://other.com/",
+ {"http", "foo", utf16String(u"💩"), "example.com", 0, "/bar", "", "", "http://foo:%F0%9F%92%A9@example.com/bar"},
+ {"", "", "", "", 0, "", "", "", utf16String(u"http://foo:💩@example.com/bar")}, testTabsValueForSurrogatePairs);
+ checkRelativeURLDifferences("http://&a:foo(b]c@d:2/", "http://example.org/foo/bar",
+ {"http", "&a", "foo(b]c", "d", 2, "/", "", "", "http://&a:foo(b%5Dc@d:2/"},
+ {"", "", "", "", 0, "", "", "", "http://&a:foo(b]c@d:2/"});
+ checkRelativeURLDifferences("http://`{}:`{}@h/`{}?`{}", "http://doesnotmatter/",
+ {"http", "`{}", "`{}", "h", 0, "/%60%7B%7D", "`{}", "", "http://%60%7B%7D:%60%7B%7D@h/%60%7B%7D?`{}"},
+ {"", "", "", "", 0, "", "", "", "http://`{}:`{}@h/`{}?`{}"});
+ checkURLDifferences("http://[0:f::f::f]",
+ {"", "", "", "", 0, "" , "", "", "http://[0:f::f::f]"},
+ {"http", "", "", "[0:f::f::f]", 0, "/" , "", "", "http://[0:f::f::f]/"});
+ checkURLDifferences("http://123",
+ {"http", "", "", "0.0.0.123", 0, "/", "", "", "http://0.0.0.123/"},
+ {"http", "", "", "123", 0, "/", "", "", "http://123/"});
+ checkURLDifferences("http://123.234/",
+ {"http", "", "", "123.0.0.234", 0, "/", "", "", "http://123.0.0.234/"},
+ {"http", "", "", "123.234", 0, "/", "", "", "http://123.234/"});
+ checkURLDifferences("http://123.234.012",
+ {"http", "", "", "123.234.0.10", 0, "/", "", "", "http://123.234.0.10/"},
+ {"http", "", "", "123.234.012", 0, "/", "", "", "http://123.234.012/"});
+ checkURLDifferences("http://123.234.12",
+ {"http", "", "", "123.234.0.12", 0, "/", "", "", "http://123.234.0.12/"},
+ {"http", "", "", "123.234.12", 0, "/", "", "", "http://123.234.12/"});
+ checkRelativeURLDifferences("file:c:\\foo\\bar.html", "file:///tmp/mock/path",
+ {"file", "", "", "", 0, "/c:/foo/bar.html", "", "", "file:///c:/foo/bar.html"},
+ {"file", "", "", "", 0, "/tmp/mock/c:/foo/bar.html", "", "", "file:///tmp/mock/c:/foo/bar.html"});
+ checkRelativeURLDifferences(" File:c|////foo\\bar.html", "file:///tmp/mock/path",
+ {"file", "", "", "", 0, "/c:////foo/bar.html", "", "", "file:///c:////foo/bar.html"},
+ {"file", "", "", "", 0, "/tmp/mock/c|////foo/bar.html", "", "", "file:///tmp/mock/c|////foo/bar.html"});
+ checkRelativeURLDifferences(" Fil\t\n\te\n\t\n:\t\n\tc\t\n\t|\n\t\n/\t\n\t/\n\t\n//foo\\bar.html", "file:///tmp/mock/path",
+ {"file", "", "", "", 0, "/c:////foo/bar.html", "", "", "file:///c:////foo/bar.html"},
+ {"file", "", "", "", 0, "/tmp/mock/c|////foo/bar.html", "", "", "file:///tmp/mock/c|////foo/bar.html"});
+ checkRelativeURLDifferences("C|/foo/bar", "file:///tmp/mock/path",
+ {"file", "", "", "", 0, "/C:/foo/bar", "", "", "file:///C:/foo/bar"},
+ {"file", "", "", "", 0, "/tmp/mock/C|/foo/bar", "", "", "file:///tmp/mock/C|/foo/bar"});
+ checkRelativeURLDifferences("/C|/foo/bar", "file:///tmp/mock/path",
+ {"file", "", "", "", 0, "/C:/foo/bar", "", "", "file:///C:/foo/bar"},
+ {"file", "", "", "", 0, "/C|/foo/bar", "", "", "file:///C|/foo/bar"});
+ checkRelativeURLDifferences("https://@test@test@example:800/", "http://doesnotmatter/",
+ {"https", "@test@test", "", "example", 800, "/", "", "", "https://%40test%40test@example:800/"},
+ {"", "", "", "", 0, "", "", "", "https://@test@test@example:800/"});
+ checkRelativeURLDifferences("https://@test@test@example:800/path@end", "http://doesnotmatter/",
+ {"https", "@test@test", "", "example", 800, "/path@end", "", "", "https://%40test%40test@example:800/path@end"},
+ {"", "", "", "", 0, "", "", "", "https://@test@test@example:800/path@end"});
+ checkURLDifferences("notspecial://@test@test@example:800/path@end",
+ {"notspecial", "@test@test", "", "example", 800, "/path@end", "", "", "notspecial://%40test%40test@example:800/path@end"},
+ {"", "", "", "", 0, "", "", "", "notspecial://@test@test@example:800/path@end"});
+ checkURLDifferences("notspecial://@test@test@example:800\\path@end",
+ {"notspecial", "@test@test@example", "800\\path", "end", 0, "", "", "", "notspecial://%40test%40test%40example:800%5Cpath@end"},
+ {"", "", "", "", 0, "", "", "", "notspecial://@test@test@example:800\\path@end"});
+ checkURLDifferences("http://%48OsT",
+ {"http", "", "", "host", 0, "/", "", "", "http://host/"},
+ {"http", "", "", "%48ost", 0, "/", "", "", "http://%48ost/"});
+ checkURLDifferences("http://h%4FsT",
+ {"http", "", "", "host", 0, "/", "", "", "http://host/"},
+ {"http", "", "", "h%4fst", 0, "/", "", "", "http://h%4fst/"});
+ checkURLDifferences("http://h%4fsT",
+ {"http", "", "", "host", 0, "/", "", "", "http://host/"},
+ {"http", "", "", "h%4fst", 0, "/", "", "", "http://h%4fst/"});
+ checkURLDifferences("http://h%6fsT",
+ {"http", "", "", "host", 0, "/", "", "", "http://host/"},
+ {"http", "", "", "h%6fst", 0, "/", "", "", "http://h%6fst/"});
+ checkURLDifferences("http://host/`",
+ {"http", "", "", "host", 0, "/%60", "", "", "http://host/%60"},
+ {"http", "", "", "host", 0, "/`", "", "", "http://host/`"});
+ checkURLDifferences("http://://",
+ {"", "", "", "", 0, "", "", "", "http://://"},
+ {"http", "", "", "", 0, "//", "", "", "http://://"});
+ checkURLDifferences("http://:123?",
+ {"", "", "", "", 0, "", "", "", "http://:123?"},
+ {"http", "", "", "", 123, "/", "", "", "http://:123/?"});
+ checkURLDifferences("http:/:",
+ {"", "", "", "", 0, "", "", "", "http:/:"},
+ {"http", "", "", "", 0, "/", "", "", "http://:/"});
+ checkURLDifferences("asdf://:",
+ {"", "", "", "", 0, "", "", "", "asdf://:"},
+ {"asdf", "", "", "", 0, "", "", "", "asdf://:"});
+ checkURLDifferences("http://:",
+ {"", "", "", "", 0, "", "", "", "http://:"},
+ {"http", "", "", "", 0, "/", "", "", "http://:/"});
+ checkURLDifferences("http:##foo",
+ {"", "", "", "", 0, "", "", "", "http:##foo"},
+ {"http", "", "", "", 0, "/", "", "#foo", "http:/##foo"});
+ checkURLDifferences("http:??bar",
+ {"", "", "", "", 0, "", "", "", "http:??bar"},
+ {"http", "", "", "", 0, "/", "?bar", "", "http:/??bar"});
+ checkURL("asdf:##foo", {"asdf", "", "", "", 0, "", "", "#foo", "asdf:##foo"});
+ checkURL("asdf:??bar", {"asdf", "", "", "", 0, "", "?bar", "", "asdf:??bar"});
+ checkRelativeURLDifferences("//C|/foo/bar", "file:///tmp/mock/path",
+ {"file", "", "", "", 0, "/C:/foo/bar", "", "", "file:///C:/foo/bar"},
+ {"", "", "", "", 0, "", "", "", "//C|/foo/bar"});
+ checkRelativeURLDifferences("//C:/foo/bar", "file:///tmp/mock/path",
+ {"file", "", "", "", 0, "/C:/foo/bar", "", "", "file:///C:/foo/bar"},
+ {"file", "", "", "c", 0, "/foo/bar", "", "", "file://c/foo/bar"});
+ checkRelativeURLDifferences("//C|?foo/bar", "file:///tmp/mock/path",
+ {"file", "", "", "", 0, "/C:/", "foo/bar", "", "file:///C:/?foo/bar"},
+ {"", "", "", "", 0, "", "", "", "//C|?foo/bar"});
+ checkRelativeURLDifferences("//C|#foo/bar", "file:///tmp/mock/path",
+ {"file", "", "", "", 0, "/C:/", "", "foo/bar", "file:///C:/#foo/bar"},
+ {"", "", "", "", 0, "", "", "", "//C|#foo/bar"});
+ checkURLDifferences("http://0xFFFFFfFF/",
+ {"http", "", "", "255.255.255.255", 0, "/", "", "", "http://255.255.255.255/"},
+ {"http", "", "", "0xffffffff", 0, "/", "", "", "http://0xffffffff/"});
+ checkURLDifferences("http://0000000000000000037777777777/",
+ {"http", "", "", "255.255.255.255", 0, "/", "", "", "http://255.255.255.255/"},
+ {"http", "", "", "0000000000000000037777777777", 0, "/", "", "", "http://0000000000000000037777777777/"});
+ checkURLDifferences("http://4294967295/",
+ {"http", "", "", "255.255.255.255", 0, "/", "", "", "http://255.255.255.255/"},
+ {"http", "", "", "4294967295", 0, "/", "", "", "http://4294967295/"});
+ checkURLDifferences("http://256/",
+ {"http", "", "", "0.0.1.0", 0, "/", "", "", "http://0.0.1.0/"},
+ {"http", "", "", "256", 0, "/", "", "", "http://256/"});
+ checkURLDifferences("http://256./",
+ {"http", "", "", "0.0.1.0", 0, "/", "", "", "http://0.0.1.0/"},
+ {"http", "", "", "256.", 0, "/", "", "", "http://256./"});
+ checkURLDifferences("http://123.256/",
+ {"http", "", "", "123.0.1.0", 0, "/", "", "", "http://123.0.1.0/"},
+ {"http", "", "", "123.256", 0, "/", "", "", "http://123.256/"});
+ checkURLDifferences("http://127.%.0.1/",
+ {"", "", "", "", 0, "", "", "", "http://127.%.0.1/"},
+ {"http", "", "", "127.%.0.1", 0, "/", "", "", "http://127.%.0.1/"});
+ checkURLDifferences("http://[1:2:3:4:5:6:7:8:]/",
+ {"", "", "", "", 0, "", "", "", "http://[1:2:3:4:5:6:7:8:]/"},
+ {"http", "", "", "[1:2:3:4:5:6:7:8:]", 0, "/", "", "", "http://[1:2:3:4:5:6:7:8:]/"});
+ checkURLDifferences("http://[:2:3:4:5:6:7:8:]/",
+ {"", "", "", "", 0, "", "", "", "http://[:2:3:4:5:6:7:8:]/"},
+ {"http", "", "", "[:2:3:4:5:6:7:8:]", 0, "/", "", "", "http://[:2:3:4:5:6:7:8:]/"});
+ checkURLDifferences("http://[1:2:3:4:5:6:7::]/",
+ {"http", "", "", "[1:2:3:4:5:6:7:0]", 0, "/", "", "", "http://[1:2:3:4:5:6:7:0]/"},
+ {"http", "", "", "[1:2:3:4:5:6:7::]", 0, "/", "", "", "http://[1:2:3:4:5:6:7::]/"});
+ checkURLDifferences("http://[1:2:3:4:5:6:7:::]/",
+ {"", "", "", "", 0, "", "", "", "http://[1:2:3:4:5:6:7:::]/"},
+ {"http", "", "", "[1:2:3:4:5:6:7:::]", 0, "/", "", "", "http://[1:2:3:4:5:6:7:::]/"});
+ checkURLDifferences("http://127.0.0.1~/",
+ {"http", "", "", "127.0.0.1~", 0, "/", "", "", "http://127.0.0.1~/"},
+ {"", "", "", "", 0, "", "", "", "http://127.0.0.1~/"});
+ checkURLDifferences("http://127.0.1~/",
+ {"http", "", "", "127.0.1~", 0, "/", "", "", "http://127.0.1~/"},
+ {"", "", "", "", 0, "", "", "", "http://127.0.1~/"});
+ checkURLDifferences("http://127.0.1./",
+ {"http", "", "", "127.0.0.1", 0, "/", "", "", "http://127.0.0.1/"},
+ {"http", "", "", "127.0.1.", 0, "/", "", "", "http://127.0.1./"});
+ checkURLDifferences("http://127.0.1.~/",
+ {"http", "", "", "127.0.1.~", 0, "/", "", "", "http://127.0.1.~/"},
+ {"", "", "", "", 0, "", "", "", "http://127.0.1.~/"});
+ checkURLDifferences("http://127.0.1.~",
+ {"http", "", "", "127.0.1.~", 0, "/", "", "", "http://127.0.1.~/"},
+ {"", "", "", "", 0, "", "", "", "http://127.0.1.~"});
+ checkRelativeURLDifferences("http://f:000/c", "http://example.org/foo/bar",
+ {"http", "", "", "f", 0, "/c", "", "", "http://f:0/c"},
+ {"http", "", "", "f", 0, "/c", "", "", "http://f:000/c"});
+ checkRelativeURLDifferences("http://f:010/c", "http://example.org/foo/bar",
+ {"http", "", "", "f", 10, "/c", "", "", "http://f:10/c"},
+ {"http", "", "", "f", 10, "/c", "", "", "http://f:010/c"});
+ checkURL("notspecial://HoSt", {"notspecial", "", "", "HoSt", 0, "", "", "", "notspecial://HoSt"});
+ checkURL("notspecial://H%6FSt", {"notspecial", "", "", "H%6FSt", 0, "", "", "", "notspecial://H%6FSt"});
+ checkURL("notspecial://H%4fSt", {"notspecial", "", "", "H%4fSt", 0, "", "", "", "notspecial://H%4fSt"});
+ checkURLDifferences(utf16String(u"notspecial://H😍ßt"),
+ {"notspecial", "", "", "H%F0%9F%98%8D%C3%9Ft", 0, "", "", "", "notspecial://H%F0%9F%98%8D%C3%9Ft"},
+ {"notspecial", "", "", "xn--hsst-qc83c", 0, "", "", "", "notspecial://xn--hsst-qc83c"}, testTabsValueForSurrogatePairs);
+ checkURLDifferences("http://[ffff:aaaa:cccc:eeee:bbbb:dddd:255.255.255.255]/",
+ {"http", "", "", "[ffff:aaaa:cccc:eeee:bbbb:dddd:ffff:ffff]", 0, "/", "", "", "http://[ffff:aaaa:cccc:eeee:bbbb:dddd:ffff:ffff]/"},
+ {"http", "", "", "[ffff:aaaa:cccc:eeee:bbbb:dddd:255.255.255.255]", 0, "/", "", "", "http://[ffff:aaaa:cccc:eeee:bbbb:dddd:255.255.255.255]/"}, TestTabs::No);
+ checkURLDifferences("http://[::123.234.12.210]/",
+ {"http", "", "", "[::7bea:cd2]", 0, "/", "", "", "http://[::7bea:cd2]/"},
+ {"http", "", "", "[::123.234.12.210]", 0, "/", "", "", "http://[::123.234.12.210]/"});
+ checkURLDifferences("http://[::a:255.255.255.255]/",
+ {"http", "", "", "[::a:ffff:ffff]", 0, "/", "", "", "http://[::a:ffff:ffff]/"},
+ {"http", "", "", "[::a:255.255.255.255]", 0, "/", "", "", "http://[::a:255.255.255.255]/"});
+ checkURLDifferences("http://[::0.00.255.255]/",
+ {"", "", "", "", 0, "", "", "", "http://[::0.00.255.255]/"},
+ {"http", "", "", "[::0.00.255.255]", 0, "/", "", "", "http://[::0.00.255.255]/"});
+ checkURLDifferences("http://[::0.0.255.255]/",
+ {"http", "", "", "[::ffff]", 0, "/", "", "", "http://[::ffff]/"},
+ {"http", "", "", "[::0.0.255.255]", 0, "/", "", "", "http://[::0.0.255.255]/"});
+ checkURLDifferences("http://[::0:1.0.255.255]/",
+ {"http", "", "", "[::100:ffff]", 0, "/", "", "", "http://[::100:ffff]/"},
+ {"http", "", "", "[::0:1.0.255.255]", 0, "/", "", "", "http://[::0:1.0.255.255]/"});
+ checkURLDifferences("http://[::A:1.0.255.255]/",
+ {"http", "", "", "[::a:100:ffff]", 0, "/", "", "", "http://[::a:100:ffff]/"},
+ {"http", "", "", "[::a:1.0.255.255]", 0, "/", "", "", "http://[::a:1.0.255.255]/"});
+ checkURLDifferences("http://[:127.0.0.1]",
+ {"", "", "", "", 0, "", "", "", "http://[:127.0.0.1]"},
+ {"http", "", "", "[:127.0.0.1]", 0, "/", "", "", "http://[:127.0.0.1]/"});
+ checkURLDifferences("http://[127.0.0.1]",
+ {"", "", "", "", 0, "", "", "", "http://[127.0.0.1]"},
+ {"http", "", "", "[127.0.0.1]", 0, "/", "", "", "http://[127.0.0.1]/"});
+ checkURLDifferences("http://[a:b:c:d:e:f:127.0.0.1]",
+ {"http", "", "", "[a:b:c:d:e:f:7f00:1]", 0, "/", "", "", "http://[a:b:c:d:e:f:7f00:1]/"},
+ {"http", "", "", "[a:b:c:d:e:f:127.0.0.1]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.0.1]/"});
+ checkURLDifferences("http://[a:b:c:d:e:f:127.0.0.101]",
+ {"http", "", "", "[a:b:c:d:e:f:7f00:65]", 0, "/", "", "", "http://[a:b:c:d:e:f:7f00:65]/"},
+ {"http", "", "", "[a:b:c:d:e:f:127.0.0.101]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.0.101]/"});
+ checkURLDifferences("http://[::a:b:c:d:e:f:127.0.0.1]",
+ {"", "", "", "", 0, "", "", "", "http://[::a:b:c:d:e:f:127.0.0.1]"},
+ {"http", "", "", "[::a:b:c:d:e:f:127.0.0.1]", 0, "/", "", "", "http://[::a:b:c:d:e:f:127.0.0.1]/"});
+ checkURLDifferences("http://[a:b::c:d:e:f:127.0.0.1]",
+ {"", "", "", "", 0, "", "", "", "http://[a:b::c:d:e:f:127.0.0.1]"},
+ {"http", "", "", "[a:b::c:d:e:f:127.0.0.1]", 0, "/", "", "", "http://[a:b::c:d:e:f:127.0.0.1]/"});
+ checkURLDifferences("http://[a:b:c:d:e:127.0.0.1]",
+ {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:127.0.0.1]"},
+ {"http", "", "", "[a:b:c:d:e:127.0.0.1]", 0, "/", "", "", "http://[a:b:c:d:e:127.0.0.1]/"});
+ checkURLDifferences("http://[a:b:c:d:e:f:127.0.0.0.1]",
+ {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f:127.0.0.0.1]"},
+ {"http", "", "", "[a:b:c:d:e:f:127.0.0.0.1]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.0.0.1]/"});
+ checkURLDifferences("http://[a:b:c:d:e:f:127.0.1]",
+ {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f:127.0.1]"},
+ {"http", "", "", "[a:b:c:d:e:f:127.0.1]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.1]/"});
+ checkURLDifferences("http://[a:b:c:d:e:f:127.0.0.011]", // Chrome treats this as octal, Firefox and the spec fail
+ {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f:127.0.0.011]"},
+ {"http", "", "", "[a:b:c:d:e:f:127.0.0.011]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.0.011]/"});
+ checkURLDifferences("http://[a:b:c:d:e:f:127.0.00.1]",
+ {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f:127.0.00.1]"},
+ {"http", "", "", "[a:b:c:d:e:f:127.0.00.1]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.00.1]/"});
+ checkURLDifferences("http://[a:b:c:d:e:f:127.0.0.1.]",
+ {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f:127.0.0.1.]"},
+ {"http", "", "", "[a:b:c:d:e:f:127.0.0.1.]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0.0.1.]/"});
+ checkURLDifferences("http://[a:b:c:d:e:f:127.0..0.1]",
+ {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f:127.0..0.1]"},
+ {"http", "", "", "[a:b:c:d:e:f:127.0..0.1]", 0, "/", "", "", "http://[a:b:c:d:e:f:127.0..0.1]/"});
+ checkURLDifferences("http://[a:b:c:d:e:f::127.0.0.1]",
+ {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f::127.0.0.1]"},
+ {"http", "", "", "[a:b:c:d:e:f::127.0.0.1]", 0, "/", "", "", "http://[a:b:c:d:e:f::127.0.0.1]/"});
+ checkURLDifferences("http://[a:b:c:d:e::127.0.0.1]",
+ {"http", "", "", "[a:b:c:d:e:0:7f00:1]", 0, "/", "", "", "http://[a:b:c:d:e:0:7f00:1]/"},
+ {"http", "", "", "[a:b:c:d:e::127.0.0.1]", 0, "/", "", "", "http://[a:b:c:d:e::127.0.0.1]/"});
+ checkURLDifferences("http://[a:b:c:d::e:127.0.0.1]",
+ {"http", "", "", "[a:b:c:d:0:e:7f00:1]", 0, "/", "", "", "http://[a:b:c:d:0:e:7f00:1]/"},
+ {"http", "", "", "[a:b:c:d::e:127.0.0.1]", 0, "/", "", "", "http://[a:b:c:d::e:127.0.0.1]/"});
+ checkURLDifferences("http://[a:b:c:d:e:f::127.0.0.]",
+ {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f::127.0.0.]"},
+ {"http", "", "", "[a:b:c:d:e:f::127.0.0.]", 0, "/", "", "", "http://[a:b:c:d:e:f::127.0.0.]/"});
+ checkURLDifferences("http://[a:b:c:d:e:f::127.0.0.256]",
+ {"", "", "", "", 0, "", "", "", "http://[a:b:c:d:e:f::127.0.0.256]"},
+ {"http", "", "", "[a:b:c:d:e:f::127.0.0.256]", 0, "/", "", "", "http://[a:b:c:d:e:f::127.0.0.256]/"});
+ checkURLDifferences("http://123456", {"http", "", "", "0.1.226.64", 0, "/", "", "", "http://0.1.226.64/"}, {"http", "", "", "123456", 0, "/", "", "", "http://123456/"});
+ checkURL("asdf://123456", {"asdf", "", "", "123456", 0, "", "", "", "asdf://123456"});
+ checkURLDifferences("http://[0:0:0:0:a:b:c:d]",
+ {"http", "", "", "[::a:b:c:d]", 0, "/", "", "", "http://[::a:b:c:d]/"},
+ {"http", "", "", "[0:0:0:0:a:b:c:d]", 0, "/", "", "", "http://[0:0:0:0:a:b:c:d]/"});
+ checkURLDifferences("asdf://[0:0:0:0:a:b:c:d]",
+ {"asdf", "", "", "[::a:b:c:d]", 0, "", "", "", "asdf://[::a:b:c:d]"},
+ {"asdf", "", "", "[0:0:0:0:a:b:c:d]", 0, "", "", "", "asdf://[0:0:0:0:a:b:c:d]"}, TestTabs::No);
+ shouldFail("a://%:a");
+ checkURL("a://%:/", {"a", "", "", "%", 0, "/", "", "", "a://%/"});
+ checkURL("a://%:", {"a", "", "", "%", 0, "", "", "", "a://%"});
+ checkURL("a://%:1/", {"a", "", "", "%", 1, "/", "", "", "a://%:1/"});
+ checkURLDifferences("http://%:",
+ {"", "", "", "", 0, "", "", "", "http://%:"},
+ {"http", "", "", "%", 0, "/", "", "", "http://%/"});
+ checkURL("a://123456", {"a", "", "", "123456", 0, "", "", "", "a://123456"});
+ checkURL("a://123456:7", {"a", "", "", "123456", 7, "", "", "", "a://123456:7"});
+ checkURL("a://123456:7/", {"a", "", "", "123456", 7, "/", "", "", "a://123456:7/"});
+ checkURL("a://A", {"a", "", "", "A", 0, "", "", "", "a://A"});
+ checkURL("a://A:2", {"a", "", "", "A", 2, "", "", "", "a://A:2"});
+ checkURL("a://A:2/", {"a", "", "", "A", 2, "/", "", "", "a://A:2/"});
+ checkURLDifferences(u8"asd://ß",
+ {"asd", "", "", "%C3%83%C2%9F", 0, "", "", "", "asd://%C3%83%C2%9F"},
+ {"", "", "", "", 0, "", "", "", "about:blank"}, TestTabs::No);
+ checkURLDifferences(u8"asd://ß:4",
+ {"asd", "", "", "%C3%83%C2%9F", 4, "", "", "", "asd://%C3%83%C2%9F:4"},
+ {"", "", "", "", 0, "", "", "", "about:blank"}, TestTabs::No);
+ checkURLDifferences(u8"asd://ß:4/",
+ {"asd", "", "", "%C3%83%C2%9F", 4, "/", "", "", "asd://%C3%83%C2%9F:4/"},
+ {"", "", "", "", 0, "", "", "", "about:blank"}, TestTabs::No);
+ checkURLDifferences("a://[A::b]:4",
+ {"a", "", "", "[a::b]", 4, "", "", "", "a://[a::b]:4"},
+ {"a", "", "", "[A::b]", 4, "", "", "", "a://[A::b]:4"});
+ shouldFail("http://[~]");
+ shouldFail("a://[~]");
+ checkRelativeURLDifferences("a://b", "//[aBc]",
+ {"a", "", "", "b", 0, "", "", "", "a://b"},
+ {"", "", "", "", 0, "", "", "", "a://b"});
+ checkURL(utf16String(u"http://öbb.at"), {"http", "", "", "xn--bb-eka.at", 0, "/", "", "", "http://xn--bb-eka.at/"});
+ checkURL(utf16String(u"http://ÖBB.at"), {"http", "", "", "xn--bb-eka.at", 0, "/", "", "", "http://xn--bb-eka.at/"});
+ checkURL(utf16String(u"http://√.com"), {"http", "", "", "xn--19g.com", 0, "/", "", "", "http://xn--19g.com/"});
+ checkURLDifferences(utf16String(u"http://faß.de"),
+ {"http", "", "", "xn--fa-hia.de", 0, "/", "", "", "http://xn--fa-hia.de/"},
+ {"http", "", "", "fass.de", 0, "/", "", "", "http://fass.de/"});
+ checkURL(utf16String(u"http://ԛәлп.com"), {"http", "", "", "xn--k1ai47bhi.com", 0, "/", "", "", "http://xn--k1ai47bhi.com/"});
+ checkURLDifferences(utf16String(u"http://Ⱥbby.com"),
+ {"http", "", "", "xn--bby-iy0b.com", 0, "/", "", "", "http://xn--bby-iy0b.com/"},
+ {"http", "", "", "xn--bby-spb.com", 0, "/", "", "", "http://xn--bby-spb.com/"});
+ checkURLDifferences(utf16String(u"http://\u2132"),
+ {"", "", "", "", 0, "", "", "", utf16String(u"http://Ⅎ")},
+ {"http", "", "", "xn--f3g", 0, "/", "", "", "http://xn--f3g/"});
+ checkURLDifferences(utf16String(u"http://\u05D9\u05B4\u05D5\u05D0\u05B8/"),
+ {"http", "", "", "xn--cdbi5etas", 0, "/", "", "", "http://xn--cdbi5etas/"},
+ {"", "", "", "", 0, "", "", "", "about:blank"}, TestTabs::No);
+ checkURLDifferences(utf16String(u"http://bidirectional\u0786\u07AE\u0782\u07B0\u0795\u07A9\u0793\u07A6\u0783\u07AA/"),
+ {"", "", "", "", 0, "", "", "", utf16String(u"http://bidirectionalކޮންޕީޓަރު/")},
+ {"", "", "", "", 0, "", "", "", "about:blank"}, TestTabs::No);
+ checkURLDifferences(utf16String(u"http://contextj\u200D"),
+ {"", "", "", "", 0, "", "", "", utf16String(u"http://contextj\u200D")},
+ {"http", "", "", "contextj", 0, "/", "", "", "http://contextj/"});
+ checkURL(utf16String(u"http://contexto\u30FB"), {"http", "", "", "xn--contexto-wg5g", 0, "/", "", "", "http://xn--contexto-wg5g/"});
+ checkURLDifferences(utf16String(u"http://\u321D\u321E/"),
+ {"http", "", "", "xn--()()-bs0sc174agx4b", 0, "/", "", "", "http://xn--()()-bs0sc174agx4b/"},
+ {"http", "", "", "xn--5mkc", 0, "/", "", "", "http://xn--5mkc/"});
+}
+
+TEST_F(URLParserTest, DefaultPort)
+{
+ checkURL("FtP://host:21/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
+ checkURL("ftp://host:21/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
+ checkURL("f\ttp://host:21/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
+ checkURL("f\ttp://host\t:21/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
+ checkURL("f\ttp://host:\t21/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
+ checkURL("f\ttp://host:2\t1/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
+ checkURL("f\ttp://host:21\t/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
+ checkURL("ftp://host\t:21/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
+ checkURL("ftp://host:\t21/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
+ checkURL("ftp://host:2\t1/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
+ checkURL("ftp://host:21\t/", {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"});
+ checkURL("ftp://host:22/", {"ftp", "", "", "host", 22, "/", "", "", "ftp://host:22/"});
+ checkURLDifferences("ftp://host:21",
+ {"ftp", "", "", "host", 0, "/", "", "", "ftp://host/"},
+ {"ftp", "", "", "host", 0, "", "", "", "ftp://host"});
+ checkURLDifferences("ftp://host:22",
+ {"ftp", "", "", "host", 22, "/", "", "", "ftp://host:22/"},
+ {"ftp", "", "", "host", 22, "", "", "", "ftp://host:22"});
+
+ checkURL("gOpHeR://host:70/", {"gopher", "", "", "host", 0, "/", "", "", "gopher://host/"});
+ checkURL("gopher://host:70/", {"gopher", "", "", "host", 0, "/", "", "", "gopher://host/"});
+ checkURL("gopher://host:71/", {"gopher", "", "", "host", 71, "/", "", "", "gopher://host:71/"});
+ // Spec, Chrome, Firefox, and URLParser have "/", URL::parse does not.
+ // Spec, Chrome, URLParser, URL::parse recognize gopher default port, Firefox does not.
+ checkURLDifferences("gopher://host:70",
+ {"gopher", "", "", "host", 0, "/", "", "", "gopher://host/"},
+ {"gopher", "", "", "host", 0, "", "", "", "gopher://host"});
+ checkURLDifferences("gopher://host:71",
+ {"gopher", "", "", "host", 71, "/", "", "", "gopher://host:71/"},
+ {"gopher", "", "", "host", 71, "", "", "", "gopher://host:71"});
+
+ checkURL("hTtP://host:80", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
+ checkURL("http://host:80", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
+ checkURL("http://host:80/", {"http", "", "", "host", 0, "/", "", "", "http://host/"});
+ checkURL("http://host:81", {"http", "", "", "host", 81, "/", "", "", "http://host:81/"});
+ checkURL("http://host:81/", {"http", "", "", "host", 81, "/", "", "", "http://host:81/"});
+
+ checkURL("hTtPs://host:443", {"https", "", "", "host", 0, "/", "", "", "https://host/"});
+ checkURL("https://host:443", {"https", "", "", "host", 0, "/", "", "", "https://host/"});
+ checkURL("https://host:443/", {"https", "", "", "host", 0, "/", "", "", "https://host/"});
+ checkURL("https://host:444", {"https", "", "", "host", 444, "/", "", "", "https://host:444/"});
+ checkURL("https://host:444/", {"https", "", "", "host", 444, "/", "", "", "https://host:444/"});
+
+ checkURL("wS://host:80/", {"ws", "", "", "host", 0, "/", "", "", "ws://host/"});
+ checkURL("ws://host:80/", {"ws", "", "", "host", 0, "/", "", "", "ws://host/"});
+ checkURL("ws://host:81/", {"ws", "", "", "host", 81, "/", "", "", "ws://host:81/"});
+ // URLParser matches Chrome and Firefox, but not URL::parse
+ checkURLDifferences("ws://host:80",
+ {"ws", "", "", "host", 0, "/", "", "", "ws://host/"},
+ {"ws", "", "", "host", 0, "", "", "", "ws://host"});
+ checkURLDifferences("ws://host:81",
+ {"ws", "", "", "host", 81, "/", "", "", "ws://host:81/"},
+ {"ws", "", "", "host", 81, "", "", "", "ws://host:81"});
+
+ checkURL("WsS://host:443/", {"wss", "", "", "host", 0, "/", "", "", "wss://host/"});
+ checkURL("wss://host:443/", {"wss", "", "", "host", 0, "/", "", "", "wss://host/"});
+ checkURL("wss://host:444/", {"wss", "", "", "host", 444, "/", "", "", "wss://host:444/"});
+ // URLParser matches Chrome and Firefox, but not URL::parse
+ checkURLDifferences("wss://host:443",
+ {"wss", "", "", "host", 0, "/", "", "", "wss://host/"},
+ {"wss", "", "", "host", 0, "", "", "", "wss://host"});
+ checkURLDifferences("wss://host:444",
+ {"wss", "", "", "host", 444, "/", "", "", "wss://host:444/"},
+ {"wss", "", "", "host", 444, "", "", "", "wss://host:444"});
+
+ checkURL("fTpS://host:990/", {"ftps", "", "", "host", 990, "/", "", "", "ftps://host:990/"});
+ checkURL("ftps://host:990/", {"ftps", "", "", "host", 990, "/", "", "", "ftps://host:990/"});
+ checkURL("ftps://host:991/", {"ftps", "", "", "host", 991, "/", "", "", "ftps://host:991/"});
+ checkURL("ftps://host:990", {"ftps", "", "", "host", 990, "", "", "", "ftps://host:990"});
+ checkURL("ftps://host:991", {"ftps", "", "", "host", 991, "", "", "", "ftps://host:991"});
+
+ checkURL("uNkNoWn://host:80/", {"unknown", "", "", "host", 80, "/", "", "", "unknown://host:80/"});
+ checkURL("unknown://host:80/", {"unknown", "", "", "host", 80, "/", "", "", "unknown://host:80/"});
+ checkURL("unknown://host:81/", {"unknown", "", "", "host", 81, "/", "", "", "unknown://host:81/"});
+ checkURL("unknown://host:80", {"unknown", "", "", "host", 80, "", "", "", "unknown://host:80"});
+ checkURL("unknown://host:81", {"unknown", "", "", "host", 81, "", "", "", "unknown://host:81"});
+
+ checkURL("file://host:0", {"file", "", "", "host", 0, "/", "", "", "file://host:0/"});
+ checkURL("file://host:80", {"file", "", "", "host", 80, "/", "", "", "file://host:80/"});
+ checkURL("file://host:80/path", {"file", "", "", "host", 80, "/path", "", "", "file://host:80/path"});
+ checkURLDifferences("file://:80/path",
+ {"", "", "", "", 0, "", "", "", "file://:80/path"},
+ {"file", "", "", "", 80, "/path", "", "", "file://:80/path"});
+ checkURLDifferences("file://:0/path",
+ {"", "", "", "", 0, "", "", "", "file://:0/path"},
+ {"file", "", "", "", 0, "/path", "", "", "file://:0/path"});
+}
+
+TEST_F(URLParserTest, ParserFailures)
+{
+ shouldFail(" ");
+ shouldFail(" \a ");
+ shouldFail("");
+ shouldFail(String());
+ shouldFail("", "about:blank");
+ shouldFail(String(), "about:blank");
+ shouldFail("http://127.0.0.1:abc");
+ shouldFail("http://host:abc");
+ shouldFail("http://:abc");
+ shouldFail("http://a:@", "about:blank");
+ shouldFail("http://:b@", "about:blank");
+ shouldFail("http://:@", "about:blank");
+ shouldFail("http://a:@");
+ shouldFail("http://:b@");
+ shouldFail("http://@");
+ shouldFail("http://[0:f::f:f:0:0]:abc");
+ shouldFail("../i", "sc:sd");
+ shouldFail("../i", "sc:sd/sd");
+ shouldFail("/i", "sc:sd");
+ shouldFail("/i", "sc:sd/sd");
+ shouldFail("?i", "sc:sd");
+ shouldFail("?i", "sc:sd/sd");
+ shouldFail("http://example example.com", "http://other.com/");
+ shouldFail("http://[www.example.com]/", "about:blank");
+ shouldFail("http://192.168.0.1 hello", "http://other.com/");
+ shouldFail("http://[example.com]", "http://other.com/");
+ shouldFail("i", "sc:sd");
+ shouldFail("i", "sc:sd/sd");
+ shouldFail("i");
+ shouldFail("asdf");
+ shouldFail("~");
+ shouldFail("%");
+ shouldFail("//%");
+ shouldFail("~", "about:blank");
+ shouldFail("~~~");
+ shouldFail("://:0/");
+ shouldFail("://:0/", "");
+ shouldFail("://:0/", "about:blank");
+ shouldFail("about~");
+ shouldFail("//C:asdf/foo/bar", "file:///tmp/mock/path");
+ shouldFail("http://[1234::ab#]");
+ shouldFail("http://[1234::ab/]");
+ shouldFail("http://[1234::ab?]");
+ shouldFail("http://[1234::ab@]");
+ shouldFail("http://[1234::ab~]");
+ shouldFail("http://[2001::1");
+ shouldFail("http://4:b\xE1");
+ shouldFail("http://[1:2:3:4:5:6:7:8~]/");
+ shouldFail("http://[a:b:c:d:e:f:g:127.0.0.1]");
+ shouldFail("http://[a:b:c:d:e:f:g:h:127.0.0.1]");
+ shouldFail("http://[a:b:c:d:e:f:127.0.0.0x11]"); // Chrome treats this as hex, Firefox and the spec fail
+ shouldFail("http://[a:b:c:d:e:f:127.0.-0.1]");
+ shouldFail("asdf://space In\aHost");
+ shouldFail("asdf://[0:0:0:0:a:b:c:d");
+}
+
+// These are in the spec but not in the web platform tests.
+TEST_F(URLParserTest, AdditionalTests)
+{
+ checkURL("about:\a\aabc", {"about", "", "", "", 0, "%07%07abc", "", "", "about:%07%07abc"});
+ checkURL("notspecial:\t\t\n\t", {"notspecial", "", "", "", 0, "", "", "", "notspecial:"});
+ checkURL("notspecial\t\t\n\t:\t\t\n\t/\t\t\n\t/\t\t\n\thost", {"notspecial", "", "", "host", 0, "", "", "", "notspecial://host"});
+ checkRelativeURL("http:", "http://example.org/foo/bar?query#fragment", {"http", "", "", "example.org", 0, "/foo/bar", "query", "", "http://example.org/foo/bar?query"});
+ checkRelativeURLDifferences("ws:", "http://example.org/foo/bar",
+ {"ws", "", "", "", 0, "", "", "", "ws:"},
+ {"ws", "", "", "", 0, "s:", "", "", "ws:s:"});
+ checkRelativeURL("notspecial:", "http://example.org/foo/bar", {"notspecial", "", "", "", 0, "", "", "", "notspecial:"});
+
+ const wchar_t surrogateBegin = 0xD800;
+ const wchar_t validSurrogateEnd = 0xDD55;
+ const wchar_t invalidSurrogateEnd = 'A';
+ checkURL(utf16String<12>({'h', 't', 't', 'p', ':', '/', '/', 'w', '/', surrogateBegin, validSurrogateEnd, '\0'}),
+ {"http", "", "", "w", 0, "/%F0%90%85%95", "", "", "http://w/%F0%90%85%95"}, testTabsValueForSurrogatePairs);
+
+ // URLParser matches Chrome and Firefox but not URL::parse.
+ checkURLDifferences(utf16String<12>({'h', 't', 't', 'p', ':', '/', '/', 'w', '/', surrogateBegin, invalidSurrogateEnd}),
+ {"http", "", "", "w", 0, "/%EF%BF%BDA", "", "", "http://w/%EF%BF%BDA"},
+ {"http", "", "", "w", 0, "/%ED%A0%80A", "", "", "http://w/%ED%A0%80A"});
+ checkURLDifferences(utf16String<13>({'h', 't', 't', 'p', ':', '/', '/', 'w', '/', '?', surrogateBegin, invalidSurrogateEnd, '\0'}),
+ {"http", "", "", "w", 0, "/", "%EF%BF%BDA", "", "http://w/?%EF%BF%BDA"},
+ {"http", "", "", "w", 0, "/", "%ED%A0%80A", "", "http://w/?%ED%A0%80A"});
+ checkURLDifferences(utf16String<11>({'h', 't', 't', 'p', ':', '/', '/', 'w', '/', surrogateBegin, '\0'}),
+ {"http", "", "", "w", 0, "/%EF%BF%BD", "", "", "http://w/%EF%BF%BD"},
+ {"http", "", "", "w", 0, "/%ED%A0%80", "", "", "http://w/%ED%A0%80"});
+ checkURLDifferences(utf16String<12>({'h', 't', 't', 'p', ':', '/', '/', 'w', '/', '?', surrogateBegin, '\0'}),
+ {"http", "", "", "w", 0, "/", "%EF%BF%BD", "", "http://w/?%EF%BF%BD"},
+ {"http", "", "", "w", 0, "/", "%ED%A0%80", "", "http://w/?%ED%A0%80"});
+ checkURLDifferences(utf16String<13>({'h', 't', 't', 'p', ':', '/', '/', 'w', '/', '?', surrogateBegin, ' ', '\0'}),
+ {"http", "", "", "w", 0, "/", "%EF%BF%BD", "", "http://w/?%EF%BF%BD"},
+ {"http", "", "", "w", 0, "/", "%ED%A0%80", "", "http://w/?%ED%A0%80"});
+
+ // FIXME: Write more invalid surrogate pair tests based on feedback from https://bugs.webkit.org/show_bug.cgi?id=162105
+}
+
+TEST_F(URLParserTest, QueryEncoding)
+{
+ checkURL(utf16String(u"http://host?ß😍#ß😍"), UTF8Encoding(), {"http", "", "", "host", 0, "/", "%C3%9F%F0%9F%98%8D", "%C3%9F%F0%9F%98%8D", utf16String(u"http://host/?%C3%9F%F0%9F%98%8D#%C3%9F%F0%9F%98%8D")}, testTabsValueForSurrogatePairs);
+
+ TextEncoding latin1(String("latin1"));
+ checkURL("http://host/?query with%20spaces", latin1, {"http", "", "", "host", 0, "/", "query%20with%20spaces", "", "http://host/?query%20with%20spaces"});
+ checkURL("http://host/?query", latin1, {"http", "", "", "host", 0, "/", "query", "", "http://host/?query"});
+ checkURL("http://host/?\tquery", latin1, {"http", "", "", "host", 0, "/", "query", "", "http://host/?query"});
+ checkURL("http://host/?q\tuery", latin1, {"http", "", "", "host", 0, "/", "query", "", "http://host/?query"});
+ checkURL("http://host/?query with SpAcEs#fragment", latin1, {"http", "", "", "host", 0, "/", "query%20with%20SpAcEs", "fragment", "http://host/?query%20with%20SpAcEs#fragment"});
+ checkURL("http://host/?que\rry\t\r\n#fragment", latin1, {"http", "", "", "host", 0, "/", "query", "fragment", "http://host/?query#fragment"});
+
+ TextEncoding unrecognized(String("unrecognized invalid encoding name"));
+ checkURL("http://host/?query", unrecognized, {"http", "", "", "host", 0, "/", "", "", "http://host/?"});
+ checkURL("http://host/?", unrecognized, {"http", "", "", "host", 0, "/", "", "", "http://host/?"});
+
+ TextEncoding iso88591(String("ISO-8859-1"));
+ String withUmlauts = utf16String<4>({0xDC, 0x430, 0x451, '\0'});
+ checkURL(makeString("ws://host/path?", withUmlauts), iso88591, {"ws", "", "", "host", 0, "/path", "%C3%9C%D0%B0%D1%91", "", "ws://host/path?%C3%9C%D0%B0%D1%91"});
+ checkURL(makeString("wss://host/path?", withUmlauts), iso88591, {"wss", "", "", "host", 0, "/path", "%C3%9C%D0%B0%D1%91", "", "wss://host/path?%C3%9C%D0%B0%D1%91"});
+ checkURL(makeString("asdf://host/path?", withUmlauts), iso88591, {"asdf", "", "", "host", 0, "/path", "%C3%9C%D0%B0%D1%91", "", "asdf://host/path?%C3%9C%D0%B0%D1%91"});
+ checkURL(makeString("https://host/path?", withUmlauts), iso88591, {"https", "", "", "host", 0, "/path", "%DC%26%231072%3B%26%231105%3B", "", "https://host/path?%DC%26%231072%3B%26%231105%3B"});
+ checkURL(makeString("gopher://host/path?", withUmlauts), iso88591, {"gopher", "", "", "host", 0, "/path", "%DC%26%231072%3B%26%231105%3B", "", "gopher://host/path?%DC%26%231072%3B%26%231105%3B"});
+ checkURL(makeString("/path?", withUmlauts, "#fragment"), "ws://example.com/", iso88591, {"ws", "", "", "example.com", 0, "/path", "%C3%9C%D0%B0%D1%91", "fragment", "ws://example.com/path?%C3%9C%D0%B0%D1%91#fragment"});
+ checkURL(makeString("/path?", withUmlauts, "#fragment"), "wss://example.com/", iso88591, {"wss", "", "", "example.com", 0, "/path", "%C3%9C%D0%B0%D1%91", "fragment", "wss://example.com/path?%C3%9C%D0%B0%D1%91#fragment"});
+ checkURL(makeString("/path?", withUmlauts, "#fragment"), "asdf://example.com/", iso88591, {"asdf", "", "", "example.com", 0, "/path", "%C3%9C%D0%B0%D1%91", "fragment", "asdf://example.com/path?%C3%9C%D0%B0%D1%91#fragment"});
+ checkURL(makeString("/path?", withUmlauts, "#fragment"), "https://example.com/", iso88591, {"https", "", "", "example.com", 0, "/path", "%DC%26%231072%3B%26%231105%3B", "fragment", "https://example.com/path?%DC%26%231072%3B%26%231105%3B#fragment"});
+ checkURL(makeString("/path?", withUmlauts, "#fragment"), "gopher://example.com/", iso88591, {"gopher", "", "", "example.com", 0, "/path", "%DC%26%231072%3B%26%231105%3B", "fragment", "gopher://example.com/path?%DC%26%231072%3B%26%231105%3B#fragment"});
+ checkURL(makeString("gopher://host/path?", withUmlauts, "#fragment"), "asdf://example.com/?doesntmatter", iso88591, {"gopher", "", "", "host", 0, "/path", "%DC%26%231072%3B%26%231105%3B", "fragment", "gopher://host/path?%DC%26%231072%3B%26%231105%3B#fragment"});
+ checkURL(makeString("asdf://host/path?", withUmlauts, "#fragment"), "http://example.com/?doesntmatter", iso88591, {"asdf", "", "", "host", 0, "/path", "%C3%9C%D0%B0%D1%91", "fragment", "asdf://host/path?%C3%9C%D0%B0%D1%91#fragment"});
+
+ checkURL("http://host/?query=foo'bar", UTF8Encoding(), {"http", "", "", "host", 0, "/", "query=foo%27bar", "", "http://host/?query=foo%27bar"});
+ // FIXME: Add more tests with other encodings and things like non-ascii characters, emoji and unmatched surrogate pairs.
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/UserAgentQuirks.cpp b/Tools/TestWebKitAPI/Tests/WebCore/UserAgentQuirks.cpp
new file mode 100644
index 000000000..7fff8e361
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/UserAgentQuirks.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#include <WebCore/URL.h>
+#include <WebCore/UserAgent.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+static void assertUserAgentForURLHasChromeBrowserQuirk(const char* url)
+{
+ String uaString = standardUserAgentForURL(URL(ParsedURLString, url));
+
+ EXPECT_TRUE(uaString.contains("Chrome"));
+ EXPECT_TRUE(uaString.contains("Safari"));
+ EXPECT_FALSE(uaString.contains("Chromium"));
+ EXPECT_FALSE(uaString.contains("Firefox"));
+}
+
+static void assertUserAgentForURLHasLinuxPlatformQuirk(const char* url)
+{
+ String uaString = standardUserAgentForURL(URL(ParsedURLString, url));
+
+ EXPECT_TRUE(uaString.contains("Linux"));
+ EXPECT_FALSE(uaString.contains("Macintosh"));
+ EXPECT_FALSE(uaString.contains("Mac OS X"));
+ EXPECT_FALSE(uaString.contains("Windows"));
+ EXPECT_FALSE(uaString.contains("Chrome"));
+ EXPECT_FALSE(uaString.contains("FreeBSD"));
+}
+
+static void assertUserAgentForURLHasMacPlatformQuirk(const char* url)
+{
+ String uaString = standardUserAgentForURL(URL(ParsedURLString, url));
+
+ EXPECT_TRUE(uaString.contains("Macintosh"));
+ EXPECT_TRUE(uaString.contains("Mac OS X"));
+ EXPECT_FALSE(uaString.contains("Linux"));
+ EXPECT_FALSE(uaString.contains("Windows"));
+ EXPECT_FALSE(uaString.contains("Chrome"));
+ EXPECT_FALSE(uaString.contains("FreeBSD"));
+}
+
+TEST(UserAgentTest, Quirks)
+{
+ // A site with not quirks should return a null String.
+ String uaString = standardUserAgentForURL(URL(ParsedURLString, "http://www.webkit.org/"));
+ EXPECT_TRUE(uaString.isNull());
+
+#if !OS(LINUX) || !CPU(X86_64)
+ // Google quirk should not affect sites with similar domains.
+ uaString = standardUserAgentForURL(URL(ParsedURLString, "http://www.googleblog.com/"));
+ EXPECT_FALSE(uaString.contains("Linux x86_64"));
+#endif
+
+ assertUserAgentForURLHasChromeBrowserQuirk("http://typekit.com/");
+ assertUserAgentForURLHasChromeBrowserQuirk("http://typekit.net/");
+
+ assertUserAgentForURLHasLinuxPlatformQuirk("http://www.google.com/");
+ assertUserAgentForURLHasLinuxPlatformQuirk("http://www.google.es/");
+ assertUserAgentForURLHasLinuxPlatformQuirk("http://calendar.google.com/");
+ assertUserAgentForURLHasLinuxPlatformQuirk("http://plus.google.com/");
+
+ assertUserAgentForURLHasMacPlatformQuirk("http://www.yahoo.com/");
+ assertUserAgentForURLHasMacPlatformQuirk("http://finance.yahoo.com/");
+ assertUserAgentForURLHasMacPlatformQuirk("http://intl.taobao.com/");
+ assertUserAgentForURLHasMacPlatformQuirk("http://www.whatsapp.com/");
+ assertUserAgentForURLHasMacPlatformQuirk("http://web.whatsapp.com/");
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/YouTubePluginReplacement.cpp b/Tools/TestWebKitAPI/Tests/WebCore/YouTubePluginReplacement.cpp
new file mode 100644
index 000000000..76b103575
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebCore/YouTubePluginReplacement.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+#include <WebCore/URL.h>
+#include <WebCore/YouTubePluginReplacement.h>
+#include <wtf/MainThread.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+class YouTubePluginReplacementTest : public testing::Test {
+public:
+ void SetUp() final {
+ WTF::initializeMainThread();
+ }
+};
+
+static bool test(const String& inputURLString, const String& expectedURLString)
+{
+ URL inputURL(URL(), inputURLString);
+ String actualURLString = YouTubePluginReplacement::youTubeURLFromAbsoluteURL(inputURL, inputURLString);
+ return actualURLString.utf8() == expectedURLString.utf8();
+}
+
+TEST_F(YouTubePluginReplacementTest, YouTubeURLFromAbsoluteURL)
+{
+ // YouTube non-video URL, not expected to be transformed.
+ EXPECT_TRUE(test("https://www.youtube.com", "https://www.youtube.com"));
+
+ // Basic YouTube video links, expected to be transformed.
+ EXPECT_TRUE(test("https://www.youtube.com/v/dQw4w9WgXcQ", "https://www.youtube.com/embed/dQw4w9WgXcQ"));
+ EXPECT_TRUE(test("http://www.youtube.com/v/dQw4w9WgXcQ", "http://www.youtube.com/embed/dQw4w9WgXcQ"));
+ EXPECT_TRUE(test("https://youtube.com/v/dQw4w9WgXcQ", "https://youtube.com/embed/dQw4w9WgXcQ"));
+ EXPECT_TRUE(test("http://youtube.com/v/dQw4w9WgXcQ", "http://youtube.com/embed/dQw4w9WgXcQ"));
+
+ // With start time, preserved.
+ EXPECT_TRUE(test("http://www.youtube.com/v/dQw4w9WgXcQ?start=4", "http://www.youtube.com/embed/dQw4w9WgXcQ?start=4"));
+ EXPECT_TRUE(test("http://www.youtube.com/v/dQw4w9WgXcQ?start=4&fs=1", "http://www.youtube.com/embed/dQw4w9WgXcQ?start=4&fs=1"));
+
+ // With an invalid query (see & instead of ?), we preserve and fix the query.
+ EXPECT_TRUE(test("http://www.youtube.com/v/dQw4w9WgXcQ&start=4", "http://www.youtube.com/embed/dQw4w9WgXcQ?start=4"));
+ EXPECT_TRUE(test("http://www.youtube.com/v/dQw4w9WgXcQ&start=4&fs=1", "http://www.youtube.com/embed/dQw4w9WgXcQ?start=4&fs=1"));
+
+ // Non-Flash URL is untouched.
+ EXPECT_TRUE(test("https://www.youtube.com/embed/dQw4w9WgXcQ", "https://www.youtube.com/embed/dQw4w9WgXcQ"));
+ EXPECT_TRUE(test("http://www.youtube.com/embed/dQw4w9WgXcQ", "http://www.youtube.com/embed/dQw4w9WgXcQ"));
+ EXPECT_TRUE(test("https://youtube.com/embed/dQw4w9WgXcQ", "https://youtube.com/embed/dQw4w9WgXcQ"));
+ EXPECT_TRUE(test("http://youtube.com/embed/dQw4w9WgXcQ", "http://youtube.com/embed/dQw4w9WgXcQ"));
+ // Even with extra parameters.
+ EXPECT_TRUE(test("https://www.youtube.com/embed/dQw4w9WgXcQ?start=4", "https://www.youtube.com/embed/dQw4w9WgXcQ?start=4"));
+ EXPECT_TRUE(test("http://www.youtube.com/embed/dQw4w9WgXcQ?enablejsapi=1", "http://www.youtube.com/embed/dQw4w9WgXcQ?enablejsapi=1"));
+ // Even with an invalid "query".
+ EXPECT_TRUE(test("https://www.youtube.com/embed/dQw4w9WgXcQ&start=4", "https://www.youtube.com/embed/dQw4w9WgXcQ&start=4"));
+
+ // Don't transform anything with a non "/v/" path component immediately following the domain.
+ EXPECT_TRUE(test("https://www.youtube.com/something/v/dQw4w9WgXcQ", "https://www.youtube.com/something/v/dQw4w9WgXcQ"));
+
+ // Non-YouTube domain whose path looks like a Flash video shouldn't be transformed.
+ EXPECT_TRUE(test("https://www.notyoutube.com/v/dQw4w9WgXcQ", "https://www.notyoutube.com/v/dQw4w9WgXcQ"));
+}
+
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/gtk/UserAgentQuirks.cpp b/Tools/TestWebKitAPI/Tests/WebCore/gtk/UserAgentQuirks.cpp
deleted file mode 100644
index 40305e801..000000000
--- a/Tools/TestWebKitAPI/Tests/WebCore/gtk/UserAgentQuirks.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2014 Igalia S.L.
- *
- * 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. 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 INC. 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.
- */
-
-#include "config.h"
-
-#include <WebCore/URL.h>
-#include <WebCore/UserAgentGtk.h>
-
-using namespace WebCore;
-
-namespace TestWebKitAPI {
-
-TEST(WebCore, UserAgentQuirksTest)
-{
- // A site with not quirks should return a null String.
- String uaString = standardUserAgentForURL(URL(ParsedURLString, "http://www.webkit.org/"));
- EXPECT_TRUE(uaString.isNull());
-
- // www.yahoo.com requires MAC OS platform in the UA.
- uaString = standardUserAgentForURL(URL(ParsedURLString, "http://www.yahoo.com/"));
- EXPECT_TRUE(uaString.contains("Macintosh"));
- EXPECT_TRUE(uaString.contains("Mac OS X"));
- EXPECT_FALSE(uaString.contains("Linux"));
-
- // For Google domains we always return the standard UA.
- uaString = standardUserAgent();
- EXPECT_FALSE(uaString.isNull());
- EXPECT_TRUE(uaString == standardUserAgentForURL(URL(ParsedURLString, "http://www.google.com/")));
- EXPECT_TRUE(uaString == standardUserAgentForURL(URL(ParsedURLString, "http://calendar.google.com/")));
- EXPECT_TRUE(uaString == standardUserAgentForURL(URL(ParsedURLString, "http://gmail.com/")));
- EXPECT_TRUE(uaString == standardUserAgentForURL(URL(ParsedURLString, "http://www.google.com.br/")));
- EXPECT_TRUE(uaString == standardUserAgentForURL(URL(ParsedURLString, "http://www.youtube.com/")));
- EXPECT_TRUE(uaString != standardUserAgentForURL(URL(ParsedURLString, "http://www.google.uk.not.com.br/")));
-
- // For Google Maps we remove the Version/8.0 string.
- uaString = standardUserAgentForURL(URL(ParsedURLString, "http://maps.google.com/"));
- EXPECT_TRUE(uaString == standardUserAgentForURL(URL(ParsedURLString, "http://www.google.com/maps/")));
- EXPECT_FALSE(uaString.contains("Version/8.0 Safari/"));
-}
-
-} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/18-characters.html b/Tools/TestWebKitAPI/Tests/WebKit2/18-characters.html
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/18-characters.html
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/AboutBlankLoad.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/AboutBlankLoad.cpp
index 0a2f00ca5..5503edd9e 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/AboutBlankLoad.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/AboutBlankLoad.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
@@ -57,3 +60,5 @@ TEST(WebKit2, AboutBlankLoad)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/Ahem.ttf b/Tools/TestWebKitAPI/Tests/WebKit2/Ahem.ttf
new file mode 100644
index 000000000..ac81cb031
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/Ahem.ttf
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest.cpp
index 4c0c77963..a1d09f2cd 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKContextPrivate.h>
+#include <WebKit/WKContextPrivate.h>
namespace TestWebKitAPI {
@@ -71,3 +74,5 @@ TEST(WebKit2, CanHandleRequest)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest_Bundle.cpp
index 5f66b537a..590615e8c 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CanHandleRequest_Bundle.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundlePage.h>
+#include <WebKit/WKBundlePage.h>
namespace TestWebKitAPI {
@@ -65,3 +68,5 @@ void CanHandleRequestTest::didReceiveMessage(WKBundleRef bundle, WKStringRef mes
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CloseFromWithinCreatePage.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/CloseFromWithinCreatePage.cpp
new file mode 100644
index 000000000..fabfd2d80
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CloseFromWithinCreatePage.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2014-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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include <WebKit/WKPreferencesRefPrivate.h>
+
+namespace TestWebKitAPI {
+
+static bool testDone;
+static std::unique_ptr<PlatformWebView> openedWebView;
+
+static void runJavaScriptAlert(WKPageRef page, WKStringRef alertText, WKFrameRef frame, WKSecurityOriginRef, const void* clientInfo)
+{
+ // FIXME: Check that the alert text matches the storage.
+ testDone = true;
+}
+
+static WKPageRef createNewPage(WKPageRef page, WKURLRequestRef urlRequest, WKDictionaryRef features, WKEventModifiers modifiers, WKEventMouseButton mouseButton, const void *clientInfo)
+{
+ EXPECT_TRUE(openedWebView == nullptr);
+
+ openedWebView = std::make_unique<PlatformWebView>(page);
+
+ WKPageUIClientV5 uiClient;
+ memset(&uiClient, 0, sizeof(uiClient));
+
+ uiClient.base.version = 5;
+ uiClient.runJavaScriptAlert = runJavaScriptAlert;
+ WKPageSetPageUIClient(openedWebView->page(), &uiClient.base);
+
+ WKPageClose(page);
+
+ WKRetain(openedWebView->page());
+ return openedWebView->page();
+}
+
+TEST(WebKit2, CloseFromWithinCreatePage)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+
+ PlatformWebView webView(context.get());
+
+ WKPageUIClientV5 uiClient;
+ memset(&uiClient, 0, sizeof(uiClient));
+
+ uiClient.base.version = 5;
+ uiClient.createNewPage = createNewPage;
+ uiClient.runJavaScriptAlert = runJavaScriptAlert;
+ WKPageSetPageUIClient(webView.page(), &uiClient.base);
+
+ // Allow file URLs to load non-file resources
+ WKRetainPtr<WKPreferencesRef> preferences(AdoptWK, WKPreferencesCreate());
+ WKPageGroupRef pageGroup = WKPageGetPageGroup(webView.page());
+ WKPreferencesSetUniversalAccessFromFileURLsAllowed(preferences.get(), true);
+ WKPageGroupSetPreferences(pageGroup, preferences.get());
+
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("close-from-within-create-page", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+
+ Util::run(&testDone);
+
+ openedWebView = nullptr;
+}
+
+}
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CloseThenTerminate.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/CloseThenTerminate.cpp
index ff70511f4..71239e4f0 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/CloseThenTerminate.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CloseThenTerminate.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
@@ -62,3 +65,5 @@ TEST(WebKit2, CloseThenTerminate)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CookieManager.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/CookieManager.cpp
index 2f17b8162..d231e0e75 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/CookieManager.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CookieManager.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKCookieManager.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKCookieManager.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -86,3 +89,5 @@ TEST(WebKit2, CookieManager)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewIsActiveSetIsActive.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewIsActiveSetIsActive.cpp
new file mode 100644
index 000000000..ef9625b99
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewIsActiveSetIsActive.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT HOLDERS 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.
+ */
+
+#include "config.h"
+#include "PlatformUtilities.h"
+#include "Test.h"
+
+#include <WebKit/WKContext.h>
+#include <WebKit/WKPage.h>
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKView.h>
+
+namespace TestWebKitAPI {
+
+static bool didWebProcessCrash = false;
+static bool didWebProcessRelaunch = false;
+static bool didFinishLoad = false;
+
+static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef, const void*)
+{
+ didFinishLoad = true;
+}
+
+static void webProcessCrashed(WKViewRef view, WKURLRef, const void*)
+{
+ // WebProcess crashed, so at this point the view should not be active.
+ ASSERT_FALSE(WKViewIsActive(view));
+ didWebProcessCrash = true;
+}
+
+static void webProcessRelaunched(WKViewRef view, const void*)
+{
+ // WebProcess just relaunched, so at this point the view should not be active.
+ ASSERT_FALSE(WKViewIsActive(view));
+
+ didWebProcessRelaunch = true;
+}
+
+TEST(WebKit2, WKViewIsActiveSetIsActive)
+{
+ WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
+ WKRetainPtr<WKViewRef> view = adoptWK(WKViewCreate(context.get(), 0));
+
+ WKViewInitialize(view.get());
+
+ // At this point we should have an active view.
+ ASSERT_TRUE(WKViewIsActive(view.get()));
+
+ // Now we are going to play with its active state a few times.
+ WKViewSetIsActive(view.get(), true);
+ ASSERT_TRUE(WKViewIsActive(view.get()));
+
+ WKViewSetIsActive(view.get(), false);
+ ASSERT_FALSE(WKViewIsActive(view.get()));
+
+ WKViewSetIsActive(view.get(), false);
+ ASSERT_FALSE(WKViewIsActive(view.get()));
+
+ WKViewSetIsActive(view.get(), true);
+ ASSERT_TRUE(WKViewIsActive(view.get()));
+}
+
+TEST(WebKit2, WKViewIsActive)
+{
+ WKRetainPtr<WKContextRef> context = adoptWK(Util::createContextForInjectedBundleTest("WKViewIsActiveSetIsActiveTest"));
+ WKRetainPtr<WKViewRef> view = adoptWK(WKViewCreate(context.get(), 0));
+
+ WKViewClientV0 viewClient;
+ memset(&viewClient, 0, sizeof(WKViewClientV0));
+ viewClient.base.version = 0;
+ viewClient.webProcessCrashed = webProcessCrashed;
+ viewClient.webProcessDidRelaunch = webProcessRelaunched;
+ WKViewSetViewClient(view.get(), &viewClient.base);
+
+ WKViewInitialize(view.get());
+
+ // At this point we should have an active view.
+ ASSERT_TRUE(WKViewIsActive(view.get()));
+
+ WKPageLoaderClientV3 pageLoaderClient;
+ memset(&pageLoaderClient, 0, sizeof(WKPageLoaderClient));
+ pageLoaderClient.base.version = 3;
+ pageLoaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+ WKPageSetPageLoaderClient(WKViewGetPage(view.get()), &pageLoaderClient.base);
+
+ const WKSize size = WKSizeMake(100, 100);
+ WKViewSetSize(view.get(), size);
+
+ didFinishLoad = false;
+ didWebProcessCrash = false;
+ didWebProcessRelaunch = false;
+
+ WKRetainPtr<WKURLRef> simpleUrl = adoptWK(Util::createURLForResource("../WebKit/simple", "html"));
+ WKPageLoadURL(WKViewGetPage(view.get()), simpleUrl.get());
+ Util::run(&didFinishLoad);
+ didFinishLoad = false;
+
+ WKContextPostMessageToInjectedBundle(context.get(), Util::toWK("Crash").get(), 0);
+ Util::run(&didWebProcessCrash);
+ ASSERT_TRUE(didWebProcessCrash);
+
+ WKPageLoadURL(WKViewGetPage(view.get()), simpleUrl.get());
+ Util::run(&didFinishLoad);
+
+ ASSERT_TRUE(didWebProcessRelaunch);
+ ASSERT_TRUE(didFinishLoad);
+}
+
+} // TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewIsActiveSetIsActive_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewIsActiveSetIsActive_Bundle.cpp
new file mode 100644
index 000000000..a3cb1b6de
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewIsActiveSetIsActive_Bundle.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT HOLDERS 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.
+ */
+
+#include "config.h"
+#include "InjectedBundleTest.h"
+#include <WebKit/WKRetainPtr.h>
+
+#include <cstdlib>
+
+namespace TestWebKitAPI {
+
+class WKViewIsActiveSetIsActiveTest : public InjectedBundleTest {
+public:
+ WKViewIsActiveSetIsActiveTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+ {
+ }
+
+ virtual void didReceiveMessage(WKBundleRef bundle, WKStringRef messageName, WKTypeRef messageBody)
+ {
+ if (!WKStringIsEqualToUTF8CString(messageName, "Crash"))
+ return;
+ abort();
+ }
+};
+
+static InjectedBundleTest::Register<WKViewIsActiveSetIsActiveTest> registrar("WKViewIsActiveSetIsActiveTest");
+
+} // namespace TestWebKitAPI
+
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewRestoreZoomAndScrollBackForward.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewRestoreZoomAndScrollBackForward.cpp
new file mode 100644
index 000000000..5c556ecee
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewRestoreZoomAndScrollBackForward.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2012-2013 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2011 Samsung Electronics. 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT HOLDERS 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.
+ */
+
+#include "config.h"
+
+#include "ewk_view_private.h"
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include <WebKit/WKContext.h>
+#include <WebKit/WKRetainPtr.h>
+#include "Test.h"
+
+namespace TestWebKitAPI {
+
+static bool finishedLoad = false;
+static bool scroll = false;
+
+static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef, const void*)
+{
+ finishedLoad = true;
+}
+
+static void didChangeContentsPosition(WKViewRef, WKPoint p, const void*)
+{
+ scroll = true;
+}
+
+TEST(WebKit2, WKViewRestoreZoomAndScrollBackForward)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+ PlatformWebView webView(context.get());
+ WKRetainPtr<WKViewRef> view = EWKViewGetWKView(webView.platformView());
+
+ WKPageSetUseFixedLayout(webView.page(), true);
+
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+ loaderClient.base.version = 0;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+ WKPageSetPageLoaderClient(webView.page(), &loaderClient.base);
+
+ WKViewClientV0 viewClient;
+ memset(&viewClient, 0, sizeof(viewClient));
+ viewClient.base.version = 0;
+ viewClient.didChangeContentsPosition = didChangeContentsPosition;
+ WKViewSetViewClient(view.get(), &viewClient.base);
+
+ // Load first page.
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("CoordinatedGraphics/backforward1", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+ Util::run(&finishedLoad);
+
+ // Change scale and position on first page.
+ float firstPageScale = 2.0;
+ WKPoint firstPageScrollPosition = WKPointMake(10, 350); // Scroll position of first page.
+ WKViewSetContentPosition(view.get(), firstPageScrollPosition);
+ WKViewSetContentScaleFactor(view.get(), firstPageScale);
+ float currentPageScale = WKViewGetContentScaleFactor(view.get());
+ WKPoint currentPagePosition = WKViewGetContentPosition(view.get());
+ Util::run(&scroll);
+ EXPECT_EQ(firstPageScale, currentPageScale);
+ EXPECT_EQ(firstPageScrollPosition.x, currentPagePosition.x);
+ EXPECT_EQ(firstPageScrollPosition.y, currentPagePosition.y);
+
+ // Load second page.
+ finishedLoad = false;
+ url = adoptWK(Util::createURLForResource("CoordinatedGraphics/backforward2", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+ Util::run(&finishedLoad);
+
+ // Check if second page scale and position is correct.
+ currentPageScale = WKViewGetContentScaleFactor(view.get());
+ currentPagePosition = WKViewGetContentPosition(view.get());
+ EXPECT_EQ(1, currentPageScale);
+ EXPECT_EQ(0, currentPagePosition.x);
+ EXPECT_EQ(0, currentPagePosition.y);
+
+ // Go back first page.
+ scroll = false;
+ finishedLoad = false;
+ WKPageGoBack(webView.page());
+ Util::run(&finishedLoad);
+ Util::run(&scroll);
+
+ // Check if scroll position and scale of first page are restored correctly.
+ currentPageScale = WKViewGetContentScaleFactor(view.get());
+ currentPagePosition = WKViewGetContentPosition(view.get());
+ EXPECT_EQ(firstPageScale, currentPageScale);
+ EXPECT_EQ(firstPageScrollPosition.x, currentPagePosition.x);
+ EXPECT_EQ(firstPageScrollPosition.y, currentPagePosition.y);
+
+ // Go to second page again.
+ WKPageGoForward(webView.page());
+ scroll = false;
+ finishedLoad = false;
+ Util::run(&finishedLoad);
+
+ // Check if the scroll position and scale of second page are restored correctly.
+ currentPageScale = WKViewGetContentScaleFactor(view.get());
+ currentPagePosition = WKViewGetContentPosition(view.get());
+ EXPECT_EQ(1, currentPageScale);
+ EXPECT_EQ(0, currentPagePosition.x);
+ EXPECT_EQ(0, currentPagePosition.y);
+}
+
+} // TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewUserViewportToContents.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewUserViewportToContents.cpp
new file mode 100644
index 000000000..e6465480c
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewUserViewportToContents.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT HOLDERS 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.
+ */
+
+#include "config.h"
+
+#include "WebKit/WKView.h"
+#include "WebKit/WKRetainPtr.h"
+
+namespace TestWebKitAPI {
+
+TEST(WebKit2, DISABLED_WKViewUserViewportToContents)
+{
+ // This test creates a WKView and uses the WKViewUserViewportToContents
+ // function to convert viewport coordinates to contents (page) coordinates.
+ // It scrolls and scales around the contents and check if the coordinates
+ // conversion math is right.
+
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+ WKRetainPtr<WKPageConfigurationRef> configuration(AdoptWK, WKPageConfigurationCreate());
+ WKPageConfigurationSetContext(configuration.get(), context.get());
+
+ WKRetainPtr<WKViewRef> webView(AdoptWK, WKViewCreate(configuration.get()));
+
+ WKViewSetIsActive(webView.get(), true);
+ WKPageSetUseFixedLayout(WKViewGetPage(webView.get()), false);
+
+ WKPoint out;
+
+ // At scale 1.0 the viewport and contents coordinates should match.
+
+ WKViewSetContentScaleFactor(webView.get(), 1.0);
+ WKViewSetContentPosition(webView.get(), WKPointMake(0, 0));
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
+ EXPECT_EQ(out.x, 0);
+ EXPECT_EQ(out.y, 0);
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
+ EXPECT_EQ(out.x, 10);
+ EXPECT_EQ(out.y, 10);
+
+ WKViewSetContentPosition(webView.get(), WKPointMake(20, 20));
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
+ EXPECT_EQ(out.x, 20);
+ EXPECT_EQ(out.y, 20);
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
+ EXPECT_EQ(out.x, 30);
+ EXPECT_EQ(out.y, 30);
+
+ // At scale 2.0 the viewport distance values will be half
+ // the ones seem in the contents.
+
+ WKViewSetContentScaleFactor(webView.get(), 2.0);
+ WKViewSetContentPosition(webView.get(), WKPointMake(0, 0));
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
+ EXPECT_EQ(out.x, 0);
+ EXPECT_EQ(out.y, 0);
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
+ EXPECT_EQ(out.x, 5);
+ EXPECT_EQ(out.y, 5);
+
+ WKViewSetContentPosition(webView.get(), WKPointMake(20, 20));
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
+ EXPECT_EQ(out.x, 20);
+ EXPECT_EQ(out.y, 20);
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
+ EXPECT_EQ(out.x, 25);
+ EXPECT_EQ(out.y, 25);
+
+ // At scale 0.5 the viewport distance values will be twice
+ // the ones seem in the contents.
+
+ WKViewSetContentScaleFactor(webView.get(), 0.5);
+ WKViewSetContentPosition(webView.get(), WKPointMake(0, 0));
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
+ EXPECT_EQ(out.x, 0);
+ EXPECT_EQ(out.y, 0);
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
+ EXPECT_EQ(out.x, 20);
+ EXPECT_EQ(out.y, 20);
+
+ WKViewSetContentPosition(webView.get(), WKPointMake(20, 20));
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
+ EXPECT_EQ(out.x, 20);
+ EXPECT_EQ(out.y, 20);
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
+ EXPECT_EQ(out.x, 40);
+ EXPECT_EQ(out.y, 40);
+
+ // Let's add translation to the viewport.
+
+ const int delta = 10;
+ WKViewSetUserViewportTranslation(webView.get(), delta, delta);
+
+ WKViewSetContentPosition(webView.get(), WKPointMake(0, 0));
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
+ EXPECT_EQ(out.x, 0 - delta / 0.5);
+ EXPECT_EQ(out.y, 0 - delta / 0.5);
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
+ EXPECT_EQ(out.x, 20 - delta / 0.5);
+ EXPECT_EQ(out.y, 20 - delta / 0.5);
+
+ WKViewSetContentPosition(webView.get(), WKPointMake(20, 20));
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(0, 0));
+ EXPECT_EQ(out.x, 20 - delta / 0.5);
+ EXPECT_EQ(out.y, 20 - delta / 0.5);
+
+ out = WKViewUserViewportToContents(webView.get(), WKPointMake(10, 10));
+ EXPECT_EQ(out.x, 40 - delta / 0.5);
+ EXPECT_EQ(out.y, 40 - delta / 0.5);
+}
+
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/backforward1.html b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/backforward1.html
new file mode 100644
index 000000000..98c1c107c
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/backforward1.html
@@ -0,0 +1,5 @@
+<html>
+<body style="width:100%; height:100%">
+ <div style="position: absolute; top: 0; left: 0; width: 900px; height: 1200px;"></div>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/backforward2.html b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/backforward2.html
new file mode 100644
index 000000000..3806b9d32
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/backforward2.html
@@ -0,0 +1 @@
+<body style="width:100%; height:100%"/>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic.cpp
index 06abe884b..c336652ac 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
#include <wtf/Vector.h>
namespace TestWebKitAPI {
@@ -133,3 +136,5 @@ TEST(WebKit2, DISABLED_DOMWindowExtensionBasic)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic_Bundle.cpp
index 5c946625a..9bdc683ba 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionBasic_Bundle.cpp
@@ -24,14 +24,17 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
-#include <WebKit2/WKBundleDOMWindowExtension.h>
-#include <WebKit2/WKBundleFrame.h>
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundlePageGroup.h>
-#include <WebKit2/WKBundlePrivate.h>
-#include <WebKit2/WKBundleScriptWorld.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKBundleDOMWindowExtension.h>
+#include <WebKit/WKBundleFrame.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundlePageGroup.h>
+#include <WebKit/WKBundlePrivate.h>
+#include <WebKit/WKBundleScriptWorld.h>
+#include <WebKit/WKRetainPtr.h>
#include <wtf/HashMap.h>
#include <assert.h>
@@ -257,3 +260,5 @@ static void willDestroyGlobalObjectForDOMWindowExtensionCallback(WKBundlePageRef
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache.cpp
index c5f6104f6..56a069fb9 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
@@ -132,3 +135,5 @@ TEST(WebKit2, DISABLED_DOMWindowExtensionNoCache)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache_Bundle.cpp
index 680c17288..e48dadd1e 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DOMWindowExtensionNoCache_Bundle.cpp
@@ -24,14 +24,17 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
-#include <WebKit2/WKBundleDOMWindowExtension.h>
-#include <WebKit2/WKBundleFrame.h>
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundlePageGroup.h>
-#include <WebKit2/WKBundlePrivate.h>
-#include <WebKit2/WKBundleScriptWorld.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKBundleDOMWindowExtension.h>
+#include <WebKit/WKBundleFrame.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundlePageGroup.h>
+#include <WebKit/WKBundlePrivate.h>
+#include <WebKit/WKBundleScriptWorld.h>
+#include <WebKit/WKRetainPtr.h>
#include <wtf/HashMap.h>
#include <assert.h>
@@ -276,3 +279,5 @@ static void willDestroyGlobalObjectForDOMWindowExtensionCallback(WKBundlePageRef
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls.cpp
index a78b8867f..a930f5346 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
@@ -83,3 +86,5 @@ TEST(WebKit2, DidAssociateFormControls)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls_Bundle.cpp
index fd373d282..4e30eee5f 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DidAssociateFormControls_Bundle.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundle.h>
-#include <WebKit2/WKBundlePage.h>
+#include <WebKit/WKBundle.h>
+#include <WebKit/WKBundlePage.h>
namespace TestWebKitAPI {
@@ -36,7 +39,7 @@ class DidAssociateFormControlsTest : public InjectedBundleTest {
public:
DidAssociateFormControlsTest(const std::string& identifier);
- virtual void didCreatePage(WKBundleRef, WKBundlePageRef) override;
+ void didCreatePage(WKBundleRef, WKBundlePageRef) override;
};
static InjectedBundleTest::Register<DidAssociateFormControlsTest> registrar("DidAssociateFormControlsTest");
@@ -54,7 +57,7 @@ static void didAssociateFormControls(WKBundlePageRef page, WKArrayRef elementHan
WKRetainPtr<WKUInt64Ref> numberOfElements = adoptWK(WKUInt64Create(WKArrayGetSize(elementHandles)));
WKDictionarySetItem(messageBody.get(), Util::toWK("NumberOfControls").get(), numberOfElements.get());
- WKBundlePostMessage(InjectedBundleController::shared().bundle(), Util::toWK("DidReceiveDidAssociateFormControls").get(), messageBody.get());
+ WKBundlePostMessage(InjectedBundleController::singleton().bundle(), Util::toWK("DidReceiveDidAssociateFormControls").get(), messageBody.get());
}
DidAssociateFormControlsTest::DidAssociateFormControlsTest(const std::string& identifier)
@@ -76,3 +79,5 @@ void DidAssociateFormControlsTest::didCreatePage(WKBundleRef bundle, WKBundlePag
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DidNotHandleKeyDown.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DidNotHandleKeyDown.cpp
index e0c5cb0d8..b5f4fb863 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/DidNotHandleKeyDown.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DidNotHandleKeyDown.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "JavaScriptTest.h"
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -76,3 +79,5 @@ TEST(WebKit2, DidNotHandleKeyDown)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DidRemoveFrameFromHiearchyInPageCache.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DidRemoveFrameFromHiearchyInPageCache.cpp
new file mode 100644
index 000000000..2a6f5da0a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DidRemoveFrameFromHiearchyInPageCache.cpp
@@ -0,0 +1,109 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+
+#include <WebKit/WKString.h>
+
+namespace TestWebKitAPI {
+
+static bool finished = false;
+static int didRemoveFrameFromHierarchyCount;
+
+static void didFinishLoadForFrame(WKPageRef, WKFrameRef frame, WKTypeRef, const void*)
+{
+ // Only mark finished when the main frame loads
+ if (!WKFrameIsMainFrame(frame))
+ return;
+
+ finished = true;
+}
+
+static void setPageLoaderClient(WKPageRef page)
+{
+ WKPageLoaderClientV1 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+
+ loaderClient.base.version = 1;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+
+ WKPageSetPageLoaderClient(page, &loaderClient.base);
+}
+
+static void didReceivePageMessageFromInjectedBundle(WKPageRef, WKStringRef messageName, WKTypeRef, const void*)
+{
+ if (WKStringIsEqualToUTF8CString(messageName, "DidRemoveFrameFromHierarchy"))
+ ++didRemoveFrameFromHierarchyCount;
+}
+
+static void setInjectedBundleClient(WKPageRef page)
+{
+ WKPageInjectedBundleClientV0 injectedBundleClient = {
+ { 0, nullptr },
+ didReceivePageMessageFromInjectedBundle,
+ nullptr,
+ };
+ WKPageSetPageInjectedBundleClient(page, &injectedBundleClient.base);
+}
+
+TEST(WebKit2, DidRemoveFrameFromHiearchyInPageCache)
+{
+ WKRetainPtr<WKContextRef> context = adoptWK(Util::createContextForInjectedBundleTest("DidRemoveFrameFromHiearchyInPageCache"));
+ // Enable the page cache so we can test the WKBundlePageDidRemoveFrameFromHierarchyCallback API
+ WKContextSetCacheModel(context.get(), kWKCacheModelPrimaryWebBrowser);
+
+ PlatformWebView webView(context.get());
+ setPageLoaderClient(webView.page());
+ setInjectedBundleClient(webView.page());
+
+ finished = false;
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("many-iframes", "html")).get());
+ Util::run(&finished);
+
+ // Perform a couple of loads so "many-iframes" gets kicked out of the PageCache.
+ finished = false;
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("simple", "html")).get());
+ Util::run(&finished);
+
+ finished = false;
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("simple2", "html")).get());
+ Util::run(&finished);
+
+ finished = false;
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("simple3", "html")).get());
+ Util::run(&finished);
+
+ EXPECT_EQ(didRemoveFrameFromHierarchyCount, 10);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DidRemoveFrameFromHiearchyInPageCache_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DidRemoveFrameFromHiearchyInPageCache_Bundle.cpp
new file mode 100644
index 000000000..712b3fb06
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DidRemoveFrameFromHiearchyInPageCache_Bundle.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "InjectedBundleTest.h"
+
+#include "PlatformUtilities.h"
+#include <WebKit/WKBundlePage.h>
+
+namespace TestWebKitAPI {
+
+class DidRemoveFrameFromHiearchyInPageCacheTest : public InjectedBundleTest {
+public:
+ DidRemoveFrameFromHiearchyInPageCacheTest(const std::string& identifier);
+
+ virtual void didCreatePage(WKBundleRef, WKBundlePageRef);
+};
+
+static InjectedBundleTest::Register<DidRemoveFrameFromHiearchyInPageCacheTest> registrar("DidRemoveFrameFromHiearchyInPageCache");
+
+static unsigned didRemoveFrameFromHierarchyCount;
+
+void didRemoveFrameFromHierarchyCallback(WKBundlePageRef page, WKBundleFrameRef, WKTypeRef*, const void*)
+{
+ didRemoveFrameFromHierarchyCount++;
+
+ WKRetainPtr<WKStringRef> message(AdoptWK, WKStringCreateWithUTF8CString("DidRemoveFrameFromHierarchy"));
+ WKBundlePagePostMessage(page, message.get(), message.get());
+}
+
+DidRemoveFrameFromHiearchyInPageCacheTest::DidRemoveFrameFromHiearchyInPageCacheTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+{
+}
+
+void DidRemoveFrameFromHiearchyInPageCacheTest::didCreatePage(WKBundleRef bundle, WKBundlePageRef page)
+{
+ WKBundlePageLoaderClientV8 pageLoaderClient;
+ memset(&pageLoaderClient, 0, sizeof(pageLoaderClient));
+
+ pageLoaderClient.base.version = 8;
+ pageLoaderClient.base.clientInfo = this;
+ pageLoaderClient.didRemoveFrameFromHierarchy = didRemoveFrameFromHierarchyCallback;
+
+ WKBundlePageSetPageLoaderClient(page, &pageLoaderClient.base);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash.cpp
index efdcd56a7..21bca74dd 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -65,3 +68,5 @@ TEST(WebKit2, DocumentStartUserScriptAlertCrashTest)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash_Bundle.cpp
index 30805f759..18b9f1b48 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DocumentStartUserScriptAlertCrash_Bundle.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
-#include <WebKit2/WKBundlePageGroup.h>
-#include <WebKit2/WKBundlePrivate.h>
-#include <WebKit2/WKBundleScriptWorld.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKBundlePageGroup.h>
+#include <WebKit/WKBundlePrivate.h>
+#include <WebKit/WKBundleScriptWorld.h>
+#include <WebKit/WKRetainPtr.h>
#include <assert.h>
namespace TestWebKitAPI {
@@ -53,3 +56,5 @@ public:
static InjectedBundleTest::Register<DocumentStartUserScriptAlertCrashTest> registrar("DocumentStartUserScriptAlertCrashTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/DownloadDecideDestinationCrash.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/DownloadDecideDestinationCrash.cpp
index aaead72dd..eac36d87a 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/DownloadDecideDestinationCrash.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/DownloadDecideDestinationCrash.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKDownload.h>
+#include <WebKit/WKDownload.h>
namespace TestWebKitAPI {
@@ -41,7 +44,7 @@ static WKStringRef decideDestinationWithSuggestedFilename(WKContextRef, WKDownlo
{
didDecideDestination = true;
WKDownloadCancel(download);
- return Util::toWK("does not matter").leakRef();
+ return Util::toWK("/tmp/WebKitAPITest/DownloadDecideDestinationCrash").leakRef();
}
static void setContextDownloadClient(WKContextRef context)
@@ -83,3 +86,5 @@ TEST(WebKit2, DownloadDecideDestinationCrash)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/EnumerateMediaDevices.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/EnumerateMediaDevices.cpp
new file mode 100644
index 000000000..0ac7d0fe1
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/EnumerateMediaDevices.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#if ENABLE(MEDIA_STREAM)
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <WebKit/WKPreferencesRef.h>
+#include <WebKit/WKPreferencesRefPrivate.h>
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKUserMediaPermissionCheck.h>
+#include <string.h>
+#include <vector>
+
+namespace TestWebKitAPI {
+
+static bool loadedFirstTime;
+static bool loadedSecondTime;
+
+void checkUserMediaPermissionCallback(WKPageRef, WKFrameRef, WKSecurityOriginRef, WKSecurityOriginRef, WKUserMediaPermissionCheckRef permissionRequest, const void*)
+{
+ WKUserMediaPermissionCheckSetUserMediaAccessInfo(permissionRequest, WKStringCreateWithUTF8CString("0x123456789"), true);
+ if (!loadedFirstTime) {
+ loadedFirstTime = true;
+ return;
+ }
+
+ loadedSecondTime = true;
+}
+
+TEST(WebKit2, EnumerateDevices)
+{
+ auto context = adoptWK(WKContextCreate());
+
+ WKRetainPtr<WKPageGroupRef> pageGroup(AdoptWK, WKPageGroupCreateWithIdentifier(Util::toWK("EnumerateDevices").get()));
+ WKPreferencesRef preferences = WKPageGroupGetPreferences(pageGroup.get());
+ WKPreferencesSetMediaStreamEnabled(preferences, true);
+ WKPreferencesSetFileAccessFromFileURLsAllowed(preferences, true);
+ WKPreferencesSetMediaCaptureRequiresSecureConnection(preferences, false);
+
+ WKPageUIClientV6 uiClient;
+ memset(&uiClient, 0, sizeof(uiClient));
+ uiClient.base.version = 6;
+ uiClient.checkUserMediaPermissionForOrigin = checkUserMediaPermissionCallback;
+
+ PlatformWebView webView(context.get(), pageGroup.get());
+ WKPageSetPageUIClient(webView.page(), &uiClient.base);
+
+ auto url = adoptWK(Util::createURLForResource("enumerateMediaDevices", "html"));
+
+ // Load and kill the page.
+ WKPageLoadURL(webView.page(), url.get());
+ Util::run(&loadedFirstTime);
+ WKPageTerminate(webView.page());
+
+ // Load it again to make sure the user media process manager doesn't assert.
+ WKPageLoadURL(webView.page(), url.get());
+ Util::run(&loadedSecondTime);
+}
+
+} // namespace TestWebKitAPI
+
+#endif // ENABLE(MEDIA_STREAM)
+
+#endif // WK_HAVE_C_SPI
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/EphemeralSessionPushStateNoHistoryCallback.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/EphemeralSessionPushStateNoHistoryCallback.cpp
new file mode 100644
index 000000000..64b666ab4
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/EphemeralSessionPushStateNoHistoryCallback.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKWebsiteDataStoreRef.h>
+
+namespace TestWebKitAPI {
+
+static bool testDone;
+
+static void didNavigateWithNavigationData(WKContextRef context, WKPageRef page, WKNavigationDataRef navigationData, WKFrameRef frame, const void* clientInfo)
+{
+ // This should never be called when navigating in Private Browsing.
+ FAIL();
+}
+
+static void didSameDocumentNavigationForFrame(WKPageRef page, WKFrameRef frame, WKSameDocumentNavigationType type, WKTypeRef userData, const void *clientInfo)
+{
+ testDone = true;
+}
+
+TEST(WebKit2, EphemeralSessionPushStateNoHistoryCallback)
+{
+ auto configuration = adoptWK(WKPageConfigurationCreate());
+
+ auto context = adoptWK(WKContextCreate());
+ WKPageConfigurationSetContext(configuration.get(), context.get());
+
+ auto websiteDataStore = adoptWK(WKWebsiteDataStoreCreateNonPersistentDataStore());
+ WKPageConfigurationSetWebsiteDataStore(configuration.get(), websiteDataStore.get());
+
+ WKContextHistoryClientV0 historyClient;
+ memset(&historyClient, 0, sizeof(historyClient));
+
+ historyClient.base.version = 0;
+ historyClient.didNavigateWithNavigationData = didNavigateWithNavigationData;
+
+ WKContextSetHistoryClient(context.get(), &historyClient.base);
+
+ PlatformWebView webView(configuration.get());
+
+ WKPageLoaderClientV0 pageLoaderClient;
+ memset(&pageLoaderClient, 0, sizeof(pageLoaderClient));
+
+ pageLoaderClient.base.version = 0;
+ pageLoaderClient.didSameDocumentNavigationForFrame = didSameDocumentNavigationForFrame;
+
+ WKPageSetPageLoaderClient(webView.page(), &pageLoaderClient.base);
+
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("push-state", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+
+ Util::run(&testDone);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/EvaluateJavaScript.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/EvaluateJavaScript.cpp
index 90ad04fd1..a6b5a4dd5 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/EvaluateJavaScript.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/EvaluateJavaScript.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
-#include <WebKit2/WKSerializedScriptValue.h>
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKSerializedScriptValue.h>
namespace TestWebKitAPI {
@@ -58,3 +61,5 @@ TEST(WebKit2, EvaluateJavaScriptThatThrowsAnException)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/EventModifiers.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/EventModifiers.cpp
new file mode 100644
index 000000000..d2cc644e1
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/EventModifiers.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2017 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "JavaScriptTest.h"
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+
+namespace TestWebKitAPI {
+
+static bool didFinishLoad { false };
+static bool mouseMoveCallbackFinished { false };
+
+static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef, const void*)
+{
+ didFinishLoad = true;
+}
+
+static void mouseDidMoveOverElement(WKPageRef, WKHitTestResultRef, WKEventModifiers modifiers, WKTypeRef, const void*)
+{
+ EXPECT_EQ(modifiers, kWKEventModifiersControlKey);
+ mouseMoveCallbackFinished = true;
+}
+
+static void setClients(WKPageRef page)
+{
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+ loaderClient.base.version = 0;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+ WKPageSetPageLoaderClient(page, &loaderClient.base);
+
+ WKPageUIClientV1 uiClient;
+ memset(&uiClient, 0, sizeof(uiClient));
+ uiClient.base.version = 1;
+ uiClient.mouseDidMoveOverElement = mouseDidMoveOverElement;
+ WKPageSetPageUIClient(page, &uiClient.base);
+}
+
+TEST(WebKit2, EventModifiers)
+{
+ WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
+
+ PlatformWebView webView(context.get());
+ setClients(webView.page());
+
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("simple", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+ Util::run(&didFinishLoad);
+
+ webView.simulateMouseMove(10, 10, kWKEventModifiersControlKey);
+ Util::run(&mouseMoveCallbackFinished);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/FailedLoad.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/FailedLoad.cpp
index ac8d6a39d..c12b5366b 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/FailedLoad.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/FailedLoad.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -65,3 +68,5 @@ TEST(WebKit2, FailedLoad)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/Find.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/Find.cpp
index 41b52eacd..2e2189906 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/Find.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/Find.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -79,3 +82,5 @@ TEST(WebKit2, Find)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ForceRepaint.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ForceRepaint.cpp
index 86c6754a2..6cd63fab4 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ForceRepaint.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ForceRepaint.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -67,3 +70,5 @@ TEST(WebKit2, ForceRepaint)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/FrameHandle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/FrameHandle.cpp
new file mode 100644
index 000000000..1e3281d89
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/FrameHandle.cpp
@@ -0,0 +1,70 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <WebKit/WKFrameHandleRef.h>
+#include <WebKit/WKFrameInfoRef.h>
+#include <WebKit/WKRetainPtr.h>
+
+namespace TestWebKitAPI {
+
+static bool done;
+
+static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo)
+{
+ done = true;
+}
+
+TEST(WebKit2, FrameHandle)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+ PlatformWebView webView(context.get());
+
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+ loaderClient.base.version = 0;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+ WKPageSetPageLoaderClient(webView.page(), &loaderClient.base);
+
+ WKPageLoadURL(webView.page(), adoptWK(WKURLCreateWithUTF8CString("about:blank")).get());
+ Util::run(&done);
+
+ auto frame = WKPageGetMainFrame(webView.page());
+ auto frameInfo = adoptWK(WKFrameCreateFrameInfo(frame));
+ auto handleFromInfo = WKFrameInfoGetFrameHandleRef(frameInfo.get());
+ auto handleFromFrame = adoptWK(WKFrameCreateFrameHandle(frame));
+
+ EXPECT_EQ(WKFrameHandleGetFrameID(handleFromInfo), WKFrameHandleGetFrameID(handleFromFrame.get()));
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypeHTML.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypeHTML.cpp
index 093a5747b..2c9c11332 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypeHTML.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypeHTML.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -75,3 +78,5 @@ TEST(WebKit2, FrameMIMETypeHTML)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypePNG.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypePNG.cpp
index edaa7cada..eb3bf38a3 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypePNG.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/FrameMIMETypePNG.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -74,3 +77,5 @@ TEST(WebKit2, FrameMIMETypePNG)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/Geolocation.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/Geolocation.cpp
index bf7a93726..90fd37937 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/Geolocation.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/Geolocation.cpp
@@ -24,10 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKContextPrivate.h>
+#include <WebKit/WKRetainPtr.h>
#include <string.h>
#include <vector>
@@ -103,7 +107,7 @@ void decidePolicyForGeolocationPermissionRequestCallBack(WKPageRef page, WKFrame
void setupGeolocationProvider(WKContextRef context, void *clientInfo)
{
WKGeolocationProviderV1 providerCallback;
- memset(&providerCallback, 0, sizeof(WKGeolocationProvider));
+ memset(&providerCallback, 0, sizeof(WKGeolocationProviderV1));
providerCallback.base.version = 1;
providerCallback.base.clientInfo = clientInfo;
@@ -209,14 +213,9 @@ TEST(WebKit2, GeolocationBasicWithHighAccuracy)
// Geolocation start without High Accuracy, then requires High Accuracy.
struct GeolocationTransitionToHighAccuracyStateTracker : GeolocationStateTracker {
- bool finishedFirstStep;
- bool finished;
-
- GeolocationTransitionToHighAccuracyStateTracker()
- : finishedFirstStep(false)
- , finished(false)
- {
- }
+ bool finishedFirstStep { false };
+ bool enabledHighAccuracy { false };
+ bool finished { false };
virtual void eventsChanged()
{
@@ -230,11 +229,19 @@ struct GeolocationTransitionToHighAccuracyStateTracker : GeolocationStateTracker
break;
case 3:
EXPECT_EQ(GeolocationEvent::EnableHighAccuracy, events[2]);
+ enabledHighAccuracy = true;
+ break;
+ case 4:
+ EXPECT_EQ(GeolocationEvent::DisableHighAccuracy, events[3]);
+ break;
+ case 5:
+ EXPECT_EQ(GeolocationEvent::StopUpdating, events[4]);
finished = true;
break;
default:
EXPECT_TRUE(false);
finishedFirstStep = true;
+ enabledHighAccuracy = true;
finished = true;
}
}
@@ -243,6 +250,7 @@ struct GeolocationTransitionToHighAccuracyStateTracker : GeolocationStateTracker
TEST(WebKit2, GeolocationTransitionToHighAccuracy)
{
WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+ WKContextSetMaximumNumberOfProcesses(context.get(), 1);
GeolocationTransitionToHighAccuracyStateTracker stateTracker;
setupGeolocationProvider(context.get(), &stateTracker);
@@ -257,19 +265,20 @@ TEST(WebKit2, GeolocationTransitionToHighAccuracy)
setupView(highAccuracyWebView);
WKRetainPtr<WKURLRef> highAccuracyURL(AdoptWK, Util::createURLForResource("geolocationWatchPositionWithHighAccuracy", "html"));
WKPageLoadURL(highAccuracyWebView.page(), highAccuracyURL.get());
+ Util::run(&stateTracker.enabledHighAccuracy);
+
+ WKRetainPtr<WKURLRef> resetUrl = adoptWK(WKURLCreateWithUTF8CString("about:blank"));
+ WKPageLoadURL(highAccuracyWebView.page(), resetUrl.get());
+ Util::run(&stateTracker.enabledHighAccuracy);
+ WKPageLoadURL(lowAccuracyWebView.page(), resetUrl.get());
Util::run(&stateTracker.finished);
}
// Geolocation start with High Accuracy, then should fall back to low accuracy.
struct GeolocationTransitionToLowAccuracyStateTracker : GeolocationStateTracker {
- bool finishedFirstStep;
- bool finished;
-
- GeolocationTransitionToLowAccuracyStateTracker()
- : finishedFirstStep(false)
- , finished(false)
- {
- }
+ bool finishedFirstStep { false };
+ bool disabledHighAccuracy { false };
+ bool finished { false };
virtual void eventsChanged()
{
@@ -283,11 +292,16 @@ struct GeolocationTransitionToLowAccuracyStateTracker : GeolocationStateTracker
break;
case 3:
EXPECT_EQ(GeolocationEvent::DisableHighAccuracy, events[2]);
+ disabledHighAccuracy = true;
+ break;
+ case 4:
+ EXPECT_EQ(GeolocationEvent::StopUpdating, events[3]);
finished = true;
break;
default:
EXPECT_TRUE(false);
finishedFirstStep = true;
+ disabledHighAccuracy = true;
finished = true;
}
}
@@ -301,6 +315,7 @@ static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef us
TEST(WebKit2, GeolocationTransitionToLowAccuracy)
{
WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+ WKContextSetMaximumNumberOfProcesses(context.get(), 1);
GeolocationTransitionToLowAccuracyStateTracker stateTracker;
setupGeolocationProvider(context.get(), &stateTracker);
@@ -331,7 +346,11 @@ TEST(WebKit2, GeolocationTransitionToLowAccuracy)
WKRetainPtr<WKURLRef> resetUrl = adoptWK(WKURLCreateWithUTF8CString("about:blank"));
WKPageLoadURL(highAccuracyWebView.page(), resetUrl.get());
+ Util::run(&stateTracker.disabledHighAccuracy);
+ WKPageLoadURL(lowAccuracyWebView.page(), resetUrl.get());
Util::run(&stateTracker.finished);
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback.cpp
index fe898ffa8..e3280a3b7 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -65,3 +68,5 @@ TEST(WebKit2, GetInjectedBundleInitializationUserDataCallback)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback_Bundle.cpp
index 97500b59b..bf8da42e3 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/GetInjectedBundleInitializationUserDataCallback_Bundle.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -46,3 +49,5 @@ public:
static InjectedBundleTest::Register<GetInjectedBundleInitializationUserDataCallbackTest> registrar("GetInjectedBundleInitializationUserDataCallbackTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle.cpp
index 2f7c7deed..1f4a3726c 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -86,3 +89,5 @@ TEST(WebKit2, HitTestResultNodeHandle)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle_Bundle.cpp
index c6aaa1fec..d68ff2193 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/HitTestResultNodeHandle_Bundle.cpp
@@ -24,12 +24,15 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "InjectedBundleController.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundleHitTestResult.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundleHitTestResult.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -46,7 +49,7 @@ public:
if (!nodeHandle)
return;
- WKBundlePostMessage(InjectedBundleController::shared().bundle(), Util::toWK("HitTestResultNodeHandleTestDoneMessageName").get(), Util::toWK("HitTestResultNodeHandleTestDoneMessageBody").get());
+ WKBundlePostMessage(InjectedBundleController::singleton().bundle(), Util::toWK("HitTestResultNodeHandleTestDoneMessageName").get(), Util::toWK("HitTestResultNodeHandleTestDoneMessageBody").get());
}
virtual void didCreatePage(WKBundleRef bundle, WKBundlePageRef page)
@@ -64,3 +67,5 @@ public:
static InjectedBundleTest::Register<HitTestResultNodeHandleTest> registrar("HitTestResultNodeHandleTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic.cpp
index 1b3b3b7b6..a1d4046ed 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -77,3 +80,5 @@ TEST(WebKit2, InjectedBundleBasic)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic_Bundle.cpp
index 6a597be41..4d8689b93 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleBasic_Bundle.cpp
@@ -24,8 +24,11 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -47,3 +50,5 @@ public:
static InjectedBundleTest::Register<InjectedBundleBasicTest> registrar("InjectedBundleBasicTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest.cpp
index acc76c01e..e178dc3cb 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -66,3 +69,5 @@ TEST(WebKit2, InjectedBundleFrameHitTest)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest_Bundle.cpp
index 6ae018765..747858501 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleFrameHitTest_Bundle.cpp
@@ -24,13 +24,16 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundle.h>
-#include <WebKit2/WKBundleFramePrivate.h>
-#include <WebKit2/WKBundleHitTestResult.h>
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKBundle.h>
+#include <WebKit/WKBundleFramePrivate.h>
+#include <WebKit/WKBundleHitTestResult.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -41,7 +44,7 @@ public:
{
}
- virtual void didCreatePage(WKBundleRef, WKBundlePageRef) override;
+ void didCreatePage(WKBundleRef, WKBundlePageRef) override;
void frameLoadFinished(WKBundleFrameRef);
WKBundleRef m_bundle;
@@ -76,3 +79,5 @@ void InjectedBundleFrameHitTestTest::frameLoadFinished(WKBundleFrameRef frame)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins.cpp
index 407ecceb5..678aaa85b 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -67,3 +70,5 @@ TEST(WebKit2, InjectedBundleInitializationUserDataCallbackWins)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins_Bundle.cpp
index 36708a4d7..cac7738dd 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleInitializationUserDataCallbackWins_Bundle.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -46,3 +49,5 @@ public:
static InjectedBundleTest::Register<InjectedBundleInitializationUserDataCallbackWinsTest> registrar("InjectedBundleInitializationUserDataCallbackWinsTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleMakeAllShadowRootsOpen.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleMakeAllShadowRootsOpen.cpp
new file mode 100644
index 000000000..91fc88929
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleMakeAllShadowRootsOpen.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2010, 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <WebKit/WKRetainPtr.h>
+
+namespace TestWebKitAPI {
+
+static unsigned testNumber = 0;
+static bool done;
+
+static void runJavaScriptAlert(WKPageRef page, WKStringRef alertText, WKFrameRef frame, const void* clientInfo)
+{
+ ASSERT_NOT_NULL(frame);
+
+ EXPECT_EQ(page, WKFrameGetPage(frame));
+ switch (++testNumber) {
+ case 1:
+ EXPECT_WK_STREQ("PASS: shadowRoot created in injected bundle", alertText);
+ break;
+ case 2:
+ EXPECT_WK_STREQ("PASS: shadowRoot created by normal world", alertText);
+ break;
+ case 3:
+ EXPECT_WK_STREQ("PASS: collectMatchingElementsInFlatTree exists", alertText);
+ break;
+ case 4:
+ EXPECT_WK_STREQ("PASS: collectMatchingElementsInFlatTree was not present in the normal world", alertText);
+ break;
+ case 5:
+ EXPECT_WK_STREQ("Found:1,2,3,4,5,6", alertText);
+ break;
+ case 6:
+ EXPECT_WK_STREQ("Found:2,3,4", alertText);
+ break;
+ case 7:
+ EXPECT_WK_STREQ("PASS: matchingElementInFlatTree exists", alertText);
+ break;
+ case 8:
+ EXPECT_WK_STREQ("PASS: matchingElementInFlatTree was not present in the normal world", alertText);
+ break;
+ case 9:
+ EXPECT_WK_STREQ("Found:1", alertText);
+ break;
+ case 10:
+ EXPECT_WK_STREQ("Found:2", alertText);
+ break;
+ case 11:
+ EXPECT_WK_STREQ("Found:0 divs", alertText);
+ break;
+ case 12:
+ EXPECT_WK_STREQ("Found:false", alertText);
+ done = true;
+ break;
+ }
+}
+
+TEST(WebKit2, InjectedBundleMakeAllShadowRootOpenTest)
+{
+ WKRetainPtr<WKPageGroupRef> pageGroup(AdoptWK, WKPageGroupCreateWithIdentifier(WKStringCreateWithUTF8CString("InjectedBundleMakeAllShadowRootOpenTestPageGroup")));
+
+ WKRetainPtr<WKContextRef> context(AdoptWK, Util::createContextForInjectedBundleTest("InjectedBundleMakeAllShadowRootOpenTest", pageGroup.get()));
+ PlatformWebView webView(context.get(), pageGroup.get());
+
+ WKPageUIClientV0 uiClient;
+ memset(&uiClient, 0, sizeof(uiClient));
+
+ uiClient.base.version = 0;
+ uiClient.runJavaScriptAlert = runJavaScriptAlert;
+
+ WKPageSetPageUIClient(webView.page(), &uiClient.base);
+
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("closed-shadow-tree-test", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+
+ Util::run(&done);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleMakeAllShadowRootsOpen_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleMakeAllShadowRootsOpen_Bundle.cpp
new file mode 100644
index 000000000..ee5761993
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleMakeAllShadowRootsOpen_Bundle.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2010, 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "InjectedBundleTest.h"
+#include <WebKit/WKBundlePageGroup.h>
+#include <WebKit/WKBundlePrivate.h>
+#include <WebKit/WKBundleScriptWorld.h>
+#include <WebKit/WKRetainPtr.h>
+#include <assert.h>
+
+namespace TestWebKitAPI {
+
+class InjectedBundleMakeAllShadowRootOpenTest : public InjectedBundleTest {
+public:
+ InjectedBundleMakeAllShadowRootOpenTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+ { }
+
+ virtual void initialize(WKBundleRef bundle, WKTypeRef userData)
+ {
+ assert(WKGetTypeID(userData) == WKBundlePageGroupGetTypeID());
+ WKBundlePageGroupRef pageGroup = static_cast<WKBundlePageGroupRef>(userData);
+
+ auto world = WKBundleScriptWorldCreateWorld();
+ WKBundleScriptWorldMakeAllShadowRootsOpen(world);
+
+ WKRetainPtr<WKStringRef> source(AdoptWK, WKStringCreateWithUTF8CString(
+ "window.onload = function () {\n"
+ " const element = document.createElement('div');\n"
+ " const queryMethodName = 'collectMatchingElementsInFlatTree';\n"
+ " element.attachShadow({mode: 'closed'});\n"
+ // Test 1
+ " alert(element.shadowRoot ? 'PASS: shadowRoot created in injected bundle' : 'FAIL');\n"
+ // Test 2
+ " alert(document.querySelector('shadow-host').shadowRoot ? 'PASS: shadowRoot created by normal world' : 'FAIL');\n"
+ // Test 3
+ " alert(window[queryMethodName] ? `PASS: ${queryMethodName} exists` : `FAIL: ${queryMethodName} does not exist`);\n"
+ // Test 4
+ " document.dispatchEvent(new CustomEvent('testnormalworld', {detail: queryMethodName}));\n"
+ // Test 5
+ " const queryMethod = window[queryMethodName];\n"
+ " let queryResult = Array.from(queryMethod(document, 'span'));\n"
+ " alert('Found:' + queryResult.map((span) => span.textContent).join(','));\n"
+ // Test 6
+ " const innerHost = queryMethod(document, 'inner-host')[0];\n"
+ " queryResult = Array.from(queryMethod(innerHost, 'span'));\n"
+ " alert('Found:' + queryResult.map((span) => span.textContent).join(','));\n"
+ // Test 7
+ " alert(window.matchingElementInFlatTree ? `PASS: matchingElementInFlatTree exists` : `FAIL: matchingElementInFlatTree does not exist`);\n"
+ // Test 8
+ " document.dispatchEvent(new CustomEvent('testnormalworld', {detail: 'matchingElementInFlatTree'}));\n"
+ // Test 9
+ " queryResult = window.matchingElementInFlatTree(document, 'span');\n"
+ " alert('Found:' + (queryResult ? queryResult.textContent : 'null'));\n"
+ // Test 10
+ " queryResult = window.matchingElementInFlatTree(innerHost, 'span');\n"
+ " alert('Found:' + (queryResult ? queryResult.textContent : 'null'));\n"
+ // Test 11
+ " alert(`Found:${queryMethod(document, 'div').length} divs`);\n"
+ // Test 12
+ " queryResult = window.matchingElementInFlatTree(document, 'div');\n"
+ " alert(`Found:${!!queryResult}`);\n"
+ "}\n"));
+ WKBundleAddUserScript(bundle, pageGroup, world, source.get(), 0, 0, 0, kWKInjectAtDocumentStart, kWKInjectInAllFrames);
+ }
+};
+
+static InjectedBundleTest::Register<InjectedBundleMakeAllShadowRootOpenTest> registrar("InjectedBundleMakeAllShadowRootOpenTest");
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/LayoutMilestonesWithAllContentInFrame.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/LayoutMilestonesWithAllContentInFrame.cpp
index ef53f5e91..aa294643c 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/LayoutMilestonesWithAllContentInFrame.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/LayoutMilestonesWithAllContentInFrame.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKContextPrivate.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKContextPrivate.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -64,3 +67,5 @@ TEST(WebKit2, LayoutMilestonesWithAllContentInFrame)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/LimitTitleSize.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/LimitTitleSize.cpp
new file mode 100644
index 000000000..fde62c624
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/LimitTitleSize.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2017 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <WebKit/WKRetainPtr.h>
+
+namespace TestWebKitAPI {
+
+static bool waitUntilLongTitleReceived = false;
+static bool didFinishLoad = false;
+static size_t maxTitleLength = 4096;
+
+static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo)
+{
+ didFinishLoad = true;
+}
+
+static void didReceiveTitleForFrame(WKPageRef page, WKStringRef title, WKFrameRef, WKTypeRef, const void*)
+{
+ WKStringRef titleString = (WKStringRef)title;
+
+ if (WKStringIsEqualToUTF8CString(titleString, "Original Short Title"))
+ return;
+
+ EXPECT_LE(WKStringGetLength(titleString), maxTitleLength);
+ waitUntilLongTitleReceived = true;
+}
+
+TEST(WebKit2, LimitTitleSize)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+ PlatformWebView webView(context.get());
+
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+
+ loaderClient.base.version = 0;
+ loaderClient.didReceiveTitleForFrame = didReceiveTitleForFrame;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+
+ WKPageSetPageLoaderClient(webView.page(), &loaderClient.base);
+
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("set-long-title", "html"));
+
+ WKPageLoadURL(webView.page(), url.get());
+ Util::run(&waitUntilLongTitleReceived);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/LoadAlternateHTMLStringWithNonDirectoryURL.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/LoadAlternateHTMLStringWithNonDirectoryURL.cpp
index def60bcb9..acc23348b 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/LoadAlternateHTMLStringWithNonDirectoryURL.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/LoadAlternateHTMLStringWithNonDirectoryURL.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2015 Igalia S.L.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -24,13 +25,16 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "JavaScriptTest.h"
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKContext.h>
-#include <WebKit2/WKPage.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKContext.h>
+#include <WebKit/WKPage.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -41,7 +45,7 @@ static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef us
didFinishLoad = true;
}
-TEST(WebKit2, LoadAlternateHTMLStringWithNonDirectoryURL)
+static void loadAlternateHTMLString(WKURLRef baseURL, WKURLRef unreachableURL)
{
WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
PlatformWebView webView(context.get());
@@ -53,14 +57,29 @@ TEST(WebKit2, LoadAlternateHTMLStringWithNonDirectoryURL)
loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
WKPageSetPageLoaderClient(webView.page(), &loaderClient.base);
- WKRetainPtr<WKURLRef> fileURL(AdoptWK, Util::createURLForResource("simple", "html"));
WKRetainPtr<WKStringRef> alternateHTMLString(AdoptWK, WKStringCreateWithUTF8CString("<html><body><img src='icon.png'></body></html>"));
-
- // Call WKPageLoadAlternateHTMLString() with fileURL which does not point to a directory
- WKPageLoadAlternateHTMLString(webView.page(), alternateHTMLString.get(), fileURL.get(), fileURL.get());
-
+ WKPageLoadAlternateHTMLString(webView.page(), alternateHTMLString.get(), baseURL, unreachableURL);
+
// If we can finish loading the html without resulting in an invalid message being sent from the WebProcess, this test passes.
Util::run(&didFinishLoad);
}
+TEST(WebKit2, LoadAlternateHTMLStringWithNonDirectoryURL)
+{
+ // Call WKPageLoadAlternateHTMLString() with fileURL which does not point to a directory.
+ WKRetainPtr<WKURLRef> fileURL(AdoptWK, Util::createURLForResource("simple", "html"));
+ loadAlternateHTMLString(fileURL.get(), fileURL.get());
+}
+
+TEST(WebKit2, LoadAlternateHTMLStringWithEmptyBaseURL)
+{
+ // Call WKPageLoadAlternateHTMLString() with empty baseURL to make sure this test works
+ // when baseURL does not grant read access to the unreachableURL. We use a separate test
+ // to ensure the previous test does not pollute the result.
+ WKRetainPtr<WKURLRef> unreachableURL(AdoptWK, Util::URLForNonExistentResource());
+ loadAlternateHTMLString(nullptr, unreachableURL.get());
+}
+
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback.cpp
index abf447155..ac45fba26 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback.cpp
@@ -24,13 +24,16 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "JavaScriptTest.h"
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKContext.h>
-#include <WebKit2/WKFrame.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKContext.h>
+#include <WebKit/WKFrame.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -93,3 +96,5 @@ TEST(WebKit2, LoadCanceledNoServerRedirectCallback)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback_Bundle.cpp
index 13aa1106e..6ea0dc77d 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/LoadCanceledNoServerRedirectCallback_Bundle.cpp
@@ -24,13 +24,16 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
#include "Test.h"
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundleFrame.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundleFrame.h>
+#include <WebKit/WKRetainPtr.h>
#include <wtf/Assertions.h>
@@ -70,3 +73,5 @@ public:
static InjectedBundleTest::Register<LoadCanceledNoServerRedirectCallbackTest> registrar("LoadCanceledNoServerRedirectCallbackTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/LoadPageOnCrash.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/LoadPageOnCrash.cpp
index 3228d084a..63ad664e2 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/LoadPageOnCrash.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/LoadPageOnCrash.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -103,3 +106,5 @@ TEST(WebKit2, LoadPageAfterCrash)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/MenuTypesForMouseEvents.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/MenuTypesForMouseEvents.cpp
new file mode 100644
index 000000000..f77a11ad8
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/MenuTypesForMouseEvents.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "JavaScriptTest.h"
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+
+namespace TestWebKitAPI {
+
+static bool didFinishLoad;
+
+static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef, const void*)
+{
+ didFinishLoad = true;
+}
+
+static void setPageLoaderClient(WKPageRef page)
+{
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+
+ loaderClient.base.version = 0;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+
+ WKPageSetPageLoaderClient(page, &loaderClient.base);
+}
+
+static void buildAndPerformTest(WKEventMouseButton button, WKEventModifiers modifiers, const char* expectedButton, const char* expectedMenuType)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+ PlatformWebView webView(context.get());
+ setPageLoaderClient(webView.page());
+
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("mouse-button-listener", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+ Util::run(&didFinishLoad);
+
+ didFinishLoad = false;
+
+ webView.simulateButtonClick(button, 10, 10, modifiers);
+
+ EXPECT_JS_EQ(webView.page(), "pressedMouseButton()", expectedButton);
+ EXPECT_JS_EQ(webView.page(), "displayedMenu()", expectedMenuType);
+}
+
+TEST(WebKit2, MenuAndButtonForNormalLeftClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonLeftButton, 0, "0", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForNormalRightClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonRightButton, 0, "2", "context");
+}
+
+TEST(WebKit2, MenuAndButtonForNormalMiddleClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonMiddleButton, 0, "1", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForControlLeftClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonLeftButton, kWKEventModifiersControlKey, "0", "context");
+}
+
+TEST(WebKit2, MenuAndButtonForControlRightClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonRightButton, kWKEventModifiersControlKey, "2", "context");
+}
+
+TEST(WebKit2, MenuAndButtonForControlMiddleClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonMiddleButton, kWKEventModifiersControlKey, "1", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForShiftLeftClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonLeftButton, kWKEventModifiersShiftKey, "0", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForShiftRightClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonRightButton, kWKEventModifiersShiftKey, "2", "context");
+}
+
+TEST(WebKit2, MenuAndButtonForShiftMiddleClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonMiddleButton, kWKEventModifiersShiftKey, "1", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForCommandLeftClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonLeftButton, kWKEventModifiersMetaKey, "0", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForCommandRightClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonRightButton, kWKEventModifiersMetaKey, "2", "context");
+}
+
+TEST(WebKit2, MenuAndButtonForCommandMiddleClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonMiddleButton, kWKEventModifiersMetaKey, "1", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForAltLeftClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonLeftButton, kWKEventModifiersAltKey, "0", "none");
+}
+
+TEST(WebKit2, MenuAndButtonForAltRightClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonRightButton, kWKEventModifiersAltKey, "2", "context");
+}
+
+TEST(WebKit2, MenuAndButtonForAltMiddleClick)
+{
+ buildAndPerformTest(kWKEventMouseButtonMiddleButton, kWKEventModifiersAltKey, "1", "none");
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ModalAlertsSPI.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ModalAlertsSPI.cpp
new file mode 100644
index 000000000..0278f005b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ModalAlertsSPI.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <WebKit/WKFrame.h>
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKSecurityOriginRef.h>
+
+namespace TestWebKitAPI {
+
+static bool done;
+static unsigned dialogsSeen;
+static const unsigned dialogsExpected = 3;
+
+static void analyzeDialogArguments(WKPageRef page, WKFrameRef frame, WKSecurityOriginRef securityOrigin)
+{
+ EXPECT_EQ(page, WKFrameGetPage(frame));
+
+ WKRetainPtr<WKURLRef> url = adoptWK(WKFrameCopyURL(frame));
+ WKRetainPtr<WKStringRef> urlString = adoptWK(WKURLCopyString(url.get()));
+ EXPECT_WK_STREQ("about:blank", urlString.get());
+
+ WKRetainPtr<WKStringRef> protocol = adoptWK(WKSecurityOriginCopyProtocol(securityOrigin));
+ EXPECT_WK_STREQ("file", protocol.get());
+
+ WKRetainPtr<WKStringRef> host = adoptWK(WKSecurityOriginCopyHost(securityOrigin));
+ EXPECT_WK_STREQ("", host.get());
+
+ EXPECT_EQ(WKSecurityOriginGetPort(securityOrigin), 0);
+
+ if (++dialogsSeen == dialogsExpected)
+ done = true;
+}
+
+static void runJavaScriptAlert(WKPageRef page, WKStringRef, WKFrameRef frame, WKSecurityOriginRef securityOrigin, const void*)
+{
+ analyzeDialogArguments(page, frame, securityOrigin);
+}
+
+static bool runJavaScriptConfirm(WKPageRef page, WKStringRef, WKFrameRef frame, WKSecurityOriginRef securityOrigin, const void*)
+{
+ analyzeDialogArguments(page, frame, securityOrigin);
+ return false;
+}
+
+static WKStringRef runJavaScriptPrompt(WKPageRef page, WKStringRef, WKStringRef, WKFrameRef frame, WKSecurityOriginRef securityOrigin, const void*)
+{
+ analyzeDialogArguments(page, frame, securityOrigin);
+ return nullptr;
+}
+
+static std::unique_ptr<PlatformWebView> openedWebView;
+
+static WKPageRef createNewPage(WKPageRef page, WKURLRequestRef urlRequest, WKDictionaryRef features, WKEventModifiers modifiers, WKEventMouseButton mouseButton, const void *clientInfo)
+{
+ EXPECT_TRUE(openedWebView == nullptr);
+
+ openedWebView = std::make_unique<PlatformWebView>(page);
+
+ WKPageUIClientV5 uiClient;
+ memset(&uiClient, 0, sizeof(uiClient));
+
+ uiClient.base.version = 5;
+ uiClient.runJavaScriptAlert = runJavaScriptAlert;
+ uiClient.runJavaScriptConfirm = runJavaScriptConfirm;
+ uiClient.runJavaScriptPrompt = runJavaScriptPrompt;
+
+ WKPageSetPageUIClient(openedWebView->page(), &uiClient.base);
+
+ WKRetain(openedWebView->page());
+ return openedWebView->page();
+}
+
+TEST(WebKit2, ModalAlertsSPI)
+{
+ WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
+ PlatformWebView webView(context.get());
+
+ WKPageUIClientV5 uiClient;
+ memset(&uiClient, 0, sizeof(uiClient));
+
+ uiClient.base.version = 5;
+ uiClient.createNewPage = createNewPage;
+
+ WKPageSetPageUIClient(webView.page(), &uiClient.base);
+
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("modal-alerts-in-new-about-blank-window", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+
+ Util::run(&done);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash.cpp
index b75be6a1a..9d7f3997d 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "JavaScriptTest.h"
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
@@ -48,11 +51,7 @@ static void setPageLoaderClient(WKPageRef page)
WKPageSetPageLoaderClient(page, &loaderClient.base);
}
-#if PLATFORM(WIN)
-TEST(WebKit2, DISABLED_MouseMoveAfterCrash)
-#else
TEST(WebKit2, MouseMoveAfterCrash)
-#endif
{
WKRetainPtr<WKContextRef> context = adoptWK(Util::createContextForInjectedBundleTest("MouseMoveAfterCrashTest"));
@@ -90,3 +89,5 @@ TEST(WebKit2, MouseMoveAfterCrash)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash_Bundle.cpp
index a07562093..8d92f4209 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/MouseMoveAfterCrash_Bundle.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
@@ -54,3 +57,5 @@ void MouseMoveAfterCrashTest::didReceiveMessage(WKBundleRef bundle, WKStringRef
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout.cpp
index 640a825f8..778d285ba 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKContextPrivate.h>
+#include <WebKit/WKContextPrivate.h>
namespace TestWebKitAPI {
@@ -86,3 +89,5 @@ TEST(WebKit2, DISABLED_NewFirstVisuallyNonEmptyLayout)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails.cpp
index 1568b7663..5cff318fa 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKContextPrivate.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKContextPrivate.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -86,3 +89,5 @@ TEST(WebKit2, NewFirstVisuallyNonEmptyLayoutFails)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp
index b909ec941..2700d66c8 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundlePagePrivate.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundlePagePrivate.h>
namespace TestWebKitAPI {
@@ -49,3 +52,5 @@ public:
static InjectedBundleTest::Register<NewFirstVisuallyNonEmptyLayoutFailsTest> registrar("NewFirstVisuallyNonEmptyLayoutFailsTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages.cpp
index 11fc17ebd..7bd1fd7b3 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKContextPrivate.h>
+#include <WebKit/WKContextPrivate.h>
namespace TestWebKitAPI {
@@ -86,3 +89,5 @@ TEST(WebKit2, DISABLED_NewFirstVisuallyNonEmptyLayoutForImages)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp
index bdaade77b..d8644bb69 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutForImages_Bundle.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundlePagePrivate.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundlePagePrivate.h>
namespace TestWebKitAPI {
@@ -49,3 +52,5 @@ public:
static InjectedBundleTest::Register<NewFirstVisuallyNonEmptyLayoutForImagesTest> registrar("NewFirstVisuallyNonEmptyLayoutForImagesTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames.cpp
index 04d6ee448..c7b24680e 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKContextPrivate.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKContextPrivate.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -64,7 +67,7 @@ static void setPageLoaderClient(WKPageRef page)
WKPageLoaderClientV3 loaderClient;
memset(&loaderClient, 0, sizeof(loaderClient));
- loaderClient.base.version = kWKPageLoaderClientCurrentVersion;
+ loaderClient.base.version = 3;
loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
loaderClient.didLayout = didLayout;
@@ -90,3 +93,5 @@ TEST(WebKit2, NewFirstVisuallyNonEmptyLayoutFrames)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp
index 33e16bd3e..f66fc957d 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundlePagePrivate.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundlePagePrivate.h>
namespace TestWebKitAPI {
@@ -49,3 +52,5 @@ public:
static InjectedBundleTest::Register<NewFirstVisuallyNonEmptyLayoutFramesTest> registrar("NewFirstVisuallyNonEmptyLayoutFramesTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout_Bundle.cpp
index c408c3b2c..8f1901d10 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/NewFirstVisuallyNonEmptyLayout_Bundle.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundlePagePrivate.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundlePagePrivate.h>
namespace TestWebKitAPI {
@@ -49,3 +52,5 @@ public:
static InjectedBundleTest::Register<NewFirstVisuallyNonEmptyLayoutTest> registrar("NewFirstVisuallyNonEmptyLayoutTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/PageGroup.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/PageGroup.cpp
new file mode 100644
index 000000000..c1a5071ab
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/PageGroup.cpp
@@ -0,0 +1,80 @@
+/*
+ * 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. 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 INC. 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 "config.h"
+#import <WebKit/WKFoundation.h>
+
+#if WK_HAVE_C_SPI
+
+#import "PlatformUtilities.h"
+#import "PlatformWebView.h"
+#import "Test.h"
+#import <WebKit/WKPageGroup.h>
+#import <WebKit/WKUserContentControllerRef.h>
+#import <WebKit/WKPageConfigurationRef.h>
+
+namespace TestWebKitAPI {
+
+TEST(PageGroup, DefaultUserContentController)
+{
+ auto pageConfiguration = adoptWK(WKPageConfigurationCreate());
+ auto context = adoptWK(WKContextCreate());
+ WKPageConfigurationSetContext(pageConfiguration.get(), context.get());
+ auto pageGroup = adoptWK(WKPageGroupCreateWithIdentifier(Util::toWK("TestPageGroup").get()));
+ WKPageConfigurationSetPageGroup(pageConfiguration.get(), pageGroup.get());
+
+ auto pageGroupUserContentController = retainWK(WKPageGroupGetUserContentController(pageGroup.get()));
+
+ EXPECT_NULL(WKPageConfigurationGetUserContentController(pageConfiguration.get()));
+
+ PlatformWebView webView(pageConfiguration.get());
+ auto copiedPageConfiguration = adoptWK(WKPageCopyPageConfiguration(webView.page()));
+
+ ASSERT_EQ(pageGroupUserContentController.get(), WKPageConfigurationGetUserContentController(copiedPageConfiguration.get()));
+}
+
+TEST(PageGroup, CustomUserContentController)
+{
+ auto pageConfiguration = adoptWK(WKPageConfigurationCreate());
+ auto context = adoptWK(WKContextCreate());
+ WKPageConfigurationSetContext(pageConfiguration.get(), context.get());
+ auto pageGroup = adoptWK(WKPageGroupCreateWithIdentifier(Util::toWK("TestPageGroup").get()));
+ WKPageConfigurationSetPageGroup(pageConfiguration.get(), pageGroup.get());
+ auto userContentController = adoptWK(WKUserContentControllerCreate());
+ WKPageConfigurationSetUserContentController(pageConfiguration.get(), userContentController.get());
+
+ auto pageGroupUserContentController = retainWK(WKPageGroupGetUserContentController(pageGroup.get()));
+
+ EXPECT_EQ(userContentController.get(), WKPageConfigurationGetUserContentController(pageConfiguration.get()));
+
+ PlatformWebView webView(pageConfiguration.get());
+ auto copiedPageConfiguration = adoptWK(WKPageCopyPageConfiguration(webView.page()));
+
+ EXPECT_EQ(userContentController.get(), WKPageConfigurationGetUserContentController(copiedPageConfiguration.get()));
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/PageLoadBasic.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/PageLoadBasic.cpp
index 26a6fddfd..7ac216b2a 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/PageLoadBasic.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/PageLoadBasic.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -151,4 +154,26 @@ TEST(WebKit2, PageLoadBasic)
Util::run(&test1Done);
}
+TEST(WebKit2, PageReload)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+ PlatformWebView webView(context.get());
+
+ // Reload test before url loading.
+ WKPageReload(webView.page());
+ WKPageReload(webView.page());
+
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("simple", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+
+ // Reload test after url loading.
+ WKPageReload(webView.page());
+
+ WKRetainPtr<WKURLRef> activeUrl = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeUrl.get());
+ EXPECT_TRUE(WKURLIsEqual(activeUrl.get(), url.get()));
+}
+
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/PageLoadDidChangeLocationWithinPageForFrame.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/PageLoadDidChangeLocationWithinPageForFrame.cpp
index 8ef9bb66d..46838db93 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/PageLoadDidChangeLocationWithinPageForFrame.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/PageLoadDidChangeLocationWithinPageForFrame.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -84,3 +87,5 @@ TEST(WebKit2, PageLoadDidChangeLocationWithinPageForFrame)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame.cpp
index ec97ac0b0..7953608c8 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKContextPrivate.h>
+#include <WebKit/WKContextPrivate.h>
namespace TestWebKitAPI {
@@ -68,3 +71,5 @@ TEST(WebKit2, ParentFrame)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame_Bundle.cpp
index b23336293..e1da9ee02 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame_Bundle.cpp
@@ -24,12 +24,15 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundleFrame.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundleFrame.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -77,3 +80,5 @@ void ParentFrameTest::didCreatePage(WKBundleRef bundle, WKBundlePageRef page)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/PasteboardNotifications_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/PasteboardNotifications_Bundle.cpp
new file mode 100644
index 000000000..8c1404e7a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/PasteboardNotifications_Bundle.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2012 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "InjectedBundleTest.h"
+
+#include "PlatformUtilities.h"
+#include <WebKit/WKArray.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundleBackForwardListItem.h>
+#include <WebKit/WKWebArchive.h>
+
+namespace TestWebKitAPI {
+
+class PasteboardNotificationsTest : public InjectedBundleTest {
+public:
+ PasteboardNotificationsTest(const std::string& identifier);
+
+ virtual void didCreatePage(WKBundleRef, WKBundlePageRef);
+};
+
+static InjectedBundleTest::Register<PasteboardNotificationsTest> registrar("PasteboardNotificationsTest");
+
+static void willWriteToPasteboard(WKBundlePageRef page, WKBundleRangeHandleRef range, const void*)
+{
+ if (!range)
+ WKBundlePostMessage(InjectedBundleController::singleton().bundle(), Util::toWK("PasteboardNotificationTestDoneMessageName").get(), Util::toWK("willWritetoPasteboardFail").get());
+}
+
+static void getPasteboardDataForRange(WKBundlePageRef, WKBundleRangeHandleRef range, WKArrayRef* pasteboardTypes, WKArrayRef* pasteboardData, const void*)
+{
+ WKTypeRef typeName = WKStringCreateWithUTF8CString("AnotherArchivePasteboardType");
+ *pasteboardTypes = WKArrayCreateAdoptingValues(&typeName, 1);
+ WKTypeRef typeData = WKWebArchiveCopyData(WKWebArchiveCreateFromRange(range));
+ *pasteboardData = WKArrayCreateAdoptingValues(&typeData, 1);
+}
+
+static void didWriteToPasteboard(WKBundlePageRef, const void*)
+{
+ WKBundlePostMessage(InjectedBundleController::singleton().bundle(), Util::toWK("PasteboardNotificationTestDoneMessageName").get(), Util::toWK("didWriteToPasteboard").get());
+}
+
+PasteboardNotificationsTest::PasteboardNotificationsTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+{
+}
+
+void PasteboardNotificationsTest::didCreatePage(WKBundleRef bundle, WKBundlePageRef page)
+{
+ WKBundlePageEditorClientV1 pageEditorClient;
+ memset(&pageEditorClient, 0, sizeof(pageEditorClient));
+
+ pageEditorClient.base.version = 1;
+ pageEditorClient.base.clientInfo = this;
+ pageEditorClient.willWriteToPasteboard = willWriteToPasteboard;
+ pageEditorClient.getPasteboardDataForRange = getPasteboardDataForRange;
+ pageEditorClient.didWriteToPasteboard = didWriteToPasteboard;
+
+ WKBundlePageSetEditorClient(page, &pageEditorClient.base);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/PendingAPIRequestURL.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/PendingAPIRequestURL.cpp
new file mode 100644
index 000000000..22a8f04fa
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/PendingAPIRequestURL.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <WebKit/WKRetainPtr.h>
+
+namespace TestWebKitAPI {
+
+static bool done;
+
+TEST(WebKit2, PendingAPIRequestURL)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+ PlatformWebView webView(context.get());
+
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+ loaderClient.base.version = 0;
+ loaderClient.didFinishLoadForFrame = [](WKPageRef, WKFrameRef, WKTypeRef, const void*) { done = true; };
+ WKPageSetPageLoaderClient(webView.page(), &loaderClient.base);
+
+ WKRetainPtr<WKURLRef> activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ EXPECT_NULL(activeURL.get());
+
+ WKRetainPtr<WKURLRef> url = adoptWK(Util::createURLForResource("simple", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), url.get()));
+ Util::run(&done);
+ done = false;
+
+ WKPageReload(webView.page());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), url.get()));
+ Util::run(&done);
+ done = false;
+
+ WKRetainPtr<WKStringRef> htmlString = Util::toWK("<body>Hello, World</body>");
+ WKRetainPtr<WKURLRef> blankURL = adoptWK(WKURLCreateWithUTF8CString("about:blank"));
+ WKPageLoadHTMLString(webView.page(), htmlString.get(), nullptr);
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), blankURL.get()));
+ Util::run(&done);
+ done = false;
+
+ WKPageReload(webView.page());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), blankURL.get()));
+ Util::run(&done);
+ done = false;
+
+ url = adoptWK(Util::createURLForResource("simple2", "html"));
+ WKPageLoadHTMLString(webView.page(), htmlString.get(), url.get());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), url.get()));
+ Util::run(&done);
+ done = false;
+
+ WKPageReload(webView.page());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), url.get()));
+ Util::run(&done);
+ done = false;
+
+ WKRetainPtr<WKDataRef> data = adoptWK(WKDataCreate(nullptr, 0));
+ WKPageLoadData(webView.page(), data.get(), nullptr, nullptr, nullptr);
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), blankURL.get()));
+ Util::run(&done);
+ done = false;
+
+ WKPageReload(webView.page());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), blankURL.get()));
+ Util::run(&done);
+ done = false;
+
+ WKPageLoadData(webView.page(), data.get(), nullptr, nullptr, url.get());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), url.get()));
+ Util::run(&done);
+ done = false;
+
+ WKPageReload(webView.page());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), url.get()));
+ Util::run(&done);
+ done = false;
+
+ WKPageLoadAlternateHTMLString(webView.page(), htmlString.get(), nullptr, url.get());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), url.get()));
+ Util::run(&done);
+ done = false;
+
+ WKPageReload(webView.page());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), url.get()));
+ Util::run(&done);
+ done = false;
+
+ WKRetainPtr<WKStringRef> plainTextString = Util::toWK("Hello, World");
+ WKPageLoadPlainTextString(webView.page(), plainTextString.get());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), blankURL.get()));
+ Util::run(&done);
+ done = false;
+
+ WKPageReload(webView.page());
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), blankURL.get()));
+ Util::run(&done);
+ done = false;
+
+ url = adoptWK(WKURLCreateWithUTF8CString("file:///tmp/index.html"));
+ WKPageLoadFile(webView.page(), url.get(), nullptr);
+ activeURL = adoptWK(WKPageCopyActiveURL(webView.page()));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(activeURL.get(), url.get()));
+ WKPageStopLoading(webView.page());
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/PreventEmptyUserAgent.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/PreventEmptyUserAgent.cpp
index c5acb6172..7712b142c 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/PreventEmptyUserAgent.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/PreventEmptyUserAgent.cpp
@@ -24,12 +24,15 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
#include <JavaScriptCore/JSContextRef.h>
-#include <WebKit2/WKRetainPtr.h>
-#include <WebKit2/WKSerializedScriptValue.h>
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKSerializedScriptValue.h>
namespace TestWebKitAPI {
@@ -68,3 +71,5 @@ TEST(WebKit2, PreventEmptyUserAgent)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/PrivateBrowsingPushStateNoHistoryCallback.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/PrivateBrowsingPushStateNoHistoryCallback.cpp
index 3d0db3d2f..532c92373 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/PrivateBrowsingPushStateNoHistoryCallback.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/PrivateBrowsingPushStateNoHistoryCallback.cpp
@@ -24,24 +24,33 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
-static bool testDone;
+static bool didNavigate;
+static bool didSameDocumentNavigation;
-static void didNavigateWithNavigationData(WKContextRef context, WKPageRef page, WKNavigationDataRef navigationData, WKFrameRef frame, const void* clientInfo)
+static void didNavigateWithoutNavigationData(WKContextRef context, WKPageRef page, WKNavigationDataRef navigationData, WKFrameRef frame, const void* clientInfo)
{
// This should never be called when navigating in Private Browsing.
FAIL();
}
+static void didNavigateWithNavigationData(WKContextRef context, WKPageRef page, WKNavigationDataRef navigationData, WKFrameRef frame, const void* clientInfo)
+{
+ didNavigate = true;
+}
+
static void didSameDocumentNavigationForFrame(WKPageRef page, WKFrameRef frame, WKSameDocumentNavigationType type, WKTypeRef userData, const void *clientInfo)
{
- testDone = true;
+ didSameDocumentNavigation = true;
}
TEST(WebKit2, PrivateBrowsingPushStateNoHistoryCallback)
@@ -52,7 +61,7 @@ TEST(WebKit2, PrivateBrowsingPushStateNoHistoryCallback)
memset(&historyClient, 0, sizeof(historyClient));
historyClient.base.version = 0;
- historyClient.didNavigateWithNavigationData = didNavigateWithNavigationData;
+ historyClient.didNavigateWithNavigationData = didNavigateWithoutNavigationData;
WKContextSetHistoryClient(context.get(), &historyClient.base);
@@ -75,7 +84,18 @@ TEST(WebKit2, PrivateBrowsingPushStateNoHistoryCallback)
WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("push-state", "html"));
WKPageLoadURL(webView.page(), url.get());
- Util::run(&testDone);
+ Util::run(&didSameDocumentNavigation);
+
+ WKPreferencesSetPrivateBrowsingEnabled(preferences.get(), false);
+
+ historyClient.didNavigateWithNavigationData = didNavigateWithNavigationData;
+ WKContextSetHistoryClient(context.get(), &historyClient.base);
+
+ WKPageLoadURL(webView.page(), url.get());
+
+ Util::run(&didNavigate);
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ProvisionalURLAfterWillSendRequestCallback.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ProvisionalURLAfterWillSendRequestCallback.cpp
new file mode 100644
index 000000000..2979f792c
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ProvisionalURLAfterWillSendRequestCallback.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 Igalia S.L.
+ *
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <WebKit/WKContext.h>
+#include <WebKit/WKFrame.h>
+#include <WebKit/WKRetainPtr.h>
+
+namespace TestWebKitAPI {
+
+static bool committedLoad;
+
+static void didCommitLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void*)
+{
+ if (!WKFrameIsMainFrame(frame))
+ return;
+
+ // The provisional URL should be null.
+ EXPECT_NULL(WKFrameCopyProvisionalURL(frame));
+
+ // The committed URL is the last known provisional URL.
+ WKRetainPtr<WKURLRef> committedURL = adoptWK(WKFrameCopyURL(frame));
+ ASSERT_NOT_NULL(committedURL.get());
+ WKRetainPtr<WKURLRef> activeURL = adoptWK(WKPageCopyActiveURL(page));
+ ASSERT_NOT_NULL(activeURL.get());
+ EXPECT_TRUE(WKURLIsEqual(committedURL.get(), activeURL.get()));
+ assert(WKGetTypeID(userData) == WKURLGetTypeID());
+ EXPECT_TRUE(WKURLIsEqual(committedURL.get(), static_cast<WKURLRef>(userData)));
+
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("simple2", "html"));
+ EXPECT_TRUE(WKURLIsEqual(committedURL.get(), url.get()));
+
+ committedLoad = true;
+}
+
+TEST(WebKit2, ProvisionalURLAfterWillSendRequestCallback)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, Util::createContextForInjectedBundleTest("ProvisionalURLAfterWillSendRequestCallbackTest"));
+
+ WKContextInjectedBundleClientV0 injectedBundleClient;
+ memset(&injectedBundleClient, 0, sizeof(injectedBundleClient));
+ injectedBundleClient.base.version = 0;
+ WKContextSetInjectedBundleClient(context.get(), &injectedBundleClient.base);
+
+ PlatformWebView webView(context.get());
+
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+
+ loaderClient.base.version = 0;
+ loaderClient.didCommitLoadForFrame = didCommitLoadForFrame;
+ WKPageSetPageLoaderClient(webView.page(), &loaderClient.base);
+
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("simple", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+ Util::run(&committedLoad);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ProvisionalURLAfterWillSendRequestCallback_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ProvisionalURLAfterWillSendRequestCallback_Bundle.cpp
new file mode 100644
index 000000000..6c3d74a95
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ProvisionalURLAfterWillSendRequestCallback_Bundle.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016 Igalia S.L.
+ *
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "InjectedBundleTest.h"
+#include "PlatformUtilities.h"
+#include "Test.h"
+#include <WebKit/WKBundleFrame.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKRetainPtr.h>
+
+namespace TestWebKitAPI {
+
+class ProvisionalURLAfterWillSendRequestCallbackTest : public InjectedBundleTest {
+public:
+ ProvisionalURLAfterWillSendRequestCallbackTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+ {
+ }
+
+ static WKURLRequestRef willSendRequestForFrame(WKBundlePageRef, WKBundleFrameRef frame, uint64_t resourceIdentifier, WKURLRequestRef request, WKURLResponseRef redirectResponse, const void*)
+ {
+ if (!WKBundleFrameIsMainFrame(frame)) {
+ WKRetainPtr<WKURLRequestRef> newRequest = request;
+ return newRequest.leakRef();
+ }
+
+ // Change the main frame URL.
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("simple2", "html"));
+ return WKURLRequestCreateWithWKURL(url.get());
+ }
+
+ static void didCommitLoadForFrame(WKBundlePageRef, WKBundleFrameRef frame, WKTypeRef* userData, const void*)
+ {
+ if (!WKBundleFrameIsMainFrame(frame))
+ return;
+ *userData = WKBundleFrameCopyURL(frame);
+ }
+
+ void didCreatePage(WKBundleRef bundle, WKBundlePageRef page) override
+ {
+ WKBundlePageResourceLoadClientV0 resourceLoadClient;
+ memset(&resourceLoadClient, 0, sizeof(resourceLoadClient));
+ resourceLoadClient.base.version = 0;
+ resourceLoadClient.willSendRequestForFrame = willSendRequestForFrame;
+ WKBundlePageSetResourceLoadClient(page, &resourceLoadClient.base);
+
+ WKBundlePageLoaderClientV0 pageLoaderClient;
+ memset(&pageLoaderClient, 0, sizeof(pageLoaderClient));
+ pageLoaderClient.base.version = 0;
+ pageLoaderClient.didCommitLoadForFrame = didCommitLoadForFrame;
+ WKBundlePageSetPageLoaderClient(page, &pageLoaderClient.base);
+ }
+};
+
+static InjectedBundleTest::Register<ProvisionalURLAfterWillSendRequestCallbackTest> registrar("ProvisionalURLAfterWillSendRequestCallbackTest");
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ReloadPageAfterCrash.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ReloadPageAfterCrash.cpp
index fb265abc1..190c85341 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ReloadPageAfterCrash.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ReloadPageAfterCrash.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -86,3 +89,5 @@ TEST(WebKit2, ReloadPageAfterCrash)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ResizeReversePaginatedWebView.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ResizeReversePaginatedWebView.cpp
index af1f1e705..f2e1ae17f 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ResizeReversePaginatedWebView.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ResizeReversePaginatedWebView.cpp
@@ -24,14 +24,17 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "JavaScriptTest.h"
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
#include <JavaScriptCore/JSContextRef.h>
-#include <WebKit2/WKContextPrivate.h>
-#include <WebKit2/WKPagePrivate.h>
-#include <WebKit2/WKSerializedScriptValue.h>
+#include <WebKit/WKContextPrivate.h>
+#include <WebKit/WKPagePrivate.h>
+#include <WebKit/WKSerializedScriptValue.h>
namespace TestWebKitAPI {
@@ -88,3 +91,5 @@ TEST(WebKit2, ResizeReversePaginatedWebView)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ResizeWindowAfterCrash.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ResizeWindowAfterCrash.cpp
index 4cd9eddb4..2dfc8b4c2 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ResizeWindowAfterCrash.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ResizeWindowAfterCrash.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -97,3 +100,5 @@ TEST(WebKit2, ResizeWindowAfterCrash)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly.cpp
index 9de11a286..a034637e3 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
@@ -96,3 +99,5 @@ TEST(WebKit2, ResponsivenessTimerDoesntFireEarly)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly_Bundle.cpp
index 50d664f38..ddd2ca158 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ResponsivenessTimerDoesntFireEarly_Bundle.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
@@ -57,3 +60,5 @@ void ResponsivenessTimerDoesntFireEarlyTest::didReceiveMessage(WKBundleRef bundl
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/RestoreSessionStateContainingFormData.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/RestoreSessionStateContainingFormData.cpp
index 079c51856..b16537e70 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/RestoreSessionStateContainingFormData.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/RestoreSessionStateContainingFormData.cpp
@@ -24,10 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "JavaScriptTest.h"
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
+#include <WebKit/WKSessionStateRef.h>
namespace TestWebKitAPI {
@@ -49,7 +53,7 @@ static void setPageLoaderClient(WKPageRef page)
WKPageSetPageLoaderClient(page, &loaderClient.base);
}
-static WKRetainPtr<WKDataRef> createSessionStateContainingFormData(WKContextRef context)
+static WKRetainPtr<WKDataRef> createSessionStateDataContainingFormData(WKContextRef context)
{
PlatformWebView webView(context);
setPageLoaderClient(webView.page());
@@ -62,7 +66,8 @@ static WKRetainPtr<WKDataRef> createSessionStateContainingFormData(WKContextRef
Util::run(&didFinishLoad);
didFinishLoad = false;
- return adoptWK(WKPageCopySessionState(webView.page(), 0, 0));
+ auto sessionState = adoptWK(static_cast<WKSessionStateRef>(WKPageCopySessionState(webView.page(), reinterpret_cast<void*>(1), nullptr)));
+ return adoptWK(WKSessionStateCopyData(sessionState.get()));
}
TEST(WebKit2, RestoreSessionStateContainingFormData)
@@ -75,13 +80,17 @@ TEST(WebKit2, RestoreSessionStateContainingFormData)
PlatformWebView webView(context.get());
setPageLoaderClient(webView.page());
- WKRetainPtr<WKDataRef> data = createSessionStateContainingFormData(context.get());
+ WKRetainPtr<WKDataRef> data = createSessionStateDataContainingFormData(context.get());
EXPECT_NOT_NULL(data);
- WKPageRestoreFromSessionState(webView.page(), data.get());
+ auto sessionState = adoptWK(WKSessionStateCreateFromData(data.get()));
+ WKPageRestoreFromSessionState(webView.page(), sessionState.get());
+
Util::run(&didFinishLoad);
EXPECT_TRUE(WKPageCanGoBack(webView.page()));
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/RestoreSessionStateWithoutNavigation.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/RestoreSessionStateWithoutNavigation.cpp
new file mode 100644
index 000000000..d597ba5fd
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/RestoreSessionStateWithoutNavigation.cpp
@@ -0,0 +1,105 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "JavaScriptTest.h"
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <WebKit/WKPagePrivate.h>
+#include <WebKit/WKSessionStateRef.h>
+
+namespace TestWebKitAPI {
+
+static bool didFinishLoad;
+static bool didChangeBackForwardList;
+
+static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef, const void*)
+{
+ didFinishLoad = true;
+}
+
+static void didChangeBackForwardListForPage(WKPageRef, WKBackForwardListItemRef addedItem, WKArrayRef, const void*)
+{
+ didChangeBackForwardList = true;
+}
+
+static void setPageLoaderClient(WKPageRef page)
+{
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+
+ loaderClient.base.version = 0;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+ loaderClient.didChangeBackForwardList = didChangeBackForwardListForPage;
+
+ WKPageSetPageLoaderClient(page, &loaderClient.base);
+}
+
+static WKRetainPtr<WKDataRef> createSessionStateData(WKContextRef context)
+{
+ PlatformWebView webView(context);
+ setPageLoaderClient(webView.page());
+
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("simple", "html")).get());
+ Util::run(&didFinishLoad);
+ didFinishLoad = false;
+
+ auto sessionState = adoptWK(static_cast<WKSessionStateRef>(WKPageCopySessionState(webView.page(), reinterpret_cast<void*>(1), nullptr)));
+ return adoptWK(WKSessionStateCopyData(sessionState.get()));
+}
+
+TEST(WebKit2, RestoreSessionStateWithoutNavigation)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+
+ PlatformWebView webView(context.get());
+ setPageLoaderClient(webView.page());
+
+ WKRetainPtr<WKDataRef> data = createSessionStateData(context.get());
+ EXPECT_NOT_NULL(data);
+
+ auto sessionState = adoptWK(WKSessionStateCreateFromData(data.get()));
+ WKPageRestoreFromSessionStateWithoutNavigation(webView.page(), sessionState.get());
+
+ Util::run(&didChangeBackForwardList);
+
+ WKRetainPtr<WKURLRef> committedURL = adoptWK(WKPageCopyCommittedURL(webView.page()));
+ EXPECT_NULL(committedURL.get());
+
+ auto backForwardList = WKPageGetBackForwardList(webView.page());
+ auto currentItem = WKBackForwardListGetCurrentItem(backForwardList);
+ auto currentItemURL = adoptWK(WKBackForwardListItemCopyURL(currentItem));
+ auto expectedURL = adoptWK(Util::createURLForResource("simple", "html"));
+ EXPECT_NOT_NULL(expectedURL);
+ EXPECT_TRUE(WKURLIsEqual(currentItemURL.get(), expectedURL.get()));
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ScrollPinningBehaviors.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ScrollPinningBehaviors.cpp
index 5b628a932..015571f5f 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ScrollPinningBehaviors.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ScrollPinningBehaviors.cpp
@@ -24,15 +24,18 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "JavaScriptTest.h"
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
#include <JavaScriptCore/JSContextRef.h>
-#include <WebKit2/WKContextPrivate.h>
-#include <WebKit2/WKPagePrivate.h>
-#include <WebKit2/WKPreferencesPrivate.h>
-#include <WebKit2/WKSerializedScriptValue.h>
+#include <WebKit/WKContextPrivate.h>
+#include <WebKit/WKPagePrivate.h>
+#include <WebKit/WKPreferencesRefPrivate.h>
+#include <WebKit/WKSerializedScriptValue.h>
namespace TestWebKitAPI {
@@ -95,3 +98,5 @@ TEST(WebKit2, ScrollPinningBehaviors)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem.cpp
index 5754155ed..f41e44a5e 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
-#include <WebKit2/WKString.h>
+#include <WebKit/WKString.h>
namespace TestWebKitAPI {
@@ -90,3 +93,5 @@ TEST(WebKit2, ShouldGoToBackForwardListItem)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem_Bundle.cpp
index dd81bf3bf..5eba75a9e 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ShouldGoToBackForwardListItem_Bundle.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKBundleBackForwardListItem.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundleBackForwardListItem.h>
namespace TestWebKitAPI {
@@ -68,3 +71,5 @@ void ShouldGoToBackForwardListItemTest::didCreatePage(WKBundleRef bundle, WKBund
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/ShouldKeepCurrentBackForwardListItemInList.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/ShouldKeepCurrentBackForwardListItemInList.cpp
new file mode 100644
index 000000000..f8098e6f1
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/ShouldKeepCurrentBackForwardListItemInList.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2014 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+
+// This test navigates from simple.html, to simple2.html, to simple3.html
+// When navigating from simple2 to simple3, it disallows the simple2 back/forward list item from staying in the list
+// It then navigates back from simple3, expecting to land at simple.
+
+namespace TestWebKitAPI {
+
+static bool finished = false;
+static bool successfulSoFar = true;
+static int navigationNumber = 0;
+
+static bool itemURLLastComponentIsString(WKBackForwardListItemRef item, const char* string)
+{
+ WKRetainPtr<WKURLRef> url = adoptWK(WKBackForwardListItemCopyURL(item));
+ WKRetainPtr<WKStringRef> path = adoptWK(WKURLCopyLastPathComponent(url.get()));
+
+ return WKStringIsEqualToUTF8CString(path.get(), string);
+}
+
+static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef, const void*)
+{
+ // Only mark finished when the main frame loads
+ if (!WKFrameIsMainFrame(frame))
+ return;
+
+ finished = true;
+ navigationNumber++;
+
+ WKBackForwardListRef list = WKPageGetBackForwardList(page);
+ WKBackForwardListItemRef currentItem = WKBackForwardListGetCurrentItem(list);
+ WKBackForwardListItemRef backItem = WKBackForwardListGetBackItem(list);
+ WKBackForwardListItemRef forwardItem = WKBackForwardListGetForwardItem(list);
+ unsigned forwardCount = WKBackForwardListGetForwardListCount(list);
+
+ // This test should never have a forward list.
+ if (forwardCount)
+ successfulSoFar = false;
+
+ if (navigationNumber == 1) {
+ // We've only performed 1 navigation, we should only have a current item.
+ if (!currentItem || !itemURLLastComponentIsString(currentItem, "simple.html"))
+ successfulSoFar = false;
+ if (backItem || forwardItem)
+ successfulSoFar = false;
+ } else if (navigationNumber == 2) {
+ // On the second navigation, simple2 should be current and simple should be the back item.
+ if (!currentItem || !itemURLLastComponentIsString(currentItem, "simple2.html"))
+ successfulSoFar = false;
+ if (!backItem || !itemURLLastComponentIsString(backItem, "simple.html"))
+ successfulSoFar = false;
+ if (forwardItem)
+ successfulSoFar = false;
+ } else if (navigationNumber == 3) {
+ // On the third navigation the item for simple2 should have been removed.
+ // So simple3 should be current and simple should still be the back item.
+ if (!currentItem || !itemURLLastComponentIsString(currentItem, "simple3.html"))
+ successfulSoFar = false;
+ if (!backItem || !itemURLLastComponentIsString(backItem, "simple.html"))
+ successfulSoFar = false;
+ if (forwardItem)
+ successfulSoFar = false;
+ } else if (navigationNumber == 4) {
+ // After the fourth navigation (which was a "back" navigation), the item for simple3 should have been removed.
+ // So simple should be current and there should be no other items.
+ if (!currentItem || !itemURLLastComponentIsString(currentItem, "simple.html"))
+ successfulSoFar = false;
+ if (backItem || forwardItem)
+ successfulSoFar = false;
+ }
+}
+
+static void willGoToBackForwardListItem(WKPageRef, WKBackForwardListItemRef item, WKTypeRef userData, const void*)
+{
+ if (!itemURLLastComponentIsString(item, "simple.html"))
+ successfulSoFar = false;
+}
+
+static bool shouldKeepCurrentBackForwardListItemInList(WKPageRef page, WKBackForwardListItemRef item, const void*)
+{
+ // We make sure the item for "simple2.html" is removed when we navigate to "simple3.html"
+ // We also want to make sure the item for "simple3.html" is removed when we go back to "simple.html"
+ // So we only want to keep "simple.html"
+ return itemURLLastComponentIsString(item, "simple.html");
+}
+
+static void setPageLoaderClient(WKPageRef page)
+{
+ WKPageLoaderClientV5 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+
+ loaderClient.base.version = 5;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+ loaderClient.shouldKeepCurrentBackForwardListItemInList = shouldKeepCurrentBackForwardListItemInList;
+ loaderClient.willGoToBackForwardListItem = willGoToBackForwardListItem;
+
+ WKPageSetPageLoaderClient(page, &loaderClient.base);
+}
+
+TEST(WebKit2, ShouldKeepCurrentBackForwardListItemInList)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+
+ PlatformWebView webView(context.get());
+ setPageLoaderClient(webView.page());
+
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("simple", "html")).get());
+ Util::run(&finished);
+ EXPECT_EQ(successfulSoFar, true);
+
+ finished = false;
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("simple2", "html")).get());
+ Util::run(&finished);
+ EXPECT_EQ(successfulSoFar, true);
+
+ finished = false;
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("simple3", "html")).get());
+ Util::run(&finished);
+ EXPECT_EQ(successfulSoFar, true);
+
+ finished = false;
+ WKPageGoBack(webView.page());
+ Util::run(&finished);
+
+ EXPECT_EQ(successfulSoFar, true);
+ EXPECT_EQ(navigationNumber, 4);
+}
+
+} // namespace TestWebKitAPI
+
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp
index 577e0d77c..226f52cc2 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/SpacebarScrolling.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "JavaScriptTest.h"
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <WebKit2/WKRetainPtr.h>
-#include <WebKit2/WKPreferencesPrivate.h>
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKPreferencesPrivate.h>
namespace TestWebKitAPI {
@@ -86,13 +89,11 @@ TEST(WebKit2, SpacebarScrolling)
EXPECT_JS_FALSE(webView.page(), "isDocumentScrolled()");
EXPECT_JS_TRUE(webView.page(), "textFieldContainsSpace()");
- // On Mac, a key down event represents both a raw key down and a key press. On Windows, a key
- // down event only represents a raw key down. We expect the key press to be handled (because it
- // inserts text into the text field). But the raw key down should not be handled.
-#if PLATFORM(MAC)
+ // On Mac, a key down event represents both a raw key down and a key press.
+ // We expect the key press to be handled (because it inserts text into the text field),
+ // but the raw key down should not be handled.
+#if PLATFORM(COCOA)
EXPECT_FALSE(didNotHandleKeyDownEvent);
-#elif PLATFORM(WIN)
- EXPECT_TRUE(didNotHandleKeyDownEvent);
#endif
EXPECT_JS_EQ(webView.page(), "blurTextField()", "undefined");
@@ -100,18 +101,14 @@ TEST(WebKit2, SpacebarScrolling)
didNotHandleKeyDownEvent = false;
webView.simulateSpacebarKeyPress();
- // This EXPECT_JS_TRUE test fails on Windows port
- // https://bugs.webkit.org/show_bug.cgi?id=84961
-#if !PLATFORM(WIN)
EXPECT_JS_TRUE(webView.page(), "isDocumentScrolled()");
-#endif
EXPECT_JS_TRUE(webView.page(), "textFieldContainsSpace()");
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA)
EXPECT_FALSE(didNotHandleKeyDownEvent);
-#elif PLATFORM(WIN)
- EXPECT_TRUE(didNotHandleKeyDownEvent);
#endif
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/StopLoadingDuringDidFailProvisionalLoad.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/StopLoadingDuringDidFailProvisionalLoad.cpp
new file mode 100644
index 000000000..386dfd303
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/StopLoadingDuringDidFailProvisionalLoad.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2014 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <WebKit/WKRetainPtr.h>
+
+namespace TestWebKitAPI {
+
+static bool done;
+static bool receivedMessageFromBundle;
+
+static void didReceiveMessageFromInjectedBundle(WKContextRef context, WKStringRef messageName, WKTypeRef messageBody, const void* clientInfo)
+{
+ if (WKStringIsEqualToUTF8CString(messageName, "StopLoadingDuringDidFailProvisionalLoadTestDone"))
+ receivedMessageFromBundle = true;
+}
+
+static void setInjectedBundleClient(WKContextRef context)
+{
+ WKContextInjectedBundleClientV0 injectedBundleClient;
+ memset(&injectedBundleClient, 0, sizeof(injectedBundleClient));
+
+ injectedBundleClient.didReceiveMessageFromInjectedBundle = didReceiveMessageFromInjectedBundle;
+
+ WKContextSetInjectedBundleClient(context, &injectedBundleClient.base);
+}
+
+static void didFailProvisionalLoadWithErrorForFrame(WKPageRef, WKFrameRef, WKErrorRef, WKTypeRef, const void*)
+{
+ // The injected bundle is notified of the failed load first. If we also receive this callback, the test didn't crash.
+ EXPECT_TRUE(receivedMessageFromBundle);
+ done = true;
+}
+
+TEST(WebKit2, StopLoadingDuringDidFailProvisionalLoadTest)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, Util::createContextForInjectedBundleTest("StopLoadingDuringDidFailProvisionalLoadTest"));
+ setInjectedBundleClient(context.get());
+
+ PlatformWebView webView(context.get());
+
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+ loaderClient.didFailProvisionalLoadWithErrorForFrame = didFailProvisionalLoadWithErrorForFrame;
+ WKPageSetPageLoaderClient(webView.page(), &loaderClient.base);
+
+ WKRetainPtr<WKURLRef> url(AdoptWK, Util::URLForNonExistentResource());
+ WKPageLoadURL(webView.page(), url.get());
+
+ Util::run(&done);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/StopLoadingDuringDidFailProvisionalLoad_bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/StopLoadingDuringDidFailProvisionalLoad_bundle.cpp
new file mode 100644
index 000000000..ad302ff51
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/StopLoadingDuringDidFailProvisionalLoad_bundle.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2014 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "InjectedBundleTest.h"
+#include "PlatformUtilities.h"
+#include <WebKit/WKBundle.h>
+#include <WebKit/WKBundleFramePrivate.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundlePagePrivate.h>
+
+namespace TestWebKitAPI {
+
+class StopLoadingDuringDidFailProvisionalLoadTest : public InjectedBundleTest {
+public:
+ StopLoadingDuringDidFailProvisionalLoadTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+ {
+ }
+
+ void didCreatePage(WKBundleRef, WKBundlePageRef) override;
+ void didFailProvisionalLoad(WKBundlePageRef, WKBundleFrameRef);
+
+ WKBundleRef m_bundle;
+};
+
+static InjectedBundleTest::Register<StopLoadingDuringDidFailProvisionalLoadTest> registrar("StopLoadingDuringDidFailProvisionalLoadTest");
+
+static void didFailProvisionalLoadWithErrorForFrameCallback(WKBundlePageRef page, WKBundleFrameRef frame, WKErrorRef, WKTypeRef*, const void *clientInfo)
+{
+ ((StopLoadingDuringDidFailProvisionalLoadTest*)clientInfo)->didFailProvisionalLoad(page, frame);
+}
+
+void StopLoadingDuringDidFailProvisionalLoadTest::didCreatePage(WKBundleRef bundle, WKBundlePageRef page)
+{
+ m_bundle = bundle;
+
+ WKBundlePageLoaderClientV2 pageLoaderClient;
+ memset(&pageLoaderClient, 0, sizeof(pageLoaderClient));
+
+ pageLoaderClient.base.version = 2;
+ pageLoaderClient.base.clientInfo = this;
+ pageLoaderClient.didFailProvisionalLoadWithErrorForFrame = didFailProvisionalLoadWithErrorForFrameCallback;
+
+ WKBundlePageSetPageLoaderClient(page, &pageLoaderClient.base);
+}
+
+void StopLoadingDuringDidFailProvisionalLoadTest::didFailProvisionalLoad(WKBundlePageRef page, WKBundleFrameRef)
+{
+ WKBundlePageStopLoading(page);
+ WKBundlePostMessage(m_bundle, Util::toWK("StopLoadingDuringDidFailProvisionalLoadTestDone").get(), nullptr);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/TerminateTwice.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/TerminateTwice.cpp
index 879312520..5d5c2f79d 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/TerminateTwice.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/TerminateTwice.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
@@ -64,3 +67,4 @@ TEST(WebKit2, TerminateTwice)
} // namespace TestWebKitAPI
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/TextFieldDidBeginAndEndEditing.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/TextFieldDidBeginAndEndEditing.cpp
new file mode 100644
index 000000000..731e8e51e
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/TextFieldDidBeginAndEndEditing.cpp
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <wtf/StdLibExtras.h>
+
+namespace TestWebKitAPI {
+
+struct WebKit2TextFieldBeginAndEditEditingTest : public ::testing::Test {
+ std::unique_ptr<PlatformWebView> webView;
+
+ WKRetainPtr<WKStringRef> messageName;
+
+ bool didFinishLoad { false };
+ bool didReceiveMessage { false };
+
+ static void didReceiveMessageFromInjectedBundle(WKContextRef, WKStringRef messageName, WKTypeRef, const void* clientInfo)
+ {
+ WebKit2TextFieldBeginAndEditEditingTest& client = *static_cast<WebKit2TextFieldBeginAndEditEditingTest*>(const_cast<void*>(clientInfo));
+ client.messageName = messageName;
+ client.didReceiveMessage = true;
+ }
+
+ static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef, const void* clientInfo)
+ {
+ WebKit2TextFieldBeginAndEditEditingTest& client = *static_cast<WebKit2TextFieldBeginAndEditEditingTest*>(const_cast<void*>(clientInfo));
+ client.didFinishLoad = true;
+ }
+
+ static void setInjectedBundleClient(WKContextRef context, const void* clientInfo)
+ {
+ WKContextInjectedBundleClientV1 injectedBundleClient;
+ memset(&injectedBundleClient, 0, sizeof(injectedBundleClient));
+
+ injectedBundleClient.base.version = 1;
+ injectedBundleClient.base.clientInfo = clientInfo;
+ injectedBundleClient.didReceiveMessageFromInjectedBundle = didReceiveMessageFromInjectedBundle;
+
+ WKContextSetInjectedBundleClient(context, &injectedBundleClient.base);
+ }
+
+ static void setPageLoaderClient(WKPageRef page, const void* clientInfo)
+ {
+ WKPageLoaderClientV6 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+
+ loaderClient.base.version = 6;
+ loaderClient.base.clientInfo = clientInfo;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+
+ WKPageSetPageLoaderClient(page, &loaderClient.base);
+ }
+
+ static void nullJavaScriptCallback(WKSerializedScriptValueRef, WKErrorRef, void*)
+ {
+ }
+
+ void executeJavaScriptAndCheckDidReceiveMessage(const char* javaScriptCode, const char* expectedMessageName)
+ {
+ didReceiveMessage = false;
+ WKPageRunJavaScriptInMainFrame(webView->page(), Util::toWK(javaScriptCode).get(), 0, nullJavaScriptCallback);
+ Util::run(&didReceiveMessage);
+ EXPECT_WK_STREQ(expectedMessageName, messageName);
+ }
+
+ // From ::testing::Test
+ void SetUp() override
+ {
+ WKRetainPtr<WKContextRef> context = adoptWK(Util::createContextForInjectedBundleTest("TextFieldDidBeginAndEndEditingEventsTest"));
+ setInjectedBundleClient(context.get(), this);
+
+ webView = std::make_unique<PlatformWebView>(context.get());
+ setPageLoaderClient(webView->page(), this);
+
+ didFinishLoad = false;
+ didReceiveMessage = false;
+
+ WKPageLoadURL(webView->page(), adoptWK(Util::createURLForResource("input-focus-blur", "html")).get());
+ Util::run(&didFinishLoad);
+ }
+};
+
+TEST_F(WebKit2TextFieldBeginAndEditEditingTest, TextFieldDidBeginAndEndEditingEvents)
+{
+ executeJavaScriptAndCheckDidReceiveMessage("focusTextField('input')", "DidReceiveTextFieldDidBeginEditing");
+ executeJavaScriptAndCheckDidReceiveMessage("blurTextField('input')", "DidReceiveTextFieldDidEndEditing");
+}
+
+TEST_F(WebKit2TextFieldBeginAndEditEditingTest, TextFieldDidBeginAndEndEditingEventsInReadOnlyField)
+{
+ executeJavaScriptAndCheckDidReceiveMessage("focusTextField('readonly')", "DidReceiveTextFieldDidBeginEditing");
+ executeJavaScriptAndCheckDidReceiveMessage("blurTextField('readonly')", "DidReceiveTextFieldDidEndEditing");
+}
+
+TEST_F(WebKit2TextFieldBeginAndEditEditingTest, TextFieldDidBeginShouldNotBeDispatchedForAlreadyFocusedField)
+{
+ executeJavaScriptAndCheckDidReceiveMessage("focusTextField('input'); focusTextField('input')", "DidReceiveTextFieldDidBeginEditing");
+ executeJavaScriptAndCheckDidReceiveMessage("blurTextField('input')", "DidReceiveTextFieldDidEndEditing");
+}
+
+TEST_F(WebKit2TextFieldBeginAndEditEditingTest, TextFieldDidEndShouldBeDispatchedForRemovedFocusField)
+{
+ executeJavaScriptAndCheckDidReceiveMessage("focusTextField('input')", "DidReceiveTextFieldDidBeginEditing");
+ executeJavaScriptAndCheckDidReceiveMessage("removeTextField('input')", "DidReceiveTextFieldDidEndEditing");
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/TextFieldDidBeginAndEndEditing_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/TextFieldDidBeginAndEndEditing_Bundle.cpp
new file mode 100644
index 000000000..347ce826c
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/TextFieldDidBeginAndEndEditing_Bundle.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "InjectedBundleTest.h"
+
+#include "PlatformUtilities.h"
+#include <WebKit/WKBundlePage.h>
+
+namespace TestWebKitAPI {
+
+class TextFieldDidBeginAndEndEditingEventsTest : public InjectedBundleTest {
+public:
+ TextFieldDidBeginAndEndEditingEventsTest(const std::string& identifier);
+
+ virtual void didCreatePage(WKBundleRef, WKBundlePageRef);
+};
+
+static InjectedBundleTest::Register<TextFieldDidBeginAndEndEditingEventsTest> registrar("TextFieldDidBeginAndEndEditingEventsTest");
+
+static void textFieldDidBeginEditing(WKBundlePageRef, WKBundleNodeHandleRef inputElement, WKBundleFrameRef, const void*)
+{
+ WKBundlePostMessage(InjectedBundleController::singleton().bundle(), Util::toWK("DidReceiveTextFieldDidBeginEditing").get(), nullptr);
+}
+
+static void textFieldDidEndEditing(WKBundlePageRef, WKBundleNodeHandleRef inputElement, WKBundleFrameRef, const void*)
+{
+ WKBundlePostMessage(InjectedBundleController::singleton().bundle(), Util::toWK("DidReceiveTextFieldDidEndEditing").get(), nullptr);
+}
+
+TextFieldDidBeginAndEndEditingEventsTest::TextFieldDidBeginAndEndEditingEventsTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+{
+}
+
+void TextFieldDidBeginAndEndEditingEventsTest::didCreatePage(WKBundleRef bundle, WKBundlePageRef page)
+{
+ WKBundlePageFormClientV2 formClient;
+ memset(&formClient, 0, sizeof(formClient));
+
+ formClient.base.version = 2;
+ formClient.base.clientInfo = this;
+ formClient.textFieldDidBeginEditing = textFieldDidBeginEditing;
+ formClient.textFieldDidEndEditing = textFieldDidEndEditing;
+
+ WKBundlePageSetFormClient(page, &formClient.base);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/UserMedia.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/UserMedia.cpp
new file mode 100644
index 000000000..fc7ade42f
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/UserMedia.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2014 Igalia S.L
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#if ENABLE(MEDIA_STREAM)
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <WebKit/WKRetainPtr.h>
+#include <string.h>
+#include <vector>
+
+namespace TestWebKitAPI {
+
+static bool done;
+
+void decidePolicyForUserMediaPermissionRequestCallBack(WKPageRef, WKFrameRef, WKSecurityOriginRef, WKSecurityOriginRef, WKUserMediaPermissionRequestRef permissionRequest, const void* /* clientInfo */)
+{
+ WKRetainPtr<WKArrayRef> audioDeviceUIDs = WKUserMediaPermissionRequestAudioDeviceUIDs(permissionRequest);
+ WKRetainPtr<WKArrayRef> videoDeviceUIDs = WKUserMediaPermissionRequestVideoDeviceUIDs(permissionRequest);
+
+ if (WKArrayGetSize(videoDeviceUIDs.get()) || WKArrayGetSize(audioDeviceUIDs.get())) {
+ WKRetainPtr<WKStringRef> videoDeviceUID;
+ if (WKArrayGetSize(videoDeviceUIDs.get()))
+ videoDeviceUID = reinterpret_cast<WKStringRef>(WKArrayGetItemAtIndex(videoDeviceUIDs.get(), 0));
+ else
+ videoDeviceUID = WKStringCreateWithUTF8CString("");
+
+ WKRetainPtr<WKStringRef> audioDeviceUID;
+ if (WKArrayGetSize(audioDeviceUIDs.get()))
+ audioDeviceUID = reinterpret_cast<WKStringRef>(WKArrayGetItemAtIndex(audioDeviceUIDs.get(), 0));
+ else
+ audioDeviceUID = WKStringCreateWithUTF8CString("");
+
+ WKUserMediaPermissionRequestAllow(permissionRequest, audioDeviceUID.get(), videoDeviceUID.get());
+ }
+
+ done = true;
+}
+
+TEST(WebKit2, DISABLED_UserMediaBasic)
+{
+ auto context = adoptWK(WKContextCreate());
+ PlatformWebView webView(context.get());
+ WKPageUIClientV5 uiClient;
+ memset(&uiClient, 0, sizeof(uiClient));
+
+
+ uiClient.base.version = 5;
+ uiClient.decidePolicyForUserMediaPermissionRequest = decidePolicyForUserMediaPermissionRequestCallBack;
+
+ WKPageSetPageUIClient(webView.page(), &uiClient.base);
+
+ done = false;
+ auto url = adoptWK(Util::createURLForResource("getUserMedia", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+
+ Util::run(&done);
+}
+
+} // namespace TestWebKitAPI
+
+#endif // ENABLE(MEDIA_STREAM)
+
+#endif // WK_HAVE_C_SPI
+
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage.cpp
index 2585a06ff..064cbb838 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage.cpp
@@ -24,12 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "Test.h"
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
namespace TestWebKitAPI {
@@ -42,7 +43,7 @@ public:
}
WKRetainPtr<WKContextRef> context;
- OwnPtr<PlatformWebView> webView;
+ std::unique_ptr<PlatformWebView> webView;
WKRetainPtr<WKTypeRef> recievedBody;
@@ -80,7 +81,7 @@ public:
WKPageLoaderClientV3 loaderClient;
memset(&loaderClient, 0, sizeof(loaderClient));
- loaderClient.base.version = kWKPageLoaderClientCurrentVersion;
+ loaderClient.base.version = 3;
loaderClient.base.clientInfo = clientInfo;
loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
@@ -92,7 +93,7 @@ public:
context = adoptWK(Util::createContextForInjectedBundleTest("UserMessageTest"));
setInjectedBundleClient(context.get(), this);
- webView = adoptPtr(new PlatformWebView(context.get()));
+ webView = std::make_unique<PlatformWebView>(context.get());
setPageLoaderClient(webView->page(), this);
didFinishLoad = false;
@@ -157,3 +158,5 @@ TEST_F(WebKit2UserMessageRoundTripTest, WKString)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage_Bundle.cpp
index 29ede3d83..cec713655 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/UserMessage_Bundle.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
@@ -50,3 +53,5 @@ private:
static InjectedBundleTest::Register<UserMessageTest> registrar("UserMessageTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKBundleFileHandle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKBundleFileHandle.cpp
new file mode 100644
index 000000000..b9a84ff80
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKBundleFileHandle.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+
+namespace TestWebKitAPI {
+
+static bool done;
+static bool loadDone;
+
+static void didReceiveMessageFromInjectedBundle(WKContextRef, WKStringRef messageName, WKTypeRef body, const void*)
+{
+ if (!WKStringIsEqualToUTF8CString(messageName, "SUCCESS"))
+ FAIL();
+ else
+ SUCCEED();
+
+ done = true;
+}
+
+static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void*)
+{
+ loadDone = true;
+}
+
+TEST(WebKit2, WKBundleFileHandle)
+{
+ WKRetainPtr<WKContextRef> context = adoptWK(Util::createContextForInjectedBundleTest("WKBundleFileHandleTest"));
+
+ WKContextInjectedBundleClientV0 injectedBundleClient;
+ memset(&injectedBundleClient, 0, sizeof(injectedBundleClient));
+ injectedBundleClient.base.version = 0;
+ injectedBundleClient.didReceiveMessageFromInjectedBundle = didReceiveMessageFromInjectedBundle;
+ WKContextSetInjectedBundleClient(context.get(), &injectedBundleClient.base);
+
+ PlatformWebView webView(context.get());
+
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+ loaderClient.base.version = 0;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+ WKPageSetPageLoaderClient(webView.page(), &loaderClient.base);
+
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("bundle-file", "html")).get());
+ Util::run(&loadDone);
+
+ // Get path to a file.
+ auto urlToFile = adoptWK(Util::createURLForResource("simple", "html"));
+ auto pathToFile = adoptWK(WKURLCopyPath(urlToFile.get()));
+
+ WKContextPostMessageToInjectedBundle(context.get(), Util::toWK("TestFile").get(), pathToFile.get());
+
+ Util::run(&done);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKBundleFileHandle_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKBundleFileHandle_Bundle.cpp
new file mode 100644
index 000000000..fcb0ab7a0
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKBundleFileHandle_Bundle.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "InjectedBundleTest.h"
+
+#include "PlatformUtilities.h"
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundleFileHandleRef.h>
+#include <WebKit/WKBundleFrame.h>
+#include <WebKit/WKBundleScriptWorld.h>
+
+namespace TestWebKitAPI {
+
+static WKBundlePageRef loadedPage;
+
+class WKBundleFileHandleTest : public InjectedBundleTest {
+public:
+ WKBundleFileHandleTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+ {
+ }
+
+private:
+ void didReceiveMessage(WKBundleRef bundle, WKStringRef messageName, WKTypeRef messageBody) override
+ {
+ if (!WKStringIsEqualToUTF8CString(messageName, "TestFile")) {
+ WKBundlePostMessage(bundle, Util::toWK("FAIL").get(), Util::toWK("Recieved invalid message").get());
+ return;
+ }
+
+ if (!loadedPage) {
+ WKBundlePostMessage(bundle, Util::toWK("FAIL").get(), Util::toWK("No loaded page").get());
+ return;
+ }
+
+ if (WKGetTypeID(messageBody) != WKStringGetTypeID()) {
+ WKBundlePostMessage(bundle, Util::toWK("FAIL").get(), Util::toWK("Message body has invalid type").get());
+ return;
+ }
+
+ WKBundleFrameRef mainFrame = WKBundlePageGetMainFrame(loadedPage);
+ WKBundleScriptWorldRef world = WKBundleScriptWorldNormalWorld();
+
+ JSGlobalContextRef globalContext = WKBundleFrameGetJavaScriptContextForWorld(mainFrame, world);
+
+ auto fileHandle = adoptWK(WKBundleFileHandleCreateWithPath((WKStringRef)messageBody));
+ JSValueRef jsFileHandle = WKBundleFrameGetJavaScriptWrapperForFileForWorld(mainFrame, fileHandle.get(), world);
+
+ JSObjectRef globalObject = JSContextGetGlobalObject(globalContext);
+
+ JSStringRef jsString = JSStringCreateWithUTF8CString("testFile");
+ JSValueRef function = JSObjectGetProperty(globalContext, globalObject, jsString, nullptr);
+ JSStringRelease(jsString);
+
+ JSValueRef result = JSObjectCallAsFunction(globalContext, (JSObjectRef)function, globalObject, 1, &jsFileHandle, nullptr);
+
+ if (JSValueToBoolean(globalContext, result))
+ WKBundlePostMessage(bundle, Util::toWK("SUCCESS").get(), nullptr);
+ else
+ WKBundlePostMessage(bundle, Util::toWK("FAIL").get(), Util::toWK("Script failed").get());
+ }
+
+ void didCreatePage(WKBundleRef bundle, WKBundlePageRef page) override
+ {
+ loadedPage = page;
+ }
+};
+
+static InjectedBundleTest::Register<WKBundleFileHandleTest> registrar("WKBundleFileHandleTest");
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKImageCreateCGImageCrash.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKImageCreateCGImageCrash.cpp
new file mode 100644
index 000000000..f0d19025f
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKImageCreateCGImageCrash.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2014 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include <WebKit/WKImageCG.h>
+
+namespace TestWebKitAPI {
+
+TEST(WebKit2, WKImageCreateCGImageCrash)
+{
+ EXPECT_FALSE(WKImageCreateCGImage(nullptr));
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKPageConfiguration.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKPageConfiguration.cpp
new file mode 100644
index 000000000..d041eeaed
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKPageConfiguration.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+
+#include <WebKit/WKWebsiteDataStoreRef.h>
+
+namespace TestWebKitAPI {
+
+TEST(WebKit2, WKPageConfigurationEmpty)
+{
+ WKRetainPtr<WKPageConfigurationRef> configuration = adoptWK(WKPageConfigurationCreate());
+
+ ASSERT_NULL(WKPageConfigurationGetContext(configuration.get()));
+ ASSERT_NULL(WKPageConfigurationGetUserContentController(configuration.get()));
+ ASSERT_NULL(WKPageConfigurationGetPageGroup(configuration.get()));
+ ASSERT_NULL(WKPageConfigurationGetPreferences(configuration.get()));
+ ASSERT_NULL(WKPageConfigurationGetRelatedPage(configuration.get()));
+}
+
+static bool didFinishLoad;
+
+static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef, const void*)
+{
+ didFinishLoad = true;
+}
+
+static void setPageLoaderClient(WKPageRef page)
+{
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+
+ loaderClient.base.version = 0;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+
+ WKPageSetPageLoaderClient(page, &loaderClient.base);
+}
+
+TEST(WebKit2, WKPageConfigurationBasic)
+{
+ WKRetainPtr<WKPageConfigurationRef> configuration = adoptWK(WKPageConfigurationCreate());
+ WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
+ WKPageConfigurationSetContext(configuration.get(), context.get());
+
+ PlatformWebView webView(configuration.get());
+ setPageLoaderClient(webView.page());
+
+ WKRetainPtr<WKPageConfigurationRef> copiedConfiguration = adoptWK(WKPageCopyPageConfiguration(webView.page()));
+ ASSERT_EQ(context.get(), WKPageConfigurationGetContext(copiedConfiguration.get()));
+
+ WKRetainPtr<WKURLRef> url = adoptWK(Util::createURLForResource("simple", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+
+ didFinishLoad = false;
+ Util::run(&didFinishLoad);
+}
+
+TEST(WebKit2, WKPageConfigurationBasicWithDataStore)
+{
+ WKRetainPtr<WKPageConfigurationRef> configuration = adoptWK(WKPageConfigurationCreate());
+ WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
+ WKPageConfigurationSetContext(configuration.get(), context.get());
+ WKRetainPtr<WKWebsiteDataStoreRef> websiteDataStore = WKWebsiteDataStoreGetDefaultDataStore();
+ WKPageConfigurationSetWebsiteDataStore(configuration.get(), websiteDataStore.get());
+
+ PlatformWebView webView(configuration.get());
+ setPageLoaderClient(webView.page());
+
+ WKRetainPtr<WKPageConfigurationRef> copiedConfiguration = adoptWK(WKPageCopyPageConfiguration(webView.page()));
+ ASSERT_EQ(context.get(), WKPageConfigurationGetContext(copiedConfiguration.get()));
+ ASSERT_EQ(WKWebsiteDataStoreGetDefaultDataStore(), WKPageConfigurationGetWebsiteDataStore(copiedConfiguration.get()));
+
+ WKRetainPtr<WKURLRef> url = adoptWK(Util::createURLForResource("simple", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+
+ didFinishLoad = false;
+ Util::run(&didFinishLoad);
+}
+
+TEST(WebKit2, WKPageConfigurationBasicWithNonPersistentDataStore)
+{
+ WKRetainPtr<WKPageConfigurationRef> configuration = adoptWK(WKPageConfigurationCreate());
+ WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
+ WKPageConfigurationSetContext(configuration.get(), context.get());
+ WKRetainPtr<WKWebsiteDataStoreRef> websiteDataStore = adoptWK(WKWebsiteDataStoreCreateNonPersistentDataStore());
+ WKPageConfigurationSetWebsiteDataStore(configuration.get(), websiteDataStore.get());
+
+ PlatformWebView webView(configuration.get());
+ setPageLoaderClient(webView.page());
+
+ WKRetainPtr<WKPageConfigurationRef> copiedConfiguration = adoptWK(WKPageCopyPageConfiguration(webView.page()));
+ ASSERT_EQ(context.get(), WKPageConfigurationGetContext(copiedConfiguration.get()));
+ ASSERT_EQ(websiteDataStore.get(), WKPageConfigurationGetWebsiteDataStore(copiedConfiguration.get()));
+
+ WKRetainPtr<WKURLRef> url = adoptWK(Util::createURLForResource("simple", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+
+ didFinishLoad = false;
+ Util::run(&didFinishLoad);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKPageCopySessionStateWithFiltering.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKPageCopySessionStateWithFiltering.cpp
new file mode 100644
index 000000000..6ce49a13b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKPageCopySessionStateWithFiltering.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+
+namespace TestWebKitAPI {
+
+static bool didFinishLoad;
+static WKRetainPtr<WKSessionStateRef> sessionStateWithFirstItemRemoved;
+static WKRetainPtr<WKSessionStateRef> sessionStateWithAllItemsRemoved;
+
+static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef, const void*)
+{
+ didFinishLoad = true;
+}
+
+static void setPageLoaderClient(WKPageRef page)
+{
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+
+ loaderClient.base.version = 0;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+
+ WKPageSetPageLoaderClient(page, &loaderClient.base);
+}
+
+static bool filterFirstItemCallback(WKPageRef page, WKStringRef valueType, WKTypeRef value, void* context)
+{
+ if (!WKStringIsEqual(valueType, WKPageGetSessionBackForwardListItemValueType()))
+ return true;
+
+ ASSERT(WKGetTypeID(value) == WKBackForwardListItemGetTypeID());
+ WKBackForwardListItemRef backForwardListItem = static_cast<WKBackForwardListItemRef>(value);
+
+ WKRetainPtr<WKURLRef> url = adoptWK(WKBackForwardListItemCopyURL(backForwardListItem));
+ WKRetainPtr<WKStringRef> path = adoptWK(WKURLCopyLastPathComponent(url.get()));
+
+ return !WKStringIsEqualToUTF8CString(path.get(), "simple.html");
+}
+
+static bool filterAllItemsCallback(WKPageRef page, WKStringRef valueType, WKTypeRef value, void* context)
+{
+ return false;
+}
+
+static void createSessionStates(WKContextRef context)
+{
+ PlatformWebView webView(context);
+ setPageLoaderClient(webView.page());
+
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("simple", "html")).get());
+ Util::run(&didFinishLoad);
+ didFinishLoad = false;
+
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("simple2", "html")).get());
+ Util::run(&didFinishLoad);
+ didFinishLoad = false;
+
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("simple3", "html")).get());
+ Util::run(&didFinishLoad);
+ didFinishLoad = false;
+
+ WKPageGoBack(webView.page());
+ Util::run(&didFinishLoad);
+ didFinishLoad = false;
+
+ WKPageGoBack(webView.page());
+ Util::run(&didFinishLoad);
+ didFinishLoad = false;
+
+ // Should be back on simple.html at this point.
+
+ sessionStateWithFirstItemRemoved = adoptWK(static_cast<WKSessionStateRef>(WKPageCopySessionState(webView.page(), reinterpret_cast<void*>(1), filterFirstItemCallback)));
+ sessionStateWithAllItemsRemoved = adoptWK(static_cast<WKSessionStateRef>(WKPageCopySessionState(webView.page(), reinterpret_cast<void*>(1), filterAllItemsCallback)));
+}
+
+TEST(WebKit2, WKPageCopySessionStateWithFiltering)
+{
+ WKRetainPtr<WKContextRef> context(AdoptWK, WKContextCreate());
+
+ createSessionStates(context.get());
+
+ EXPECT_NOT_NULL(sessionStateWithFirstItemRemoved);
+ PlatformWebView webView1(context.get());
+ setPageLoaderClient(webView1.page());
+ WKPageRestoreFromSessionState(webView1.page(), sessionStateWithFirstItemRemoved.get());
+ Util::run(&didFinishLoad);
+ didFinishLoad = false;
+
+ WKBackForwardListRef backForwardList1 = WKPageGetBackForwardList(webView1.page());
+ EXPECT_EQ(0u, WKBackForwardListGetBackListCount(backForwardList1));
+ EXPECT_EQ(1u, WKBackForwardListGetForwardListCount(backForwardList1));
+
+ EXPECT_NOT_NULL(sessionStateWithAllItemsRemoved);
+ PlatformWebView webView2(context.get());
+ setPageLoaderClient(webView2.page());
+ WKPageRestoreFromSessionState(webView2.page(), sessionStateWithAllItemsRemoved.get());
+ // Because the session state ends up being empty, nothing is actually loaded.
+
+ WKBackForwardListRef backForwardList2 = WKPageGetBackForwardList(webView2.page());
+ EXPECT_EQ(0u, WKBackForwardListGetBackListCount(backForwardList2));
+ EXPECT_EQ(0u, WKBackForwardListGetForwardListCount(backForwardList2));
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKPageGetScaleFactorNotZero.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKPageGetScaleFactorNotZero.cpp
index 8ecf1659f..929baaa71 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/WKPageGetScaleFactorNotZero.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKPageGetScaleFactorNotZero.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
@@ -48,7 +51,7 @@ static void setPageLoaderClient(WKPageRef page)
WKPageSetPageLoaderClient(page, &loaderClient.base);
}
-static WKRetainPtr<WKDataRef> createSessionState(WKContextRef context)
+static WKRetainPtr<WKSessionStateRef> createSessionState(WKContextRef context)
{
PlatformWebView webView(context);
setPageLoaderClient(webView.page());
@@ -57,7 +60,7 @@ static WKRetainPtr<WKDataRef> createSessionState(WKContextRef context)
Util::run(&didFinishLoad);
didFinishLoad = false;
- return adoptWK(WKPageCopySessionState(webView.page(), 0, 0));
+ return adoptWK(static_cast<WKSessionStateRef>(WKPageCopySessionState(webView.page(), reinterpret_cast<void*>(1), nullptr)));
}
TEST(WebKit2, WKPageGetScaleFactorNotZero)
@@ -67,13 +70,15 @@ TEST(WebKit2, WKPageGetScaleFactorNotZero)
PlatformWebView webView(context.get());
setPageLoaderClient(webView.page());
- WKRetainPtr<WKDataRef> data = createSessionState(context.get());
- EXPECT_NOT_NULL(data);
+ auto sessionState = createSessionState(context.get());
+ EXPECT_NOT_NULL(sessionState);
- WKPageRestoreFromSessionState(webView.page(), data.get());
+ WKPageRestoreFromSessionState(webView.page(), sessionState.get());
Util::run(&didFinishLoad);
EXPECT_TRUE(WKPageGetScaleFactor(webView.page()) == 1.0);
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKPageIsPlayingAudio.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKPageIsPlayingAudio.cpp
new file mode 100644
index 000000000..1e848133f
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKPageIsPlayingAudio.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2014 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include "Test.h"
+#include <JavaScriptCore/JSRetainPtr.h>
+#include <JavaScriptCore/JavaScriptCore.h>
+#include <WebKit/WKSerializedScriptValue.h>
+#include <WebKit/WKPagePrivate.h>
+#include <WebKit/WKPreferencesRef.h>
+#include <WebKit/WKPreferencesRefPrivate.h>
+
+// This test loads file-with-video.html. It first checks to make sure WKPageIsPlayingAudio() returns
+// false for the page. Then it calls a JavaScript method to play the video, waits for
+// WKPageUIClient::isPlayingAudioDidChange() to get called, and checks that WKPageIsPlayingAudio() now
+// returns true for the page.
+
+namespace TestWebKitAPI {
+
+static bool isMSEEnabledChanged;
+static bool isMSEEnabled;
+static bool didFinishLoad;
+static bool isPlayingAudioChanged;
+
+static void nullJavaScriptCallback(WKSerializedScriptValueRef, WKErrorRef error, void*)
+{
+}
+
+static void isMSEEnabledCallback(WKSerializedScriptValueRef serializedResultValue, WKErrorRef error, void*)
+{
+ JSGlobalContextRef scriptContext = JSGlobalContextCreate(0);
+
+ JSValueRef resultValue = WKSerializedScriptValueDeserialize(serializedResultValue, scriptContext, 0);
+ EXPECT_TRUE(JSValueIsBoolean(scriptContext, resultValue));
+
+ isMSEEnabledChanged = true;
+ isMSEEnabled = JSValueToBoolean(scriptContext, resultValue);
+
+ JSGlobalContextRelease(scriptContext);
+}
+
+static void didFinishLoadForFrame(WKPageRef page, WKFrameRef, WKTypeRef, const void*)
+{
+ didFinishLoad = true;
+}
+
+static void isPlayingAudioDidChangeCallback(WKPageRef page, const void*)
+{
+ isPlayingAudioChanged = true;
+}
+
+static void setUpClients(WKPageRef page)
+{
+ WKPageLoaderClientV0 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+
+ loaderClient.base.version = 0;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+
+ WKPageSetPageLoaderClient(page, &loaderClient.base);
+
+ WKPageUIClientV5 uiClient;
+ memset(&uiClient, 0, sizeof(uiClient));
+
+ uiClient.base.version = 5;
+ uiClient.isPlayingAudioDidChange = isPlayingAudioDidChangeCallback;
+
+ WKPageSetPageUIClient(page, &uiClient.base);
+}
+
+TEST(WebKit2, WKPageIsPlayingAudio)
+{
+ WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
+
+ PlatformWebView webView(context.get());
+ setUpClients(webView.page());
+
+ WKRetainPtr<WKURLRef> url = adoptWK(Util::createURLForResource("file-with-video", "html"));
+ WKPageLoadURL(webView.page(), url.get());
+
+ Util::run(&didFinishLoad);
+
+ EXPECT_FALSE(WKPageIsPlayingAudio(webView.page()));
+ WKPageRunJavaScriptInMainFrame(webView.page(), Util::toWK("playVideo()").get(), 0, nullJavaScriptCallback);
+
+ Util::run(&isPlayingAudioChanged);
+ EXPECT_TRUE(WKPageIsPlayingAudio(webView.page()));
+}
+
+TEST(WebKit2, MSEIsPlayingAudio)
+{
+ WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
+
+ WKRetainPtr<WKPageGroupRef> pageGroup(AdoptWK, WKPageGroupCreateWithIdentifier(Util::toWK("MSEIsPlayingAudioPageGroup").get()));
+ WKPreferencesRef preferences = WKPageGroupGetPreferences(pageGroup.get());
+ WKPreferencesSetMediaSourceEnabled(preferences, true);
+ WKPreferencesSetFileAccessFromFileURLsAllowed(preferences, true);
+
+ PlatformWebView webView(context.get(), pageGroup.get());
+ setUpClients(webView.page());
+
+ WKRetainPtr<WKURLRef> url = adoptWK(Util::createURLForResource("file-with-mse", "html"));
+ didFinishLoad = false;
+ WKPageLoadURL(webView.page(), url.get());
+
+ Util::run(&didFinishLoad);
+
+ // Bail out of the test early if the platform does not support MSE.
+ isMSEEnabledChanged = false;
+ WKPageRunJavaScriptInMainFrame(webView.page(), Util::toWK("window.MediaSource !== undefined").get(), 0, isMSEEnabledCallback);
+ Util::run(&isMSEEnabledChanged);
+ if (!isMSEEnabled)
+ return;
+
+ EXPECT_FALSE(WKPageIsPlayingAudio(webView.page()));
+ isPlayingAudioChanged = false;
+ WKPageRunJavaScriptInMainFrame(webView.page(), Util::toWK("playVideo()").get(), 0, nullJavaScriptCallback);
+
+ Util::run(&isPlayingAudioChanged);
+ EXPECT_TRUE(WKPageIsPlayingAudio(webView.page()));
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKPreferences.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKPreferences.cpp
index 976e7041b..7f8616f5d 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/WKPreferences.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKPreferences.cpp
@@ -24,9 +24,12 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
-#include <WebKit2/WKPreferencesPrivate.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKPreferencesRefPrivate.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -41,15 +44,15 @@ TEST(WebKit2, WKPreferencesBasic)
TEST(WebKit2, WKPreferencesDefaults)
{
-#if PLATFORM(WIN)
- static const char* expectedStandardFontFamily = "Times New Roman";
+#if PLATFORM(GTK) || PLATFORM(EFL)
+ static const char* expectedStandardFontFamily = "Times";
static const char* expectedFixedFontFamily = "Courier New";
- static const char* expectedSerifFontFamily = "Times New Roman";
- static const char* expectedSansSerifFontFamily = "Arial";
+ static const char* expectedSerifFontFamily = "Times";
+ static const char* expectedSansSerifFontFamily = "Helvetica";
static const char* expectedCursiveFontFamily = "Comic Sans MS";
- static const char* expectedFantasyFontFamily = "Comic Sans MS";
- static const char* expectedPictographFontFamily = "Times New Roman";
-#elif PLATFORM(MAC)
+ static const char* expectedFantasyFontFamily = "Impact";
+ static const char* expectedPictographFontFamily = "Times";
+#elif WK_HAVE_C_SPI
static const char* expectedStandardFontFamily = "Times";
static const char* expectedFixedFontFamily = "Courier";
static const char* expectedSerifFontFamily = "Times";
@@ -57,21 +60,21 @@ TEST(WebKit2, WKPreferencesDefaults)
static const char* expectedCursiveFontFamily = "Apple Chancery";
static const char* expectedFantasyFontFamily = "Papyrus";
static const char* expectedPictographFontFamily = "Apple Color Emoji";
-#elif PLATFORM(GTK) || PLATFORM(EFL)
+#elif PLATFORM(IOS)
static const char* expectedStandardFontFamily = "Times";
- static const char* expectedFixedFontFamily = "Courier New";
+ static const char* expectedFixedFontFamily = "Courier";
static const char* expectedSerifFontFamily = "Times";
static const char* expectedSansSerifFontFamily = "Helvetica";
- static const char* expectedCursiveFontFamily = "Comic Sans MS";
- static const char* expectedFantasyFontFamily = "Impact";
- static const char* expectedPictographFontFamily = "Times";
+ static const char* expectedCursiveFontFamily = "Snell Roundhand";
+ static const char* expectedFantasyFontFamily = "Papyrus";
+ static const char* expectedPictographFontFamily = "AppleColorEmoji";
#endif
WKPreferencesRef preference = WKPreferencesCreate();
EXPECT_TRUE(WKPreferencesGetJavaScriptEnabled(preference));
EXPECT_TRUE(WKPreferencesGetLoadsImagesAutomatically(preference));
- EXPECT_FALSE(WKPreferencesGetOfflineWebApplicationCacheEnabled(preference));
+ EXPECT_TRUE(WKPreferencesGetOfflineWebApplicationCacheEnabled(preference));
EXPECT_TRUE(WKPreferencesGetLocalStorageEnabled(preference));
EXPECT_TRUE(WKPreferencesGetXSSAuditorEnabled(preference));
EXPECT_FALSE(WKPreferencesGetFrameFlatteningEnabled(preference));
@@ -91,11 +94,7 @@ TEST(WebKit2, WKPreferencesDefaults)
EXPECT_FALSE(WKPreferencesGetDeveloperExtrasEnabled(preference));
EXPECT_TRUE(WKPreferencesGetTextAreasAreResizable(preference));
-#if PLATFORM(WIN)
- EXPECT_EQ(kWKFontSmoothingLevelWindows, WKPreferencesGetFontSmoothingLevel(preference));
-#else
EXPECT_EQ(kWKFontSmoothingLevelMedium, WKPreferencesGetFontSmoothingLevel(preference));
-#endif
EXPECT_TRUE(WKPreferencesGetAcceleratedCompositingEnabled(preference));
EXPECT_FALSE(WKPreferencesGetCompositingBordersVisible(preference));
@@ -122,3 +121,5 @@ TEST(WebKit2, WKPreferencesCopying)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKRetainPtr.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKRetainPtr.cpp
new file mode 100644
index 000000000..860d7d48d
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKRetainPtr.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include <wtf/HashMap.h>
+
+namespace TestWebKitAPI {
+
+TEST(WebKit2, WKRetainPtr)
+{
+ WKRetainPtr<WKStringRef> string1 = adoptWK(WKStringCreateWithUTF8CString("a"));
+ WKRetainPtr<WKStringRef> string2 = adoptWK(WKStringCreateWithUTF8CString("a"));
+ WKRetainPtr<WKStringRef> string3 = adoptWK(WKStringCreateWithUTF8CString("a"));
+ WKRetainPtr<WKStringRef> string4 = adoptWK(WKStringCreateWithUTF8CString("a"));
+
+ HashMap<WKRetainPtr<WKStringRef>, int> map;
+
+ map.set(string2, 2);
+ map.set(string1, 1);
+
+ EXPECT_TRUE(map.contains(string1));
+ EXPECT_TRUE(map.contains(string2));
+ EXPECT_FALSE(map.contains(string3));
+ EXPECT_FALSE(map.contains(string4));
+
+ EXPECT_EQ(1, map.get(string1));
+ EXPECT_EQ(2, map.get(string2));
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKString.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKString.cpp
index b67235932..b4167be81 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/WKString.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKString.cpp
@@ -25,6 +25,8 @@
#include "config.h"
+#if WK_HAVE_C_SPI
+
namespace TestWebKitAPI {
TEST(WebKit2, WKString)
@@ -69,3 +71,5 @@ TEST(WebKit2, WKString)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WKStringJSString.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WKStringJSString.cpp
index cdba57de4..8b6e08b9d 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/WKStringJSString.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WKStringJSString.cpp
@@ -24,7 +24,10 @@
*/
#include "config.h"
-#include <WebKit2/WKStringPrivate.h>
+
+#if WK_HAVE_C_SPI
+
+#include <WebKit/WKStringPrivate.h>
#include <JavaScriptCore/JSStringRef.h>
namespace TestWebKitAPI {
@@ -48,3 +51,5 @@ TEST(WebKit2, WKStringJSString)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WebArchive.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WebArchive.cpp
new file mode 100644
index 000000000..06d673e21
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WebArchive.cpp
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2011 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "PlatformWebView.h"
+#include <CoreFoundation/CoreFoundation.h>
+#include <WebKit/WKURLCF.h>
+#include <WebKit/WKContextPrivate.h>
+#include <wtf/RetainPtr.h>
+
+namespace TestWebKitAPI {
+
+static bool didFinishLoad;
+static bool didReceiveMessage;
+
+static void didReceiveMessageFromInjectedBundle(WKContextRef, WKStringRef messageName, WKTypeRef body, const void*)
+{
+ didReceiveMessage = true;
+
+ EXPECT_WK_STREQ("DidGetWebArchive", messageName);
+ EXPECT_TRUE(body);
+ EXPECT_EQ(WKDataGetTypeID(), WKGetTypeID(body));
+ WKDataRef receivedData = static_cast<WKDataRef>(body);
+
+ // Do basic sanity checks on the returned webarchive. We have more thorough checks in LayoutTests.
+ size_t size = WKDataGetSize(receivedData);
+ const unsigned char* bytes = WKDataGetBytes(receivedData);
+ RetainPtr<CFDataRef> data = adoptCF(CFDataCreate(0, bytes, size));
+ RetainPtr<CFPropertyListRef> propertyList = adoptCF(CFPropertyListCreateWithData(0, data.get(), kCFPropertyListImmutable, 0, 0));
+ EXPECT_TRUE(propertyList);
+
+ // It should be a dictionary.
+ EXPECT_EQ(CFDictionaryGetTypeID(), CFGetTypeID(propertyList.get()));
+ CFDictionaryRef dictionary = (CFDictionaryRef)propertyList.get();
+
+ // It should have a main resource.
+ CFTypeRef mainResource = CFDictionaryGetValue(dictionary, CFSTR("WebMainResource"));
+ EXPECT_TRUE(mainResource);
+ EXPECT_EQ(CFDictionaryGetTypeID(), CFGetTypeID(mainResource));
+ CFDictionaryRef mainResourceDictionary = (CFDictionaryRef)mainResource;
+
+ // Main resource should have a non-empty url and mime type.
+ CFTypeRef url = CFDictionaryGetValue(mainResourceDictionary, CFSTR("WebResourceURL"));
+ EXPECT_TRUE(url);
+ EXPECT_EQ(CFStringGetTypeID(), CFGetTypeID(url));
+ EXPECT_NE(CFStringGetLength((CFStringRef)url), 0);
+
+ CFTypeRef mimeType = CFDictionaryGetValue(mainResourceDictionary, CFSTR("WebResourceMIMEType"));
+ EXPECT_TRUE(mimeType);
+ EXPECT_EQ(CFStringGetTypeID(), CFGetTypeID(mimeType));
+ EXPECT_NE(CFStringGetLength((CFStringRef)mimeType), 0);
+
+ // Main resource dictionary should have a "WebResourceData" key.
+ CFTypeRef resourceData = CFDictionaryGetValue(mainResourceDictionary, CFSTR("WebResourceData"));
+ EXPECT_TRUE(resourceData);
+ EXPECT_EQ(CFDataGetTypeID(), CFGetTypeID(resourceData));
+
+ RetainPtr<CFStringRef> stringData = adoptCF(CFStringCreateFromExternalRepresentation(0, (CFDataRef)resourceData, kCFStringEncodingUTF8));
+ EXPECT_TRUE(stringData);
+
+ // It should contain the string "Simple HTML file." in it.
+ bool foundString = CFStringFind(stringData.get(), CFSTR("Simple HTML file."), 0).location != kCFNotFound;
+ EXPECT_TRUE(foundString);
+}
+
+static void setInjectedBundleClient(WKContextRef context)
+{
+ WKContextInjectedBundleClientV0 injectedBundleClient;
+ memset(&injectedBundleClient, 0, sizeof(injectedBundleClient));
+
+ injectedBundleClient.base.version = 0;
+ injectedBundleClient.didReceiveMessageFromInjectedBundle = didReceiveMessageFromInjectedBundle;
+
+ WKContextSetInjectedBundleClient(context, &injectedBundleClient.base);
+}
+
+static void didFinishLoadForFrame(WKPageRef page, WKFrameRef, WKTypeRef, const void*)
+{
+ didFinishLoad = true;
+}
+
+TEST(WebKit2, WebArchive)
+{
+ WKRetainPtr<WKContextRef> context = adoptWK(Util::createContextForInjectedBundleTest("WebArchiveTest"));
+ setInjectedBundleClient(context.get());
+
+ PlatformWebView webView(context.get());
+
+ WKPageLoaderClientV3 loaderClient;
+ memset(&loaderClient, 0, sizeof(loaderClient));
+
+ loaderClient.base.version = 3;
+ loaderClient.didFinishLoadForFrame = didFinishLoadForFrame;
+
+ WKPageSetPageLoaderClient(webView.page(), &loaderClient.base);
+
+ WKPageLoadURL(webView.page(), adoptWK(Util::createURLForResource("simple", "html")).get());
+
+ // Wait till the load finishes before getting the web archive.
+ Util::run(&didFinishLoad);
+ WKContextPostMessageToInjectedBundle(context.get(), Util::toWK("GetWebArchive").get(), webView.page());
+
+ // Wait till we have received the web archive from the injected bundle.
+ Util::run(&didReceiveMessage);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WebArchive_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WebArchive_Bundle.cpp
new file mode 100644
index 000000000..11109fee0
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WebArchive_Bundle.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2011 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "InjectedBundleTest.h"
+
+#include "PlatformUtilities.h"
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKBundleFrame.h>
+
+namespace TestWebKitAPI {
+
+class WebArchiveTest : public InjectedBundleTest {
+public:
+ WebArchiveTest(const std::string& identifier);
+
+private:
+ virtual void didReceiveMessage(WKBundleRef, WKStringRef messageName, WKTypeRef messageBody);
+};
+
+static InjectedBundleTest::Register<WebArchiveTest> registrar("WebArchiveTest");
+
+WebArchiveTest::WebArchiveTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+{
+}
+
+void WebArchiveTest::didReceiveMessage(WKBundleRef bundle, WKStringRef messageName, WKTypeRef body)
+{
+ if (!WKStringIsEqualToUTF8CString(messageName, "GetWebArchive"))
+ return;
+
+ if (WKGetTypeID(body) != WKBundlePageGetTypeID())
+ return;
+
+ WKBundleFrameRef frame = WKBundlePageGetMainFrame(static_cast<WKBundlePageRef>(body));
+ if (!frame)
+ return;
+ WKBundlePostMessage(bundle, Util::toWK("DidGetWebArchive").get(), adoptWK(WKBundleFrameCopyWebArchive(frame)).get());
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WebCoreStatisticsWithNoWebProcess.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WebCoreStatisticsWithNoWebProcess.cpp
new file mode 100644
index 000000000..ff5eef04d
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WebCoreStatisticsWithNoWebProcess.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "PlatformUtilities.h"
+#include "Test.h"
+
+namespace TestWebKitAPI {
+
+static bool done;
+
+// Callback for WKContextGetStatistics.
+static void wkContextGetStatisticsCallback(WKDictionaryRef statistics, WKErrorRef error, void* functionContext)
+{
+ EXPECT_NOT_NULL(error);
+ done = true;
+}
+
+TEST(WebKit2, WebCoreStatisticsWithNoWebProcess)
+{
+ WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
+
+ WKContextGetStatistics(context.get(), 0, wkContextGetStatisticsCallback);
+
+ Util::run(&done);
+}
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WillLoad.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WillLoad.cpp
index 0f0bf4caf..83d63ab18 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/WillLoad.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WillLoad.cpp
@@ -24,12 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "Test.h"
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
namespace TestWebKitAPI {
@@ -41,7 +42,7 @@ public:
}
WKRetainPtr<WKContextRef> context;
- OwnPtr<PlatformWebView> webView;
+ std::unique_ptr<PlatformWebView> webView;
WKRetainPtr<WKStringRef> messageName;
WKRetainPtr<WKTypeRef> messageBody;
@@ -71,7 +72,7 @@ public:
context = adoptWK(Util::createContextForInjectedBundleTest("WillLoadTest"));
setInjectedBundleClient(context.get(), this);
- webView = adoptPtr(new PlatformWebView(context.get()));
+ webView = std::make_unique<PlatformWebView>(context.get());
didReceiveMessage = false;
}
@@ -239,3 +240,5 @@ TEST_F(WebKit2WillLoadTest, WKPageLoadPlainTextString)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WillLoad_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WillLoad_Bundle.cpp
index 783aebe7a..906ff05b7 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/WillLoad_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WillLoad_Bundle.cpp
@@ -24,11 +24,14 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundlePage.h>
-#include <WebKit2/WKRetainPtr.h>
+#include <WebKit/WKBundlePage.h>
+#include <WebKit/WKRetainPtr.h>
namespace TestWebKitAPI {
@@ -47,7 +50,7 @@ private:
WKDictionarySetItem(messageBody.get(), Util::toWK("URLRequestReturn").get(), request);
WKDictionarySetItem(messageBody.get(), Util::toWK("UserDataReturn").get(), userData);
- WKBundlePostMessage(InjectedBundleController::shared().bundle(), Util::toWK("WillLoadURLRequestReturn").get(), messageBody.get());
+ WKBundlePostMessage(InjectedBundleController::singleton().bundle(), Util::toWK("WillLoadURLRequestReturn").get(), messageBody.get());
}
static void willLoadDataRequest(WKBundlePageRef page, WKURLRequestRef request, WKDataRef data, WKStringRef MIMEType, WKStringRef encodingName, WKURLRef unreachableURL, WKTypeRef userData, const void *clientInfo)
@@ -61,11 +64,11 @@ private:
WKDictionarySetItem(messageBody.get(), Util::toWK("UnreachableURLReturn").get(), unreachableURL);
WKDictionarySetItem(messageBody.get(), Util::toWK("UserDataReturn").get(), userData);
- WKBundlePostMessage(InjectedBundleController::shared().bundle(), Util::toWK("WillLoadDataRequestReturn").get(), messageBody.get());
+ WKBundlePostMessage(InjectedBundleController::singleton().bundle(), Util::toWK("WillLoadDataRequestReturn").get(), messageBody.get());
}
- virtual void didCreatePage(WKBundleRef, WKBundlePageRef bundlePage) override
+ void didCreatePage(WKBundleRef, WKBundlePageRef bundlePage) override
{
WKBundlePageLoaderClientV6 pageLoaderClient;
memset(&pageLoaderClient, 0, sizeof(pageLoaderClient));
@@ -82,3 +85,5 @@ private:
static InjectedBundleTest::Register<WillLoadTest> registrar("WillLoadTest");
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent.cpp
index ee5934688..951aaf005 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent.cpp
@@ -24,6 +24,9 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "PlatformUtilities.h"
#include "PlatformWebView.h"
#include "Test.h"
@@ -77,3 +80,5 @@ TEST(WebKit2, WillSendSubmitEvent)
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent_Bundle.cpp
index e85ca256f..fa7d2a9a7 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent_Bundle.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/WillSendSubmitEvent_Bundle.cpp
@@ -24,10 +24,13 @@
*/
#include "config.h"
+
+#if WK_HAVE_C_SPI
+
#include "InjectedBundleTest.h"
#include "PlatformUtilities.h"
-#include <WebKit2/WKBundlePage.h>
+#include <WebKit/WKBundlePage.h>
namespace TestWebKitAPI {
@@ -42,7 +45,7 @@ static InjectedBundleTest::Register<WillSendSubmitEventTest> registrar("WillSend
static void willSendSubmitEvent(WKBundlePageRef, WKBundleNodeHandleRef, WKBundleFrameRef, WKBundleFrameRef, WKDictionaryRef values, const void*)
{
- WKBundlePostMessage(InjectedBundleController::shared().bundle(), Util::toWK("DidReceiveWillSendSubmitEvent").get(), values);
+ WKBundlePostMessage(InjectedBundleController::singleton().bundle(), Util::toWK("DidReceiveWillSendSubmitEvent").get(), values);
}
WillSendSubmitEventTest::WillSendSubmitEventTest(const std::string& identifier)
@@ -63,3 +66,5 @@ void WillSendSubmitEventTest::didCreatePage(WKBundleRef bundle, WKBundlePageRef
}
} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/all-content-in-one-iframe.html b/Tools/TestWebKitAPI/Tests/WebKit2/all-content-in-one-iframe.html
new file mode 100644
index 000000000..6f45cbd6b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/all-content-in-one-iframe.html
@@ -0,0 +1 @@
+<iframe src="lots-of-text.html"></iframe>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/associate-form-controls.html b/Tools/TestWebKitAPI/Tests/WebKit2/associate-form-controls.html
new file mode 100644
index 000000000..906246a54
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/associate-form-controls.html
@@ -0,0 +1,31 @@
+<html>
+<head>
+ <script>
+ function addForm()
+ {
+ var form = document.createElement("form");
+ form.id = "login_form";
+
+ var usernameField = document.createElement("input");
+ usernameField.id = "username";
+ usernameField.type = "text";
+ form.appendChild(usernameField);
+
+ document.body.appendChild(form);
+ }
+
+ function addPasswordFieldToForm()
+ {
+ var passwordField = document.createElement("input");
+ passwordField.id = "password";
+ passwordField.type = "password";
+
+ var form = document.getElementById("login_form");
+ form.appendChild(passwordField);
+ }
+ </script>
+</head>
+<body onload="addForm()">
+<button onclick="addPasswordFieldToForm()">Manual Testing: Add the password field</button>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/auto-submitting-form.html b/Tools/TestWebKitAPI/Tests/WebKit2/auto-submitting-form.html
new file mode 100644
index 000000000..9ed815e03
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/auto-submitting-form.html
@@ -0,0 +1,20 @@
+<html>
+ <head>
+ <script>
+ function submitFormIfNecessary()
+ {
+ if (window.location.search)
+ return;
+ document.forms[0].submit.click();
+ }
+ </script>
+ </head>
+ <body onload="submitFormIfNecessary()">
+ <form action="#" method="GET">
+ <input type="text" name="textField" value="text field">
+ <input type="password" name="passwordField" value="password field">
+ <input type="hidden" name="hiddenField" value="hidden field">
+ <input type="submit" name="submit">
+ </form>
+ </body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/autoplay-check-frame.html b/Tools/TestWebKitAPI/Tests/WebKit2/autoplay-check-frame.html
new file mode 100644
index 000000000..2c43fda1a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/autoplay-check-frame.html
@@ -0,0 +1,16 @@
+<html>
+ <head>
+ <script>
+ function pageLoaded() {
+ document.getElementById("video").play().then(function() {
+ window.parent.postMessage('autoplayed', '*');
+ }).catch(function() {
+ window.parent.postMessage('did-not-play', '*');
+ });
+ }
+ </script>
+ </head>
+ <body onload="pageLoaded()">
+ <video id="video" playsinline src="test.mp4" />
+ </body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/autoplay-check-in-iframe.html b/Tools/TestWebKitAPI/Tests/WebKit2/autoplay-check-in-iframe.html
new file mode 100644
index 000000000..f1a3cbc8f
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/autoplay-check-in-iframe.html
@@ -0,0 +1,16 @@
+<html>
+ <head>
+ <script>
+ function pageLoaded() {
+ window.onmessage = function(event) {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage(event.data);
+ } catch(e) { }
+ };
+ }
+ </script>
+ </head>
+ <body onload="pageLoaded()">
+ <iframe src="autoplay-check-frame.html"></iframe>
+ </body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/autoplay-check.html b/Tools/TestWebKitAPI/Tests/WebKit2/autoplay-check.html
new file mode 100644
index 000000000..ecc3c884e
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/autoplay-check.html
@@ -0,0 +1,20 @@
+<html>
+ <head>
+ <script>
+ function pageLoaded() {
+ document.getElementById("video").play().then(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("autoplayed");
+ } catch(e) { }
+ }).catch(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("did-not-play");
+ } catch(e) { }
+ });
+ }
+ </script>
+ </head>
+ <body onload="pageLoaded()">
+ <video id="video" playsinline src="test.mp4" />
+ </body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/autoplay-no-audio-check.html b/Tools/TestWebKitAPI/Tests/WebKit2/autoplay-no-audio-check.html
new file mode 100644
index 000000000..dc1cc7325
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/autoplay-no-audio-check.html
@@ -0,0 +1,20 @@
+<html>
+ <head>
+ <script>
+ function pageLoaded() {
+ document.getElementById("video").play().then(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("autoplayed");
+ } catch(e) { }
+ }).catch(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("did-not-play");
+ } catch(e) { }
+ });
+ }
+ </script>
+ </head>
+ <body onload="pageLoaded()">
+ <video id="video" playsinline src="test-without-audio-track.mp4" />
+ </body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/autoplay-with-controls.html b/Tools/TestWebKitAPI/Tests/WebKit2/autoplay-with-controls.html
new file mode 100644
index 000000000..cf80a6578
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/autoplay-with-controls.html
@@ -0,0 +1,19 @@
+<html>
+ <head>
+ <script>
+ function pageLoaded() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("loaded");
+ } catch(e) { }
+ }
+
+ function play() {
+ document.getElementById("video").play();
+ }
+ </script>
+ </head>
+ <body onload="pageLoaded()">
+ <button onclick="play()">Play</button>
+ <video id="video" autoplay src="test.mp4" />
+ </body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/bundle-file.html b/Tools/TestWebKitAPI/Tests/WebKit2/bundle-file.html
new file mode 100644
index 000000000..f426ebdb0
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/bundle-file.html
@@ -0,0 +1,16 @@
+<html>
+<head>
+ <script>
+ function testFile(file)
+ {
+ if (!(file instanceof File))
+ return false;
+
+ return true;
+ }
+ </script>
+</head>
+<body>
+ File test.
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/chinese-character-with-image.html b/Tools/TestWebKitAPI/Tests/WebKit2/chinese-character-with-image.html
new file mode 100644
index 000000000..179085749
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/chinese-character-with-image.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<meta http-equiv='content-type' content='text/html; charset=utf-8'>
+<body>
+<div contenteditable>
+<p><br></p>
+<p style="text-align: center; font-size: 15px;"><img src="icon.png">你</p>
+<p>hello, world</p>
+</div>
+<script>
+document.querySelector('div').focus();
+getSelection().setPosition(document.querySelector('img').parentNode, 1);
+</script>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/close-from-within-create-page.html b/Tools/TestWebKitAPI/Tests/WebKit2/close-from-within-create-page.html
new file mode 100644
index 000000000..51c7981c1
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/close-from-within-create-page.html
@@ -0,0 +1,16 @@
+<html>
+<script>
+function runTest()
+{
+ if (document.location.search === "?opened-window") {
+ alert(window.sessionStorage['storageKey'])
+ return;
+ }
+
+ window.sessionStorage['storageKey'] = 'value';
+ window.open("close-from-within-create-page.html?opened-window");
+}
+</script>
+<body onload="runTest()">
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/closed-shadow-tree-test.html b/Tools/TestWebKitAPI/Tests/WebKit2/closed-shadow-tree-test.html
new file mode 100644
index 000000000..a161563e2
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/closed-shadow-tree-test.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<body>
+<shadow-host><span>5</span><span slot="bar">2</span></shadow-host>
+<input type="text">
+<script>
+const shadowRoot = document.querySelector('shadow-host').attachShadow({mode: 'closed'});
+shadowRoot.innerHTML = `
+ <span>1</span>
+ <inner-host>
+ <slot name="bar" slot="foo"><span>FAIL - named slot fallback</span></slot>
+ <span>FAIL - unassigned content</span>
+ <span slot="foo">3</span>
+ </inner-host>
+ <slot><span>FAIL - default slot fallback</span></slot>
+ <span>6</span>`;
+const innerHost = shadowRoot.querySelector('inner-host');
+innerHost.attachShadow({mode: 'closed'}).innerHTML = `
+ <slot name="foo"></slot>
+ <span>4</span>`;
+
+document.addEventListener('testnormalworld', function (event) {
+ alert(window[event.detail] ? `FAIL: ${event.detail} was present in the normal world` : `PASS: ${event.detail} was not present in the normal world`);
+});
+
+</script>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/contentBlockerCheck.html b/Tools/TestWebKitAPI/Tests/WebKit2/contentBlockerCheck.html
new file mode 100644
index 000000000..c791a857a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/contentBlockerCheck.html
@@ -0,0 +1,13 @@
+<html>
+ <head>
+ <script>
+ function sendMessage() { alert(getComputedStyle(document.querySelector(".hidden")).display == "none" ? "content blockers enabled" :"content blockers disabled"); }
+ </script>
+ </head>
+ <body onload="sendMessage()">
+ <p class="hidden">
+ This text exists to determine if content blockers are enabled.
+ If they're enabled, the computed style of this text will be display:none.
+ </p>
+ </body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/custom-protocol-sync-xhr.html b/Tools/TestWebKitAPI/Tests/WebKit2/custom-protocol-sync-xhr.html
new file mode 100644
index 000000000..6cf00b6ca
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/custom-protocol-sync-xhr.html
@@ -0,0 +1,6 @@
+<script>
+ var request = new XMLHttpRequest();
+ request.open('GET', 'http://test', false);
+ request.send(null);
+ window._testResult = request.responseText;
+</script> \ No newline at end of file
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/enumerateMediaDevices.html b/Tools/TestWebKitAPI/Tests/WebKit2/enumerateMediaDevices.html
new file mode 100644
index 000000000..ffde3ced5
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/enumerateMediaDevices.html
@@ -0,0 +1,24 @@
+<html>
+ <head>
+ <script>
+ function enumerate(devices)
+ {
+ console.log("enumerateDevices succeeded");
+ }
+
+ function userMediaError(error)
+ {
+ console.log(error);
+ }
+
+ function test()
+ {
+ navigator.mediaDevices.enumerateDevices()
+ .then(enumerate)
+ .catch(userMediaError);
+ }
+ </script>
+ </head>
+ <body onload="test()">
+ </body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/execCopy.html b/Tools/TestWebKitAPI/Tests/WebKit2/execCopy.html
new file mode 100644
index 000000000..cf4608ebd
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/execCopy.html
@@ -0,0 +1,15 @@
+<html>
+<head>
+<script type="text/javascript">
+ function doCopy() {
+ document.execCommand("selectAll", true);
+ document.execCommand("copy");
+ }
+</script>
+</head>
+<body onLoad="doCopy()">
+ <div>Hello world.</div>
+ <div><b>Hello</b><i> world</i></div>
+ <div style="border: solid red 1px">Hello world</div>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/file-with-anchor.html b/Tools/TestWebKitAPI/Tests/WebKit2/file-with-anchor.html
new file mode 100644
index 000000000..8ea866ba9
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/file-with-anchor.html
@@ -0,0 +1,19 @@
+<html>
+<head>
+ <script>
+ function clickLink()
+ {
+ var evt = document.createEvent("MouseEvent");
+ evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ var link = document.querySelector('a');
+ link.dispatchEvent(evt);
+ }
+ </script>
+</head>
+<body>
+ <a href="#anchor">Link to anchor</a><br>
+ In between.<br>
+ <span id="anchor">Anchor</span><br>
+ After the anchor.<br>
+ </body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/file-with-mse.html b/Tools/TestWebKitAPI/Tests/WebKit2/file-with-mse.html
new file mode 100644
index 000000000..4cc910135
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/file-with-mse.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script>
+ var source;
+ var request;
+
+ function playVideo()
+ {
+ document.getElementById('test-video').play();
+ request = new XMLHttpRequest();
+ request.responseType = 'arraybuffer';
+ request.open('GET', 'test-mse.mp4', true);
+ request.addEventListener('load', load);
+ request.send();
+ }
+
+ function load(event)
+ {
+ source = new MediaSource();
+ source.addEventListener('sourceopen', sourceopen);
+ var video = document.getElementById('test-video');
+ video.src = URL.createObjectURL(source);
+ }
+
+ function sourceopen(event)
+ {
+ var sourceBuffer = source.addSourceBuffer('video/mp4;codecs="avc1.4D4001,mp4a.40.2"');
+ sourceBuffer.appendBuffer(request.response);
+ }
+ </script>
+</head>
+<body>
+ <p>
+ <video id="test-video" controls></video>
+ </p>
+ <p>
+ <button onclick="playVideo()">Play video</button>
+ </p>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/file-with-video.html b/Tools/TestWebKitAPI/Tests/WebKit2/file-with-video.html
new file mode 100644
index 000000000..aa2259a0f
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/file-with-video.html
@@ -0,0 +1,18 @@
+<html>
+<head>
+ <script>
+ function playVideo()
+ {
+ document.getElementById("test-video").play();
+ }
+ </script>
+</head>
+<body>
+ <p>
+ <video id="test-video" src="test.mp4" controls></video>
+ </p>
+ <p>
+ <button onclick="playVideo()">Play Video</button>
+ </p>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/find.html b/Tools/TestWebKitAPI/Tests/WebKit2/find.html
new file mode 100644
index 000000000..d9659119d
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/find.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+ Test search. Hello Hello Hello!
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/findRanges.html b/Tools/TestWebKitAPI/Tests/WebKit2/findRanges.html
new file mode 100644
index 000000000..e10bbeb47
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/findRanges.html
@@ -0,0 +1,11 @@
+<html>
+<body>Test search. Hello world, Hello crazy world, Hello!</body>
+<script>
+ var s = window.getSelection();
+ var r = document.createRange();
+
+ r.setStart(document.body.firstChild, 38);
+ r.setEnd(document.body.firstChild, 43);
+ s.addRange(r);
+</script>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/geolocationGetCurrentPosition.html b/Tools/TestWebKitAPI/Tests/WebKit2/geolocationGetCurrentPosition.html
new file mode 100644
index 000000000..099f51536
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/geolocationGetCurrentPosition.html
@@ -0,0 +1,3 @@
+<script>
+navigator.geolocation.getCurrentPosition(function() { });
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/geolocationGetCurrentPositionWithHighAccuracy.html b/Tools/TestWebKitAPI/Tests/WebKit2/geolocationGetCurrentPositionWithHighAccuracy.html
new file mode 100644
index 000000000..26a314858
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/geolocationGetCurrentPositionWithHighAccuracy.html
@@ -0,0 +1,3 @@
+<script>
+navigator.geolocation.getCurrentPosition(function() { }, function() {}, { enableHighAccuracy:true });
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/geolocationWatchPosition.html b/Tools/TestWebKitAPI/Tests/WebKit2/geolocationWatchPosition.html
new file mode 100644
index 000000000..24788b780
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/geolocationWatchPosition.html
@@ -0,0 +1,3 @@
+<script>
+navigator.geolocation.watchPosition(function() { });
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/geolocationWatchPositionWithHighAccuracy.html b/Tools/TestWebKitAPI/Tests/WebKit2/geolocationWatchPositionWithHighAccuracy.html
new file mode 100644
index 000000000..aba98fce7
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/geolocationWatchPositionWithHighAccuracy.html
@@ -0,0 +1,3 @@
+<script>
+navigator.geolocation.watchPosition(function() { }, function() {}, { enableHighAccuracy:true });
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/getUserMedia.html b/Tools/TestWebKitAPI/Tests/WebKit2/getUserMedia.html
new file mode 100644
index 000000000..e54f853bf
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/getUserMedia.html
@@ -0,0 +1,14 @@
+<script>
+function gotUserMedia(mediaStream)
+{
+ console.log("Got user media");
+}
+
+function userMediaError(error)
+{
+ console.log(error);
+}
+
+var options = { audio: false, video: true};
+navigator.webkitGetUserMedia(options, gotUserMedia, userMediaError);
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/gtk/InputMethodFilter.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/gtk/InputMethodFilter.cpp
index 4aab7c0a2..4a0e684d6 100644
--- a/Tools/TestWebKitAPI/Tests/gtk/InputMethodFilter.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/gtk/InputMethodFilter.cpp
@@ -25,44 +25,45 @@
#include "config.h"
-#include "GtkInputMethodFilter.h"
#include "WTFStringUtilities.h"
+#include <WebKit/InputMethodFilter.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
-#include <wtf/gobject/GUniquePtr.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/glib/GUniquePtr.h>
#include <wtf/text/CString.h>
-using namespace WebCore;
+using namespace WebKit;
namespace TestWebKitAPI {
-class TestInputMethodFilter : public GtkInputMethodFilter {
+class TestInputMethodFilter : public InputMethodFilter {
public:
TestInputMethodFilter()
: m_testWindow(gtk_window_new(GTK_WINDOW_POPUP))
{
- gtk_widget_show(m_testWindow.get());
- setWidget(m_testWindow.get());
+ setTestingMode(true);
- // Focus in is necessary to activate the default input method in the multicontext.
- notifyFocusedIn();
+ gtk_widget_show(m_testWindow);
+ gtk_im_context_set_client_window(context(), gtk_widget_get_window(m_testWindow));
+
+ setEnabled(true);
}
- Vector<String>& events() { return m_events; }
+ ~TestInputMethodFilter()
+ {
+ gtk_widget_destroy(m_testWindow);
+ }
- void sendKeyEventToFilter(unsigned int gdkKeyValue, GdkEventType type, unsigned int modifiers = 0)
+ void sendKeyEventToFilter(unsigned gdkKeyValue, GdkEventType type, unsigned modifiers = 0)
{
GdkEvent* event = gdk_event_new(type);
event->key.keyval = gdkKeyValue;
event->key.state = modifiers;
- event->key.window = gtk_widget_get_window(m_testWindow.get());
+ event->key.window = gtk_widget_get_window(m_testWindow);
event->key.time = GDK_CURRENT_TIME;
g_object_ref(event->key.window);
-
-#ifndef GTK_API_VERSION_2
gdk_event_set_device(event, gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gdk_display_get_default())));
-#endif
GUniqueOutPtr<GdkKeymapKey> keys;
gint nKeys;
@@ -73,70 +74,17 @@ public:
gdk_event_free(event);
}
- void sendPressAndReleaseKeyEventPairToFilter(unsigned int gdkKeyValue, unsigned int modifiers = 0)
+ void sendPressAndReleaseKeyEventPairToFilter(unsigned gdkKeyValue, unsigned modifiers = 0)
{
sendKeyEventToFilter(gdkKeyValue, GDK_KEY_PRESS, modifiers);
sendKeyEventToFilter(gdkKeyValue, GDK_KEY_RELEASE, modifiers);
}
-protected:
- virtual bool sendSimpleKeyEvent(GdkEventKey* event, WTF::String eventString, EventFakedForComposition faked)
- {
- const char* eventType = event->type == GDK_KEY_RELEASE ? "release" : "press";
- const char* fakedString = faked == EventFaked ? " (faked)" : "";
- if (!eventString.isNull())
- m_events.append(String::format("sendSimpleKeyEvent type=%s keycode=%x text='%s'%s", eventType, event->keyval, eventString.utf8().data(), fakedString));
- else
- m_events.append(String::format("sendSimpleKeyEvent type=%s keycode=%x%s", eventType, event->keyval, fakedString));
-
- return true;
- }
-
- virtual bool sendKeyEventWithCompositionResults(GdkEventKey* event, ResultsToSend resultsToSend, EventFakedForComposition faked)
- {
- const char* eventType = event->type == GDK_KEY_RELEASE ? "release" : "press";
- const char* fakedString = faked == EventFaked ? " (faked)" : "";
- m_events.append(String::format("sendKeyEventWithCompositionResults type=%s keycode=%u%s", eventType, event->keyval, fakedString));
-
- if (resultsToSend & Composition && !m_confirmedComposition.isNull())
- confirmCompositionText(m_confirmedComposition);
- if (resultsToSend & Preedit && !m_preedit.isNull())
- setPreedit(m_preedit, m_cursorOffset);
-
- return true;
- }
-
- virtual bool canEdit()
- {
- return true;
- }
-
- virtual void confirmCompositionText(String text)
- {
- m_events.append(String::format("confirmComposition '%s'", text.utf8().data()));
- }
-
- virtual void confirmCurrentComposition()
- {
- m_events.append(String("confirmCurrentcomposition"));
- }
-
- virtual void cancelCurrentComposition()
- {
- m_events.append(String("cancelCurrentComposition"));
- }
-
- virtual void setPreedit(String preedit, int cursorOffset)
- {
- m_events.append(String::format("setPreedit text='%s' cursorOffset=%i", preedit.utf8().data(), cursorOffset));
- }
-
private:
- GRefPtr<GtkWidget> m_testWindow;
- Vector<String> m_events;
+ GtkWidget* m_testWindow;
};
-TEST(GTK, GtkInputMethodFilterSimple)
+TEST(WebKit2, InputMethodFilterSimple)
{
TestInputMethodFilter inputMethodFilter;
inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_g);
@@ -154,7 +102,7 @@ TEST(GTK, GtkInputMethodFilterSimple)
ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=6b"), events[5]);
}
-TEST(GTK, GtkInputMethodFilterUnicodeSequence)
+TEST(WebKit2, InputMethodFilterUnicodeSequence)
{
TestInputMethodFilter inputMethodFilter;
@@ -201,7 +149,7 @@ TEST(GTK, GtkInputMethodFilterUnicodeSequence)
ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=ffe3"), events[20]);
}
-TEST(GTK, GtkInputMethodFilterComposeKey)
+TEST(WebKit2, InputMethodFilterComposeKey)
{
TestInputMethodFilter inputMethodFilter;
@@ -225,7 +173,7 @@ static void temporaryGetPreeditStringOverride(GtkIMContext*, char** string, Pang
*cursorPosition = 3;
}
-TEST(GTK, GtkInputMethodFilterContextEventsWithoutKeyEvents)
+TEST(WebKit2, InputMethodFilterContextEventsWithoutKeyEvents)
{
TestInputMethodFilter inputMethodFilter;
@@ -267,7 +215,7 @@ static void verifyCanceledComposition(const Vector<String>& events)
ASSERT(gSawContextReset);
}
-TEST(GTK, GtkInputMethodFilterContextFocusOutDuringOngoingComposition)
+TEST(WebKit2, InputMethodFilterContextFocusOutDuringOngoingComposition)
{
TestInputMethodFilter inputMethodFilter;
@@ -287,7 +235,7 @@ TEST(GTK, GtkInputMethodFilterContextFocusOutDuringOngoingComposition)
contextClass->reset = previousCallback;
}
-TEST(GTK, GtkInputMethodFilterContextMouseClickDuringOngoingComposition)
+TEST(WebKit2, InputMethodFilterContextMouseClickDuringOngoingComposition)
{
TestInputMethodFilter inputMethodFilter;
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/icon.png b/Tools/TestWebKitAPI/Tests/WebKit2/icon.png
new file mode 100644
index 000000000..79e459894
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/icon.png
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/input-focus-blur.html b/Tools/TestWebKitAPI/Tests/WebKit2/input-focus-blur.html
new file mode 100644
index 000000000..05d84902b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/input-focus-blur.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div tabindex=0></div>
+<input id="input" type="text">
+<input id="readonly" type="text" readonly>
+<script>
+
+document.querySelector('div').focus();
+
+function focusTextField(id)
+{
+ document.getElementById(id).focus();
+}
+
+function blurTextField(id)
+{
+ document.getElementById(id).blur();
+}
+
+function removeTextField(id)
+{
+ document.getElementById(id).remove();
+}
+
+</script>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/js-play-with-controls.html b/Tools/TestWebKitAPI/Tests/WebKit2/js-play-with-controls.html
new file mode 100644
index 000000000..da9cb1c07
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/js-play-with-controls.html
@@ -0,0 +1,20 @@
+<html>
+ <head>
+ <script>
+ function pageLoaded() {
+ document.getElementById("video").play();
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("loaded");
+ } catch(e) { }
+ }
+
+ function play() {
+ document.getElementById("video").play();
+ }
+ </script>
+ </head>
+ <body onload="pageLoaded()">
+ <button onclick="play()">Play</button>
+ <video id="video" src="test.mp4" />
+ </body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/link-with-download-attribute.html b/Tools/TestWebKitAPI/Tests/WebKit2/link-with-download-attribute.html
new file mode 100644
index 000000000..c05594518
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/link-with-download-attribute.html
@@ -0,0 +1,10 @@
+<html>
+ <body>
+ <a id="testAnchor" style="display: block; height: 100%; width: 100%" download="downloadAttributeValue.txt"></a>
+ <script>
+ var blob = new Blob(["Hello world!"], {type: "application/octet-stream"});
+ var link = document.getElementById("testAnchor");
+ link.href = window.URL.createObjectURL(blob);
+ </script>
+ </body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/link-with-title.html b/Tools/TestWebKitAPI/Tests/WebKit2/link-with-title.html
new file mode 100644
index 000000000..971ed281b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/link-with-title.html
@@ -0,0 +1,5 @@
+<html>
+ <body>
+ <a href="#" style="display: block; height: 100%;" title="HitTestLinkTitle"></a>
+ </body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-iframes.html b/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-iframes.html
new file mode 100644
index 000000000..5436310c8
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-iframes.html
@@ -0,0 +1,35 @@
+<html>
+<head>
+<script type="text/javascript">
+ var maxNumberOfFrames = 100;
+
+ function createIFrames() {
+ var str = "<div id=\"status\"></div>";
+ for (var i = 0; i < maxNumberOfFrames + 1; i++) {
+ str += "<iframe id=\"i" + i + "\" src=\"data:text/html,iframe_" + i + "\"></iframe>";
+ }
+ document.getElementsByTagName("body")[0].innerHTML = str;
+
+ var results = "";
+
+ var f = document.getElementById("i" + (maxNumberOfFrames - 1));
+ if (f && f.contentWindow) {
+ results += "Sucessfully created " + maxNumberOfFrames + " frames.<br>";
+ } else {
+ results += "Failed to create " + maxNumberOfFrames + " frames.<br>";
+ }
+
+ var g = document.getElementById("i" + maxNumberOfFrames);
+ if (g && g.contentWindow) {
+ results += "Failed to block creation of frame number " + (maxNumberOfFrames + 1) + ".";
+ } else {
+ results += "Successfully blocked creation of frame number " + (maxNumberOfFrames + 1) + ".";
+ }
+
+ document.getElementById("status").innerHTML = results;
+ }
+</script>
+</head>
+<body onLoad="createIFrames()">
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-images.html b/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-images.html
new file mode 100644
index 000000000..2233b8e0b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-images.html
@@ -0,0 +1,17 @@
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
+<img src="icon.png"/>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-text-vertical-lr.html b/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-text-vertical-lr.html
new file mode 100644
index 000000000..9598a3efa
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-text-vertical-lr.html
@@ -0,0 +1,3 @@
+<body style="-webkit-writing-mode: vertical-lr;">
+You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!
+</body>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-text.html b/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-text.html
new file mode 100644
index 000000000..3cd1b4c52
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/lots-of-text.html
@@ -0,0 +1,3 @@
+<body style="width:800px">
+You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too! You say it's your Birthday. It's my Birthday too!
+</body>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/many-iframes.html b/Tools/TestWebKitAPI/Tests/WebKit2/many-iframes.html
new file mode 100644
index 000000000..44f17f586
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/many-iframes.html
@@ -0,0 +1,15 @@
+<html>
+<body>
+ Simple HTML file with many iframes.
+ <iframe src="simple.html"></iframe>
+ <iframe src="simple.html"></iframe>
+ <iframe src="simple.html"></iframe>
+ <iframe src="simple.html"></iframe>
+ <iframe src="simple.html"></iframe>
+ <iframe src="simple.html"></iframe>
+ <iframe src="simple.html"></iframe>
+ <iframe src="simple.html"></iframe>
+ <iframe src="simple.html"></iframe>
+ <iframe src="simple.html"></iframe>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/modal-alerts-in-new-about-blank-window.html b/Tools/TestWebKitAPI/Tests/WebKit2/modal-alerts-in-new-about-blank-window.html
new file mode 100644
index 000000000..f76cb650b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/modal-alerts-in-new-about-blank-window.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+
+var newWindow = window.open("about:blank");
+newWindow.alert("Testing alert");
+newWindow.confirm("Testing confirm");
+newWindow.prompt("Testing prompt", "Default text");
+
+</script>
+</head>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/mouse-button-listener.html b/Tools/TestWebKitAPI/Tests/WebKit2/mouse-button-listener.html
new file mode 100644
index 000000000..1fdbb1a95
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/mouse-button-listener.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<script>
+ var mouseButton = -1;
+ var menuType = "none";
+
+ function mouseDownHandler(event)
+ {
+ mouseButton = event.button;
+ event.preventDefault();
+ }
+
+ function pressedMouseButton()
+ {
+ return mouseButton;
+ }
+
+ function contextMenuHandler(event)
+ {
+ menuType = "context";
+ event.preventDefault();
+ }
+
+ function displayedMenu()
+ {
+ return menuType;
+ }
+
+ addEventListener("mousedown", mouseDownHandler);
+ addEventListener("contextmenu", contextMenuHandler);
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/mouse-move-listener.html b/Tools/TestWebKitAPI/Tests/WebKit2/mouse-move-listener.html
new file mode 100644
index 000000000..afca7ed86
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/mouse-move-listener.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<script>
+ var mouseMoved = false;
+
+ function mouseMoveHandler()
+ {
+ mouseMoved = true;
+ }
+
+ function didMoveMouse()
+ {
+ return mouseMoved;
+ }
+
+ addEventListener("mousemove", mouseMoveHandler);
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/no-autoplay-with-controls.html b/Tools/TestWebKitAPI/Tests/WebKit2/no-autoplay-with-controls.html
new file mode 100644
index 000000000..676bac205
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/no-autoplay-with-controls.html
@@ -0,0 +1,25 @@
+<html>
+ <head>
+ <script>
+ function pageLoaded() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("loaded");
+ } catch(e) { }
+ }
+
+ function beganPlaying() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("played");
+ } catch(e) { }
+ }
+
+ function play() {
+ document.getElementById("video").play();
+ }
+ </script>
+ </head>
+ <body onload="pageLoaded()">
+ <button onclick="play()">Play</button>
+ <video id="video" onplaying=beganPlaying() src="test.mp4" />
+ </body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/open-and-close-window.html b/Tools/TestWebKitAPI/Tests/WebKit2/open-and-close-window.html
new file mode 100644
index 000000000..6ac778a9e
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/open-and-close-window.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+if (document.location.search === "?close-window")
+ window.close();
+else
+ window.open("open-and-close-window.html?close-window");
+</script>
+</head>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/push-state.html b/Tools/TestWebKitAPI/Tests/WebKit2/push-state.html
new file mode 100644
index 000000000..f3a04a6bb
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/push-state.html
@@ -0,0 +1,3 @@
+<script type="text/javascript">
+history.pushState('newState', 0, '?newState');
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/set-long-title.html b/Tools/TestWebKitAPI/Tests/WebKit2/set-long-title.html
new file mode 100644
index 000000000..c31765a9e
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/set-long-title.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<title>Original Short Title</title>
+</head>
+<body>
+<script>
+document.title = Array(8096).join(String.fromCharCode(0x8181));
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/should-open-external-schemes.html b/Tools/TestWebKitAPI/Tests/WebKit2/should-open-external-schemes.html
new file mode 100644
index 000000000..299e4d66a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/should-open-external-schemes.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+function navigateToTelURL()
+{
+ window.location.href = "tel:+1 (408) 996-1010";
+}
+
+function navigateToTelURLInZeroTimer()
+{
+ window.setTimeout(navigateToTelURL, 0);
+}
+
+function navigateToTelURLInNestedZeroTimer()
+{
+ window.setTimeout(navigateToTelURLInZeroTimer, 0);
+}
+</script>
+</head>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/simple-accelerated-compositing.html b/Tools/TestWebKitAPI/Tests/WebKit2/simple-accelerated-compositing.html
new file mode 100644
index 000000000..bea62721b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/simple-accelerated-compositing.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+ <div style="-webkit-transform: translateZ(0);">Simple HTML file with accelerated compositing</div>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/simple-form.html b/Tools/TestWebKitAPI/Tests/WebKit2/simple-form.html
new file mode 100644
index 000000000..3bf185293
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/simple-form.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<script>
+function submitForm()
+{
+ document.forms[0].submit();
+}
+</script>
+<form method=post>
+<input name=foo value="Some unimportant data">
+<input type=submit>
+</form>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/simple-iframe.html b/Tools/TestWebKitAPI/Tests/WebKit2/simple-iframe.html
new file mode 100644
index 000000000..429521c7f
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/simple-iframe.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+ Simple HTML file.
+ <iframe src="simple.html"></iframe>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/simple-tall.html b/Tools/TestWebKitAPI/Tests/WebKit2/simple-tall.html
new file mode 100644
index 000000000..a220e9b2d
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/simple-tall.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+<body>
+ Simple and tall HTML file.
+ <div style="height: 3000px;"></div>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/simple.html b/Tools/TestWebKitAPI/Tests/WebKit2/simple.html
new file mode 100644
index 000000000..12cf87364
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/simple.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+ Simple HTML file.
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/simple2.html b/Tools/TestWebKitAPI/Tests/WebKit2/simple2.html
new file mode 100644
index 000000000..1dcbfddd2
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/simple2.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+ Second simple HTML file.
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/simple3.html b/Tools/TestWebKitAPI/Tests/WebKit2/simple3.html
new file mode 100644
index 000000000..786516e89
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/simple3.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+ Third simple HTML file.
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/spacebar-scrolling.html b/Tools/TestWebKitAPI/Tests/WebKit2/spacebar-scrolling.html
new file mode 100644
index 000000000..8da08b3f9
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/spacebar-scrolling.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<script>
+ function textFieldContainsSpace()
+ {
+ return document.querySelector("input").value === " ";
+ }
+
+ function blurTextField()
+ {
+ document.querySelector("input").blur();
+ }
+
+ function isDocumentScrolled()
+ {
+ return scrollY !== 0;
+ }
+
+ function loaded()
+ {
+ document.querySelector("input").focus();
+ }
+
+ addEventListener("load", loaded);
+</script>
+<input>
+<div style="height: 3000px;"></div>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/test-mse.mp4 b/Tools/TestWebKitAPI/Tests/WebKit2/test-mse.mp4
new file mode 100644
index 000000000..901c907e0
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/test-mse.mp4
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/test-without-audio-track.mp4 b/Tools/TestWebKitAPI/Tests/WebKit2/test-without-audio-track.mp4
new file mode 100644
index 000000000..8ad09c03c
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/test-without-audio-track.mp4
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/test.mp4 b/Tools/TestWebKitAPI/Tests/WebKit2/test.mp4
new file mode 100644
index 000000000..d278c8ad8
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/test.mp4
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/webfont.html b/Tools/TestWebKitAPI/Tests/WebKit2/webfont.html
new file mode 100644
index 000000000..008edd098
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2/webfont.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+@font-face {
+ font-family: "WebFont";
+ src: url("Ahem.ttf") format("truetype");
+}
+</style>
+</head>
+<body>
+<div style="font: 100px 'WebFont';">Hello</div>
+This tests passes if there is no Web Process crash.
+</body>
+</html> \ No newline at end of file
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/AllAhem.svg b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/AllAhem.svg
new file mode 100644
index 000000000..135d00999
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/AllAhem.svg
@@ -0,0 +1,111 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata></metadata>
+<defs>
+<font id="Litherum" horiz-adv-x="1024">
+<font-face units-per-em="1024" ascent="1024" descent="-1"/>
+<glyph unicode="1" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="2" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="3" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x0021;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x0024;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x0025;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x003a;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x003b;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x003f;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x00a2;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x00a3;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x00a5;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x00b0;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x2010;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x2013;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x2025;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x2026;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x2030;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x2032;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x2033;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x203c;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x2047;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x2048;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x2049;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x20ac;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x2103;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x2116;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x3005;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x301c;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x303b;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x3041;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x3043;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x3045;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x3047;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x3049;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x3063;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x3083;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x3085;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x3087;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x308e;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x3095;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x3096;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x309d;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x309e;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x30a0;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x30a1;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x30a3;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x30a5;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x30a7;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x30a9;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x30c3;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x30e3;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x30e5;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x30e7;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x30ee;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x30f5;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x30f6;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x30fb;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x30fc;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x30fd;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x30fe;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x31f0;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x31f1;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x31f2;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x31f3;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x31f4;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x31f5;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x31f6;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x31f7;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x31f8;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x31f9;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x31fa;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x31fb;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x31fc;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x31fd;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x31fe;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x31ff;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x4e00;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x4e09;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x4e8c;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#x56db;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#xff01;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#xff04;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#xff05;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#xff1a;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#xff1b;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#xff1f;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#xff65;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#xff67;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#xff68;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#xff69;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#xff6a;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#xff6b;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#xff6c;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#xff6d;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#xff6e;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#xff6f;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#xff70;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#xffe0;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#xffe1;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+<glyph unicode="&#xffe5;" horiz-adv-x="1024" d="M0 0V1024H1024V0z"/>
+</font>
+</defs>
+</svg>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ApplicationCache.db b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ApplicationCache.db
new file mode 100644
index 000000000..e7cbb3d7d
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ApplicationCache.db
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ApplicationCache.db-shm b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ApplicationCache.db-shm
new file mode 100644
index 000000000..f5a2be9ff
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ApplicationCache.db-shm
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ApplicationCache.db-wal b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ApplicationCache.db-wal
new file mode 100644
index 000000000..dfd74404b
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ApplicationCache.db-wal
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/BundleEditingDelegateProtocol.h b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/BundleEditingDelegateProtocol.h
new file mode 100644
index 000000000..528afa0e9
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/BundleEditingDelegateProtocol.h
@@ -0,0 +1,40 @@
+/*
+ * 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. 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 INC. 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 <WebKit/WKFoundation.h>
+
+#if WK_API_ENABLED
+
+#import <WebKit/WKWebProcessPlugInEditingDelegate.h>
+
+@protocol BundleEditingDelegateProtocol <NSObject>
+
+- (void)shouldInsertText:(NSString *)text replacingRange:(NSString *)rangeAsString givenAction:(WKEditorInsertAction)action;
+- (void)willWriteToPasteboard:(NSString *)rangeAsString;
+- (void)didWriteToPasteboard;
+
+@end
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/BundleRangeHandleProtocol.h b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/BundleRangeHandleProtocol.h
new file mode 100644
index 000000000..2edab241f
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/BundleRangeHandleProtocol.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 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. 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 INC. 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 <WebKit/WKFoundation.h>
+
+#if WK_API_ENABLED
+
+@protocol BundleRangeHandleProtocol <NSObject>
+- (void)textFromBodyRange:(NSString *)text;
+- (void)bodyInnerHTMLAfterDetectingData:(NSString *)text;
+@end
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.h b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.h
new file mode 100644
index 000000000..9d5b5d433
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.h
@@ -0,0 +1,28 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+@protocol ContentFilteringProtocol <NSObject>
+- (void)checkIfPlatformFrameworksAreLoaded:(void (^)(BOOL parentalControlsLoaded, BOOL networkExtensionLoaded))completionHandler;
+@end
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.html
new file mode 100644
index 000000000..a48eabb65
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+PASS
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/CookieMessage.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/CookieMessage.html
new file mode 100644
index 000000000..78553d43d
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/CookieMessage.html
@@ -0,0 +1,4 @@
+<script>
+document.cookie = "key=value";
+window.webkit.messageHandlers.testHandler.postMessage("COOKIE:" + document.cookie);
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestBlobURL.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestBlobURL.html
new file mode 100644
index 000000000..55ff0c066
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestBlobURL.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<body>
+<a id="href" href="simple.html">download</a>
+<script>
+ var element = document.getElementById("href");
+ var data = { x: 42, s: "hello, world" };
+ var json = JSON.stringify(data);
+ var blob = new Blob([json], {type: "octet/stream"});
+ var url = window.URL.createObjectURL(blob);
+
+ element.href = url;
+ element.click();
+</script>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURL.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURL.html
new file mode 100644
index 000000000..61447c2fd
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURL.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<body>
+<a id="href" href="simple.html">download</a>
+<script>
+ var element = document.getElementById("href");
+ element.click();
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURL2.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURL2.html
new file mode 100644
index 000000000..01f6a7773
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURL2.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+<iframe src="DownloadRequestOriginalURLFrame.html"></iframe>
+</body>
+</html> \ No newline at end of file
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURLFrame.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURLFrame.html
new file mode 100644
index 000000000..61447c2fd
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURLFrame.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<body>
+<a id="href" href="simple.html">download</a>
+<script>
+ var element = document.getElementById("href");
+ element.click();
+</script>
+</body>
+</html> \ No newline at end of file
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenDelegate.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenDelegate.html
new file mode 100644
index 000000000..9a9006203
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenDelegate.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script>
+ function load() {
+ window.webkit.messageHandlers.fullscreenChangeHandler.postMessage('load');
+ }
+ document.addEventListener('webkitfullscreenchange', function(event) {
+ window.webkit.messageHandlers.fullscreenChangeHandler.postMessage('fullscreenchange');
+ });
+ document.addEventListener('mousedown', function(event) {
+ // Toggle fullscreen
+ var target = document.getElementById('target');
+ if (document.webkitFullscreenElement == target)
+ document.webkitExitFullscreen();
+ else
+ target.webkitRequestFullScreen();
+ });
+ </script>
+ <style>
+ #target {
+ background-color: red;
+ width: 150px;
+ height: 150px;
+ }
+ </style>
+</head>
+<body onload="load()">
+ <div id="target"></div>
+</body>
+</html> \ No newline at end of file
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenLayoutConstraints.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenLayoutConstraints.html
new file mode 100644
index 000000000..063d901da
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenLayoutConstraints.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script>
+ function load() {
+ window.webkit.messageHandlers.fullscreenStateChangeHandler.postMessage('load');
+ }
+ document.addEventListener('webkitfullscreenchange', function(event) {
+ window.webkit.messageHandlers.fullscreenStateChangeHandler.postMessage('fullscreenchange');
+ });
+ document.addEventListener('mousedown', function(event) {
+ // Toggle fullscreen
+ var target = document.getElementById('target');
+ if (document.webkitFullscreenElement == target)
+ document.webkitExitFullscreen();
+ else
+ target.webkitRequestFullScreen();
+ });
+ </script>
+ <style>
+ #target {
+ background-color: red;
+ width: 150px;
+ height: 150px;
+ }
+ </style>
+</head>
+<body onload="load()">
+ <div id="target"></div>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenTopContentInset.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenTopContentInset.html
new file mode 100644
index 000000000..9a9006203
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenTopContentInset.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script>
+ function load() {
+ window.webkit.messageHandlers.fullscreenChangeHandler.postMessage('load');
+ }
+ document.addEventListener('webkitfullscreenchange', function(event) {
+ window.webkit.messageHandlers.fullscreenChangeHandler.postMessage('fullscreenchange');
+ });
+ document.addEventListener('mousedown', function(event) {
+ // Toggle fullscreen
+ var target = document.getElementById('target');
+ if (document.webkitFullscreenElement == target)
+ document.webkitExitFullscreen();
+ else
+ target.webkitRequestFullScreen();
+ });
+ </script>
+ <style>
+ #target {
+ background-color: red;
+ width: 150px;
+ height: 150px;
+ }
+ </style>
+</head>
+<body onload="load()">
+ <div id="target"></div>
+</body>
+</html> \ No newline at end of file
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.html
new file mode 100644
index 000000000..c2bc464ab
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.html
@@ -0,0 +1,14 @@
+<script>
+
+var request = window.indexedDB.deleteDatabase("IDBDeleteRecovery");
+
+request.onsuccess = function(e)
+{
+ window.webkit.messageHandlers.testHandler.postMessage('Deleted database');
+}
+request.onerror = function(e)
+{
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Error deleting database');
+}
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3 b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3
new file mode 100644
index 000000000..25ef255ee
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3-shm b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3-shm
new file mode 100644
index 000000000..285d37720
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3-shm
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3-wal b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3-wal
new file mode 100644
index 000000000..51fe61926
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3-wal
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBIndexUpgradeToV2.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBIndexUpgradeToV2.html
new file mode 100644
index 000000000..813bbd852
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBIndexUpgradeToV2.html
@@ -0,0 +1,21 @@
+<script>
+
+var databaseName = "index-upgrade-test";
+var openRequest = indexedDB.open(databaseName);
+var db;
+openRequest.onupgradeneeded = function(event) {
+ window.webkit.messageHandlers.testHandler.postMessage('Unexpected upgrade needed');
+}
+
+openRequest.onsuccess = function(event) {
+ var req = event.target.result.transaction('store').objectStore('store').index('index').get("indexkey!");
+
+ req.onsuccess = function (event) {
+ window.webkit.messageHandlers.testHandler.postMessage("Object expected to be a blob: " + event.target.result.test);
+ }
+ req.onerror = function (event) {
+ window.webkit.messageHandlers.testHandler.postMessage("Unexpected get error");
+ }
+}
+
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexUpgrade.blob b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexUpgrade.blob
new file mode 100644
index 000000000..6c51fb115
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexUpgrade.blob
@@ -0,0 +1 @@
+fun times all around! \ No newline at end of file
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexUpgrade.sqlite3 b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexUpgrade.sqlite3
new file mode 100644
index 000000000..bc3b63888
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexUpgrade.sqlite3
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBDatabaseProcessKill-1.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBDatabaseProcessKill-1.html
new file mode 100644
index 000000000..ab4299bd8
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBDatabaseProcessKill-1.html
@@ -0,0 +1,33 @@
+<script>
+
+var database;
+
+for (var i = 0; i < 100; ++i) {
+ var request = window.indexedDB.deleteDatabase("IndexedDBDatabaseProcessKill");
+ request.onsuccess = function() {
+ window.webkit.messageHandlers.testHandler.postMessage('DeleteRequestDone');
+ }
+ request.onerror = function() {
+ window.webkit.messageHandlers.testHandler.postMessage('DeleteRequestError');
+ }
+
+ request = window.indexedDB.open("IndexedDBDatabaseProcessKill");
+ request.onsuccess = function() {
+ window.webkit.messageHandlers.testHandler.postMessage('OpenRequestDone');
+ }
+ request.onerror = function() {
+ window.webkit.messageHandlers.testHandler.postMessage('OpenRequestError');
+ }
+ request.onupgradeneeded = function(e) {
+ database = e.target.result;
+ database.onerror = function() {
+ notifyDatabaseErrorReceived = function() {
+ window.webkit.messageHandlers.testHandler.postMessage('DatabaseErrorReceived');
+ }
+ setTimeout("setTimeout(notifyDatabaseErrorReceived, 0)", 0);
+ }
+ window.webkit.messageHandlers.testHandler.postMessage('OpenRequestUpgradeNeeded');
+ }
+}
+
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-1.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-1.html
new file mode 100644
index 000000000..51223a1cb
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-1.html
@@ -0,0 +1,46 @@
+<script>
+
+var request = window.indexedDB.deleteDatabase("IndexedDBMultiProcess");
+request.onsuccess = function(e)
+{
+ continueTest();
+}
+request.onerror = function(e)
+{
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Error deleting database');
+}
+
+function continueTest()
+{
+ var request = window.indexedDB.open("IndexedDBMultiProcess", 2);
+
+ request.onsuccess = function()
+ {
+ window.webkit.messageHandlers.testHandler.postMessage('Open success');
+ }
+
+ request.onerror = function()
+ {
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Unexpected error opening database');
+ }
+
+ request.onupgradeneeded = function(event)
+ {
+ window.webkit.messageHandlers.testHandler.postMessage('UpgradeNeeded');
+
+ var store = event.target.result.createObjectStore("TestObjectStore");
+
+ event.target.transaction.oncomplete = function() {
+ window.webkit.messageHandlers.testHandler.postMessage('Transaction complete');
+ }
+
+ event.target.transaction.onerror = function() {
+ window.webkit.messageHandlers.testHandler.postMessage('Transaction errored!');
+ }
+
+ store.put("bar", "foo");
+ }
+}
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-2.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-2.html
new file mode 100644
index 000000000..31035c993
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-2.html
@@ -0,0 +1,92 @@
+<script>
+
+var request = window.indexedDB.open("IndexedDBMultiProcess", 2);
+
+request.onsuccess = function(event)
+{
+ var req = event.target.result.transaction("TestObjectStore").objectStore("TestObjectStore").get("foo");
+
+ req.onsuccess = function(event)
+ {
+ window.webkit.messageHandlers.testHandler.postMessage('Value of foo: ' + req.result);
+ continueTest1();
+ }
+
+ req.onerror = function(event)
+ {
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Unexpected error getting value');
+ }
+}
+
+request.onerror = function()
+{
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Unexpected error opening database');
+}
+
+request.onupgradeneeded = function(event)
+{
+ // Unexpected upgrade needed
+ window.webkit.messageHandlers.testHandler.postMessage('Unexpected UpgradeNeeded');
+}
+
+function continueTest1()
+{
+ var request = window.indexedDB.deleteDatabase("ProcessCloseIDBCleanup");
+ request.onsuccess = function(e)
+ {
+ continueTest2();
+ }
+ request.onerror = function(e)
+ {
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Error deleting ProcessCloseIDBCleanup database');
+ }
+}
+
+function startGetLoop()
+{
+ var request = window.indexedDB.open("ProcessCloseIDBCleanup");
+ request.onsuccess = function(e)
+ {
+ var req = e.target.result.transaction(["TestObjectStore"]).objectStore("TestObjectStore").get("foo");
+ req.onsuccess = startGetLoop;
+ req.onerror = function(e)
+ {
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Error with a get loop');
+ }
+ }
+
+ request.onerror = function(e)
+ {
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Error with a get loop');
+ }
+}
+
+function continueTest2()
+{
+ var request = window.indexedDB.open("ProcessCloseIDBCleanup");
+ request.onsuccess = function(e)
+ {
+ for (var i = 0; i < 75; ++i)
+ startGetLoop();
+
+ setTimeout("window.webkit.messageHandlers.testHandler.postMessage('Get loops started');", 0);
+ }
+
+ request.onerror = function(e)
+ {
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Error opening ProcessCloseIDBCleanup database');
+ }
+
+ request.onupgradeneeded = function(e)
+ {
+ e.target.result.createObjectStore("TestObjectStore").put("bar", "foo");
+ }
+}
+
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-3.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-3.html
new file mode 100644
index 000000000..872885b75
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-3.html
@@ -0,0 +1,21 @@
+<script>
+
+var request = window.indexedDB.deleteDatabase("ProcessCloseIDBCleanup");
+
+request.onsuccess = function(event)
+{
+ window.webkit.messageHandlers.testHandler.postMessage('Deleted!');
+}
+
+request.onerror = function()
+{
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Unexpected error opening database');
+}
+
+request.onblocked = function(event)
+{
+ window.webkit.messageHandlers.testHandler.postMessage('Blocked!');
+}
+
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBPersistence-1.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBPersistence-1.html
new file mode 100644
index 000000000..62a1baf6f
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBPersistence-1.html
@@ -0,0 +1,35 @@
+<script>
+
+var request = window.indexedDB.deleteDatabase("IndexedDBPersistence");
+request.onsuccess = function(e)
+{
+ continueTest();
+}
+request.onerror = function(e)
+{
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Error');
+}
+
+function continueTest()
+{
+ var request = window.indexedDB.open("IndexedDBPersistence", 2);
+
+ request.onsuccess = function()
+ {
+ window.webkit.messageHandlers.testHandler.postMessage('Success');
+
+ }
+ request.onerror = function()
+ {
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Error');
+ }
+ request.onupgradeneeded = function(event)
+ {
+ window.webkit.messageHandlers.testHandler.postMessage('UpgradeNeeded');
+
+ event.target.result.createObjectStore("TestObjectStore");
+ }
+}
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBPersistence-2.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBPersistence-2.html
new file mode 100644
index 000000000..d8ab125f2
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBPersistence-2.html
@@ -0,0 +1,22 @@
+<script>
+
+var request = window.indexedDB.open("IndexedDBPersistence");
+
+request.onsuccess = function(event)
+{
+ window.webkit.messageHandlers.testHandler.postMessage(event.target.result.version + " " + event.target.result.objectStoreNames[0]);
+}
+
+request.onerror = function()
+{
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Unexpected Error');
+}
+
+request.onupgradeneeded = function()
+{
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Unexpected UpgradeNeeded');
+}
+
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LineBreaking.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LineBreaking.html
new file mode 100644
index 000000000..48da6e69a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LineBreaking.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<style>
+@font-face {
+ font-family: "AllAhem";
+ src: url("AllAhem.svg") format("svg");
+}
+
+#test {
+ font: 20px "AllAhem";
+}
+</style>
+<script>
+function runTest(testContent, localeString, lineBreakValue) {
+ var container = document.getElementById("container");
+ var test = document.getElementById("test");
+
+ test.textContent = testContent;
+ container.lang = localeString;
+ container.style.webkitLineBreak = lineBreakValue;
+
+ var current = 0;
+ var breakpoints = [];
+ var clientRectsLength = 2;
+ for (var i = 1; clientRectsLength > 1; i += 5) {
+ container.style.width = "" + i + "px";
+ var width = test.getClientRects()[0].width;
+ if (current != width) {
+ current = width;
+ breakpoints.push(width / 20);
+ }
+ clientRectsLength = test.getClientRects().length;
+ }
+ return breakpoints;
+}
+</script>
+</head>
+<body>
+<div id="container" style="width: 99999999px;">
+ <span id="test">Hello World</span>
+</div>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageClear.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageClear.html
new file mode 100644
index 000000000..11bdd6c14
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageClear.html
@@ -0,0 +1,6 @@
+<script>
+
+window.localStorage.foo = "bar";
+window.webkit.messageHandlers.testHandler.postMessage('Go ahead and clear it');
+
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.html
new file mode 100644
index 000000000..9878f36ac
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.html
@@ -0,0 +1,6 @@
+<script>
+
+window.localStorage.key(0);
+window.webkit.messageHandlers.testHandler.postMessage('DONE');
+
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.localstorage b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.localstorage
new file mode 100644
index 000000000..0b41b25c7
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.localstorage
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.localstorage-shm b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.localstorage-shm
new file mode 100644
index 000000000..fe9ac2845
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.localstorage-shm
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageQuirkEnabled.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageQuirkEnabled.html
new file mode 100644
index 000000000..c53f1deb4
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageQuirkEnabled.html
@@ -0,0 +1,10 @@
+<script>
+
+try {
+ if (window.localStorage)
+ window.webkit.messageHandlers.testHandler.postMessage('PASS');
+} catch(e) {
+ window.webkit.messageHandlers.testHandler.postMessage('FAIL');
+}
+
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/RemoteObjectRegistry.h b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/RemoteObjectRegistry.h
new file mode 100644
index 000000000..3d2654b98
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/RemoteObjectRegistry.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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 <WebKit/WKFoundation.h>
+
+#if WK_API_ENABLED
+
+#import <WebKit/_WKRemoteObjectInterface.h>
+
+@protocol RemoteObjectProtocol <NSObject>
+
+- (void)sayHello:(NSString *)hello;
+- (void)sayHello:(NSString *)hello completionHandler:(void (^)(NSString *))completionHandler;
+- (void)selectionAndClickInformationForClickAtPoint:(NSValue *)pointValue completionHandler:(void (^)(NSDictionary *))completionHandler;
+- (void)takeRange:(NSRange)range completionHandler:(void (^)(NSUInteger location, NSUInteger length))completionHandler;
+- (void)takeSize:(CGSize)size completionHandler:(void (^)(CGFloat width, CGFloat height))completionHandler;
+- (void)doNotCallCompletionHandler:(void (^)())completionHandler;
+
+@end
+
+static inline _WKRemoteObjectInterface *remoteObjectInterface()
+{
+ _WKRemoteObjectInterface *interface = [_WKRemoteObjectInterface remoteObjectInterfaceWithProtocol:@protocol(RemoteObjectProtocol)];
+
+ [interface setClasses:[NSSet setWithObjects:[NSDictionary class], [NSString class], [NSURL class], nil] forSelector:@selector(selectionAndClickInformationForClickAtPoint:completionHandler:) argumentIndex:0 ofReply:YES];
+
+ return interface;
+}
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/StoreBlobToBeDeleted.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/StoreBlobToBeDeleted.html
new file mode 100644
index 000000000..bcaf972ad
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/StoreBlobToBeDeleted.html
@@ -0,0 +1,41 @@
+<script>
+
+var dbName = "StoreBlobToBeDeleted";
+var request = window.indexedDB.deleteDatabase(dbName);
+request.onsuccess = function(e)
+{
+ continueTest();
+}
+request.onerror = function(e)
+{
+ window.webkit.messageHandlers.testHandler.postMessage('Error deleting database');
+}
+
+var db;
+
+function continueTest(event)
+{
+ var request = window.indexedDB.open(dbName);
+
+ request.onupgradeneeded = function(e) {
+ db = e.target.result;
+ var objectStore = db.createObjectStore("TestStore");
+
+ const blobData = ["fun ", "times ", "all ", "around!"];
+ let blob = new Blob(blobData, { type: "text/plain" });
+
+ var addRequest = objectStore.add(blob, "BlobKey");
+ addRequest.onerror = function() {
+ window.webkit.messageHandlers.testHandler.postMessage('Error storing blob in database');
+ }
+ }
+
+ request.onsuccess = function() {
+ db.close();
+ window.webkit.messageHandlers.testHandler.postMessage('Success');
+ }
+ request.onerror = function() {
+ window.webkit.messageHandlers.testHandler.postMessage('Error storing blob in database');
+ }
+}
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentWorldProtocol.h b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentWorldProtocol.h
new file mode 100644
index 000000000..0b335792e
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentWorldProtocol.h
@@ -0,0 +1,37 @@
+/*
+ * 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. 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 INC. 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 <WebKit/WKFoundation.h>
+
+#if WK_API_ENABLED
+
+@protocol UserContentWorldProtocol <NSObject>
+
+- (void)didObserveNormalWorld;
+- (void)didObserveWorldWithName:(NSString *)name;
+
+@end
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebProcessKillIDBCleanup-1.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebProcessKillIDBCleanup-1.html
new file mode 100644
index 000000000..a9a121e49
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebProcessKillIDBCleanup-1.html
@@ -0,0 +1,67 @@
+<script>
+
+var request = window.indexedDB.deleteDatabase("WebProcessKillIDBCleanup");
+request.onsuccess = function(e)
+{
+ continueTest();
+}
+request.onerror = function(e)
+{
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Error deleting database');
+}
+
+var database;
+
+function continueTest()
+{
+ var request = window.indexedDB.open("WebProcessKillIDBCleanup");
+
+ request.onsuccess = function()
+ {
+ window.webkit.messageHandlers.testHandler.postMessage('Open success');
+ setTimeout(continueTest2, 0);
+ }
+
+ request.onerror = function()
+ {
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Unexpected error opening database');
+ }
+
+ request.onupgradeneeded = function(event)
+ {
+ window.webkit.messageHandlers.testHandler.postMessage('UpgradeNeeded');
+
+ database = event.target.result;
+ var store = database.createObjectStore("TestObjectStore");
+
+ event.target.transaction.oncomplete = function() {
+ window.webkit.messageHandlers.testHandler.postMessage('Transaction complete');
+ }
+
+ event.target.transaction.onerror = function() {
+ window.webkit.messageHandlers.testHandler.postMessage('Transaction errored!');
+ }
+
+ store.put("bar", "foo");
+ }
+}
+
+function continueTest2()
+{
+ var objectStore = database.transaction("TestObjectStore", "readonly").objectStore("TestObjectStore");
+
+ // Start a get-loop to keep this transaction active.
+ var shouldMessageClose = true;
+ function success() {
+ objectStore.get("foo").onsuccess = success;
+ if (shouldMessageClose) {
+ window.webkit.messageHandlers.testHandler.postMessage('Infinite Transaction Started');
+ shouldMessageClose = false;
+ }
+ }
+
+ objectStore.get("foo").onsuccess = success;
+}
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebProcessKillIDBCleanup-2.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebProcessKillIDBCleanup-2.html
new file mode 100644
index 000000000..3b3047aca
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebProcessKillIDBCleanup-2.html
@@ -0,0 +1,25 @@
+<script>
+
+var request = window.indexedDB.open("WebProcessKillIDBCleanup");
+
+request.onsuccess = function(event)
+{
+ window.webkit.messageHandlers.testHandler.postMessage('Second open success');
+
+ event.target.result.transaction("TestObjectStore", "readonly").objectStore("TestObjectStore").get("foo").onsuccess = function() {
+ window.webkit.messageHandlers.testHandler.postMessage('Second WebView Transaction Started');
+ }
+}
+
+request.onerror = function()
+{
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Unexpected error opening database');
+}
+
+request.onupgradeneeded = function(event)
+{
+ // Unexpected error
+ window.webkit.messageHandlers.testHandler.postMessage('Unexpected UpgradeNeeded opening database');
+}
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/autofocused-text-input.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/autofocused-text-input.html
new file mode 100644
index 000000000..c429b188a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/autofocused-text-input.html
@@ -0,0 +1,3 @@
+<body>
+<input id="input" type="text" autofocus/>
+</body>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/autoplaying-video-with-audio.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/autoplaying-video-with-audio.html
new file mode 100644
index 000000000..53b456388
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/autoplaying-video-with-audio.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script>
+ var timeout;
+
+ function pauseVideo() {
+ document.getElementsByTagName("video")[0].pause();
+ }
+
+ function handlePaused() {
+ // Wait until the next runloop to allow media controls to update.
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("paused");
+ } catch(e) { }
+ }, 0);
+ }
+
+ function beganAutoplaying() {
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("autoplayed");
+ } catch(e) {
+ }
+ }, 0)
+ }
+
+ </script>
+</head>
+<body onmousedown=pauseVideo()>
+ <video autoplay controls onplaying=beganAutoplaying() src="video-with-audio.mp4" webkit-playsinline onpause=handlePaused()></video>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/blinking-div.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/blinking-div.html
new file mode 100644
index 000000000..e0f27aab7
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/blinking-div.html
@@ -0,0 +1,23 @@
+<html>
+ <script>
+window.onload = function () {
+ setInterval(blink, 0);
+}
+
+var a = 0;
+
+function blink() {
+ document.getElementById("blink").style.backgroundColor = a ? "blue" : "green";
+ a = !a;
+}
+ </script>
+ <style>
+#blink {
+ width: 200px; height: 200px;
+ display: inline-block;
+}
+ </style>
+ <body>
+ <div id="blink"></div>
+ </body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/change-video-source-on-click.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/change-video-source-on-click.html
new file mode 100644
index 000000000..560e6850a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/change-video-source-on-click.html
@@ -0,0 +1,33 @@
+<head>
+ <style>
+ video {
+ width: 800px;
+ height: 600px;
+ }
+ </style>
+ <script type="text/javascript">
+ function changeSource() {
+ var video = document.querySelector("video");
+ video.src = "large-video-with-audio.mp4";
+ video.play();
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("changed");
+ } catch(e) {
+ }
+ });
+ }
+
+ function handlePlaying() {
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("autoplayed");
+ } catch(e) {
+ }
+ }, 0);
+ }
+ </script>
+</head>
+<body>
+ <video autoplay onplaying=handlePlaying() onmousedown=changeSource() src="large-video-with-audio.mp4"></video>
+</body>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/change-video-source-on-end.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/change-video-source-on-end.html
new file mode 100644
index 000000000..f84f7f7ac
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/change-video-source-on-end.html
@@ -0,0 +1,35 @@
+<head>
+ <style>
+ video {
+ width: 800px;
+ height: 600px;
+ }
+ </style>
+ <script type="text/javascript">
+ var hasBegunPlayingBefore = false;
+
+ function changeSource() {
+ var video = document.querySelector("video");
+ video.src = "large-video-with-audio.mp4";
+ video.play();
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("changed");
+ } catch(e) {
+ }
+ });
+ }
+
+ function handlePlaying() {
+ if (hasBegunPlayingBefore)
+ return;
+
+ hasBegunPlayingBefore = true;
+ var video = document.querySelector("video");
+ video.currentTime = video.duration - 0.5;
+ }
+ </script>
+</head>
+<body>
+ <video autoplay onplaying=handlePlaying() src="large-video-with-audio.mp4" onended=changeSource()></video>
+</body>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/duplicate-completion-handler-calls.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/duplicate-completion-handler-calls.html
new file mode 100644
index 000000000..1e7492bed
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/duplicate-completion-handler-calls.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<form action="about:blank"></form>
+<script>
+ alert("alert");
+ confirm("confirm");
+ prompt("prompt");
+ openDatabase("testDatabase", "1", "test database", 1024);
+ document.forms[0].submit();
+</script>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/editable-body.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/editable-body.html
new file mode 100644
index 000000000..0c7baced7
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/editable-body.html
@@ -0,0 +1,7 @@
+<html>
+ <body contenteditable>Lorem Ipsum Et Cetera
+ <script>
+ document.body.focus();
+ </script>
+ </body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/enormous-video-with-sound.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/enormous-video-with-sound.html
new file mode 100644
index 000000000..0934f5ed8
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/enormous-video-with-sound.html
@@ -0,0 +1,15 @@
+<html>
+<head>
+<script>
+ function handlePlaying() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("playing");
+ } catch(e) {
+ }
+ }
+</script>
+</head>
+<body>
+ <video autoplay src="large-video-with-audio.mp4" width=65536 height=65536 onplaying=handlePlaying()></video>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/focus-inputs.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/focus-inputs.html
new file mode 100644
index 000000000..9f292c79d
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/focus-inputs.html
@@ -0,0 +1,15 @@
+<html>
+<head>
+<script>
+function focusPasswordField() {
+ var password = document.getElementById("password");
+ password.focus();
+}
+</script>
+</head>
+
+<body>
+<input type="text" autofocus/>
+<input id="password" type="password" />
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/full-size-autoplaying-video-with-audio.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/full-size-autoplaying-video-with-audio.html
new file mode 100644
index 000000000..48301e630
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/full-size-autoplaying-video-with-audio.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style>
+ video {
+ width: 100vw;
+ height: 100vh;
+ }
+ </style>
+ <script>
+ function finishTest() {
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("playing");
+ } catch(e) { }
+ }, 0);
+ }
+ </script>
+</head>
+<body>
+ <video autoplay src="video-with-audio.mp4" webkit-playsinline onplaying=finishTest()></video>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/input-field-in-scrollable-document.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/input-field-in-scrollable-document.html
new file mode 100644
index 000000000..6eedf375c
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/input-field-in-scrollable-document.html
@@ -0,0 +1,36 @@
+<html>
+
+<head>
+ <style>
+ body {
+ margin: 0;
+ }
+
+ input {
+ width: 100%;
+ height: 400px;
+ margin-bottom: 5000px;
+ }
+ </style>
+ <script type="text/javascript">
+ function loaded() {
+ var input = document.querySelector("input");
+ input.setSelectionRange(0, 0);
+ input.focus();
+ }
+
+ function focused() {
+ setTimeout(() => window.webkit.messageHandlers.testHandler.postMessage("focused"), 0);
+ }
+
+ function input() {
+ setTimeout(() => window.webkit.messageHandlers.testHandler.postMessage("input"), 0);
+ }
+ </script>
+</head>
+
+<body onload=loaded()>
+ <input onfocus=focused() oninput=input()></input>
+</body>
+
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-input-field-focus-onload.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-input-field-focus-onload.html
new file mode 100644
index 000000000..0671a12f5
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-input-field-focus-onload.html
@@ -0,0 +1,38 @@
+<html>
+
+<head>
+ <style>
+ body {
+ margin: 0;
+ }
+
+ input {
+ width: 100vw;
+ height: 100vh;
+ font-size: 50vh;
+ }
+ </style>
+ <script type="text/javascript">
+ function loaded() {
+ document.querySelector("input").focus();
+ }
+
+ function focused() {
+ setTimeout(() => window.webkit.messageHandlers.testHandler.postMessage("focused"), 0);
+ }
+
+ function input() {
+ setTimeout(() => window.webkit.messageHandlers.testHandler.postMessage("input"), 0);
+ }
+
+ function mousedown() {
+ setTimeout(() => window.webkit.messageHandlers.testHandler.postMessage("mousedown"), 0);
+ }
+ </script>
+</head>
+
+<body onload=loaded()>
+ <input onfocus=focused() oninput=input() onmousedown=mousedown()></input>
+</body>
+
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-hides-controls-after-seek-to-end.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-hides-controls-after-seek-to-end.html
new file mode 100644
index 000000000..0102e9629
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-hides-controls-after-seek-to-end.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script>
+
+ function handleEnded() {
+ // The media controls should be updated on the next runloop.
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("ended");
+ } catch(e) { }
+ }, 0);
+ }
+
+ function seekToEnd() {
+ var video = document.getElementsByTagName("video")[0];
+ video.currentTime = video.duration;
+ }
+
+ function beginTest() {
+ try {
+ window.webkit.messageHandlers.onloadHandler.postMessage("loaded");
+ } catch(e) { }
+ }
+
+ function beganAutoplaying() {
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("autoplayed");
+ } catch(e) {
+ }
+ }, 0)
+ }
+
+ </script>
+</head>
+<body onmousedown=seekToEnd() onload=beginTest()>
+ <video autoplay onplaying=beganAutoplaying() onended=handleEnded() src="large-video-with-audio.mp4" webkit-playsinline style="width: 800px; height: 600px;"></video>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-mutes-onplaying.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-mutes-onplaying.html
new file mode 100644
index 000000000..38fb32552
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-mutes-onplaying.html
@@ -0,0 +1,16 @@
+<html>
+<head>
+<script>
+ function handlePlaying() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("playing");
+ } catch(e) {
+ }
+ document.querySelector("video").muted = true;
+ }
+</script>
+</head>
+<body>
+ <video autoplay src="large-video-with-audio.mp4" width=640 height=480 onplaying=handlePlaying()></video>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-offscreen.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-offscreen.html
new file mode 100644
index 000000000..39cf476ab
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-offscreen.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style>
+ video {
+ width: 480px;
+ height: 320px;
+ position: absolute;
+ }
+ .offscreen {
+ top: -320px;
+ }
+ </style>
+ <script>
+ function moveVideoOffscreen() {
+ document.querySelector("video").classList.add("offscreen");
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("moved");
+ } catch(e) {
+ }
+ }, 0);
+ }
+ </script>
+</head>
+<body>
+ <video autoplay onplaying=moveVideoOffscreen()><source src="large-video-with-audio.mp4"></video>
+</body>
+<html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-playing-scroll-away.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-playing-scroll-away.html
new file mode 100644
index 000000000..0b7e09a32
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-playing-scroll-away.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <style>
+ video {
+ width: 480px;
+ height: 320px;
+ }
+ div {
+ margin-top: 5000px;
+ }
+ </style>
+ <script>
+ function scrollVideoOutOfView() {
+ document.querySelector("div").scrollIntoView();
+ setTimeout(function() {
+ window.webkit.messageHandlers.testHandler.postMessage("scrolled");
+ }, 0);
+ }
+
+ function beganAutoplaying() {
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("autoplayed");
+ } catch(e) {
+ }
+ }, 0)
+ }
+ </script>
+ </head>
+ <body>
+ <video autoplay onplaying=beganAutoplaying() loop id="first" src="large-video-with-audio.mp4"></video>
+ <br>
+ <div>hello world!</div>
+ </body>
+<html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-seek-after-ending.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-seek-after-ending.html
new file mode 100644
index 000000000..0386540a3
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-seek-after-ending.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script>
+ function seekToBeginningAndFinishTest() {
+ document.querySelector("#test-video").currentTime = 0;
+ // The media controls should be updated on the next runloop.
+ setTimeout(function() {
+ window.webkit.messageHandlers.testHandler.postMessage("ended");
+ }, 0);
+ }
+
+ function seekToEnd() {
+ document.querySelector("#test-video").currentTime = document.querySelector("#test-video").duration - 0.1;
+ }
+ </script>
+</head>
+<body>
+ <video id="test-video" autoplay onended=seekToBeginningAndFinishTest() onplaying=seekToEnd() style="width: 800px; height: 600px;" src="large-video-with-audio.mp4"></video>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-seek-to-beginning-and-play-after-ending.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-seek-to-beginning-and-play-after-ending.html
new file mode 100644
index 000000000..ada9a2d12
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-seek-to-beginning-and-play-after-ending.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <script>
+ function seekToBeginningAndFinishTest() {
+ var video = document.querySelector("#test-video");
+ video.currentTime = 0;
+ video.play();
+ // The media controls should be updated on the next runloop.
+ setTimeout(function() {
+ window.webkit.messageHandlers.testHandler.postMessage("replaying");
+ }, 0);
+ }
+
+ function seekToEnd() {
+ document.querySelector("#test-video").currentTime = document.querySelector("#test-video").duration - 0.1;
+ }
+ </script>
+</head>
+<body>
+ <video id="test-video" autoplay onended=seekToBeginningAndFinishTest() onplaying=seekToEnd() style="width: 800px; height: 600px;" src="large-video-with-audio.mp4"></video>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-test-now-playing.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-test-now-playing.html
new file mode 100644
index 000000000..657dbd739
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-test-now-playing.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style>
+ video {
+ width: 480px;
+ height: 320px;
+ position: absolute;
+ }
+
+ body {
+ margin: 0;
+ }
+ </style>
+ <script>
+ function playing() {
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("playing");
+ } catch(e) {
+ }
+ }, 0);
+ }
+
+ function mousedown() {
+ document.querySelector("video").muted = true;
+ }
+ </script>
+</head>
+<body>
+ <video autoplay title="foo" onmousedown=mousedown() onplaying=playing()><source src="large-video-with-audio.mp4"></video>
+</body>
+<html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-with-audio.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-with-audio.html
new file mode 100644
index 000000000..8c982ae5c
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-with-audio.html
@@ -0,0 +1,12 @@
+<html>
+<head>
+<script>
+ function play() {
+ document.getElementsByTagName('video')[0].play();
+ }
+</script>
+</head>
+<body onload="play()">
+ <video src="large-video-with-audio.mp4" width=640 height=480></video>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-with-audio.mp4 b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-with-audio.mp4
new file mode 100644
index 000000000..4b4bcff48
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-with-audio.mp4
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-without-audio.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-without-audio.html
new file mode 100644
index 000000000..27838eb25
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-without-audio.html
@@ -0,0 +1,29 @@
+<html>
+<head>
+<script>
+ var timeout;
+
+ function go() {
+ var video = document.getElementsByTagName('video')[0];
+ video.play().then(playing).catch(notPlaying);
+ }
+
+ function playing() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage('playing');
+ } catch(e) {
+ window.location = 'callback:playing';
+ }
+ }
+
+ function notPlaying() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage('not playing');
+ } catch(e) { }
+ }
+</script>
+</head>
+<body onload="go()">
+ <video id="test-video" src="video-without-audio.mp4" controls width=640 height=480></video>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-click-to-pause.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-click-to-pause.html
new file mode 100644
index 000000000..22dbebf12
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-click-to-pause.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <style>
+ video {
+ width: 480px;
+ height: 320px;
+ }
+ </style>
+ <script>
+ var isFirstClick = true;
+ function handleMouseDown() {
+ document.querySelector(isFirstClick ? "#first" : "#second").pause();
+ isFirstClick = false;
+ }
+
+ function handleFirstPause() {
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("paused");
+ } catch(e) { }
+ }, 0);
+ }
+
+ function handleSecondPause() {
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("paused");
+ } catch(e) { }
+ }, 0);
+ }
+
+ function beganAutoplaying() {
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("autoplayed");
+ } catch(e) {
+ }
+ }, 0)
+ }
+ </script>
+ </head>
+ <body onmousedown=handleMouseDown()>
+ <video autoplay onplaying=beganAutoplaying() loop id="first" src="large-video-with-audio.mp4" onpause=handleFirstPause()></video>
+ <video autoplay onplaying=beganAutoplaying() loop id="second" src="large-video-with-audio.mp4" onpause=handleSecondPause()></video>
+ </body>
+<html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-scroll-to-video.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-scroll-to-video.html
new file mode 100644
index 000000000..d1c1aaea9
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-scroll-to-video.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <style>
+ video {
+ width: 480px;
+ height: 320px;
+ }
+ #second {
+ margin-top: 5000px;
+ }
+ </style>
+ <script>
+ function scrollToSecondView() {
+ document.querySelector("#second").scrollIntoView();
+ setTimeout(function() {
+ window.webkit.messageHandlers.testHandler.postMessage("scrolled");
+ }, 0);
+ }
+ function beganAutoplaying() {
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("autoplayed");
+ } catch(e) {
+ }
+ }, 0)
+ }
+ </script>
+ </head>
+ <body>
+ <video autoplay onplaying=beganAutoplaying() loop id="first" src="large-video-with-audio.mp4"></video>
+ <br>
+ <video autoplay onplaying=beganAutoplaying() loop id="second" src="large-video-with-audio.mp4"></video>
+ </body>
+<html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-paused-video-hides-controls.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-paused-video-hides-controls.html
new file mode 100644
index 000000000..31f86cbc9
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-paused-video-hides-controls.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<style>
+ video {
+ width: 480px;
+ height: 320px;
+ }
+ #bar {
+ margin-top: 5000px;
+ }
+</style>
+<script>
+ function pauseFirstVideoAndScrollToSecondVideo() {
+ document.querySelector("#bar").scrollIntoView();
+ document.querySelector("#foo").pause();
+ }
+ function handlePaused() {
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("paused");
+ } catch(e) { }
+ }, 0);
+ }
+ function beganAutoplaying() {
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("autoplayed");
+ } catch(e) {
+ }
+ }, 0)
+ }
+</script>
+<body>
+ <video autoplay onplaying=beganAutoplaying() loop id="foo" onpause=handlePaused()><source src="large-video-with-audio.mp4"></video>
+ <br>
+ <video id="bar"><source src="large-video-with-audio.mp4"></video>
+</body>
+<html> \ No newline at end of file
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-muted-video-hides-controls.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-muted-video-hides-controls.html
new file mode 100644
index 000000000..34486e2e3
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-muted-video-hides-controls.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<style>
+ video {
+ width: 480px;
+ height: 320px;
+ }
+ #bar {
+ margin-top: 5000px;
+ }
+</style>
+<script>
+ function muteFirstVideoAndScrollToSecondVideo() {
+ document.querySelector("#foo").muted = true;
+ document.querySelector("#bar").scrollIntoView();
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("playing");
+ } catch(e) { }
+ }, 0);
+ }
+ function beganAutoplaying() {
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("autoplayed");
+ } catch(e) {
+ }
+ }, 0)
+ }
+</script>
+<body>
+ <video autoplay onplaying=beganAutoplaying() loop id="foo"><source src="large-video-with-audio.mp4"></video>
+ <br>
+ <video id="bar"><source src="large-video-with-audio.mp4"></video>
+</body>
+<html> \ No newline at end of file
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-video-keeps-controls.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-video-keeps-controls.html
new file mode 100644
index 000000000..b6fcf7a05
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-video-keeps-controls.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<style>
+ video {
+ width: 480px;
+ height: 320px;
+ }
+ #bar {
+ margin-top: 5000px;
+ }
+</style>
+<script>
+ function scrollToSecondVideo() {
+ document.querySelector("#bar").scrollIntoView();
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("scrolled");
+ } catch(e) { }
+ }, 0);
+ }
+ function beganAutoplaying() {
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("autoplayed");
+ } catch(e) {
+ }
+ }, 0)
+ }
+</script>
+<body>
+ <video autoplay onplaying=beganAutoplaying() loop id="foo"><source src="large-video-with-audio.mp4"></video>
+ <br>
+ <video id="bar"><source src="large-video-with-audio.mp4"></video>
+</body>
+<html> \ No newline at end of file
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-with-audio-autoplay.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-with-audio-autoplay.html
new file mode 100644
index 000000000..3e170ced5
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-with-audio-autoplay.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<script>
+ function beganAutoplaying() {
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("autoplayed");
+ } catch(e) {
+ }
+ }, 0)
+ }
+</script>
+<body>
+ <video id="foo" style="width: 480px; height: 320px;"><source src="large-video-with-audio.mp4"></video>
+ <video autoplay onplaying=beganAutoplaying() id="bar" style="width: 480px; height: 320px;"><source src="large-video-with-audio.mp4"></video>
+ <video id="baz" style="width: 480px; height: 320px;"><source src="large-video-with-audio.mp4"></video>
+</body>
+<html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-with-audio.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-with-audio.html
new file mode 100644
index 000000000..0fdde2f2a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-with-audio.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<script>
+ function handleLoaded() {
+ // The media controls should be updated on the next runloop.
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.onloadHandler.postMessage("loaded");
+ } catch(e) { }
+ }, 0);
+ }
+</script>
+<body onload=handleLoaded()>
+ <video id="foo" style="width: 480px; height: 320px;"><source src="large-video-with-audio.mp4"></video>
+ <video id="bar" style="width: 480px; height: 320px;"><source src="large-video-with-audio.mp4"></video>
+ <video id="baz" style="width: 480px; height: 320px;"><source src="large-video-with-audio.mp4"></video>
+</body>
+<html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/open-multiple-external-url.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/open-multiple-external-url.html
new file mode 100644
index 000000000..9c3df85e2
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/open-multiple-external-url.html
@@ -0,0 +1,66 @@
+<style>
+ iframe { width: 0; height: 0; visibility: hidden; }
+</style>
+
+<body>
+
+<script>
+window.addEventListener("click", function() {
+ let hash = window.location.hash;
+ switch (hash) {
+ case "#normalLoop":
+ normalLoop();
+ break;
+ case "#loopAfterTimer":
+ loopAfterTimer();
+ break;
+ case "#loopAfterPostMessage":
+ loopAfterPostMessage();
+ break;
+ case "#loopAfterLongTimer":
+ loopAfterLongTimer();
+ break;
+ }
+}, false);
+
+function normalLoop() {
+ for (var i = 0; i < 3; ++i) {
+ var iframe = document.createElement('iframe');
+ document.body.appendChild(iframe);
+ iframe.contentWindow.location = "mailto:someone@example.com?Subject=Hello%20again";
+ }
+}
+
+function loopAfterTimer() {
+ setTimeout(function() {
+ for (var i = 0; i < 3; ++i) {
+ var iframe = document.createElement('iframe');
+ document.body.appendChild(iframe);
+ iframe.contentWindow.location = "mailto:someone@example.com?Subject=Hello%20again";
+ }
+ }, 500);
+}
+
+function loopAfterPostMessage() {
+ window.onmessage = function() {
+ for (var i = 0; i < 3; ++i) {
+ var iframe = document.createElement('iframe');
+ document.body.appendChild(iframe);
+ iframe.contentWindow.location = "mailto:someone@example.com?Subject=Hello%20again";
+ }
+ }
+ window.postMessage("foo", "*");
+}
+
+function loopAfterLongTimer() {
+ setTimeout(function() {
+ for (var i = 0; i < 3; ++i) {
+ var iframe = document.createElement('iframe');
+ document.body.appendChild(iframe);
+ iframe.contentWindow.location = "mailto:someone@example.com?Subject=Hello%20again";
+ }
+ }, 2000);
+}
+
+</script>
+</body>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/page-with-csp-iframe.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/page-with-csp-iframe.html
new file mode 100644
index 000000000..4c2a9dbb6
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/page-with-csp-iframe.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Security-Policy" content="script-src 'none'">
+</head>
+<body>
+<script nonce="a">
+window.webkit.messageHandlers.testHandler.postMessage("Subframe: A");
+</script>
+<script nonce="b">
+window.webkit.messageHandlers.testHandler.postMessage("Subframe: B");
+</script>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/page-with-csp.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/page-with-csp.html
new file mode 100644
index 000000000..3fb76fe84
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/page-with-csp.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="Content-Security-Policy" content="script-src 'none'">
+</head>
+<body>
+<script nonce="a">
+window.webkit.messageHandlers.testHandler.postMessage("MainFrame: A");
+</script>
+<script nonce="b">
+window.webkit.messageHandlers.testHandler.postMessage("MainFrame: B");
+</script>
+<iframe id="iframe" src="page-with-csp-iframe.html"></iframe>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/page-without-csp-iframe.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/page-without-csp-iframe.html
new file mode 100644
index 000000000..84a23d5f0
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/page-without-csp-iframe.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script nonce="a">
+window.webkit.messageHandlers.testHandler.postMessage("Subframe: A");
+</script>
+<script nonce="b">
+window.webkit.messageHandlers.testHandler.postMessage("Subframe: B");
+</script>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/page-without-csp.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/page-without-csp.html
new file mode 100644
index 000000000..74cecafe8
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/page-without-csp.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script nonce="a">
+window.webkit.messageHandlers.testHandler.postMessage("MainFrame: A");
+</script>
+<script nonce="b">
+window.webkit.messageHandlers.testHandler.postMessage("MainFrame: B");
+</script>
+<iframe id="iframe" src="page-without-csp-iframe.html"></iframe>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/play-audio-on-click.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/play-audio-on-click.html
new file mode 100644
index 000000000..d7768a64e
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/play-audio-on-click.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style>
+ div {
+ width: 400px;
+ height: 400px;
+ background-color: red;
+ }
+ body {
+ margin: 0;
+ }
+ </style>
+ <script>
+ var audio;
+
+ function playFirstTrack()
+ {
+ audio = document.createElement("audio");
+ audio.src = "video-with-audio.mp4";
+ audio.id = "first";
+ audio.onplaying = audioPlayingHandler("first");
+ audio.onended = playSecondTrack;
+ audio.play();
+ }
+
+ function playSecondTrack()
+ {
+ audio = document.createElement("audio");
+ audio.src = "large-video-with-audio.mp4";
+ audio.id = "second";
+ audio.onplaying = audioPlayingHandler("second");
+ audio.play();
+ }
+
+ function seekToEnd()
+ {
+ audio.currentTime = audio.duration - 0.5;
+ }
+
+ function audioPlayingHandler(id)
+ {
+ return function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("playing-" + id);
+ } catch(e) {}
+ }
+ }
+ </script>
+</head>
+<body>
+ <div onmousedown=playFirstTrack()>Click me to start playing!</div>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/skinny-autoplaying-video-with-audio.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/skinny-autoplaying-video-with-audio.html
new file mode 100644
index 000000000..26ef53dc2
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/skinny-autoplaying-video-with-audio.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style>
+ video {
+ width: 300vw;
+ height: 40vh;
+ }
+ </style>
+ <script>
+ function finishTest() {
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("playing");
+ } catch(e) { }
+ }, 0);
+ }
+ </script>
+</head>
+<body>
+ <video autoplay src="video-with-audio.mp4" webkit-playsinline onplaying=finishTest()></video>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/text-and-password-inputs.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/text-and-password-inputs.html
new file mode 100644
index 000000000..e7e11db24
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/text-and-password-inputs.html
@@ -0,0 +1,39 @@
+<html>
+<head>
+ <script>
+ function loaded() {
+ setTimeout(() => window.webkit.messageHandlers.testHandler.postMessage("loaded"), 0);
+ }
+
+ function textFocused() {
+ setTimeout(() => window.webkit.messageHandlers.testHandler.postMessage("text-focused"), 0);
+ }
+
+ function textInput() {
+ setTimeout(() => window.webkit.messageHandlers.testHandler.postMessage("text-input"), 0);
+ }
+
+ function passwordFocused() {
+ setTimeout(() => window.webkit.messageHandlers.testHandler.postMessage("password-focused"), 0);
+ }
+
+ function passwordInput() {
+ setTimeout(() => window.webkit.messageHandlers.testHandler.postMessage("password-input"), 0);
+ }
+ </script>
+
+ <style>
+ input {
+ width: 100%;
+ height: 50%;
+ font-size: 100px;
+ }
+ body { margin: 0; }
+ </style>
+</head>
+
+<body onload=loaded() onmousedown=mousedown(event)>
+ <input id="text" type="text" onfocus=textFocused() oninput=textInput()></input>
+ <input id="password" type="password" onfocus=passwordFocused() oninput=passwordInput()></input>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/wide-autoplaying-video-with-audio.html b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/wide-autoplaying-video-with-audio.html
new file mode 100644
index 000000000..ea2cb5063
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/wide-autoplaying-video-with-audio.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <style>
+ video {
+ width: 800px;
+ height: 400px;
+ }
+ </style>
+ <script>
+ function finishTest() {
+ setTimeout(function() {
+ try {
+ window.webkit.messageHandlers.testHandler.postMessage("playing");
+ } catch(e) { }
+ }, 0);
+ }
+ </script>
+</head>
+<body>
+ <video autoplay src="video-with-audio.mp4" webkit-playsinline onplaying=finishTest()></video>
+</body>
+</html>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/AutocleanupsTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/AutocleanupsTest.cpp
new file mode 100644
index 000000000..a20cbfd73
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/AutocleanupsTest.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2013 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebProcessTest.h"
+#include <webkit2/webkit-web-extension.h>
+
+#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
+
+class AutocleanupsTest : public WebProcessTest {
+public:
+ static std::unique_ptr<WebProcessTest> create() { return std::unique_ptr<WebProcessTest>(new AutocleanupsTest()); }
+
+private:
+ bool testWebProcessAutocleanups(WebKitWebPage* webPage)
+ {
+ // Transfer none
+ g_autoptr(WebKitWebPage) page = WEBKIT_WEB_PAGE(g_object_ref(G_OBJECT(webPage)));
+ g_assert(WEBKIT_IS_WEB_PAGE(page));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(page));
+
+ // Transfer none
+ g_autoptr(WebKitDOMDocument) document = WEBKIT_DOM_DOCUMENT(g_object_ref(G_OBJECT(webkit_web_page_get_dom_document(page))));
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(document));
+
+ // Transfer full
+ g_autoptr(WebKitDOMDOMWindow) window = webkit_dom_document_get_default_view(document);
+ g_assert(WEBKIT_DOM_IS_DOM_WINDOW(window));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(window));
+
+ // Transfer full
+ g_autoptr(WebKitDOMRange) range = webkit_dom_document_create_range(document);
+ g_assert(WEBKIT_DOM_IS_RANGE(range));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(range));
+
+ return true;
+ }
+
+ bool runTest(const char* testName, WebKitWebPage* page) override
+ {
+ if (!strcmp(testName, "web-process-autocleanups"))
+ return testWebProcessAutocleanups(page);
+
+ g_assert_not_reached();
+ return false;
+ }
+};
+
+static void __attribute__((constructor)) registerTests()
+{
+ REGISTER_TEST(AutocleanupsTest, "Autocleanups/web-process-autocleanups");
+}
+
+#endif // G_DEFINE_AUTOPTR_CLEANUP_FUNC
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/CMakeLists.txt b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/CMakeLists.txt
new file mode 100644
index 000000000..64640f51c
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/CMakeLists.txt
@@ -0,0 +1,135 @@
+set(TEST_LIBRARY_DIR ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/WebKit2GtkAPITests)
+set(TEST_BINARY_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/TestWebKitAPI/WebKit2Gtk)
+set(TEST_RESOURCES_DIR ${TEST_BINARY_DIR}/resources)
+file(MAKE_DIRECTORY ${TEST_RESOURCES_DIR})
+
+add_definitions(
+ -DWEBKIT_TEST_PLUGIN_DIR="${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/plugins"
+ -DWEBKIT_EXEC_PATH="${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
+ -DWEBKIT_SRC_DIR="${CMAKE_SOURCE_DIR}"
+ -DWEBKIT_TEST_WEB_EXTENSIONS_DIR="${TEST_LIBRARY_DIR}"
+ -DWEBKIT_INJECTED_BUNDLE_PATH="${CMAKE_LIBRARY_OUTPUT_DIRECTORY}"
+)
+
+include_directories(
+ ${CMAKE_SOURCE_DIR}/Source
+ ${CMAKE_SOURCE_DIR}/Source/WTF
+ ${DERIVED_SOURCES_WEBKIT2GTK_DIR}
+ ${FORWARDING_HEADERS_DIR}
+ ${FORWARDING_HEADERS_WEBKIT2GTK_DIR}
+ ${FORWARDING_HEADERS_WEBKIT2GTK_EXTENSION_DIR}
+ ${TOOLS_DIR}/TestWebKitAPI/gtk/WebKit2Gtk
+)
+
+include_directories(SYSTEM
+ ${ATSPI_INCLUDE_DIRS}
+ ${GLIB_INCLUDE_DIRS}
+ ${GSTREAMER_INCLUDE_DIRS}
+ ${GTK3_INCLUDE_DIRS}
+ ${GTK_UNIX_PRINT_INCLUDE_DIRS}
+ ${LIBSOUP_INCLUDE_DIRS}
+)
+
+add_library(WebKit2APITestCore STATIC
+ ${TOOLS_DIR}/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.cpp
+ ${TOOLS_DIR}/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.cpp
+ ${TOOLS_DIR}/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.cpp
+ ${TOOLS_DIR}/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.cpp
+ ${TOOLS_DIR}/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp
+)
+target_link_libraries(WebKit2APITestCore WebKit2)
+
+add_custom_command(
+ OUTPUT ${TEST_RESOURCES_DIR}/webkit2gtk-tests-resources.gresource
+ DEPENDS resources/webkit2gtk-tests.gresource.xml
+ resources/link-title.js
+ COMMAND glib-compile-resources
+ --target=${TEST_RESOURCES_DIR}/webkit2gtk-tests-resources.gresource
+ --sourcedir=${CMAKE_SOURCE_DIR}
+ ${CMAKE_CURRENT_LIST_DIR}/resources/webkit2gtk-tests.gresource.xml
+)
+
+add_custom_target(test-gresource-bundle
+ DEPENDS ${TEST_RESOURCES_DIR}/webkit2gtk-tests-resources.gresource
+)
+
+macro(ADD_WK2_TEST_WEB_EXTENSION extension_name)
+ add_library(${extension_name} MODULE ${ARGN})
+ add_dependencies(${extension_name} WebKit2)
+ set_property(
+ TARGET ${extension_name}
+ APPEND
+ PROPERTY COMPILE_DEFINITIONS WEBKIT2_COMPILATION
+ )
+ set_target_properties(${extension_name} PROPERTIES
+ LIBRARY_OUTPUT_DIRECTORY ${TEST_LIBRARY_DIR}
+ )
+ target_link_libraries(${extension_name}
+ JavaScriptCore
+ WebKit2
+ ${GLIB_LIBRARIES}
+ )
+endmacro()
+
+macro(ADD_WK2_TEST test_name)
+ add_executable(${test_name} ${ARGN})
+ add_dependencies(${test_name}
+ test-gresource-bundle
+ WebExtensionTest
+ )
+ target_link_libraries(${test_name}
+ JavaScriptCore
+ WebKit2
+ WebKit2APITestCore
+ ${ATSPI_LIBRARIES}
+ ${GLIB_LIBRARIES}
+ ${GTK3_LIBRARIES}
+ ${GTK_UNIX_PRINT_LIBRARIES}
+ ${LIBSOUP_LIBRARIES}
+ )
+ set_target_properties(${test_name} PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY ${TEST_BINARY_DIR}
+ )
+endmacro()
+
+ADD_WK2_TEST_WEB_EXTENSION(WebExtensionTest WebExtensionTest.cpp)
+ADD_WK2_TEST_WEB_EXTENSION(WebProcessTest AutocleanupsTest.cpp DOMNodeTest.cpp DOMNodeFilterTest.cpp DOMXPathNSResolverTest.cpp FrameTest.cpp WebProcessTest.cpp EditorTest.cpp)
+
+ADD_WK2_TEST(InspectorTestServer InspectorTestServer.cpp)
+ADD_WK2_TEST(TestAuthentication TestAuthentication.cpp)
+ADD_WK2_TEST(TestAutocleanups TestAutocleanups.cpp)
+ADD_WK2_TEST(TestBackForwardList TestBackForwardList.cpp)
+ADD_WK2_TEST(TestContextMenu TestContextMenu.cpp)
+ADD_WK2_TEST(TestCookieManager TestCookieManager.cpp)
+ADD_WK2_TEST(TestDOMNode TestDOMNode.cpp)
+ADD_WK2_TEST(TestDOMNodeFilter TestDOMNodeFilter.cpp)
+ADD_WK2_TEST(TestDOMXPathNSResolver TestDOMXPathNSResolver.cpp)
+ADD_WK2_TEST(TestDownloads TestDownloads.cpp)
+ADD_WK2_TEST(TestWebKitFaviconDatabase TestWebKitFaviconDatabase.cpp)
+ADD_WK2_TEST(TestWebKitFindController TestWebKitFindController.cpp)
+ADD_WK2_TEST(TestFrame TestFrame.cpp)
+ADD_WK2_TEST(TestInspector TestInspector.cpp)
+ADD_WK2_TEST(TestInspectorServer TestInspectorServer.cpp)
+ADD_WK2_TEST(TestLoaderClient TestLoaderClient.cpp)
+ADD_WK2_TEST(TestMultiprocess TestMultiprocess.cpp)
+ADD_WK2_TEST(TestPrinting TestPrinting.cpp)
+ADD_WK2_TEST(TestResources TestResources.cpp)
+ADD_WK2_TEST(TestSSL TestSSL.cpp)
+ADD_WK2_TEST(TestUIClient TestUIClient.cpp)
+ADD_WK2_TEST(TestWebExtensions TestWebExtensions.cpp)
+ADD_WK2_TEST(TestWebKitPolicyClient TestWebKitPolicyClient.cpp)
+ADD_WK2_TEST(TestWebKitSecurityOrigin TestWebKitSecurityOrigin.cpp)
+ADD_WK2_TEST(TestWebKitSettings TestWebKitSettings.cpp)
+ADD_WK2_TEST(TestWebKitVersion TestWebKitVersion.cpp)
+ADD_WK2_TEST(TestWebViewEditor TestWebViewEditor.cpp)
+ADD_WK2_TEST(TestWebKitWebContext TestWebKitWebContext.cpp)
+ADD_WK2_TEST(TestWebKitWebView TestWebKitWebView.cpp)
+ADD_WK2_TEST(TestWebKitUserContentManager TestWebKitUserContentManager.cpp)
+ADD_WK2_TEST(TestWebsiteData TestWebsiteData.cpp)
+ADD_WK2_TEST(TestEditor TestEditor.cpp)
+ADD_WK2_TEST(TestConsoleMessage TestConsoleMessage.cpp)
+
+if (ATSPI_FOUND)
+ ADD_WK2_TEST(AccessibilityTestServer AccessibilityTestServer.cpp)
+ ADD_WK2_TEST(TestWebKitAccessibility TestWebKitAccessibility.cpp)
+endif ()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMDOMWindowTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMDOMWindowTest.cpp
new file mode 100644
index 000000000..fc8cefb52
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMDOMWindowTest.cpp
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2013 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebProcessTest.h"
+#include <gio/gio.h>
+#include <webkit2/webkit-web-extension.h>
+#include <wtf/RunLoop.h>
+
+class WebKitDOMDOMWindowTest;
+static gboolean loadedCallback(WebKitDOMDOMWindow*, WebKitDOMEvent*, WebKitDOMDOMWindowTest*);
+static gboolean clickedCallback(WebKitDOMDOMWindow*, WebKitDOMEvent*, WebKitDOMDOMWindowTest*);
+
+class WebKitDOMDOMWindowTest : public WebProcessTest {
+public:
+ static std::unique_ptr<WebProcessTest> create() { return std::make_unique<WebKitDOMDOMWindowTest>(); }
+
+private:
+ guint64 webPageFromArgs(GVariant* args)
+ {
+ GVariantIter iter;
+ g_variant_iter_init(&iter, args);
+
+ const char* key;
+ GVariant* value;
+ while (g_variant_iter_loop(&iter, "{&sv}", &key, &value)) {
+ if (!strcmp(key, "pageID") && g_variant_classify(value) == G_VARIANT_CLASS_UINT64)
+ return g_variant_get_uint64(value);
+ }
+
+ g_assert_not_reached();
+ return 0;
+ }
+
+ bool testSignals(WebKitWebExtension* extension, GVariant* args)
+ {
+ notify("ready", "");
+
+ WebKitWebPage* page = webkit_web_extension_get_page(extension, webPageFromArgs(args));
+ g_assert(WEBKIT_IS_WEB_PAGE(page));
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+
+ WebKitDOMDOMWindow* domWindow = webkit_dom_document_get_default_view(document);
+ g_assert(domWindow);
+
+ // The "load" WebKitDOMDOMWindow signal is issued before this test is
+ // called. There's no way to capture it here. We simply assume that
+ // the document is loaded and notify the uiprocess accordingly
+ // notify("loaded", "");
+
+ webkit_dom_event_target_add_event_listener(
+ WEBKIT_DOM_EVENT_TARGET(domWindow),
+ "load",
+ G_CALLBACK(loadedCallback),
+ false,
+ this);
+
+ // loadedCallback() will stop this loop
+ RunLoop::run();
+
+ document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+
+ WebKitDOMElement* element = webkit_dom_document_get_element_by_id(document, "test");
+ g_assert(element);
+
+ webkit_dom_event_target_add_event_listener(
+ WEBKIT_DOM_EVENT_TARGET(element),
+ "click",
+ G_CALLBACK(clickedCallback),
+ false,
+ this);
+
+ // The "click" action will be issued in the uiprocess and that will
+ // trigger the dom event here.
+ // clickedCallback() will stop this loop
+ RunLoop::run();
+
+ return true;
+ }
+
+ bool testDispatchEvent(WebKitWebExtension* extension, GVariant* args)
+ {
+ notify("ready", "");
+
+ WebKitWebPage* page = webkit_web_extension_get_page(extension, webPageFromArgs(args));
+ g_assert(WEBKIT_IS_WEB_PAGE(page));
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+
+ WebKitDOMDOMWindow* domWindow = webkit_dom_document_get_default_view(document);
+ g_assert(domWindow);
+
+ // The "load" WebKitDOMDOMWindow signal is issued before this test is
+ // called. There's no way to capture it here. We simply assume that
+ // the document is loaded and notify the uiprocess accordingly
+ // notify("loaded", "");
+
+ webkit_dom_event_target_add_event_listener(
+ WEBKIT_DOM_EVENT_TARGET(domWindow),
+ "load",
+ G_CALLBACK(loadedCallback),
+ false,
+ this);
+
+ // loadedCallback() will stop this loop
+ RunLoop::run();
+
+ document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+
+ WebKitDOMElement* element = webkit_dom_document_get_element_by_id(document, "test");
+ g_assert(element);
+
+ WebKitDOMEvent* event = webkit_dom_document_create_event(document, "MouseEvent", 0);
+ g_assert(event);
+ g_assert(WEBKIT_DOM_IS_EVENT(event));
+ g_assert(WEBKIT_DOM_IS_MOUSE_EVENT(event));
+
+ glong clientX, clientY;
+ clientX = webkit_dom_element_get_client_left(element);
+ clientY = webkit_dom_element_get_client_top(element);
+
+ webkit_dom_event_target_add_event_listener(
+ WEBKIT_DOM_EVENT_TARGET(element),
+ "click",
+ G_CALLBACK(clickedCallback),
+ false,
+ this);
+
+ webkit_dom_mouse_event_init_mouse_event(WEBKIT_DOM_MOUSE_EVENT(event),
+ "click", TRUE, TRUE,
+ domWindow, 0, 0, 0, clientX, clientY,
+ FALSE, FALSE, FALSE, FALSE,
+ 1, WEBKIT_DOM_EVENT_TARGET(element));
+
+ webkit_dom_event_target_dispatch_event(WEBKIT_DOM_EVENT_TARGET(element), event, 0);
+
+ // clickedCallback() will stop this loop
+ RunLoop::run();
+
+ return true;
+ }
+
+ bool testGetComputedStyle(WebKitWebExtension* extension, GVariant* args)
+ {
+ WebKitWebPage* page = webkit_web_extension_get_page(extension, webPageFromArgs(args));
+ g_assert(WEBKIT_IS_WEB_PAGE(page));
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ WebKitDOMDOMWindow* domWindow = webkit_dom_document_get_default_view(document);
+ g_assert(domWindow);
+ WebKitDOMElement* element = webkit_dom_document_get_element_by_id(document, "test");
+ g_assert(element);
+ g_assert(WEBKIT_DOM_IS_ELEMENT(element));
+ WebKitDOMCSSStyleDeclaration* cssStyle = webkit_dom_dom_window_get_computed_style(domWindow, element, 0);
+ gchar* fontSize = webkit_dom_css_style_declaration_get_property_value(cssStyle, "font-size");
+ g_assert_cmpstr(fontSize, ==, "16px");
+
+ return true;
+ }
+
+ virtual bool runTest(const char* testName, WebKitWebExtension* extension, GVariant* args)
+ {
+ if (!strcmp(testName, "signals"))
+ return testSignals(extension, args);
+ if (!strcmp(testName, "dispatch-event"))
+ return testDispatchEvent(extension, args);
+ if (!strcmp(testName, "get-computed-style"))
+ return testGetComputedStyle(extension, args);
+
+ g_assert_not_reached();
+ return false;
+ }
+};
+
+static void __attribute__((constructor)) registerTests()
+{
+ REGISTER_TEST(WebKitDOMDOMWindowTest, "WebKitDOMDOMWindow/signals");
+ REGISTER_TEST(WebKitDOMDOMWindowTest, "WebKitDOMDOMWindow/dispatch-event");
+ REGISTER_TEST(WebKitDOMDOMWindowTest, "WebKitDOMDOMWindow/get-computed-style");
+}
+
+static gboolean loadedCallback(WebKitDOMDOMWindow* view, WebKitDOMEvent* event, WebKitDOMDOMWindowTest* test)
+{
+ test->notify("loaded", "");
+
+ // Stop the loop and let testSignals() or testDispatchEvent() continue its course
+ RunLoop::current().stop();
+
+ return FALSE;
+}
+
+static gboolean clickedCallback(WebKitDOMDOMWindow* view, WebKitDOMEvent* event, WebKitDOMDOMWindowTest* test)
+{
+ test->notify("clicked", "");
+ test->notify("finish", "");
+
+ // Stop the loop and let testSignals() or testDispatchEvent() continue its course
+ RunLoop::current().stop();
+
+ return FALSE;
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeFilterTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeFilterTest.cpp
new file mode 100644
index 000000000..0f18d1f31
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeFilterTest.cpp
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2013 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebProcessTest.h"
+#include <gio/gio.h>
+#include <webkit2/webkit-web-extension.h>
+#include <wtf/glib/GUniquePtr.h>
+
+typedef struct _WebKitNodeFilter {
+ GObject parent;
+} WebKitNodeFilter;
+
+typedef struct _WebKitNodeFilterClass {
+ GObjectClass parentClass;
+} WebKitNodeFilterClass;
+
+static short webkitNodeFilterAcceptNode(WebKitDOMNodeFilter*, WebKitDOMNode* node)
+{
+ // Filter out input elements.
+ return WEBKIT_DOM_IS_HTML_INPUT_ELEMENT(node) ? WEBKIT_DOM_NODE_FILTER_REJECT : WEBKIT_DOM_NODE_FILTER_ACCEPT;
+}
+
+static void webkitNodeFilterDOMNodeFilterIfaceInit(WebKitDOMNodeFilterIface* iface)
+{
+ iface->accept_node = webkitNodeFilterAcceptNode;
+}
+
+G_DEFINE_TYPE_WITH_CODE(WebKitNodeFilter, webkit_node_filter, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(WEBKIT_DOM_TYPE_NODE_FILTER, webkitNodeFilterDOMNodeFilterIfaceInit))
+
+static void webkit_node_filter_init(WebKitNodeFilter*)
+{
+}
+
+static void webkit_node_filter_class_init(WebKitNodeFilterClass*)
+{
+}
+
+static const char* expectedNodesAll[] = { "HTML", "HEAD", "TITLE", "#text", "BODY", "INPUT", "INPUT", "BR" };
+static const char* expectedNodesNoInput[] = { "HTML", "HEAD", "TITLE", "#text", "BODY", "BR" };
+static const char* expectedElementsNoInput[] = { "HTML", "HEAD", "TITLE", "BODY", "BR" };
+
+class WebKitDOMNodeFilterTest : public WebProcessTest {
+public:
+ static std::unique_ptr<WebProcessTest> create() { return std::unique_ptr<WebProcessTest>(new WebKitDOMNodeFilterTest()); }
+
+private:
+ bool testTreeWalker(WebKitWebPage* page)
+ {
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(document));
+
+ WebKitDOMElement* root = webkit_dom_document_get_element_by_id(document, "root");
+ g_assert(WEBKIT_DOM_IS_NODE(root));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(root));
+
+ // No filter.
+ GRefPtr<WebKitDOMTreeWalker> walker = adoptGRef(webkit_dom_document_create_tree_walker(document, WEBKIT_DOM_NODE(root), WEBKIT_DOM_NODE_FILTER_SHOW_ALL, nullptr, FALSE, nullptr));
+ g_assert(WEBKIT_DOM_IS_TREE_WALKER(walker.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(walker.get()));
+ g_assert(!webkit_dom_tree_walker_get_filter(walker.get()));
+
+ unsigned i = 0;
+ for (WebKitDOMNode* node = WEBKIT_DOM_NODE(root); node; node = webkit_dom_tree_walker_next_node(walker.get()), ++i) {
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
+ g_assert_cmpuint(i, <, G_N_ELEMENTS(expectedNodesAll));
+ GUniquePtr<char> nodeName(webkit_dom_node_get_node_name(node));
+ g_assert_cmpstr(nodeName.get(), ==, expectedNodesAll[i]);
+ }
+ g_assert_cmpuint(i, ==, G_N_ELEMENTS(expectedNodesAll));
+
+ // Input elements filter.
+ GRefPtr<WebKitDOMNodeFilter> filter = adoptGRef(static_cast<WebKitDOMNodeFilter*>(g_object_new(webkit_node_filter_get_type(), nullptr)));
+ walker = adoptGRef(webkit_dom_document_create_tree_walker(document, WEBKIT_DOM_NODE(root), WEBKIT_DOM_NODE_FILTER_SHOW_ALL, filter.get(), FALSE, nullptr));
+ g_assert(WEBKIT_DOM_IS_TREE_WALKER(walker.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(filter.get()));
+ g_assert(webkit_dom_tree_walker_get_filter(walker.get()) == filter.get());
+
+ i = 0;
+ for (WebKitDOMNode* node = WEBKIT_DOM_NODE(root); node; node = webkit_dom_tree_walker_next_node(walker.get()), ++i) {
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
+ g_assert_cmpuint(i, <, G_N_ELEMENTS(expectedNodesNoInput));
+ GUniquePtr<char> nodeName(webkit_dom_node_get_node_name(node));
+ g_assert_cmpstr(nodeName.get(), ==, expectedNodesNoInput[i]);
+ }
+ g_assert_cmpuint(i, ==, G_N_ELEMENTS(expectedNodesNoInput));
+
+ // Show only elements, reusing the input filter.
+ walker = adoptGRef(webkit_dom_document_create_tree_walker(document, WEBKIT_DOM_NODE(root), WEBKIT_DOM_NODE_FILTER_SHOW_ELEMENT, filter.get(), FALSE, nullptr));
+ g_assert(WEBKIT_DOM_IS_TREE_WALKER(walker.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(walker.get()));
+ g_assert(webkit_dom_tree_walker_get_filter(walker.get()) == filter.get());
+
+ i = 0;
+ for (WebKitDOMNode* node = WEBKIT_DOM_NODE(root); node; node = webkit_dom_tree_walker_next_node(walker.get()), ++i) {
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
+ g_assert_cmpuint(i, <, G_N_ELEMENTS(expectedElementsNoInput));
+ GUniquePtr<char> nodeName(webkit_dom_node_get_node_name(node));
+ g_assert_cmpstr(nodeName.get(), ==, expectedElementsNoInput[i]);
+ }
+ g_assert_cmpuint(i, ==, G_N_ELEMENTS(expectedElementsNoInput));
+
+ return true;
+ }
+
+ bool testNodeIterator(WebKitWebPage* page)
+ {
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(document));
+
+ WebKitDOMElement* root = webkit_dom_document_get_element_by_id(document, "root");
+ g_assert(WEBKIT_DOM_IS_NODE(root));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(root));
+
+ // No filter.
+ GRefPtr<WebKitDOMNodeIterator> iter = adoptGRef(webkit_dom_document_create_node_iterator(document, WEBKIT_DOM_NODE(root), WEBKIT_DOM_NODE_FILTER_SHOW_ALL, nullptr, FALSE, nullptr));
+ g_assert(WEBKIT_DOM_IS_NODE_ITERATOR(iter.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(iter.get()));
+ g_assert(!webkit_dom_node_iterator_get_filter(iter.get()));
+
+ unsigned i = 0;
+ while (WebKitDOMNode* node = webkit_dom_node_iterator_next_node(iter.get(), nullptr)) {
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
+ g_assert_cmpuint(i, <, G_N_ELEMENTS(expectedNodesAll));
+ GUniquePtr<char> nodeName(webkit_dom_node_get_node_name(node));
+ g_assert_cmpstr(nodeName.get(), ==, expectedNodesAll[i]);
+ i++;
+ }
+ g_assert_cmpuint(i, ==, G_N_ELEMENTS(expectedNodesAll));
+
+ // Input elements filter.
+ GRefPtr<WebKitDOMNodeFilter> filter = adoptGRef(static_cast<WebKitDOMNodeFilter*>(g_object_new(webkit_node_filter_get_type(), nullptr)));
+ iter = adoptGRef(webkit_dom_document_create_node_iterator(document, WEBKIT_DOM_NODE(root), WEBKIT_DOM_NODE_FILTER_SHOW_ALL, filter.get(), FALSE, nullptr));
+ g_assert(WEBKIT_DOM_IS_NODE_ITERATOR(iter.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(iter.get()));
+ g_assert(webkit_dom_node_iterator_get_filter(iter.get()) == filter.get());
+
+ i = 0;
+ while (WebKitDOMNode* node = webkit_dom_node_iterator_next_node(iter.get(), nullptr)) {
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
+ g_assert_cmpuint(i, <, G_N_ELEMENTS(expectedNodesNoInput));
+ GUniquePtr<char> nodeName(webkit_dom_node_get_node_name(node));
+ g_assert_cmpstr(nodeName.get(), ==, expectedNodesNoInput[i]);
+ i++;
+ }
+ g_assert_cmpuint(i, ==, G_N_ELEMENTS(expectedNodesNoInput));
+
+ // Show only elements, reusing the input filter.
+ iter = adoptGRef(webkit_dom_document_create_node_iterator(document, WEBKIT_DOM_NODE(root), WEBKIT_DOM_NODE_FILTER_SHOW_ELEMENT, filter.get(), FALSE, nullptr));
+ g_assert(WEBKIT_DOM_IS_NODE_ITERATOR(iter.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(iter.get()));
+ g_assert(webkit_dom_node_iterator_get_filter(iter.get()) == filter.get());
+
+ i = 0;
+ while (WebKitDOMNode* node = webkit_dom_node_iterator_next_node(iter.get(), nullptr)) {
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
+ g_assert_cmpuint(i, <, G_N_ELEMENTS(expectedElementsNoInput));
+ GUniquePtr<char> nodeName(webkit_dom_node_get_node_name(node));
+ g_assert_cmpstr(nodeName.get(), ==, expectedElementsNoInput[i]);
+ i++;
+ }
+ g_assert_cmpuint(i, ==, G_N_ELEMENTS(expectedElementsNoInput));
+
+ return true;
+ }
+
+ bool runTest(const char* testName, WebKitWebPage* page) override
+ {
+ if (!strcmp(testName, "tree-walker"))
+ return testTreeWalker(page);
+ if (!strcmp(testName, "node-iterator"))
+ return testNodeIterator(page);
+
+ g_assert_not_reached();
+ return false;
+ }
+};
+
+static void __attribute__((constructor)) registerTests()
+{
+ REGISTER_TEST(WebKitDOMNodeFilterTest, "WebKitDOMNodeFilter/tree-walker");
+ REGISTER_TEST(WebKitDOMNodeFilterTest, "WebKitDOMNodeFilter/node-iterator");
+}
+
+
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeTest.cpp
index 5f62e5493..9d57b42d2 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeTest.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeTest.cpp
@@ -22,7 +22,7 @@
#include "WebProcessTest.h"
#include <gio/gio.h>
#include <webkit2/webkit-web-extension.h>
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GUniquePtr.h>
class WebKitDOMNodeTest : public WebProcessTest {
public:
@@ -33,21 +33,26 @@ private:
{
WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(document));
WebKitDOMHTMLHeadElement* head = webkit_dom_document_get_head(document);
g_assert(WEBKIT_DOM_IS_HTML_HEAD_ELEMENT(head));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(head));
// Title, head's child.
g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(head)));
GRefPtr<WebKitDOMNodeList> list = adoptGRef(webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(head)));
g_assert(WEBKIT_DOM_IS_NODE_LIST(list.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(list.get()));
g_assert_cmpint(webkit_dom_node_list_get_length(list.get()), ==, 1);
WebKitDOMNode* node = webkit_dom_node_list_item(list.get(), 0);
g_assert(WEBKIT_DOM_IS_HTML_TITLE_ELEMENT(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
// Body, Head sibling.
node = webkit_dom_node_get_next_sibling(WEBKIT_DOM_NODE(head));
g_assert(WEBKIT_DOM_IS_HTML_BODY_ELEMENT(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
WebKitDOMHTMLBodyElement* body = WEBKIT_DOM_HTML_BODY_ELEMENT(node);
// There is no third sibling
@@ -56,10 +61,13 @@ private:
// Body's previous sibling is Head.
node = webkit_dom_node_get_previous_sibling(WEBKIT_DOM_NODE(body));
g_assert(WEBKIT_DOM_IS_HTML_HEAD_ELEMENT(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
// Body has 3 children.
g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
list = adoptGRef(webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body)));
+ g_assert(WEBKIT_DOM_IS_NODE_LIST(list.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(list.get()));
unsigned long length = webkit_dom_node_list_get_length(list.get());
g_assert_cmpint(length, ==, 3);
@@ -67,6 +75,7 @@ private:
for (unsigned long i = 0; i < length; i++) {
node = webkit_dom_node_list_item(list.get(), i);
g_assert(WEBKIT_DOM_IS_HTML_PARAGRAPH_ELEMENT(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
}
// Go backwards
@@ -81,88 +90,135 @@ private:
{
WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(document));
WebKitDOMHTMLElement* body = webkit_dom_document_get_body(document);
g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(body));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(body));
// Body shouldn't have any children at this point.
g_assert(!webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
+ // The value of a non-existent attribute should be null, not an empty string
+ g_assert(!webkit_dom_html_body_element_get_background(WEBKIT_DOM_HTML_BODY_ELEMENT(body)));
+
// Insert one P element.
WebKitDOMElement* p = webkit_dom_document_create_element(document, "P", 0);
g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(p));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(p));
webkit_dom_node_append_child(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(p), 0);
// Now it should have one, the same that we inserted.
g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
GRefPtr<WebKitDOMNodeList> list = adoptGRef(webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body)));
g_assert(WEBKIT_DOM_IS_NODE_LIST(list.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(list.get()));
g_assert_cmpint(webkit_dom_node_list_get_length(list.get()), ==, 1);
WebKitDOMNode* node = webkit_dom_node_list_item(list.get(), 0);
g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
g_assert(webkit_dom_node_is_same_node(WEBKIT_DOM_NODE(p), node));
// Replace the P tag with a DIV tag.
WebKitDOMElement* div = webkit_dom_document_create_element(document, "DIV", 0);
g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(div));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(div));
webkit_dom_node_replace_child(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(div), WEBKIT_DOM_NODE(p), 0);
g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
list = adoptGRef(webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body)));
g_assert(WEBKIT_DOM_IS_NODE_LIST(list.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(list.get()));
g_assert_cmpint(webkit_dom_node_list_get_length(list.get()), ==, 1);
node = webkit_dom_node_list_item(list.get(), 0);
g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
g_assert(webkit_dom_node_is_same_node(WEBKIT_DOM_NODE(div), node));
// Now remove the tag.
webkit_dom_node_remove_child(WEBKIT_DOM_NODE(body), node, 0);
list = adoptGRef(webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body)));
g_assert(WEBKIT_DOM_IS_NODE_LIST(list.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(list.get()));
g_assert_cmpint(webkit_dom_node_list_get_length(list.get()), ==, 0);
// Test insert before. If refChild is null, insert newChild as last element of parent.
div = webkit_dom_document_create_element(document, "DIV", 0);
g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(div));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(div));
webkit_dom_node_insert_before(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(div), 0, 0);
g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
list = adoptGRef(webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body)));
g_assert(WEBKIT_DOM_IS_NODE_LIST(list.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(list.get()));
g_assert_cmpint(webkit_dom_node_list_get_length(list.get()), ==, 1);
node = webkit_dom_node_list_item(list.get(), 0);
g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
g_assert(webkit_dom_node_is_same_node(WEBKIT_DOM_NODE(div), node));
// Now insert a 'p' before 'div'.
p = webkit_dom_document_create_element(document, "P", 0);
g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(p));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(p));
webkit_dom_node_insert_before(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(p), WEBKIT_DOM_NODE(div), 0);
g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
list = adoptGRef(webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body)));
g_assert(WEBKIT_DOM_IS_NODE_LIST(list.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(list.get()));
g_assert_cmpint(webkit_dom_node_list_get_length(list.get()), ==, 2);
node = webkit_dom_node_list_item(list.get(), 0);
g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
g_assert(webkit_dom_node_is_same_node(WEBKIT_DOM_NODE(p), node));
node = webkit_dom_node_list_item(list.get(), 1);
g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
g_assert(webkit_dom_node_is_same_node(WEBKIT_DOM_NODE(div), node));
return true;
}
- bool testTagNames(WebKitWebPage* page)
+ bool testTagNamesNodeList(WebKitWebPage* page)
+ {
+ static const char* expectedTagNames[] = { "HTML", "HEAD", "BODY", "VIDEO", "SOURCE", "VIDEO", "SOURCE", "INPUT" };
+
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(document));
+
+ GRefPtr<WebKitDOMNodeList> list = adoptGRef(webkit_dom_document_query_selector_all(document, "*", nullptr));
+ g_assert(WEBKIT_DOM_IS_NODE_LIST(list.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(list.get()));
+ gulong nodeCount = webkit_dom_node_list_get_length(list.get());
+ g_assert_cmpuint(nodeCount, ==, G_N_ELEMENTS(expectedTagNames));
+ for (unsigned i = 0; i < nodeCount; i++) {
+ WebKitDOMNode* node = webkit_dom_node_list_item(list.get(), i);
+ g_assert(WEBKIT_DOM_IS_NODE(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
+ GUniquePtr<char> tagName(webkit_dom_node_get_node_name(node));
+ g_assert_cmpstr(tagName.get(), ==, expectedTagNames[i]);
+ }
+
+ return true;
+ }
+
+ bool testTagNamesHTMLCollection(WebKitWebPage* page)
{
static const char* expectedTagNames[] = { "HTML", "HEAD", "BODY", "VIDEO", "SOURCE", "VIDEO", "SOURCE", "INPUT" };
WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(document));
- WebKitDOMNodeList* list = webkit_dom_document_get_elements_by_tag_name(document, "*");
- gulong nodeCount = webkit_dom_node_list_get_length(list);
+ GRefPtr<WebKitDOMHTMLCollection> collection = adoptGRef(webkit_dom_document_get_elements_by_tag_name_as_html_collection(document, "*"));
+ g_assert(WEBKIT_DOM_IS_HTML_COLLECTION(collection.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(collection.get()));
+ gulong nodeCount = webkit_dom_html_collection_get_length(collection.get());
g_assert_cmpuint(nodeCount, ==, G_N_ELEMENTS(expectedTagNames));
for (unsigned i = 0; i < nodeCount; i++) {
- WebKitDOMNode* node = webkit_dom_node_list_item(list, i);
+ WebKitDOMNode* node = webkit_dom_html_collection_item(collection.get(), i);
g_assert(WEBKIT_DOM_IS_NODE(node));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(node));
GUniquePtr<char> tagName(webkit_dom_node_get_node_name(node));
g_assert_cmpstr(tagName.get(), ==, expectedTagNames[i]);
}
@@ -170,14 +226,62 @@ private:
return true;
}
+ bool testDOMCache(WebKitWebPage* page)
+ {
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(document));
+
+ // DOM objects already in the document should be automatically handled by the cache.
+ WebKitDOMElement* div = webkit_dom_document_get_element_by_id(document, "container");
+ g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(div));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(div));
+
+ // Get the same elment twice should return the same pointer.
+ g_assert(div == webkit_dom_document_get_element_by_id(document, "container"));
+
+ // A new DOM object created that is derived from Node should be automatically handled by the cache.
+ WebKitDOMElement* p = webkit_dom_document_create_element(document, "P", nullptr);
+ g_assert(WEBKIT_DOM_IS_HTML_PARAGRAPH_ELEMENT(p));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(p));
+
+ // A new DOM object created that isn't derived from Node should be manually handled.
+ GRefPtr<WebKitDOMNodeIterator> iter = adoptGRef(webkit_dom_document_create_node_iterator(document, WEBKIT_DOM_NODE(div), WEBKIT_DOM_NODE_FILTER_SHOW_ALL, nullptr, FALSE, nullptr));
+ g_assert(WEBKIT_DOM_IS_NODE_ITERATOR(iter.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(iter.get()));
+
+ // We can also manually handle a DOM object handled by the cache.
+ GRefPtr<WebKitDOMElement> p2 = adoptGRef(webkit_dom_document_create_element(document, "P", nullptr));
+ g_assert(WEBKIT_DOM_IS_HTML_PARAGRAPH_ELEMENT(p2.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(p2.get()));
+
+ // Manually handling a DOM object owned by the cache shouldn't crash when the cache has more than one reference.
+ GRefPtr<WebKitDOMElement> p3 = adoptGRef(webkit_dom_document_create_element(document, "P", nullptr));
+ g_assert(WEBKIT_DOM_IS_HTML_PARAGRAPH_ELEMENT(p3.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(p3.get()));
+ webkit_dom_node_append_child(WEBKIT_DOM_NODE(div), WEBKIT_DOM_NODE(p3.get()), nullptr);
+
+ // DOM objects removed from the document are also correctly handled by the cache.
+ WebKitDOMElement* a = webkit_dom_document_create_element(document, "A", nullptr);
+ g_assert(WEBKIT_DOM_IS_ELEMENT(a));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(a));
+ webkit_dom_node_remove_child(WEBKIT_DOM_NODE(div), WEBKIT_DOM_NODE(a), nullptr);
+
+ return true;
+ }
+
bool runTest(const char* testName, WebKitWebPage* page) override
{
if (!strcmp(testName, "hierarchy-navigation"))
return testHierarchyNavigation(page);
if (!strcmp(testName, "insertion"))
return testInsertion(page);
- if (!strcmp(testName, "tag-names"))
- return testTagNames(page);
+ if (!strcmp(testName, "tag-names-node-list"))
+ return testTagNamesNodeList(page);
+ if (!strcmp(testName, "tag-names-html-collection"))
+ return testTagNamesHTMLCollection(page);
+ if (!strcmp(testName, "dom-cache"))
+ return testDOMCache(page);
g_assert_not_reached();
return false;
@@ -188,7 +292,9 @@ static void __attribute__((constructor)) registerTests()
{
REGISTER_TEST(WebKitDOMNodeTest, "WebKitDOMNode/hierarchy-navigation");
REGISTER_TEST(WebKitDOMNodeTest, "WebKitDOMNode/insertion");
- REGISTER_TEST(WebKitDOMNodeTest, "WebKitDOMNode/tag-names");
+ REGISTER_TEST(WebKitDOMNodeTest, "WebKitDOMNode/tag-names-node-list");
+ REGISTER_TEST(WebKitDOMNodeTest, "WebKitDOMNode/tag-names-html-collection");
+ REGISTER_TEST(WebKitDOMNodeTest, "WebKitDOMNode/dom-cache");
}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMXPathNSResolverTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMXPathNSResolverTest.cpp
new file mode 100644
index 000000000..110677e41
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMXPathNSResolverTest.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebProcessTest.h"
+#include <gio/gio.h>
+#include <webkit2/webkit-web-extension.h>
+#include <wtf/glib/GUniquePtr.h>
+
+typedef struct _WebKitXPathNSResolver {
+ GObject parent;
+} WebKitXPathNSResolver;
+
+typedef struct _WebKitXPathNSResolverClass {
+ GObjectClass parentClass;
+} WebKitXPathNSResolverClass;
+
+static char* webkitXPathNSResolverLookupNamespaceURI(WebKitDOMXPathNSResolver* resolver, const char* prefix)
+{
+ if (!g_strcmp0(prefix, "foo"))
+ return g_strdup("http://www.example.com");
+
+ return nullptr;
+}
+
+static void webkitXPathNSResolverDOMXPathNSResolverIfaceInit(WebKitDOMXPathNSResolverIface* iface)
+{
+ iface->lookup_namespace_uri = webkitXPathNSResolverLookupNamespaceURI;
+}
+
+G_DEFINE_TYPE_WITH_CODE(WebKitXPathNSResolver, webkit_xpath_ns_resolver, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(WEBKIT_DOM_TYPE_XPATH_NS_RESOLVER, webkitXPathNSResolverDOMXPathNSResolverIfaceInit))
+
+static void webkit_xpath_ns_resolver_init(WebKitXPathNSResolver*)
+{
+}
+
+static void webkit_xpath_ns_resolver_class_init(WebKitXPathNSResolverClass*)
+{
+}
+
+class WebKitDOMXPathNSResolverTest : public WebProcessTest {
+public:
+ static std::unique_ptr<WebProcessTest> create() { return std::unique_ptr<WebProcessTest>(new WebKitDOMXPathNSResolverTest()); }
+
+private:
+ void evaluateFooChildTextAndCheckResult(WebKitDOMDocument* document, WebKitDOMXPathNSResolver* resolver)
+ {
+ WebKitDOMElement* documentElement = webkit_dom_document_get_document_element(document);
+ g_assert(WEBKIT_DOM_IS_ELEMENT(documentElement));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(documentElement));
+
+ GRefPtr<WebKitDOMXPathResult> result = adoptGRef(webkit_dom_document_evaluate(document, "foo:child/text()", WEBKIT_DOM_NODE(documentElement), resolver, WEBKIT_DOM_XPATH_RESULT_ORDERED_NODE_ITERATOR_TYPE, nullptr, nullptr));
+ g_assert(WEBKIT_DOM_IS_XPATH_RESULT(result.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(result.get()));
+
+ WebKitDOMNode* nodeResult = webkit_dom_xpath_result_iterate_next(result.get(), nullptr);
+ g_assert(WEBKIT_DOM_IS_NODE(nodeResult));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(nodeResult));
+
+ GUniquePtr<char> nodeValue(webkit_dom_node_get_node_value(nodeResult));
+ g_assert_cmpstr(nodeValue.get(), ==, "SUCCESS");
+ }
+
+ bool testXPathNSResolverNative(WebKitWebPage* page)
+ {
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(document));
+
+ GRefPtr<WebKitDOMXPathNSResolver> resolver = adoptGRef(webkit_dom_document_create_ns_resolver(document, WEBKIT_DOM_NODE(webkit_dom_document_get_document_element(document))));
+ g_assert(WEBKIT_DOM_IS_XPATH_NS_RESOLVER(resolver.get()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(resolver.get()));
+ evaluateFooChildTextAndCheckResult(document, resolver.get());
+
+ return true;
+ }
+
+ bool testXPathNSResolverCustom(WebKitWebPage* page)
+ {
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(document));
+
+ GRefPtr<WebKitDOMXPathNSResolver> resolver = adoptGRef(WEBKIT_DOM_XPATH_NS_RESOLVER(g_object_new(webkit_xpath_ns_resolver_get_type(), nullptr)));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(resolver.get()));
+ evaluateFooChildTextAndCheckResult(document, resolver.get());
+
+ return true;
+ }
+
+ bool runTest(const char* testName, WebKitWebPage* page) override
+ {
+ if (!strcmp(testName, "native"))
+ return testXPathNSResolverNative(page);
+ if (!strcmp(testName, "custom"))
+ return testXPathNSResolverCustom(page);
+
+ g_assert_not_reached();
+ return false;
+ }
+};
+
+static void __attribute__((constructor)) registerTests()
+{
+ REGISTER_TEST(WebKitDOMXPathNSResolverTest, "WebKitDOMXPathNSResolver/native");
+ REGISTER_TEST(WebKitDOMXPathNSResolverTest, "WebKitDOMXPathNSResolver/custom");
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/EditorTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/EditorTest.cpp
new file mode 100644
index 000000000..873344271
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/EditorTest.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2015 Red Hat Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebProcessTest.h"
+#include <webkit2/webkit-web-extension.h>
+
+#define WEBKIT_DOM_USE_UNSTABLE_API
+#include <webkitdom/WebKitDOMDOMSelection.h>
+#include <webkitdom/WebKitDOMDOMWindowUnstable.h>
+
+class WebKitWebEditorTest : public WebProcessTest {
+public:
+ static std::unique_ptr<WebProcessTest> create() { return std::unique_ptr<WebProcessTest>(new WebKitWebEditorTest()); }
+
+private:
+ static void selectionChangedCallback(bool* selectionChanged)
+ {
+ *selectionChanged = true;
+ }
+
+ void testSelectionSelectAll(WebKitWebPage* page)
+ {
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+
+ webkit_dom_document_exec_command(document, "SelectAll", false, "");
+ }
+
+ void testSelectionCollapse(WebKitWebPage* page)
+ {
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ GRefPtr<WebKitDOMDOMWindow> domWindow = adoptGRef(webkit_dom_document_get_default_view(document));
+ g_assert(WEBKIT_DOM_IS_DOM_WINDOW(domWindow.get()));
+ GRefPtr<WebKitDOMDOMSelection> domSelection = adoptGRef(webkit_dom_dom_window_get_selection(domWindow.get()));
+ g_assert(WEBKIT_DOM_IS_DOM_SELECTION(domSelection.get()));
+
+ webkit_dom_dom_selection_collapse_to_start(domSelection.get(), nullptr);
+ }
+
+ void testSelectionModifyMove(WebKitWebPage* page)
+ {
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ GRefPtr<WebKitDOMDOMWindow> domWindow = adoptGRef(webkit_dom_document_get_default_view(document));
+ g_assert(WEBKIT_DOM_IS_DOM_WINDOW(domWindow.get()));
+ GRefPtr<WebKitDOMDOMSelection> domSelection = adoptGRef(webkit_dom_dom_window_get_selection(domWindow.get()));
+ g_assert(WEBKIT_DOM_IS_DOM_SELECTION(domSelection.get()));
+
+ webkit_dom_dom_selection_modify(domSelection.get(), "move", "forward", "character");
+ }
+
+ void testSelectionModifyExtend(WebKitWebPage* page)
+ {
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+ GRefPtr<WebKitDOMDOMWindow> domWindow = adoptGRef(webkit_dom_document_get_default_view(document));
+ g_assert(WEBKIT_DOM_IS_DOM_WINDOW(domWindow.get()));
+ GRefPtr<WebKitDOMDOMSelection> domSelection = adoptGRef(webkit_dom_dom_window_get_selection(domWindow.get()));
+ g_assert(WEBKIT_DOM_IS_DOM_SELECTION(domSelection.get()));
+
+ webkit_dom_dom_selection_modify(domSelection.get(), "extend", "forward", "word");
+ }
+
+ void testSelectionUnselect(WebKitWebPage* page)
+ {
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(page);
+ g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
+
+ webkit_dom_document_exec_command(document, "Unselect", false, "");
+ }
+
+ bool runTest(const char* testName, WebKitWebPage* page) override
+ {
+ if (!strcmp(testName, "selection-changed")) {
+ bool selectionChanged = false;
+
+ WebKitWebEditor* editor = webkit_web_page_get_editor(page);
+ g_assert(WEBKIT_IS_WEB_EDITOR(editor));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(editor));
+ g_signal_connect_swapped(editor, "selection-changed", G_CALLBACK(selectionChangedCallback), &selectionChanged);
+
+ testSelectionSelectAll(page);
+ g_assert(selectionChanged);
+
+ selectionChanged = false;
+ testSelectionCollapse(page);
+ g_assert(selectionChanged);
+
+ selectionChanged = false;
+ testSelectionModifyMove(page);
+ g_assert(selectionChanged);
+
+ selectionChanged = false;
+ testSelectionModifyExtend(page);
+ g_assert(selectionChanged);
+
+ selectionChanged = false;
+ testSelectionUnselect(page);
+ g_assert(selectionChanged);
+
+ return true;
+ }
+
+ g_assert_not_reached();
+ return false;
+ }
+};
+
+static void __attribute__((constructor)) registerTests()
+{
+ REGISTER_TEST(WebKitWebEditorTest, "WebKitWebEditor/selection-changed");
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/FrameTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/FrameTest.cpp
index b9c86365b..a32d3e52f 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/FrameTest.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/FrameTest.cpp
@@ -32,6 +32,7 @@ private:
{
WebKitFrame* frame = webkit_web_page_get_main_frame(page);
g_assert(WEBKIT_IS_FRAME(frame));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(frame));
g_assert(webkit_frame_is_main_frame(frame));
return true;
@@ -41,6 +42,7 @@ private:
{
WebKitFrame* frame = webkit_web_page_get_main_frame(page);
g_assert(WEBKIT_IS_FRAME(frame));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(frame));
g_assert_cmpstr(webkit_web_page_get_uri(page), ==, webkit_frame_get_uri(frame));
return true;
@@ -50,6 +52,7 @@ private:
{
WebKitFrame* frame = webkit_web_page_get_main_frame(page);
g_assert(WEBKIT_IS_FRAME(frame));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(frame));
g_assert(webkit_frame_get_javascript_global_context(frame));
return true;
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAuthentication.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAuthentication.cpp
index ede422556..9cd9f5e7a 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAuthentication.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAuthentication.cpp
@@ -20,7 +20,7 @@
#include "config.h"
#include "LoadTrackingTest.h"
#include "WebKitTestServer.h"
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
static WebKitTestServer* kServer;
@@ -187,7 +187,9 @@ static void testWebViewAuthenticationNoCredential(AuthenticationTest* test, gcon
static void testWebViewAuthenticationStorage(AuthenticationTest* test, gconstpointer)
{
// Enable private browsing before authentication request to test that credentials can't be saved.
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
webkit_settings_set_enable_private_browsing(webkit_web_view_get_settings(test->m_webView), TRUE);
+ G_GNUC_END_IGNORE_DEPRECATIONS;
test->loadURI(kServer->getURIForPath("/auth-test.html").data());
WebKitAuthenticationRequest* request = test->waitForAuthenticationRequest();
g_assert(!webkit_authentication_request_get_proposed_credential(request));
@@ -195,8 +197,10 @@ static void testWebViewAuthenticationStorage(AuthenticationTest* test, gconstpoi
// If WebKit has been compiled with libsecret, and private browsing is disabled
// then check that credentials can be saved.
-#if ENABLE(CREDENTIAL_STORAGE)
+#if USE(LIBSECRET)
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
webkit_settings_set_enable_private_browsing(webkit_web_view_get_settings(test->m_webView), FALSE);
+ G_GNUC_END_IGNORE_DEPRECATIONS;
test->loadURI(kServer->getURIForPath("/auth-test.html").data());
request = test->waitForAuthenticationRequest();
g_assert(!webkit_authentication_request_get_proposed_credential(request));
@@ -232,6 +236,22 @@ static void testWebViewAuthenticationSuccess(AuthenticationTest* test, gconstpoi
g_assert_cmpstr(webkit_web_view_get_title(test->m_webView), ==, authExpectedSuccessTitle);
}
+static void testWebViewAuthenticationEmptyRealm(AuthenticationTest* test, gconstpointer)
+{
+ test->loadURI(kServer->getURIForPath("/empty-realm.html").data());
+ WebKitAuthenticationRequest* request = test->waitForAuthenticationRequest();
+ WebKitCredential* credential = webkit_credential_new(authTestUsername, authTestPassword, WEBKIT_CREDENTIAL_PERSISTENCE_FOR_SESSION);
+ webkit_authentication_request_authenticate(request, credential);
+ webkit_credential_free(credential);
+ test->waitUntilLoadFinished();
+
+ g_assert_cmpint(test->m_loadEvents.size(), ==, 3);
+ g_assert_cmpint(test->m_loadEvents[0], ==, LoadTrackingTest::ProvisionalLoadStarted);
+ g_assert_cmpint(test->m_loadEvents[1], ==, LoadTrackingTest::LoadCommitted);
+ g_assert_cmpint(test->m_loadEvents[2], ==, LoadTrackingTest::LoadFinished);
+ g_assert_cmpstr(webkit_web_view_get_title(test->m_webView), ==, authExpectedSuccessTitle);
+}
+
static void serverCallback(SoupServer*, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, void*)
{
if (message->method != SOUP_METHOD_GET) {
@@ -239,7 +259,7 @@ static void serverCallback(SoupServer*, SoupMessage* message, const char* path,
return;
}
- if (!strcmp(path, "/auth-test.html")) {
+ if (!strcmp(path, "/auth-test.html") || !strcmp(path, "/empty-realm.html")) {
const char* authorization = soup_message_headers_get_one(message->request_headers, "Authorization");
// Require authentication.
if (!g_strcmp0(authorization, authExpectedAuthorization)) {
@@ -250,7 +270,10 @@ static void serverCallback(SoupServer*, SoupMessage* message, const char* path,
} else if (++AuthenticationTest::authenticationRetries < 3) {
// No or invalid authorization header provided by the client, request authentication twice then fail.
soup_message_set_status(message, SOUP_STATUS_UNAUTHORIZED);
- soup_message_headers_append(message->response_headers, "WWW-Authenticate", "Basic realm=\"my realm\"");
+ if (!strcmp(path, "/empty-realm.html"))
+ soup_message_headers_append(message->response_headers, "WWW-Authenticate", "Basic");
+ else
+ soup_message_headers_append(message->response_headers, "WWW-Authenticate", "Basic realm=\"my realm\"");
// Include a failure message in case the user attempts to proceed without authentication.
soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, authFailureHTMLString, strlen(authFailureHTMLString));
} else {
@@ -272,12 +295,11 @@ void beforeAll()
AuthenticationTest::add("WebKitWebView", "authentication-request", testWebViewAuthenticationRequest);
AuthenticationTest::add("WebKitWebView", "authentication-cancel", testWebViewAuthenticationCancel);
AuthenticationTest::add("WebKitWebView", "authentication-load-cancelled", testWebViewAuthenticationLoadCancelled);
+ AuthenticationTest::add("WebKitWebView", "authentication-success", testWebViewAuthenticationSuccess);
AuthenticationTest::add("WebKitWebView", "authentication-failure", testWebViewAuthenticationFailure);
AuthenticationTest::add("WebKitWebView", "authentication-no-credential", testWebViewAuthenticationNoCredential);
AuthenticationTest::add("WebKitWebView", "authentication-storage", testWebViewAuthenticationStorage);
- // Testing authentication success must be done last because libsoup will never fire
- // the authenticate signal again once authentication is successful.
- AuthenticationTest::add("WebKitWebView", "authentication-success", testWebViewAuthenticationSuccess);
+ AuthenticationTest::add("WebKitWebView", "authentication-empty-realm", testWebViewAuthenticationEmptyRealm);
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAutocleanups.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAutocleanups.cpp
new file mode 100644
index 000000000..975688ced
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAutocleanups.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2015 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebViewTest.h"
+#include <webkit2/webkit2.h>
+
+#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC
+
+static void testUIProcessAutocleanups(WebViewTest* test, gconstpointer)
+{
+ // Sanity-check a couple UI process API autocleanups that are easy to test....
+ g_autoptr(WebKitWebContext) context = webkit_web_context_new();
+ g_assert(WEBKIT_IS_WEB_CONTEXT(context));
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(context));
+
+ g_autoptr(WebKitWebsiteDataManager) manager = webkit_website_data_manager_new(nullptr);
+ g_assert(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager));
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(context));
+
+ g_autoptr(WebKitUserScript) userScript = webkit_user_script_new("",
+ WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START,
+ nullptr, nullptr);
+ g_assert(userScript);
+ // Not a GObject, so just checking that this doesn't crash....
+}
+
+static void testWebProcessAutocleanups(WebViewTest* test, gconstpointer)
+{
+ static const char* testHTML = "<html><body></body></html>";
+ test->loadHtml(testHTML, nullptr);
+ test->waitUntilLoadFinished();
+
+ g_assert(test->runWebProcessTest("Autocleanups", "web-process-autocleanups"));
+}
+
+void beforeAll()
+{
+ WebViewTest::add("Autocleanups", "ui-process-autocleanups", testUIProcessAutocleanups);
+ WebViewTest::add("Autocleanups", "web-process-autocleanups", testWebProcessAutocleanups);
+}
+
+#else
+
+void beforeAll()
+{
+}
+
+#endif // G_DEFINE_AUTOPTR_CLEANUP_FUNC
+
+void afterAll()
+{
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestBackForwardList.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestBackForwardList.cpp
index 65c3d2d7c..fd2fbf5f2 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestBackForwardList.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestBackForwardList.cpp
@@ -264,6 +264,140 @@ static void testBackForwardListLimitAndCache(BackForwardListTest* test, gconstpo
g_assert_cmpuint(webkit_back_forward_list_get_length(test->m_list), ==, kBackForwardListLimit);
}
+static void testWebKitWebViewSessionState(BackForwardListTest* test, gconstpointer)
+{
+ WebKitWebViewSessionState* state = webkit_web_view_get_session_state(test->m_webView);
+ g_assert(state);
+ GRefPtr<WebKitWebView> view = WEBKIT_WEB_VIEW(webkit_web_view_new());
+ WebKitBackForwardList* bfList = webkit_web_view_get_back_forward_list(view.get());
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 0);
+ webkit_web_view_restore_session_state(view.get(), state);
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 0);
+ GRefPtr<GBytes> data = adoptGRef(webkit_web_view_session_state_serialize(state));
+ g_assert(data);
+ state = webkit_web_view_session_state_new(data.get());
+ g_assert(state);
+ view = WEBKIT_WEB_VIEW(webkit_web_view_new());
+ bfList = webkit_web_view_get_back_forward_list(view.get());
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 0);
+ webkit_web_view_restore_session_state(view.get(), state);
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 0);
+ webkit_web_view_session_state_unref(state);
+
+ CString uriPage1 = kServer->getURIForPath("/Page1");
+ test->m_changedFlags = BackForwardListTest::CurrentItem | BackForwardListTest::AddedItem;
+ test->loadURI(uriPage1.data());
+ test->waitUntilLoadFinished();
+
+ CString uriPage2 = kServer->getURIForPath("/Page2");
+ test->m_changedFlags = BackForwardListTest::CurrentItem | BackForwardListTest::AddedItem;
+ test->loadURI(uriPage2.data());
+ test->waitUntilLoadFinished();
+
+ CString uriPage3 = kServer->getURIForPath("/Page3");
+ test->m_changedFlags = BackForwardListTest::CurrentItem | BackForwardListTest::AddedItem;
+ test->loadURI(uriPage3.data());
+ test->waitUntilLoadFinished();
+
+ test->m_changedFlags = BackForwardListTest::CurrentItem;
+ test->goBack();
+ test->waitUntilLoadFinished();
+
+ state = webkit_web_view_get_session_state(test->m_webView);
+ g_assert(state);
+
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 0);
+ webkit_web_view_restore_session_state(view.get(), state);
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 3);
+
+ BackForwardListTest::checkItem(webkit_back_forward_list_get_nth_item(bfList, -1), "Page1", uriPage1.data(), uriPage1.data());
+ BackForwardListTest::checkItem(webkit_back_forward_list_get_current_item(bfList), "Page2", uriPage2.data(), uriPage2.data());
+ BackForwardListTest::checkItem(webkit_back_forward_list_get_nth_item(bfList, 1), "Page3", uriPage3.data(), uriPage3.data());
+
+ data = adoptGRef(webkit_web_view_session_state_serialize(state));
+ g_assert(data);
+ webkit_web_view_session_state_unref(state);
+ state = webkit_web_view_session_state_new(data.get());
+ g_assert(state);
+
+ view = WEBKIT_WEB_VIEW(webkit_web_view_new());
+ bfList = webkit_web_view_get_back_forward_list(view.get());
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 0);
+ webkit_web_view_restore_session_state(view.get(), state);
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 3);
+ webkit_web_view_session_state_unref(state);
+
+ BackForwardListTest::checkItem(webkit_back_forward_list_get_nth_item(bfList, -1), "Page1", uriPage1.data(), uriPage1.data());
+ BackForwardListTest::checkItem(webkit_back_forward_list_get_current_item(bfList), "Page2", uriPage2.data(), uriPage2.data());
+ BackForwardListTest::checkItem(webkit_back_forward_list_get_nth_item(bfList, 1), "Page3", uriPage3.data(), uriPage3.data());
+
+ static const char* invalidSessionData = "invalid session data";
+ data = adoptGRef(g_bytes_new_static(invalidSessionData, strlen(invalidSessionData)));
+ g_assert(!webkit_web_view_session_state_new(data.get()));
+}
+
+static void testWebKitWebViewSessionStateWithFormData(BackForwardListTest* test, gconstpointer)
+{
+ GUniquePtr<char> htmlPath(g_build_filename(Test::getResourcesDir(Test::WebKit2Resources).data(), "simple-form.html", nullptr));
+ GUniquePtr<char> htmlURL(g_filename_to_uri(htmlPath.get(), nullptr, nullptr));
+ test->m_changedFlags = BackForwardListTest::CurrentItem | BackForwardListTest::AddedItem;
+ test->loadURI(htmlURL.get());
+ test->waitUntilLoadFinished();
+
+ webkit_web_view_run_javascript(test->m_webView, "submitForm();", nullptr, nullptr, nullptr);
+ test->waitUntilLoadFinished();
+
+ WebKitWebViewSessionState* state = webkit_web_view_get_session_state(test->m_webView);
+ g_assert(state);
+ GRefPtr<WebKitWebView> view = WEBKIT_WEB_VIEW(webkit_web_view_new());
+ WebKitBackForwardList* bfList = webkit_web_view_get_back_forward_list(view.get());
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 0);
+ webkit_web_view_restore_session_state(view.get(), state);
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 2);
+ GRefPtr<GBytes> data = adoptGRef(webkit_web_view_session_state_serialize(state));
+ g_assert(data);
+ state = webkit_web_view_session_state_new(data.get());
+ g_assert(state);
+ view = WEBKIT_WEB_VIEW(webkit_web_view_new());
+ bfList = webkit_web_view_get_back_forward_list(view.get());
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 0);
+ webkit_web_view_restore_session_state(view.get(), state);
+ g_assert_cmpuint(webkit_back_forward_list_get_length(bfList), ==, 2);
+ webkit_web_view_session_state_unref(state);
+}
+
+static void viewLoadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent, GMainLoop* mainLoop)
+{
+ if (loadEvent == WEBKIT_LOAD_FINISHED)
+ g_main_loop_quit(mainLoop);
+}
+
+static void testWebKitWebViewNavigationAfterSessionRestore(BackForwardListTest* test, gconstpointer)
+{
+ // This test checks that a normal load after a session restore with a BackForard list having
+ // forward items doesn't produce any runtime critical warning. See https://bugs.webkit.org/show_bug.cgi?id=153233.
+ GRefPtr<WebKitWebView> view = WEBKIT_WEB_VIEW(webkit_web_view_new());
+ g_signal_connect(view.get(), "load-changed", G_CALLBACK(viewLoadChanged), test->m_mainLoop);
+
+ webkit_web_view_load_uri(view.get(), kServer->getURIForPath("/Page1").data());
+ g_main_loop_run(test->m_mainLoop);
+ webkit_web_view_load_uri(view.get(), kServer->getURIForPath("/Page2").data());
+ g_main_loop_run(test->m_mainLoop);
+ webkit_web_view_load_uri(view.get(), kServer->getURIForPath("/Page3").data());
+ g_main_loop_run(test->m_mainLoop);
+ webkit_web_view_go_back(view.get());
+ g_main_loop_run(test->m_mainLoop);
+
+ WebKitWebViewSessionState* state = webkit_web_view_get_session_state(view.get());
+ webkit_web_view_restore_session_state(test->m_webView, state);
+ webkit_web_view_session_state_unref(state);
+
+ // A normal load after a session restore should remove the forward list, add the new item and update the current one.
+ test->m_changedFlags = BackForwardListTest::CurrentItem | BackForwardListTest::AddedItem | BackForwardListTest::RemovedItems;
+ test->loadURI(kServer->getURIForPath("/Page4").data());
+ test->waitUntilLoadFinished();
+}
+
void beforeAll()
{
kServer = new WebKitTestServer();
@@ -271,6 +405,9 @@ void beforeAll()
BackForwardListTest::add("BackForwardList", "navigation", testBackForwardListNavigation);
BackForwardListTest::add("BackForwardList", "list-limit-and-cache", testBackForwardListLimitAndCache);
+ BackForwardListTest::add("WebKitWebView", "session-state", testWebKitWebViewSessionState);
+ BackForwardListTest::add("WebKitWebView", "session-state-with-form-data", testWebKitWebViewSessionStateWithFormData);
+ BackForwardListTest::add("WebKitWebView", "navigation-after-session-restore", testWebKitWebViewNavigationAfterSessionRestore);
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestConsoleMessage.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestConsoleMessage.cpp
new file mode 100644
index 000000000..2595a8a42
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestConsoleMessage.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2015 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2,1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebViewTest.h"
+#include <gtk/gtk.h>
+#include <webkit2/webkit2.h>
+
+class ConsoleMessageTest : public WebViewTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(ConsoleMessageTest);
+
+ // This should be keep in sync with the public enums in WebKitConsoleMessage.h.
+ enum class MessageSource { JavaScript, Network, ConsoleAPI, Security, Other };
+ enum class MessageLevel { Info, Log, Warning, Error, Debug };
+ struct ConsoleMessage {
+ bool operator==(const ConsoleMessage& other)
+ {
+ return source == other.source
+ && level == other.level
+ && message == other.message
+ && lineNumber == other.lineNumber
+ && sourceID == other.sourceID;
+ }
+
+ MessageSource source;
+ MessageLevel level;
+ CString message;
+ unsigned lineNumber;
+ CString sourceID;
+ };
+
+ static void consoleMessageReceivedCallback(WebKitUserContentManager*, WebKitJavascriptResult* message, ConsoleMessageTest* test)
+ {
+ g_assert(message);
+ GUniquePtr<char> messageString(WebViewTest::javascriptResultToCString(message));
+ GRefPtr<GVariant> variant = g_variant_parse(G_VARIANT_TYPE("(uusus)"), messageString.get(), nullptr, nullptr, nullptr);
+ g_assert(variant.get());
+
+ unsigned source, level, lineNumber;
+ const char* messageText;
+ const char* sourceID;
+ g_variant_get(variant.get(), "(uu&su&s)", &source, &level, &messageText, &lineNumber, &sourceID);
+ test->m_consoleMessage = { static_cast<ConsoleMessageTest::MessageSource>(source), static_cast<ConsoleMessageTest::MessageLevel>(level), messageText, lineNumber, sourceID };
+
+ g_main_loop_quit(test->m_mainLoop);
+ }
+
+ ConsoleMessageTest()
+ {
+ webkit_user_content_manager_register_script_message_handler(m_userContentManager.get(), "console");
+ g_signal_connect(m_userContentManager.get(), "script-message-received::console", G_CALLBACK(consoleMessageReceivedCallback), this);
+ }
+
+ ~ConsoleMessageTest()
+ {
+ g_signal_handlers_disconnect_matched(m_userContentManager.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this);
+ webkit_user_content_manager_unregister_script_message_handler(m_userContentManager.get(), "console");
+ }
+
+ void waitUntilConsoleMessageReceived()
+ {
+ g_main_loop_run(m_mainLoop);
+ }
+
+ ConsoleMessage m_consoleMessage;
+};
+
+static void testWebKitConsoleMessageConsoleAPI(ConsoleMessageTest* test, gconstpointer)
+{
+ ConsoleMessageTest::ConsoleMessage referenceMessage = { ConsoleMessageTest::MessageSource::ConsoleAPI, ConsoleMessageTest::MessageLevel::Log, "Log Console Message", 1, "http://foo.com/bar" };
+ test->loadHtml("<html><body onload='console.log(\"Log Console Message\");'></body></html>", "http://foo.com/bar");
+ test->waitUntilConsoleMessageReceived();
+ g_assert(test->m_consoleMessage == referenceMessage);
+
+ referenceMessage.level = ConsoleMessageTest::MessageLevel::Info;
+ referenceMessage.message = "Info Console Message";
+ test->loadHtml("<html><body onload='console.info(\"Info Console Message\");'></body></html>", "http://foo.com/bar");
+ test->waitUntilConsoleMessageReceived();
+ g_assert(test->m_consoleMessage == referenceMessage);
+
+ referenceMessage.level = ConsoleMessageTest::MessageLevel::Warning;
+ referenceMessage.message = "Warning Console Message";
+ test->loadHtml("<html><body onload='console.warn(\"Warning Console Message\");'></body></html>", "http://foo.com/bar");
+ test->waitUntilConsoleMessageReceived();
+ g_assert(test->m_consoleMessage == referenceMessage);
+
+ referenceMessage.level = ConsoleMessageTest::MessageLevel::Error;
+ referenceMessage.message = "Error Console Message";
+ test->loadHtml("<html><body onload='console.error(\"Error Console Message\");'></body></html>", "http://foo.com/bar");
+ test->waitUntilConsoleMessageReceived();
+ g_assert(test->m_consoleMessage == referenceMessage);
+
+ referenceMessage.level = ConsoleMessageTest::MessageLevel::Debug;
+ referenceMessage.message = "Debug Console Message";
+ test->loadHtml("<html><body onload='console.debug(\"Debug Console Message\");'></body></html>", "http://foo.com/bar");
+ test->waitUntilConsoleMessageReceived();
+ g_assert(test->m_consoleMessage == referenceMessage);
+}
+
+static void testWebKitConsoleMessageJavaScriptException(ConsoleMessageTest* test, gconstpointer)
+{
+ ConsoleMessageTest::ConsoleMessage referenceMessage = { ConsoleMessageTest::MessageSource::JavaScript, ConsoleMessageTest::MessageLevel::Error,
+ "ReferenceError: Can't find variable: foo", 1, "http://foo.com/bar" };
+ test->loadHtml("<html><body onload='foo()'></body></html>", "http://foo.com/bar");
+ test->waitUntilConsoleMessageReceived();
+ g_assert(test->m_consoleMessage == referenceMessage);
+}
+
+static void testWebKitConsoleMessageNetworkError(ConsoleMessageTest* test, gconstpointer)
+{
+ ConsoleMessageTest::ConsoleMessage referenceMessage = { ConsoleMessageTest::MessageSource::Network, ConsoleMessageTest::MessageLevel::Error,
+ "Failed to load resource: The resource at '/org/webkit/webkit2gtk/tests/not-found.css' does not exist", 0, "resource:///org/webkit/webkit2gtk/tests/not-found.css" };
+ test->loadHtml("<html><head><link rel='stylesheet' href='not-found.css' type='text/css'></head><body></body></html>", "resource:///org/webkit/webkit2gtk/tests/");
+ test->waitUntilConsoleMessageReceived();
+ g_assert(test->m_consoleMessage == referenceMessage);
+}
+
+static void testWebKitConsoleMessageSecurityError(ConsoleMessageTest* test, gconstpointer)
+{
+ ConsoleMessageTest::ConsoleMessage referenceMessage = { ConsoleMessageTest::MessageSource::Security, ConsoleMessageTest::MessageLevel::Error,
+ "Not allowed to load local resource: file:///foo/bar/source.png", 1, "http://foo.com/bar" };
+ test->loadHtml("<html><body><img src=\"file:///foo/bar/source.png\"/></body></html>", "http://foo.com/bar");
+ test->waitUntilConsoleMessageReceived();
+ g_assert(test->m_consoleMessage == referenceMessage);
+}
+
+void beforeAll()
+{
+ ConsoleMessageTest::add("WebKitConsoleMessage", "console-api", testWebKitConsoleMessageConsoleAPI);
+ ConsoleMessageTest::add("WebKitConsoleMessage", "js-exception", testWebKitConsoleMessageJavaScriptException);
+ ConsoleMessageTest::add("WebKitConsoleMessage", "network-error", testWebKitConsoleMessageNetworkError);
+ ConsoleMessageTest::add("WebKitConsoleMessage", "security-error", testWebKitConsoleMessageSecurityError);
+}
+
+void afterAll()
+{
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp
index a91e78741..3d7ab00cc 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestContextMenu.cpp
@@ -19,7 +19,8 @@
#include "config.h"
#include "WebViewTest.h"
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/glib/GRefPtr.h>
class ContextMenuTest: public WebViewTest {
public:
@@ -32,10 +33,24 @@ public:
void checkContextMenuEvent(GdkEvent* event)
{
g_assert(event);
- g_assert_cmpint(event->type, ==, GDK_BUTTON_PRESS);
- g_assert_cmpint(event->button.button, ==, 3);
- g_assert_cmpint(event->button.x, ==, m_menuPositionX);
- g_assert_cmpint(event->button.y, ==, m_menuPositionY);
+ g_assert_cmpint(event->type, ==, m_expectedEventType);
+
+ switch (m_expectedEventType) {
+ case GDK_BUTTON_PRESS:
+ g_assert_cmpint(event->button.button, ==, 3);
+ g_assert_cmpint(event->button.x, ==, m_menuPositionX);
+ g_assert_cmpint(event->button.y, ==, m_menuPositionY);
+ break;
+ case GDK_KEY_PRESS:
+ g_assert_cmpint(event->key.keyval, ==, GDK_KEY_Menu);
+ break;
+ case GDK_NOTHING:
+ // GDK_NOTHING means that the context menu was triggered by the
+ // popup-menu signal. We don't have anything to check here.
+ break;
+ default:
+ g_assert_not_reached();
+ }
}
static gboolean contextMenuCallback(WebKitWebView* webView, WebKitContextMenu* contextMenu, GdkEvent* event, WebKitHitTestResult* hitTestResult, ContextMenuTest* test)
@@ -57,6 +72,7 @@ public:
ContextMenuTest()
: m_menuPositionX(0)
, m_menuPositionY(0)
+ , m_expectedEventType(GDK_BUTTON_PRESS)
{
g_signal_connect(m_webView, "context-menu", G_CALLBACK(contextMenuCallback), this);
g_signal_connect(m_webView, "context-menu-dismissed", G_CALLBACK(contextMenuDismissedCallback), this);
@@ -92,17 +108,6 @@ public:
return 0;
}
- bool shouldShowInputMethodsMenu()
- {
- GtkSettings* settings = gtk_widget_get_settings(GTK_WIDGET(m_webView));
- if (!settings)
- return true;
-
- gboolean showInputMethodMenu;
- g_object_get(settings, "gtk-show-input-method-menu", &showInputMethodMenu, NULL);
- return showInputMethodMenu;
- }
-
void checkActionState(GtkAction* action, unsigned state)
{
if (state & Visible)
@@ -209,6 +214,7 @@ public:
void showContextMenuAndWaitUntilFinished()
{
+ m_expectedEventType = GDK_BUTTON_PRESS;
showContextMenuAtPositionAndWaitUntilFinished(0, 0);
}
@@ -224,8 +230,35 @@ public:
g_main_loop_run(m_mainLoop);
}
+ static gboolean emitPopupMenuSignalIdleCallback(ContextMenuTest* test)
+ {
+ test->emitPopupMenuSignal();
+ return FALSE;
+ }
+
+ void showContextMenuTriggeredByPopupEventAndWaitUntilFinished()
+ {
+ m_expectedEventType = GDK_NOTHING;
+ g_idle_add(reinterpret_cast<GSourceFunc>(emitPopupMenuSignalIdleCallback), this);
+ g_main_loop_run(m_mainLoop);
+ }
+
+ static gboolean simulateMenuKeyIdleCallback(ContextMenuTest* test)
+ {
+ test->keyStroke(GDK_KEY_Menu);
+ return FALSE;
+ }
+
+ void showContextMenuTriggeredByContextMenuKeyAndWaitUntilFinished()
+ {
+ m_expectedEventType = GDK_KEY_PRESS;
+ g_idle_add(reinterpret_cast<GSourceFunc>(simulateMenuKeyIdleCallback), this);
+ g_main_loop_run(m_mainLoop);
+ }
+
double m_menuPositionX;
double m_menuPositionY;
+ GdkEventType m_expectedEventType;
};
class ContextMenuDefaultTest: public ContextMenuTest {
@@ -239,7 +272,8 @@ public:
LinkImage,
Video,
Audio,
- Editable
+ Editable,
+ Selection
};
ContextMenuDefaultTest()
@@ -257,6 +291,7 @@ public:
g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_GO_BACK, Visible);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD, Visible);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_STOP, Visible);
@@ -267,6 +302,7 @@ public:
g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK, Visible | Enabled);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW, Visible | Enabled);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK, Visible | Enabled);
@@ -277,6 +313,7 @@ public:
g_assert(webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_IMAGE_IN_NEW_WINDOW, Visible | Enabled);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_IMAGE_TO_DISK, Visible | Enabled);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_TO_CLIPBOARD, Visible | Enabled);
@@ -287,6 +324,7 @@ public:
g_assert(webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK, Visible | Enabled);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW, Visible | Enabled);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK, Visible | Enabled);
@@ -302,6 +340,7 @@ public:
g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_MEDIA_PLAY, Visible | Enabled);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_MEDIA_MUTE, Visible);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_CONTROLS, Visible | Enabled | Checked);
@@ -317,6 +356,7 @@ public:
g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_MEDIA_PLAY, Visible | Enabled);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_MEDIA_MUTE, Visible);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_TOGGLE_MEDIA_CONTROLS, Visible | Enabled | Checked);
@@ -332,6 +372,7 @@ public:
g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_CUT, Visible);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY, Visible);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_PASTE, Visible | Enabled);
@@ -339,10 +380,16 @@ public:
iter = checkCurrentItemIsSeparatorAndGetNext(iter);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_SELECT_ALL, Visible | Enabled);
iter = checkCurrentItemIsSeparatorAndGetNext(iter);
- if (shouldShowInputMethodsMenu())
- iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_INPUT_METHODS, Visible | Enabled);
iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_UNICODE, Visible | Enabled);
break;
+ case Selection:
+ g_assert(!webkit_hit_test_result_context_is_link(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(webkit_hit_test_result_context_is_selection(hitTestResult));
+ iter = checkCurrentItemIsStockActionAndGetNext(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY, Visible | Enabled);
+ break;
default:
g_assert_not_reached();
}
@@ -361,21 +408,39 @@ public:
DefaultMenuType m_expectedMenuType;
};
-static void testContextMenuDefaultMenu(ContextMenuDefaultTest* test, gconstpointer)
+static void prepareContextMenuTestView(ContextMenuDefaultTest* test)
{
- test->showInWindowAndWaitUntilMapped();
-
+ GUniquePtr<char> baseDir(g_strdup_printf("file://%s/", Test::getResourcesDir().data()));
const char* linksHTML =
"<html><body>"
" <a style='position:absolute; left:1; top:1' href='http://www.webkitgtk.org' title='WebKitGTK+ Title'>WebKitGTK+ Website</a>"
- " <img style='position:absolute; left:1; top:10' src='0xdeadbeef' width=5 height=5></img>"
- " <a style='position:absolute; left:1; top:20' href='http://www.webkitgtk.org/logo' title='WebKitGTK+ Logo'><img src='0xdeadbeef' width=5 height=5></img></a>"
+ " <img style='position:absolute; left:1; top:10' src='blank.ico' width=5 height=5></img>"
+ " <a style='position:absolute; left:1; top:20' href='http://www.webkitgtk.org/logo' title='WebKitGTK+ Logo'><img src='blank.ico' width=5 height=5></img></a>"
" <input style='position:absolute; left:1; top:30' size='10'></input>"
- " <video style='position:absolute; left:1; top:50' width='300' height='300' controls='controls' preload='none'><source src='movie.ogg' type='video/ogg' /></video>"
- " <audio style='position:absolute; left:1; top:60' width='50' height='20' controls='controls' preload='none'><source src='track.mp3' type='audio/mp3' /></audio>"
+ " <video style='position:absolute; left:1; top:50' width='300' height='300' controls='controls' preload='none'><source src='silence.mpg' type='video/mpeg' /></video>"
+ " <audio style='position:absolute; left:1; top:60' width='50' height='20' controls='controls' preload='none'><source src='track.ogg' type='audio/ogg' /></audio>"
+ " <p style='position:absolute; left:1; top:90' id='text_to_select'>Lorem ipsum.</p>"
+ " <script>"
+ " window.getSelection().removeAllRanges();"
+ " var select_range = document.createRange();"
+ " select_range.selectNodeContents(document.getElementById('text_to_select'));"
+ " window.getSelection().addRange(select_range);"
+ " </script>"
"</body></html>";
- test->loadHtml(linksHTML, "file:///");
+ test->loadHtml(linksHTML, baseDir.get());
test->waitUntilLoadFinished();
+}
+
+static void testContextMenuDefaultMenu(ContextMenuDefaultTest* test, gconstpointer)
+{
+ test->showInWindowAndWaitUntilMapped();
+
+ prepareContextMenuTestView(test);
+
+ // Context menu for selection.
+ // This test should always be the first because any other click removes the selection.
+ test->m_expectedMenuType = ContextMenuDefaultTest::Selection;
+ test->showContextMenuAtPositionAndWaitUntilFinished(2, 115);
// Context menu for document.
test->m_expectedMenuType = ContextMenuDefaultTest::Navigation;
@@ -410,6 +475,26 @@ static void testContextMenuDefaultMenu(ContextMenuDefaultTest* test, gconstpoint
test->showContextMenuAtPositionAndWaitUntilFinished(5, 35);
}
+static void testPopupEventSignal(ContextMenuDefaultTest* test, gconstpointer)
+{
+ test->showInWindowAndWaitUntilMapped();
+
+ prepareContextMenuTestView(test);
+
+ test->m_expectedMenuType = ContextMenuDefaultTest::Selection;
+ test->showContextMenuTriggeredByPopupEventAndWaitUntilFinished();
+}
+
+static void testContextMenuKey(ContextMenuDefaultTest* test, gconstpointer)
+{
+ test->showInWindowAndWaitUntilMapped();
+
+ prepareContextMenuTestView(test);
+
+ test->m_expectedMenuType = ContextMenuDefaultTest::Selection;
+ test->showContextMenuTriggeredByContextMenuKeyAndWaitUntilFinished();
+}
+
class ContextMenuCustomTest: public ContextMenuTest {
public:
MAKE_GLIB_TEST_FIXTURE(ContextMenuCustomTest);
@@ -742,124 +827,173 @@ static void testContextMenuDismissed(ContextMenuDismissedTest* test, gconstpoint
g_assert(test->m_dismissed);
}
-class ContextMenuSmartSeparatorsTest: public ContextMenuTest {
+class ContextMenuWebExtensionTest: public ContextMenuTest {
public:
- MAKE_GLIB_TEST_FIXTURE(ContextMenuSmartSeparatorsTest);
+ MAKE_GLIB_TEST_FIXTURE(ContextMenuWebExtensionTest);
- bool contextMenu(WebKitContextMenu* contextMenu, GdkEvent*, WebKitHitTestResult*)
+ void deserializeContextMenuFromUserData(GVariant* userData)
{
- webkit_context_menu_remove_all(contextMenu);
+ m_actions.clear();
+ if (!userData)
+ return;
- webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_separator());
- webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_separator());
- webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_from_stock_action(WEBKIT_CONTEXT_MENU_ACTION_GO_BACK));
- webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_from_stock_action(WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD));
- webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_separator());
- webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_separator());
- webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_from_stock_action(WEBKIT_CONTEXT_MENU_ACTION_COPY));
- webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_separator());
- webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_from_stock_action(WEBKIT_CONTEXT_MENU_ACTION_INSPECT_ELEMENT));
- webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_separator());
- webkit_context_menu_append(contextMenu, webkit_context_menu_item_new_separator());
+ GVariantIter iter;
+ g_variant_iter_init(&iter, userData);
+ m_actions.reserveInitialCapacity(g_variant_iter_n_children(&iter));
+
+ uint32_t item;
+ while (g_variant_iter_next(&iter, "u", &item))
+ m_actions.uncheckedAppend(static_cast<WebKitContextMenuAction>(item));
+ }
+
+ bool contextMenu(WebKitContextMenu* menu, GdkEvent*, WebKitHitTestResult*)
+ {
+ deserializeContextMenuFromUserData(webkit_context_menu_get_user_data(menu));
+ GList* items = webkit_context_menu_get_items(menu);
+ g_assert_cmpuint(g_list_length(items), ==, m_actions.size());
+
+ unsigned actionIndex = 0;
+ for (GList* it = items; it; it = g_list_next(it)) {
+ WebKitContextMenuItem* item = WEBKIT_CONTEXT_MENU_ITEM(it->data);
+ g_assert_cmpuint(webkit_context_menu_item_get_stock_action(item), ==, m_actions[actionIndex++]);
+ }
quitMainLoop();
- return false;
+ return true;
+ }
+
+ Vector<WebKitContextMenuAction> m_actions;
+};
+
+static void testContextMenuWebExtensionMenu(ContextMenuWebExtensionTest* test, gconstpointer)
+{
+ test->showInWindowAndWaitUntilMapped();
+ test->loadHtml("<html><body>WebKitGTK+ Context menu tests<br>"
+ "<a style='position:absolute; left:1; top:10' href='http://www.webkitgtk.org'>WebKitGTK+ Website</a></body></html>",
+ "ContextMenuTestDefault");
+ test->waitUntilLoadFinished();
+
+ // Default context menu.
+ test->showContextMenuAtPositionAndWaitUntilFinished(1, 1);
+ g_assert_cmpuint(test->m_actions.size(), ==, 4);
+ g_assert_cmpuint(test->m_actions[0], ==, WEBKIT_CONTEXT_MENU_ACTION_GO_BACK);
+ g_assert_cmpuint(test->m_actions[1], ==, WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD);
+ g_assert_cmpuint(test->m_actions[2], ==, WEBKIT_CONTEXT_MENU_ACTION_STOP);
+ g_assert_cmpuint(test->m_actions[3], ==, WEBKIT_CONTEXT_MENU_ACTION_RELOAD);
+
+ // Link menu.
+ test->showContextMenuAtPositionAndWaitUntilFinished(1, 11);
+ g_assert_cmpuint(test->m_actions.size(), ==, 4);
+ g_assert_cmpuint(test->m_actions[0], ==, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK);
+ g_assert_cmpuint(test->m_actions[1], ==, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW);
+ g_assert_cmpuint(test->m_actions[2], ==, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK);
+ g_assert_cmpuint(test->m_actions[3], ==, WEBKIT_CONTEXT_MENU_ACTION_COPY_LINK_TO_CLIPBOARD);
+
+ // Custom menu.
+ test->loadHtml("<html><body></body></html>", "ContextMenuTestCustom");
+ test->showContextMenuAndWaitUntilFinished();
+ g_assert_cmpuint(test->m_actions.size(), ==, 4);
+ g_assert_cmpuint(test->m_actions[0], ==, WEBKIT_CONTEXT_MENU_ACTION_STOP);
+ g_assert_cmpuint(test->m_actions[1], ==, WEBKIT_CONTEXT_MENU_ACTION_RELOAD);
+ g_assert_cmpuint(test->m_actions[2], ==, WEBKIT_CONTEXT_MENU_ACTION_NO_ACTION);
+ g_assert_cmpuint(test->m_actions[3], ==, WEBKIT_CONTEXT_MENU_ACTION_INSPECT_ELEMENT);
+
+ // Menu cleared by the web process.
+ test->loadHtml("<html><body></body></html>", "ContextMenuTestClear");
+ test->showContextMenuAndWaitUntilFinished();
+ g_assert_cmpuint(test->m_actions.size(), ==, 0);
+}
+
+class ContextMenuWebExtensionNodeTest: public ContextMenuTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(ContextMenuWebExtensionNodeTest);
+
+ struct Node {
+ enum {
+ NodeUnknown = 0,
+ NodeElement = 1,
+ NodeText = 3
+ };
+ typedef unsigned Type;
+
+ CString name;
+ Type type;
+ CString contents;
+ CString parentName;
+ };
+
+ void deserializeNodeFromUserData(GVariant* userData)
+ {
+ GVariantIter iter;
+ g_variant_iter_init(&iter, userData);
+
+ const char* key;
+ GVariant* value;
+ while (g_variant_iter_next(&iter, "{&sv}", &key, &value)) {
+ if (!strcmp(key, "Name") && g_variant_classify(value) == G_VARIANT_CLASS_STRING)
+ m_node.name = g_variant_get_string(value, nullptr);
+ else if (!strcmp(key, "Type") && g_variant_classify(value) == G_VARIANT_CLASS_UINT32)
+ m_node.type = g_variant_get_uint32(value);
+ else if (!strcmp(key, "Contents") && g_variant_classify(value) == G_VARIANT_CLASS_STRING)
+ m_node.contents = g_variant_get_string(value, nullptr);
+ else if (!strcmp(key, "Parent") && g_variant_classify(value) == G_VARIANT_CLASS_STRING)
+ m_node.parentName = g_variant_get_string(value, nullptr);
+ g_variant_unref(value);
+ }
}
- GtkMenu* showContextMenuAndGetGtkMenu()
+ bool contextMenu(WebKitContextMenu* menu, GdkEvent*, WebKitHitTestResult*)
{
- showContextMenuAndWaitUntilFinished();
- return getPopupMenu();
+ deserializeNodeFromUserData(webkit_context_menu_get_user_data(menu));
+ quitMainLoop();
+
+ return true;
}
+
+ Node m_node;
};
-static void testContextMenuSmartSeparators(ContextMenuSmartSeparatorsTest* test, gconstpointer)
+static void testContextMenuWebExtensionNode(ContextMenuWebExtensionNodeTest* test, gconstpointer)
{
test->showInWindowAndWaitUntilMapped();
-
- test->loadHtml("<html><body>WebKitGTK+ Context menu tests</body></html>", "file:///");
+ test->loadHtml("<html><body><p style='position:absolute; left:1; top:1'>WebKitGTK+ Context menu tests</p><br>"
+ "<a style='position:absolute; left:1; top:100' href='http://www.webkitgtk.org'>WebKitGTK+ Website</a></body></html>",
+ "ContextMenuTestNode");
test->waitUntilLoadFinished();
- GtkMenu* menu = test->showContextMenuAndGetGtkMenu();
- g_assert(menu);
-
- // Leading and trailing separators are not added to the context menu.
- GUniquePtr<GList> menuItems(gtk_container_get_children(GTK_CONTAINER(menu)));
- g_assert_cmpuint(g_list_length(menuItems.get()), ==, 6);
- GtkWidget* item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 0));
- g_assert(!GTK_IS_SEPARATOR_MENU_ITEM(item) && gtk_widget_get_visible(item));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 1));
- g_assert(!GTK_IS_SEPARATOR_MENU_ITEM(item) && gtk_widget_get_visible(item));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 2));
- g_assert(GTK_IS_SEPARATOR_MENU_ITEM(item) && gtk_widget_get_visible(item));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 3));
- g_assert(!GTK_IS_SEPARATOR_MENU_ITEM(item) && gtk_widget_get_visible(item));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 4));
- g_assert(GTK_IS_SEPARATOR_MENU_ITEM(item) && gtk_widget_get_visible(item));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 5));
- g_assert(!GTK_IS_SEPARATOR_MENU_ITEM(item) && gtk_widget_get_visible(item));
-
- // Hiding a menu item between two separators hides the following separator.
- GtkAction* action = gtk_activatable_get_related_action(GTK_ACTIVATABLE(g_list_nth_data(menuItems.get(), 3)));
- gtk_action_set_visible(action, FALSE);
- menuItems.reset(gtk_container_get_children(GTK_CONTAINER(menu)));
- g_assert_cmpuint(g_list_length(menuItems.get()), ==, 6);
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 0));
- g_assert(!GTK_IS_SEPARATOR_MENU_ITEM(item) && gtk_widget_get_visible(item));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 1));
- g_assert(!GTK_IS_SEPARATOR_MENU_ITEM(item) && gtk_widget_get_visible(item));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 2));
- g_assert(GTK_IS_SEPARATOR_MENU_ITEM(item) && gtk_widget_get_visible(item));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 3));
- g_assert(!GTK_IS_SEPARATOR_MENU_ITEM(item) && !gtk_widget_get_visible(item));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 4));
- g_assert(GTK_IS_SEPARATOR_MENU_ITEM(item) && !gtk_widget_get_visible(item));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 5));
- g_assert(!GTK_IS_SEPARATOR_MENU_ITEM(item) && gtk_widget_get_visible(item));
- gtk_action_set_visible(action, TRUE);
-
- // Showing an action between two separators shows the hidden separator.
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 0));
- g_assert(!GTK_IS_SEPARATOR_MENU_ITEM(item) && gtk_widget_get_visible(item));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 1));
- g_assert(!GTK_IS_SEPARATOR_MENU_ITEM(item) && gtk_widget_get_visible(item));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 2));
- g_assert(GTK_IS_SEPARATOR_MENU_ITEM(item) && gtk_widget_get_visible(item));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 3));
- g_assert(!GTK_IS_SEPARATOR_MENU_ITEM(item) && gtk_widget_get_visible(item));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 4));
- g_assert(GTK_IS_SEPARATOR_MENU_ITEM(item) && gtk_widget_get_visible(item));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 5));
- g_assert(!GTK_IS_SEPARATOR_MENU_ITEM(item) && gtk_widget_get_visible(item));
-
- // Trailing separators are hidden too.
- action = gtk_activatable_get_related_action(GTK_ACTIVATABLE(g_list_nth_data(menuItems.get(), 5)));
- gtk_action_set_visible(action, FALSE);
- menuItems.reset(gtk_container_get_children(GTK_CONTAINER(menu)));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 0));
- g_assert(!GTK_IS_SEPARATOR_MENU_ITEM(item) && gtk_widget_get_visible(item));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 1));
- g_assert(!GTK_IS_SEPARATOR_MENU_ITEM(item) && gtk_widget_get_visible(item));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 2));
- g_assert(GTK_IS_SEPARATOR_MENU_ITEM(item) && gtk_widget_get_visible(item));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 3));
- g_assert(!GTK_IS_SEPARATOR_MENU_ITEM(item) && gtk_widget_get_visible(item));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 4));
- g_assert(GTK_IS_SEPARATOR_MENU_ITEM(item) && !gtk_widget_get_visible(item));
- item = GTK_WIDGET(g_list_nth_data(menuItems.get(), 5));
- g_assert(!GTK_IS_SEPARATOR_MENU_ITEM(item) && !gtk_widget_get_visible(item));
+ test->showContextMenuAtPositionAndWaitUntilFinished(0, 0);
+ g_assert_cmpstr(test->m_node.name.data(), ==, "HTML");
+ g_assert_cmpuint(test->m_node.type, ==, ContextMenuWebExtensionNodeTest::Node::NodeElement);
+ g_assert_cmpstr(test->m_node.contents.data(), ==, "WebKitGTK+ Context menu testsWebKitGTK+ Website");
+ g_assert_cmpstr(test->m_node.parentName.data(), ==, "#document");
+
+ test->showContextMenuAtPositionAndWaitUntilFinished(1, 20);
+ g_assert_cmpstr(test->m_node.name.data(), ==, "#text");
+ g_assert_cmpuint(test->m_node.type, ==, ContextMenuWebExtensionNodeTest::Node::NodeText);
+ g_assert_cmpstr(test->m_node.contents.data(), ==, "WebKitGTK+ Context menu tests");
+ g_assert_cmpstr(test->m_node.parentName.data(), ==, "P");
+
+ // Link menu.
+ test->showContextMenuAtPositionAndWaitUntilFinished(1, 101);
+ g_assert_cmpstr(test->m_node.name.data(), ==, "#text");
+ g_assert_cmpuint(test->m_node.type, ==, ContextMenuWebExtensionNodeTest::Node::NodeText);
+ g_assert_cmpstr(test->m_node.contents.data(), ==, "WebKitGTK+ Website");
+ g_assert_cmpstr(test->m_node.parentName.data(), ==, "A");
}
void beforeAll()
{
ContextMenuDefaultTest::add("WebKitWebView", "default-menu", testContextMenuDefaultMenu);
+ ContextMenuDefaultTest::add("WebKitWebView", "context-menu-key", testContextMenuKey);
+ ContextMenuDefaultTest::add("WebKitWebView", "popup-event-signal", testPopupEventSignal);
ContextMenuCustomTest::add("WebKitWebView", "populate-menu", testContextMenuPopulateMenu);
ContextMenuCustomFullTest::add("WebKitWebView", "custom-menu", testContextMenuCustomMenu);
ContextMenuDisabledTest::add("WebKitWebView", "disable-menu", testContextMenuDisableMenu);
ContextMenuSubmenuTest::add("WebKitWebView", "submenu", testContextMenuSubMenu);
ContextMenuDismissedTest::add("WebKitWebView", "menu-dismissed", testContextMenuDismissed);
- ContextMenuSmartSeparatorsTest::add("WebKitWebView", "smart-separators", testContextMenuSmartSeparators);
+ ContextMenuWebExtensionTest::add("WebKitWebPage", "context-menu", testContextMenuWebExtensionMenu);
+ ContextMenuWebExtensionNodeTest::add("WebKitWebPage", "context-menu-node", testContextMenuWebExtensionNode);
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestCookieManager.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestCookieManager.cpp
index 2e98645e8..4cd4b5c8c 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestCookieManager.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestCookieManager.cpp
@@ -24,7 +24,6 @@
#include <glib/gstdio.h>
static WebKitTestServer* kServer;
-static char* kTempDirectory;
static const char* kFirstPartyDomain = "127.0.0.1";
static const char* kThirdPartyDomain = "localhost";
@@ -53,6 +52,7 @@ public:
, m_cookiesChanged(false)
, m_finishLoopWhenCookiesChange(false)
{
+ g_assert(webkit_website_data_manager_get_cookie_manager(webkit_web_context_get_website_data_manager(webkit_web_view_get_context(m_webView))) == m_cookieManager);
g_signal_connect(m_cookieManager, "changed", G_CALLBACK(cookiesChangedCallback), this);
}
@@ -72,12 +72,12 @@ public:
switch (storage) {
case WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT:
if (!m_cookiesTextFile)
- m_cookiesTextFile.reset(g_build_filename(kTempDirectory, "cookies.txt", NULL));
+ m_cookiesTextFile.reset(g_build_filename(Test::dataDirectory(), "cookies.txt", nullptr));
filename = m_cookiesTextFile.get();
break;
case WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE:
if (!m_cookiesSQLiteFile)
- m_cookiesSQLiteFile.reset(g_build_filename(kTempDirectory, "cookies.db", NULL));
+ m_cookiesSQLiteFile.reset(g_build_filename(Test::dataDirectory(), "cookies.db", nullptr));
filename = m_cookiesSQLiteFile.get();
break;
default:
@@ -114,7 +114,9 @@ public:
static void getDomainsReadyCallback(GObject* object, GAsyncResult* result, gpointer userData)
{
GUniqueOutPtr<GError> error;
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
char** domains = webkit_cookie_manager_get_domains_with_cookies_finish(WEBKIT_COOKIE_MANAGER(object), result, &error.outPtr());
+ G_GNUC_END_IGNORE_DEPRECATIONS;
g_assert(!error.get());
CookieManagerTest* test = static_cast<CookieManagerTest*>(userData);
@@ -126,7 +128,9 @@ public:
{
g_strfreev(m_domains);
m_domains = 0;
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
webkit_cookie_manager_get_domains_with_cookies(m_cookieManager, 0, getDomainsReadyCallback, this);
+ G_GNUC_END_IGNORE_DEPRECATIONS;
g_main_loop_run(m_mainLoop);
return m_domains;
@@ -145,12 +149,16 @@ public:
void deleteCookiesForDomain(const char* domain)
{
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
webkit_cookie_manager_delete_cookies_for_domain(m_cookieManager, domain);
+ G_GNUC_END_IGNORE_DEPRECATIONS;
}
void deleteAllCookies()
{
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
webkit_cookie_manager_delete_all_cookies(m_cookieManager);
+ G_GNUC_END_IGNORE_DEPRECATIONS;
}
void waitUntilCookiesChanged()
@@ -291,6 +299,58 @@ static void testCookieManagerPersistentStorage(CookieManagerTest* test, gconstpo
g_assert_cmpint(g_strv_length(test->getDomains()), ==, 0);
}
+static void ephemeralViewloadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent, WebViewTest* test)
+{
+ if (loadEvent != WEBKIT_LOAD_FINISHED)
+ return;
+ g_signal_handlers_disconnect_by_func(webView, reinterpret_cast<void*>(ephemeralViewloadChanged), test);
+ test->quitMainLoop();
+}
+
+static void testCookieManagerEphemeral(CookieManagerTest* test, gconstpointer)
+{
+ test->setAcceptPolicy(WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS);
+ test->setPersistentStorage(WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT);
+ char** domains = test->getDomains();
+ g_assert(domains);
+ g_assert_cmpint(g_strv_length(domains), ==, 0);
+
+ GRefPtr<WebKitWebView> webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW,
+ "web-context", webkit_web_view_get_context(test->m_webView),
+ "is-ephemeral", TRUE,
+ nullptr));
+ g_assert(webkit_web_view_is_ephemeral(webView.get()));
+ g_assert(!webkit_web_context_is_ephemeral(webkit_web_view_get_context(webView.get())));
+
+ g_signal_connect(webView.get(), "load-changed", G_CALLBACK(ephemeralViewloadChanged), test);
+ webkit_web_view_load_uri(webView.get(), kServer->getURIForPath("/index.html").data());
+ g_main_loop_run(test->m_mainLoop);
+
+ domains = test->getDomains();
+ g_assert(domains);
+ g_assert_cmpint(g_strv_length(domains), ==, 0);
+
+ auto* viewDataManager = webkit_web_view_get_website_data_manager(webView.get());
+ g_assert(WEBKIT_IS_WEBSITE_DATA_MANAGER(viewDataManager));
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(viewDataManager));
+ g_assert(viewDataManager != webkit_web_context_get_website_data_manager(webkit_web_view_get_context(test->m_webView)));
+ auto* cookieManager = webkit_website_data_manager_get_cookie_manager(viewDataManager);
+ g_assert(WEBKIT_IS_COOKIE_MANAGER(cookieManager));
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(cookieManager));
+ g_assert(cookieManager != test->m_cookieManager);
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
+ webkit_cookie_manager_get_domains_with_cookies(cookieManager, nullptr, [](GObject* object, GAsyncResult* result, gpointer userData) {
+ auto* test = static_cast<CookieManagerTest*>(userData);
+ GUniquePtr<char*> domains(webkit_cookie_manager_get_domains_with_cookies_finish(WEBKIT_COOKIE_MANAGER(object), result, nullptr));
+ g_assert(domains);
+ g_assert_cmpint(g_strv_length(domains.get()), ==, 1);
+ g_assert_cmpstr(domains.get()[0], ==, kFirstPartyDomain);
+ test->quitMainLoop();
+ }, test);
+ G_GNUC_END_IGNORE_DEPRECATIONS;
+ g_main_loop_run(test->m_mainLoop);
+}
+
static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
{
if (message->method != SOUP_METHOD_GET) {
@@ -315,17 +375,14 @@ void beforeAll()
kServer = new WebKitTestServer();
kServer->run(serverCallback);
- kTempDirectory = g_dir_make_tmp("WebKit2Tests-XXXXXX", 0);
- g_assert(kTempDirectory);
-
CookieManagerTest::add("WebKitCookieManager", "accept-policy", testCookieManagerAcceptPolicy);
CookieManagerTest::add("WebKitCookieManager", "delete-cookies", testCookieManagerDeleteCookies);
CookieManagerTest::add("WebKitCookieManager", "cookies-changed", testCookieManagerCookiesChanged);
CookieManagerTest::add("WebKitCookieManager", "persistent-storage", testCookieManagerPersistentStorage);
+ CookieManagerTest::add("WebKitCookieManager", "ephemeral", testCookieManagerEphemeral);
}
void afterAll()
{
delete kServer;
- g_rmdir(kTempDirectory);
}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMDOMWindow.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMDOMWindow.cpp
new file mode 100644
index 000000000..98c6e1064
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMDOMWindow.cpp
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2013 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2,1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebProcessTestRunner.h"
+#include "WebViewTest.h"
+#include <gtk/gtk.h>
+#include <webkit2/webkit2.h>
+
+#define HTML_DOCUMENT "<html><head><title></title></head><style type='text/css'>#test { font-size: 16px; }</style><body><p id='test'>test</p></body></html>"
+
+typedef struct {
+ gboolean loaded;
+ gboolean clicked;
+ WebProcessTestRunner* testRunner;
+ WebViewTest* test;
+} DomDomWindowTestStatus;
+
+static DomDomWindowTestStatus status;
+
+static void signalsNotifyCallback(const gchar *key, const gchar *value, gconstpointer)
+{
+ if (g_str_equal(key, "ready")) {
+ // The document was already loaded in the webprocess, and its "load"
+ // signal couldn't be captured on time (was issued before the test
+ // started). We load it again to force a new "load" signal in the
+ // webprocess, which will be captured this time
+ status.test->loadHtml(HTML_DOCUMENT, 0);
+ }
+
+ if (g_str_equal(key, "loaded")) {
+ status.loaded = TRUE;
+ status.test->showInWindowAndWaitUntilMapped();
+
+ // Click in a known location where the text is
+ status.test->clickMouseButton(20, 18, 1, 0);
+ }
+
+ if (g_str_equal(key, "clicked"))
+ status.clicked = TRUE;
+
+ if (g_str_equal(key, "finish")) {
+ status.test = 0;
+ status.testRunner->finishTest(status.loaded && status.clicked);
+ }
+}
+
+static void dispatchEventNotifyCallback(const gchar *key, const gchar *value, gconstpointer)
+{
+ if (g_str_equal(key, "ready")) {
+ // The document was already loaded in the webprocess, and its "load"
+ // signal couldn't be captured on time (was issued before the test
+ // started). We load it again to force a new "load" signal in the
+ // webprocess, which will be captured this time
+ status.test->loadHtml(HTML_DOCUMENT, 0);
+ }
+
+ if (g_str_equal(key, "loaded"))
+ status.loaded = TRUE;
+
+ if (g_str_equal(key, "clicked"))
+ status.clicked = TRUE;
+
+ if (g_str_equal(key, "finish")) {
+ status.test = 0;
+ status.testRunner->finishTest(status.loaded && status.clicked);
+ }
+}
+
+static void testWebKitDOMDOMWindowSignals(WebViewTest* test, gconstpointer)
+{
+ status.loaded = FALSE;
+ status.clicked = FALSE;
+ status.test = test;
+
+ status.testRunner->setNotifyCallback(G_CALLBACK(signalsNotifyCallback), 0);
+
+ // The HTML document will we loaded later, when the test is "ready" because
+ // we want to test the "load" signal
+
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
+ g_variant_builder_add(&builder, "{sv}", "pageID", g_variant_new_uint64(webkit_web_view_get_page_id(status.test->m_webView)));
+ status.testRunner->runTestAndWait("WebKitDOMDOMWindow", "signals", g_variant_builder_end(&builder));
+ g_assert(status.testRunner->getTestResult());
+}
+
+static void testWebKitDOMDOMWindowDispatchEvent(WebViewTest* test, gconstpointer)
+{
+ status.loaded = FALSE;
+ status.clicked = FALSE;
+ status.test = test;
+
+ status.testRunner->setNotifyCallback(G_CALLBACK(dispatchEventNotifyCallback), 0);
+
+ // The HTML document will we loaded later, when the test is "ready" because
+ // we want to test the "load" signal
+
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
+ g_variant_builder_add(&builder, "{sv}", "pageID", g_variant_new_uint64(webkit_web_view_get_page_id(status.test->m_webView)));
+ status.testRunner->runTestAndWait("WebKitDOMDOMWindow", "dispatch-event", g_variant_builder_end(&builder));
+ g_assert(status.testRunner->getTestResult());
+}
+
+static void testWebKitDOMDOMWindowGetComputedStyle(WebViewTest* test, gconstpointer)
+{
+ status.loaded = FALSE;
+ status.clicked = FALSE;
+ status.test = test;
+
+ static const char* testHTML = HTML_DOCUMENT;
+ status.test->loadHtml(testHTML, 0);
+ status.test->waitUntilLoadFinished();
+
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
+ g_variant_builder_add(&builder, "{sv}", "pageID", g_variant_new_uint64(webkit_web_view_get_page_id(status.test->m_webView)));
+ g_assert(status.testRunner->runTest("WebKitDOMDOMWindow", "get-computed-style", g_variant_builder_end(&builder)));
+}
+
+void beforeAll()
+{
+ status.testRunner = new WebProcessTestRunner();
+ webkit_web_context_set_web_extensions_directory(webkit_web_context_get_default(), WEBKIT_TEST_WEB_EXTENSIONS_DIR);
+
+ WebViewTest::add("WebKitDOMDOMWindow", "signals", testWebKitDOMDOMWindowSignals);
+ WebViewTest::add("WebKitDOMDOMWindow", "dispatch-event", testWebKitDOMDOMWindowDispatchEvent);
+ WebViewTest::add("WebKitDOMDOMWindow", "get-computed-style", testWebKitDOMDOMWindowGetComputedStyle);
+}
+
+void afterAll()
+{
+ delete status.testRunner;
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNode.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNode.cpp
index 16db87d98..886356b7e 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNode.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNode.cpp
@@ -41,7 +41,7 @@ static void testWebKitDOMNodeInsertion(WebViewTest* test, gconstpointer)
g_assert(test->runWebProcessTest("WebKitDOMNode", "insertion"));
}
-static void testWebKitDOMNodeTagNames(WebViewTest* test, gconstpointer)
+static void prepareDOMForTagNamesTests(WebViewTest* test)
{
static const char* testHTML = "<html><head></head><body>"
"<video id='video' preload='none'>"
@@ -53,19 +53,44 @@ static void testWebKitDOMNodeTagNames(WebViewTest* test, gconstpointer)
" Your browser does not support the video tag."
"</video>"
"<input type='hidden' id='test' name='finish' value='false'></body></html>";
- test->loadHtml(testHTML, 0);
+ test->loadHtml(testHTML, nullptr);
test->waitUntilLoadFinished();
+}
- g_assert(test->runWebProcessTest("WebKitDOMNode", "tag-names"));
+static void testWebKitDOMNodeTagNamesNodeList(WebViewTest* test, gconstpointer)
+{
+ prepareDOMForTagNamesTests(test);
+ g_assert(test->runWebProcessTest("WebKitDOMNode", "tag-names-node-list"));
}
-void beforeAll()
+static void testWebKitDOMNodeTagNamesHTMLCollection(WebViewTest* test, gconstpointer)
+{
+ prepareDOMForTagNamesTests(test);
+ g_assert(test->runWebProcessTest("WebKitDOMNode", "tag-names-html-collection"));
+}
+
+static void testWebKitDOMObjectCache(WebViewTest* test, gconstpointer)
{
- webkit_web_context_set_web_extensions_directory(webkit_web_context_get_default(), WEBKIT_TEST_WEB_EXTENSIONS_DIR);
+ static const char* testHTML = "<html><body><div id='container'><p>DOM Cache test</p><a id='link href='#'>link</a></div></body></html>";
+ // Run the test 3 times to make sure the DOM objects are correctly released when the
+ // document is detached from the frame for every new document created.
+ for (unsigned i = 0; i < 3; ++i) {
+ test->loadHtml(testHTML, nullptr);
+ test->waitUntilLoadFinished();
+
+ g_assert(test->runWebProcessTest("WebKitDOMNode", "dom-cache"));
+ }
+}
+
+
+void beforeAll()
+{
WebViewTest::add("WebKitDOMNode", "hierarchy-navigation", testWebKitDOMNodeHierarchyNavigation);
WebViewTest::add("WebKitDOMNode", "insertion", testWebKitDOMNodeInsertion);
- WebViewTest::add("WebKitDOMNode", "tag-names", testWebKitDOMNodeTagNames);
+ WebViewTest::add("WebKitDOMNode", "tag-names-node-list", testWebKitDOMNodeTagNamesNodeList);
+ WebViewTest::add("WebKitDOMNode", "tag-names-html-collection", testWebKitDOMNodeTagNamesHTMLCollection);
+ WebViewTest::add("WebKitDOMNode", "dom-cache", testWebKitDOMObjectCache);
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNodeFilter.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNodeFilter.cpp
new file mode 100644
index 000000000..812946153
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNodeFilter.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2,1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebViewTest.h"
+#include <gtk/gtk.h>
+#include <webkit2/webkit2.h>
+
+static const char* testHTML = "<html id='root'><head><title>DOMNodeTreeWalker</title></head>"
+ "<body><input type='button' name='push' value='push'><input type='button' name='clear' value='clear'><br></body></html>";
+
+static void runTest(WebViewTest* test, const char* name)
+{
+ test->loadHtml(testHTML, nullptr);
+ test->waitUntilLoadFinished();
+
+ g_assert(test->runWebProcessTest("WebKitDOMNodeFilter", name));
+}
+
+static void testWebKitDOMNodeFilterTreeWalker(WebViewTest* test, gconstpointer)
+{
+ runTest(test, "tree-walker");
+}
+
+static void testWebKitDOMNodeFilterNodeIterator(WebViewTest* test, gconstpointer)
+{
+ runTest(test, "node-iterator");
+}
+
+void beforeAll()
+{
+ WebViewTest::add("WebKitDOMNodeFilter", "tree-walker", testWebKitDOMNodeFilterTreeWalker);
+ WebViewTest::add("WebKitDOMNodeFilter", "node-iterator", testWebKitDOMNodeFilterNodeIterator);
+}
+
+void afterAll()
+{
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMXPathNSResolver.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMXPathNSResolver.cpp
new file mode 100644
index 000000000..ff9a77192
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMXPathNSResolver.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2,1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebViewTest.h"
+#include <gtk/gtk.h>
+#include <webkit2/webkit2.h>
+
+static void testWebKitDOMXPathNSResolverNative(WebViewTest* test, gconstpointer)
+{
+ static const char* nativeXML = "<root xmlns:foo='http://www.example.org'><foo:child>SUCCESS</foo:child></root>";
+ GRefPtr<GBytes> bytes = adoptGRef(g_bytes_new_static(nativeXML, strlen(nativeXML)));
+ test->loadBytes(bytes.get(), "text/xml", nullptr, nullptr);
+ test->waitUntilLoadFinished();
+ g_assert(test->runWebProcessTest("WebKitDOMXPathNSResolver", "native"));
+}
+
+static void testWebKitDOMXPathNSResolverCustom(WebViewTest* test, gconstpointer)
+{
+ static const char* customXML = "<root xmlns='http://www.example.com'><child>SUCCESS</child></root>";
+ GRefPtr<GBytes> bytes = adoptGRef(g_bytes_new_static(customXML, strlen(customXML)));
+ test->loadBytes(bytes.get(), "text/xml", nullptr, nullptr);
+ test->waitUntilLoadFinished();
+ g_assert(test->runWebProcessTest("WebKitDOMXPathNSResolver", "custom"));
+}
+
+void beforeAll()
+{
+ WebViewTest::add("WebKitDOMXPathNSResolver", "native", testWebKitDOMXPathNSResolverNative);
+ WebViewTest::add("WebKitDOMXPathNSResolver", "custom", testWebKitDOMXPathNSResolverCustom);
+}
+
+void afterAll()
+{
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp
index a4d27a508..6b95a7fe4 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDownloads.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Igalia S.L.
+ * Copyright (C) 2012, 2014 Igalia S.L.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -27,12 +27,10 @@
#include <string.h>
#include <webkit2/webkit2.h>
#include <wtf/Vector.h>
-#include <wtf/gobject/GRefPtr.h>
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/glib/GUniquePtr.h>
#include <wtf/text/CString.h>
-static char* kTempDirectory;
-
class DownloadTest: public Test {
public:
MAKE_GLIB_TEST_FIXTURE(DownloadTest);
@@ -56,6 +54,8 @@ public:
{
g_assert(webkit_download_get_destination(download));
g_assert_cmpstr(webkit_download_get_destination(download), ==, destination);
+ GRefPtr<GFile> file = adoptGRef(g_file_new_for_uri(destination));
+ g_assert(g_file_query_exists(file.get(), nullptr));
test->createdDestination(download, destination);
}
@@ -72,6 +72,14 @@ public:
static void failedCallback(WebKitDownload* download, GError* error, DownloadTest* test)
{
g_assert(error);
+
+ const char* destinationURI = webkit_download_get_destination(download);
+ if (destinationURI) {
+ GUniquePtr<char> tempFileURI(g_strconcat(destinationURI, ".wkdownload", nullptr));
+ GRefPtr<GFile> tempFile = adoptGRef(g_file_new_for_uri(tempFileURI.get()));
+ g_assert(!g_file_query_exists(tempFile.get(), nullptr));
+ }
+
test->failed(download, error);
}
@@ -95,21 +103,23 @@ public:
}
DownloadTest()
- : m_webContext(webkit_web_context_get_default())
- , m_mainLoop(g_main_loop_new(0, TRUE))
+ : m_mainLoop(g_main_loop_new(nullptr, TRUE))
, m_downloadSize(0)
+ , m_allowOverwrite(false)
{
- g_signal_connect(m_webContext, "download-started", G_CALLBACK(downloadStartedCallback), this);
+ g_signal_connect(m_webContext.get(), "download-started", G_CALLBACK(downloadStartedCallback), this);
}
~DownloadTest()
{
- g_signal_handlers_disconnect_matched(m_webContext, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
+ g_signal_handlers_disconnect_matched(m_webContext.get(), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
g_main_loop_unref(m_mainLoop);
}
virtual void started(WebKitDownload* download)
{
+ m_downloadSize = 0;
+ m_downloadEvents.clear();
m_downloadEvents.append(Started);
}
@@ -144,17 +154,21 @@ public:
virtual void decideDestination(WebKitDownload* download, const gchar* suggestedFilename)
{
- GUniquePtr<char> destination(g_build_filename(kTempDirectory, suggestedFilename, NULL));
+ GUniquePtr<char> destination(g_build_filename(Test::dataDirectory(), suggestedFilename, nullptr));
GUniquePtr<char> destinationURI(g_filename_to_uri(destination.get(), 0, 0));
webkit_download_set_destination(download, destinationURI.get());
}
- WebKitDownload* downloadURIAndWaitUntilFinishes(const CString& requestURI)
+ GRefPtr<WebKitDownload> downloadURIAndWaitUntilFinishes(const CString& requestURI)
{
- WebKitDownload* download = webkit_web_context_download_uri(m_webContext, requestURI.data());
- assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download));
+ GRefPtr<WebKitDownload> download = adoptGRef(webkit_web_context_download_uri(m_webContext.get(), requestURI.data()));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get()));
- WebKitURIRequest* request = webkit_download_get_request(download);
+ g_assert(!webkit_download_get_allow_overwrite(download.get()));
+ webkit_download_set_allow_overwrite(download.get(), m_allowOverwrite);
+ g_assert(webkit_download_get_allow_overwrite(download.get()) == m_allowOverwrite);
+
+ WebKitURIRequest* request = webkit_download_get_request(download.get());
g_assert(request);
ASSERT_CMP_CSTRING(webkit_uri_request_get_uri(request), ==, requestURI);
@@ -174,19 +188,19 @@ public:
g_file_delete(destFile.get(), 0, 0);
}
- WebKitWebContext* m_webContext;
GMainLoop* m_mainLoop;
Vector<DownloadEvent> m_downloadEvents;
guint64 m_downloadSize;
+ bool m_allowOverwrite;
};
-static void testDownloadLocalFile(DownloadTest* test, gconstpointer)
+static GRefPtr<WebKitDownload> downloadLocalFileSuccessfully(DownloadTest* test, const char* filename)
{
- GUniquePtr<char> sourcePath(g_build_filename(Test::getWebKit1TestResoucesDir().data(), "test.pdf", NULL));
+ GUniquePtr<char> sourcePath(g_build_filename(Test::getResourcesDir().data(), filename, nullptr));
GRefPtr<GFile> source = adoptGRef(g_file_new_for_path(sourcePath.get()));
GRefPtr<GFileInfo> sourceInfo = adoptGRef(g_file_query_info(source.get(), G_FILE_ATTRIBUTE_STANDARD_SIZE, static_cast<GFileQueryInfoFlags>(0), 0, 0));
GUniquePtr<char> sourceURI(g_file_get_uri(source.get()));
- GRefPtr<WebKitDownload> download = adoptGRef(test->downloadURIAndWaitUntilFinishes(sourceURI.get()));
+ GRefPtr<WebKitDownload> download = test->downloadURIAndWaitUntilFinishes(sourceURI.get());
g_assert(!webkit_download_get_web_view(download.get()));
Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents;
@@ -204,15 +218,50 @@ static void testDownloadLocalFile(DownloadTest* test, gconstpointer)
g_assert_cmpint(test->m_downloadSize, ==, g_file_info_get_size(sourceInfo.get()));
g_assert(webkit_download_get_destination(download.get()));
g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), ==, 1);
- test->checkDestinationAndDeleteFile(download.get(), "test.pdf");
+
+ return download;
+}
+
+static void testDownloadLocalFile(DownloadTest* test, gconstpointer)
+{
+ static const char* filename = "test.pdf";
+ GRefPtr<WebKitDownload> download = downloadLocalFileSuccessfully(test, filename);
+ test->checkDestinationAndDeleteFile(download.get(), filename);
+}
+
+static void createFileAtDestination(const char* filename)
+{
+ GUniquePtr<char> path(g_build_filename(Test::dataDirectory(), filename, nullptr));
+ GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(path.get()));
+ GUniqueOutPtr<GError> error;
+ g_file_create(file.get(), G_FILE_CREATE_NONE, nullptr, &error.outPtr());
+ g_assert(!error);
+ g_assert(g_file_query_exists(file.get(), nullptr));
+}
+
+static void testDownloadOverwriteDestinationAllowed(DownloadTest* test, gconstpointer)
+{
+ static const char* filename = "test.pdf";
+ createFileAtDestination(filename);
+
+ test->m_allowOverwrite = true;
+ GRefPtr<WebKitDownload> download = downloadLocalFileSuccessfully(test, filename);
+ test->checkDestinationAndDeleteFile(download.get(), filename);
}
class DownloadErrorTest: public DownloadTest {
public:
MAKE_GLIB_TEST_FIXTURE(DownloadErrorTest);
+ enum ExpectedError {
+ NetworkError,
+ DownloadCancelled,
+ InvalidDestination,
+ DestinationExists
+ };
+
DownloadErrorTest()
- : m_expectedError(WEBKIT_DOWNLOAD_ERROR_NETWORK)
+ : m_expectedError(NetworkError)
{
}
@@ -223,7 +272,7 @@ public:
void createdDestination(WebKitDownload* download, const char* destination)
{
- if (m_expectedError == WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER)
+ if (m_expectedError == DownloadCancelled)
webkit_download_cancel(download);
else
g_assert_not_reached();
@@ -231,26 +280,65 @@ public:
void failed(WebKitDownload* download, GError* error)
{
- g_assert(g_error_matches(error, WEBKIT_DOWNLOAD_ERROR, m_expectedError));
+ g_assert(g_error_matches(error, WEBKIT_DOWNLOAD_ERROR, expectedErrorToWebKitDownloadError(m_expectedError)));
DownloadTest::failed(download, error);
}
void decideDestination(WebKitDownload* download, const gchar* suggestedFilename)
{
- if (m_expectedError != WEBKIT_DOWNLOAD_ERROR_DESTINATION) {
+ if (m_expectedError != InvalidDestination) {
DownloadTest::decideDestination(download, suggestedFilename);
return;
}
webkit_download_set_destination(download, "file:///foo/bar");
}
- WebKitDownloadError m_expectedError;
+ static WebKitDownloadError expectedErrorToWebKitDownloadError(ExpectedError expected)
+ {
+ switch (expected) {
+ case NetworkError:
+ return WEBKIT_DOWNLOAD_ERROR_NETWORK;
+ case DownloadCancelled:
+ return WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER;
+ case InvalidDestination:
+ return WEBKIT_DOWNLOAD_ERROR_DESTINATION;
+ case DestinationExists:
+ return WEBKIT_DOWNLOAD_ERROR_DESTINATION;
+ default:
+ g_assert_not_reached();
+ }
+ }
+
+ ExpectedError m_expectedError;
};
+static void testDownloadOverwriteDestinationDisallowed(DownloadErrorTest* test, gconstpointer)
+{
+ static const char* filename = "test.pdf";
+ createFileAtDestination(filename);
+
+ test->m_expectedError = DownloadErrorTest::DestinationExists;
+ GUniquePtr<char> sourcePath(g_build_filename(Test::getResourcesDir().data(), filename, nullptr));
+ GRefPtr<GFile> source = adoptGRef(g_file_new_for_path(sourcePath.get()));
+ GUniquePtr<char> sourceURI(g_file_get_uri(source.get()));
+ GRefPtr<WebKitDownload> download = test->downloadURIAndWaitUntilFinishes(sourceURI.get());
+ g_assert(!webkit_download_get_web_view(download.get()));
+
+ Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents;
+ g_assert_cmpint(events.size(), ==, 4);
+ g_assert_cmpint(events[0], ==, DownloadTest::Started);
+ g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse);
+ g_assert_cmpint(events[2], ==, DownloadTest::Failed);
+ g_assert_cmpint(events[3], ==, DownloadTest::Finished);
+ g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), ==, 0);
+
+ test->checkDestinationAndDeleteFile(download.get(), filename);
+}
+
static void testDownloadLocalFileError(DownloadErrorTest* test, gconstpointer)
{
- test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_NETWORK;
- GRefPtr<WebKitDownload> download = adoptGRef(test->downloadURIAndWaitUntilFinishes("file:///foo/bar"));
+ test->m_expectedError = DownloadErrorTest::NetworkError;
+ GRefPtr<WebKitDownload> download = test->downloadURIAndWaitUntilFinishes("file:///foo/bar");
g_assert(!webkit_download_get_web_view(download.get()));
Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents;
@@ -261,11 +349,11 @@ static void testDownloadLocalFileError(DownloadErrorTest* test, gconstpointer)
events.clear();
g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1);
- test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_DESTINATION;
- GUniquePtr<char> path(g_build_filename(Test::getWebKit1TestResoucesDir().data(), "test.pdf", NULL));
+ test->m_expectedError = DownloadErrorTest::InvalidDestination;
+ GUniquePtr<char> path(g_build_filename(Test::getResourcesDir().data(), "test.pdf", nullptr));
GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(path.get()));
GUniquePtr<char> uri(g_file_get_uri(file.get()));
- download = adoptGRef(test->downloadURIAndWaitUntilFinishes(uri.get()));
+ download = test->downloadURIAndWaitUntilFinishes(uri.get());
g_assert(!webkit_download_get_web_view(download.get()));
g_assert_cmpint(events.size(), ==, 4);
@@ -277,8 +365,8 @@ static void testDownloadLocalFileError(DownloadErrorTest* test, gconstpointer)
g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1);
test->checkDestinationAndDeleteFile(download.get(), "bar");
- test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER;
- download = adoptGRef(test->downloadURIAndWaitUntilFinishes(uri.get()));
+ test->m_expectedError = DownloadErrorTest::DownloadCancelled;
+ download = test->downloadURIAndWaitUntilFinishes(uri.get());
g_assert(!webkit_download_get_web_view(download.get()));
g_assert_cmpint(events.size(), ==, 4);
@@ -300,15 +388,17 @@ static void addContentDispositionHTTPHeaderToResponse(SoupMessage* message)
soup_message_headers_append(message->response_headers, "Content-Disposition", contentDisposition.get());
}
-static gboolean writeNextChunkIdle(SoupMessage* message)
-{
- soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, "chunk", 5);
- return FALSE;
-}
-
static void writeNextChunk(SoupMessage* message)
{
- g_timeout_add(100, reinterpret_cast<GSourceFunc>(writeNextChunkIdle), message);
+ /* We need a big enough chunk for the sniffer to not block the load */
+ static const char* chunk = "Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
+ "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
+ "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
+ "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
+ "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
+ "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
+ "Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!";
+ soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, chunk, strlen(chunk));
}
static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
@@ -329,7 +419,10 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char*
return;
}
- GUniquePtr<char> filePath(g_build_filename(Test::getWebKit1TestResoucesDir().data(), path, NULL));
+ if (g_str_equal(path, "/unknown"))
+ path = "/test.pdf";
+
+ GUniquePtr<char> filePath(g_build_filename(Test::getResourcesDir().data(), path, nullptr));
char* contents;
gsize contentsLength;
if (!g_file_get_contents(filePath.get(), &contents, &contentsLength, 0)) {
@@ -346,7 +439,7 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char*
static void testDownloadRemoteFile(DownloadTest* test, gconstpointer)
{
- GRefPtr<WebKitDownload> download = adoptGRef(test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/test.pdf")));
+ GRefPtr<WebKitDownload> download = test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/test.pdf"));
g_assert(!webkit_download_get_web_view(download.get()));
Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents;
@@ -364,13 +457,14 @@ static void testDownloadRemoteFile(DownloadTest* test, gconstpointer)
g_assert(webkit_download_get_destination(download.get()));
g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), ==, 1);
- test->checkDestinationAndDeleteFile(download.get(), kServerSuggestedFilename);
+ GUniquePtr<char> expectedFilename(g_strdup_printf("%s.pdf", kServerSuggestedFilename));
+ test->checkDestinationAndDeleteFile(download.get(), expectedFilename.get());
}
static void testDownloadRemoteFileError(DownloadErrorTest* test, gconstpointer)
{
- test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_NETWORK;
- GRefPtr<WebKitDownload> download = adoptGRef(test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/foo")));
+ test->m_expectedError = DownloadErrorTest::NetworkError;
+ GRefPtr<WebKitDownload> download = test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/foo"));
g_assert(!webkit_download_get_web_view(download.get()));
Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents;
@@ -384,8 +478,8 @@ static void testDownloadRemoteFileError(DownloadErrorTest* test, gconstpointer)
g_assert_cmpuint(webkit_uri_response_get_status_code(response), ==, 404);
g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1);
- test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_DESTINATION;
- download = adoptGRef(test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/test.pdf")));
+ test->m_expectedError = DownloadErrorTest::InvalidDestination;
+ download = test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/test.pdf"));
g_assert(!webkit_download_get_web_view(download.get()));
g_assert_cmpint(events.size(), ==, 4);
@@ -397,8 +491,8 @@ static void testDownloadRemoteFileError(DownloadErrorTest* test, gconstpointer)
g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), <, 1);
test->checkDestinationAndDeleteFile(download.get(), "bar");
- test->m_expectedError = WEBKIT_DOWNLOAD_ERROR_CANCELLED_BY_USER;
- download = adoptGRef(test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/cancel-after-destination")));
+ test->m_expectedError = DownloadErrorTest::DownloadCancelled;
+ download = test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/cancel-after-destination"));
g_assert(!webkit_download_get_web_view(download.get()));
g_assert_cmpint(events.size(), ==, 4);
@@ -422,6 +516,8 @@ public:
{
test->m_download = download;
test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download));
+ g_signal_connect(download, "decide-destination", G_CALLBACK(downloadDecideDestinationCallback), test);
+ g_signal_connect(download, "finished", G_CALLBACK(downloadFinishedCallback), test);
test->quitMainLoop();
}
@@ -444,8 +540,10 @@ public:
static gboolean downloadDecideDestinationCallback(WebKitDownload* download, const gchar* suggestedFilename, WebViewDownloadTest* test)
{
- GUniquePtr<char> destination(g_build_filename(kTempDirectory, suggestedFilename, NULL));
+ GUniquePtr<char> destination(g_build_filename(Test::dataDirectory(), suggestedFilename, nullptr));
GUniquePtr<char> destinationURI(g_filename_to_uri(destination.get(), 0, 0));
+ if (test->m_shouldDelayDecideDestination)
+ g_usleep(0.2 * G_USEC_PER_SEC);
webkit_download_set_destination(download, destinationURI.get());
return TRUE;
}
@@ -457,17 +555,17 @@ public:
void waitUntilDownloadFinished()
{
- g_signal_connect(m_download.get(), "decide-destination", G_CALLBACK(downloadDecideDestinationCallback), this);
- g_signal_connect(m_download.get(), "finished", G_CALLBACK(downloadFinishedCallback), this);
g_main_loop_run(m_mainLoop);
}
GRefPtr<WebKitDownload> m_download;
+ bool m_shouldDelayDecideDestination { false };
};
static void testWebViewDownloadURI(WebViewDownloadTest* test, gconstpointer)
{
GRefPtr<WebKitDownload> download = adoptGRef(webkit_web_view_download_uri(test->m_webView, kServer->getURIForPath("/test.pdf").data()));
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(download.get()));
test->waitUntilDownloadStarted();
g_assert(test->m_webView == webkit_download_get_web_view(download.get()));
test->waitUntilDownloadFinished();
@@ -511,7 +609,28 @@ public:
static void testPolicyResponseDownload(PolicyResponseDownloadTest* test, gconstpointer)
{
- // Test that a download started by the the policy checker contains the web view.
+ CString requestURI = kServer->getURIForPath("/test.pdf").data();
+ // Delay the DecideDestination to ensure that the load is aborted before the network task has became a download.
+ // See https://bugs.webkit.org/show_bug.cgi?id=164220.
+ test->m_shouldDelayDecideDestination = true;
+ test->loadURI(requestURI.data());
+ test->waitUntilDownloadStarted();
+
+ WebKitURIRequest* request = webkit_download_get_request(test->m_download.get());
+ g_assert(request);
+ ASSERT_CMP_CSTRING(webkit_uri_request_get_uri(request), ==, requestURI);
+
+ g_assert(test->m_webView == webkit_download_get_web_view(test->m_download.get()));
+ test->waitUntilDownloadFinished();
+
+ GRefPtr<GFile> downloadFile = adoptGRef(g_file_new_for_uri(webkit_download_get_destination(test->m_download.get())));
+ GRefPtr<GFileInfo> downloadFileInfo = adoptGRef(g_file_query_info(downloadFile.get(), G_FILE_ATTRIBUTE_STANDARD_SIZE, static_cast<GFileQueryInfoFlags>(0), nullptr, nullptr));
+ g_assert_cmpint(g_file_info_get_size(downloadFileInfo.get()), >, 0);
+ g_file_delete(downloadFile.get(), nullptr, nullptr);
+}
+
+static void testPolicyResponseDownloadCancel(PolicyResponseDownloadTest* test, gconstpointer)
+{
CString requestURI = kServer->getURIForPath("/test.pdf").data();
test->loadURI(requestURI.data());
test->waitUntilDownloadStarted();
@@ -524,24 +643,146 @@ static void testPolicyResponseDownload(PolicyResponseDownloadTest* test, gconstp
test->cancelDownloadAndWaitUntilFinished();
}
+static void testDownloadMIMEType(DownloadTest* test, gconstpointer)
+{
+ GRefPtr<WebKitDownload> download = test->downloadURIAndWaitUntilFinishes(kServer->getURIForPath("/unknown"));
+ g_assert(!webkit_download_get_web_view(download.get()));
+
+ Vector<DownloadTest::DownloadEvent>& events = test->m_downloadEvents;
+ g_assert_cmpint(events.size(), ==, 5);
+ g_assert_cmpint(events[0], ==, DownloadTest::Started);
+ g_assert_cmpint(events[1], ==, DownloadTest::ReceivedResponse);
+ g_assert_cmpint(events[2], ==, DownloadTest::CreatedDestination);
+ g_assert_cmpint(events[3], ==, DownloadTest::ReceivedData);
+ g_assert_cmpint(events[4], ==, DownloadTest::Finished);
+ events.clear();
+
+ WebKitURIRequest* request = webkit_download_get_request(download.get());
+ WEBKIT_IS_URI_REQUEST(request);
+ ASSERT_CMP_CSTRING(webkit_uri_request_get_uri(request), ==, kServer->getURIForPath("/unknown"));
+
+ WebKitURIResponse* response = webkit_download_get_response(download.get());
+ WEBKIT_IS_URI_RESPONSE(response);
+ g_assert_cmpstr(webkit_uri_response_get_mime_type(response), ==, "application/pdf");
+
+ g_assert(webkit_download_get_destination(download.get()));
+ g_assert_cmpfloat(webkit_download_get_estimated_progress(download.get()), ==, 1);
+ GUniquePtr<char> expectedFilename(g_strdup_printf("%s.pdf", kServerSuggestedFilename));
+ test->checkDestinationAndDeleteFile(download.get(), expectedFilename.get());
+}
+
+static gboolean contextMenuCallback(WebKitWebView* webView, WebKitContextMenu* contextMenu, GdkEvent*, WebKitHitTestResult* hitTestResult, WebViewDownloadTest* test)
+{
+ g_assert(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult));
+ g_assert(webkit_hit_test_result_context_is_link(hitTestResult));
+ GList* items = webkit_context_menu_get_items(contextMenu);
+ GRefPtr<WebKitContextMenuItem> contextMenuItem;
+ for (GList* l = items; l; l = g_list_next(l)) {
+ g_assert(WEBKIT_IS_CONTEXT_MENU_ITEM(l->data));
+ auto* item = WEBKIT_CONTEXT_MENU_ITEM(l->data);
+ if (webkit_context_menu_item_get_stock_action(item) == WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK) {
+ contextMenuItem = item;
+ break;
+ }
+ }
+ g_assert(contextMenuItem.get());
+ webkit_context_menu_remove_all(contextMenu);
+ webkit_context_menu_append(contextMenu, contextMenuItem.get());
+ test->quitMainLoop();
+ return FALSE;
+}
+
+static void testContextMenuDownloadActions(WebViewDownloadTest* test, gconstpointer)
+{
+ test->showInWindowAndWaitUntilMapped();
+
+ static const char* linkHTMLFormat = "<html><body><a style='position:absolute; left:1; top:1' href='%s'>Download Me</a></body></html>";
+ GUniquePtr<char> linkHTML(g_strdup_printf(linkHTMLFormat, kServer->getURIForPath("/test.pdf").data()));
+ test->loadHtml(linkHTML.get(), kServer->getURIForPath("/").data());
+ test->waitUntilLoadFinished();
+
+ g_signal_connect(test->m_webView, "context-menu", G_CALLBACK(contextMenuCallback), test);
+ g_idle_add([](gpointer userData) -> gboolean {
+ auto* test = static_cast<WebViewDownloadTest*>(userData);
+ test->clickMouseButton(1, 1, 3);
+ return FALSE;
+ }, test);
+ g_main_loop_run(test->m_mainLoop);
+
+ g_idle_add([](gpointer userData) -> gboolean {
+ auto* test = static_cast<WebViewDownloadTest*>(userData);
+ // Select and activate the context menu action.
+ test->keyStroke(GDK_KEY_Down);
+ test->keyStroke(GDK_KEY_Return);
+ return FALSE;
+ }, test);
+ test->waitUntilDownloadStarted();
+
+ g_assert(test->m_webView == webkit_download_get_web_view(test->m_download.get()));
+ test->waitUntilDownloadFinished();
+
+ GRefPtr<GFile> downloadFile = adoptGRef(g_file_new_for_uri(webkit_download_get_destination(test->m_download.get())));
+ GRefPtr<GFileInfo> downloadFileInfo = adoptGRef(g_file_query_info(downloadFile.get(), G_FILE_ATTRIBUTE_STANDARD_SIZE, static_cast<GFileQueryInfoFlags>(0), nullptr, nullptr));
+ g_assert_cmpint(g_file_info_get_size(downloadFileInfo.get()), >, 0);
+ g_file_delete(downloadFile.get(), nullptr, nullptr);
+}
+
+static void testBlobDownload(WebViewDownloadTest* test, gconstpointer)
+{
+ test->showInWindowAndWaitUntilMapped();
+
+ static const char* linkBlobHTML =
+ "<html><body>"
+ "<a id='downloadLink' style='position:absolute; left:1; top:1' download='foo.pdf'>Download Me</a>"
+ "<script>"
+ " blob = new Blob(['Hello world'], {type: 'text/plain'});"
+ " document.getElementById('downloadLink').href = window.URL.createObjectURL(blob);"
+ "</script>"
+ "</body></html>";
+ test->loadHtml(linkBlobHTML, kServer->getURIForPath("/").data());
+ test->waitUntilLoadFinished();
+
+ g_idle_add([](gpointer userData) -> gboolean {
+ auto* test = static_cast<WebViewDownloadTest*>(userData);
+ test->clickMouseButton(1, 1, 1);
+ return FALSE;
+ }, test);
+ test->waitUntilDownloadStarted();
+
+ g_assert(test->m_webView == webkit_download_get_web_view(test->m_download.get()));
+ test->waitUntilDownloadFinished();
+
+ GRefPtr<GFile> downloadFile = adoptGRef(g_file_new_for_uri(webkit_download_get_destination(test->m_download.get())));
+ GRefPtr<GFileInfo> downloadFileInfo = adoptGRef(g_file_query_info(downloadFile.get(), G_FILE_ATTRIBUTE_STANDARD_SIZE, static_cast<GFileQueryInfoFlags>(0), nullptr, nullptr));
+ GUniquePtr<char> downloadPath(g_file_get_path(downloadFile.get()));
+ GUniqueOutPtr<char> downloadContents;
+ gsize downloadContentsLength;
+ g_assert(g_file_get_contents(downloadPath.get(), &downloadContents.outPtr(), &downloadContentsLength, nullptr));
+ g_assert_cmpint(g_file_info_get_size(downloadFileInfo.get()), ==, downloadContentsLength);
+ g_assert_cmpstr(downloadContents.get(), ==, "Hello world");
+ g_file_delete(downloadFile.get(), nullptr, nullptr);
+}
+
void beforeAll()
{
kServer = new WebKitTestServer();
kServer->run(serverCallback);
- kTempDirectory = g_dir_make_tmp("WebKit2Tests-XXXXXX", 0);
- g_assert(kTempDirectory);
-
DownloadTest::add("Downloads", "local-file", testDownloadLocalFile);
+ DownloadTest::add("Downloads", "overwrite-destination-allowed", testDownloadOverwriteDestinationAllowed);
+ DownloadErrorTest::add("Downloads", "overwrite-destination-disallowed", testDownloadOverwriteDestinationDisallowed);
DownloadErrorTest::add("Downloads", "local-file-error", testDownloadLocalFileError);
DownloadTest::add("Downloads", "remote-file", testDownloadRemoteFile);
DownloadErrorTest::add("Downloads", "remote-file-error", testDownloadRemoteFileError);
WebViewDownloadTest::add("WebKitWebView", "download-uri", testWebViewDownloadURI);
PolicyResponseDownloadTest::add("Downloads", "policy-decision-download", testPolicyResponseDownload);
+ PolicyResponseDownloadTest::add("Downloads", "policy-decision-download-cancel", testPolicyResponseDownloadCancel);
+ DownloadTest::add("Downloads", "mime-type", testDownloadMIMEType);
+ WebViewDownloadTest::add("Downloads", "contex-menu-download-actions", testContextMenuDownloadActions);
+ WebViewDownloadTest::add("Downloads", "blob-download", testBlobDownload);
}
void afterAll()
{
delete kServer;
- g_rmdir(kTempDirectory);
}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testapplicationcache.c b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestEditor.cpp
index 718f401a7..fc429d4c3 100644
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testapplicationcache.c
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestEditor.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Lukasz Slachciak
+ * Copyright (C) 2015 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -18,32 +18,25 @@
*/
#include "config.h"
-#include <glib.h>
-#include <glib/gprintf.h>
+
+#include "WebViewTest.h"
#include <gtk/gtk.h>
-#include <webkit/webkit.h>
+#include <webkit2/webkit2.h>
-static void test_application_cache_maximum_size()
+static void testWebKitWebEditorSelectionChanged(WebViewTest* test, gconstpointer)
{
- unsigned long long maxSize = 8192;
- webkit_application_cache_set_maximum_size(maxSize);
-
- // Creating a WebView - make sure that it didn't change anything
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- g_object_unref(webView);
+ static const gchar* testHTML = "<html><body>All work and no play make Jack a dull boy.</body></html>";
+ test->loadHtml(testHTML, nullptr);
+ test->waitUntilLoadFinished();
- g_assert(maxSize == webkit_application_cache_get_maximum_size());
+ g_assert(test->runWebProcessTest("WebKitWebEditor", "selection-changed"));
}
-int main(int argc, char** argv)
+void beforeAll()
{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/application_cache/maximum_size",
- test_application_cache_maximum_size);
-
- return g_test_run();
+ WebViewTest::add("WebKitWebEditor", "selection-changed", testWebKitWebEditorSelectionChanged);
}
+void afterAll()
+{
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestFrame.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestFrame.cpp
index 69b5082cd..9145ab813 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestFrame.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestFrame.cpp
@@ -49,8 +49,6 @@ static void testWebKitFrameJavaScriptContext(WebViewTest* test, gconstpointer)
void beforeAll()
{
- webkit_web_context_set_web_extensions_directory(webkit_web_context_get_default(), WEBKIT_TEST_WEB_EXTENSIONS_DIR);
-
WebViewTest::add("WebKitFrame", "main-frame", testWebKitFrameMainFrame);
WebViewTest::add("WebKitFrame", "uri", testWebKitFrameURI);
WebViewTest::add("WebKitFrame", "javascript-context", testWebKitFrameJavaScriptContext);
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspector.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspector.cpp
index 1f0430389..3d993e24f 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspector.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspector.cpp
@@ -21,7 +21,7 @@
#include "WebViewTest.h"
#include <wtf/Vector.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
class InspectorTest: public WebViewTest {
public:
@@ -125,10 +125,22 @@ public:
g_main_loop_run(m_mainLoop);
}
+ static void canAttachChanged(InspectorTest* test)
+ {
+ g_main_loop_quit(test->m_mainLoop);
+ }
+
void resizeViewAndAttach()
{
// Resize the view to make room for the inspector.
- resizeView(gMinimumAttachedInspectorWidth, (gMinimumAttachedInspectorHeight + 1) * 4 / 3);
+ if (!webkit_web_inspector_get_can_attach(m_inspector)) {
+ unsigned long handler = g_signal_connect_swapped(m_inspector, "notify::can-attach", G_CALLBACK(canAttachChanged), this);
+ resizeView(gMinimumAttachedInspectorWidth, (gMinimumAttachedInspectorHeight + 1) * 4 / 3);
+ g_main_loop_run(m_mainLoop);
+ g_signal_handler_disconnect(m_inspector, handler);
+ }
+
+ g_assert(webkit_web_inspector_get_can_attach(m_inspector));
webkit_web_inspector_attach(m_inspector);
}
@@ -167,6 +179,7 @@ static void testInspectorDefault(InspectorTest* test, gconstpointer)
test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(inspectorView.get()));
g_assert(!webkit_web_inspector_is_attached(test->m_inspector));
g_assert_cmpuint(webkit_web_inspector_get_attached_height(test->m_inspector), ==, 0);
+ g_assert(!webkit_web_inspector_get_can_attach(test->m_inspector));
Vector<InspectorTest::InspectorEvents>& events = test->m_events;
g_assert_cmpint(events.size(), ==, 1);
g_assert_cmpint(events[0], ==, InspectorTest::OpenWindow);
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspectorServer.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspectorServer.cpp
index 58fefea5e..bbdd104c5 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspectorServer.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestInspectorServer.cpp
@@ -25,7 +25,7 @@
#include "config.h"
#include "WebViewTest.h"
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
#include <wtf/text/WTFString.h>
// Name of the test server application creating the webView object.
@@ -237,12 +237,10 @@ static void openRemoteDebuggingSession(InspectorServerTest* test, gconstpointer)
test->loadURI(resolvedURL.utf8().data());
test->waitUntilLoadFinished();
- javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.document.getElementsByTagName('li')[0].title", &error.outPtr());
- g_assert(javascriptResult);
- g_assert(!error.get());
-
- GUniquePtr<char> title(WebViewTest::javascriptResultToCString(javascriptResult));
- g_assert_cmpstr(title.get(), ==, "http://127.0.0.1:2999/");
+ const char* title = webkit_web_view_get_title(test->m_webView);
+ if (!title || !*title)
+ test->waitUntilTitleChanged();
+ g_assert_cmpstr(webkit_web_view_get_title(test->m_webView), ==, "127.0.0.1");
}
static void sendIncompleteRequest(InspectorServerTest* test, gconstpointer)
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestLoaderClient.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestLoaderClient.cpp
index 331915e00..7dd69f5f9 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestLoaderClient.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestLoaderClient.cpp
@@ -27,6 +27,7 @@
#include "WebViewTest.h"
#include <gtk/gtk.h>
#include <libsoup/soup.h>
+#include <wtf/Vector.h>
#include <wtf/text/CString.h>
static WebKitTestBus* bus;
@@ -82,6 +83,13 @@ static void testLoadAlternateHTML(LoadTrackingTest* test, gconstpointer)
assertNormalLoadHappened(test->m_loadEvents);
}
+static void testLoadAlternateHTMLForLocalPage(LoadTrackingTest* test, gconstpointer)
+{
+ test->loadAlternateHTML("<html><body>Alternate page</body></html>", "file:///not/actually/loaded.html", 0);
+ test->waitUntilLoadFinished();
+ assertNormalLoadHappened(test->m_loadEvents);
+}
+
static void testLoadPlainText(LoadTrackingTest* test, gconstpointer)
{
test->loadPlainText("Hello WebKit-GTK+");
@@ -89,6 +97,18 @@ static void testLoadPlainText(LoadTrackingTest* test, gconstpointer)
assertNormalLoadHappened(test->m_loadEvents);
}
+static void testLoadBytes(LoadTrackingTest* test, gconstpointer)
+{
+ GUniquePtr<char> filePath(g_build_filename(Test::getResourcesDir().data(), "blank.ico", nullptr));
+ char* contents;
+ gsize contentsLength;
+ g_file_get_contents(filePath.get(), &contents, &contentsLength, nullptr);
+ GRefPtr<GBytes> bytes = adoptGRef(g_bytes_new_take(contents, contentsLength));
+ test->loadBytes(bytes.get(), "image/vnd.microsoft.icon", nullptr, nullptr);
+ test->waitUntilLoadFinished();
+ assertNormalLoadHappened(test->m_loadEvents);
+}
+
static void testLoadRequest(LoadTrackingTest* test, gconstpointer)
{
GRefPtr<WebKitURIRequest> request(webkit_uri_request_new(kServer->getURIForPath("/normal").data()));
@@ -97,6 +117,14 @@ static void testLoadRequest(LoadTrackingTest* test, gconstpointer)
assertNormalLoadHappened(test->m_loadEvents);
}
+static void testLoadFromGResource(LoadTrackingTest* test, gconstpointer)
+{
+ GRefPtr<WebKitURIRequest> request(webkit_uri_request_new("resource:///org/webkit/webkit2gtk/tests/boring.html"));
+ test->loadRequest(request.get());
+ test->waitUntilLoadFinished();
+ assertNormalLoadHappened(test->m_loadEvents);
+}
+
class LoadStopTrackingTest : public LoadTrackingTest {
public:
MAKE_GLIB_TEST_FIXTURE(LoadStopTrackingTest);
@@ -182,51 +210,100 @@ public:
static void uriChanged(GObject*, GParamSpec*, ViewURITrackingTest* test)
{
- g_assert_cmpstr(test->m_activeURI.data(), !=, webkit_web_view_get_uri(test->m_webView));
- test->m_activeURI = webkit_web_view_get_uri(test->m_webView);
+ g_assert_cmpstr(test->m_currentURI.data(), !=, webkit_web_view_get_uri(test->m_webView));
+ test->m_currentURI = webkit_web_view_get_uri(test->m_webView);
}
ViewURITrackingTest()
- : m_activeURI(webkit_web_view_get_uri(m_webView))
+ : m_currentURI(webkit_web_view_get_uri(m_webView))
{
- g_assert(m_activeURI.isNull());
+ g_assert(m_currentURI.isNull());
+ m_currentURIList.grow(m_currentURIList.capacity());
g_signal_connect(m_webView, "notify::uri", G_CALLBACK(uriChanged), this);
}
+ enum State { Provisional, ProvisionalAfterRedirect, Commited, Finished };
+
+ void loadURI(const char* uri)
+ {
+ reset();
+ LoadTrackingTest::loadURI(uri);
+ }
+
void provisionalLoadStarted()
{
- checkActiveURI("/redirect");
+ m_currentURIList[Provisional] = m_currentURI;
}
void provisionalLoadReceivedServerRedirect()
{
- checkActiveURI("/normal");
+ m_currentURIList[ProvisionalAfterRedirect] = m_currentURI;
}
void loadCommitted()
{
- checkActiveURI("/normal");
+ m_currentURIList[Commited] = m_currentURI;
}
void loadFinished()
{
- checkActiveURI("/normal");
+ m_currentURIList[Finished] = m_currentURI;
LoadTrackingTest::loadFinished();
}
- CString m_activeURI;
+ void checkURIAtState(State state, const char* path)
+ {
+ if (path)
+ ASSERT_CMP_CSTRING(m_currentURIList[state], ==, kServer->getURIForPath(path));
+ else
+ g_assert(m_currentURIList[state].isNull());
+ }
private:
- void checkActiveURI(const char* uri)
+ void reset()
{
- ASSERT_CMP_CSTRING(m_activeURI, ==, kServer->getURIForPath(uri));
+ m_currentURI = CString();
+ m_currentURIList.clear();
+ m_currentURIList.grow(m_currentURIList.capacity());
}
+
+ CString m_currentURI;
+ Vector<CString, 4> m_currentURIList;
};
static void testWebViewActiveURI(ViewURITrackingTest* test, gconstpointer)
{
+ // Normal load, the URL doesn't change.
+ test->loadURI(kServer->getURIForPath("/normal1").data());
+ test->waitUntilLoadFinished();
+ test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/normal1");
+ test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr);
+ test->checkURIAtState(ViewURITrackingTest::State::Commited, "/normal1");
+ test->checkURIAtState(ViewURITrackingTest::State::Finished, "/normal1");
+
+ // Redirect, the URL changes after the redirect.
test->loadURI(kServer->getURIForPath("/redirect").data());
test->waitUntilLoadFinished();
+ test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect");
+ test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, "/normal");
+ test->checkURIAtState(ViewURITrackingTest::State::Commited, "/normal");
+ test->checkURIAtState(ViewURITrackingTest::State::Finished, "/normal");
+
+ // Normal load, URL changed by WebKitPage::send-request.
+ test->loadURI(kServer->getURIForPath("/normal-change-request").data());
+ test->waitUntilLoadFinished();
+ test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/normal-change-request");
+ test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, nullptr);
+ test->checkURIAtState(ViewURITrackingTest::State::Commited, "/request-changed");
+ test->checkURIAtState(ViewURITrackingTest::State::Finished, "/request-changed");
+
+ // Redirect, URL changed by WebKitPage::send-request.
+ test->loadURI(kServer->getURIForPath("/redirect-to-change-request").data());
+ test->waitUntilLoadFinished();
+ test->checkURIAtState(ViewURITrackingTest::State::Provisional, "/redirect-to-change-request");
+ test->checkURIAtState(ViewURITrackingTest::State::ProvisionalAfterRedirect, "/normal-change-request");
+ test->checkURIAtState(ViewURITrackingTest::State::Commited, "/request-changed-on-redirect");
+ test->checkURIAtState(ViewURITrackingTest::State::Finished, "/request-changed-on-redirect");
}
class ViewIsLoadingTest: public LoadTrackingTest {
@@ -303,7 +380,8 @@ public:
WebPageURITest()
{
- GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy("org.webkit.gtk.WebExtensionTest",
+ GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
+ GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
"/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", m_mainLoop));
m_uriChangedSignalID = g_dbus_connection_signal_subscribe(
g_dbus_proxy_get_connection(proxy.get()),
@@ -327,6 +405,20 @@ public:
g_dbus_connection_signal_unsubscribe(bus->connection(), m_uriChangedSignalID);
}
+ void loadURI(const char* uri)
+ {
+ m_webPageURIs.clear();
+ m_webViewURIs.clear();
+ WebViewTest::loadURI(uri);
+ }
+
+ void checkViewAndPageURIsMatch() const
+ {
+ g_assert_cmpint(m_webPageURIs.size(), ==, m_webViewURIs.size());
+ for (size_t i = 0; i < m_webPageURIs.size(); ++i)
+ ASSERT_CMP_CSTRING(m_webPageURIs[i], ==, m_webViewURIs[i]);
+ }
+
unsigned m_uriChangedSignalID;
Vector<CString> m_webPageURIs;
Vector<CString> m_webViewURIs;
@@ -334,17 +426,37 @@ public:
static void testWebPageURI(WebPageURITest* test, gconstpointer)
{
- test->loadURI(kServer->getURIForPath("/redirect").data());
+ // Normal load.
+ test->loadURI(kServer->getURIForPath("/normal1").data());
test->waitUntilLoadFinished();
+ test->checkViewAndPageURIsMatch();
+ g_assert_cmpint(test->m_webPageURIs.size(), ==, 1);
+ ASSERT_CMP_CSTRING(test->m_webPageURIs[0], ==, kServer->getURIForPath("/normal1"));
- g_assert_cmpint(test->m_webPageURIs.size(), ==, test->m_webViewURIs.size());
- for (size_t i = 0; i < test->m_webPageURIs.size(); ++i)
- ASSERT_CMP_CSTRING(test->m_webPageURIs[i], ==, test->m_webViewURIs[i]);
-
+ // Redirect
+ test->loadURI(kServer->getURIForPath("/redirect").data());
+ test->waitUntilLoadFinished();
+ test->checkViewAndPageURIsMatch();
g_assert_cmpint(test->m_webPageURIs.size(), ==, 2);
ASSERT_CMP_CSTRING(test->m_webPageURIs[0], ==, kServer->getURIForPath("/redirect"));
ASSERT_CMP_CSTRING(test->m_webPageURIs[1], ==, kServer->getURIForPath("/normal"));
+ // Normal load, URL changed by WebKitPage::send-request.
+ test->loadURI(kServer->getURIForPath("/normal-change-request").data());
+ test->waitUntilLoadFinished();
+ test->checkViewAndPageURIsMatch();
+ g_assert_cmpint(test->m_webPageURIs.size(), ==, 2);
+ ASSERT_CMP_CSTRING(test->m_webPageURIs[0], ==, kServer->getURIForPath("/normal-change-request"));
+ ASSERT_CMP_CSTRING(test->m_webPageURIs[1], ==, kServer->getURIForPath("/request-changed"));
+
+ // Redirect, URL changed by WebKitPage::send-request.
+ test->loadURI(kServer->getURIForPath("/redirect-to-change-request").data());
+ test->waitUntilLoadFinished();
+ test->checkViewAndPageURIsMatch();
+ g_assert_cmpint(test->m_webPageURIs.size(), ==, 3);
+ ASSERT_CMP_CSTRING(test->m_webPageURIs[0], ==, kServer->getURIForPath("/redirect-to-change-request"));
+ ASSERT_CMP_CSTRING(test->m_webPageURIs[1], ==, kServer->getURIForPath("/normal-change-request"));
+ ASSERT_CMP_CSTRING(test->m_webPageURIs[2], ==, kServer->getURIForPath("/request-changed-on-redirect"));
}
static void testURIRequestHTTPHeaders(WebViewTest* test, gconstpointer)
@@ -384,6 +496,53 @@ static void testURIRequestHTTPHeaders(WebViewTest* test, gconstpointer)
g_assert(!strncmp(mainResourceData, "1", mainResourceDataSize));
}
+static void testURIRequestHTTPMethod(WebViewTest* test, gconstpointer)
+{
+ GRefPtr<WebKitURIRequest> uriRequest = adoptGRef(webkit_uri_request_new("file:///foo/bar"));
+ g_assert(uriRequest.get());
+ g_assert_cmpstr(webkit_uri_request_get_uri(uriRequest.get()), ==, "file:///foo/bar");
+ g_assert(!webkit_uri_request_get_http_method(uriRequest.get()));
+
+ webkit_uri_request_set_uri(uriRequest.get(), kServer->getURIForPath("/http-get-method").data());
+ test->loadRequest(uriRequest.get());
+ test->waitUntilLoadFinished();
+
+ test->runJavaScriptAndWaitUntilFinished("xhr = new XMLHttpRequest; xhr.open('POST', '/http-post-method', false); xhr.send();", nullptr);
+}
+
+static void testURIResponseHTTPHeaders(WebViewTest* test, gconstpointer)
+{
+ test->loadHtml("<html><body>No HTTP headers</body></html>", "file:///");
+ test->waitUntilLoadFinished();
+ WebKitWebResource* resource = webkit_web_view_get_main_resource(test->m_webView);
+ g_assert(WEBKIT_IS_WEB_RESOURCE(resource));
+ WebKitURIResponse* response = webkit_web_resource_get_response(resource);
+ g_assert(WEBKIT_IS_URI_RESPONSE(response));
+ g_assert(!webkit_uri_response_get_http_headers(response));
+
+ test->loadURI(kServer->getURIForPath("/headers").data());
+ test->waitUntilLoadFinished();
+ resource = webkit_web_view_get_main_resource(test->m_webView);
+ g_assert(WEBKIT_IS_WEB_RESOURCE(resource));
+ response = webkit_web_resource_get_response(resource);
+ g_assert(WEBKIT_IS_URI_RESPONSE(response));
+ SoupMessageHeaders* headers = webkit_uri_response_get_http_headers(response);
+ g_assert(headers);
+ g_assert_cmpstr(soup_message_headers_get_one(headers, "Foo"), ==, "bar");
+}
+
+static void testRedirectToDataURI(WebViewTest* test, gconstpointer)
+{
+ test->loadURI(kServer->getURIForPath("/redirect-to-data").data());
+ test->waitUntilLoadFinished();
+
+ static const char* expectedData = "data-uri";
+ size_t mainResourceDataSize = 0;
+ const char* mainResourceData = test->mainResourceData(mainResourceDataSize);
+ g_assert_cmpint(mainResourceDataSize, ==, strlen(expectedData));
+ g_assert(!strncmp(mainResourceData, expectedData, mainResourceDataSize));
+}
+
static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
{
static const char* responseString = "<html><body>Testing!Testing!Testing!Testing!Testing!Testing!Testing!"
@@ -402,13 +561,16 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char*
soup_message_set_status(message, SOUP_STATUS_OK);
- if (g_str_has_prefix(path, "/normal"))
+ if (g_str_has_prefix(path, "/normal") || g_str_has_prefix(path, "/http-get-method"))
soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, responseString, strlen(responseString));
else if (g_str_equal(path, "/error"))
soup_message_set_status(message, SOUP_STATUS_CANT_CONNECT);
else if (g_str_equal(path, "/redirect")) {
soup_message_set_status(message, SOUP_STATUS_MOVED_PERMANENTLY);
soup_message_headers_append(message->response_headers, "Location", "/normal");
+ } else if (g_str_equal(path, "/redirect-to-change-request")) {
+ soup_message_set_status(message, SOUP_STATUS_MOVED_PERMANENTLY);
+ soup_message_headers_append(message->response_headers, "Location", "/normal-change-request");
} else if (g_str_equal(path, "/cancelled")) {
soup_message_headers_set_encoding(message->response_headers, SOUP_ENCODING_CHUNKED);
soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, responseString, strlen(responseString));
@@ -421,6 +583,12 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char*
else
soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kDNTHeaderNotPresent, strlen(kDNTHeaderNotPresent));
soup_message_set_status(message, SOUP_STATUS_OK);
+ } else if (g_str_equal(path, "/headers")) {
+ soup_message_headers_append(message->response_headers, "Foo", "bar");
+ soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, responseString, strlen(responseString));
+ } else if (g_str_equal(path, "/redirect-to-data")) {
+ soup_message_set_status(message, SOUP_STATUS_MOVED_PERMANENTLY);
+ soup_message_headers_append(message->response_headers, "Location", "data:text/plain;charset=utf-8,data-uri");
} else
soup_message_set_status(message, SOUP_STATUS_NOT_FOUND);
@@ -429,7 +597,6 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char*
void beforeAll()
{
- webkit_web_context_set_web_extensions_directory(webkit_web_context_get_default(), WEBKIT_TEST_WEB_EXTENSIONS_DIR);
bus = new WebKitTestBus();
if (!bus->run())
return;
@@ -441,8 +608,11 @@ void beforeAll()
LoadTrackingTest::add("WebKitWebView", "loading-error", testLoadingError);
LoadTrackingTest::add("WebKitWebView", "load-html", testLoadHtml);
LoadTrackingTest::add("WebKitWebView", "load-alternate-html", testLoadAlternateHTML);
+ LoadTrackingTest::add("WebKitWebView", "load-alternate-html-for-local-page", testLoadAlternateHTMLForLocalPage);
LoadTrackingTest::add("WebKitWebView", "load-plain-text", testLoadPlainText);
+ LoadTrackingTest::add("WebKitWebView", "load-bytes", testLoadBytes);
LoadTrackingTest::add("WebKitWebView", "load-request", testLoadRequest);
+ LoadTrackingTest::add("WebKitWebView", "load-gresource", testLoadFromGResource);
LoadStopTrackingTest::add("WebKitWebView", "stop-loading", testLoadCancelled);
LoadTrackingTest::add("WebKitWebView", "title", testWebViewTitle);
LoadTrackingTest::add("WebKitWebView", "progress", testLoadProgress);
@@ -456,6 +626,9 @@ void beforeAll()
ViewIsLoadingTest::add("WebKitWebView", "is-loading", testWebViewIsLoading);
WebPageURITest::add("WebKitWebPage", "get-uri", testWebPageURI);
WebViewTest::add("WebKitURIRequest", "http-headers", testURIRequestHTTPHeaders);
+ WebViewTest::add("WebKitURIRequest", "http-method", testURIRequestHTTPMethod);
+ WebViewTest::add("WebKitURIResponse", "http-headers", testURIResponseHTTPHeaders);
+ WebViewTest::add("WebKitWebPage", "redirect-to-data-uri", testRedirectToDataURI);
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestMultiprocess.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestMultiprocess.cpp
index f48b6a3b6..020ad3529 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestMultiprocess.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestMultiprocess.cpp
@@ -26,8 +26,6 @@
#include <wtf/Vector.h>
static const unsigned numViews = 2;
-static guint32 nextInitializationId = 1;
-static unsigned initializeWebExtensionsSignalCount;
static WebKitTestBus* bus;
class MultiprocessTest: public Test {
@@ -36,8 +34,18 @@ public:
MultiprocessTest()
: m_mainLoop(g_main_loop_new(nullptr, TRUE))
+ , m_initializeWebExtensionsSignalCount(0)
, m_webViewBusNames(numViews)
- , m_webViews(numViews) { }
+ , m_webViews(numViews)
+ {
+ webkit_web_context_set_process_model(m_webContext.get(), WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES);
+ }
+
+ void initializeWebExtensions() override
+ {
+ Test::initializeWebExtensions();
+ m_initializeWebExtensionsSignalCount++;
+ }
static void loadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent, MultiprocessTest* test)
{
@@ -51,11 +59,11 @@ public:
{
g_assert_cmpuint(index, <, numViews);
- m_webViewBusNames[index] = GUniquePtr<char>(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", nextInitializationId));
-
- m_webViews[index] = WEBKIT_WEB_VIEW(webkit_web_view_new());
+ m_webViews[index] = WEBKIT_WEB_VIEW(webkit_web_view_new_with_context(m_webContext.get()));
assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_webViews[index].get()));
+ m_webViewBusNames[index] = GUniquePtr<char>(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
+
webkit_web_view_load_html(m_webViews[index].get(), "<html></html>", nullptr);
g_signal_connect(m_webViews[index].get(), "load-changed", G_CALLBACK(loadChanged), this);
g_main_loop_run(m_mainLoop);
@@ -88,8 +96,6 @@ public:
void destroyWebViewAndWaitUntilWebProcessFinishes(unsigned index)
{
- // FIXME: This test is disabled because the web processed don't actually die
- // due to bug https://bugs.webkit.org/show_bug.cgi?id=129684.
g_assert_cmpuint(index, <, numViews);
unsigned watcherID = g_bus_watch_name_on_connection(bus->connection(), m_webViewBusNames[index].get(), G_BUS_NAME_WATCHER_FLAGS_NONE,
@@ -100,6 +106,7 @@ public:
}
GMainLoop* m_mainLoop;
+ unsigned m_initializeWebExtensionsSignalCount;
Vector<GUniquePtr<char>, numViews> m_webViewBusNames;
Vector<GRefPtr<WebKitWebView>, numViews> m_webViews;
};
@@ -118,7 +125,7 @@ static void testProcessPerWebView(MultiprocessTest* test, gconstpointer)
g_assert(test->m_webViewBusNames[i]);
}
- g_assert_cmpuint(initializeWebExtensionsSignalCount, ==, numViews);
+ g_assert_cmpuint(test->m_initializeWebExtensionsSignalCount, ==, numViews);
g_assert_cmpstr(test->m_webViewBusNames[0].get(), !=, test->m_webViewBusNames[1].get());
g_assert_cmpuint(test->webProcessPid(0), !=, test->webProcessPid(1));
@@ -130,7 +137,7 @@ static void testProcessPerWebView(MultiprocessTest* test, gconstpointer)
}
}
-class UIClientMultiprocessTest: public WebViewTest {
+class UIClientMultiprocessTest: public Test {
public:
MAKE_GLIB_TEST_FIXTURE(UIClientMultiprocessTest);
@@ -140,7 +147,7 @@ public:
Close
};
- static GtkWidget* viewCreateCallback(WebKitWebView* webView, UIClientMultiprocessTest* test)
+ static GtkWidget* viewCreateCallback(WebKitWebView* webView, WebKitNavigationAction*, UIClientMultiprocessTest* test)
{
return test->viewCreate(webView);
}
@@ -156,14 +163,26 @@ public:
}
UIClientMultiprocessTest()
+ : m_mainLoop(g_main_loop_new(nullptr, TRUE))
+ , m_initializeWebExtensionsSignalCount(0)
{
+ webkit_web_context_set_process_model(m_webContext.get(), WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES);
+ m_webView = WEBKIT_WEB_VIEW(g_object_ref_sink(webkit_web_view_new_with_context(m_webContext.get())));
webkit_settings_set_javascript_can_open_windows_automatically(webkit_web_view_get_settings(m_webView), TRUE);
+
g_signal_connect(m_webView, "create", G_CALLBACK(viewCreateCallback), this);
}
~UIClientMultiprocessTest()
{
g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
+ gtk_widget_destroy(GTK_WIDGET(m_webView));
+ }
+
+ void initializeWebExtensions() override
+ {
+ Test::initializeWebExtensions();
+ m_initializeWebExtensionsSignalCount++;
}
GtkWidget* viewCreate(WebKitWebView* webView)
@@ -201,16 +220,15 @@ public:
g_main_loop_run(m_mainLoop);
}
+ WebKitWebView* m_webView;
+ GMainLoop* m_mainLoop;
+ unsigned m_initializeWebExtensionsSignalCount;
Vector<WebViewEvents> m_webViewEvents;
};
static void testMultiprocessWebViewCreateReadyClose(UIClientMultiprocessTest* test, gconstpointer)
{
- // At this point the web process of the current view has already been created.
- // We save it here to check that after window.open() the number of processes
- // is the same.
- guint32 processCountBefore = nextInitializationId - 1;
- test->loadHtml("<html><body onLoad=\"window.open().close();\"></html>", nullptr);
+ webkit_web_view_load_html(test->m_webView, "<html><body onLoad=\"window.open().close();\"></html>", nullptr);
test->waitUntilNewWebViewClose();
Vector<UIClientMultiprocessTest::WebViewEvents>& events = test->m_webViewEvents;
@@ -219,23 +237,27 @@ static void testMultiprocessWebViewCreateReadyClose(UIClientMultiprocessTest* te
g_assert_cmpint(events[1], ==, UIClientMultiprocessTest::ReadyToShow);
g_assert_cmpint(events[2], ==, UIClientMultiprocessTest::Close);
- guint32 processesCountAfter = nextInitializationId - 1;
- g_assert_cmpuint(processesCountAfter, ==, processCountBefore);
+ g_assert_cmpuint(test->m_initializeWebExtensionsSignalCount, ==, 1);
}
-static void initializeWebExtensions(WebKitWebContext* context, gpointer)
+static void testWebProcessLimit(MultiprocessTest* test, gconstpointer)
{
- initializeWebExtensionsSignalCount++;
- webkit_web_context_set_web_extensions_directory(context, WEBKIT_TEST_WEB_EXTENSIONS_DIR);
- webkit_web_context_set_web_extensions_initialization_user_data(context,
- g_variant_new_uint32(nextInitializationId++));
+ g_assert_cmpuint(webkit_web_context_get_web_process_count_limit(test->m_webContext.get()), ==, 0);
+
+ webkit_web_context_set_web_process_count_limit(test->m_webContext.get(), 1);
+ g_assert_cmpuint(webkit_web_context_get_web_process_count_limit(test->m_webContext.get()), ==, 1);
+
+ // Create two web views but there should be only one web process.
+ for (unsigned i = 0; i < numViews; i++) {
+ test->loadWebViewAndWaitUntilLoaded(i);
+ g_assert(WEBKIT_IS_WEB_VIEW(test->m_webViews[i].get()));
+ }
+
+ g_assert_cmpuint(test->m_initializeWebExtensionsSignalCount, ==, 1);
}
void beforeAll()
{
- g_signal_connect(webkit_web_context_get_default(),
- "initialize-web-extensions", G_CALLBACK(initializeWebExtensions), nullptr);
-
// Check that default setting is the one stated in the documentation
g_assert_cmpuint(webkit_web_context_get_process_model(webkit_web_context_get_default()),
==, WEBKIT_PROCESS_MODEL_SHARED_SECONDARY_PROCESS);
@@ -253,11 +275,10 @@ void beforeAll()
MultiprocessTest::add("WebKitWebContext", "process-per-web-view", testProcessPerWebView);
UIClientMultiprocessTest::add("WebKitWebView", "multiprocess-create-ready-close", testMultiprocessWebViewCreateReadyClose);
+ MultiprocessTest::add("WebKitWebContext", "web-process-limit", testWebProcessLimit);
}
void afterAll()
{
delete bus;
- g_signal_handlers_disconnect_by_func(webkit_web_context_get_default(),
- reinterpret_cast<void*>(initializeWebExtensions), nullptr);
}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp
index 99efa7cfb..2b5221192 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestPrinting.cpp
@@ -20,14 +20,12 @@
#include "config.h"
#include "WebViewTest.h"
#include <glib/gstdio.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
#ifdef HAVE_GTK_UNIX_PRINTING
#include <gtk/gtkunixprint.h>
#endif
-static char* kTempDirectory;
-
static void testPrintOperationPrintSettings(WebViewTest* test, gconstpointer)
{
GRefPtr<WebKitPrintOperation> printOperation = adoptGRef(webkit_print_operation_new(test->m_webView));
@@ -134,7 +132,7 @@ static void testPrintOperationPrint(PrintTest* test, gconstpointer)
return;
}
- GUniquePtr<char> outputFilename(g_build_filename(kTempDirectory, "webkit-print.pdf", NULL));
+ GUniquePtr<char> outputFilename(g_build_filename(Test::dataDirectory(), "webkit-print.pdf", nullptr));
GRefPtr<GFile> outputFile = adoptGRef(g_file_new_for_path(outputFilename.get()));
GUniquePtr<char> outputURI(g_file_get_uri(outputFile.get()));
@@ -194,7 +192,7 @@ class CloseAfterPrintTest: public WebViewTest {
public:
MAKE_GLIB_TEST_FIXTURE(CloseAfterPrintTest);
- static GtkWidget* webViewCreate(WebKitWebView* webView, CloseAfterPrintTest* test)
+ static GtkWidget* webViewCreate(WebKitWebView* webView, WebKitNavigationAction*, CloseAfterPrintTest* test)
{
return test->createWebView();
}
@@ -228,7 +226,7 @@ public:
GtkWidget* createWebView()
{
- GtkWidget* newWebView = webkit_web_view_new();
+ GtkWidget* newWebView = webkit_web_view_new_with_context(m_webContext.get());
g_object_ref_sink(newWebView);
assertObjectIsDeletedWhenTestFinishes(G_OBJECT(newWebView));
@@ -247,7 +245,7 @@ public:
return;
}
- GUniquePtr<char> outputFilename(g_build_filename(kTempDirectory, "webkit-close-after-print.pdf", NULL));
+ GUniquePtr<char> outputFilename(g_build_filename(Test::dataDirectory(), "webkit-close-after-print.pdf", nullptr));
m_outputFile = adoptGRef(g_file_new_for_path(outputFilename.get()));
GUniquePtr<char> outputURI(g_file_get_uri(m_outputFile.get()));
@@ -288,23 +286,210 @@ static void testPrintOperationCloseAfterPrint(CloseAfterPrintTest* test, gconstp
test->loadHtml("<html><body onLoad=\"w = window.open();w.print();w.close();\"></body></html>", 0);
test->waitUntilPrintFinishedAndViewClosed();
}
+
+class PrintCustomWidgetTest: public WebViewTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(PrintCustomWidgetTest);
+
+ static void applyCallback(WebKitPrintCustomWidget*, PrintCustomWidgetTest* test)
+ {
+ test->m_applyEmitted = true;
+ }
+
+ static gboolean scheduleJumpToCustomWidget(PrintCustomWidgetTest* test)
+ {
+ test->jumpToCustomWidget();
+
+ return FALSE;
+ }
+
+ static void updateCallback(WebKitPrintCustomWidget* customWidget, GtkPageSetup*, GtkPrintSettings*, PrintCustomWidgetTest* test)
+ {
+ g_assert(test->m_widget == webkit_print_custom_widget_get_widget(customWidget));
+
+ test->m_updateEmitted = true;
+ // Would be nice to avoid the 1 second timeout here - but I didn't found
+ // a way to do so without making the test flaky.
+ g_timeout_add_seconds(1, reinterpret_cast<GSourceFunc>(scheduleJumpToCustomWidget), test);
+ }
+
+ static void widgetRealizeCallback(GtkWidget* widget, PrintCustomWidgetTest* test)
+ {
+ g_assert(GTK_IS_LABEL(widget));
+ g_assert(!g_strcmp0(gtk_label_get_text(GTK_LABEL(widget)), "Label"));
+
+ test->m_widgetRealized = true;
+ test->startPrinting();
+ }
+
+ static WebKitPrintCustomWidget* createCustomWidgetCallback(WebKitPrintOperation* printOperation, PrintCustomWidgetTest* test)
+ {
+ test->m_createEmitted = true;
+ WebKitPrintCustomWidget* printCustomWidget = test->createPrintCustomWidget();
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(printCustomWidget));
+ g_signal_connect(printCustomWidget, "apply", G_CALLBACK(applyCallback), test);
+ g_signal_connect(printCustomWidget, "update", G_CALLBACK(updateCallback), test);
+
+ GtkWidget* widget = webkit_print_custom_widget_get_widget(printCustomWidget);
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(widget));
+ g_signal_connect(widget, "realize", G_CALLBACK(widgetRealizeCallback), test);
+
+ return printCustomWidget;
+ }
+
+ static gboolean scheduleMovementThroughDialog(PrintCustomWidgetTest* test)
+ {
+ test->jumpToFirstPrinter();
+
+ return FALSE;
+ }
+
+ static gboolean openPrintDialog(PrintCustomWidgetTest* test)
+ {
+ g_idle_add(reinterpret_cast<GSourceFunc>(scheduleMovementThroughDialog), test);
+ test->m_response = webkit_print_operation_run_dialog(test->m_printOperation.get(), GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(test->m_webView))));
+
+ return FALSE;
+ }
+
+ static void printOperationFinished(WebKitPrintOperation* printOperation, PrintCustomWidgetTest* test)
+ {
+ test->printFinished();
+ }
+
+ void printFinished()
+ {
+ g_assert(m_outputFile);
+ g_file_delete(m_outputFile.get(), nullptr, nullptr);
+ m_outputFile = nullptr;
+ g_main_loop_quit(m_mainLoop);
+ }
+
+ void sendKeyEvent(unsigned gdkKeyValue, GdkEventType type, unsigned modifiers)
+ {
+ GdkEvent* event = gdk_event_new(type);
+ event->key.keyval = gdkKeyValue;
+ event->key.state = modifiers;
+ event->key.window = gtk_widget_get_window(GTK_WIDGET(m_webView));
+ event->key.time = GDK_CURRENT_TIME;
+ g_object_ref(event->key.window);
+ gdk_event_set_device(event, gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gdk_display_get_default())));
+
+ GUniqueOutPtr<GdkKeymapKey> keys;
+ gint nKeys;
+ if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), gdkKeyValue, &keys.outPtr(), &nKeys))
+ event->key.hardware_keycode = keys.get()[0].keycode;
+
+ gtk_main_do_event(event);
+
+ gdk_event_free(event);
+ }
+
+ void sendKeyPressAndReleaseEvent(unsigned gdkKeyValue, unsigned modifiers = 0)
+ {
+ sendKeyEvent(gdkKeyValue, GDK_KEY_PRESS, modifiers);
+ sendKeyEvent(gdkKeyValue, GDK_KEY_RELEASE, modifiers);
+ }
+
+ void createWebKitPrintOperation()
+ {
+ m_printOperation = adoptGRef(webkit_print_operation_new(m_webView));
+ g_assert(m_printOperation);
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_printOperation.get()));
+
+ g_signal_connect(m_printOperation.get(), "create-custom-widget", G_CALLBACK(createCustomWidgetCallback), this);
+ g_signal_connect(m_printOperation.get(), "finished", G_CALLBACK(printOperationFinished), this);
+ }
+
+ WebKitPrintCustomWidget* createPrintCustomWidget()
+ {
+ m_widget = gtk_label_new("Label");
+ return webkit_print_custom_widget_new(m_widget, "Custom Widget");
+ }
+
+ void startPrinting()
+ {
+ // To start printing it is enough to press the Return key
+ sendKeyPressAndReleaseEvent(GDK_KEY_Return);
+ }
+
+ void jumpToFirstPrinter()
+ {
+ // Initially the GtkNotebook has focus, so we just need to press the Tab
+ // key to jump to the first printer
+ sendKeyPressAndReleaseEvent(GDK_KEY_Tab);
+ }
+
+ void jumpToCustomWidget()
+ {
+ // Jump back to the GtkNotebook
+ sendKeyPressAndReleaseEvent(GDK_KEY_Tab, GDK_SHIFT_MASK);
+ // Custom widget is on the third tab
+ sendKeyPressAndReleaseEvent(GDK_KEY_Right);
+ sendKeyPressAndReleaseEvent(GDK_KEY_Right);
+ }
+
+ void openDialogMoveThroughItAndWaitUntilClosed()
+ {
+ g_idle_add(reinterpret_cast<GSourceFunc>(openPrintDialog), this);
+ g_main_loop_run(m_mainLoop);
+ }
+
+ GRefPtr<WebKitPrintOperation> m_printOperation;
+ GRefPtr<GFile> m_outputFile;
+ GtkWidget* m_widget;
+ bool m_widgetRealized {false};
+ bool m_applyEmitted {false};
+ bool m_updateEmitted {false};
+ bool m_createEmitted {false};
+ WebKitPrintOperationResponse m_response {WEBKIT_PRINT_OPERATION_RESPONSE_CANCEL};
+};
+
+static void testPrintCustomWidget(PrintCustomWidgetTest* test, gconstpointer)
+{
+ test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL, 0, 0);
+
+ test->loadHtml("<html><body>Text</body></html>", 0);
+ test->waitUntilLoadFinished();
+
+ test->createWebKitPrintOperation();
+
+ GRefPtr<GtkPrinter> printer = adoptGRef(findPrintToFilePrinter());
+ if (!printer) {
+ g_message("%s", "Cannot test WebKitPrintOperation/print: no suitable printer found");
+ return;
+ }
+
+ GUniquePtr<char> outputFilename(g_build_filename(Test::dataDirectory(), "webkit-close-after-print.pdf", nullptr));
+ test->m_outputFile = adoptGRef(g_file_new_for_path(outputFilename.get()));
+ GUniquePtr<char> outputURI(g_file_get_uri(test->m_outputFile.get()));
+
+ GRefPtr<GtkPrintSettings> printSettings = adoptGRef(gtk_print_settings_new());
+ gtk_print_settings_set(printSettings.get(), GTK_PRINT_SETTINGS_OUTPUT_URI, outputURI.get());
+ webkit_print_operation_set_print_settings(test->m_printOperation.get(), printSettings.get());
+
+ test->openDialogMoveThroughItAndWaitUntilClosed();
+
+ g_assert(test->m_response == WEBKIT_PRINT_OPERATION_RESPONSE_PRINT);
+ g_assert(test->m_createEmitted);
+ g_assert(test->m_widgetRealized);
+ g_assert(test->m_updateEmitted);
+ g_assert(test->m_applyEmitted);
+}
#endif // HAVE_GTK_UNIX_PRINTING
void beforeAll()
{
- kTempDirectory = g_dir_make_tmp("WebKit2Tests-XXXXXX", 0);
- g_assert(kTempDirectory);
-
WebViewTest::add("WebKitPrintOperation", "printing-settings", testPrintOperationPrintSettings);
WebViewTest::add("WebKitWebView", "print", testWebViewPrint);
#ifdef HAVE_GTK_UNIX_PRINTING
PrintTest::add("WebKitPrintOperation", "print", testPrintOperationPrint);
PrintTest::add("WebKitPrintOperation", "print-errors", testPrintOperationErrors);
CloseAfterPrintTest::add("WebKitPrintOperation", "close-after-print", testPrintOperationCloseAfterPrint);
+ PrintCustomWidgetTest::add("WebKitPrintOperation", "custom-widget", testPrintCustomWidget);
#endif
}
void afterAll()
{
- g_rmdir(kTempDirectory);
}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestResources.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestResources.cpp
index 4d97846a2..1510e5d49 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestResources.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestResources.cpp
@@ -22,7 +22,8 @@
#include "WebKitTestServer.h"
#include "WebViewTest.h"
#include <wtf/Vector.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GMutexLocker.h>
+#include <wtf/glib/GRefPtr.h>
static WebKitTestServer* kServer;
@@ -189,6 +190,13 @@ public:
} else if (uri == kServer->getURIForPath("/javascript.js")) {
g_assert_cmpint(m_resourceDataSize, ==, strlen(kJavascript));
g_assert(!strncmp(m_resourceData.get(), kJavascript, m_resourceDataSize));
+ } else if (uri == kServer->getURIForPath("/blank.ico")) {
+ GUniquePtr<char> filePath(g_build_filename(Test::getResourcesDir().data(), "blank.ico", nullptr));
+ GUniqueOutPtr<char> contents;
+ gsize contentsLength;
+ g_file_get_contents(filePath.get(), &contents.outPtr(), &contentsLength, nullptr);
+ g_assert_cmpint(m_resourceDataSize, ==, contentsLength);
+ g_assert(!memcmp(m_resourceData.get(), contents.get(), contentsLength));
} else
g_assert_not_reached();
m_resourceData.reset();
@@ -417,7 +425,7 @@ static void testWebResourceMimeType(SingleResourceLoadTest* test, gconstpointer)
test->loadURI(kServer->getURIForPath("/image.html").data());
response = test->waitUntilResourceLoadFinishedAndReturnURIResponse();
- g_assert_cmpstr(webkit_uri_response_get_mime_type(response), ==, "image/vnd.microsoft.icon");
+ g_assert_cmpstr(webkit_uri_response_get_mime_type(response), ==, "image/x-icon");
test->loadURI(kServer->getURIForPath("/redirected-css.html").data());
response = test->waitUntilResourceLoadFinishedAndReturnURIResponse();
@@ -517,9 +525,7 @@ static void testWebResourceActiveURI(ResourceURITrackingTest* test, gconstpointe
static void testWebResourceGetData(ResourcesTest* test, gconstpointer)
{
test->loadURI(kServer->getURIForPath("/").data());
- // FIXME: this should be 4 instead of 3, but we don't get the css image resource
- // due to bug https://bugs.webkit.org/show_bug.cgi?id=78510.
- test->waitUntilResourcesLoaded(3);
+ test->waitUntilResourcesLoaded(4);
WebKitWebResource* resource = webkit_web_view_get_main_resource(test->m_webView);
g_assert(resource);
@@ -667,6 +673,66 @@ static void testWebResourceSendRequest(SendRequestTest* test, gconstpointer)
events.clear();
}
+static GMutex s_serverMutex;
+static const unsigned s_maxConnectionsPerHost = 6;
+
+class SyncRequestOnMaxConnsTest: public ResourcesTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(SyncRequestOnMaxConnsTest);
+
+ void resourceLoadStarted(WebKitWebResource*, WebKitURIRequest*) override
+ {
+ if (!m_resourcesToStartPending)
+ return;
+
+ if (!--m_resourcesToStartPending)
+ g_main_loop_quit(m_mainLoop);
+ }
+
+ void waitUntilResourcesStarted(unsigned requestCount)
+ {
+ m_resourcesToStartPending = requestCount;
+ g_main_loop_run(m_mainLoop);
+ }
+
+ unsigned m_resourcesToStartPending;
+};
+
+static void testWebViewSyncRequestOnMaxConns(SyncRequestOnMaxConnsTest* test, gconstpointer)
+{
+ WTF::GMutexLocker<GMutex> lock(s_serverMutex);
+ test->loadURI(kServer->getURIForPath("/sync-request-on-max-conns-0").data());
+ test->waitUntilResourcesStarted(s_maxConnectionsPerHost + 1); // s_maxConnectionsPerHost resource + main resource.
+
+ for (unsigned i = 0; i < 2; ++i) {
+ GUniquePtr<char> xhr(g_strdup_printf("xhr = new XMLHttpRequest; xhr.open('GET', '/sync-request-on-max-conns-xhr%u', false); xhr.send();", i));
+ webkit_web_view_run_javascript(test->m_webView, xhr.get(), nullptr, nullptr, nullptr);
+ }
+
+ // By default sync XHRs have a 10 seconds timeout, we don't want to wait all that so use our own timeout.
+ guint timeoutSourceID = g_timeout_add(1000, [] (gpointer) -> gboolean {
+ g_assert_not_reached();
+ return G_SOURCE_REMOVE;
+ }, nullptr);
+
+ struct UnlockServerSourceContext {
+ WTF::GMutexLocker<GMutex>& lock;
+ guint unlockServerSourceID;
+ } context = {
+ lock,
+ g_idle_add_full(G_PRIORITY_DEFAULT, [](gpointer userData) -> gboolean {
+ auto& context = *static_cast<UnlockServerSourceContext*>(userData);
+ context.unlockServerSourceID = 0;
+ context.lock.unlock();
+ return G_SOURCE_REMOVE;
+ }, &context, nullptr)
+ };
+ test->waitUntilResourcesLoaded(s_maxConnectionsPerHost + 3); // s_maxConnectionsPerHost resource + main resource + 2 XHR.
+ g_source_remove(timeoutSourceID);
+ if (context.unlockServerSourceID)
+ g_source_remove(context.unlockServerSourceID);
+}
+
static void addCacheHTTPHeadersToResponse(SoupMessage* message)
{
// The actual date doesn't really matter.
@@ -734,7 +800,7 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char*
static const char* javascriptRelativeHTML = "<html><head><script language='javascript' src='/redirected-to-cancel.js'></script></head><body></body></html>";
soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, javascriptRelativeHTML, strlen(javascriptRelativeHTML));
} else if (g_str_equal(path, "/blank.ico")) {
- GUniquePtr<char> filePath(g_build_filename(Test::getWebKit1TestResoucesDir().data(), path, NULL));
+ GUniquePtr<char> filePath(g_build_filename(Test::getResourcesDir().data(), path, nullptr));
char* contents;
gsize contentsLength;
g_file_get_contents(filePath.get(), &contents, &contentsLength, 0);
@@ -760,18 +826,37 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char*
soup_message_headers_append(message->response_headers, "Location", "/cancel-this.js");
} else if (g_str_equal(path, "/invalid.css"))
soup_message_set_status(message, SOUP_STATUS_CANT_CONNECT);
- else
+ else if (g_str_has_prefix(path, "/sync-request-on-max-conns-")) {
+ char* contents;
+ gsize contentsLength;
+ if (g_str_equal(path, "/sync-request-on-max-conns-0")) {
+ GString* imagesHTML = g_string_new("<html><body>");
+ for (unsigned i = 1; i <= s_maxConnectionsPerHost; ++i)
+ g_string_append_printf(imagesHTML, "<img src='/sync-request-on-max-conns-%u'>", i);
+ g_string_append(imagesHTML, "</body></html>");
+
+ contentsLength = imagesHTML->len;
+ contents = g_string_free(imagesHTML, FALSE);
+ } else {
+ {
+ // We don't actually need to keep the mutex, so we release it as soon as we get it.
+ WTF::GMutexLocker<GMutex> lock(s_serverMutex);
+ }
+
+ GUniquePtr<char> filePath(g_build_filename(Test::getResourcesDir().data(), "blank.ico", nullptr));
+ g_file_get_contents(filePath.get(), &contents, &contentsLength, 0);
+ }
+ soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, contents, contentsLength);
+ } else
soup_message_set_status(message, SOUP_STATUS_NOT_FOUND);
soup_message_body_complete(message->response_body);
}
void beforeAll()
{
- kServer = new WebKitTestServer();
+ kServer = new WebKitTestServer(WebKitTestServer::ServerOptions::ServerRunInThread);
kServer->run(serverCallback);
- webkit_web_context_set_web_extensions_directory(webkit_web_context_get_default(), WEBKIT_TEST_WEB_EXTENSIONS_DIR);
-
ResourcesTest::add("WebKitWebView", "resources", testWebViewResources);
SingleResourceLoadTest::add("WebKitWebResource", "loading", testWebResourceLoading);
SingleResourceLoadTest::add("WebKitWebResource", "response", testWebResourceResponse);
@@ -781,6 +866,9 @@ void beforeAll()
ResourcesTest::add("WebKitWebResource", "get-data", testWebResourceGetData);
SingleResourceLoadTest::add("WebKitWebView", "history-cache", testWebViewResourcesHistoryCache);
SendRequestTest::add("WebKitWebPage", "send-request", testWebResourceSendRequest);
+#if SOUP_CHECK_VERSION(2, 49, 91)
+ SyncRequestOnMaxConnsTest::add("WebKitWebView", "sync-request-on-max-conns", testWebViewSyncRequestOnMaxConns);
+#endif
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestSSL.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestSSL.cpp
index c3075b697..10c5e73b6 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestSSL.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestSSL.cpp
@@ -67,6 +67,10 @@ public:
static void testSSL(SSLTest* test, gconstpointer)
{
+ WebKitWebContext* context = webkit_web_view_get_context(test->m_webView);
+ WebKitTLSErrorsPolicy originalPolicy = webkit_web_context_get_tls_errors_policy(context);
+ webkit_web_context_set_tls_errors_policy(context, WEBKIT_TLS_ERRORS_POLICY_IGNORE);
+
test->loadURI(kHttpsServer->getURIForPath("/").data());
test->waitUntilLoadFinished();
g_assert(test->m_certificate);
@@ -80,6 +84,8 @@ static void testSSL(SSLTest* test, gconstpointer)
test->waitUntilLoadFinished();
g_assert(!test->m_certificate);
g_assert(!test->m_tlsErrors);
+
+ webkit_web_context_set_tls_errors_policy(context, originalPolicy);
}
class InsecureContentTest: public WebViewTest {
@@ -110,38 +116,64 @@ public:
static void testInsecureContent(InsecureContentTest* test, gconstpointer)
{
+ WebKitWebContext* context = webkit_web_view_get_context(test->m_webView);
+ WebKitTLSErrorsPolicy originalPolicy = webkit_web_context_get_tls_errors_policy(context);
+ webkit_web_context_set_tls_errors_policy(context, WEBKIT_TLS_ERRORS_POLICY_IGNORE);
+
test->loadURI(kHttpsServer->getURIForPath("/insecure-content/").data());
test->waitUntilLoadFinished();
- g_assert(test->m_insecureContentRun);
+ g_assert(!test->m_insecureContentRun);
+ // Images are currently always displayed, even bypassing mixed content settings. Check
+ // https://bugs.webkit.org/show_bug.cgi?id=142469
g_assert(test->m_insecureContentDisplayed);
+
+ webkit_web_context_set_tls_errors_policy(context, originalPolicy);
}
+static bool assertIfSSLRequestProcessed = false;
+
static void testTLSErrorsPolicy(SSLTest* test, gconstpointer)
{
WebKitWebContext* context = webkit_web_view_get_context(test->m_webView);
- // TLS errors are ignored by default.
- g_assert(webkit_web_context_get_tls_errors_policy(context) == WEBKIT_TLS_ERRORS_POLICY_IGNORE);
- test->loadURI(kHttpsServer->getURIForPath("/").data());
- test->waitUntilLoadFinished();
- g_assert(!test->m_loadFailed);
+ // TLS errors are treated as transport failures by default.
+ g_assert(webkit_web_context_get_tls_errors_policy(context) == WEBKIT_TLS_ERRORS_POLICY_FAIL);
- webkit_web_context_set_tls_errors_policy(context, WEBKIT_TLS_ERRORS_POLICY_FAIL);
+ assertIfSSLRequestProcessed = true;
test->loadURI(kHttpsServer->getURIForPath("/").data());
test->waitUntilLoadFinished();
g_assert(test->m_loadFailed);
g_assert(test->m_loadEvents.contains(LoadTrackingTest::ProvisionalLoadFailed));
g_assert(!test->m_loadEvents.contains(LoadTrackingTest::LoadCommitted));
+ assertIfSSLRequestProcessed = false;
+
+ webkit_web_context_set_tls_errors_policy(context, WEBKIT_TLS_ERRORS_POLICY_IGNORE);
+ g_assert(webkit_web_context_get_tls_errors_policy(context) == WEBKIT_TLS_ERRORS_POLICY_IGNORE);
+
+ test->m_loadFailed = false;
+ test->loadURI(kHttpsServer->getURIForPath("/").data());
+ test->waitUntilLoadFinished();
+ g_assert(!test->m_loadFailed);
+
+ webkit_web_context_set_tls_errors_policy(context, WEBKIT_TLS_ERRORS_POLICY_FAIL);
+ g_assert(webkit_web_context_get_tls_errors_policy(context) == WEBKIT_TLS_ERRORS_POLICY_FAIL);
}
static void testTLSErrorsRedirect(SSLTest* test, gconstpointer)
{
- webkit_web_context_set_tls_errors_policy(webkit_web_view_get_context(test->m_webView), WEBKIT_TLS_ERRORS_POLICY_FAIL);
+ WebKitWebContext* context = webkit_web_view_get_context(test->m_webView);
+ WebKitTLSErrorsPolicy originalPolicy = webkit_web_context_get_tls_errors_policy(context);
+ webkit_web_context_set_tls_errors_policy(context, WEBKIT_TLS_ERRORS_POLICY_FAIL);
+
+ assertIfSSLRequestProcessed = true;
test->loadURI(kHttpsServer->getURIForPath("/redirect").data());
test->waitUntilLoadFinished();
g_assert(test->m_loadFailed);
g_assert(test->m_loadEvents.contains(LoadTrackingTest::ProvisionalLoadFailed));
g_assert(!test->m_loadEvents.contains(LoadTrackingTest::LoadCommitted));
+ assertIfSSLRequestProcessed = false;
+
+ webkit_web_context_set_tls_errors_policy(context, originalPolicy);
}
static gboolean webViewAuthenticationCallback(WebKitWebView*, WebKitAuthenticationRequest* request)
@@ -153,13 +185,20 @@ static gboolean webViewAuthenticationCallback(WebKitWebView*, WebKitAuthenticati
static void testTLSErrorsHTTPAuth(SSLTest* test, gconstpointer)
{
- webkit_web_context_set_tls_errors_policy(webkit_web_view_get_context(test->m_webView), WEBKIT_TLS_ERRORS_POLICY_FAIL);
+ WebKitWebContext* context = webkit_web_view_get_context(test->m_webView);
+ WebKitTLSErrorsPolicy originalPolicy = webkit_web_context_get_tls_errors_policy(context);
+ webkit_web_context_set_tls_errors_policy(context, WEBKIT_TLS_ERRORS_POLICY_FAIL);
+
+ assertIfSSLRequestProcessed = true;
g_signal_connect(test->m_webView, "authenticate", G_CALLBACK(webViewAuthenticationCallback), NULL);
test->loadURI(kHttpsServer->getURIForPath("/auth").data());
test->waitUntilLoadFinished();
g_assert(test->m_loadFailed);
g_assert(test->m_loadEvents.contains(LoadTrackingTest::ProvisionalLoadFailed));
g_assert(!test->m_loadEvents.contains(LoadTrackingTest::LoadCommitted));
+ assertIfSSLRequestProcessed = false;
+
+ webkit_web_context_set_tls_errors_policy(context, originalPolicy);
}
class TLSErrorsTest: public SSLTest {
@@ -167,69 +206,60 @@ public:
MAKE_GLIB_TEST_FIXTURE(TLSErrorsTest);
TLSErrorsTest()
+ : m_tlsErrors(static_cast<GTlsCertificateFlags>(0))
+ , m_failingURI(nullptr)
{
- g_signal_connect(m_webView, "load-failed-with-tls-errors", G_CALLBACK(runLoadFailedWithTLSErrorsCallback), this);
}
~TLSErrorsTest()
{
- g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
- if (m_certificateInfo)
- webkit_certificate_info_free(m_certificateInfo);
- }
-
- static gboolean runLoadFailedWithTLSErrorsCallback(WebKitWebView*, WebKitCertificateInfo* info, const char* host, TLSErrorsTest* test)
- {
- test->runLoadFailedWithTLSErrors(info, host);
- return TRUE;
- }
-
- void runLoadFailedWithTLSErrors(WebKitCertificateInfo* info, const char* host)
- {
- if (m_certificateInfo)
- webkit_certificate_info_free(m_certificateInfo);
- m_certificateInfo = webkit_certificate_info_copy(info);
- m_host.reset(g_strdup(host));
- g_main_loop_quit(m_mainLoop);
+ if (m_failingURI)
+ soup_uri_free(m_failingURI);
}
- void waitUntilLoadFailedWithTLSErrors()
+ bool loadFailedWithTLSErrors(const char* failingURI, GTlsCertificate* certificate, GTlsCertificateFlags tlsErrors) override
{
- g_main_loop_run(m_mainLoop);
- }
+ LoadTrackingTest::loadFailedWithTLSErrors(failingURI, certificate, tlsErrors);
- WebKitCertificateInfo* certificateInfo()
- {
- return m_certificateInfo;
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(certificate));
+ m_certificate = certificate;
+ m_tlsErrors = tlsErrors;
+ if (m_failingURI)
+ soup_uri_free(m_failingURI);
+ m_failingURI = soup_uri_new(failingURI);
+ return true;
}
- const char* host()
- {
- return m_host.get();
- }
+ GTlsCertificate* certificate() const { return m_certificate.get(); }
+ GTlsCertificateFlags tlsErrors() const { return m_tlsErrors; }
+ const char* host() const { return m_failingURI->host; }
private:
- WebKitCertificateInfo* m_certificateInfo;
- GUniquePtr<char> m_host;
+ GRefPtr<GTlsCertificate> m_certificate;
+ GTlsCertificateFlags m_tlsErrors;
+ SoupURI* m_failingURI;
};
static void testLoadFailedWithTLSErrors(TLSErrorsTest* test, gconstpointer)
{
WebKitWebContext* context = webkit_web_view_get_context(test->m_webView);
+ WebKitTLSErrorsPolicy originalPolicy = webkit_web_context_get_tls_errors_policy(context);
webkit_web_context_set_tls_errors_policy(context, WEBKIT_TLS_ERRORS_POLICY_FAIL);
+ assertIfSSLRequestProcessed = true;
// The load-failed-with-tls-errors signal should be emitted when there is a TLS failure.
test->loadURI(kHttpsServer->getURIForPath("/test-tls/").data());
- test->waitUntilLoadFailedWithTLSErrors();
- // Test the WebKitCertificateInfo API.
- g_assert(G_IS_TLS_CERTIFICATE(webkit_certificate_info_get_tls_certificate(test->certificateInfo())));
- g_assert_cmpuint(webkit_certificate_info_get_tls_errors(test->certificateInfo()), ==, G_TLS_CERTIFICATE_UNKNOWN_CA);
+ test->waitUntilLoadFinished();
+ g_assert(G_IS_TLS_CERTIFICATE(test->certificate()));
+ g_assert_cmpuint(test->tlsErrors(), ==, G_TLS_CERTIFICATE_UNKNOWN_CA);
g_assert_cmpstr(test->host(), ==, soup_uri_get_host(kHttpsServer->baseURI()));
g_assert_cmpint(test->m_loadEvents[0], ==, LoadTrackingTest::ProvisionalLoadStarted);
- g_assert_cmpint(test->m_loadEvents[1], ==, LoadTrackingTest::LoadFinished);
+ g_assert_cmpint(test->m_loadEvents[1], ==, LoadTrackingTest::LoadFailedWithTLSErrors);
+ g_assert_cmpint(test->m_loadEvents[2], ==, LoadTrackingTest::LoadFinished);
+ assertIfSSLRequestProcessed = false;
// Test allowing an exception for this certificate on this host.
- webkit_web_context_allow_tls_certificate_for_host(context, test->certificateInfo(), test->host());
+ webkit_web_context_allow_tls_certificate_for_host(context, test->certificate(), test->host());
// The page should now load without errors.
test->loadURI(kHttpsServer->getURIForPath("/test-tls/").data());
test->waitUntilLoadFinished();
@@ -238,8 +268,76 @@ static void testLoadFailedWithTLSErrors(TLSErrorsTest* test, gconstpointer)
g_assert_cmpint(test->m_loadEvents[1], ==, LoadTrackingTest::LoadCommitted);
g_assert_cmpint(test->m_loadEvents[2], ==, LoadTrackingTest::LoadFinished);
g_assert_cmpstr(webkit_web_view_get_title(test->m_webView), ==, TLSExpectedSuccessTitle);
+
+ webkit_web_context_set_tls_errors_policy(context, originalPolicy);
}
+class TLSSubresourceTest : public WebViewTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(TLSSubresourceTest);
+
+ static void resourceLoadStartedCallback(WebKitWebView* webView, WebKitWebResource* resource, WebKitURIRequest* request, TLSSubresourceTest* test)
+ {
+ if (webkit_web_view_get_main_resource(test->m_webView) == resource)
+ return;
+
+ // Ignore favicons.
+ if (g_str_has_suffix(webkit_uri_request_get_uri(request), "favicon.ico"))
+ return;
+
+ test->subresourceLoadStarted(resource);
+ }
+
+ TLSSubresourceTest()
+ : m_tlsErrors(static_cast<GTlsCertificateFlags>(0))
+ {
+ g_signal_connect(m_webView, "resource-load-started", G_CALLBACK(resourceLoadStartedCallback), this);
+ }
+
+ static void subresourceFailedCallback(WebKitWebResource*, GError*)
+ {
+ g_assert_not_reached();
+ }
+
+ static void subresourceFailedWithTLSErrorsCallback(WebKitWebResource* resource, GTlsCertificate* certificate, GTlsCertificateFlags tlsErrors, TLSSubresourceTest* test)
+ {
+ test->subresourceFailedWithTLSErrors(resource, certificate, tlsErrors);
+ }
+
+ void subresourceLoadStarted(WebKitWebResource* resource)
+ {
+ g_signal_connect(resource, "failed", G_CALLBACK(subresourceFailedCallback), nullptr);
+ g_signal_connect(resource, "failed-with-tls-errors", G_CALLBACK(subresourceFailedWithTLSErrorsCallback), this);
+ }
+
+ void subresourceFailedWithTLSErrors(WebKitWebResource* resource, GTlsCertificate* certificate, GTlsCertificateFlags tlsErrors)
+ {
+ m_certificate = certificate;
+ m_tlsErrors = tlsErrors;
+ g_main_loop_quit(m_mainLoop);
+ }
+
+ void waitUntilSubresourceLoadFail()
+ {
+ g_main_loop_run(m_mainLoop);
+ }
+
+ GRefPtr<GTlsCertificate> m_certificate;
+ GTlsCertificateFlags m_tlsErrors;
+};
+
+static void testSubresourceLoadFailedWithTLSErrors(TLSSubresourceTest* test, gconstpointer)
+{
+ WebKitWebContext* context = webkit_web_view_get_context(test->m_webView);
+ webkit_web_context_set_tls_errors_policy(context, WEBKIT_TLS_ERRORS_POLICY_FAIL);
+
+ assertIfSSLRequestProcessed = true;
+ test->loadURI(kHttpServer->getURIForPath("/").data());
+ test->waitUntilSubresourceLoadFail();
+ g_assert(G_IS_TLS_CERTIFICATE(test->m_certificate.get()));
+ g_assert_cmpuint(test->m_tlsErrors, ==, G_TLS_CERTIFICATE_UNKNOWN_CA);
+ assertIfSSLRequestProcessed = false;
+}
static void httpsServerCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
{
@@ -248,6 +346,8 @@ static void httpsServerCallback(SoupServer* server, SoupMessage* message, const
return;
}
+ g_assert(!assertIfSSLRequestProcessed);
+
if (g_str_equal(path, "/")) {
soup_message_set_status(message, SOUP_STATUS_OK);
soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, indexHTML, strlen(indexHTML));
@@ -267,6 +367,10 @@ static void httpsServerCallback(SoupServer* server, SoupMessage* message, const
} else if (g_str_equal(path, "/auth")) {
soup_message_set_status(message, SOUP_STATUS_UNAUTHORIZED);
soup_message_headers_append(message->response_headers, "WWW-Authenticate", "Basic realm=\"HTTPS auth\"");
+ } else if (g_str_equal(path, "/style.css")) {
+ soup_message_set_status(message, SOUP_STATUS_OK);
+ static const char* styleCSS = "body { color: black; }";
+ soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, styleCSS, strlen(styleCSS));
} else
soup_message_set_status(message, SOUP_STATUS_NOT_FOUND);
}
@@ -279,7 +383,7 @@ static void httpServerCallback(SoupServer* server, SoupMessage* message, const c
}
if (g_str_equal(path, "/test-script")) {
- GUniquePtr<char> pathToFile(g_build_filename(Test::getResourcesDir().data(), "link-title.js", NULL));
+ GUniquePtr<char> pathToFile(g_build_filename(Test::getResourcesDir().data(), "link-title.js", nullptr));
char* contents;
gsize length;
g_file_get_contents(pathToFile.get(), &contents, &length, 0);
@@ -288,7 +392,7 @@ static void httpServerCallback(SoupServer* server, SoupMessage* message, const c
soup_message_set_status(message, SOUP_STATUS_OK);
soup_message_body_complete(message->response_body);
} else if (g_str_equal(path, "/test-image")) {
- GUniquePtr<char> pathToFile(g_build_filename(Test::getWebKit1TestResoucesDir().data(), "blank.ico", NULL));
+ GUniquePtr<char> pathToFile(g_build_filename(Test::getResourcesDir().data(), "blank.ico", nullptr));
char* contents;
gsize length;
g_file_get_contents(pathToFile.get(), &contents, &length, 0);
@@ -296,6 +400,12 @@ static void httpServerCallback(SoupServer* server, SoupMessage* message, const c
soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, contents, length);
soup_message_set_status(message, SOUP_STATUS_OK);
soup_message_body_complete(message->response_body);
+ } else if (g_str_equal(path, "/")) {
+ soup_message_set_status(message, SOUP_STATUS_OK);
+ char* responseHTML = g_strdup_printf("<html><head><link rel='stylesheet' href='%s' type='text/css'></head><body>SSL subresource test</body></html>",
+ kHttpsServer->getURIForPath("/style.css").data());
+ soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, responseHTML, strlen(responseHTML));
+ soup_message_body_complete(message->response_body);
} else
soup_message_set_status(message, SOUP_STATUS_NOT_FOUND);
}
@@ -310,12 +420,10 @@ void beforeAll()
SSLTest::add("WebKitWebView", "ssl", testSSL);
InsecureContentTest::add("WebKitWebView", "insecure-content", testInsecureContent);
- // In this case the order of the tests does matter because tls-errors-policy tests the default policy,
- // and expects that no exception will have been added for this certificate and host pair as is
- // done in the tls-permission-request test.
SSLTest::add("WebKitWebView", "tls-errors-policy", testTLSErrorsPolicy);
SSLTest::add("WebKitWebView", "tls-errors-redirect-to-http", testTLSErrorsRedirect);
SSLTest::add("WebKitWebView", "tls-http-auth", testTLSErrorsHTTPAuth);
+ TLSSubresourceTest::add("WebKitWebView", "tls-subresource", testSubresourceLoadFailedWithTLSErrors);
TLSErrorsTest::add("WebKitWebView", "load-failed-with-tls-errors", testLoadFailedWithTLSErrors);
}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp
index d24edc601..4c44039cc 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp
@@ -20,13 +20,14 @@
#include "config.h"
#include "WebViewTest.h"
#include <wtf/HashSet.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
#include <wtf/text/StringHash.h>
static const char* kAlertDialogMessage = "WebKitGTK+ alert dialog message";
static const char* kConfirmDialogMessage = "WebKitGTK+ confirm dialog message";
static const char* kPromptDialogMessage = "WebKitGTK+ prompt dialog message";
static const char* kPromptDialogReturnedText = "WebKitGTK+ prompt dialog returned text";
+static const char* kBeforeUnloadConfirmDialogMessage = "WebKitGTK+ beforeunload dialog message";
class UIClientTest: public WebViewTest {
public:
@@ -117,9 +118,9 @@ public:
test->m_windowPropertiesChanged.add(g_param_spec_get_name(paramSpec));
}
- static GtkWidget* viewCreateCallback(WebKitWebView* webView, UIClientTest* test)
+ static GtkWidget* viewCreateCallback(WebKitWebView* webView, WebKitNavigationAction* navigation, UIClientTest* test)
{
- return test->viewCreate(webView);
+ return test->viewCreate(webView, navigation);
}
static void viewReadyToShowCallback(WebKitWebView* webView, UIClientTest* test)
@@ -146,6 +147,9 @@ public:
case WEBKIT_SCRIPT_DIALOG_PROMPT:
g_assert_cmpstr(webkit_script_dialog_get_message(dialog), ==, kPromptDialogReturnedText);
break;
+ case WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM:
+ g_assert_not_reached();
+ break;
}
g_main_loop_quit(m_mainLoop);
@@ -165,6 +169,13 @@ public:
webkit_script_dialog_prompt_set_text(dialog, kPromptDialogReturnedText);
}
+ void scriptBeforeUnloadConfirm(WebKitScriptDialog* dialog)
+ {
+ g_assert_cmpstr(webkit_script_dialog_get_message(dialog), ==, kBeforeUnloadConfirmDialogMessage);
+ m_scriptDialogConfirmed = true;
+ webkit_script_dialog_confirm_set_confirmed(dialog, m_scriptDialogConfirmed);
+ }
+
static gboolean scriptDialog(WebKitWebView*, WebKitScriptDialog* dialog, UIClientTest* test)
{
switch (webkit_script_dialog_get_dialog_type(dialog)) {
@@ -177,6 +188,9 @@ public:
case WEBKIT_SCRIPT_DIALOG_PROMPT:
test->scriptPrompt(dialog);
break;
+ case WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM:
+ test->scriptBeforeUnloadConfirm(dialog);
+ break;
}
return TRUE;
@@ -197,6 +211,12 @@ public:
g_assert(WEBKIT_IS_PERMISSION_REQUEST(request));
test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request));
+ if (test->m_verifyMediaTypes && WEBKIT_IS_USER_MEDIA_PERMISSION_REQUEST(request)) {
+ WebKitUserMediaPermissionRequest* userMediaRequest = WEBKIT_USER_MEDIA_PERMISSION_REQUEST(request);
+ g_assert(webkit_user_media_permission_is_for_audio_device(userMediaRequest) == test->m_expectedAudioMedia);
+ g_assert(webkit_user_media_permission_is_for_video_device(userMediaRequest) == test->m_expectedVideoMedia);
+ }
+
if (test->m_allowPermissionRequests)
webkit_permission_request_allow(request);
else
@@ -205,10 +225,19 @@ public:
return TRUE;
}
+ static void permissionResultMessageReceivedCallback(WebKitUserContentManager* userContentManager, WebKitJavascriptResult* javascriptResult, UIClientTest* test)
+ {
+ test->m_permissionResult.reset(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_main_loop_quit(test->m_mainLoop);
+ }
+
UIClientTest()
: m_scriptDialogType(WEBKIT_SCRIPT_DIALOG_ALERT)
, m_scriptDialogConfirmed(true)
, m_allowPermissionRequests(false)
+ , m_verifyMediaTypes(false)
+ , m_expectedAudioMedia(false)
+ , m_expectedVideoMedia(false)
, m_mouseTargetModifiers(0)
{
webkit_settings_set_javascript_can_open_windows_automatically(webkit_web_view_get_settings(m_webView), TRUE);
@@ -216,11 +245,33 @@ public:
g_signal_connect(m_webView, "script-dialog", G_CALLBACK(scriptDialog), this);
g_signal_connect(m_webView, "mouse-target-changed", G_CALLBACK(mouseTargetChanged), this);
g_signal_connect(m_webView, "permission-request", G_CALLBACK(permissionRequested), this);
+ webkit_user_content_manager_register_script_message_handler(m_userContentManager.get(), "permission");
+ g_signal_connect(m_userContentManager.get(), "script-message-received::permission", G_CALLBACK(permissionResultMessageReceivedCallback), this);
}
~UIClientTest()
{
g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
+ g_signal_handlers_disconnect_matched(m_userContentManager.get(), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
+ webkit_user_content_manager_unregister_script_message_handler(m_userContentManager.get(), "permission");
+ }
+
+ static void tryWebViewCloseCallback(UIClientTest* test)
+ {
+ g_main_loop_quit(test->m_mainLoop);
+ }
+
+ void tryCloseAndWaitUntilClosed()
+ {
+ gulong handler = g_signal_connect_swapped(m_webView, "close", G_CALLBACK(tryWebViewCloseCallback), this);
+ // Use an idle because webkit_web_view_try_close can emit the close signal in the
+ // current run loop iteration.
+ g_idle_add([](gpointer data) -> gboolean {
+ webkit_web_view_try_close(WEBKIT_WEB_VIEW(data));
+ return G_SOURCE_REMOVE;
+ }, m_webView);
+ g_main_loop_run(m_mainLoop);
+ g_signal_handler_disconnect(m_webView, handler);
}
void waitUntilMainLoopFinishes()
@@ -228,6 +279,13 @@ public:
g_main_loop_run(m_mainLoop);
}
+ const char* waitUntilPermissionResultMessageReceived()
+ {
+ m_permissionResult = nullptr;
+ g_main_loop_run(m_mainLoop);
+ return m_permissionResult.get();
+ }
+
void setExpectedWindowProperties(const WindowProperties& windowProperties)
{
m_windowProperties = windowProperties;
@@ -240,9 +298,19 @@ public:
return m_mouseTargetHitTestResult.get();
}
- virtual GtkWidget* viewCreate(WebKitWebView* webView)
+ void simulateUserInteraction()
+ {
+ runJavaScriptAndWaitUntilFinished("document.getElementById('testInput').focus()", nullptr);
+ keyStroke(GDK_KEY_a);
+ keyStroke(GDK_KEY_b);
+ while (gtk_events_pending())
+ gtk_main_iteration();
+ }
+
+ virtual GtkWidget* viewCreate(WebKitWebView* webView, WebKitNavigationAction* navigation)
{
g_assert(webView == m_webView);
+ g_assert(navigation);
GtkWidget* newWebView = webkit_web_view_new_with_context(webkit_web_view_get_context(webView));
g_object_ref_sink(newWebView);
@@ -287,10 +355,14 @@ public:
WebKitScriptDialogType m_scriptDialogType;
bool m_scriptDialogConfirmed;
bool m_allowPermissionRequests;
+ gboolean m_verifyMediaTypes;
+ gboolean m_expectedAudioMedia;
+ gboolean m_expectedVideoMedia;
WindowProperties m_windowProperties;
HashSet<WTF::String> m_windowPropertiesChanged;
GRefPtr<WebKitHitTestResult> m_mouseTargetHitTestResult;
unsigned m_mouseTargetModifiers;
+ GUniquePtr<char> m_permissionResult;
};
static void testWebViewCreateReadyClose(UIClientTest* test, gconstpointer)
@@ -305,6 +377,91 @@ static void testWebViewCreateReadyClose(UIClientTest* test, gconstpointer)
g_assert_cmpint(events[2], ==, UIClientTest::Close);
}
+class CreateNavigationDataTest: public UIClientTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(CreateNavigationDataTest);
+
+ CreateNavigationDataTest()
+ : m_navigation(nullptr)
+ {
+ }
+
+ ~CreateNavigationDataTest()
+ {
+ clearNavigation();
+ }
+
+ void clearNavigation()
+ {
+ if (m_navigation)
+ webkit_navigation_action_free(m_navigation);
+ m_navigation = nullptr;
+ }
+
+ GtkWidget* viewCreate(WebKitWebView* webView, WebKitNavigationAction* navigation)
+ {
+ g_assert(navigation);
+ g_assert(!m_navigation);
+ m_navigation = webkit_navigation_action_copy(navigation);
+ g_main_loop_quit(m_mainLoop);
+ return nullptr;
+ }
+
+ void loadHTML(const char* html)
+ {
+ clearNavigation();
+ WebViewTest::loadHtml(html, nullptr);
+ }
+
+ void clickAndWaitUntilMainLoopFinishes(int x, int y)
+ {
+ clearNavigation();
+ clickMouseButton(x, y, 1);
+ g_main_loop_run(m_mainLoop);
+ }
+
+ WebKitNavigationAction* m_navigation;
+};
+
+static void testWebViewCreateNavigationData(CreateNavigationDataTest* test, gconstpointer)
+{
+ test->showInWindowAndWaitUntilMapped();
+
+ test->loadHTML(
+ "<html><body>"
+ "<input style=\"position:absolute; left:0; top:0; margin:0; padding:0\" type=\"button\" value=\"click to show a popup\" onclick=\"window.open('data:foo');\"/>"
+ "<a style=\"position:absolute; left:20; top:20;\" href=\"data:bar\" target=\"_blank\">popup link</a>"
+ "</body></html>");
+ test->waitUntilLoadFinished();
+
+ // Click on a button.
+ test->clickAndWaitUntilMainLoopFinishes(5, 5);
+ g_assert_cmpstr(webkit_uri_request_get_uri(webkit_navigation_action_get_request(test->m_navigation)), ==, "data:foo");
+ g_assert_cmpuint(webkit_navigation_action_get_navigation_type(test->m_navigation), ==, WEBKIT_NAVIGATION_TYPE_OTHER);
+ // FIXME: This should be button 1.
+ g_assert_cmpuint(webkit_navigation_action_get_mouse_button(test->m_navigation), ==, 0);
+ g_assert_cmpuint(webkit_navigation_action_get_modifiers(test->m_navigation), ==, 0);
+ g_assert(webkit_navigation_action_is_user_gesture(test->m_navigation));
+
+ // Click on a link.
+ test->clickAndWaitUntilMainLoopFinishes(21, 21);
+ g_assert_cmpstr(webkit_uri_request_get_uri(webkit_navigation_action_get_request(test->m_navigation)), ==, "data:bar");
+ g_assert_cmpuint(webkit_navigation_action_get_navigation_type(test->m_navigation), ==, WEBKIT_NAVIGATION_TYPE_LINK_CLICKED);
+ g_assert_cmpuint(webkit_navigation_action_get_mouse_button(test->m_navigation), ==, 1);
+ g_assert_cmpuint(webkit_navigation_action_get_modifiers(test->m_navigation), ==, 0);
+ g_assert(webkit_navigation_action_is_user_gesture(test->m_navigation));
+
+ // No user interaction.
+ test->loadHTML("<html><body onLoad=\"window.open();\"></html>");
+ test->waitUntilMainLoopFinishes();
+
+ g_assert_cmpstr(webkit_uri_request_get_uri(webkit_navigation_action_get_request(test->m_navigation)), ==, "");
+ g_assert_cmpuint(webkit_navigation_action_get_navigation_type(test->m_navigation), ==, WEBKIT_NAVIGATION_TYPE_OTHER);
+ g_assert_cmpuint(webkit_navigation_action_get_mouse_button(test->m_navigation), ==, 0);
+ g_assert_cmpuint(webkit_navigation_action_get_modifiers(test->m_navigation), ==, 0);
+ g_assert(!webkit_navigation_action_is_user_gesture(test->m_navigation));
+}
+
static gboolean checkMimeTypeForFilter(GtkFileFilter* filter, const gchar* mimeType)
{
GtkFileFilterInfo filterInfo;
@@ -323,11 +480,11 @@ public:
test->m_webViewEvents.append(RunAsModal);
}
- GtkWidget* viewCreate(WebKitWebView* webView)
+ GtkWidget* viewCreate(WebKitWebView* webView, WebKitNavigationAction* navigation)
{
g_assert(webView == m_webView);
- GtkWidget* newWebView = UIClientTest::viewCreate(webView);
+ GtkWidget* newWebView = UIClientTest::viewCreate(webView, navigation);
g_signal_connect(newWebView, "run-as-modal", G_CALLBACK(dialogRunAsModalCallback), this);
return newWebView;
}
@@ -371,28 +528,80 @@ static void testWebViewDisallowModalDialogs(ModalDialogsTest* test, gconstpointe
static void testWebViewJavaScriptDialogs(UIClientTest* test, gconstpointer)
{
+ test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL);
+
static const char* htmlOnLoadFormat = "<html><body onLoad=\"%s\"></body></html>";
static const char* jsAlertFormat = "alert('%s')";
static const char* jsConfirmFormat = "do { confirmed = confirm('%s'); } while (!confirmed); alert('confirmed');";
static const char* jsPromptFormat = "alert(prompt('%s', 'default'));";
+ static const char* htmlOnBeforeUnloadFormat =
+ "<html><body onbeforeunload=\"return beforeUnloadHandler();\"><input id=\"testInput\" type=\"text\"></input><script>function beforeUnloadHandler() { return \"%s\"; }</script></body></html>";
test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_ALERT;
GUniquePtr<char> alertDialogMessage(g_strdup_printf(jsAlertFormat, kAlertDialogMessage));
GUniquePtr<char> alertHTML(g_strdup_printf(htmlOnLoadFormat, alertDialogMessage.get()));
test->loadHtml(alertHTML.get(), 0);
test->waitUntilMainLoopFinishes();
+ webkit_web_view_stop_loading(test->m_webView);
+ test->waitUntilLoadFinished();
test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_CONFIRM;
GUniquePtr<char> confirmDialogMessage(g_strdup_printf(jsConfirmFormat, kConfirmDialogMessage));
GUniquePtr<char> confirmHTML(g_strdup_printf(htmlOnLoadFormat, confirmDialogMessage.get()));
test->loadHtml(confirmHTML.get(), 0);
test->waitUntilMainLoopFinishes();
+ webkit_web_view_stop_loading(test->m_webView);
+ test->waitUntilLoadFinished();
test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_PROMPT;
GUniquePtr<char> promptDialogMessage(g_strdup_printf(jsPromptFormat, kPromptDialogMessage));
GUniquePtr<char> promptHTML(g_strdup_printf(htmlOnLoadFormat, promptDialogMessage.get()));
test->loadHtml(promptHTML.get(), 0);
test->waitUntilMainLoopFinishes();
+ webkit_web_view_stop_loading(test->m_webView);
+ test->waitUntilLoadFinished();
+
+ test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM;
+ GUniquePtr<char> beforeUnloadDialogHTML(g_strdup_printf(htmlOnBeforeUnloadFormat, kBeforeUnloadConfirmDialogMessage));
+ test->loadHtml(beforeUnloadDialogHTML.get(), nullptr);
+ test->waitUntilLoadFinished();
+
+ // Reload should trigger onbeforeunload.
+#if 0
+ test->simulateUserInteraction();
+ // FIXME: reloading HTML data doesn't emit finished load event.
+ // See https://bugs.webkit.org/show_bug.cgi?id=139089.
+ test->m_scriptDialogConfirmed = false;
+ webkit_web_view_reload(test->m_webView);
+ test->waitUntilLoadFinished();
+ g_assert(test->m_scriptDialogConfirmed);
+#endif
+
+ // Navigation should trigger onbeforeunload.
+ test->simulateUserInteraction();
+ test->m_scriptDialogConfirmed = false;
+ test->loadHtml("<html></html>", nullptr);
+ test->waitUntilLoadFinished();
+ g_assert(test->m_scriptDialogConfirmed);
+
+ // Try close should trigger onbeforeunload.
+ test->m_scriptDialogConfirmed = false;
+ test->loadHtml(beforeUnloadDialogHTML.get(), nullptr);
+ test->waitUntilLoadFinished();
+ test->simulateUserInteraction();
+ test->tryCloseAndWaitUntilClosed();
+ g_assert(test->m_scriptDialogConfirmed);
+
+ // Try close on a page with no unload handlers should not trigger onbeforeunload,
+ // but should actually close the page.
+ test->m_scriptDialogConfirmed = false;
+ test->loadHtml("<html><body></body></html>", nullptr);
+ test->waitUntilLoadFinished();
+ // We got a onbeforeunload of the previous page.
+ g_assert(test->m_scriptDialogConfirmed);
+ test->m_scriptDialogConfirmed = false;
+ test->tryCloseAndWaitUntilClosed();
+ g_assert(!test->m_scriptDialogConfirmed);
}
static void testWebViewWindowProperties(UIClientTest* test, gconstpointer)
@@ -423,13 +632,22 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer)
test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL);
const char* linksHoveredHTML =
- "<html><body>"
+ "<html><head>"
+ " <script>"
+ " window.onload = function () {"
+ " window.getSelection().removeAllRanges();"
+ " var select_range = document.createRange();"
+ " select_range.selectNodeContents(document.getElementById('text_to_select'));"
+ " window.getSelection().addRange(select_range);"
+ " }"
+ " </script>"
+ "</head><body>"
" <a style='position:absolute; left:1; top:1' href='http://www.webkitgtk.org' title='WebKitGTK+ Title'>WebKitGTK+ Website</a>"
" <img style='position:absolute; left:1; top:10' src='0xdeadbeef' width=5 height=5></img>"
" <a style='position:absolute; left:1; top:20' href='http://www.webkitgtk.org/logo' title='WebKitGTK+ Logo'><img src='0xdeadbeef' width=5 height=5></img></a>"
" <input style='position:absolute; left:1; top:30' size='10'></input>"
- " <div style='position:absolute; left:1; top:50; width:30; height:30; overflow:scroll'>&nbsp;</div>"
" <video style='position:absolute; left:1; top:100' width='300' height='300' controls='controls' preload='none'><source src='movie.ogg' type='video/ogg' /></video>"
+ " <p style='position:absolute; left:1; top:120' id='text_to_select'>Lorem ipsum.</p>"
"</body></html>";
test->loadHtml(linksHoveredHTML, "file:///");
@@ -441,6 +659,7 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer)
g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
g_assert_cmpstr(webkit_hit_test_result_get_link_uri(hitTestResult), ==, "http://www.webkitgtk.org/");
g_assert_cmpstr(webkit_hit_test_result_get_link_title(hitTestResult), ==, "WebKitGTK+ Title");
g_assert_cmpstr(webkit_hit_test_result_get_link_label(hitTestResult), ==, "WebKitGTK+ Website");
@@ -452,6 +671,7 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer)
g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
g_assert(!test->m_mouseTargetModifiers);
// Move over image with GDK_CONTROL_MASK.
@@ -460,6 +680,7 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer)
g_assert(webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_scrollbar(hitTestResult));
g_assert_cmpstr(webkit_hit_test_result_get_image_uri(hitTestResult), ==, "file:///0xdeadbeef");
g_assert(test->m_mouseTargetModifiers & GDK_CONTROL_MASK);
@@ -471,6 +692,7 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer)
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_scrollbar(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
g_assert_cmpstr(webkit_hit_test_result_get_link_uri(hitTestResult), ==, "http://www.webkitgtk.org/logo");
g_assert_cmpstr(webkit_hit_test_result_get_image_uri(hitTestResult), ==, "file:///0xdeadbeef");
g_assert_cmpstr(webkit_hit_test_result_get_link_title(hitTestResult), ==, "WebKitGTK+ Logo");
@@ -484,6 +706,7 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer)
g_assert(webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_scrollbar(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
g_assert_cmpstr(webkit_hit_test_result_get_media_uri(hitTestResult), ==, "file:///movie.ogg");
g_assert(!test->m_mouseTargetModifiers);
@@ -494,19 +717,32 @@ static void testWebViewMouseTarget(UIClientTest* test, gconstpointer)
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_scrollbar(hitTestResult));
g_assert(webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
g_assert(!test->m_mouseTargetModifiers);
// Move over scrollbar.
- hitTestResult = test->moveMouseAndWaitUntilMouseTargetChanged(5, 75);
+ hitTestResult = test->moveMouseAndWaitUntilMouseTargetChanged(gtk_widget_get_allocated_width(GTK_WIDGET(test->m_webView)) - 4, 5);
g_assert(!webkit_hit_test_result_context_is_link(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
g_assert(webkit_hit_test_result_context_is_scrollbar(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_selection(hitTestResult));
+ g_assert(!test->m_mouseTargetModifiers);
+
+ // Move over selection.
+ hitTestResult = test->moveMouseAndWaitUntilMouseTargetChanged(2, 145);
+ g_assert(!webkit_hit_test_result_context_is_link(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_image(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_media(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_editable(hitTestResult));
+ g_assert(!webkit_hit_test_result_context_is_scrollbar(hitTestResult));
+ g_assert(webkit_hit_test_result_context_is_selection(hitTestResult));
g_assert(!test->m_mouseTargetModifiers);
+
}
-static void testWebViewPermissionRequests(UIClientTest* test, gconstpointer)
+static void testWebViewGeolocationPermissionRequests(UIClientTest* test, gconstpointer)
{
// Some versions of geoclue give a runtime warning because it tries
// to register the error quark twice. See https://bugs.webkit.org/show_bug.cgi?id=89858.
@@ -518,35 +754,108 @@ static void testWebViewPermissionRequests(UIClientTest* test, gconstpointer)
" <script>"
" function runTest()"
" {"
- " navigator.geolocation.getCurrentPosition(function(p) { document.title = \"OK\" },"
- " function(e) { document.title = e.code });"
+ " navigator.geolocation.getCurrentPosition(function(p) { window.webkit.messageHandlers.permission.postMessage('OK'); },"
+ " function(e) { window.webkit.messageHandlers.permission.postMessage(e.code.toString()); });"
" }"
" </script>"
" <body onload='runTest();'></body>"
"</html>";
- // Test denying a permission request.
+ // Geolocation is not allowed from insecure connections like HTTP,
+ // POSITION_UNAVAILABLE ('2') is returned in that case without even
+ // asking the API layer.
test->m_allowPermissionRequests = false;
- test->loadHtml(geolocationRequestHTML, 0);
- test->waitUntilTitleChanged();
+ test->loadHtml(geolocationRequestHTML, "http://foo.com/bar");
+ const gchar* result = test->waitUntilPermissionResultMessageReceived();
+ g_assert_cmpstr(result, ==, "2");
- // According to the Geolocation API specification, '1' is the
- // error code returned for the PERMISSION_DENIED error.
- // http://dev.w3.org/geo/api/spec-source.html#position_error_interface
- const gchar* result = webkit_web_view_get_title(test->m_webView);
+ // Test denying a permission request. PERMISSION_DENIED ('1') is
+ // returned in this case.
+ test->m_allowPermissionRequests = false;
+ test->loadHtml(geolocationRequestHTML, "https://foo.com/bar");
+ result = test->waitUntilPermissionResultMessageReceived();
g_assert_cmpstr(result, ==, "1");
- // Test allowing a permission request.
+ // Test allowing a permission request. Result should be different
+ // to PERMISSION_DENIED ('1').
test->m_allowPermissionRequests = true;
- test->loadHtml(geolocationRequestHTML, 0);
- test->waitUntilTitleChanged();
-
- // Check that we did not get the PERMISSION_DENIED error now.
- result = webkit_web_view_get_title(test->m_webView);
+ test->loadHtml(geolocationRequestHTML, "https://foo.com/bar");
+ result = test->waitUntilPermissionResultMessageReceived();
g_assert_cmpstr(result, !=, "1");
test->addLogFatalFlag(G_LOG_LEVEL_WARNING);
}
+#if ENABLE(MEDIA_STREAM)
+static void testWebViewUserMediaPermissionRequests(UIClientTest* test, gconstpointer)
+{
+ WebKitSettings* settings = webkit_web_view_get_settings(test->m_webView);
+ gboolean enabled = webkit_settings_get_enable_media_stream(settings);
+ webkit_settings_set_enable_media_stream(settings, TRUE);
+
+ test->showInWindowAndWaitUntilMapped();
+ static const char* userMediaRequestHTML =
+ "<html>"
+ " <script>"
+ " function runTest()"
+ " {"
+ " navigator.webkitGetUserMedia({audio: true, video: true},"
+ " function(s) { document.title = \"OK\" },"
+ " function(e) { document.title = e.name });"
+ " }"
+ " </script>"
+ " <body onload='runTest();'></body>"
+ "</html>";
+
+ test->m_verifyMediaTypes = TRUE;
+ test->m_expectedAudioMedia = TRUE;
+ test->m_expectedVideoMedia = TRUE;
+
+ // Test denying a permission request.
+ test->m_allowPermissionRequests = false;
+ test->loadHtml(userMediaRequestHTML, nullptr);
+ test->waitUntilTitleChangedTo("PermissionDeniedError");
+
+ // Test allowing a permission request.
+ test->m_allowPermissionRequests = true;
+ test->loadHtml(userMediaRequestHTML, nullptr);
+ test->waitUntilTitleChangedTo("OK");
+
+ webkit_settings_set_enable_media_stream(settings, enabled);
+}
+
+static void testWebViewAudioOnlyUserMediaPermissionRequests(UIClientTest* test, gconstpointer)
+{
+ WebKitSettings* settings = webkit_web_view_get_settings(test->m_webView);
+ gboolean enabled = webkit_settings_get_enable_media_stream(settings);
+ webkit_settings_set_enable_media_stream(settings, TRUE);
+
+ test->showInWindowAndWaitUntilMapped();
+ static const char* userMediaRequestHTML =
+ "<html>"
+ " <script>"
+ " function runTest()"
+ " {"
+ " navigator.webkitGetUserMedia({audio: true, video: false},"
+ " function(s) { document.title = \"OK\" },"
+ " function(e) { document.title = e.name });"
+ " }"
+ " </script>"
+ " <body onload='runTest();'></body>"
+ "</html>";
+
+ test->m_verifyMediaTypes = TRUE;
+ test->m_expectedAudioMedia = TRUE;
+ test->m_expectedVideoMedia = FALSE;
+
+ // Test denying a permission request.
+ test->m_allowPermissionRequests = false;
+ test->loadHtml(userMediaRequestHTML, nullptr);
+ test->waitUntilTitleChangedTo("PermissionDeniedError");
+
+ webkit_settings_set_enable_media_stream(settings, enabled);
+}
+#endif // ENABLE(MEDIA_STREAM)
+
class FileChooserTest: public UIClientTest {
public:
MAKE_GLIB_TEST_FIXTURE(FileChooserTest);
@@ -662,16 +971,124 @@ static void testWebViewFileChooserRequest(FileChooserTest* test, gconstpointer)
webkit_file_chooser_request_cancel(fileChooserRequest);
}
+class ColorChooserTest: public WebViewTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(ColorChooserTest);
+
+ static gboolean runColorChooserCallback(WebKitWebView*, WebKitColorChooserRequest* request, ColorChooserTest* test)
+ {
+ test->runColorChooser(request);
+ return TRUE;
+ }
+
+ static void requestFinishedCallback(WebKitColorChooserRequest* request, ColorChooserTest* test)
+ {
+ g_assert(test->m_request.get() == request);
+ test->m_request = nullptr;
+ if (g_main_loop_is_running(test->m_mainLoop))
+ g_main_loop_quit(test->m_mainLoop);
+ }
+
+ ColorChooserTest()
+ {
+ g_signal_connect(m_webView, "run-color-chooser", G_CALLBACK(runColorChooserCallback), this);
+ }
+
+ void runColorChooser(WebKitColorChooserRequest* request)
+ {
+ g_assert(WEBKIT_IS_COLOR_CHOOSER_REQUEST(request));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request));
+ m_request = request;
+ g_signal_connect(request, "finished", G_CALLBACK(requestFinishedCallback), this);
+ g_main_loop_quit(m_mainLoop);
+ }
+
+ void finishRequest()
+ {
+ g_assert(m_request.get());
+ webkit_color_chooser_request_finish(m_request.get());
+ g_assert(!m_request);
+ }
+
+ void cancelRequest()
+ {
+ g_assert(m_request.get());
+ webkit_color_chooser_request_cancel(m_request.get());
+ g_assert(!m_request);
+ }
+
+ WebKitColorChooserRequest* clickMouseButtonAndWaitForColorChooserRequest(int x, int y)
+ {
+ clickMouseButton(x, y);
+ g_main_loop_run(m_mainLoop);
+ g_assert(m_request.get());
+ return m_request.get();
+ }
+
+private:
+ GRefPtr<WebKitColorChooserRequest> m_request;
+};
+
+static void testWebViewColorChooserRequest(ColorChooserTest* test, gconstpointer)
+{
+ static const char* colorChooserHTMLFormat = "<html><body><input style='position:absolute;left:1;top:1;margin:0;padding:0;width:45;height:25' type='color' %s/></body></html>";
+ test->showInWindowAndWaitUntilMapped();
+
+ GUniquePtr<char> defaultColorHTML(g_strdup_printf(colorChooserHTMLFormat, ""));
+ test->loadHtml(defaultColorHTML.get(), nullptr);
+ test->waitUntilLoadFinished();
+ WebKitColorChooserRequest* request = test->clickMouseButtonAndWaitForColorChooserRequest(5, 5);
+
+ // Default color is black (#000000).
+ GdkRGBA rgba1;
+ GdkRGBA rgba2 = { 0., 0., 0., 1. };
+ webkit_color_chooser_request_get_rgba(request, &rgba1);
+ g_assert(gdk_rgba_equal(&rgba1, &rgba2));
+
+ // Set a different color.
+ rgba2.green = 1;
+ webkit_color_chooser_request_set_rgba(request, &rgba2);
+ webkit_color_chooser_request_get_rgba(request, &rgba1);
+ g_assert(gdk_rgba_equal(&rgba1, &rgba2));
+
+ GdkRectangle rect;
+ webkit_color_chooser_request_get_element_rectangle(request, &rect);
+ g_assert_cmpint(rect.x, == , 1);
+ g_assert_cmpint(rect.y, == , 1);
+ g_assert_cmpint(rect.width, == , 45);
+ g_assert_cmpint(rect.height, == , 25);
+
+ test->finishRequest();
+
+ // Use an initial color.
+ GUniquePtr<char> initialColorHTML(g_strdup_printf(colorChooserHTMLFormat, "value='#FF00FF'"));
+ test->loadHtml(initialColorHTML.get(), nullptr);
+ test->waitUntilLoadFinished();
+ request = test->clickMouseButtonAndWaitForColorChooserRequest(5, 5);
+
+ webkit_color_chooser_request_get_rgba(request, &rgba1);
+ GdkRGBA rgba3 = { 1., 0., 1., 1. };
+ g_assert(gdk_rgba_equal(&rgba1, &rgba3));
+
+ test->cancelRequest();
+}
+
void beforeAll()
{
UIClientTest::add("WebKitWebView", "create-ready-close", testWebViewCreateReadyClose);
+ CreateNavigationDataTest::add("WebKitWebView", "create-navigation-data", testWebViewCreateNavigationData);
ModalDialogsTest::add("WebKitWebView", "allow-modal-dialogs", testWebViewAllowModalDialogs);
ModalDialogsTest::add("WebKitWebView", "disallow-modal-dialogs", testWebViewDisallowModalDialogs);
UIClientTest::add("WebKitWebView", "javascript-dialogs", testWebViewJavaScriptDialogs);
UIClientTest::add("WebKitWebView", "window-properties", testWebViewWindowProperties);
UIClientTest::add("WebKitWebView", "mouse-target", testWebViewMouseTarget);
- UIClientTest::add("WebKitWebView", "permission-requests", testWebViewPermissionRequests);
+ UIClientTest::add("WebKitWebView", "geolocation-permission-requests", testWebViewGeolocationPermissionRequests);
+#if ENABLE(MEDIA_STREAM)
+ UIClientTest::add("WebKitWebView", "usermedia-permission-requests", testWebViewUserMediaPermissionRequests);
+ UIClientTest::add("WebKitWebView", "audio-usermedia-permission-request", testWebViewAudioOnlyUserMediaPermissionRequests);
+#endif
FileChooserTest::add("WebKitWebView", "file-chooser-request", testWebViewFileChooserRequest);
+ ColorChooserTest::add("WebKitWebView", "color-chooser-request", testWebViewColorChooserRequest);
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebExtensions.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebExtensions.cpp
index b02cdfd03..fa4ab2d6c 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebExtensions.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebExtensions.cpp
@@ -21,19 +21,24 @@
#include "WebKitTestBus.h"
#include "WebViewTest.h"
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
static const char* webExtensionsUserData = "Web Extensions user data";
static WebKitTestBus* bus;
static GUniquePtr<char> scriptDialogResult;
+#define INPUT_ID "input-id"
+#define FORM_ID "form-id"
+#define FORM2_ID "form2-id"
+
static void testWebExtensionGetTitle(WebViewTest* test, gconstpointer)
{
test->loadHtml("<html><head><title>WebKitGTK+ Web Extensions Test</title></head><body></body></html>", 0);
test->waitUntilLoadFinished();
- GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy("org.webkit.gtk.WebExtensionTest",
- "/org/webkit/gtk/WebExtensionTest" , "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
+ GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
+ GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
+ "/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
GRefPtr<GVariant> result = adoptGRef(g_dbus_proxy_call_sync(
proxy.get(),
"GetTitle",
@@ -54,7 +59,8 @@ static void documentLoadedCallback(GDBusConnection*, const char*, const char*, c
static void testDocumentLoadedSignal(WebViewTest* test, gconstpointer)
{
- GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy("org.webkit.gtk.WebExtensionTest",
+ GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
+ GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
"/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
GDBusConnection* connection = g_dbus_proxy_get_connection(proxy.get());
guint id = g_dbus_connection_signal_subscribe(connection,
@@ -86,10 +92,13 @@ static void testWebKitWebViewProcessCrashed(WebViewTest* test, gconstpointer)
test->loadHtml("<html></html>", 0);
test->waitUntilLoadFinished();
- g_signal_connect(test->m_webView, "web-process-crashed",
+ g_signal_connect_after(test->m_webView, "web-process-crashed",
G_CALLBACK(webProcessCrashedCallback), test);
- GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy("org.webkit.gtk.WebExtensionTest",
+ test->m_expectedWebProcessCrash = true;
+
+ GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
+ GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
"/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
GRefPtr<GVariant> result = adoptGRef(g_dbus_proxy_call_sync(
@@ -100,6 +109,7 @@ static void testWebKitWebViewProcessCrashed(WebViewTest* test, gconstpointer)
-1, 0, 0));
g_assert(!result);
g_main_loop_run(test->m_mainLoop);
+ test->m_expectedWebProcessCrash = false;
}
static void testWebExtensionWindowObjectCleared(WebViewTest* test, gconstpointer)
@@ -152,7 +162,8 @@ static void testWebExtensionIsolatedWorld(WebViewTest* test, gconstpointer)
"document.getElementById('console').innerHTML = top.foo;\n"
"window.open = function () { alert('Isolated World'); }\n"
"document.open(1, 2, 3);";
- GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy("org.webkit.gtk.WebExtensionTest",
+ GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
+ GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
"/org/webkit/gtk/WebExtensionTest" , "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
g_dbus_proxy_call(proxy.get(),
"RunJavaScriptInIsolatedWorld",
@@ -173,49 +184,110 @@ static void testWebExtensionIsolatedWorld(WebViewTest* test, gconstpointer)
g_signal_handler_disconnect(test->m_webView, scriptDialogID);
}
-static void testWebExtensionInitializationUserData(WebViewTest* test, gconstpointer)
+static gboolean permissionRequestCallback(WebKitWebView*, WebKitPermissionRequest* request, WebViewTest* test)
{
- test->loadHtml("<html></html>", 0);
- test->waitUntilLoadFinished();
+ if (!WEBKIT_IS_INSTALL_MISSING_MEDIA_PLUGINS_PERMISSION_REQUEST(request))
+ return FALSE;
+
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request));
+ WebKitInstallMissingMediaPluginsPermissionRequest* missingPluginsRequest = WEBKIT_INSTALL_MISSING_MEDIA_PLUGINS_PERMISSION_REQUEST(request);
+ g_assert(webkit_install_missing_media_plugins_permission_request_get_description(missingPluginsRequest));
+ webkit_permission_request_deny(request);
+ test->quitMainLoop();
+
+ return TRUE;
+}
- GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy("org.webkit.gtk.WebExtensionTest",
+static void testInstallMissingPluginsPermissionRequest(WebViewTest* test, gconstpointer)
+{
+ GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
+ GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
"/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
+ GRefPtr<GVariant> result = adoptGRef(g_dbus_proxy_call_sync(proxy.get(), "RemoveAVPluginsFromGSTRegistry",
+ nullptr, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, nullptr));
- GRefPtr<GVariant> result = adoptGRef(g_dbus_proxy_call_sync(
- proxy.get(),
- "GetInitializationUserData",
- nullptr,
- G_DBUS_CALL_FLAGS_NONE,
- -1, 0, 0));
- g_assert(result);
+ test->showInWindowAndWaitUntilMapped();
- const gchar* userData = nullptr;
- g_variant_get(result.get(), "(&s)", &userData);
- g_assert_cmpstr(userData, ==, webExtensionsUserData);
+ gulong permissionRequestSignalID = g_signal_connect(test->m_webView, "permission-request", G_CALLBACK(permissionRequestCallback), test);
+ // FIXME: the base URI needs to finish with / to work, that shouldn't happen.
+ GUniquePtr<char> baseURI(g_strconcat("file://", Test::getResourcesDir(Test::WebKit2Resources).data(), "/", nullptr));
+ test->loadHtml("<html><body><video src=\"test.mp4\" autoplay></video></body></html>", baseURI.get());
+ g_main_loop_run(test->m_mainLoop);
+ g_signal_handler_disconnect(test->m_webView, permissionRequestSignalID);
}
-static void initializeWebExtensions(WebKitWebContext* context, gpointer)
+static void didAssociateFormControlsCallback(GDBusConnection*, const char*, const char*, const char*, const char*, GVariant* result, WebViewTest* test)
{
- webkit_web_context_set_web_extensions_directory(context, WEBKIT_TEST_WEB_EXTENSIONS_DIR);
- webkit_web_context_set_web_extensions_initialization_user_data(context,
- g_variant_new("&s", webExtensionsUserData));
+ const char* formIds;
+ g_variant_get(result, "(&s)", &formIds);
+ g_assert(!g_strcmp0(formIds, FORM_ID FORM2_ID) || !g_strcmp0(formIds, INPUT_ID));
+
+ test->quitMainLoop();
}
-void beforeAll()
+static void testWebExtensionFormControlsAssociated(WebViewTest* test, gconstpointer)
{
- g_signal_connect(webkit_web_context_get_default(),
- "initialize-web-extensions", G_CALLBACK(initializeWebExtensions), nullptr);
+ GUniquePtr<char> extensionBusName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", Test::s_webExtensionID));
+ GRefPtr<GDBusProxy> proxy = adoptGRef(bus->createProxy(extensionBusName.get(),
+ "/org/webkit/gtk/WebExtensionTest", "org.webkit.gtk.WebExtensionTest", test->m_mainLoop));
+ GDBusConnection* connection = g_dbus_proxy_get_connection(proxy.get());
+ guint id = g_dbus_connection_signal_subscribe(connection,
+ nullptr,
+ "org.webkit.gtk.WebExtensionTest",
+ "FormControlsAssociated",
+ "/org/webkit/gtk/WebExtensionTest",
+ nullptr,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ reinterpret_cast<GDBusSignalCallback>(didAssociateFormControlsCallback),
+ test,
+ nullptr);
+ g_assert(id);
+
+ test->loadHtml("<!DOCTYPE html><head><title>WebKitGTK+ Web Extensions Test</title></head><div id=\"placeholder\"/>", 0);
+ test->waitUntilLoadFinished();
+
+ static const char* addFormScript =
+ "var input = document.createElement(\"input\");"
+ "input.id = \"" INPUT_ID "\";"
+ "input.type = \"password\";"
+ "var form = document.createElement(\"form\");"
+ "form.id = \"" FORM_ID "\";"
+ "form.appendChild(input);"
+ "var form2 = document.createElement(\"form\");"
+ "form2.id = \"" FORM2_ID "\";"
+ "var placeholder = document.getElementById(\"placeholder\");"
+ "placeholder.appendChild(form);"
+ "placeholder.appendChild(form2);";
+
+ webkit_web_view_run_javascript(test->m_webView, addFormScript, nullptr, nullptr, nullptr);
+ g_main_loop_run(test->m_mainLoop);
+
+ static const char* moveFormElementScript =
+ "var form = document.getElementById(\"" FORM_ID "\");"
+ "var form2 = document.getElementById(\"" FORM2_ID "\");"
+ "var input = document.getElementById(\"" INPUT_ID "\");"
+ "form.removeChild(input);"
+ "form2.appendChild(input);";
+
+ webkit_web_view_run_javascript(test->m_webView, moveFormElementScript, nullptr, nullptr, nullptr);
+ g_main_loop_run(test->m_mainLoop);
+ g_dbus_connection_signal_unsubscribe(connection, id);
+}
+
+void beforeAll()
+{
bus = new WebKitTestBus();
if (!bus->run())
return;
- WebViewTest::add("WebKitWebContext", "initialization-user-data", testWebExtensionInitializationUserData);
WebViewTest::add("WebKitWebExtension", "dom-document-title", testWebExtensionGetTitle);
WebViewTest::add("WebKitWebExtension", "document-loaded-signal", testDocumentLoadedSignal);
WebViewTest::add("WebKitWebView", "web-process-crashed", testWebKitWebViewProcessCrashed);
WebViewTest::add("WebKitWebExtension", "window-object-cleared", testWebExtensionWindowObjectCleared);
WebViewTest::add("WebKitWebExtension", "isolated-world", testWebExtensionIsolatedWorld);
+ WebViewTest::add("WebKitWebView", "install-missing-plugins-permission-request", testInstallMissingPluginsPermissionRequest);
+ WebViewTest::add("WebKitWebExtension", "form-controls-associated-signal", testWebExtensionFormControlsAssociated);
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitAccessibility.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitAccessibility.cpp
index a5d8df9de..9c6bbdd7c 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitAccessibility.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitAccessibility.cpp
@@ -32,9 +32,8 @@ extern "C" {
#include <glib.h>
#include <signal.h>
#include <unistd.h>
-#include <wtf/PassRefPtr.h>
-#include <wtf/gobject/GRefPtr.h>
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/glib/GUniquePtr.h>
// Name of the test server application creating the webView object.
static const char* kTestServerAppName = "AccessibilityTestServer";
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFaviconDatabase.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFaviconDatabase.cpp
index 0f5a82042..5a3b057fd 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFaviconDatabase.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFaviconDatabase.cpp
@@ -23,21 +23,19 @@
#include "WebViewTest.h"
#include <glib/gstdio.h>
#include <libsoup/soup.h>
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GUniquePtr.h>
static WebKitTestServer* kServer;
-static char* kTempDirectory;
class FaviconDatabaseTest: public WebViewTest {
public:
MAKE_GLIB_TEST_FIXTURE(FaviconDatabaseTest);
FaviconDatabaseTest()
- : m_webContext(webkit_web_context_get_default())
- , m_favicon(0)
+ : m_favicon(nullptr)
, m_faviconNotificationReceived(false)
{
- WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(m_webContext);
+ WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(m_webContext.get());
g_signal_connect(database, "favicon-changed", G_CALLBACK(faviconChangedCallback), this);
}
@@ -46,7 +44,7 @@ public:
if (m_favicon)
cairo_surface_destroy(m_favicon);
- WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(m_webContext);
+ WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(m_webContext.get());
g_signal_handlers_disconnect_matched(database, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
}
@@ -67,7 +65,7 @@ public:
static void getFaviconCallback(GObject* sourceObject, GAsyncResult* result, void* data)
{
FaviconDatabaseTest* test = static_cast<FaviconDatabaseTest*>(data);
- WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(test->m_webContext);
+ WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(test->m_webContext.get());
test->m_favicon = webkit_favicon_database_get_favicon_finish(database, result, &test->m_error.outPtr());
test->quitMainLoop();
}
@@ -87,12 +85,11 @@ public:
m_favicon = 0;
}
- WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(m_webContext);
+ WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(m_webContext.get());
webkit_favicon_database_get_favicon(database, pageURI, 0, getFaviconCallback, this);
g_main_loop_run(m_mainLoop);
}
- WebKitWebContext* m_webContext;
cairo_surface_t* m_favicon;
CString m_faviconURI;
GUniqueOutPtr<GError> m_error;
@@ -116,7 +113,7 @@ serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHash
char* contents;
gsize length;
if (g_str_equal(path, "/icon/favicon.ico")) {
- GUniquePtr<char> pathToFavicon(g_build_filename(Test::getWebKit1TestResoucesDir().data(), "blank.ico", NULL));
+ GUniquePtr<char> pathToFavicon(g_build_filename(Test::getResourcesDir().data(), "blank.ico", nullptr));
g_file_get_contents(pathToFavicon.get(), &contents, &length, 0);
soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, contents, length);
} else if (g_str_equal(path, "/nofavicon")) {
@@ -142,19 +139,43 @@ static void testNotInitialized(FaviconDatabaseTest* test)
static void testSetDirectory(FaviconDatabaseTest* test)
{
- webkit_web_context_set_favicon_database_directory(test->m_webContext, kTempDirectory);
- g_assert_cmpstr(kTempDirectory, ==, webkit_web_context_get_favicon_database_directory(test->m_webContext));
+ webkit_web_context_set_favicon_database_directory(test->m_webContext.get(), Test::dataDirectory());
+ g_assert_cmpstr(Test::dataDirectory(), ==, webkit_web_context_get_favicon_database_directory(test->m_webContext.get()));
}
static void testClearDatabase(FaviconDatabaseTest* test)
{
- WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(test->m_webContext);
+ WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(test->m_webContext.get());
webkit_favicon_database_clear(database);
GUniquePtr<char> iconURI(webkit_favicon_database_get_favicon_uri(database, kServer->getURIForPath("/foo").data()));
g_assert(!iconURI);
}
+static void ephemeralViewLoadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent, WebViewTest* test)
+{
+ if (loadEvent != WEBKIT_LOAD_FINISHED)
+ return;
+ g_signal_handlers_disconnect_by_func(webView, reinterpret_cast<void*>(ephemeralViewLoadChanged), test);
+ test->quitMainLoop();
+}
+
+static void testPrivateBrowsing(FaviconDatabaseTest* test)
+{
+ GRefPtr<WebKitWebView> webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW,
+ "web-context", test->m_webContext.get(),
+ "is-ephemeral", TRUE,
+ nullptr));
+ g_signal_connect(webView.get(), "load-changed", G_CALLBACK(ephemeralViewLoadChanged), test);
+ webkit_web_view_load_uri(webView.get(), kServer->getURIForPath("/foo").data());
+ g_main_loop_run(test->m_mainLoop);
+
+ // An ephemeral web view should not write to the database.
+ test->getFaviconForPageURIAndWaitUntilReady(kServer->getURIForPath("/foo").data());
+ g_assert(!test->m_favicon);
+ g_assert(test->m_error);
+}
+
static void testGetFavicon(FaviconDatabaseTest* test)
{
// We need to load the page first to ensure the icon data will be
@@ -198,7 +219,7 @@ static void testGetFavicon(FaviconDatabaseTest* test)
static void testGetFaviconURI(FaviconDatabaseTest* test)
{
- WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(test->m_webContext);
+ WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(test->m_webContext.get());
CString baseURI = kServer->getURIForPath("/foo");
GUniquePtr<char> iconURI(webkit_favicon_database_get_favicon_uri(database, baseURI.data()));
@@ -231,6 +252,7 @@ static void testFaviconDatabase(FaviconDatabaseTest* test, gconstpointer)
// See https://bugs.webkit.org/show_bug.cgi?id=111434.
testNotInitialized(test);
testSetDirectory(test);
+ testPrivateBrowsing(test);
testGetFavicon(test);
testGetFaviconURI(test);
testWebViewFavicon(test);
@@ -243,30 +265,11 @@ void beforeAll()
kServer = new WebKitTestServer();
kServer->run(serverCallback);
- kTempDirectory = g_dir_make_tmp("WebKit2Tests-XXXXXX", 0);
- g_assert(kTempDirectory);
-
// Add tests to the suite.
FaviconDatabaseTest::add("WebKitFaviconDatabase", "favicon-database-test", testFaviconDatabase);
}
-static void webkitFaviconDatabaseFinalizedCallback(gpointer, GObject*)
-{
- if (!g_file_test(kTempDirectory, G_FILE_TEST_IS_DIR))
- return;
-
- GUniquePtr<char> filename(g_build_filename(kTempDirectory, "WebpageIcons.db", nullptr));
- g_unlink(filename.get());
-
- g_rmdir(kTempDirectory);
-}
-
void afterAll()
{
delete kServer;
-
- // Delete the temporary files after the IconDatabase has been
- // closed, that is, once WebKitFaviconDatabase is being destroyed.
- WebKitFaviconDatabase* database = webkit_web_context_get_favicon_database(webkit_web_context_get_default());
- g_object_weak_ref(G_OBJECT(database), webkitFaviconDatabaseFinalizedCallback, 0);
}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFindController.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFindController.cpp
index d2eef4ca4..7289fd37f 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFindController.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitFindController.cpp
@@ -22,7 +22,7 @@
#include "LoadTrackingTest.h"
#include <gtk/gtk.h>
#include <webkit2/webkit2.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
static const char* testString = "<html><body>first testing second testing secondHalf</body></html>";
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitPolicyClient.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitPolicyClient.cpp
index 209ea045e..9f9515123 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitPolicyClient.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitPolicyClient.cpp
@@ -21,7 +21,7 @@
#include "LoadTrackingTest.h"
#include "WebKitTestServer.h"
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
#include <wtf/text/CString.h>
static WebKitTestServer* kServer;
@@ -117,11 +117,12 @@ static void testNavigationPolicy(PolicyClientTest* test, gconstpointer)
// Ideally we'd like to have a more intensive test here, but it's still pretty tricky
// to trigger different types of navigations with the GTK+ WebKit2 API.
WebKitNavigationPolicyDecision* decision = WEBKIT_NAVIGATION_POLICY_DECISION(test->m_previousPolicyDecision.get());
- g_assert_cmpint(webkit_navigation_policy_decision_get_navigation_type(decision), ==, WEBKIT_NAVIGATION_TYPE_OTHER);
- g_assert_cmpint(webkit_navigation_policy_decision_get_mouse_button(decision), ==, 0);
- g_assert_cmpint(webkit_navigation_policy_decision_get_modifiers(decision), ==, 0);
- g_assert_cmpstr(webkit_navigation_policy_decision_get_frame_name(decision), ==, 0);
- WebKitURIRequest* request = webkit_navigation_policy_decision_get_request(decision);
+ WebKitNavigationAction* navigationAction = webkit_navigation_policy_decision_get_navigation_action(decision);
+ g_assert_cmpint(webkit_navigation_action_get_navigation_type(navigationAction), ==, WEBKIT_NAVIGATION_TYPE_OTHER);
+ g_assert_cmpint(webkit_navigation_action_get_mouse_button(navigationAction), ==, 0);
+ g_assert_cmpint(webkit_navigation_action_get_modifiers(navigationAction), ==, 0);
+ g_assert(!webkit_navigation_policy_decision_get_frame_name(decision));
+ WebKitURIRequest* request = webkit_navigation_action_get_request(navigationAction);
g_assert_cmpstr(webkit_uri_request_get_uri(request), ==, "http://webkitgtk.org/");
test->m_policyDecisionResponse = PolicyClientTest::Use;
@@ -191,7 +192,7 @@ struct CreateCallbackData {
GMainLoop* mainLoop;
};
-static WebKitWebView* createCallback(WebKitWebView* webView, CreateCallbackData* data)
+static WebKitWebView* createCallback(WebKitWebView* webView, WebKitNavigationAction*, CreateCallbackData* data)
{
data->triedToOpenWindow = true;
g_main_loop_quit(data->mainLoop);
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSecurityOrigin.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSecurityOrigin.cpp
new file mode 100644
index 000000000..1cc9e7709
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSecurityOrigin.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2017 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2,1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "TestMain.h"
+#include <webkit2/webkit2.h>
+#include <wtf/glib/GUniquePtr.h>
+
+static void testSecurityOriginBasicConstructor(Test*, gconstpointer)
+{
+ WebKitSecurityOrigin* origin = webkit_security_origin_new("http", "127.0.0.1", 1234);
+ g_assert(origin);
+ GUniquePtr<char> asString(webkit_security_origin_to_string(origin));
+ g_assert_cmpstr(asString.get(), ==, "http://127.0.0.1:1234");
+ g_assert_cmpstr(webkit_security_origin_get_protocol(origin), ==, "http");
+ g_assert_cmpstr(webkit_security_origin_get_host(origin), ==, "127.0.0.1");
+ g_assert_cmpint(webkit_security_origin_get_port(origin), ==, 1234);
+ g_assert(!webkit_security_origin_is_opaque(origin));
+ webkit_security_origin_unref(origin);
+}
+
+static void testSecurityOriginURIConstructor(Test*, gconstpointer)
+{
+ WebKitSecurityOrigin* origin = webkit_security_origin_new_for_uri("http://127.0.0.1:1234");
+ g_assert(origin);
+ GUniquePtr<char> asString(webkit_security_origin_to_string(origin));
+ g_assert_cmpstr(asString.get(), ==, "http://127.0.0.1:1234");
+ g_assert_cmpstr(webkit_security_origin_get_protocol(origin), ==, "http");
+ g_assert_cmpstr(webkit_security_origin_get_host(origin), ==, "127.0.0.1");
+ g_assert_cmpint(webkit_security_origin_get_port(origin), ==, 1234);
+ g_assert(!webkit_security_origin_is_opaque(origin));
+ webkit_security_origin_unref(origin);
+
+ origin = webkit_security_origin_new_for_uri("http://127.0.0.1:1234/this/path/?should=be#ignored");
+ g_assert(origin);
+ asString.reset(webkit_security_origin_to_string(origin));
+ g_assert_cmpstr(asString.get(), ==, "http://127.0.0.1:1234");
+ g_assert_cmpstr(webkit_security_origin_get_protocol(origin), ==, "http");
+ g_assert_cmpstr(webkit_security_origin_get_host(origin), ==, "127.0.0.1");
+ g_assert_cmpint(webkit_security_origin_get_port(origin), ==, 1234);
+ g_assert(!webkit_security_origin_is_opaque(origin));
+ webkit_security_origin_unref(origin);
+}
+
+static void testSecurityOriginDefaultPort(Test*, gconstpointer)
+{
+ WebKitSecurityOrigin* origin = webkit_security_origin_new("http", "127.0.0.1", 0);
+ g_assert(origin);
+ GUniquePtr<char> asString(webkit_security_origin_to_string(origin));
+ g_assert_cmpstr(asString.get(), ==, "http://127.0.0.1");
+ g_assert_cmpstr(webkit_security_origin_get_protocol(origin), ==, "http");
+ g_assert_cmpstr(webkit_security_origin_get_host(origin), ==, "127.0.0.1");
+ g_assert_cmpint(webkit_security_origin_get_port(origin), ==, 0);
+ g_assert(!webkit_security_origin_is_opaque(origin));
+ webkit_security_origin_unref(origin);
+
+ origin = webkit_security_origin_new("http", "127.0.0.1", 80);
+ g_assert(origin);
+ asString.reset(webkit_security_origin_to_string(origin));
+ g_assert_cmpstr(asString.get(), ==, "http://127.0.0.1");
+ g_assert_cmpstr(webkit_security_origin_get_protocol(origin), ==, "http");
+ g_assert_cmpstr(webkit_security_origin_get_host(origin), ==, "127.0.0.1");
+ g_assert_cmpint(webkit_security_origin_get_port(origin), ==, 0);
+ g_assert(!webkit_security_origin_is_opaque(origin));
+ webkit_security_origin_unref(origin);
+
+ origin = webkit_security_origin_new_for_uri("http://127.0.0.1");
+ g_assert(origin);
+ asString.reset(webkit_security_origin_to_string(origin));
+ g_assert_cmpstr(asString.get(), ==, "http://127.0.0.1");
+ g_assert_cmpstr(webkit_security_origin_get_protocol(origin), ==, "http");
+ g_assert_cmpstr(webkit_security_origin_get_host(origin), ==, "127.0.0.1");
+ g_assert_cmpint(webkit_security_origin_get_port(origin), ==, 0);
+ g_assert(!webkit_security_origin_is_opaque(origin));
+ webkit_security_origin_unref(origin);
+
+ origin = webkit_security_origin_new_for_uri("http://127.0.0.1:80");
+ g_assert(origin);
+ asString.reset(webkit_security_origin_to_string(origin));
+ g_assert_cmpstr(asString.get(), ==, "http://127.0.0.1");
+ g_assert_cmpstr(webkit_security_origin_get_protocol(origin), ==, "http");
+ g_assert_cmpstr(webkit_security_origin_get_host(origin), ==, "127.0.0.1");
+ g_assert_cmpint(webkit_security_origin_get_port(origin), ==, 0);
+ g_assert(!webkit_security_origin_is_opaque(origin));
+ webkit_security_origin_unref(origin);
+}
+
+static void testSecurityOriginFileURI(Test*, gconstpointer)
+{
+ WebKitSecurityOrigin* origin = webkit_security_origin_new_for_uri("file:///abcdefg");
+ g_assert(origin);
+ GUniquePtr<char> asString(webkit_security_origin_to_string(origin));
+ g_assert_cmpstr(asString.get(), ==, "file://");
+ g_assert_cmpstr(webkit_security_origin_get_protocol(origin), ==, "file");
+ g_assert(!webkit_security_origin_get_host(origin));
+ g_assert_cmpint(webkit_security_origin_get_port(origin), ==, 0);
+ g_assert(!webkit_security_origin_is_opaque(origin));
+ webkit_security_origin_unref(origin);
+}
+
+static void testOpaqueSecurityOrigin(Test*, gconstpointer)
+{
+ WebKitSecurityOrigin* origin = webkit_security_origin_new_for_uri("data:Lali ho!");
+ g_assert(origin);
+ GUniquePtr<char> asString(webkit_security_origin_to_string(origin));
+ g_assert(!asString);
+ g_assert(!webkit_security_origin_get_protocol(origin));
+ g_assert(!webkit_security_origin_get_host(origin));
+ g_assert_cmpint(webkit_security_origin_get_port(origin), ==, 0);
+ g_assert(webkit_security_origin_is_opaque(origin));
+ webkit_security_origin_unref(origin);
+}
+
+void beforeAll()
+{
+ Test::add("WebKitSecurityOrigin", "basic-constructor", testSecurityOriginBasicConstructor);
+ Test::add("WebKitSecurityOrigin", "uri-constructor", testSecurityOriginURIConstructor);
+ Test::add("WebKitSecruityOrigin", "default-port", testSecurityOriginDefaultPort);
+ Test::add("WebKitSecurityOrigin", "file-uri", testSecurityOriginFileURI);
+ Test::add("WebKitSecruityOrigin", "opaque-origin", testOpaqueSecurityOrigin);
+}
+
+void afterAll()
+{
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSettings.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSettings.cpp
index fb1091889..db60c2fe8 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSettings.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSettings.cpp
@@ -35,7 +35,7 @@
#include "WebKitTestServer.h"
#include <gtk/gtk.h>
#include <webkit2/webkit2.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
static WebKitTestServer* gServer;
@@ -158,9 +158,11 @@ static void testWebKitSettings(Test*, gconstpointer)
webkit_settings_set_default_charset(settings, "utf8");
g_assert_cmpstr(webkit_settings_get_default_charset(settings), ==, "utf8");
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
g_assert(!webkit_settings_get_enable_private_browsing(settings));
webkit_settings_set_enable_private_browsing(settings, TRUE);
g_assert(webkit_settings_get_enable_private_browsing(settings));
+ G_GNUC_END_IGNORE_DEPRECATIONS;
g_assert(!webkit_settings_get_enable_developer_extras(settings));
webkit_settings_set_enable_developer_extras(settings, TRUE);
@@ -273,6 +275,25 @@ static void testWebKitSettings(Test*, gconstpointer)
webkit_settings_set_enable_mediasource(settings, TRUE);
g_assert(webkit_settings_get_enable_mediasource(settings));
+ // File access from file URLs is not allowed by default.
+ g_assert(!webkit_settings_get_allow_file_access_from_file_urls(settings));
+ webkit_settings_set_allow_file_access_from_file_urls(settings, TRUE);
+ g_assert(webkit_settings_get_allow_file_access_from_file_urls(settings));
+
+ // Universal access from file URLs is not allowed by default.
+ g_assert(!webkit_settings_get_allow_universal_access_from_file_urls(settings));
+ webkit_settings_set_allow_universal_access_from_file_urls(settings, TRUE);
+ g_assert(webkit_settings_get_allow_universal_access_from_file_urls(settings));
+
+ // Ondemand is the default hardware acceleration policy.
+ g_assert_cmpuint(webkit_settings_get_hardware_acceleration_policy(settings), ==, WEBKIT_HARDWARE_ACCELERATION_POLICY_ON_DEMAND);
+ webkit_settings_set_hardware_acceleration_policy(settings, WEBKIT_HARDWARE_ACCELERATION_POLICY_NEVER);
+ g_assert_cmpuint(webkit_settings_get_hardware_acceleration_policy(settings), ==, WEBKIT_HARDWARE_ACCELERATION_POLICY_NEVER);
+ webkit_settings_set_hardware_acceleration_policy(settings, WEBKIT_HARDWARE_ACCELERATION_POLICY_ALWAYS);
+ g_assert_cmpuint(webkit_settings_get_hardware_acceleration_policy(settings), ==, WEBKIT_HARDWARE_ACCELERATION_POLICY_ALWAYS);
+ webkit_settings_set_hardware_acceleration_policy(settings, WEBKIT_HARDWARE_ACCELERATION_POLICY_ON_DEMAND);
+ g_assert_cmpuint(webkit_settings_get_hardware_acceleration_policy(settings), ==, WEBKIT_HARDWARE_ACCELERATION_POLICY_ON_DEMAND);
+
g_object_unref(G_OBJECT(settings));
}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp
new file mode 100644
index 000000000..134ad3837
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2013-2014 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2,1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebKitTestServer.h"
+#include "WebViewTest.h"
+#include <cstdarg>
+#include <gtk/gtk.h>
+#include <webkit2/webkit2.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/glib/GUniquePtr.h>
+
+static WebKitTestServer* kServer;
+
+// These are all here so that they can be changed easily, if necessary.
+static const char* kStyleSheetHTML = "<html><div id=\"styledElement\">Sweet stylez!</div></html>";
+static const char* kInjectedStyleSheet = "#styledElement { font-weight: bold; }";
+static const char* kStyleSheetTestScript = "getComputedStyle(document.getElementById('styledElement'))['font-weight']";
+static const char* kStyleSheetTestScriptResult = "bold";
+static const char* kInjectedScript = "document.write('<div id=\"item\">Generated by a script</div>')";
+static const char* kScriptTestScript = "document.getElementById('item').innerText";
+static const char* kScriptTestScriptResult = "Generated by a script";
+
+static void testWebViewNewWithUserContentManager(Test* test, gconstpointer)
+{
+ GRefPtr<WebKitUserContentManager> userContentManager1 = adoptGRef(webkit_user_content_manager_new());
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(userContentManager1.get()));
+ GRefPtr<WebKitWebView> webView1 = WEBKIT_WEB_VIEW(webkit_web_view_new_with_user_content_manager(userContentManager1.get()));
+ g_assert(webkit_web_view_get_user_content_manager(webView1.get()) == userContentManager1.get());
+
+ GRefPtr<WebKitWebView> webView2 = WEBKIT_WEB_VIEW(webkit_web_view_new());
+ g_assert(webkit_web_view_get_user_content_manager(webView2.get()) != userContentManager1.get());
+}
+
+static bool isStyleSheetInjectedForURLAtPath(WebViewTest* test, const char* path)
+{
+ test->loadURI(kServer->getURIForPath(path).data());
+ test->waitUntilLoadFinished();
+
+ GUniqueOutPtr<GError> error;
+ WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished(kStyleSheetTestScript, &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error.get());
+
+ GUniquePtr<char> resultString(WebViewTest::javascriptResultToCString(javascriptResult));
+ return !g_strcmp0(resultString.get(), kStyleSheetTestScriptResult);
+}
+
+static bool isScriptInjectedForURLAtPath(WebViewTest* test, const char* path)
+{
+ test->loadURI(kServer->getURIForPath(path).data());
+ test->waitUntilLoadFinished();
+
+ GUniqueOutPtr<GError> error;
+ if (WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished(kScriptTestScript, &error.outPtr())) {
+ g_assert(!error.get());
+
+ GUniquePtr<char> resultString(WebViewTest::javascriptResultToCString(javascriptResult));
+ return !g_strcmp0(resultString.get(), kScriptTestScriptResult);
+ }
+ return false;
+}
+
+static void fillURLListFromPaths(char** list, const char* path, ...)
+{
+ va_list argumentList;
+ va_start(argumentList, path);
+
+ int i = 0;
+ while (path) {
+ // FIXME: We must use a wildcard for the host here until http://wkbug.com/112476 is fixed.
+ // Until that time patterns with port numbers in them will not properly match URLs with port numbers.
+ list[i++] = g_strdup_printf("http://*/%s*", path);
+ path = va_arg(argumentList, const char*);
+ }
+}
+
+static void removeOldInjectedContentAndResetLists(WebKitUserContentManager* userContentManager, char** whitelist, char** blacklist)
+{
+ webkit_user_content_manager_remove_all_style_sheets(userContentManager);
+ webkit_user_content_manager_remove_all_scripts(userContentManager);
+
+ while (*whitelist) {
+ g_free(*whitelist);
+ *whitelist = 0;
+ whitelist++;
+ }
+
+ while (*blacklist) {
+ g_free(*blacklist);
+ *blacklist = 0;
+ blacklist++;
+ }
+}
+
+static void testUserContentManagerInjectedStyleSheet(WebViewTest* test, gconstpointer)
+{
+ char* whitelist[3] = { 0, 0, 0 };
+ char* blacklist[3] = { 0, 0, 0 };
+
+ removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist);
+
+ // Without a whitelist or a blacklist all URLs should have the injected style sheet.
+ static const char* randomPath = "somerandompath";
+ g_assert(!isStyleSheetInjectedForURLAtPath(test, randomPath));
+ WebKitUserStyleSheet* styleSheet = webkit_user_style_sheet_new(kInjectedStyleSheet, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_STYLE_LEVEL_USER, nullptr, nullptr);
+ webkit_user_content_manager_add_style_sheet(test->m_userContentManager.get(), styleSheet);
+ webkit_user_style_sheet_unref(styleSheet);
+ g_assert(isStyleSheetInjectedForURLAtPath(test, randomPath));
+
+ removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist);
+
+ fillURLListFromPaths(blacklist, randomPath, 0);
+ styleSheet = webkit_user_style_sheet_new(kInjectedStyleSheet, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_STYLE_LEVEL_USER, nullptr, blacklist);
+ webkit_user_content_manager_add_style_sheet(test->m_userContentManager.get(), styleSheet);
+ webkit_user_style_sheet_unref(styleSheet);
+ g_assert(!isStyleSheetInjectedForURLAtPath(test, randomPath));
+ g_assert(isStyleSheetInjectedForURLAtPath(test, "someotherrandompath"));
+
+ removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist);
+
+ static const char* inTheWhiteList = "inthewhitelist";
+ static const char* notInWhitelist = "notinthewhitelist";
+ static const char* inTheWhiteListAndBlackList = "inthewhitelistandblacklist";
+
+ fillURLListFromPaths(whitelist, inTheWhiteList, inTheWhiteListAndBlackList, 0);
+ fillURLListFromPaths(blacklist, inTheWhiteListAndBlackList, 0);
+ styleSheet = webkit_user_style_sheet_new(kInjectedStyleSheet, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_STYLE_LEVEL_USER, whitelist, blacklist);
+ webkit_user_content_manager_add_style_sheet(test->m_userContentManager.get(), styleSheet);
+ webkit_user_style_sheet_unref(styleSheet);
+ g_assert(isStyleSheetInjectedForURLAtPath(test, inTheWhiteList));
+ g_assert(!isStyleSheetInjectedForURLAtPath(test, inTheWhiteListAndBlackList));
+ g_assert(!isStyleSheetInjectedForURLAtPath(test, notInWhitelist));
+
+ // It's important to clean up the environment before other tests.
+ removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist);
+}
+
+static void testUserContentManagerInjectedScript(WebViewTest* test, gconstpointer)
+{
+ char* whitelist[3] = { 0, 0, 0 };
+ char* blacklist[3] = { 0, 0, 0 };
+
+ removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist);
+
+ // Without a whitelist or a blacklist all URLs should have the injected script.
+ static const char* randomPath = "somerandompath";
+ g_assert(!isScriptInjectedForURLAtPath(test, randomPath));
+ WebKitUserScript* script = webkit_user_script_new(kInjectedScript, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END, nullptr, nullptr);
+ webkit_user_content_manager_add_script(test->m_userContentManager.get(), script);
+ webkit_user_script_unref(script);
+ g_assert(isScriptInjectedForURLAtPath(test, randomPath));
+
+ removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist);
+
+ fillURLListFromPaths(blacklist, randomPath, 0);
+ script = webkit_user_script_new(kInjectedScript, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END, nullptr, blacklist);
+ webkit_user_content_manager_add_script(test->m_userContentManager.get(), script);
+ webkit_user_script_unref(script);
+ g_assert(!isScriptInjectedForURLAtPath(test, randomPath));
+ g_assert(isScriptInjectedForURLAtPath(test, "someotherrandompath"));
+
+ removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist);
+
+ static const char* inTheWhiteList = "inthewhitelist";
+ static const char* notInWhitelist = "notinthewhitelist";
+ static const char* inTheWhiteListAndBlackList = "inthewhitelistandblacklist";
+
+ fillURLListFromPaths(whitelist, inTheWhiteList, inTheWhiteListAndBlackList, 0);
+ fillURLListFromPaths(blacklist, inTheWhiteListAndBlackList, 0);
+ script = webkit_user_script_new(kInjectedScript, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END, whitelist, blacklist);
+ webkit_user_content_manager_add_script(test->m_userContentManager.get(), script);
+ webkit_user_script_unref(script);
+ g_assert(isScriptInjectedForURLAtPath(test, inTheWhiteList));
+ g_assert(!isScriptInjectedForURLAtPath(test, inTheWhiteListAndBlackList));
+ g_assert(!isScriptInjectedForURLAtPath(test, notInWhitelist));
+
+ // It's important to clean up the environment before other tests.
+ removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist);
+}
+
+class UserScriptMessageTest : public WebViewTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(UserScriptMessageTest);
+
+ UserScriptMessageTest()
+ : m_userScriptMessage(nullptr)
+ {
+ }
+
+ ~UserScriptMessageTest()
+ {
+ if (m_userScriptMessage)
+ webkit_javascript_result_unref(m_userScriptMessage);
+ }
+
+ bool registerHandler(const char* handlerName)
+ {
+ return webkit_user_content_manager_register_script_message_handler(m_userContentManager.get(), handlerName);
+ }
+
+ void unregisterHandler(const char* handlerName)
+ {
+ webkit_user_content_manager_unregister_script_message_handler(m_userContentManager.get(), handlerName);
+ }
+
+ static void scriptMessageReceived(WebKitUserContentManager* userContentManager, WebKitJavascriptResult* jsResult, UserScriptMessageTest* test)
+ {
+ g_signal_handlers_disconnect_by_func(userContentManager, reinterpret_cast<gpointer>(scriptMessageReceived), test);
+ g_main_loop_quit(test->m_mainLoop);
+
+ g_assert(!test->m_userScriptMessage);
+ test->m_userScriptMessage = webkit_javascript_result_ref(jsResult);
+ }
+
+ WebKitJavascriptResult* waitUntilMessageReceived(const char* handlerName)
+ {
+ if (m_userScriptMessage) {
+ webkit_javascript_result_unref(m_userScriptMessage);
+ m_userScriptMessage = nullptr;
+ }
+
+ GUniquePtr<char> signalName(g_strdup_printf("script-message-received::%s", handlerName));
+ g_signal_connect(m_userContentManager.get(), signalName.get(), G_CALLBACK(scriptMessageReceived), this);
+
+ g_main_loop_run(m_mainLoop);
+ g_assert(m_userScriptMessage);
+ return m_userScriptMessage;
+ }
+
+ WebKitJavascriptResult* postMessageAndWaitUntilReceived(const char* handlerName, const char* javascriptValueAsText)
+ {
+ GUniquePtr<char> javascriptSnippet(g_strdup_printf("window.webkit.messageHandlers.%s.postMessage(%s);", handlerName, javascriptValueAsText));
+ webkit_web_view_run_javascript(m_webView, javascriptSnippet.get(), nullptr, nullptr, nullptr);
+ return waitUntilMessageReceived(handlerName);
+ }
+
+private:
+ WebKitJavascriptResult* m_userScriptMessage;
+};
+
+static void testUserContentManagerScriptMessageReceived(UserScriptMessageTest* test, gconstpointer)
+{
+ g_assert(test->registerHandler("msg"));
+
+ // Trying to register the same handler a second time must fail.
+ g_assert(!test->registerHandler("msg"));
+
+ test->loadHtml("<html></html>", nullptr);
+ test->waitUntilLoadFinished();
+
+ // Check that the "window.webkit.messageHandlers" namespace exists.
+ GUniqueOutPtr<GError> error;
+ WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers ? 'y' : 'n';", &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error.get());
+ GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(valueString.get(), ==, "y");
+
+ // Check that the "document.webkit.messageHandlers.msg" namespace exists.
+ javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers.msg ? 'y' : 'n';", &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error.get());
+ valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(valueString.get(), ==, "y");
+
+ valueString.reset(WebViewTest::javascriptResultToCString(test->postMessageAndWaitUntilReceived("msg", "'user message'")));
+ g_assert_cmpstr(valueString.get(), ==, "user message");
+
+ // Messages should arrive despite of other handlers being registered.
+ g_assert(test->registerHandler("anotherHandler"));
+
+ // Check that the "document.webkit.messageHandlers.msg" namespace still exists.
+ javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers.msg ? 'y' : 'n';", &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error.get());
+ valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(valueString.get(), ==, "y");
+
+ // Check that the "document.webkit.messageHandlers.anotherHandler" namespace exists.
+ javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers.anotherHandler ? 'y' : 'n';", &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error.get());
+ valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(valueString.get(), ==, "y");
+
+ valueString.reset(WebViewTest::javascriptResultToCString(test->postMessageAndWaitUntilReceived("msg", "'handler: msg'")));
+ g_assert_cmpstr(valueString.get(), ==, "handler: msg");
+
+ valueString.reset(WebViewTest::javascriptResultToCString(test->postMessageAndWaitUntilReceived("anotherHandler", "'handler: anotherHandler'")));
+ g_assert_cmpstr(valueString.get(), ==, "handler: anotherHandler");
+
+ // Unregistering a handler and re-registering again under the same name should work.
+ test->unregisterHandler("msg");
+
+ javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.webkit.messageHandlers.msg.postMessage('42');", &error.outPtr());
+ g_assert(!javascriptResult);
+ g_assert(error.get());
+
+ // Re-registering a handler that has been unregistered must work
+ g_assert(test->registerHandler("msg"));
+ valueString.reset(WebViewTest::javascriptResultToCString(test->postMessageAndWaitUntilReceived("msg", "'handler: msg'")));
+ g_assert_cmpstr(valueString.get(), ==, "handler: msg");
+
+ test->unregisterHandler("anotherHandler");
+}
+
+static void testUserContentManagerScriptMessageFromDOMBindings(UserScriptMessageTest* test, gconstpointer)
+{
+ g_assert(test->registerHandler("dom"));
+
+ test->loadHtml("<html>1</html>", nullptr);
+ WebKitJavascriptResult* javascriptResult = test->waitUntilMessageReceived("dom");
+ g_assert(javascriptResult);
+ GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(valueString.get(), ==, "DocumentLoaded");
+
+ test->unregisterHandler("dom");
+}
+
+static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
+{
+ soup_message_set_status(message, SOUP_STATUS_OK);
+ soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kStyleSheetHTML, strlen(kStyleSheetHTML));
+ soup_message_body_complete(message->response_body);
+}
+
+void beforeAll()
+{
+ kServer = new WebKitTestServer();
+ kServer->run(serverCallback);
+
+ Test::add("WebKitWebView", "new-with-user-content-manager", testWebViewNewWithUserContentManager);
+ WebViewTest::add("WebKitUserContentManager", "injected-style-sheet", testUserContentManagerInjectedStyleSheet);
+ WebViewTest::add("WebKitUserContentManager", "injected-script", testUserContentManagerInjectedScript);
+ UserScriptMessageTest::add("WebKitUserContentManager", "script-message-received", testUserContentManagerScriptMessageReceived);
+ UserScriptMessageTest::add("WebKitUserContentManager", "script-message-from-dom-bindings", testUserContentManagerScriptMessageFromDOMBindings);
+}
+
+void afterAll()
+{
+ delete kServer;
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebContext.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebContext.cpp
index 74e8d6817..e7b03fe0d 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebContext.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebContext.cpp
@@ -22,10 +22,13 @@
#include "LoadTrackingTest.h"
#include "WebKitTestServer.h"
#include <gtk/gtk.h>
+#include <limits.h>
+#include <stdlib.h>
#include <webkit2/webkit2.h>
#include <wtf/HashMap.h>
-#include <wtf/gobject/GRefPtr.h>
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/glib/GUniquePtr.h>
+#include <wtf/text/StringBuilder.h>
#include <wtf/text/StringHash.h>
static WebKitTestServer* kServer;
@@ -34,6 +37,45 @@ static void testWebContextDefault(Test* test, gconstpointer)
{
// Check there's a single instance of the default web context.
g_assert(webkit_web_context_get_default() == webkit_web_context_get_default());
+ g_assert(webkit_web_context_get_default() != test->m_webContext.get());
+}
+
+static void testWebContextEphemeral(Test* test, gconstpointer)
+{
+ // By default web contexts are not ephemeral.
+ g_assert(!webkit_web_context_is_ephemeral(webkit_web_context_get_default()));
+ g_assert(!webkit_web_context_is_ephemeral(test->m_webContext.get()));
+
+ WebKitWebsiteDataManager* manager = webkit_web_context_get_website_data_manager(webkit_web_context_get_default());
+ g_assert(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager));
+ g_assert(!webkit_website_data_manager_is_ephemeral(manager));
+ manager = webkit_web_context_get_website_data_manager(test->m_webContext.get());
+ g_assert(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager));
+ g_assert(!webkit_website_data_manager_is_ephemeral(manager));
+
+ GRefPtr<WebKitWebView> webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
+ g_assert(!webkit_web_view_is_ephemeral(webView.get()));
+ g_assert(webkit_web_view_get_website_data_manager(webView.get()) == webkit_web_context_get_website_data_manager(webkit_web_context_get_default()));
+
+ webView = WEBKIT_WEB_VIEW(webkit_web_view_new_with_context(test->m_webContext.get()));
+ g_assert(!webkit_web_view_is_ephemeral(webView.get()));
+ g_assert(webkit_web_view_get_website_data_manager(webView.get()) == manager);
+
+ GRefPtr<WebKitWebContext> context = adoptGRef(webkit_web_context_new_ephemeral());
+ g_assert(webkit_web_context_is_ephemeral(context.get()));
+ manager = webkit_web_context_get_website_data_manager(context.get());
+ g_assert(WEBKIT_IS_WEBSITE_DATA_MANAGER(manager));
+ g_assert(webkit_website_data_manager_is_ephemeral(manager));
+ g_assert(webkit_web_view_get_website_data_manager(webView.get()) != manager);
+
+ webView = WEBKIT_WEB_VIEW(webkit_web_view_new_with_context(context.get()));
+ g_assert(webkit_web_view_is_ephemeral(webView.get()));
+ g_assert(webkit_web_view_get_website_data_manager(webView.get()) == manager);
+
+ GRefPtr<WebKitWebsiteDataManager> ephemeralManager = adoptGRef(webkit_website_data_manager_new_ephemeral());
+ g_assert(webkit_website_data_manager_is_ephemeral(ephemeralManager.get()));
+ context = adoptGRef(webkit_web_context_new_with_website_data_manager(ephemeralManager.get()));
+ g_assert(webkit_web_context_is_ephemeral(context.get()));
}
class PluginsTest: public Test {
@@ -41,11 +83,10 @@ public:
MAKE_GLIB_TEST_FIXTURE(PluginsTest);
PluginsTest()
- : m_context(webkit_web_context_get_default())
- , m_mainLoop(g_main_loop_new(0, TRUE))
- , m_plugins(0)
+ : m_mainLoop(g_main_loop_new(nullptr, TRUE))
+ , m_plugins(nullptr)
{
- webkit_web_context_set_additional_plugins_directory(m_context, WEBKIT_TEST_PLUGIN_DIR);
+ webkit_web_context_set_additional_plugins_directory(m_webContext.get(), WEBKIT_TEST_PLUGIN_DIR);
}
~PluginsTest()
@@ -56,19 +97,18 @@ public:
static void getPluginsAsyncReadyCallback(GObject*, GAsyncResult* result, PluginsTest* test)
{
- test->m_plugins = webkit_web_context_get_plugins_finish(test->m_context, result, 0);
+ test->m_plugins = webkit_web_context_get_plugins_finish(test->m_webContext.get(), result, nullptr);
g_main_loop_quit(test->m_mainLoop);
}
GList* getPlugins()
{
g_list_free_full(m_plugins, g_object_unref);
- webkit_web_context_get_plugins(m_context, 0, reinterpret_cast<GAsyncReadyCallback>(getPluginsAsyncReadyCallback), this);
+ webkit_web_context_get_plugins(m_webContext.get(), nullptr, reinterpret_cast<GAsyncReadyCallback>(getPluginsAsyncReadyCallback), this);
g_main_loop_run(m_mainLoop);
return m_plugins;
}
- WebKitWebContext* m_context;
GMainLoop* m_mainLoop;
GList* m_plugins;
};
@@ -89,7 +129,9 @@ static void testWebContextGetPlugins(PluginsTest* test, gconstpointer)
}
g_assert(WEBKIT_IS_PLUGIN(testPlugin.get()));
- GUniquePtr<char> pluginPath(g_build_filename(WEBKIT_TEST_PLUGIN_DIR, "libTestNetscapePlugin.so", nullptr));
+ char normalizedPath[PATH_MAX];
+ g_assert(realpath(WEBKIT_TEST_PLUGIN_DIR, normalizedPath));
+ GUniquePtr<char> pluginPath(g_build_filename(normalizedPath, "libTestNetscapePlugIn.so", nullptr));
g_assert_cmpstr(webkit_plugin_get_path(testPlugin.get()), ==, pluginPath.get());
g_assert_cmpstr(webkit_plugin_get_description(testPlugin.get()), ==, "Simple Netscape® plug-in that handles test content for WebKit");
GList* mimeInfoList = webkit_plugin_get_mime_info_list(testPlugin.get());
@@ -116,7 +158,10 @@ static const char* kBarHTML = "<html><body>Bar</body></html>";
static const char* kEchoHTMLFormat = "<html><body>%s</body></html>";
static const char* errorDomain = "test";
static const int errorCode = 10;
-static const char* errorMessage = "Error message.";
+
+static const char* genericErrorMessage = "Error message.";
+static const char* beforeReceiveResponseErrorMessage = "Error before didReceiveResponse.";
+static const char* afterInitialChunkErrorMessage = "Error after reading the initial chunk.";
class URISchemeTest: public LoadTrackingTest {
public:
@@ -148,23 +193,38 @@ public:
g_assert(webkit_uri_scheme_request_get_web_view(request) == test->m_webView);
- GRefPtr<GInputStream> inputStream = adoptGRef(g_memory_input_stream_new());
- test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(inputStream.get()));
-
const char* scheme = webkit_uri_scheme_request_get_scheme(request);
g_assert(scheme);
g_assert(test->m_handlersMap.contains(String::fromUTF8(scheme)));
+ const URISchemeHandler& handler = test->m_handlersMap.get(String::fromUTF8(scheme));
+
+ GRefPtr<GInputStream> inputStream = adoptGRef(g_memory_input_stream_new());
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(inputStream.get()));
+
+ const gchar* requestPath = webkit_uri_scheme_request_get_path(request);
+
if (!g_strcmp0(scheme, "error")) {
- GUniquePtr<GError> error(g_error_new_literal(g_quark_from_string(errorDomain), errorCode, errorMessage));
- webkit_uri_scheme_request_finish_error(request, error.get());
+ if (!g_strcmp0(requestPath, "before-response")) {
+ GUniquePtr<GError> error(g_error_new_literal(g_quark_from_string(errorDomain), errorCode, beforeReceiveResponseErrorMessage));
+ // We call finish() and then finish_error() to make sure that not even
+ // the didReceiveResponse message is processed at the time of failing.
+ webkit_uri_scheme_request_finish(request, G_INPUT_STREAM(inputStream.get()), handler.replyLength, handler.mimeType.data());
+ webkit_uri_scheme_request_finish_error(request, error.get());
+ } else if (!g_strcmp0(requestPath, "after-first-chunk")) {
+ g_memory_input_stream_add_data(G_MEMORY_INPUT_STREAM(inputStream.get()), handler.reply.data(), handler.reply.length(), 0);
+ webkit_uri_scheme_request_finish(request, inputStream.get(), handler.replyLength, handler.mimeType.data());
+ // We need to wait until we reach the load-committed state before calling webkit_uri_scheme_request_finish_error(),
+ // so we rely on the test using finishOnCommittedAndWaitUntilLoadFinished() to actually call it from loadCommitted().
+ } else {
+ GUniquePtr<GError> error(g_error_new_literal(g_quark_from_string(errorDomain), errorCode, genericErrorMessage));
+ webkit_uri_scheme_request_finish_error(request, error.get());
+ }
return;
}
- const URISchemeHandler& handler = test->m_handlersMap.get(String::fromUTF8(scheme));
-
if (!g_strcmp0(scheme, "echo")) {
- char* replyHTML = g_strdup_printf(handler.reply.data(), webkit_uri_scheme_request_get_path(request));
+ char* replyHTML = g_strdup_printf(handler.reply.data(), requestPath);
g_memory_input_stream_add_data(G_MEMORY_INPUT_STREAM(inputStream.get()), replyHTML, strlen(replyHTML), g_free);
} else if (!g_strcmp0(scheme, "closed"))
g_input_stream_close(inputStream.get(), 0, 0);
@@ -177,13 +237,58 @@ public:
void registerURISchemeHandler(const char* scheme, const char* reply, int replyLength, const char* mimeType)
{
m_handlersMap.set(String::fromUTF8(scheme), URISchemeHandler(reply, replyLength, mimeType));
- webkit_web_context_register_uri_scheme(webkit_web_context_get_default(), scheme, uriSchemeRequestCallback, this, 0);
+ webkit_web_context_register_uri_scheme(m_webContext.get(), scheme, uriSchemeRequestCallback, this, 0);
+ }
+
+ void loadCommitted() override
+ {
+ if (m_finishOnCommitted) {
+ GUniquePtr<GError> error(g_error_new_literal(g_quark_from_string(errorDomain), errorCode, afterInitialChunkErrorMessage));
+ webkit_uri_scheme_request_finish_error(m_uriSchemeRequest.get(), error.get());
+ }
+
+ LoadTrackingTest::loadCommitted();
+ }
+
+ void finishOnCommittedAndWaitUntilLoadFinished()
+ {
+ m_finishOnCommitted = true;
+ waitUntilLoadFinished();
+ m_finishOnCommitted = false;
}
GRefPtr<WebKitURISchemeRequest> m_uriSchemeRequest;
HashMap<String, URISchemeHandler> m_handlersMap;
+ bool m_finishOnCommitted { false };
};
+String generateHTMLContent(unsigned contentLength)
+{
+ String baseString("abcdefghijklmnopqrstuvwxyz0123457890");
+ unsigned baseLength = baseString.length();
+
+ StringBuilder builder;
+ builder.append("<html><body>");
+
+ if (contentLength <= baseLength)
+ builder.append(baseString, 0, contentLength);
+ else {
+ unsigned currentLength = 0;
+ while (currentLength < contentLength) {
+ if ((currentLength + baseLength) <= contentLength)
+ builder.append(baseString);
+ else
+ builder.append(baseString, 0, contentLength - currentLength);
+
+ // Account for the 12 characters of the '<html><body>' prefix.
+ currentLength = builder.length() - 12;
+ }
+ }
+ builder.append("</body></html>");
+
+ return builder.toString();
+}
+
static void testWebContextURIScheme(URISchemeTest* test, gconstpointer)
{
test->registerURISchemeHandler("foo", kBarHTML, strlen(kBarHTML), "text/html");
@@ -203,6 +308,16 @@ static void testWebContextURIScheme(URISchemeTest* test, gconstpointer)
g_assert_cmpint(mainResourceDataSize, ==, strlen(echoHTML.get()));
g_assert(!strncmp(mainResourceData, echoHTML.get(), mainResourceDataSize));
+ test->loadURI("echo:with#fragment");
+ test->waitUntilLoadFinished();
+ g_assert_cmpstr(webkit_uri_scheme_request_get_path(test->m_uriSchemeRequest.get()), ==, "with");
+ g_assert_cmpstr(webkit_uri_scheme_request_get_uri(test->m_uriSchemeRequest.get()), ==, "echo:with#fragment");
+ echoHTML.reset(g_strdup_printf(kEchoHTMLFormat, webkit_uri_scheme_request_get_path(test->m_uriSchemeRequest.get())));
+ mainResourceDataSize = 0;
+ mainResourceData = test->mainResourceData(mainResourceDataSize);
+ g_assert_cmpint(mainResourceDataSize, ==, strlen(echoHTML.get()));
+ g_assert(!strncmp(mainResourceData, echoHTML.get(), mainResourceDataSize));
+
test->registerURISchemeHandler("nomime", kBarHTML, -1, 0);
test->m_loadEvents.clear();
test->loadURI("nomime:foo-bar");
@@ -216,14 +331,35 @@ static void testWebContextURIScheme(URISchemeTest* test, gconstpointer)
g_assert(!test->m_loadEvents.contains(LoadTrackingTest::ProvisionalLoadFailed));
g_assert(!test->m_loadEvents.contains(LoadTrackingTest::LoadFailed));
- test->registerURISchemeHandler("error", 0, 0, 0);
+ // Anything over 8192 bytes will get multiple calls to g_input_stream_read_async in
+ // WebKitURISchemeRequest when reading data, but we still need way more than that to
+ // ensure that we reach the load-committed state before failing, so we use an 8MB HTML.
+ String longHTMLContent = generateHTMLContent(8 * 1024 * 1024);
+ test->registerURISchemeHandler("error", longHTMLContent.utf8().data(), -1, "text/html");
test->m_loadEvents.clear();
test->loadURI("error:error");
test->waitUntilLoadFinished();
g_assert(test->m_loadEvents.contains(LoadTrackingTest::ProvisionalLoadFailed));
g_assert(test->m_loadFailed);
g_assert_error(test->m_error.get(), g_quark_from_string(errorDomain), errorCode);
- g_assert_cmpstr(test->m_error->message, ==, errorMessage);
+ g_assert_cmpstr(test->m_error->message, ==, genericErrorMessage);
+
+ test->m_loadEvents.clear();
+ test->loadURI("error:before-response");
+ test->waitUntilLoadFinished();
+ g_assert(test->m_loadEvents.contains(LoadTrackingTest::ProvisionalLoadFailed));
+ g_assert(test->m_loadFailed);
+ g_assert_error(test->m_error.get(), g_quark_from_string(errorDomain), errorCode);
+ g_assert_cmpstr(test->m_error->message, ==, beforeReceiveResponseErrorMessage);
+
+ test->m_loadEvents.clear();
+ test->loadURI("error:after-first-chunk");
+ test->finishOnCommittedAndWaitUntilLoadFinished();
+ g_assert(!test->m_loadEvents.contains(LoadTrackingTest::ProvisionalLoadFailed));
+ g_assert(test->m_loadEvents.contains(LoadTrackingTest::LoadFailed));
+ g_assert(test->m_loadFailed);
+ g_assert_error(test->m_error.get(), g_quark_from_string(errorDomain), errorCode);
+ g_assert_cmpstr(test->m_error->message, ==, afterInitialChunkErrorMessage);
test->registerURISchemeHandler("closed", 0, 0, 0);
test->m_loadEvents.clear();
@@ -236,7 +372,7 @@ static void testWebContextURIScheme(URISchemeTest* test, gconstpointer)
static void testWebContextSpellChecker(Test* test, gconstpointer)
{
- WebKitWebContext* webContext = webkit_web_context_get_default();
+ WebKitWebContext* webContext = test->m_webContext.get();
// Check what happens if no spell checking language has been set.
const gchar* const* currentLanguage = webkit_web_context_get_spell_checking_languages(webContext);
@@ -289,7 +425,7 @@ static void testWebContextSpellChecker(Test* test, gconstpointer)
static void testWebContextLanguages(WebViewTest* test, gconstpointer)
{
- static const char* expectedDefaultLanguage = "en";
+ static const char* expectedDefaultLanguage = "en-US";
test->loadURI(kServer->getURIForPath("/").data());
test->waitUntilLoadFinished();
size_t mainResourceDataSize = 0;
@@ -302,7 +438,7 @@ static void testWebContextLanguages(WebViewTest* test, gconstpointer)
g_ptr_array_add(languages.get(), const_cast<gpointer>(static_cast<const void*>("ES_es")));
g_ptr_array_add(languages.get(), const_cast<gpointer>(static_cast<const void*>("dE")));
g_ptr_array_add(languages.get(), 0);
- webkit_web_context_set_preferred_languages(webkit_web_context_get_default(), reinterpret_cast<const char* const*>(languages->pdata));
+ webkit_web_context_set_preferred_languages(test->m_webContext.get(), reinterpret_cast<const char* const*>(languages->pdata));
static const char* expectedLanguages = "en, es-es;q=0.90, de;q=0.80";
test->loadURI(kServer->getURIForPath("/").data());
@@ -311,6 +447,32 @@ static void testWebContextLanguages(WebViewTest* test, gconstpointer)
mainResourceData = test->mainResourceData(mainResourceDataSize);
g_assert_cmpuint(mainResourceDataSize, ==, strlen(expectedLanguages));
g_assert(!strncmp(mainResourceData, expectedLanguages, mainResourceDataSize));
+
+ // When using the C locale, en-US should be used as default.
+ const char* cLanguage[] = { "C", nullptr };
+ webkit_web_context_set_preferred_languages(test->m_webContext.get(), cLanguage);
+ GUniqueOutPtr<GError> error;
+ WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("Intl.DateTimeFormat().resolvedOptions().locale", &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error);
+ GUniquePtr<char> locale(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(locale.get(), ==, expectedDefaultLanguage);
+
+ // When using the POSIX locale, en-US should be used as default.
+ const char* posixLanguage[] = { "POSIX", nullptr };
+ webkit_web_context_set_preferred_languages(test->m_webContext.get(), posixLanguage);
+ javascriptResult = test->runJavaScriptAndWaitUntilFinished("Intl.DateTimeFormat().resolvedOptions().locale", &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error);
+ locale.reset(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(locale.get(), ==, expectedDefaultLanguage);
+
+ // An invalid locale should throw an exception.
+ const char* invalidLanguage[] = { "A", nullptr };
+ webkit_web_context_set_preferred_languages(test->m_webContext.get(), invalidLanguage);
+ javascriptResult = test->runJavaScriptAndWaitUntilFinished("Intl.DateTimeFormat().resolvedOptions().locale", &error.outPtr());
+ g_assert(!javascriptResult);
+ g_assert_error(error.get(), WEBKIT_JAVASCRIPT_ERROR, WEBKIT_JAVASCRIPT_ERROR_SCRIPT_FAILED);
}
static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
@@ -325,6 +487,16 @@ static void serverCallback(SoupServer* server, SoupMessage* message, const char*
soup_message_set_status(message, SOUP_STATUS_OK);
soup_message_body_append(message->response_body, SOUP_MEMORY_COPY, acceptLanguage, strlen(acceptLanguage));
soup_message_body_complete(message->response_body);
+ } else if (g_str_equal(path, "/empty")) {
+ const char* emptyHTML = "<html><body></body></html>";
+ soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, emptyHTML, strlen(emptyHTML));
+ soup_message_body_complete(message->response_body);
+ soup_message_set_status(message, SOUP_STATUS_OK);
+ } else if (g_str_equal(path, "/echoPort")) {
+ char* port = g_strdup_printf("%u", soup_server_get_port(server));
+ soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, port, strlen(port));
+ soup_message_body_complete(message->response_body);
+ soup_message_set_status(message, SOUP_STATUS_OK);
} else
soup_message_set_status(message, SOUP_STATUS_NOT_FOUND);
}
@@ -343,7 +515,7 @@ public:
};
SecurityPolicyTest()
- : m_manager(webkit_web_context_get_security_manager(webkit_web_context_get_default()))
+ : m_manager(webkit_web_context_get_security_manager(m_webContext.get()))
{
}
@@ -406,17 +578,205 @@ static void testWebContextSecurityPolicy(SecurityPolicyTest* test, gconstpointer
| SecurityPolicyTest::CORSEnabled | SecurityPolicyTest::EmptyDocument);
}
+static void consoleMessageReceivedCallback(WebKitUserContentManager*, WebKitJavascriptResult* message, WebKitJavascriptResult** result)
+{
+ g_assert(result);
+ g_assert(!*result);
+ *result = webkit_javascript_result_ref(message);
+}
+
+static void testWebContextSecurityFileXHR(WebViewTest* test, gconstpointer)
+{
+ GUniquePtr<char> fileURL(g_strdup_printf("file://%s/simple.html", Test::getResourcesDir(Test::WebKit2Resources).data()));
+ test->loadURI(fileURL.get());
+ test->waitUntilLoadFinished();
+
+ GUniquePtr<char> jsonURL(g_strdup_printf("file://%s/simple.json", Test::getResourcesDir().data()));
+ GUniquePtr<char> xhr(g_strdup_printf("var xhr = new XMLHttpRequest; xhr.open(\"GET\", \"%s\"); xhr.send();", jsonURL.get()));
+
+ WebKitJavascriptResult* consoleMessage = nullptr;
+ webkit_user_content_manager_register_script_message_handler(test->m_userContentManager.get(), "console");
+ g_signal_connect(test->m_userContentManager.get(), "script-message-received::console", G_CALLBACK(consoleMessageReceivedCallback), &consoleMessage);
+
+ // By default file access is not allowed, this will show a console message with a cross-origin error.
+ GUniqueOutPtr<GError> error;
+ WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished(xhr.get(), &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error);
+ g_assert(consoleMessage);
+ GUniquePtr<char> messageString(WebViewTest::javascriptResultToCString(consoleMessage));
+ GRefPtr<GVariant> variant = g_variant_parse(G_VARIANT_TYPE("(uusus)"), messageString.get(), nullptr, nullptr, nullptr);
+ g_assert(variant.get());
+ unsigned level;
+ const char* messageText;
+ g_variant_get(variant.get(), "(uu&su&s)", nullptr, &level, &messageText, nullptr, nullptr);
+ g_assert_cmpuint(level, ==, 3); // Console error message.
+ GUniquePtr<char> expectedErrorMessage(g_strdup_printf("XMLHttpRequest cannot load %s. Cross origin requests are only supported for HTTP.", jsonURL.get()));
+ g_assert_cmpstr(messageText, ==, expectedErrorMessage.get());
+ webkit_javascript_result_unref(consoleMessage);
+ consoleMessage = nullptr;
+ level = 0;
+ messageText = nullptr;
+ variant = nullptr;
+
+ // Allow file access from file URLs.
+ webkit_settings_set_allow_file_access_from_file_urls(webkit_web_view_get_settings(test->m_webView), TRUE);
+ test->loadURI(fileURL.get());
+ test->waitUntilLoadFinished();
+ javascriptResult = test->runJavaScriptAndWaitUntilFinished(xhr.get(), &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error);
+
+ // It isn't still possible to load file from an HTTP URL.
+ test->loadURI(kServer->getURIForPath("/").data());
+ test->waitUntilLoadFinished();
+ javascriptResult = test->runJavaScriptAndWaitUntilFinished(xhr.get(), &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error);
+ g_assert(consoleMessage);
+ variant = g_variant_parse(G_VARIANT_TYPE("(uusus)"), messageString.get(), nullptr, nullptr, nullptr);
+ g_assert(variant.get());
+ g_variant_get(variant.get(), "(uu&su&s)", nullptr, &level, &messageText, nullptr, nullptr);
+ g_assert_cmpuint(level, ==, 3); // Console error message.
+ g_assert_cmpstr(messageText, ==, expectedErrorMessage.get());
+ webkit_javascript_result_unref(consoleMessage);
+
+ g_signal_handlers_disconnect_matched(test->m_userContentManager.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, &consoleMessage);
+ webkit_user_content_manager_unregister_script_message_handler(test->m_userContentManager.get(), "console");
+
+ webkit_settings_set_allow_file_access_from_file_urls(webkit_web_view_get_settings(test->m_webView), FALSE);
+}
+
+class ProxyTest : public WebViewTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(ProxyTest);
+
+ ProxyTest()
+ {
+ // This "proxy server" is actually just a different instance of the main
+ // test server (kServer), listening on a different port. Requests
+ // will not actually be proxied to kServer because proxyServer is not
+ // actually a proxy server. We're testing whether the proxy settings
+ // work, not whether we can write a soup proxy server.
+ m_proxyServer.run(serverCallback);
+ g_assert(m_proxyServer.baseURI());
+ }
+
+ CString loadURIAndGetMainResourceData(const char* uri)
+ {
+ loadURI(uri);
+ waitUntilLoadFinished();
+ size_t dataSize = 0;
+ const char* data = mainResourceData(dataSize);
+ return CString(data, dataSize);
+ }
+
+ GUniquePtr<char> proxyServerPortAsString()
+ {
+ GUniquePtr<char> port(g_strdup_printf("%u", soup_uri_get_port(m_proxyServer.baseURI())));
+ return port;
+ }
+
+ WebKitTestServer m_proxyServer;
+};
+
+static void ephemeralViewloadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent, WebViewTest* test)
+{
+ if (loadEvent != WEBKIT_LOAD_FINISHED)
+ return;
+ g_signal_handlers_disconnect_by_func(webView, reinterpret_cast<void*>(ephemeralViewloadChanged), test);
+ test->quitMainLoop();
+}
+
+static void testWebContextProxySettings(ProxyTest* test, gconstpointer)
+{
+ // Proxy URI is unset by default. Requests to kServer should be received by kServer.
+ GUniquePtr<char> serverPortAsString(g_strdup_printf("%u", soup_uri_get_port(kServer->baseURI())));
+ auto mainResourceData = test->loadURIAndGetMainResourceData(kServer->getURIForPath("/echoPort").data());
+ ASSERT_CMP_CSTRING(mainResourceData, ==, serverPortAsString.get());
+
+ // Set default proxy URI to point to proxyServer. Requests to kServer should be received by proxyServer instead.
+ GUniquePtr<char> proxyURI(soup_uri_to_string(test->m_proxyServer.baseURI(), FALSE));
+ WebKitNetworkProxySettings* settings = webkit_network_proxy_settings_new(proxyURI.get(), nullptr);
+ webkit_web_context_set_network_proxy_settings(test->m_webContext.get(), WEBKIT_NETWORK_PROXY_MODE_CUSTOM, settings);
+ GUniquePtr<char> proxyServerPortAsString = test->proxyServerPortAsString();
+ mainResourceData = test->loadURIAndGetMainResourceData(kServer->getURIForPath("/echoPort").data());
+ ASSERT_CMP_CSTRING(mainResourceData, ==, proxyServerPortAsString.get());
+ webkit_network_proxy_settings_free(settings);
+
+ // Proxy settings also affect ephemeral web views.
+ GRefPtr<WebKitWebView> webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW,
+ "web-context", test->m_webContext.get(),
+ "is-ephemeral", TRUE,
+ nullptr));
+ g_assert(webkit_web_view_is_ephemeral(webView.get()));
+ g_assert(!webkit_web_context_is_ephemeral(webkit_web_view_get_context(webView.get())));
+
+ g_signal_connect(webView.get(), "load-changed", G_CALLBACK(ephemeralViewloadChanged), test);
+ webkit_web_view_load_uri(webView.get(), kServer->getURIForPath("/echoPort").data());
+ g_main_loop_run(test->m_mainLoop);
+ WebKitWebResource* resource = webkit_web_view_get_main_resource(webView.get());
+ g_assert(WEBKIT_IS_WEB_RESOURCE(resource));
+ webkit_web_resource_get_data(resource, nullptr, [](GObject* object, GAsyncResult* result, gpointer userData) {
+ size_t dataSize;
+ GUniquePtr<char> data(reinterpret_cast<char*>(webkit_web_resource_get_data_finish(WEBKIT_WEB_RESOURCE(object), result, &dataSize, nullptr)));
+ g_assert(data);
+ auto* test = static_cast<ProxyTest*>(userData);
+ GUniquePtr<char> proxyServerPortAsString = test->proxyServerPortAsString();
+ ASSERT_CMP_CSTRING(CString(data.get(), dataSize), ==, proxyServerPortAsString.get());
+ test->quitMainLoop();
+ }, test);
+ g_main_loop_run(test->m_mainLoop);
+
+ // Remove the proxy. Requests to kServer should be received by kServer again.
+ webkit_web_context_set_network_proxy_settings(test->m_webContext.get(), WEBKIT_NETWORK_PROXY_MODE_NO_PROXY, nullptr);
+ mainResourceData = test->loadURIAndGetMainResourceData(kServer->getURIForPath("/echoPort").data());
+ ASSERT_CMP_CSTRING(mainResourceData, ==, serverPortAsString.get());
+
+ // Use a default proxy uri, but ignoring requests to localhost.
+ static const char* ignoreHosts[] = { "localhost", nullptr };
+ settings = webkit_network_proxy_settings_new(proxyURI.get(), ignoreHosts);
+ webkit_web_context_set_network_proxy_settings(test->m_webContext.get(), WEBKIT_NETWORK_PROXY_MODE_CUSTOM, settings);
+ mainResourceData = test->loadURIAndGetMainResourceData(kServer->getURIForPath("/echoPort").data());
+ ASSERT_CMP_CSTRING(mainResourceData, ==, proxyServerPortAsString.get());
+ GUniquePtr<char> localhostEchoPortURI(g_strdup_printf("http://localhost:%s/echoPort", serverPortAsString.get()));
+ mainResourceData = test->loadURIAndGetMainResourceData(localhostEchoPortURI.get());
+ ASSERT_CMP_CSTRING(mainResourceData, ==, serverPortAsString.get());
+ webkit_network_proxy_settings_free(settings);
+
+ // Remove the proxy again to ensure next test is not using any previous values.
+ webkit_web_context_set_network_proxy_settings(test->m_webContext.get(), WEBKIT_NETWORK_PROXY_MODE_NO_PROXY, nullptr);
+ mainResourceData = test->loadURIAndGetMainResourceData(kServer->getURIForPath("/echoPort").data());
+ ASSERT_CMP_CSTRING(mainResourceData, ==, serverPortAsString.get());
+
+ // Use scheme specific proxy instead of the default.
+ settings = webkit_network_proxy_settings_new(nullptr, nullptr);
+ webkit_network_proxy_settings_add_proxy_for_scheme(settings, "http", proxyURI.get());
+ webkit_web_context_set_network_proxy_settings(test->m_webContext.get(), WEBKIT_NETWORK_PROXY_MODE_CUSTOM, settings);
+ mainResourceData = test->loadURIAndGetMainResourceData(kServer->getURIForPath("/echoPort").data());
+ ASSERT_CMP_CSTRING(mainResourceData, ==, proxyServerPortAsString.get());
+ webkit_network_proxy_settings_free(settings);
+
+ // Reset to use the default resolver.
+ webkit_web_context_set_network_proxy_settings(test->m_webContext.get(), WEBKIT_NETWORK_PROXY_MODE_DEFAULT, nullptr);
+ mainResourceData = test->loadURIAndGetMainResourceData(kServer->getURIForPath("/echoPort").data());
+ ASSERT_CMP_CSTRING(mainResourceData, ==, serverPortAsString.get());
+}
+
void beforeAll()
{
kServer = new WebKitTestServer();
kServer->run(serverCallback);
Test::add("WebKitWebContext", "default-context", testWebContextDefault);
+ Test::add("WebKitWebContext", "ephemeral", testWebContextEphemeral);
PluginsTest::add("WebKitWebContext", "get-plugins", testWebContextGetPlugins);
URISchemeTest::add("WebKitWebContext", "uri-scheme", testWebContextURIScheme);
Test::add("WebKitWebContext", "spell-checker", testWebContextSpellChecker);
WebViewTest::add("WebKitWebContext", "languages", testWebContextLanguages);
SecurityPolicyTest::add("WebKitSecurityManager", "security-policy", testWebContextSecurityPolicy);
+ WebViewTest::add("WebKitSecurityManager", "file-xhr", testWebContextSecurityFileXHR);
+ ProxyTest::add("WebKitWebContext", "proxy", testWebContextProxySettings);
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp
index 334f8dafe..4e3d1d7e7 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebView.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2011 Igalia S.L.
+ * Copyright (C) 2014 Collabora Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -18,38 +19,153 @@
*/
#include "config.h"
+#include "WebKitTestServer.h"
#include "WebViewTest.h"
#include <JavaScriptCore/JSStringRef.h>
#include <JavaScriptCore/JSValueRef.h>
#include <glib/gstdio.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
-static void testWebViewDefaultContext(WebViewTest* test, gconstpointer)
+class IsPlayingAudioWebViewTest : public WebViewTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(IsPlayingAudioWebViewTest);
+
+ static void isPlayingAudioChanged(GObject*, GParamSpec*, IsPlayingAudioWebViewTest* test)
+ {
+ g_signal_handlers_disconnect_by_func(test->m_webView, reinterpret_cast<void*>(isPlayingAudioChanged), test);
+ g_main_loop_quit(test->m_mainLoop);
+ }
+
+ void waitUntilIsPlayingAudioChanged()
+ {
+ g_signal_connect(m_webView, "notify::is-playing-audio", G_CALLBACK(isPlayingAudioChanged), this);
+ g_main_loop_run(m_mainLoop);
+ }
+};
+
+static WebKitTestServer* gServer;
+
+static void testWebViewWebContext(WebViewTest* test, gconstpointer)
{
- g_assert(webkit_web_view_get_context(test->m_webView) == webkit_web_context_get_default());
+ g_assert(webkit_web_view_get_context(test->m_webView) == test->m_webContext.get());
+ g_assert(webkit_web_context_get_default() != test->m_webContext.get());
// Check that a web view created with g_object_new has the default context.
- GRefPtr<WebKitWebView> webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, NULL));
+ GRefPtr<WebKitWebView> webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, nullptr));
g_assert(webkit_web_view_get_context(webView.get()) == webkit_web_context_get_default());
+
+ // Check that a web view created with a related view has the related view context.
+ webView = WEBKIT_WEB_VIEW(webkit_web_view_new_with_related_view(test->m_webView));
+ g_assert(webkit_web_view_get_context(webView.get()) == test->m_webContext.get());
+
+ // Check that a web context given as construct parameter is ignored if a related view is also provided.
+ webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW,
+ "web-context", webkit_web_context_get_default(), "related-view", test->m_webView, nullptr));
+ g_assert(webkit_web_view_get_context(webView.get()) == test->m_webContext.get());
+}
+
+static void testWebViewWebContextLifetime(WebViewTest* test, gconstpointer)
+{
+ WebKitWebContext* webContext = webkit_web_context_new();
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webContext));
+
+ GtkWidget* webView = webkit_web_view_new_with_context(webContext);
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webView));
+
+ g_object_ref_sink(webView);
+ g_object_unref(webContext);
+
+ // Check that the web view still has a valid context.
+ WebKitWebContext* tmpContext = webkit_web_view_get_context(WEBKIT_WEB_VIEW(webView));
+ g_assert_true(WEBKIT_IS_WEB_CONTEXT(tmpContext));
+ g_object_unref(webView);
+
+ WebKitWebContext* webContext2 = webkit_web_context_new();
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webContext2));
+
+ GtkWidget* webView2 = webkit_web_view_new_with_context(webContext2);
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webView2));
+
+ g_object_ref_sink(webView2);
+ g_object_unref(webView2);
+
+ // Check that the context is still valid.
+ g_assert_true(WEBKIT_IS_WEB_CONTEXT(webContext2));
+ g_object_unref(webContext2);
+}
+
+static void ephemeralViewloadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent, WebViewTest* test)
+{
+ if (loadEvent != WEBKIT_LOAD_FINISHED)
+ return;
+ g_signal_handlers_disconnect_by_func(webView, reinterpret_cast<void*>(ephemeralViewloadChanged), test);
+ test->quitMainLoop();
+}
+
+static void testWebViewEphemeral(WebViewTest* test, gconstpointer)
+{
+ g_assert(!webkit_web_view_is_ephemeral(test->m_webView));
+ g_assert(!webkit_web_context_is_ephemeral(webkit_web_view_get_context(test->m_webView)));
+ auto* manager = webkit_web_context_get_website_data_manager(test->m_webContext.get());
+ g_assert(!webkit_website_data_manager_is_ephemeral(manager));
+ g_assert(webkit_web_view_get_website_data_manager(test->m_webView) == manager);
+ webkit_website_data_manager_clear(manager, WEBKIT_WEBSITE_DATA_DISK_CACHE, 0, nullptr, [](GObject* manager, GAsyncResult* result, gpointer userData) {
+ webkit_website_data_manager_clear_finish(WEBKIT_WEBSITE_DATA_MANAGER(manager), result, nullptr);
+ static_cast<WebViewTest*>(userData)->quitMainLoop();
+ }, test);
+ g_main_loop_run(test->m_mainLoop);
+
+ // A WebView on a non ephemeral context can be ephemeral.
+ GRefPtr<WebKitWebView> webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW,
+ "web-context", webkit_web_view_get_context(test->m_webView),
+ "is-ephemeral", TRUE,
+ nullptr));
+ g_assert(webkit_web_view_is_ephemeral(webView.get()));
+ g_assert(!webkit_web_context_is_ephemeral(webkit_web_view_get_context(webView.get())));
+ g_assert(webkit_web_view_get_website_data_manager(webView.get()) != manager);
+
+ g_signal_connect(webView.get(), "load-changed", G_CALLBACK(ephemeralViewloadChanged), test);
+ webkit_web_view_load_uri(webView.get(), gServer->getURIForPath("/").data());
+ g_main_loop_run(test->m_mainLoop);
+
+ // Disk cache delays the storing of initial resources for 1 second to avoid
+ // affecting early page load. So, wait 1 second here to make sure resources
+ // have already been stored.
+ test->wait(1);
+
+ webkit_website_data_manager_fetch(manager, WEBKIT_WEBSITE_DATA_DISK_CACHE, nullptr, [](GObject* manager, GAsyncResult* result, gpointer userData) {
+ auto* test = static_cast<WebViewTest*>(userData);
+ g_assert(!webkit_website_data_manager_fetch_finish(WEBKIT_WEBSITE_DATA_MANAGER(manager), result, nullptr));
+ test->quitMainLoop();
+ }, test);
+ g_main_loop_run(test->m_mainLoop);
}
static void testWebViewCustomCharset(WebViewTest* test, gconstpointer)
{
+ test->loadURI(gServer->getURIForPath("/").data());
+ test->waitUntilLoadFinished();
g_assert(!webkit_web_view_get_custom_charset(test->m_webView));
webkit_web_view_set_custom_charset(test->m_webView, "utf8");
+ // Changing the charset reloads the page, so wait until reloaded.
+ test->waitUntilLoadFinished();
g_assert_cmpstr(webkit_web_view_get_custom_charset(test->m_webView), ==, "utf8");
- // Go back to the default charset.
- webkit_web_view_set_custom_charset(test->m_webView, 0);
+
+ // Go back to the default charset and wait until reloaded.
+ webkit_web_view_set_custom_charset(test->m_webView, nullptr);
+ test->waitUntilLoadFinished();
g_assert(!webkit_web_view_get_custom_charset(test->m_webView));
}
static void testWebViewSettings(WebViewTest* test, gconstpointer)
{
WebKitSettings* defaultSettings = webkit_web_view_get_settings(test->m_webView);
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(defaultSettings));
g_assert(defaultSettings);
g_assert(webkit_settings_get_enable_javascript(defaultSettings));
GRefPtr<WebKitSettings> newSettings = adoptGRef(webkit_settings_new());
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(newSettings.get()));
g_object_set(G_OBJECT(newSettings.get()), "enable-javascript", FALSE, NULL);
webkit_web_view_set_settings(test->m_webView, newSettings.get());
@@ -63,10 +179,15 @@ static void testWebViewSettings(WebViewTest* test, gconstpointer)
g_assert(webkit_web_view_get_settings(WEBKIT_WEB_VIEW(webView2.get())) == settings);
GRefPtr<WebKitSettings> newSettings2 = adoptGRef(webkit_settings_new());
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(newSettings2.get()));
webkit_web_view_set_settings(WEBKIT_WEB_VIEW(webView2.get()), newSettings2.get());
settings = webkit_web_view_get_settings(WEBKIT_WEB_VIEW(webView2.get()));
g_assert(settings == newSettings2.get());
g_assert(webkit_settings_get_enable_javascript(settings));
+
+ GRefPtr<GtkWidget> webView3 = webkit_web_view_new_with_settings(newSettings2.get());
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webView3.get()));
+ g_assert(webkit_web_view_get_settings(WEBKIT_WEB_VIEW(webView3.get())) == newSettings2.get());
}
static void testWebViewZoomLevel(WebViewTest* test, gconstpointer)
@@ -407,7 +528,7 @@ static void testWebViewSave(SaveWebViewTest* test, gconstpointer)
gchar buffer[512] = { 0 };
gssize readBytes = 0;
gssize totalBytesFromStream = 0;
- while (readBytes = g_input_stream_read(test->m_inputStream.get(), &buffer, 512, 0, &error.outPtr())) {
+ while ((readBytes = g_input_stream_read(test->m_inputStream.get(), &buffer, 512, 0, &error.outPtr()))) {
g_assert(!error);
totalBytesFromStream += readBytes;
}
@@ -417,28 +538,7 @@ static void testWebViewSave(SaveWebViewTest* test, gconstpointer)
g_assert_cmpint(g_file_info_get_size(fileInfo.get()), ==, totalBytesFromStream);
}
-static void testWebViewMode(WebViewTest* test, gconstpointer)
-{
- static const char* indexHTML = "<html><body><p>Test Web View Mode</p></body></html>";
-
- // Web mode.
- g_assert_cmpuint(webkit_web_view_get_view_mode(test->m_webView), ==, WEBKIT_VIEW_MODE_WEB);
- test->loadHtml(indexHTML, 0);
- test->waitUntilLoadFinished();
- WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.document.body.textContent;", 0);
- GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult));
- g_assert_cmpstr(valueString.get(), ==, "Test Web View Mode");
-
- // Source mode.
- webkit_web_view_set_view_mode(test->m_webView, WEBKIT_VIEW_MODE_SOURCE);
- test->loadHtml(indexHTML, 0);
- test->waitUntilLoadFinished();
- javascriptResult = test->runJavaScriptAndWaitUntilFinished("window.document.body.textContent;", 0);
- valueString.reset(WebViewTest::javascriptResultToCString(javascriptResult));
- g_assert_cmpstr(valueString.get(), ==, indexHTML);
-}
-
-// To test page visibility API. Currently only 'visible' and 'hidden' states are implemented fully in WebCore.
+// To test page visibility API. Currently only 'visible', 'hidden' and 'prerender' states are implemented fully in WebCore.
// See also http://www.w3.org/TR/2011/WD-page-visibility-20110602/ and https://developers.google.com/chrome/whitepapers/pagevisibility
static void testWebViewPageVisibility(WebViewTest* test, gconstpointer)
{
@@ -453,7 +553,7 @@ static void testWebViewPageVisibility(WebViewTest* test, gconstpointer)
"</body></html>",
0);
- // Wait untill the page is loaded. Initial visibility should be 'hidden'.
+ // Wait until the page is loaded. Initial visibility should be 'prerender'.
test->waitUntilLoadFinished();
GUniqueOutPtr<GError> error;
@@ -461,7 +561,7 @@ static void testWebViewPageVisibility(WebViewTest* test, gconstpointer)
g_assert(javascriptResult);
g_assert(!error.get());
GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult));
- g_assert_cmpstr(valueString.get(), ==, "hidden");
+ g_assert_cmpstr(valueString.get(), ==, "prerender");
javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.hidden;", &error.outPtr());
g_assert(javascriptResult);
@@ -564,15 +664,404 @@ static void testWebViewSnapshot(SnapshotWebViewTest* test, gconstpointer)
g_assert_cmpint(cairo_image_surface_get_width(surface1), ==, cairo_image_surface_get_width(surface2));
g_assert_cmpint(cairo_image_surface_get_height(surface1), ==, cairo_image_surface_get_height(surface2));
g_assert(!Test::cairoSurfacesEqual(surface1, surface2));
+
+ // Get a snpashot with a transparent background, the result must be different.
+ surface2 = test->getSnapshotAndWaitUntilReady(WEBKIT_SNAPSHOT_REGION_VISIBLE, WEBKIT_SNAPSHOT_OPTIONS_TRANSPARENT_BACKGROUND);
+ g_assert_cmpuint(cairo_surface_get_type(surface2), ==, CAIRO_SURFACE_TYPE_IMAGE);
+ g_assert_cmpint(cairo_image_surface_get_width(surface1), ==, cairo_image_surface_get_width(surface2));
+ g_assert_cmpint(cairo_image_surface_get_height(surface1), ==, cairo_image_surface_get_height(surface2));
+ g_assert(!Test::cairoSurfacesEqual(surface1, surface2));
cairo_surface_destroy(surface1);
// Test that cancellation works.
g_assert(test->getSnapshotAndCancel());
}
+class NotificationWebViewTest: public WebViewTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE_WITH_SETUP_TEARDOWN(NotificationWebViewTest, setup, teardown);
+
+ static void setup()
+ {
+ WebViewTest::shouldInitializeWebViewInConstructor = false;
+ }
+
+ static void teardown()
+ {
+ WebViewTest::shouldInitializeWebViewInConstructor = true;
+ }
+
+ enum NotificationEvent {
+ None,
+ Permission,
+ Shown,
+ Clicked,
+ OnClicked,
+ Closed,
+ OnClosed,
+ };
+
+ static gboolean permissionRequestCallback(WebKitWebView*, WebKitPermissionRequest *request, NotificationWebViewTest* test)
+ {
+ g_assert(WEBKIT_IS_NOTIFICATION_PERMISSION_REQUEST(request));
+ g_assert(test->m_isExpectingPermissionRequest);
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request));
+
+ test->m_event = Permission;
+
+ webkit_permission_request_allow(request);
+
+ g_main_loop_quit(test->m_mainLoop);
+
+ return TRUE;
+ }
+
+ static gboolean notificationClosedCallback(WebKitNotification* notification, NotificationWebViewTest* test)
+ {
+ g_assert(test->m_notification == notification);
+ test->m_notification = nullptr;
+ test->m_event = Closed;
+ if (g_main_loop_is_running(test->m_mainLoop))
+ g_main_loop_quit(test->m_mainLoop);
+ return TRUE;
+ }
+
+ static gboolean notificationClickedCallback(WebKitNotification* notification, NotificationWebViewTest* test)
+ {
+ g_assert(test->m_notification == notification);
+ test->m_event = Clicked;
+ return TRUE;
+ }
+
+ static gboolean showNotificationCallback(WebKitWebView*, WebKitNotification* notification, NotificationWebViewTest* test)
+ {
+ g_assert(!test->m_notification);
+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(notification));
+ test->m_notification = notification;
+ g_signal_connect(notification, "closed", G_CALLBACK(notificationClosedCallback), test);
+ g_signal_connect(notification, "clicked", G_CALLBACK(notificationClickedCallback), test);
+ test->m_event = Shown;
+ g_main_loop_quit(test->m_mainLoop);
+ return TRUE;
+ }
+
+ static void notificationsMessageReceivedCallback(WebKitUserContentManager* userContentManager, WebKitJavascriptResult* javascriptResult, NotificationWebViewTest* test)
+ {
+ GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult));
+
+ if (g_str_equal(valueString.get(), "clicked"))
+ test->m_event = OnClicked;
+ else if (g_str_equal(valueString.get(), "closed"))
+ test->m_event = OnClosed;
+
+ g_main_loop_quit(test->m_mainLoop);
+ }
+
+ void initialize()
+ {
+ initializeWebView();
+ g_signal_connect(m_webView, "permission-request", G_CALLBACK(permissionRequestCallback), this);
+ g_signal_connect(m_webView, "show-notification", G_CALLBACK(showNotificationCallback), this);
+ webkit_user_content_manager_register_script_message_handler(m_userContentManager.get(), "notifications");
+ g_signal_connect(m_userContentManager.get(), "script-message-received::notifications", G_CALLBACK(notificationsMessageReceivedCallback), this);
+ }
+
+ ~NotificationWebViewTest()
+ {
+ g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
+ g_signal_handlers_disconnect_matched(m_userContentManager.get(), G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this);
+ webkit_user_content_manager_unregister_script_message_handler(m_userContentManager.get(), "notifications");
+ }
+
+ bool hasPermission()
+ {
+ auto* result = runJavaScriptAndWaitUntilFinished("Notification.permission;", nullptr);
+ g_assert(result);
+ GUniquePtr<char> value(javascriptResultToCString(result));
+ return !g_strcmp0(value.get(), "granted");
+ }
+
+ void requestPermissionAndWaitUntilGiven()
+ {
+ m_event = None;
+ m_isExpectingPermissionRequest = true;
+ webkit_web_view_run_javascript(m_webView, "Notification.requestPermission();", nullptr, nullptr, nullptr);
+ g_main_loop_run(m_mainLoop);
+ }
+
+ void requestNotificationAndWaitUntilShown(const char* title, const char* body)
+ {
+ m_event = None;
+
+ GUniquePtr<char> jscode(g_strdup_printf("n = new Notification('%s', { body: '%s'});", title, body));
+ webkit_web_view_run_javascript(m_webView, jscode.get(), nullptr, nullptr, nullptr);
+
+ g_main_loop_run(m_mainLoop);
+ }
+
+ void requestNotificationAndWaitUntilShown(const char* title, const char* body, const char* tag)
+ {
+ m_event = None;
+
+ GUniquePtr<char> jscode(g_strdup_printf("n = new Notification('%s', { body: '%s', tag: '%s'});", title, body, tag));
+ webkit_web_view_run_javascript(m_webView, jscode.get(), nullptr, nullptr, nullptr);
+
+ g_main_loop_run(m_mainLoop);
+ }
+
+ void clickNotificationAndWaitUntilClicked()
+ {
+ m_event = None;
+ runJavaScriptAndWaitUntilFinished("n.onclick = function() { window.webkit.messageHandlers.notifications.postMessage('clicked'); }", nullptr);
+ webkit_notification_clicked(m_notification);
+ g_assert(m_event == Clicked);
+ g_main_loop_run(m_mainLoop);
+ }
+
+ void closeNotificationAndWaitUntilClosed()
+ {
+ m_event = None;
+ webkit_web_view_run_javascript(m_webView, "n.close()", nullptr, nullptr, nullptr);
+ g_main_loop_run(m_mainLoop);
+ }
+
+ void closeNotificationAndWaitUntilOnClosed()
+ {
+ g_assert(m_notification);
+ m_event = None;
+ runJavaScriptAndWaitUntilFinished("n.onclose = function() { window.webkit.messageHandlers.notifications.postMessage('closed'); }", nullptr);
+ webkit_notification_close(m_notification);
+ g_assert(m_event == Closed);
+ g_main_loop_run(m_mainLoop);
+ }
+
+ NotificationEvent m_event { None };
+ WebKitNotification* m_notification { nullptr };
+ bool m_isExpectingPermissionRequest { false };
+ bool m_hasPermission { false };
+};
+
+static void testWebViewNotification(NotificationWebViewTest* test, gconstpointer)
+{
+ test->initialize();
+
+ // Notifications don't work with local or special schemes.
+ test->loadURI(gServer->getURIForPath("/").data());
+ test->waitUntilLoadFinished();
+ g_assert(!test->hasPermission());
+
+ test->requestPermissionAndWaitUntilGiven();
+ g_assert(test->m_event == NotificationWebViewTest::Permission);
+ g_assert(test->hasPermission());
+
+ static const char* title = "This is a notification";
+ static const char* body = "This is the body.";
+ static const char* tag = "This is the tag.";
+ test->requestNotificationAndWaitUntilShown(title, body, tag);
+
+ g_assert(test->m_event == NotificationWebViewTest::Shown);
+ g_assert(test->m_notification);
+ g_assert_cmpstr(webkit_notification_get_title(test->m_notification), ==, title);
+ g_assert_cmpstr(webkit_notification_get_body(test->m_notification), ==, body);
+ g_assert_cmpstr(webkit_notification_get_tag(test->m_notification), ==, tag);
+
+ test->clickNotificationAndWaitUntilClicked();
+ g_assert(test->m_event == NotificationWebViewTest::OnClicked);
+
+ test->closeNotificationAndWaitUntilClosed();
+ g_assert(test->m_event == NotificationWebViewTest::Closed);
+
+ test->requestNotificationAndWaitUntilShown(title, body);
+ g_assert(test->m_event == NotificationWebViewTest::Shown);
+ g_assert_cmpstr(webkit_notification_get_tag(test->m_notification), ==, nullptr);
+
+ test->closeNotificationAndWaitUntilOnClosed();
+ g_assert(test->m_event == NotificationWebViewTest::OnClosed);
+
+ // The first notification should be closed automatically because the tag is
+ // the same. It will crash in showNotificationCallback on failure.
+ test->requestNotificationAndWaitUntilShown(title, body, tag);
+ test->requestNotificationAndWaitUntilShown(title, body, tag);
+ g_assert(test->m_event == NotificationWebViewTest::Shown);
+
+ // Notification should be closed when navigating to a different webpage.
+ test->loadURI(gServer->getURIForPath("/").data());
+ test->waitUntilLoadFinished();
+ g_assert(test->m_event == NotificationWebViewTest::Closed);
+}
+
+static void setInitialNotificationPermissionsAllowedCallback(WebKitWebContext* context, NotificationWebViewTest* test)
+{
+ GUniquePtr<char> baseURI(soup_uri_to_string(gServer->baseURI(), FALSE));
+ GList* allowedOrigins = g_list_prepend(nullptr, webkit_security_origin_new_for_uri(baseURI.get()));
+ webkit_web_context_initialize_notification_permissions(test->m_webContext.get(), allowedOrigins, nullptr);
+ g_list_free_full(allowedOrigins, reinterpret_cast<GDestroyNotify>(webkit_security_origin_unref));
+}
+
+static void setInitialNotificationPermissionsDisallowedCallback(WebKitWebContext* context, NotificationWebViewTest* test)
+{
+ GUniquePtr<char> baseURI(soup_uri_to_string(gServer->baseURI(), FALSE));
+ GList* disallowedOrigins = g_list_prepend(nullptr, webkit_security_origin_new_for_uri(baseURI.get()));
+ webkit_web_context_initialize_notification_permissions(test->m_webContext.get(), nullptr, disallowedOrigins);
+ g_list_free_full(disallowedOrigins, reinterpret_cast<GDestroyNotify>(webkit_security_origin_unref));
+}
+
+static void testWebViewNotificationInitialPermissionAllowed(NotificationWebViewTest* test, gconstpointer)
+{
+ g_signal_connect(test->m_webContext.get(), "initialize-notification-permissions", G_CALLBACK(setInitialNotificationPermissionsAllowedCallback), test);
+ test->initialize();
+
+ test->loadURI(gServer->getURIForPath("/").data());
+ test->waitUntilLoadFinished();
+ g_assert(test->hasPermission());
+
+ test->requestNotificationAndWaitUntilShown("This is a notification", "This is the body.");
+ g_assert(test->m_event == NotificationWebViewTest::Shown);
+}
+
+static void testWebViewNotificationInitialPermissionDisallowed(NotificationWebViewTest* test, gconstpointer)
+{
+ g_signal_connect(test->m_webContext.get(), "initialize-notification-permissions", G_CALLBACK(setInitialNotificationPermissionsDisallowedCallback), test);
+ test->initialize();
+
+ test->loadURI(gServer->getURIForPath("/").data());
+ test->waitUntilLoadFinished();
+ g_assert(!test->hasPermission());
+}
+
+static void testWebViewIsPlayingAudio(IsPlayingAudioWebViewTest* test, gconstpointer)
+{
+ // The web view must be realized for the video to start playback and
+ // trigger changes in WebKitWebView::is-playing-audio.
+ test->showInWindowAndWaitUntilMapped(GTK_WINDOW_TOPLEVEL);
+
+ // Initially, web views should always report no audio being played.
+ g_assert(!webkit_web_view_is_playing_audio(test->m_webView));
+
+ GUniquePtr<char> resourcePath(g_build_filename(Test::getResourcesDir(Test::WebKit2Resources).data(), "file-with-video.html", nullptr));
+ GUniquePtr<char> resourceURL(g_filename_to_uri(resourcePath.get(), nullptr, nullptr));
+ webkit_web_view_load_uri(test->m_webView, resourceURL.get());
+ test->waitUntilLoadFinished();
+ g_assert(!webkit_web_view_is_playing_audio(test->m_webView));
+
+ test->runJavaScriptAndWaitUntilFinished("playVideo();", nullptr);
+ if (!webkit_web_view_is_playing_audio(test->m_webView))
+ test->waitUntilIsPlayingAudioChanged();
+ g_assert(webkit_web_view_is_playing_audio(test->m_webView));
+
+ // Pause the video, and check again.
+ test->runJavaScriptAndWaitUntilFinished("document.getElementById('test-video').pause();", nullptr);
+ if (webkit_web_view_is_playing_audio(test->m_webView))
+ test->waitUntilIsPlayingAudioChanged();
+ g_assert(!webkit_web_view_is_playing_audio(test->m_webView));
+}
+
+static void testWebViewBackgroundColor(WebViewTest* test, gconstpointer)
+{
+ // White is the default background.
+ GdkRGBA rgba;
+ webkit_web_view_get_background_color(test->m_webView, &rgba);
+ g_assert_cmpfloat(rgba.red, ==, 1);
+ g_assert_cmpfloat(rgba.green, ==, 1);
+ g_assert_cmpfloat(rgba.blue, ==, 1);
+ g_assert_cmpfloat(rgba.alpha, ==, 1);
+
+ // Set a different (semi-transparent red).
+ rgba.red = 1;
+ rgba.green = 0;
+ rgba.blue = 0;
+ rgba.alpha = 0.5;
+ webkit_web_view_set_background_color(test->m_webView, &rgba);
+ g_assert_cmpfloat(rgba.red, ==, 1);
+ g_assert_cmpfloat(rgba.green, ==, 0);
+ g_assert_cmpfloat(rgba.blue, ==, 0);
+ g_assert_cmpfloat(rgba.alpha, ==, 0.5);
+
+ // The actual rendering can't be tested using unit tests, use
+ // MiniBrowser --bg-color="<color-value>" for manually testing this API.
+}
+
+static void testWebViewPreferredSize(WebViewTest* test, gconstpointer)
+{
+ test->loadHtml("<html style='width: 325px; height: 615px'></html>", nullptr);
+ test->waitUntilLoadFinished();
+ test->showInWindowAndWaitUntilMapped();
+ GtkRequisition minimunSize, naturalSize;
+ gtk_widget_get_preferred_size(GTK_WIDGET(test->m_webView), &minimunSize, &naturalSize);
+ g_assert_cmpint(minimunSize.width, ==, 0);
+ g_assert_cmpint(minimunSize.height, ==, 0);
+ g_assert_cmpint(naturalSize.width, ==, 325);
+ g_assert_cmpint(naturalSize.height, ==, 615);
+}
+
+class WebViewTitleTest: public WebViewTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(WebViewTitleTest);
+
+ static void titleChangedCallback(WebKitWebView* view, GParamSpec*, WebViewTitleTest* test)
+ {
+ test->m_webViewTitles.append(webkit_web_view_get_title(view));
+ }
+
+ WebViewTitleTest()
+ {
+ g_signal_connect(m_webView, "notify::title", G_CALLBACK(titleChangedCallback), this);
+ }
+
+ Vector<CString> m_webViewTitles;
+};
+
+static void testWebViewTitleChange(WebViewTitleTest* test, gconstpointer)
+{
+ g_assert_cmpint(test->m_webViewTitles.size(), ==, 0);
+
+ test->loadHtml("<head><title>Page Title</title></head>", nullptr);
+ test->waitUntilLoadFinished();
+ g_assert_cmpint(test->m_webViewTitles.size(), ==, 1);
+ g_assert_cmpstr(test->m_webViewTitles[0].data(), ==, "Page Title");
+
+ test->loadHtml("<head><title>Another Page Title</title></head>", nullptr);
+ test->waitUntilLoadFinished();
+ g_assert_cmpint(test->m_webViewTitles.size(), ==, 3);
+ /* Page title should be immediately unset when loading a new page. */
+ g_assert_cmpstr(test->m_webViewTitles[1].data(), ==, "");
+ g_assert_cmpstr(test->m_webViewTitles[2].data(), ==, "Another Page Title");
+
+ test->loadHtml("<p>This page has no title!</p>", nullptr);
+ test->waitUntilLoadFinished();
+ g_assert_cmpint(test->m_webViewTitles.size(), ==, 4);
+ g_assert_cmpstr(test->m_webViewTitles[3].data(), ==, "");
+
+ test->loadHtml("<script>document.title = 'one'; document.title = 'two'; document.title = 'three';</script>", nullptr);
+ test->waitUntilLoadFinished();
+ g_assert_cmpint(test->m_webViewTitles.size(), ==, 7);
+ g_assert_cmpstr(test->m_webViewTitles[4].data(), ==, "one");
+ g_assert_cmpstr(test->m_webViewTitles[5].data(), ==, "two");
+ g_assert_cmpstr(test->m_webViewTitles[6].data(), ==, "three");
+}
+
+static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
+{
+ if (message->method != SOUP_METHOD_GET) {
+ soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED);
+ return;
+ }
+
+ if (g_str_equal(path, "/")) {
+ soup_message_set_status(message, SOUP_STATUS_OK);
+ soup_message_body_complete(message->response_body);
+ } else
+ soup_message_set_status(message, SOUP_STATUS_NOT_FOUND);
+}
+
void beforeAll()
{
- WebViewTest::add("WebKitWebView", "default-context", testWebViewDefaultContext);
+ gServer = new WebKitTestServer();
+ gServer->run(serverCallback);
+
+ WebViewTest::add("WebKitWebView", "web-context", testWebViewWebContext);
+ WebViewTest::add("WebKitWebView", "web-context-lifetime", testWebViewWebContextLifetime);
+ WebViewTest::add("WebKitWebView", "ephemeral", testWebViewEphemeral);
WebViewTest::add("WebKitWebView", "custom-charset", testWebViewCustomCharset);
WebViewTest::add("WebKitWebView", "settings", testWebViewSettings);
WebViewTest::add("WebKitWebView", "zoom-level", testWebViewZoomLevel);
@@ -581,9 +1070,15 @@ void beforeAll()
WebViewTest::add("WebKitWebView", "can-show-mime-type", testWebViewCanShowMIMEType);
FormClientTest::add("WebKitWebView", "submit-form", testWebViewSubmitForm);
SaveWebViewTest::add("WebKitWebView", "save", testWebViewSave);
- WebViewTest::add("WebKitWebView", "view-mode", testWebViewMode);
SnapshotWebViewTest::add("WebKitWebView", "snapshot", testWebViewSnapshot);
WebViewTest::add("WebKitWebView", "page-visibility", testWebViewPageVisibility);
+ NotificationWebViewTest::add("WebKitWebView", "notification", testWebViewNotification);
+ NotificationWebViewTest::add("WebKitWebView", "notification-initial-permission-allowed", testWebViewNotificationInitialPermissionAllowed);
+ NotificationWebViewTest::add("WebKitWebView", "notification-initial-permission-disallowed", testWebViewNotificationInitialPermissionDisallowed);
+ IsPlayingAudioWebViewTest::add("WebKitWebView", "is-playing-audio", testWebViewIsPlayingAudio);
+ WebViewTest::add("WebKitWebView", "background-color", testWebViewBackgroundColor);
+ WebViewTest::add("WebKitWebView", "preferred-size", testWebViewPreferredSize);
+ WebViewTitleTest::add("WebKitWebView", "title-change", testWebViewTitleChange);
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebViewGroup.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebViewGroup.cpp
deleted file mode 100644
index 448abd2fe..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebViewGroup.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2013 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2,1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-
-#include "WebKitTestServer.h"
-#include "WebViewTest.h"
-#include <cstdarg>
-#include <gtk/gtk.h>
-#include <webkit2/webkit2.h>
-#include <wtf/gobject/GRefPtr.h>
-
-static WebKitTestServer* kServer;
-
-// These are all here so that they can be changed easily, if necessary.
-static const char* kStyleSheetHTML = "<html><div id=\"styledElement\">Sweet stylez!</div></html>";
-static const char* kInjectedStyleSheet = "#styledElement { font-weight: bold; }";
-static const char* kStyleSheetTestScript = "getComputedStyle(document.getElementById('styledElement'))['font-weight']";
-static const char* kStyleSheetTestScriptResult = "bold";
-
-static void testWebViewGroupDefault(Test* test, gconstpointer)
-{
- // Default group is shared by all WebViews by default.
- GRefPtr<WebKitWebView> webView1 = WEBKIT_WEB_VIEW(webkit_web_view_new());
- GRefPtr<WebKitWebView> webView2 = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_assert(webkit_web_view_get_group(webView1.get()) == webkit_web_view_get_group(webView2.get()));
-
- // Settings are shared by all web view in the same group.
- g_assert(webkit_web_view_get_settings(webView1.get()) == webkit_web_view_get_settings(webView2.get()));
- g_assert(webkit_web_view_get_settings(webView1.get()) == webkit_web_view_group_get_settings(webkit_web_view_get_group(webView2.get())));
-}
-
-static void testWebViewGroupNewGroup(Test* test, gconstpointer)
-{
- // Passing 0 as group name generates the name automatically.
- GRefPtr<WebKitWebViewGroup> viewGroup1 = adoptGRef(webkit_web_view_group_new(0));
- test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(viewGroup1.get()));
- g_assert(webkit_web_view_group_get_name(viewGroup1.get()));
-
- // New group with a given name.
- GRefPtr<WebKitWebViewGroup> viewGroup2 = adoptGRef(webkit_web_view_group_new("TestGroup2"));
- test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(viewGroup2.get()));
- g_assert_cmpstr(webkit_web_view_group_get_name(viewGroup2.get()), ==, "TestGroup2");
- g_assert_cmpstr(webkit_web_view_group_get_name(viewGroup2.get()), !=, webkit_web_view_group_get_name(viewGroup1.get()));
-
- // Every group has its own settings.
- g_assert(webkit_web_view_group_get_settings(viewGroup1.get()) != webkit_web_view_group_get_settings(viewGroup2.get()));
-}
-
-static void testWebViewNewWithGroup(Test* test, gconstpointer)
-{
- GRefPtr<WebKitWebViewGroup> viewGroup1 = adoptGRef(webkit_web_view_group_new("TestGroup1"));
- test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(viewGroup1.get()));
- GRefPtr<WebKitWebView> webView1 = WEBKIT_WEB_VIEW(webkit_web_view_new_with_group(viewGroup1.get()));
- g_assert(webkit_web_view_get_group(webView1.get()) == viewGroup1.get());
-
- GRefPtr<WebKitWebView> webView2 = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_assert(webkit_web_view_get_group(webView2.get()) != viewGroup1.get());
-
- // Settings should be different for views in different groups.
- g_assert(webkit_web_view_get_settings(webView1.get()) != webkit_web_view_get_settings(webView2.get()));
-}
-
-static void testWebViewGroupSettings(Test* test, gconstpointer)
-{
- GRefPtr<WebKitWebViewGroup> viewGroup1 = adoptGRef(webkit_web_view_group_new("TestGroup1"));
- test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(viewGroup1.get()));
- GRefPtr<WebKitSettings> newSettings = adoptGRef(webkit_settings_new_with_settings("enable-javascript", FALSE, nullptr));
- test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(newSettings.get()));
- webkit_web_view_group_set_settings(viewGroup1.get(), newSettings.get());
- g_assert(webkit_web_view_group_get_settings(viewGroup1.get()) == newSettings.get());
-
- GRefPtr<WebKitWebView> webView1 = WEBKIT_WEB_VIEW(webkit_web_view_new_with_group(viewGroup1.get()));
- GRefPtr<WebKitWebView> webView2 = WEBKIT_WEB_VIEW(webkit_web_view_new());
- WebKitSettings* webView1Settings = webkit_web_view_get_settings(webView1.get());
- WebKitSettings* webView2Settings = webkit_web_view_get_settings(webView2.get());
- g_assert(webView1Settings != webView2Settings);
- g_assert(webkit_settings_get_enable_javascript(webView1Settings) != webkit_settings_get_enable_javascript(webView2Settings));
-
- webkit_web_view_set_settings(webView1.get(), webView2Settings);
- g_assert(webkit_web_view_get_settings(webView1.get()) == webView2Settings);
- g_assert(webkit_web_view_group_get_settings(webkit_web_view_get_group(webView1.get())) == webView2Settings);
-}
-
-static bool isStyleSheetInjectedForURLAtPath(WebViewTest* test, const char* path)
-{
- test->loadURI(kServer->getURIForPath(path).data());
- test->waitUntilLoadFinished();
-
- GUniqueOutPtr<GError> error;
- WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished(kStyleSheetTestScript, &error.outPtr());
- g_assert(javascriptResult);
- g_assert(!error.get());
-
- GUniquePtr<char> resultString(WebViewTest::javascriptResultToCString(javascriptResult));
- return !g_strcmp0(resultString.get(), kStyleSheetTestScriptResult);
-}
-
-static void fillURLListFromPaths(char** list, const char* path, ...)
-{
- va_list argumentList;
- va_start(argumentList, path);
-
- int i = 0;
- while (path) {
- // FIXME: We must use a wildcard for the host here until http://wkbug.com/112476 is fixed.
- // Until that time patterns with port numbers in them will not properly match URLs with port numbers.
- list[i++] = g_strdup_printf("http://*/%s*", path);
- path = va_arg(argumentList, const char*);
- }
-}
-
-static void removeOldInjectedStyleSheetsAndResetLists(WebKitWebViewGroup* group, char** whitelist, char** blacklist)
-{
- webkit_web_view_group_remove_all_user_style_sheets(group);
-
- while (*whitelist) {
- g_free(*whitelist);
- *whitelist = 0;
- whitelist++;
- }
-
- while (*blacklist) {
- g_free(*blacklist);
- *blacklist = 0;
- blacklist++;
- }
-}
-
-static void testWebViewGroupInjectedStyleSheet(WebViewTest* test, gconstpointer)
-{
- WebKitWebViewGroup* group = webkit_web_view_get_group(test->m_webView);
- char* whitelist[3] = { 0, 0, 0 };
- char* blacklist[3] = { 0, 0, 0 };
-
- removeOldInjectedStyleSheetsAndResetLists(group, whitelist, blacklist);
-
- // Without a whitelist or a blacklist all URLs should have the injected style sheet.
- static const char* randomPath = "somerandompath";
- g_assert(!isStyleSheetInjectedForURLAtPath(test, randomPath));
- webkit_web_view_group_add_user_style_sheet(group, kInjectedStyleSheet, 0, 0, 0, WEBKIT_INJECTED_CONTENT_FRAMES_ALL);
- g_assert(isStyleSheetInjectedForURLAtPath(test, randomPath));
-
- removeOldInjectedStyleSheetsAndResetLists(group, whitelist, blacklist);
-
- fillURLListFromPaths(blacklist, randomPath, 0);
- webkit_web_view_group_add_user_style_sheet(group, kInjectedStyleSheet, 0, 0, blacklist, WEBKIT_INJECTED_CONTENT_FRAMES_ALL);
- g_assert(!isStyleSheetInjectedForURLAtPath(test, randomPath));
- g_assert(isStyleSheetInjectedForURLAtPath(test, "someotherrandompath"));
-
- removeOldInjectedStyleSheetsAndResetLists(group, whitelist, blacklist);
-
- static const char* inTheWhiteList = "inthewhitelist";
- static const char* notInWhitelist = "notinthewhitelist";
- static const char* inTheWhiteListAndBlackList = "inthewhitelistandblacklist";
-
- fillURLListFromPaths(whitelist, inTheWhiteList, inTheWhiteListAndBlackList, 0);
- fillURLListFromPaths(blacklist, inTheWhiteListAndBlackList, 0);
- webkit_web_view_group_add_user_style_sheet(group, kInjectedStyleSheet, 0, whitelist, blacklist, WEBKIT_INJECTED_CONTENT_FRAMES_ALL);
- g_assert(isStyleSheetInjectedForURLAtPath(test, inTheWhiteList));
- g_assert(!isStyleSheetInjectedForURLAtPath(test, inTheWhiteListAndBlackList));
- g_assert(!isStyleSheetInjectedForURLAtPath(test, notInWhitelist));
-
- // It's important to clean up the environment before other tests.
- removeOldInjectedStyleSheetsAndResetLists(group, whitelist, blacklist);
-}
-
-static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
-{
- soup_message_set_status(message, SOUP_STATUS_OK);
- soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kStyleSheetHTML, strlen(kStyleSheetHTML));
- soup_message_body_complete(message->response_body);
-}
-
-void beforeAll()
-{
- kServer = new WebKitTestServer();
- kServer->run(serverCallback);
-
- Test::add("WebKitWebViewGroup", "default-group", testWebViewGroupDefault);
- Test::add("WebKitWebViewGroup", "new-group", testWebViewGroupNewGroup);
- Test::add("WebKitWebView", "new-with-group", testWebViewNewWithGroup);
- Test::add("WebKitWebViewGroup", "settings", testWebViewGroupSettings);
- WebViewTest::add("WebKitWebViewGroup", "injected-style-sheet", testWebViewGroupInjectedStyleSheet);
-}
-
-void afterAll()
-{
- delete kServer;
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebViewEditor.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebViewEditor.cpp
index 9e69bfa48..00c02aed2 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebViewEditor.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebViewEditor.cpp
@@ -19,7 +19,7 @@
#include "config.h"
#include "WebViewTest.h"
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
class EditorTest: public WebViewTest {
public:
@@ -32,6 +32,7 @@ public:
: m_clipboard(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD))
, m_canExecuteEditingCommand(false)
, m_triesCount(0)
+ , m_editorState(nullptr)
{
gtk_clipboard_clear(m_clipboard);
}
@@ -73,25 +74,71 @@ public:
g_main_loop_run(m_mainLoop);
}
+ gchar* cutSelection()
+ {
+ g_assert(canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_CUT));
+ g_assert(canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_PASTE));
+
+ webkit_web_view_execute_editing_command(m_webView, WEBKIT_EDITING_COMMAND_CUT);
+ // There's no way to know when the selection has been cut to
+ // the clipboard, so use a timeout source to query the clipboard.
+ m_triesCount = 0;
+ g_timeout_add(kClipboardWaitTimeout, reinterpret_cast<GSourceFunc>(waitForClipboardText), this);
+ g_main_loop_run(m_mainLoop);
+
+ return gtk_clipboard_wait_for_text(m_clipboard);
+ }
+
+ WebKitEditorState* editorState()
+ {
+ if (m_editorState)
+ return m_editorState;
+
+ m_editorState = webkit_web_view_get_editor_state(m_webView);
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_editorState));
+ return m_editorState;
+ }
+
+ static void quitMainLoopInCallback(EditorTest* test)
+ {
+ g_main_loop_quit(test->m_mainLoop);
+ }
+
+ unsigned typingAttributes()
+ {
+ return webkit_editor_state_get_typing_attributes(editorState());
+ }
+
+ unsigned waitUntilTypingAttributesChanged()
+ {
+ unsigned long handlerID = g_signal_connect_swapped(editorState(), "notify::typing-attributes", G_CALLBACK(quitMainLoopInCallback), this);
+ g_main_loop_run(m_mainLoop);
+ g_signal_handler_disconnect(m_editorState, handlerID);
+ return typingAttributes();
+ }
+
GtkClipboard* m_clipboard;
bool m_canExecuteEditingCommand;
size_t m_triesCount;
+ WebKitEditorState* m_editorState;
};
+static const char* selectedSpanHTMLFormat =
+ "<html><body contentEditable=\"%s\">"
+ "<span id=\"mainspan\">All work and no play <span id=\"subspan\">make Jack a dull</span> boy.</span>"
+ "<script>document.getSelection().removeAllRanges();\n"
+ "document.getSelection().selectAllChildren(document.getElementById('subspan'));\n"
+ "</script></body></html>";
+
static void testWebViewEditorCutCopyPasteNonEditable(EditorTest* test, gconstpointer)
{
- static const char* selectedSpanHTML = "<html><body contentEditable=\"false\">"
- "<span id=\"mainspan\">All work and no play <span id=\"subspan\">make Jack a dull</span> boy.</span>"
- "<script>document.getSelection().collapse();\n"
- "document.getSelection().selectAllChildren(document.getElementById('subspan'));\n"
- "</script></body></html>";
-
// Nothing loaded yet.
g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_CUT));
g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_COPY));
g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_PASTE));
- test->loadHtml(selectedSpanHTML, 0);
+ GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, "false"));
+ test->loadHtml(selectedSpanHTML.get(), nullptr);
test->waitUntilLoadFinished();
g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_COPY));
@@ -107,18 +154,17 @@ static void testWebViewEditorCutCopyPasteNonEditable(EditorTest* test, gconstpoi
static void testWebViewEditorCutCopyPasteEditable(EditorTest* test, gconstpointer)
{
- static const char* selectedSpanHTML = "<html><body contentEditable=\"true\">"
- "<span id=\"mainspan\">All work and no play <span>make Jack a dull</span> boy.</span>"
- "<script>document.getSelection().collapse();\n"
- "document.getSelection().selectAllChildren(document.getElementById('mainspan'));\n"
- "</script></body></html>";
-
// Nothing loaded yet.
g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_CUT));
g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_COPY));
g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_PASTE));
- test->loadHtml(selectedSpanHTML, 0);
+ g_assert(!test->isEditable());
+ test->setEditable(true);
+ g_assert(test->isEditable());
+
+ GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, "false"));
+ test->loadHtml(selectedSpanHTML.get(), nullptr);
test->waitUntilLoadFinished();
// There's a selection.
@@ -128,20 +174,15 @@ static void testWebViewEditorCutCopyPasteEditable(EditorTest* test, gconstpointe
test->copyClipboard();
GUniquePtr<char> clipboardText(gtk_clipboard_wait_for_text(test->m_clipboard));
- g_assert_cmpstr(clipboardText.get(), ==, "All work and no play make Jack a dull boy.");
+ g_assert_cmpstr(clipboardText.get(), ==, "make Jack a dull");
}
static void testWebViewEditorSelectAllNonEditable(EditorTest* test, gconstpointer)
{
- static const char* selectedSpanHTML = "<html><body contentEditable=\"false\">"
- "<span id=\"mainspan\">All work and no play <span id=\"subspan\">make Jack a dull</span> boy.</span>"
- "<script>document.getSelection().collapse();\n"
- "document.getSelection().selectAllChildren(document.getElementById('subspan'));\n"
- "</script></body></html>";
-
g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL));
- test->loadHtml(selectedSpanHTML, 0);
+ GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, "false"));
+ test->loadHtml(selectedSpanHTML.get(), nullptr);
test->waitUntilLoadFinished();
g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL));
@@ -162,15 +203,14 @@ static void testWebViewEditorSelectAllNonEditable(EditorTest* test, gconstpointe
static void testWebViewEditorSelectAllEditable(EditorTest* test, gconstpointer)
{
- static const char* selectedSpanHTML = "<html><body contentEditable=\"true\">"
- "<span id=\"mainspan\">All work and no play <span id=\"subspan\">make Jack a dull</span> boy.</span>"
- "<script>document.getSelection().collapse();\n"
- "document.getSelection().selectAllChildren(document.getElementById('subspan'));\n"
- "</script></body></html>";
-
g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL));
- test->loadHtml(selectedSpanHTML, 0);
+ g_assert(!test->isEditable());
+ test->setEditable(true);
+ g_assert(test->isEditable());
+
+ GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, "false"));
+ test->loadHtml(selectedSpanHTML.get(), nullptr);
test->waitUntilLoadFinished();
g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL));
@@ -189,12 +229,240 @@ static void testWebViewEditorSelectAllEditable(EditorTest* test, gconstpointer)
g_assert_cmpstr(clipboardText.get(), ==, "All work and no play make Jack a dull boy.");
}
+static void loadContentsAndTryToCutSelection(EditorTest* test, bool contentEditable)
+{
+ // View is not editable by default.
+ g_assert(!test->isEditable());
+
+ GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, contentEditable ? "true" : "false"));
+ test->loadHtml(selectedSpanHTML.get(), nullptr);
+ test->waitUntilLoadFinished();
+
+ g_assert(!test->isEditable());
+ test->setEditable(true);
+ g_assert(test->isEditable());
+
+ // Cut the selection to the clipboard to see if the view is indeed editable.
+ GUniquePtr<char> clipboardText(test->cutSelection());
+ g_assert_cmpstr(clipboardText.get(), ==, "make Jack a dull");
+
+ // Reset the editable for next test.
+ test->setEditable(false);
+ g_assert(!test->isEditable());
+}
+
+static void testWebViewEditorNonEditable(EditorTest* test)
+{
+ GUniquePtr<char> selectedSpanHTML(g_strdup_printf(selectedSpanHTMLFormat, "false"));
+ test->loadHtml(selectedSpanHTML.get(), nullptr);
+ test->waitUntilLoadFinished();
+
+ g_assert(!test->isEditable());
+ test->setEditable(true);
+ g_assert(test->isEditable());
+ test->setEditable(false);
+ g_assert(!test->isEditable());
+
+ // Check if view is indeed non-editable.
+ g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_CUT));
+ g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_PASTE));
+}
+
+static void testWebViewEditorEditable(EditorTest* test, gconstpointer)
+{
+ testWebViewEditorNonEditable(test);
+
+ // Reset the editable for next test.
+ test->setEditable(false);
+ g_assert(!test->isEditable());
+
+ loadContentsAndTryToCutSelection(test, true);
+
+ // Reset the editable for next test.
+ test->setEditable(false);
+ g_assert(!test->isEditable());
+
+ loadContentsAndTryToCutSelection(test, false);
+}
+
+static void testWebViewEditorEditorStateTypingAttributes(EditorTest* test, gconstpointer)
+{
+ static const char* typingAttributesHTML =
+ "<html><body>"
+ "normal <b>bold </b><i>italic </i><u>underline </u><strike>strike </strike>"
+ "<b><i>boldanditalic </i></b>"
+ "</body></html>";
+
+ test->loadHtml(typingAttributesHTML, nullptr);
+ test->waitUntilLoadFinished();
+ test->setEditable(true);
+
+ unsigned typingAttributes = test->typingAttributes();
+ g_assert_cmpuint(typingAttributes, ==, WEBKIT_EDITOR_TYPING_ATTRIBUTE_NONE);
+
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD);
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
+
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD));
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC);
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
+
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC));
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE);
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
+
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH);
+
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD);
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC);
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
+
+ // Selections.
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveToBeginningOfDocument");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForwardAndModifySelection");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert_cmpuint(typingAttributes, ==, WEBKIT_EDITOR_TYPING_ATTRIBUTE_NONE);
+
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForwardAndModifySelection");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD);
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
+
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForwardAndModifySelection");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD));
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC);
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
+
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForwardAndModifySelection");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC));
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE);
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
+
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForwardAndModifySelection");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH);
+
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveForward");
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveWordForwardAndModifySelection");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_BOLD);
+ g_assert(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_ITALIC);
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_UNDERLINE));
+ g_assert(!(typingAttributes & WEBKIT_EDITOR_TYPING_ATTRIBUTE_STRIKETHROUGH));
+
+ webkit_web_view_execute_editing_command(test->m_webView, "SelectAll");
+ typingAttributes = test->waitUntilTypingAttributesChanged();
+ g_assert_cmpuint(typingAttributes, ==, WEBKIT_EDITOR_TYPING_ATTRIBUTE_NONE);
+}
+
+static void testWebViewEditorInsertImage(EditorTest* test, gconstpointer)
+{
+ test->loadHtml("<html><body></body></html>", "file:///");
+ test->waitUntilLoadFinished();
+ test->setEditable(true);
+
+ GUniquePtr<char> imagePath(g_build_filename(Test::getResourcesDir().data(), "blank.ico", nullptr));
+ GUniquePtr<char> imageURI(g_filename_to_uri(imagePath.get(), nullptr, nullptr));
+ webkit_web_view_execute_editing_command_with_argument(test->m_webView, WEBKIT_EDITING_COMMAND_INSERT_IMAGE, imageURI.get());
+ GUniqueOutPtr<GError> error;
+ WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByTagName('IMG')[0].src", &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error);
+ GUniquePtr<char> resultString(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(resultString.get(), ==, imageURI.get());
+}
+
+static void testWebViewEditorCreateLink(EditorTest* test, gconstpointer)
+{
+ test->loadHtml("<html><body onload=\"document.getSelection().selectAllChildren(document.body);\">webkitgtk.org</body></html>", nullptr);
+ test->waitUntilLoadFinished();
+ test->setEditable(true);
+
+ static const char* webkitGTKURL = "http://www.webkitgtk.org/";
+ webkit_web_view_execute_editing_command_with_argument(test->m_webView, WEBKIT_EDITING_COMMAND_CREATE_LINK, webkitGTKURL);
+ GUniqueOutPtr<GError> error;
+ WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByTagName('A')[0].href;", &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error);
+ GUniquePtr<char> resultString(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(resultString.get(), ==, webkitGTKURL);
+ javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByTagName('A')[0].innerText;", &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error);
+ resultString.reset(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(resultString.get(), ==, "webkitgtk.org");
+
+ // When there isn't text selected, the URL is used as link text.
+ webkit_web_view_execute_editing_command(test->m_webView, "MoveToEndOfLine");
+ webkit_web_view_execute_editing_command_with_argument(test->m_webView, WEBKIT_EDITING_COMMAND_CREATE_LINK, webkitGTKURL);
+ javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByTagName('A')[1].href;", &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error);
+ resultString.reset(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(resultString.get(), ==, webkitGTKURL);
+ javascriptResult = test->runJavaScriptAndWaitUntilFinished("document.getElementsByTagName('A')[1].innerText;", &error.outPtr());
+ g_assert(javascriptResult);
+ g_assert(!error);
+ resultString.reset(WebViewTest::javascriptResultToCString(javascriptResult));
+ g_assert_cmpstr(resultString.get(), ==, webkitGTKURL);
+}
+
void beforeAll()
{
+ EditorTest::add("WebKitWebView", "editable/editable", testWebViewEditorEditable);
EditorTest::add("WebKitWebView", "cut-copy-paste/non-editable", testWebViewEditorCutCopyPasteNonEditable);
EditorTest::add("WebKitWebView", "cut-copy-paste/editable", testWebViewEditorCutCopyPasteEditable);
EditorTest::add("WebKitWebView", "select-all/non-editable", testWebViewEditorSelectAllNonEditable);
EditorTest::add("WebKitWebView", "select-all/editable", testWebViewEditorSelectAllEditable);
+ EditorTest::add("WebKitWebView", "editor-state/typing-attributes", testWebViewEditorEditorStateTypingAttributes);
+ EditorTest::add("WebKitWebView", "insert/image", testWebViewEditorInsertImage);
+ EditorTest::add("WebKitWebView", "insert/link", testWebViewEditorCreateLink);
}
void afterAll()
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebsiteData.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebsiteData.cpp
new file mode 100644
index 000000000..4959e838e
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebsiteData.cpp
@@ -0,0 +1,537 @@
+/*
+ * Copyright (C) 2017 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2,1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include "WebKitTestServer.h"
+#include "WebViewTest.h"
+
+static WebKitTestServer* kServer;
+
+static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
+{
+ if (message->method != SOUP_METHOD_GET) {
+ soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED);
+ return;
+ }
+
+ if (g_str_equal(path, "/empty")) {
+ const char* emptyHTML = "<html><body></body></html>";
+ soup_message_headers_replace(message->response_headers, "Set-Cookie", "foo=bar; Max-Age=60");
+ soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, emptyHTML, strlen(emptyHTML));
+ soup_message_body_complete(message->response_body);
+ soup_message_set_status(message, SOUP_STATUS_OK);
+ } else if (g_str_equal(path, "/appcache")) {
+ const char* appcacheHTML = "<html manifest=appcache.manifest><body></body></html>";
+ soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, appcacheHTML, strlen(appcacheHTML));
+ soup_message_body_complete(message->response_body);
+ soup_message_set_status(message, SOUP_STATUS_OK);
+ } else if (g_str_equal(path, "/appcache.manifest")) {
+ const char* appcacheManifest = "CACHE MANIFEST\nCACHE:\nappcache/foo.txt\n";
+ soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, appcacheManifest, strlen(appcacheManifest));
+ soup_message_body_complete(message->response_body);
+ soup_message_set_status(message, SOUP_STATUS_OK);
+ } else if (g_str_equal(path, "/appcache/foo.txt")) {
+ soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, "foo", 3);
+ soup_message_body_complete(message->response_body);
+ soup_message_set_status(message, SOUP_STATUS_OK);
+ } else if (g_str_equal(path, "/sessionstorage")) {
+ const char* sessionStorageHTML = "<html><body onload=\"sessionStorage.foo = 'bar';\"></body></html>";
+ soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, sessionStorageHTML, strlen(sessionStorageHTML));
+ soup_message_body_complete(message->response_body);
+ soup_message_set_status(message, SOUP_STATUS_OK);
+ } else if (g_str_equal(path, "/localstorage")) {
+ const char* localStorageHTML = "<html><body onload=\"localStorage.foo = 'bar';\"></body></html>";
+ soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, localStorageHTML, strlen(localStorageHTML));
+ soup_message_body_complete(message->response_body);
+ soup_message_set_status(message, SOUP_STATUS_OK);
+ } else
+ soup_message_set_status(message, SOUP_STATUS_NOT_FOUND);
+}
+
+class WebsiteDataTest : public WebViewTest {
+public:
+ MAKE_GLIB_TEST_FIXTURE(WebsiteDataTest);
+
+
+ WebsiteDataTest()
+ : m_manager(webkit_web_context_get_website_data_manager(webkit_web_view_get_context(m_webView)))
+ {
+ g_assert(WEBKIT_IS_WEBSITE_DATA_MANAGER(m_manager));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_manager));
+ // WebsiteDataStore creates a new WebProcessPool when used before any secondary process has been created.
+ // Ensure we have a web process by always loading about:blank here.
+ loadURI("about:blank");
+ waitUntilLoadFinished();
+ }
+
+ ~WebsiteDataTest()
+ {
+ g_list_free_full(m_dataList, reinterpret_cast<GDestroyNotify>(webkit_website_data_unref));
+ }
+
+ GList* fetch(WebKitWebsiteDataTypes types)
+ {
+ if (m_dataList) {
+ g_list_free_full(m_dataList, reinterpret_cast<GDestroyNotify>(webkit_website_data_unref));
+ m_dataList = nullptr;
+ }
+ webkit_website_data_manager_fetch(m_manager, types, nullptr, [](GObject*, GAsyncResult* result, gpointer userData) {
+ WebsiteDataTest* test = static_cast<WebsiteDataTest*>(userData);
+ test->m_dataList = webkit_website_data_manager_fetch_finish(test->m_manager, result, nullptr);
+ test->quitMainLoop();
+ }, this);
+ g_main_loop_run(m_mainLoop);
+ return m_dataList;
+ }
+
+ void remove(WebKitWebsiteDataTypes types, GList* dataList)
+ {
+ webkit_website_data_manager_remove(m_manager, types, dataList, nullptr, [](GObject*, GAsyncResult* result, gpointer userData) {
+ WebsiteDataTest* test = static_cast<WebsiteDataTest*>(userData);
+ g_assert(webkit_website_data_manager_remove_finish(test->m_manager, result, nullptr));
+ test->quitMainLoop();
+ }, this);
+ g_main_loop_run(m_mainLoop);
+ }
+
+ void clear(WebKitWebsiteDataTypes types, GTimeSpan timeSpan)
+ {
+ webkit_website_data_manager_clear(m_manager, types, timeSpan, nullptr, [](GObject*, GAsyncResult* result, gpointer userData) {
+ WebsiteDataTest* test = static_cast<WebsiteDataTest*>(userData);
+ g_assert(webkit_website_data_manager_clear_finish(test->m_manager, result, nullptr));
+ test->quitMainLoop();
+ }, this);
+ g_main_loop_run(m_mainLoop);
+ }
+
+ WebKitWebsiteDataManager* m_manager;
+ GList* m_dataList { nullptr };
+};
+
+static void testWebsiteDataConfiguration(WebsiteDataTest* test, gconstpointer)
+{
+ // Base directories are not used by TestMain.
+ g_assert(!webkit_website_data_manager_get_base_data_directory(test->m_manager));
+ g_assert(!webkit_website_data_manager_get_base_cache_directory(test->m_manager));
+
+ GUniquePtr<char> localStorageDirectory(g_build_filename(Test::dataDirectory(), "local-storage", nullptr));
+ g_assert_cmpstr(localStorageDirectory.get(), ==, webkit_website_data_manager_get_local_storage_directory(test->m_manager));
+ g_assert(g_file_test(localStorageDirectory.get(), G_FILE_TEST_IS_DIR));
+
+ test->loadURI(kServer->getURIForPath("/empty").data());
+ test->waitUntilLoadFinished();
+ test->runJavaScriptAndWaitUntilFinished("window.indexedDB.open('TestDatabase');", nullptr);
+ GUniquePtr<char> indexedDBDirectory(g_build_filename(Test::dataDirectory(), "indexeddb", nullptr));
+ g_assert_cmpstr(indexedDBDirectory.get(), ==, webkit_website_data_manager_get_indexeddb_directory(test->m_manager));
+ g_assert(g_file_test(indexedDBDirectory.get(), G_FILE_TEST_IS_DIR));
+
+ GUniquePtr<char> webSQLDirectory(g_build_filename(Test::dataDirectory(), "websql", nullptr));
+ g_assert_cmpstr(webSQLDirectory.get(), ==, webkit_website_data_manager_get_websql_directory(test->m_manager));
+ test->runJavaScriptAndWaitUntilFinished("db = openDatabase(\"TestDatabase\", \"1.0\", \"TestDatabase\", 1);", nullptr);
+ g_assert(g_file_test(webSQLDirectory.get(), G_FILE_TEST_IS_DIR));
+
+ test->loadURI(kServer->getURIForPath("/appcache").data());
+ test->waitUntilLoadFinished();
+ GUniquePtr<char> applicationCacheDirectory(g_build_filename(Test::dataDirectory(), "appcache", nullptr));
+ g_assert_cmpstr(applicationCacheDirectory.get(), ==, webkit_website_data_manager_get_offline_application_cache_directory(test->m_manager));
+ GUniquePtr<char> applicationCacheDatabase(g_build_filename(applicationCacheDirectory.get(), "ApplicationCache.db", nullptr));
+ unsigned triesCount = 4;
+ while (!g_file_test(applicationCacheDatabase.get(), G_FILE_TEST_IS_REGULAR) && --triesCount)
+ test->wait(0.25);
+ g_assert(triesCount);
+
+ GUniquePtr<char> diskCacheDirectory(g_build_filename(Test::dataDirectory(), "disk-cache", nullptr));
+ g_assert_cmpstr(diskCacheDirectory.get(), ==, webkit_website_data_manager_get_disk_cache_directory(test->m_manager));
+ g_assert(g_file_test(diskCacheDirectory.get(), G_FILE_TEST_IS_DIR));
+
+ // Clear all persistent caches, since the data dir is common to all test cases.
+ static const WebKitWebsiteDataTypes persistentCaches = static_cast<WebKitWebsiteDataTypes>(WEBKIT_WEBSITE_DATA_DISK_CACHE | WEBKIT_WEBSITE_DATA_LOCAL_STORAGE
+ | WEBKIT_WEBSITE_DATA_WEBSQL_DATABASES | WEBKIT_WEBSITE_DATA_INDEXEDDB_DATABASES | WEBKIT_WEBSITE_DATA_OFFLINE_APPLICATION_CACHE);
+ test->clear(persistentCaches, 0);
+ g_assert(!test->fetch(persistentCaches));
+
+ // The default context should have a different manager with different configuration.
+ WebKitWebsiteDataManager* defaultManager = webkit_web_context_get_website_data_manager(webkit_web_context_get_default());
+ g_assert(WEBKIT_IS_WEBSITE_DATA_MANAGER(defaultManager));
+ g_assert(test->m_manager != defaultManager);
+ g_assert_cmpstr(webkit_website_data_manager_get_local_storage_directory(test->m_manager), !=, webkit_website_data_manager_get_local_storage_directory(defaultManager));
+ g_assert_cmpstr(webkit_website_data_manager_get_indexeddb_directory(test->m_manager), !=, webkit_website_data_manager_get_indexeddb_directory(defaultManager));
+ g_assert_cmpstr(webkit_website_data_manager_get_disk_cache_directory(test->m_manager), !=, webkit_website_data_manager_get_disk_cache_directory(defaultManager));
+ g_assert_cmpstr(webkit_website_data_manager_get_offline_application_cache_directory(test->m_manager), !=, webkit_website_data_manager_get_offline_application_cache_directory(defaultManager));
+ g_assert_cmpstr(webkit_website_data_manager_get_websql_directory(test->m_manager), !=, webkit_website_data_manager_get_websql_directory(defaultManager));
+
+ // Using Test::dataDirectory() we get the default configuration but for a differrent prefix.
+ GRefPtr<WebKitWebsiteDataManager> baseDataManager = adoptGRef(webkit_website_data_manager_new("base-data-directory", Test::dataDirectory(), "base-cache-directory", Test::dataDirectory(), nullptr));
+ g_assert(WEBKIT_IS_WEBSITE_DATA_MANAGER(baseDataManager.get()));
+
+ localStorageDirectory.reset(g_build_filename(Test::dataDirectory(), "localstorage", nullptr));
+ g_assert_cmpstr(webkit_website_data_manager_get_local_storage_directory(baseDataManager.get()), ==, localStorageDirectory.get());
+
+ indexedDBDirectory.reset(g_build_filename(Test::dataDirectory(), "databases", "indexeddb", nullptr));
+ g_assert_cmpstr(webkit_website_data_manager_get_indexeddb_directory(baseDataManager.get()), ==, indexedDBDirectory.get());
+
+ applicationCacheDirectory.reset(g_build_filename(Test::dataDirectory(), "applications", nullptr));
+ g_assert_cmpstr(webkit_website_data_manager_get_offline_application_cache_directory(baseDataManager.get()), ==, applicationCacheDirectory.get());
+
+ webSQLDirectory.reset(g_build_filename(Test::dataDirectory(), "databases", nullptr));
+ g_assert_cmpstr(webkit_website_data_manager_get_websql_directory(baseDataManager.get()), ==, webSQLDirectory.get());
+
+ g_assert_cmpstr(webkit_website_data_manager_get_disk_cache_directory(baseDataManager.get()), ==, Test::dataDirectory());
+
+ // Any specific configuration provided takes precedence over base dirs.
+ indexedDBDirectory.reset(g_build_filename(Test::dataDirectory(), "mycustomindexeddb", nullptr));
+ applicationCacheDirectory.reset(g_build_filename(Test::dataDirectory(), "mycustomappcache", nullptr));
+ baseDataManager = adoptGRef(webkit_website_data_manager_new("base-data-directory", Test::dataDirectory(), "base-cache-directory", Test::dataDirectory(),
+ "indexeddb-directory", indexedDBDirectory.get(), "offline-application-cache-directory", applicationCacheDirectory.get(), nullptr));
+ g_assert_cmpstr(webkit_website_data_manager_get_indexeddb_directory(baseDataManager.get()), ==, indexedDBDirectory.get());
+ g_assert_cmpstr(webkit_website_data_manager_get_offline_application_cache_directory(baseDataManager.get()), ==, applicationCacheDirectory.get());
+ // The result should be the same as previous manager.
+ g_assert_cmpstr(webkit_website_data_manager_get_local_storage_directory(baseDataManager.get()), ==, localStorageDirectory.get());
+ g_assert_cmpstr(webkit_website_data_manager_get_websql_directory(baseDataManager.get()), ==, webSQLDirectory.get());
+ g_assert_cmpstr(webkit_website_data_manager_get_disk_cache_directory(baseDataManager.get()), ==, Test::dataDirectory());
+}
+
+static void ephemeralViewloadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent, WebViewTest* test)
+{
+ if (loadEvent != WEBKIT_LOAD_FINISHED)
+ return;
+ g_signal_handlers_disconnect_by_func(webView, reinterpret_cast<void*>(ephemeralViewloadChanged), test);
+ test->quitMainLoop();
+}
+
+static void testWebsiteDataEphemeral(WebViewTest* test, gconstpointer)
+{
+ GRefPtr<WebKitWebsiteDataManager> manager = adoptGRef(webkit_website_data_manager_new_ephemeral());
+ g_assert(webkit_website_data_manager_is_ephemeral(manager.get()));
+ g_assert(!webkit_website_data_manager_get_base_data_directory(manager.get()));
+ g_assert(!webkit_website_data_manager_get_base_cache_directory(manager.get()));
+ g_assert(!webkit_website_data_manager_get_local_storage_directory(manager.get()));
+ g_assert(!webkit_website_data_manager_get_disk_cache_directory(manager.get()));
+ g_assert(!webkit_website_data_manager_get_offline_application_cache_directory(manager.get()));
+ g_assert(!webkit_website_data_manager_get_indexeddb_directory(manager.get()));
+ g_assert(!webkit_website_data_manager_get_websql_directory(manager.get()));
+
+ // Configuration is ignored when is-ephemeral is used.
+ manager = adoptGRef(WEBKIT_WEBSITE_DATA_MANAGER(g_object_new(WEBKIT_TYPE_WEBSITE_DATA_MANAGER, "base-data-directory", Test::dataDirectory(), "is-ephemeral", TRUE, nullptr)));
+ g_assert(webkit_website_data_manager_is_ephemeral(manager.get()));
+ g_assert(!webkit_website_data_manager_get_base_data_directory(manager.get()));
+
+ // Non persistent data can be queried in an ephemeral manager.
+ GRefPtr<WebKitWebContext> webContext = adoptGRef(webkit_web_context_new_with_website_data_manager(manager.get()));
+ g_assert(webkit_web_context_is_ephemeral(webContext.get()));
+ GRefPtr<WebKitWebView> webView = WEBKIT_WEB_VIEW(webkit_web_view_new_with_context(webContext.get()));
+ g_assert(webkit_web_view_is_ephemeral(webView.get()));
+ g_assert(webkit_web_view_get_website_data_manager(webView.get()) == manager.get());
+
+ g_signal_connect(webView.get(), "load-changed", G_CALLBACK(ephemeralViewloadChanged), test);
+ webkit_web_view_load_uri(webView.get(), kServer->getURIForPath("/empty").data());
+ g_main_loop_run(test->m_mainLoop);
+
+ webkit_website_data_manager_fetch(manager.get(), WEBKIT_WEBSITE_DATA_MEMORY_CACHE, nullptr, [](GObject* manager, GAsyncResult* result, gpointer userData) {
+ auto* test = static_cast<WebViewTest*>(userData);
+ GList* dataList = webkit_website_data_manager_fetch_finish(WEBKIT_WEBSITE_DATA_MANAGER(manager), result, nullptr);
+ g_assert(dataList);
+ g_assert_cmpuint(g_list_length(dataList), ==, 1);
+ WebKitWebsiteData* data = static_cast<WebKitWebsiteData*>(dataList->data);
+ g_assert(data);
+ WebKitSecurityOrigin* origin = webkit_security_origin_new_for_uri(kServer->getURIForPath("/").data());
+ g_assert_cmpstr(webkit_website_data_get_name(data), ==, webkit_security_origin_get_host(origin));
+ webkit_security_origin_unref(origin);
+ g_list_free_full(dataList, reinterpret_cast<GDestroyNotify>(webkit_website_data_unref));
+ test->quitMainLoop();
+ }, test);
+ g_main_loop_run(test->m_mainLoop);
+}
+
+static void testWebsiteDataCache(WebsiteDataTest* test, gconstpointer)
+{
+ static const WebKitWebsiteDataTypes cacheTypes = static_cast<WebKitWebsiteDataTypes>(WEBKIT_WEBSITE_DATA_MEMORY_CACHE | WEBKIT_WEBSITE_DATA_DISK_CACHE);
+ GList* dataList = test->fetch(cacheTypes);
+ g_assert(!dataList);
+
+ test->loadURI(kServer->getURIForPath("/empty").data());
+ test->waitUntilLoadFinished();
+
+ // Disk cache delays the storing of initial resources for 1 second to avoid
+ // affecting early page load. So, wait 1 second here to make sure resources
+ // have already been stored.
+ test->wait(1);
+
+ dataList = test->fetch(cacheTypes);
+ g_assert(dataList);
+ g_assert_cmpuint(g_list_length(dataList), ==, 1);
+ WebKitWebsiteData* data = static_cast<WebKitWebsiteData*>(dataList->data);
+ g_assert(data);
+ WebKitSecurityOrigin* origin = webkit_security_origin_new_for_uri(kServer->getURIForPath("/").data());
+ g_assert_cmpstr(webkit_website_data_get_name(data), ==, webkit_security_origin_get_host(origin));
+ webkit_security_origin_unref(origin);
+ g_assert_cmpuint(webkit_website_data_get_types(data), ==, cacheTypes);
+ // Memory cache size is unknown.
+ g_assert_cmpuint(webkit_website_data_get_size(data, WEBKIT_WEBSITE_DATA_MEMORY_CACHE), ==, 0);
+ g_assert_cmpuint(webkit_website_data_get_size(data, WEBKIT_WEBSITE_DATA_DISK_CACHE), >, 0);
+
+ // Try again but only getting disk cache.
+ dataList = test->fetch(WEBKIT_WEBSITE_DATA_DISK_CACHE);
+ g_assert(dataList);
+ g_assert_cmpuint(g_list_length(dataList), ==, 1);
+ data = static_cast<WebKitWebsiteData*>(dataList->data);
+ g_assert(data);
+ g_assert(webkit_website_data_get_types(data) & WEBKIT_WEBSITE_DATA_DISK_CACHE);
+ g_assert(!(webkit_website_data_get_types(data) & WEBKIT_WEBSITE_DATA_MEMORY_CACHE));
+
+ GUniquePtr<char> fileURL(g_strdup_printf("file://%s/simple.html", Test::getResourcesDir(Test::WebKit2Resources).data()));
+ test->loadURI(fileURL.get());
+ test->waitUntilLoadFinished();
+
+ fileURL.reset(g_strdup_printf("file://%s/simple2.html", Test::getResourcesDir(Test::WebKit2Resources).data()));
+ test->loadURI(fileURL.get());
+ test->waitUntilLoadFinished();
+
+ // Local files are grouped.
+ dataList = test->fetch(cacheTypes);
+ g_assert(dataList);
+ g_assert_cmpuint(g_list_length(dataList), ==, 2);
+ GList* itemList = g_list_find_custom(dataList, nullptr, [](gconstpointer item, gconstpointer) -> int {
+ WebKitWebsiteData* data = static_cast<WebKitWebsiteData*>(const_cast<gpointer>(item));
+ return g_strcmp0(webkit_website_data_get_name(data), "Local files");
+ });
+ g_assert(itemList);
+ data = static_cast<WebKitWebsiteData*>(itemList->data);
+ g_assert(data);
+ g_assert(webkit_website_data_get_types(data) & WEBKIT_WEBSITE_DATA_MEMORY_CACHE);
+ // Local files are never stored in disk cache.
+ g_assert(!(webkit_website_data_get_types(data) & WEBKIT_WEBSITE_DATA_DISK_CACHE));
+
+ // Clear data modified since the last microsecond should not clear anything.
+ // Use disk-cache because memory cache ignores the modified since.
+ test->clear(WEBKIT_WEBSITE_DATA_DISK_CACHE, 1);
+ dataList = test->fetch(cacheTypes);
+ g_assert(dataList);
+ g_assert_cmpuint(g_list_length(dataList), ==, 2);
+
+ // Remove memory cache only for local files.
+ itemList = g_list_find_custom(dataList, nullptr, [](gconstpointer item, gconstpointer) -> int {
+ WebKitWebsiteData* data = static_cast<WebKitWebsiteData*>(const_cast<gpointer>(item));
+ return g_strcmp0(webkit_website_data_get_name(data), "Local files");
+ });
+ g_assert(itemList);
+ GList removeList = { itemList->data, nullptr, nullptr };
+ test->remove(WEBKIT_WEBSITE_DATA_MEMORY_CACHE, &removeList);
+ dataList = test->fetch(cacheTypes);
+ g_assert(dataList);
+ g_assert_cmpuint(g_list_length(dataList), ==, 1);
+ data = static_cast<WebKitWebsiteData*>(dataList->data);
+ g_assert(webkit_website_data_get_types(data) & WEBKIT_WEBSITE_DATA_DISK_CACHE);
+
+ // Clear all.
+ test->clear(cacheTypes, 0);
+ dataList = test->fetch(cacheTypes);
+ g_assert(!dataList);
+}
+
+static void testWebsiteDataStorage(WebsiteDataTest* test, gconstpointer)
+{
+ static const WebKitWebsiteDataTypes storageTypes = static_cast<WebKitWebsiteDataTypes>(WEBKIT_WEBSITE_DATA_SESSION_STORAGE | WEBKIT_WEBSITE_DATA_LOCAL_STORAGE);
+ GList* dataList = test->fetch(storageTypes);
+ g_assert(!dataList);
+
+ test->loadURI(kServer->getURIForPath("/sessionstorage").data());
+ test->waitUntilLoadFinished();
+
+ test->loadURI(kServer->getURIForPath("/localstorage").data());
+ test->waitUntilLoadFinished();
+
+ // Local storage uses a 1 second timer to update the database.
+ test->wait(1);
+
+ dataList = test->fetch(storageTypes);
+ g_assert(dataList);
+ g_assert_cmpuint(g_list_length(dataList), ==, 1);
+ WebKitWebsiteData* data = static_cast<WebKitWebsiteData*>(dataList->data);
+ g_assert(data);
+ WebKitSecurityOrigin* origin = webkit_security_origin_new_for_uri(kServer->getURIForPath("/").data());
+ g_assert_cmpstr(webkit_website_data_get_name(data), ==, webkit_security_origin_get_host(origin));
+ webkit_security_origin_unref(origin);
+ g_assert_cmpuint(webkit_website_data_get_types(data), ==, storageTypes);
+ // Storage sizes are unknown.
+ g_assert_cmpuint(webkit_website_data_get_size(data, WEBKIT_WEBSITE_DATA_SESSION_STORAGE), ==, 0);
+ g_assert_cmpuint(webkit_website_data_get_size(data, WEBKIT_WEBSITE_DATA_LOCAL_STORAGE), ==, 0);
+
+ // Get also cached data, and clear it.
+ static const WebKitWebsiteDataTypes cacheAndStorageTypes = static_cast<WebKitWebsiteDataTypes>(storageTypes | WEBKIT_WEBSITE_DATA_MEMORY_CACHE | WEBKIT_WEBSITE_DATA_DISK_CACHE);
+ dataList = test->fetch(cacheAndStorageTypes);
+ g_assert(dataList);
+ g_assert_cmpuint(g_list_length(dataList), ==, 1);
+ data = static_cast<WebKitWebsiteData*>(dataList->data);
+ g_assert(data);
+ g_assert_cmpuint(webkit_website_data_get_types(data), ==, cacheAndStorageTypes);
+ test->clear(static_cast<WebKitWebsiteDataTypes>(WEBKIT_WEBSITE_DATA_MEMORY_CACHE | WEBKIT_WEBSITE_DATA_DISK_CACHE), 0);
+
+ // Get all types again, but only storage is retrieved now.
+ dataList = test->fetch(cacheAndStorageTypes);
+ g_assert(dataList);
+ g_assert_cmpuint(g_list_length(dataList), ==, 1);
+ data = static_cast<WebKitWebsiteData*>(dataList->data);
+ g_assert(data);
+ g_assert_cmpuint(webkit_website_data_get_types(data), ==, storageTypes);
+
+ // Remove the session storage.
+ GList removeList = { data, nullptr, nullptr };
+ test->remove(WEBKIT_WEBSITE_DATA_SESSION_STORAGE, &removeList);
+ dataList = test->fetch(storageTypes);
+ g_assert(dataList);
+ g_assert_cmpuint(g_list_length(dataList), ==, 1);
+ data = static_cast<WebKitWebsiteData*>(dataList->data);
+ g_assert(!(webkit_website_data_get_types(data) & WEBKIT_WEBSITE_DATA_SESSION_STORAGE));
+ g_assert(webkit_website_data_get_types(data) & WEBKIT_WEBSITE_DATA_LOCAL_STORAGE);
+
+ // Clear all.
+ test->clear(cacheAndStorageTypes, 0);
+ dataList = test->fetch(cacheAndStorageTypes);
+ g_assert(!dataList);
+}
+
+static void testWebsiteDataDatabases(WebsiteDataTest* test, gconstpointer)
+{
+ static const WebKitWebsiteDataTypes databaseTypes = static_cast<WebKitWebsiteDataTypes>(WEBKIT_WEBSITE_DATA_WEBSQL_DATABASES | WEBKIT_WEBSITE_DATA_INDEXEDDB_DATABASES);
+ GList* dataList = test->fetch(databaseTypes);
+ g_assert(!dataList);
+
+ test->loadURI(kServer->getURIForPath("/empty").data());
+ test->waitUntilLoadFinished();
+ test->runJavaScriptAndWaitUntilFinished("window.indexedDB.open('TestDatabase');", nullptr);
+
+ dataList = test->fetch(databaseTypes);
+ g_assert(dataList);
+ g_assert_cmpuint(g_list_length(dataList), ==, 1);
+ WebKitWebsiteData* data = static_cast<WebKitWebsiteData*>(dataList->data);
+ g_assert(data);
+ WebKitSecurityOrigin* origin = webkit_security_origin_new_for_uri(kServer->getURIForPath("/").data());
+ g_assert_cmpstr(webkit_website_data_get_name(data), ==, webkit_security_origin_get_host(origin));
+ webkit_security_origin_unref(origin);
+ g_assert_cmpuint(webkit_website_data_get_types(data), ==, WEBKIT_WEBSITE_DATA_INDEXEDDB_DATABASES);
+ // Database sizes are unknown.
+ g_assert_cmpuint(webkit_website_data_get_size(data, WEBKIT_WEBSITE_DATA_INDEXEDDB_DATABASES), ==, 0);
+
+ test->runJavaScriptAndWaitUntilFinished("db = openDatabase(\"TestDatabase\", \"1.0\", \"TestDatabase\", 1);", nullptr);
+ dataList = test->fetch(databaseTypes);
+ g_assert(dataList);
+ g_assert_cmpuint(g_list_length(dataList), ==, 1);
+ data = static_cast<WebKitWebsiteData*>(dataList->data);
+ g_assert(data);
+ g_assert_cmpuint(webkit_website_data_get_types(data), ==, databaseTypes);
+ // Database sizes are unknown.
+ g_assert_cmpuint(webkit_website_data_get_size(data, WEBKIT_WEBSITE_DATA_INDEXEDDB_DATABASES), ==, 0);
+ g_assert_cmpuint(webkit_website_data_get_size(data, WEBKIT_WEBSITE_DATA_WEBSQL_DATABASES), ==, 0);
+
+ // Remove all databases at once.
+ GList removeList = { data, nullptr, nullptr };
+ test->remove(databaseTypes, &removeList);
+ dataList = test->fetch(databaseTypes);
+ g_assert(!dataList);
+
+ // Clear all.
+ static const WebKitWebsiteDataTypes cacheAndDatabaseTypes = static_cast<WebKitWebsiteDataTypes>(databaseTypes | WEBKIT_WEBSITE_DATA_MEMORY_CACHE | WEBKIT_WEBSITE_DATA_DISK_CACHE);
+ test->clear(cacheAndDatabaseTypes, 0);
+ dataList = test->fetch(cacheAndDatabaseTypes);
+ g_assert(!dataList);
+}
+
+static void testWebsiteDataAppcache(WebsiteDataTest* test, gconstpointer)
+{
+ GList* dataList = test->fetch(WEBKIT_WEBSITE_DATA_OFFLINE_APPLICATION_CACHE);
+ g_assert(!dataList);
+
+ test->loadURI(kServer->getURIForPath("/appcache").data());
+ test->waitUntilLoadFinished();
+
+ test->wait(1);
+ dataList = test->fetch(WEBKIT_WEBSITE_DATA_OFFLINE_APPLICATION_CACHE);
+ g_assert(dataList);
+ g_assert_cmpuint(g_list_length(dataList), ==, 1);
+ WebKitWebsiteData* data = static_cast<WebKitWebsiteData*>(dataList->data);
+ g_assert(data);
+ WebKitSecurityOrigin* origin = webkit_security_origin_new_for_uri(kServer->getURIForPath("/").data());
+ g_assert_cmpstr(webkit_website_data_get_name(data), ==, webkit_security_origin_get_host(origin));
+ webkit_security_origin_unref(origin);
+ g_assert_cmpuint(webkit_website_data_get_types(data), ==, WEBKIT_WEBSITE_DATA_OFFLINE_APPLICATION_CACHE);
+ // Appcache size is unknown.
+ g_assert_cmpuint(webkit_website_data_get_size(data, WEBKIT_WEBSITE_DATA_OFFLINE_APPLICATION_CACHE), ==, 0);
+
+ GList removeList = { data, nullptr, nullptr };
+ test->remove(WEBKIT_WEBSITE_DATA_OFFLINE_APPLICATION_CACHE, &removeList);
+ dataList = test->fetch(WEBKIT_WEBSITE_DATA_OFFLINE_APPLICATION_CACHE);
+ g_assert(!dataList);
+
+ // Clear all.
+ static const WebKitWebsiteDataTypes cacheAndAppcacheTypes = static_cast<WebKitWebsiteDataTypes>(WEBKIT_WEBSITE_DATA_OFFLINE_APPLICATION_CACHE | WEBKIT_WEBSITE_DATA_MEMORY_CACHE | WEBKIT_WEBSITE_DATA_DISK_CACHE);
+ test->clear(cacheAndAppcacheTypes, 0);
+ dataList = test->fetch(cacheAndAppcacheTypes);
+ g_assert(!dataList);
+}
+
+static void testWebsiteDataCookies(WebsiteDataTest* test, gconstpointer)
+{
+ GList* dataList = test->fetch(WEBKIT_WEBSITE_DATA_COOKIES);
+ g_assert(!dataList);
+
+ test->loadURI(kServer->getURIForPath("/empty").data());
+ test->waitUntilLoadFinished();
+
+ dataList = test->fetch(WEBKIT_WEBSITE_DATA_COOKIES);
+ g_assert(dataList);
+ g_assert_cmpuint(g_list_length(dataList), ==, 1);
+ WebKitWebsiteData* data = static_cast<WebKitWebsiteData*>(dataList->data);
+ g_assert(data);
+ g_assert_cmpstr(webkit_website_data_get_name(data), ==, "127.0.0.1");
+ g_assert_cmpuint(webkit_website_data_get_types(data), ==, WEBKIT_WEBSITE_DATA_COOKIES);
+ // Cookies size is unknown.
+ g_assert_cmpuint(webkit_website_data_get_size(data, WEBKIT_WEBSITE_DATA_COOKIES), ==, 0);
+
+ GList removeList = { data, nullptr, nullptr };
+ test->remove(WEBKIT_WEBSITE_DATA_COOKIES, &removeList);
+ dataList = test->fetch(WEBKIT_WEBSITE_DATA_COOKIES);
+ g_assert(!dataList);
+
+ // Clear all.
+ static const WebKitWebsiteDataTypes cacheAndCookieTypes = static_cast<WebKitWebsiteDataTypes>(WEBKIT_WEBSITE_DATA_COOKIES | WEBKIT_WEBSITE_DATA_MEMORY_CACHE | WEBKIT_WEBSITE_DATA_DISK_CACHE);
+ test->clear(cacheAndCookieTypes, 0);
+ dataList = test->fetch(cacheAndCookieTypes);
+ g_assert(!dataList);
+}
+
+void beforeAll()
+{
+ kServer = new WebKitTestServer();
+ kServer->run(serverCallback);
+
+ WebsiteDataTest::add("WebKitWebsiteData", "configuration", testWebsiteDataConfiguration);
+ WebViewTest::add("WebKitWebsiteData", "ephemeral", testWebsiteDataEphemeral);
+ WebsiteDataTest::add("WebKitWebsiteData", "cache", testWebsiteDataCache);
+ WebsiteDataTest::add("WebKitWebsiteData", "storage", testWebsiteDataStorage);
+ WebsiteDataTest::add("WebKitWebsiteData", "databases", testWebsiteDataDatabases);
+ WebsiteDataTest::add("WebKitWebsiteData", "appcache", testWebsiteDataAppcache);
+ WebsiteDataTest::add("WebKitWebsiteData", "cookies", testWebsiteDataCookies);
+}
+
+void afterAll()
+{
+ delete kServer;
+}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp
index 757532f7a..f632bc371 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebExtensionTest.cpp
@@ -22,15 +22,14 @@
#include <JavaScriptCore/JSContextRef.h>
#include <JavaScriptCore/JSRetainPtr.h>
#include <gio/gio.h>
+#include <gst/gst.h>
#include <stdlib.h>
#include <string.h>
#include <webkit2/webkit-web-extension.h>
#include <wtf/Deque.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
#include <wtf/ProcessID.h>
-#include <wtf/gobject/GRefPtr.h>
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/glib/GUniquePtr.h>
#include <wtf/text/CString.h>
static const char introspectionXML[] =
@@ -46,25 +45,26 @@ static const char introspectionXML[] =
" <arg type='t' name='pageID' direction='in'/>"
" <arg type='s' name='script' direction='in'/>"
" </method>"
- " <method name='GetInitializationUserData'>"
- " <arg type='s' name='userData' direction='out'/>"
- " </method>"
" <method name='GetProcessIdentifier'>"
" <arg type='u' name='identifier' direction='out'/>"
" </method>"
+ " <method name='RemoveAVPluginsFromGSTRegistry'>"
+ " </method>"
" <signal name='DocumentLoaded'/>"
+ " <signal name='FormControlsAssociated'>"
+ " <arg type='s' name='formIds' direction='out'/>"
+ " </signal>"
" <signal name='URIChanged'>"
" <arg type='s' name='uri' direction='out'/>"
" </signal>"
" </interface>"
"</node>";
-static GRefPtr<GVariant> initializationUserData;
-
typedef enum {
DocumentLoadedSignal,
URIChangedSignal,
+ FormControlsAssociatedSignal,
} DelayedSignalType;
struct DelayedSignal {
@@ -73,17 +73,17 @@ struct DelayedSignal {
{
}
- DelayedSignal(DelayedSignalType type, const char* uri)
+ DelayedSignal(DelayedSignalType type, const char* str)
: type(type)
- , uri(uri)
+ , str(str)
{
}
DelayedSignalType type;
- CString uri;
+ CString str;
};
-Deque<OwnPtr<DelayedSignal>> delayedSignalsQueue;
+Deque<DelayedSignal> delayedSignalsQueue;
static void emitDocumentLoaded(GDBusConnection* connection)
{
@@ -98,13 +98,17 @@ static void emitDocumentLoaded(GDBusConnection* connection)
g_assert(ok);
}
-static void documentLoadedCallback(WebKitWebPage*, WebKitWebExtension* extension)
+static void documentLoadedCallback(WebKitWebPage* webPage, WebKitWebExtension* extension)
{
+ WebKitDOMDocument* document = webkit_web_page_get_dom_document(webPage);
+ GRefPtr<WebKitDOMDOMWindow> window = adoptGRef(webkit_dom_document_get_default_view(document));
+ webkit_dom_dom_window_webkit_message_handlers_post_message(window.get(), "dom", "DocumentLoaded");
+
gpointer data = g_object_get_data(G_OBJECT(extension), "dbus-connection");
if (data)
emitDocumentLoaded(G_DBUS_CONNECTION(data));
else
- delayedSignalsQueue.append(adoptPtr(new DelayedSignal(DocumentLoadedSignal)));
+ delayedSignalsQueue.append(DelayedSignal(DocumentLoadedSignal));
}
static void emitURIChanged(GDBusConnection* connection, const char* uri)
@@ -126,11 +130,12 @@ static void uriChangedCallback(WebKitWebPage* webPage, GParamSpec* pspec, WebKit
if (data)
emitURIChanged(G_DBUS_CONNECTION(data), webkit_web_page_get_uri(webPage));
else
- delayedSignalsQueue.append(adoptPtr(new DelayedSignal(URIChangedSignal, webkit_web_page_get_uri(webPage))));
+ delayedSignalsQueue.append(DelayedSignal(URIChangedSignal, webkit_web_page_get_uri(webPage)));
}
static gboolean sendRequestCallback(WebKitWebPage*, WebKitURIRequest* request, WebKitURIResponse* redirectResponse, gpointer)
{
+ gboolean returnValue = FALSE;
const char* requestURI = webkit_uri_request_get_uri(request);
g_assert(requestURI);
@@ -153,17 +158,128 @@ static gboolean sendRequestCallback(WebKitWebPage*, WebKitURIRequest* request, W
SoupMessageHeaders* headers = webkit_uri_request_get_http_headers(request);
g_assert(headers);
soup_message_headers_append(headers, "DNT", "1");
+ } else if (g_str_has_suffix(requestURI, "/normal-change-request")) {
+ GUniquePtr<char> prefix(g_strndup(requestURI, strlen(requestURI) - strlen("/normal-change-request")));
+ GUniquePtr<char> newURI(g_strdup_printf("%s/request-changed%s", prefix.get(), redirectResponse ? "-on-redirect" : ""));
+ webkit_uri_request_set_uri(request, newURI.get());
+ } else if (g_str_has_suffix(requestURI, "/http-get-method")) {
+ g_assert_cmpstr(webkit_uri_request_get_http_method(request), ==, "GET");
+ g_assert(webkit_uri_request_get_http_method(request) == SOUP_METHOD_GET);
+ } else if (g_str_has_suffix(requestURI, "/http-post-method")) {
+ g_assert_cmpstr(webkit_uri_request_get_http_method(request), ==, "POST");
+ g_assert(webkit_uri_request_get_http_method(request) == SOUP_METHOD_POST);
+ returnValue = TRUE;
} else if (g_str_has_suffix(requestURI, "/cancel-this.js"))
+ returnValue = TRUE;
+
+ return returnValue;
+}
+
+static GVariant* serializeContextMenu(WebKitContextMenu* menu)
+{
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
+ GList* items = webkit_context_menu_get_items(menu);
+ for (GList* it = items; it; it = g_list_next(it))
+ g_variant_builder_add(&builder, "u", webkit_context_menu_item_get_stock_action(WEBKIT_CONTEXT_MENU_ITEM(it->data)));
+ return g_variant_builder_end(&builder);
+}
+
+static GVariant* serializeNode(WebKitDOMNode* node)
+{
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
+ g_variant_builder_add(&builder, "{sv}", "Name", g_variant_new_take_string(webkit_dom_node_get_node_name(node)));
+ g_variant_builder_add(&builder, "{sv}", "Type", g_variant_new_uint32(webkit_dom_node_get_node_type(node)));
+ g_variant_builder_add(&builder, "{sv}", "Contents", g_variant_new_take_string(webkit_dom_node_get_text_content(node)));
+ WebKitDOMNode* parent = webkit_dom_node_get_parent_node(node);
+ g_variant_builder_add(&builder, "{sv}", "Parent", parent ? g_variant_new_take_string(webkit_dom_node_get_node_name(parent)) : g_variant_new_string("ROOT"));
+ return g_variant_builder_end(&builder);
+}
+
+static gboolean contextMenuCallback(WebKitWebPage* page, WebKitContextMenu* menu, WebKitWebHitTestResult* hitTestResult, gpointer)
+{
+ const char* pageURI = webkit_web_page_get_uri(page);
+ if (!g_strcmp0(pageURI, "ContextMenuTestDefault")) {
+ webkit_context_menu_set_user_data(menu, serializeContextMenu(menu));
+ return FALSE;
+ }
+
+ if (!g_strcmp0(pageURI, "ContextMenuTestCustom")) {
+ // Remove Back and Forward, and add Inspector action.
+ webkit_context_menu_remove(menu, webkit_context_menu_first(menu));
+ webkit_context_menu_remove(menu, webkit_context_menu_first(menu));
+ webkit_context_menu_append(menu, webkit_context_menu_item_new_separator());
+ webkit_context_menu_append(menu, webkit_context_menu_item_new_from_stock_action(WEBKIT_CONTEXT_MENU_ACTION_INSPECT_ELEMENT));
+ webkit_context_menu_set_user_data(menu, serializeContextMenu(menu));
+ return TRUE;
+ }
+
+ if (!g_strcmp0(pageURI, "ContextMenuTestClear")) {
+ webkit_context_menu_remove_all(menu);
+ return TRUE;
+ }
+
+ if (!g_strcmp0(pageURI, "ContextMenuTestNode")) {
+ WebKitDOMNode* node = webkit_web_hit_test_result_get_node(hitTestResult);
+ g_assert(WEBKIT_DOM_IS_NODE(node));
+ webkit_context_menu_set_user_data(menu, serializeNode(node));
return TRUE;
+ }
return FALSE;
}
+static void consoleMessageSentCallback(WebKitWebPage* webPage, WebKitConsoleMessage* consoleMessage)
+{
+ g_assert(consoleMessage);
+ GRefPtr<GVariant> variant = g_variant_new("(uusus)", webkit_console_message_get_source(consoleMessage),
+ webkit_console_message_get_level(consoleMessage), webkit_console_message_get_text(consoleMessage),
+ webkit_console_message_get_line(consoleMessage), webkit_console_message_get_source_id(consoleMessage));
+ GUniquePtr<char> messageString(g_variant_print(variant.get(), FALSE));
+ GRefPtr<WebKitDOMDOMWindow> window = adoptGRef(webkit_dom_document_get_default_view(webkit_web_page_get_dom_document(webPage)));
+ g_assert(WEBKIT_DOM_IS_DOM_WINDOW(window.get()));
+ webkit_dom_dom_window_webkit_message_handlers_post_message(window.get(), "console", messageString.get());
+}
+
+
+static void emitFormControlsAssociated(GDBusConnection* connection, const char* formIds)
+{
+ bool ok = g_dbus_connection_emit_signal(
+ connection,
+ nullptr,
+ "/org/webkit/gtk/WebExtensionTest",
+ "org.webkit.gtk.WebExtensionTest",
+ "FormControlsAssociated",
+ g_variant_new("(s)", formIds),
+ nullptr);
+ g_assert(ok);
+}
+
+static void formControlsAssociatedCallback(WebKitWebPage* webPage, GPtrArray* formElements, WebKitWebExtension* extension)
+{
+ GString* formIdsBuilder = g_string_new(nullptr);
+ for (int i = 0; i < formElements->len; ++i) {
+ g_assert(WEBKIT_DOM_IS_ELEMENT(g_ptr_array_index(formElements, i)));
+ auto domElement = WEBKIT_DOM_ELEMENT(g_ptr_array_index(formElements, i));
+ g_string_append(formIdsBuilder, webkit_dom_element_get_id(domElement));
+ }
+ GUniquePtr<char> formIds(g_string_free(formIdsBuilder, FALSE));
+ gpointer data = g_object_get_data(G_OBJECT(extension), "dbus-connection");
+ if (data)
+ emitFormControlsAssociated(G_DBUS_CONNECTION(data), formIds.get());
+ else
+ delayedSignalsQueue.append(DelayedSignal(FormControlsAssociatedSignal, formIds.get()));
+}
+
static void pageCreatedCallback(WebKitWebExtension* extension, WebKitWebPage* webPage, gpointer)
{
g_signal_connect(webPage, "document-loaded", G_CALLBACK(documentLoadedCallback), extension);
g_signal_connect(webPage, "notify::uri", G_CALLBACK(uriChangedCallback), extension);
- g_signal_connect(webPage, "send-request", G_CALLBACK(sendRequestCallback), 0);
+ g_signal_connect(webPage, "send-request", G_CALLBACK(sendRequestCallback), nullptr);
+ g_signal_connect(webPage, "context-menu", G_CALLBACK(contextMenuCallback), nullptr);
+ g_signal_connect(webPage, "console-message-sent", G_CALLBACK(consoleMessageSentCallback), nullptr);
+ g_signal_connect(webPage, "form-controls-associated", G_CALLBACK(formControlsAssociatedCallback), extension);
}
static JSValueRef echoCallback(JSContextRef jsContext, JSObjectRef, JSObjectRef, size_t argumentCount, const JSValueRef arguments[], JSValueRef*)
@@ -233,14 +349,20 @@ static void methodCallCallback(GDBusConnection* connection, const char* sender,
g_dbus_method_invocation_return_value(invocation, 0);
} else if (!g_strcmp0(methodName, "AbortProcess")) {
abort();
- } else if (!g_strcmp0(methodName, "GetInitializationUserData")) {
- g_assert(initializationUserData);
- g_assert(g_variant_is_of_type(initializationUserData.get(), G_VARIANT_TYPE_STRING));
- g_dbus_method_invocation_return_value(invocation, g_variant_new("(s)",
- g_variant_get_string(initializationUserData.get(), nullptr)));
} else if (!g_strcmp0(methodName, "GetProcessIdentifier")) {
g_dbus_method_invocation_return_value(invocation,
g_variant_new("(u)", static_cast<guint32>(getCurrentProcessID())));
+ } else if (!g_strcmp0(methodName, "RemoveAVPluginsFromGSTRegistry")) {
+ gst_init(nullptr, nullptr);
+ static const char* avPlugins[] = { "libav", "omx", "vaapi", nullptr };
+ GstRegistry* registry = gst_registry_get();
+ for (unsigned i = 0; avPlugins[i]; ++i) {
+ if (GstPlugin* plugin = gst_registry_find_plugin(registry, avPlugins[i])) {
+ gst_registry_remove_plugin(registry, plugin);
+ gst_object_unref(plugin);
+ }
+ }
+ g_dbus_method_invocation_return_value(invocation, nullptr);
}
}
@@ -268,38 +390,41 @@ static void busAcquiredCallback(GDBusConnection* connection, const char* name, g
g_object_set_data(G_OBJECT(userData), "dbus-connection", connection);
while (delayedSignalsQueue.size()) {
- OwnPtr<DelayedSignal> delayedSignal = delayedSignalsQueue.takeFirst();
- switch (delayedSignal->type) {
+ DelayedSignal delayedSignal = delayedSignalsQueue.takeFirst();
+ switch (delayedSignal.type) {
case DocumentLoadedSignal:
emitDocumentLoaded(connection);
break;
case URIChangedSignal:
- emitURIChanged(connection, delayedSignal->uri.data());
+ emitURIChanged(connection, delayedSignal.str.data());
+ break;
+ case FormControlsAssociatedSignal:
+ emitFormControlsAssociated(connection, delayedSignal.str.data());
break;
}
}
}
-static GUniquePtr<char> makeBusName(GVariant* userData)
+static void registerGResource(void)
{
- // When the web extension is used by TestMultiprocess, an uint32
- // identifier is passed as user data. It uniquely identifies
- // the web process, and the UI side expects it added as suffix to
- // the bus name.
- if (userData && g_variant_is_of_type(userData, G_VARIANT_TYPE_UINT32))
- return GUniquePtr<char>(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", g_variant_get_uint32(userData)));
-
- return GUniquePtr<char>(g_strdup("org.webkit.gtk.WebExtensionTest"));
+ GUniquePtr<char> resourcesPath(g_build_filename(WEBKIT_EXEC_PATH, "TestWebKitAPI", "WebKit2Gtk", "resources", "webkit2gtk-tests-resources.gresource", nullptr));
+ GResource* resource = g_resource_load(resourcesPath.get(), nullptr);
+ g_assert(resource);
+
+ g_resources_register(resource);
+ g_resource_unref(resource);
}
extern "C" void webkit_web_extension_initialize_with_user_data(WebKitWebExtension* extension, GVariant* userData)
{
- initializationUserData = userData;
-
g_signal_connect(extension, "page-created", G_CALLBACK(pageCreatedCallback), extension);
g_signal_connect(webkit_script_world_get_default(), "window-object-cleared", G_CALLBACK(windowObjectCleared), 0);
- GUniquePtr<char> busName(makeBusName(userData));
+ registerGResource();
+
+ g_assert(userData);
+ g_assert(g_variant_is_of_type(userData, G_VARIANT_TYPE_UINT32));
+ GUniquePtr<char> busName(g_strdup_printf("org.webkit.gtk.WebExtensionTest%u", g_variant_get_uint32(userData)));
g_bus_own_name(
G_BUS_TYPE_SESSION,
busName.get(),
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.cpp b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.cpp
index 09d0785aa..bc058693d 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.cpp
@@ -22,8 +22,11 @@
#include <JavaScriptCore/JSRetainPtr.h>
#include <gio/gio.h>
+#include <wtf/HashSet.h>
#include <wtf/NeverDestroyed.h>
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GUniquePtr.h>
+
+static HashSet<GObject*> s_watchedObjects;
typedef HashMap<String, std::function<std::unique_ptr<WebProcessTest> ()>> TestsMap;
static TestsMap& testsMap()
@@ -34,7 +37,15 @@ static TestsMap& testsMap()
void WebProcessTest::add(const String& testName, std::function<std::unique_ptr<WebProcessTest> ()> closure)
{
- testsMap().add(testName, std::move(closure));
+ testsMap().add(testName, WTFMove(closure));
+}
+
+void WebProcessTest::assertObjectIsDeletedWhenTestFinishes(GObject* object)
+{
+ s_watchedObjects.add(object);
+ g_object_weak_ref(object, [](gpointer, GObject* finalizedObject) {
+ s_watchedObjects.remove(finalizedObject);
+ }, nullptr);
}
std::unique_ptr<WebProcessTest> WebProcessTest::create(const String& testName)
@@ -53,6 +64,14 @@ static JSValueRef runTest(JSContextRef context, JSObjectRef function, JSObjectRe
WebKitWebPage* webPage = WEBKIT_WEB_PAGE(JSObjectGetPrivate(thisObject));
g_assert(WEBKIT_IS_WEB_PAGE(webPage));
+ // Test /WebKitDOMNode/dom-cache is an exception, because it's called 3 times, so
+ // the WebPage is destroyed after the third time.
+ if (g_str_equal(testPath.get(), "WebKitDOMNode/dom-cache")) {
+ static unsigned domCacheTestRunCount = 0;
+ if (++domCacheTestRunCount == 3)
+ WebProcessTest::assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webPage));
+ } else
+ WebProcessTest::assertObjectIsDeletedWhenTestFinishes(G_OBJECT(webPage));
std::unique_ptr<WebProcessTest> test = WebProcessTest::create(String::fromUTF8(testPath.get()));
return JSValueMakeBoolean(context, test->runTest(g_strrstr(testPath.get(), "/") + 1, webPage));
@@ -67,6 +86,16 @@ static const JSStaticFunction webProcessTestRunnerStaticFunctions[] =
static void webProcessTestRunnerFinalize(JSObjectRef object)
{
g_object_unref(JSObjectGetPrivate(object));
+
+ if (s_watchedObjects.isEmpty())
+ return;
+
+ g_print("Leaked objects in WebProcess:");
+ for (const auto object : s_watchedObjects)
+ g_print(" %s(%p)", g_type_name_from_instance(reinterpret_cast<GTypeInstance*>(object)), object);
+ g_print("\n");
+
+ g_assert(s_watchedObjects.isEmpty());
}
static void windowObjectClearedCallback(WebKitScriptWorld* world, WebKitWebPage* webPage, WebKitFrame* frame, WebKitWebExtension* extension)
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.h b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.h
index fb4dd5d33..3715eb91e 100644
--- a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.h
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/WebProcessTest.h
@@ -19,7 +19,7 @@
#include <webkit2/webkit-web-extension.h>
#include <wtf/HashMap.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
#include <wtf/text/StringHash.h>
#include <wtf/text/WTFString.h>
@@ -28,6 +28,8 @@ public:
virtual ~WebProcessTest() { }
virtual bool runTest(const char* testName, WebKitWebPage*) = 0;
+ static void assertObjectIsDeletedWhenTestFinishes(GObject*);
+
static void add(const String& testName, std::function<std::unique_ptr<WebProcessTest> ()>);
static std::unique_ptr<WebProcessTest> create(const String& testName);
};
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/blank.ico b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/blank.ico
new file mode 100644
index 000000000..ea848b991
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/blank.ico
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/boring.html b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/boring.html
new file mode 100644
index 000000000..c0eeb49ee
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/boring.html
@@ -0,0 +1 @@
+<p>This is a boring HTML file.</p>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/link-title.js b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/link-title.js
new file mode 100644
index 000000000..2c824da38
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/link-title.js
@@ -0,0 +1 @@
+window.document.getElementById('WebKitLink').title;
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/silence.mpg b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/silence.mpg
new file mode 100644
index 000000000..b6bbf2088
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/silence.mpg
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/simple.json b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/simple.json
new file mode 100644
index 000000000..76519fa8c
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/simple.json
@@ -0,0 +1 @@
+{"key": "value"}
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-cert.pem b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-cert.pem
new file mode 100644
index 000000000..b34301f25
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-cert.pem
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB9jCCAV+gAwIBAgIJALeuXBo+vwz9MA0GCSqGSIb3DQEBBQUAMBQxEjAQBgNV
+BAMMCTEyNy4wLjAuMTAeFw0xMjA3MTIxMjQ4MjRaFw0yMjA3MTAxMjQ4MjRaMBQx
+EjAQBgNVBAMMCTEyNy4wLjAuMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
+0TUzOQxHBIKDD2mkuq+tU92mQvDZg73B0G+Nhr2T2G6MbcLqIwjg1QYtBZWJ83tZ
+xMMEfiweHLF85Z9ohavAgxJlKG7YmvZO79KkFpmjV2W5CVRm0eYMPnzmxNCoaYqo
+DLl0zsH6KZOLPKu/fX4eDX9XpAP1f83hWB1UFBmHKN8CAwEAAaNQME4wHQYDVR0O
+BBYEFDHv5ZQ1BdmhzTsDUEoY55EXyUdKMB8GA1UdIwQYMBaAFDHv5ZQ1BdmhzTsD
+UEoY55EXyUdKMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAh3qMBx7v
+jSodMf3OyTqTLE7deLnmnCeBVpgzxRZEoizcGqYcjiqO27i5N5Z6KVQsnITnLiyC
+mUtuR5KnF69uTKUw4m/ugZe5whjig5Mq2l410KVK6EeG4tdLlfXR+wi4U5K4KjP6
+p4nchQUXLa2zcbJn+VBexJn6/9wdhr+DUGY=
+-----END CERTIFICATE-----
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-key.pem b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-key.pem
new file mode 100644
index 000000000..9036222ce
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-key.pem
@@ -0,0 +1,16 @@
+-----BEGIN PRIVATE KEY-----
+MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANE1MzkMRwSCgw9p
+pLqvrVPdpkLw2YO9wdBvjYa9k9hujG3C6iMI4NUGLQWVifN7WcTDBH4sHhyxfOWf
+aIWrwIMSZShu2Jr2Tu/SpBaZo1dluQlUZtHmDD585sTQqGmKqAy5dM7B+imTizyr
+v31+Hg1/V6QD9X/N4VgdVBQZhyjfAgMBAAECgYB2QwOUsRsIMprRwJ9tJNfvO7G7
+z5i1/zOrlxPC4jHMPBnIBlICwgcOhLI4oOLdr5H8R12n0VqoT7DRwP396iwlJipF
+iO1heDMn/8z8LPGwkCK/+ck04rMDksxWIdMwYKBXt9ahnJ/xRLzQ1/3AJiAGnoe5
+/QLXQweofd4mmfsjKQJBAO2CwT7uMP6nMjXgtVMJq5QP8UbeCS1sEOPJJbHuDxJB
+/HePQHBjq4kzG6CL4oO7T+5fDv4g+fIIHzuXerZ0imsCQQDhfmiTIc9OucEIfg6/
+ms0JiKSmWc+qoiOCtrILuQvFoNwJRciQANqeJs6wpaDvevSUvBLGfG/7b3HvaE5X
+iqBdAkBEQIvp2qcHtuJN60oQF7pPrRknxUyb2e8sljQX4pJAK+gyL19ULMAxiBdL
+Vod8VYqNtJFpY+6Pp9fZ1xjzb6ALAkEA4JzrDAw0lQXA+3WduUw4ixOadr2ldyG0
+36KebcDwsfZO18m0Q4UmPz0Gy7zgN0wxzuochaw0W6+iPUiYKOlEXQJBAMWQrPlu
+rrinoZS2f8doJ9BNNUa+RNpMug6UXc55qoUJlyiXEh+tu4AaMOtxuGIyC0sAcuw6
+XdAPVPXKd7Mne70=
+-----END PRIVATE KEY-----
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/track.ogg b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/track.ogg
new file mode 100644
index 000000000..c569c8f40
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/track.ogg
Binary files differ
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/webkit2gtk-tests.gresource.xml b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/webkit2gtk-tests.gresource.xml
new file mode 100644
index 000000000..87bc50158
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/webkit2gtk-tests.gresource.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/webkit/webkit2gtk/tests/">
+ <file alias="boring.html">Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/boring.html</file>
+ <file alias="link-title.js">Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/link-title.js</file>
+ </gresource>
+</gresources>
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsInvalidScheme_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsInvalidScheme_Bundle.cpp
new file mode 100644
index 000000000..279ddd268
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsInvalidScheme_Bundle.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2013 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "InjectedBundleTest.h"
+#include <WebKit/WKBundlePage.h>
+
+namespace TestWebKitAPI {
+
+static WKBundlePagePolicyAction decidePolicyForNavigationAction(WKBundlePageRef, WKBundleFrameRef, WKBundleNavigationActionRef, WKURLRequestRef request, WKTypeRef*, const void*)
+{
+ if (WKBundlePageCanHandleRequest(request))
+ return WKBundlePagePolicyActionUse;
+ return WKBundlePagePolicyActionPassThrough;
+}
+
+class CustomProtocolInvalidSchemeTest : public InjectedBundleTest {
+public:
+ CustomProtocolInvalidSchemeTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+ {
+ }
+
+private:
+ void didCreatePage(WKBundleRef, WKBundlePageRef bundlePage) override
+ {
+ WKBundlePagePolicyClientV0 policyClient;
+ memset(&policyClient, 0, sizeof(policyClient));
+
+ policyClient.base.version = 0;
+ policyClient.decidePolicyForNavigationAction = decidePolicyForNavigationAction;
+
+ WKBundlePageSetPolicyClient(bundlePage, &policyClient.base);
+ }
+};
+
+static InjectedBundleTest::Register<CustomProtocolInvalidSchemeTest> registrar("CustomProtocolInvalidSchemeTest");
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing_Bundle.cpp b/Tools/TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing_Bundle.cpp
new file mode 100644
index 000000000..dde94407a
--- /dev/null
+++ b/Tools/TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing_Bundle.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2013 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. 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 INC. 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.
+ */
+
+#include "config.h"
+
+#if WK_HAVE_C_SPI
+
+#include "InjectedBundleTest.h"
+#include "PlatformUtilities.h"
+#include "Test.h"
+
+#include <WebKit/WKBundlePage.h>
+
+#include <wtf/Assertions.h>
+
+namespace TestWebKitAPI {
+
+class DenyWillSendRequestTest : public InjectedBundleTest {
+public:
+ DenyWillSendRequestTest(const std::string& identifier)
+ : InjectedBundleTest(identifier)
+ {
+ }
+
+ static WKURLRequestRef willSendRequestForFrame(WKBundlePageRef, WKBundleFrameRef frame, uint64_t resourceIdentifier, WKURLRequestRef request, WKURLResponseRef redirectResponse, const void *clientInfo)
+ {
+ return 0;
+ }
+
+ virtual void didCreatePage(WKBundleRef bundle, WKBundlePageRef page)
+ {
+ WKBundlePageResourceLoadClientV0 resourceLoadClient;
+ memset(&resourceLoadClient, 0, sizeof(resourceLoadClient));
+
+ resourceLoadClient.base.version = 0;
+ resourceLoadClient.willSendRequestForFrame = willSendRequestForFrame;
+
+ WKBundlePageSetResourceLoadClient(page, &resourceLoadClient.base);
+
+ }
+};
+
+static InjectedBundleTest::Register<DenyWillSendRequestTest> registrar("DenyWillSendRequestTest");
+
+} // namespace TestWebKitAPI
+
+#endif
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/test_utils.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/test_utils.c
deleted file mode 100644
index 6bb645d0d..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/test_utils.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2010 Arno Renevier
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "test_utils.h"
-
-#include <glib.h>
-#include <glib/gstdio.h>
-
-int testutils_relative_chdir(const gchar *targetFilename, const gchar *executablePath)
-{
- /* user can set location of the webkit repository directory if it differs from build directory */
- const gchar *repoPath = g_getenv("WEBKITREPODIR");
- if (repoPath) {
- if (g_chdir(repoPath))
- return -1;
- } else if (g_chdir(g_path_get_dirname(executablePath)))
- return -1;
-
- while (!g_file_test(targetFilename, G_FILE_TEST_EXISTS)) {
- gchar *pathName;
- if (g_chdir(".."))
- return -1;
- g_assert(!g_str_equal((pathName = g_get_current_dir()), "/"));
- g_free(pathName);
- }
-
- gchar *dirName = g_path_get_dirname(targetFilename);
- if (g_chdir(dirName)) {
- g_free(dirName);
- return -1;
- }
-
- g_free(dirName);
- return 0;
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testatk.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testatk.c
deleted file mode 100644
index 2a2db6146..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testatk.c
+++ /dev/null
@@ -1,1476 +0,0 @@
-/*
- * Copyright (C) 2009 Igalia S.L.
- * Copyright (C) 2013 Samsung Electronics. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <locale.h>
-#include <unistd.h>
-#include <webkit/webkit.h>
-
-static const char* centeredContents = "<html><body><p style='text-align: center;'>Short line</p><p style='text-align: center;'>Long-size line with some foo bar baz content</p><p style='text-align: center;'>Short line</p><p style='text-align: center;'>This is a multi-line paragraph<br />where the first line<br />is the biggest one</p></body></html>";
-
-static const char* contents = "<html><body><p>This is a test. This is the second sentence. And this the third.</p></body></html>";
-
-static const char* contentsInTableWithHeaders = "<html><body><table><tr><th>foo</th><th>bar</th><th colspan='2'>baz</th></tr><tr><th>qux</th><td>1</td><td>2</td><td>3</td></tr><tr><th rowspan='2'>quux</th><td>4</td><td>5</td><td>6</td></tr><tr><td>6</td><td>7</td><td>8</td></tr><tr><th>corge</th><td>9</td><td>10</td><td>11</td></tr></table><table><tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr></table></body></html>";
-
-static const char* contentsWithExtraneousWhiteSpaces = "<html><head><body><p>This\n paragraph\n is\n borked!</p></body></html>";
-
-static const char* comboBoxSelector = "<html><body><select><option selected value='foo'>foo</option><option value='bar'>bar</option></select></body></html>";
-
-static const char* embeddedObjects = "<html><body><p>Choose: <input value='foo' type='checkbox'/>foo <input value='bar' type='checkbox'/>bar (pick one)</p><p>Choose: <select name='foo'><option>bar</option><option>baz</option></select> (pick one)</p><p><input name='foobarbutton' value='foobar' type='button'/></p></body></html>";
-
-static const char* formWithTextInputs = "<html><body><form><input type='text' name='entry' /><input type='password' name='passwordEntry' /></form></body></html>";
-
-static const char* hypertextAndHyperlinks = "<html><body><p>A paragraph with no links at all</p><p><a href='http://foo.bar.baz/'>A line</a> with <a href='http://bar.baz.foo/'>a link in the middle</a> as well as at the beginning and <a href='http://baz.foo.bar/'>at the end</a></p><ol><li>List item with a <span><a href='http://foo.bar.baz/'>link inside a span node</a></span></li></ol></body></html>";
-
-static const char* layoutAndDataTables = "<html><body><table><tr><th>Odd</th><th>Even</th></tr><tr><td>1</td><td>2</td></tr></table><table><tr><td>foo</td><td>bar</td></tr></table></body></html>";
-
-static const char* linksWithInlineImages = "<html><head><style>a.http:before {content: url(no-image.png);}</style><body><p><a class='http' href='foo'>foo</a> bar baz</p><p>foo <a class='http' href='bar'>bar</a> baz</p><p>foo bar <a class='http' href='baz'>baz</a></p></body></html>";
-
-static const char* listsOfItems = "<html><body><ul><li>text only</li><li><a href='foo'>link only</a></li><li>text and a <a href='bar'>link</a></li></ul><ol><li>text only</li><li><a href='foo'>link only</a></li><li>text and a <a href='bar'>link</a></li></ol></body></html>";
-
-static const char* textForCaretBrowsing = "<html><body><h1>A text header</h1><p>A paragraph <a href='http://foo.bar.baz/'>with a link</a> in the middle</p><ol><li>A list item</li><li><span style='display:block;'>Block span in a list item</span><span>Inline span in a list item</span></li><li><a href='foo'><span style='display:block;'>Block span in a link in a list item</span><span>Inline span in a link in a list item</span></a></li></ol><select><option selected value='foo'>An option in a combo box</option></select><input type='text' name='foo' value='foo bar baz' /><table><tr><td>a table cell</td><td></td><td><a href='foo'><span style='display:block;'>Block span in a link in a table cell</span><span>Inline span in a link in a table cell</span></a></td><td><span style='display:block;'>Block span in a table cell</span><span>Inline span in a table cell</span></td></tr></table><h4><a href='foo'><span style='display:block;'>Block span in a link in a heading</span><span>Inline span in a link in a heading</span></h4><h4><span style='display:block;'>Block span in a heading</span><span>Inline span in a heading</span></h4></body></html>";
-
-static const char* textForSelections = "<html><body><p>A paragraph with plain text</p><p>A paragraph with <a href='http://webkit.org'>a link</a> in the middle</p><ol><li>A list item</li></ol><select></body></html>";
-
-static const char* textWithAttributes = "<html><head><style>.st1 {font-family: monospace; color:rgb(120,121,122);} .st2 {text-decoration:underline; background-color:rgb(80,81,82);}</style></head><body><p style=\"font-size:14; text-align:right;\">This is the <i>first</i><b> sentence of this text.</b></p><p class=\"st1\">This sentence should have an style applied <span class=\"st2\">and this part should have another one</span>.</p><p>x<sub>1</sub><sup>2</sup>=x<sub>2</sub><sup>3</sup></p><p style=\"text-align:center;\">This sentence is the <strike>last</strike> one.</p></body></html>";
-
-static AtkObject* getWebAreaObject(WebKitWebView* webView)
-{
- /* Manually spin the main context to make sure the accessible
- objects are properly created before continuing. */
- while (g_main_context_pending(0))
- g_main_context_iteration(0, TRUE);
-
- AtkObject* rootObject = gtk_widget_get_accessible(GTK_WIDGET(webView));
- if (!rootObject)
- return NULL;
-
- AtkObject* webAreaObject = atk_object_ref_accessible_child(rootObject, 0);
- if (!webAreaObject)
- return NULL;
-
- /* We don't need the extra ref here. */
- g_object_unref(webAreaObject);
-
- return webAreaObject;
-}
-
-static gchar* textCaretMovedResult = 0;
-
-static void textCaretMovedCallback(AtkText* text, gint pos, gpointer data)
-{
- g_assert(ATK_IS_TEXT(text));
-
- g_free(textCaretMovedResult);
- AtkRole role = atk_object_get_role(ATK_OBJECT(text));
- textCaretMovedResult = g_strdup_printf("|%s|%d|", atk_role_get_name(role), pos);
-}
-
-static void testWebkitAtkCaretOffsets()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, textForCaretBrowsing, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- AtkObject* header = atk_object_ref_accessible_child(object, 0);
- g_assert(ATK_IS_TEXT(header));
- g_signal_connect(header, "text-caret-moved", G_CALLBACK(textCaretMovedCallback), 0);
-
- /* It should be possible to place the caret inside a header. */
- gboolean result = atk_text_set_caret_offset(ATK_TEXT(header), 5);
- g_assert_cmpint(result, ==, TRUE);
- gint offset = atk_text_get_caret_offset(ATK_TEXT(header));
- g_assert_cmpint(offset, ==, 5);
- g_assert_cmpstr(textCaretMovedResult, ==, "|heading|5|");
-
- AtkObject* paragraph = atk_object_ref_accessible_child(object, 1);
- g_assert(ATK_IS_TEXT(paragraph));
- g_signal_connect(paragraph, "text-caret-moved", G_CALLBACK(textCaretMovedCallback), 0);
-
- /* It should be possible to place the caret inside a paragraph and a link. */
- result = atk_text_set_caret_offset(ATK_TEXT(paragraph), 5);
- g_assert_cmpint(result, ==, TRUE);
- offset = atk_text_get_caret_offset(ATK_TEXT(paragraph));
- g_assert_cmpint(offset, ==, 5);
- g_assert_cmpstr(textCaretMovedResult, ==, "|paragraph|5|");
-
- result = atk_text_set_caret_offset(ATK_TEXT(paragraph), 20);
- g_assert_cmpint(result, ==, TRUE);
- offset = atk_text_get_caret_offset(ATK_TEXT(paragraph));
- g_assert_cmpint(offset, ==, 20);
- g_assert_cmpstr(textCaretMovedResult, ==, "|paragraph|20|");
-
- result = atk_text_set_caret_offset(ATK_TEXT(paragraph), 30);
- g_assert_cmpint(result, ==, TRUE);
- offset = atk_text_get_caret_offset(ATK_TEXT(paragraph));
- g_assert_cmpint(offset, ==, 30);
- g_assert_cmpstr(textCaretMovedResult, ==, "|paragraph|30|");
-
- AtkObject* link = atk_object_ref_accessible_child(paragraph, 0);
- g_assert(ATK_IS_TEXT(link));
-
- result = atk_text_set_caret_offset(ATK_TEXT(link), 5);
- g_assert_cmpint(result, ==, TRUE);
- offset = atk_text_get_caret_offset(ATK_TEXT(link));
- g_assert_cmpint(offset, ==, 5);
- /* Positions inside links are reported relative to the paragraph. */
- g_assert_cmpstr(textCaretMovedResult, ==, "|paragraph|17|");
-
- AtkObject* list = atk_object_ref_accessible_child(object, 2);
- g_assert(ATK_OBJECT(list));
- g_assert(atk_object_get_role(list) == ATK_ROLE_LIST);
- g_assert_cmpint(atk_object_get_n_accessible_children(list), ==, 3);
-
- AtkObject* listItem = atk_object_ref_accessible_child(list, 0);
- listItem = atk_object_ref_accessible_child(list, 2);
- g_assert(ATK_IS_TEXT(listItem));
-
- /* It's not possible to place the caret inside an item's marker. */
- result = atk_text_set_caret_offset(ATK_TEXT(listItem), 1);
- g_assert_cmpint(result, ==, FALSE);
-
- /* It should be possible to place the caret inside an item's text. */
- result = atk_text_set_caret_offset(ATK_TEXT(listItem), 5);
- g_assert_cmpint(result, ==, TRUE);
- offset = atk_text_get_caret_offset(ATK_TEXT(listItem));
- g_assert_cmpint(offset, ==, 5);
-
- AtkObject* panel = atk_object_ref_accessible_child(object, 3);
- g_assert(ATK_IS_OBJECT(panel));
- g_assert(atk_object_get_role(panel) == ATK_ROLE_PANEL);
-
- AtkObject* comboBox = atk_object_ref_accessible_child(panel, 0);
- g_assert(ATK_IS_OBJECT(comboBox));
- g_assert(atk_object_get_role(comboBox) == ATK_ROLE_COMBO_BOX);
-
- AtkObject* menuPopup = atk_object_ref_accessible_child(comboBox, 0);
- g_assert(ATK_IS_OBJECT(menuPopup));
- g_assert(atk_object_get_role(menuPopup) == ATK_ROLE_MENU);
-
- AtkObject* comboBoxOption = atk_object_ref_accessible_child(menuPopup, 0);
- g_assert(ATK_IS_OBJECT(comboBoxOption));
- g_assert(atk_object_get_role(comboBoxOption) == ATK_ROLE_MENU_ITEM);
-
- /* It's not possible to place the caret inside an option for a combobox. */
- result = atk_text_set_caret_offset(ATK_TEXT(comboBoxOption), 1);
- g_assert_cmpint(result, ==, FALSE);
-
- AtkObject* textEntry = atk_object_ref_accessible_child(panel, 1);
- g_assert(ATK_IS_OBJECT(textEntry));
- g_assert(atk_object_get_role(textEntry) == ATK_ROLE_ENTRY);
-
- result = atk_text_set_caret_offset(ATK_TEXT(textEntry), 5);
- g_assert_cmpint(result, ==, TRUE);
- offset = atk_text_get_caret_offset(ATK_TEXT(textEntry));
- g_assert_cmpint(offset, ==, 5);
-
- AtkObject* table = atk_object_ref_accessible_child(object, 4);
- g_assert(ATK_IS_OBJECT(table));
- g_assert(atk_object_get_role(table) == ATK_ROLE_TABLE);
- g_assert_cmpint(atk_object_get_n_accessible_children(table), ==, 4);
-
- AtkObject* tableCell = atk_object_ref_accessible_child(table, 0);
- g_assert(atk_object_get_role(tableCell) == ATK_ROLE_TABLE_CELL);
- result = atk_text_set_caret_offset(ATK_TEXT(tableCell), 2);
- g_assert_cmpint(result, ==, TRUE);
- offset = atk_text_get_caret_offset(ATK_TEXT(tableCell));
- g_assert_cmpint(offset, ==, 2);
-
- g_free(textCaretMovedResult);
-
- g_object_unref(paragraph);
- g_object_unref(link);
- g_object_unref(list);
- g_object_unref(listItem);
- g_object_unref(panel);
- g_object_unref(comboBox);
- g_object_unref(menuPopup);
- g_object_unref(comboBoxOption);
- g_object_unref(textEntry);
- g_object_unref(table);
- g_object_unref(tableCell);
- g_object_unref(webView);
-}
-
-static void testWebkitAtkCaretOffsetsAndExtranousWhiteSpaces()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, contentsWithExtraneousWhiteSpaces, 0, 0, 0);
-
- /* Enable caret browsing. */
- WebKitWebSettings* settings = webkit_web_view_get_settings(webView);
- g_object_set(G_OBJECT(settings), "enable-caret-browsing", TRUE, NULL);
-
- /* Get to the inner AtkText object. */
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
- object = atk_object_ref_accessible_child(object, 0);
- g_assert(object);
-
- AtkText* textObject = ATK_TEXT(object);
- g_assert(ATK_IS_TEXT(textObject));
-
- gint characterCount = atk_text_get_character_count(textObject);
- g_assert_cmpint(characterCount, ==, 25);
-
- gboolean result = atk_text_set_caret_offset(textObject, characterCount - 1);
- g_assert_cmpint(result, ==, TRUE);
-
- gint caretOffset = atk_text_get_caret_offset(textObject);
- g_assert_cmpint(caretOffset, ==, characterCount - 1);
-
- result = atk_text_set_caret_offset(textObject, characterCount);
- g_assert_cmpint(result, ==, TRUE);
-
- caretOffset = atk_text_get_caret_offset(textObject);
- g_assert_cmpint(caretOffset, ==, characterCount);
-
- g_object_unref(object);
- g_object_unref(webView);
-}
-
-static void testWebkitAtkComboBox()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, comboBoxSelector, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- AtkObject* formObject = atk_object_ref_accessible_child(object, 0);
- g_assert(formObject);
-
- AtkObject* comboBox = atk_object_ref_accessible_child(formObject, 0);
- g_assert(ATK_IS_OBJECT(comboBox));
-
- AtkObject* menuPopup = atk_object_ref_accessible_child(comboBox, 0);
- g_assert(ATK_IS_OBJECT(menuPopup));
-
- AtkObject* item1 = atk_object_ref_accessible_child(menuPopup, 0);
- g_assert(ATK_IS_OBJECT(item1));
-
- AtkObject* item2 = atk_object_ref_accessible_child(menuPopup, 1);
- g_assert(ATK_IS_OBJECT(item2));
-
- /* Check roles. */
- g_assert(atk_object_get_role(comboBox) == ATK_ROLE_COMBO_BOX);
- g_assert(atk_object_get_role(menuPopup) == ATK_ROLE_MENU);
- g_assert(atk_object_get_role(item1) == ATK_ROLE_MENU_ITEM);
- g_assert(atk_object_get_role(item2) == ATK_ROLE_MENU_ITEM);
-
- /* Check the implementation of the AtkSelection interface. */
- g_assert(ATK_IS_SELECTION(comboBox));
- AtkSelection* atkSelection = ATK_SELECTION(comboBox);
- g_assert_cmpint(atk_selection_get_selection_count(atkSelection), ==, 1);
- g_assert(atk_selection_is_child_selected(atkSelection, 0));
- g_assert(!atk_selection_is_child_selected(atkSelection, 1));
- AtkObject* selectedItem = atk_selection_ref_selection(atkSelection, 0);
- g_assert(selectedItem == item1);
- g_object_unref(selectedItem);
-
- /* Check that the menu popup has 0 links and doesn't crash from checking. */
- gint nLinks = atk_hypertext_get_n_links(ATK_HYPERTEXT(menuPopup));
- g_assert_cmpint(nLinks, ==, 0);
-
- /* Check the implementations of the AtkAction interface. */
- g_assert(ATK_IS_ACTION(comboBox));
- AtkAction* atkAction = ATK_ACTION(comboBox);
- g_assert_cmpint(atk_action_get_n_actions(atkAction), ==, 1);
- g_assert(atk_action_do_action(atkAction, 0));
-
- g_assert(ATK_IS_ACTION(menuPopup));
- atkAction = ATK_ACTION(menuPopup);
- g_assert_cmpint(atk_action_get_n_actions(atkAction), ==, 1);
- g_assert(atk_action_do_action(atkAction, 0));
-
- g_assert(ATK_IS_ACTION(item1));
- atkAction = ATK_ACTION(item1);
- g_assert_cmpint(atk_action_get_n_actions(atkAction), ==, 1);
- g_assert(atk_action_do_action(atkAction, 0));
-
- g_assert(ATK_IS_ACTION(item2));
- atkAction = ATK_ACTION(item2);
- g_assert_cmpint(atk_action_get_n_actions(atkAction), ==, 1);
- g_assert(atk_action_do_action(atkAction, 0));
-
- /* After selecting the second item, selection should have changed. */
- g_assert_cmpint(atk_selection_get_selection_count(atkSelection), ==, 1);
- g_assert(!atk_selection_is_child_selected(atkSelection, 0));
- g_assert(atk_selection_is_child_selected(atkSelection, 1));
- selectedItem = atk_selection_ref_selection(atkSelection, 0);
- g_assert(selectedItem == item2);
- g_object_unref(selectedItem);
-
- g_object_unref(formObject);
- g_object_unref(comboBox);
- g_object_unref(menuPopup);
- g_object_unref(item1);
- g_object_unref(item2);
- g_object_unref(webView);
-}
-
-static gchar* loadingEventsResult = 0;
-
-static void updateLoadingEventsResult(const gchar* signalName)
-{
- g_assert(signalName);
-
- gchar* previousResult = loadingEventsResult;
- loadingEventsResult = g_strdup_printf("%s|%s", previousResult, signalName);
- g_free(previousResult);
-}
-
-static gboolean documentLoadingEventCallback(GSignalInvocationHint *signalHint, guint numParamValues, const GValue *paramValues, gpointer data)
-{
- // At least we should receive the instance emitting the signal.
- if (numParamValues < 1)
- return TRUE;
-
- GSignalQuery signal_query;
- g_signal_query(signalHint->signal_id, &signal_query);
-
- updateLoadingEventsResult(signal_query.signal_name);
- return TRUE;
-}
-
-static void testWebkitAtkDocumentLoadingEvents()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
-
- /* Connect globally to see those events during a future load. */
- guint loadCompleteListenerId = atk_add_global_event_listener(documentLoadingEventCallback, "ATK:AtkDocument:load-complete");
-
- /* Do the load, so we can see those events happening. */
- loadingEventsResult = g_strdup("");
- webkit_web_view_load_string(webView, contents, 0, 0, 0);
-
- /* Trigger the creation of the full accessibility hierarchy by
- asking for the webArea object, so we can listen to events. */
- getWebAreaObject(webView);
-
- atk_remove_global_event_listener(loadCompleteListenerId);
-
- g_assert_cmpstr(loadingEventsResult, ==, "|load-complete");
-
- g_free(loadingEventsResult);
- g_object_unref(webView);
-}
-
-static void testWebkitAtkEmbeddedObjects()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, embeddedObjects, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- AtkText* paragraph1 = ATK_TEXT(atk_object_ref_accessible_child(object, 0));
- g_assert(ATK_IS_TEXT(paragraph1));
- g_assert(ATK_IS_HYPERTEXT(paragraph1));
-
- gint nLinks = atk_hypertext_get_n_links(ATK_HYPERTEXT(paragraph1));
- g_assert_cmpint(nLinks, ==, 2);
-
- AtkHyperlink* hLink = atk_hypertext_get_link(ATK_HYPERTEXT(paragraph1), 0);
- g_assert(ATK_HYPERLINK(hLink));
- AtkObject* hLinkObject = atk_hyperlink_get_object(hLink, 0);
- g_assert(ATK_OBJECT(hLinkObject));
- g_assert(atk_object_get_role(hLinkObject) == ATK_ROLE_CHECK_BOX);
- g_assert_cmpint(atk_hyperlink_get_start_index(hLink), ==, 8);
- g_assert_cmpint(atk_hyperlink_get_end_index(hLink), ==, 9);
- g_assert_cmpint(atk_hyperlink_get_n_anchors(hLink), ==, 1);
- g_assert_cmpstr(atk_hyperlink_get_uri(hLink, 0), ==, 0);
-
- AtkText* paragraph2 = ATK_TEXT(atk_object_ref_accessible_child(object, 1));
- g_assert(ATK_IS_HYPERTEXT(paragraph2));
-
- nLinks = atk_hypertext_get_n_links(ATK_HYPERTEXT(paragraph2));
- g_assert_cmpint(nLinks, ==, 1);
-
- hLink = atk_hypertext_get_link(ATK_HYPERTEXT(paragraph2), 0);
- g_assert(ATK_HYPERLINK(hLink));
- hLinkObject = atk_hyperlink_get_object(hLink, 0);
- g_assert(ATK_OBJECT(hLinkObject));
- g_assert(atk_object_get_role(hLinkObject) == ATK_ROLE_COMBO_BOX);
- g_assert_cmpint(atk_hyperlink_get_start_index(hLink), ==, 8);
- g_assert_cmpint(atk_hyperlink_get_end_index(hLink), ==, 9);
- g_assert_cmpint(atk_hyperlink_get_n_anchors(hLink), ==, 1);
- g_assert_cmpstr(atk_hyperlink_get_uri(hLink, 0), ==, 0);
-
- AtkText* paragraph3 = ATK_TEXT(atk_object_ref_accessible_child(object, 2));
- g_assert(ATK_IS_HYPERTEXT(paragraph3));
-
- nLinks = atk_hypertext_get_n_links(ATK_HYPERTEXT(paragraph3));
- g_assert_cmpint(nLinks, ==, 1);
-
- hLink = atk_hypertext_get_link(ATK_HYPERTEXT(paragraph3), 0);
- g_assert(ATK_HYPERLINK(hLink));
- hLinkObject = atk_hyperlink_get_object(hLink, 0);
- g_assert(ATK_OBJECT(hLinkObject));
- g_assert(atk_object_get_role(hLinkObject) == ATK_ROLE_PUSH_BUTTON);
- g_assert_cmpint(atk_hyperlink_get_start_index(hLink), ==, 0);
- g_assert_cmpint(atk_hyperlink_get_end_index(hLink), ==, 1);
- g_assert_cmpint(atk_hyperlink_get_n_anchors(hLink), ==, 1);
- g_assert_cmpstr(atk_hyperlink_get_uri(hLink, 0), ==, 0);
-
- g_object_unref(paragraph1);
- g_object_unref(paragraph2);
- g_object_unref(paragraph3);
- g_object_unref(webView);
-}
-
-static void testWebkitAtkGetHeadersInTable()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, contentsInTableWithHeaders, 0, 0, 0);
-
- AtkObject* axWebView = getWebAreaObject(webView);
- g_assert(axWebView);
-
- /* Check table with both column and row headers. */
- AtkObject* table = atk_object_ref_accessible_child(axWebView, 0);
- g_assert(table);
- g_assert(atk_object_get_role(table) == ATK_ROLE_TABLE);
-
- AtkObject* colHeader = atk_table_get_column_header(ATK_TABLE(table), 0);
- g_assert(colHeader);
- g_assert(atk_object_get_role(colHeader) == ATK_ROLE_TABLE_CELL);
- g_assert(atk_object_get_index_in_parent(colHeader) == 0);
-
- colHeader = atk_table_get_column_header(ATK_TABLE(table), 1);
- g_assert(colHeader);
- g_assert(atk_object_get_role(colHeader) == ATK_ROLE_TABLE_CELL);
- g_assert(atk_object_get_index_in_parent(colHeader) == 1);
-
- colHeader = atk_table_get_column_header(ATK_TABLE(table), 2);
- g_assert(colHeader);
- g_assert(atk_object_get_role(colHeader) == ATK_ROLE_TABLE_CELL);
- g_assert(atk_object_get_index_in_parent(colHeader) == 2);
-
- colHeader = atk_table_get_column_header(ATK_TABLE(table), 3);
- g_assert(colHeader);
- g_assert(atk_object_get_role(colHeader) == ATK_ROLE_TABLE_CELL);
- g_assert(atk_object_get_index_in_parent(colHeader) == 2);
-
- AtkObject* rowHeader = atk_table_get_row_header(ATK_TABLE(table), 0);
- g_assert(rowHeader);
- g_assert(atk_object_get_role(rowHeader) == ATK_ROLE_TABLE_CELL);
- g_assert(atk_object_get_index_in_parent(rowHeader) == 0);
-
- rowHeader = atk_table_get_row_header(ATK_TABLE(table), 1);
- g_assert(rowHeader);
- g_assert(atk_object_get_role(rowHeader) == ATK_ROLE_TABLE_CELL);
- g_assert(atk_object_get_index_in_parent(rowHeader) == 3);
-
- rowHeader = atk_table_get_row_header(ATK_TABLE(table), 2);
- g_assert(rowHeader);
- g_assert(atk_object_get_role(rowHeader) == ATK_ROLE_TABLE_CELL);
- g_assert(atk_object_get_index_in_parent(rowHeader) == 7);
-
- rowHeader = atk_table_get_row_header(ATK_TABLE(table), 3);
- g_assert(rowHeader);
- g_assert(atk_object_get_role(rowHeader) == ATK_ROLE_TABLE_CELL);
- g_assert(atk_object_get_index_in_parent(rowHeader) == 7);
-
- g_object_unref(table);
-
- /* Check table with no headers at all. */
- table = atk_object_ref_accessible_child(axWebView, 1);
- g_assert(table);
- g_assert(atk_object_get_role(table) == ATK_ROLE_TABLE);
-
- colHeader = atk_table_get_column_header(ATK_TABLE(table), 0);
- g_assert(colHeader == 0);
-
- colHeader = atk_table_get_column_header(ATK_TABLE(table), 1);
- g_assert(colHeader == 0);
-
- rowHeader = atk_table_get_row_header(ATK_TABLE(table), 0);
- g_assert(rowHeader == 0);
-
- rowHeader = atk_table_get_row_header(ATK_TABLE(table), 1);
- g_assert(rowHeader == 0);
-
- g_object_unref(table);
- g_object_unref(webView);
-}
-
-static gint compAtkAttribute(AtkAttribute* a1, AtkAttribute* a2)
-{
- gint strcmpVal = g_strcmp0(a1->name, a2->name);
- if (strcmpVal)
- return strcmpVal;
- return g_strcmp0(a1->value, a2->value);
-}
-
-static gint compAtkAttributeName(AtkAttribute* a1, AtkAttribute* a2)
-{
- return g_strcmp0(a1->name, a2->name);
-}
-
-static gboolean atkAttributeSetAttributeNameHasValue(AtkAttributeSet* set, const gchar* attributeName, const gchar* value)
-{
- AtkAttribute at;
- at.name = (gchar*)attributeName;
- GSList* element = g_slist_find_custom(set, &at, (GCompareFunc)compAtkAttributeName);
- return element && !g_strcmp0(((AtkAttribute*)(element->data))->value, value);
-}
-
-static gboolean atkAttributeSetContainsAttributeName(AtkAttributeSet* set, const gchar* attributeName)
-{
- AtkAttribute at;
- at.name = (gchar*)attributeName;
- return g_slist_find_custom(set, &at, (GCompareFunc)compAtkAttributeName) ? true : false;
-}
-
-static gboolean atkAttributeSetAttributeHasValue(AtkAttributeSet* set, AtkTextAttribute attribute, const gchar* value)
-{
- return atkAttributeSetAttributeNameHasValue(set, atk_text_attribute_get_name(attribute), value);
-}
-
-static gboolean atkAttributeSetAreEqual(AtkAttributeSet* set1, AtkAttributeSet* set2)
-{
- if (!set1)
- return !set2;
-
- set1 = g_slist_sort(set1, (GCompareFunc)compAtkAttribute);
- set2 = g_slist_sort(set2, (GCompareFunc)compAtkAttribute);
-
- while (set1) {
- if (!set2 || compAtkAttribute(set1->data, set2->data))
- return FALSE;
-
- set1 = set1->next;
- set2 = set2->next;
- }
-
- return (!set2);
-}
-
-static void testWebkitAtkTextAttributes()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, textWithAttributes, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- AtkObject* child = atk_object_ref_accessible_child(object, 0);
- g_assert(child && ATK_IS_TEXT(child));
- AtkText* childText = ATK_TEXT(child);
-
- gint startOffset;
- gint endOffset;
- AtkAttributeSet* set1 = atk_text_get_run_attributes(childText, 0, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 0);
- g_assert_cmpint(endOffset, ==, 12);
- g_assert(atkAttributeSetAreEqual(set1, 0));
-
- AtkAttributeSet* set2 = atk_text_get_run_attributes(childText, 15, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 12);
- g_assert_cmpint(endOffset, ==, 17);
- g_assert(atkAttributeSetAttributeHasValue(set2, ATK_TEXT_ATTR_STYLE, "italic"));
-
- AtkAttributeSet* set3 = atk_text_get_run_attributes(childText, 17, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 17);
- g_assert_cmpint(endOffset, ==, 40);
- g_assert(atkAttributeSetAttributeHasValue(set3, ATK_TEXT_ATTR_WEIGHT, "700"));
-
- AtkAttributeSet* set4 = atk_text_get_default_attributes(childText);
- g_assert(atkAttributeSetAttributeHasValue(set4, ATK_TEXT_ATTR_STYLE, "normal"));
- g_assert(atkAttributeSetAttributeHasValue(set4, ATK_TEXT_ATTR_JUSTIFICATION, "right"));
- g_assert(atkAttributeSetAttributeHasValue(set4, ATK_TEXT_ATTR_SIZE, "14"));
- atk_attribute_set_free(set1);
- atk_attribute_set_free(set2);
- atk_attribute_set_free(set3);
- atk_attribute_set_free(set4);
-
- g_object_unref(child);
- child = atk_object_ref_accessible_child(object, 1);
- g_assert(child && ATK_IS_TEXT(child));
- childText = ATK_TEXT(child);
-
- set1 = atk_text_get_default_attributes(childText);
- g_assert(atkAttributeSetAttributeHasValue(set1, ATK_TEXT_ATTR_FAMILY_NAME, "monospace"));
- g_assert(atkAttributeSetAttributeHasValue(set1, ATK_TEXT_ATTR_STYLE, "normal"));
- g_assert(atkAttributeSetAttributeHasValue(set1, ATK_TEXT_ATTR_STRIKETHROUGH, "false"));
- g_assert(atkAttributeSetAttributeHasValue(set1, ATK_TEXT_ATTR_WEIGHT, "400"));
- g_assert(atkAttributeSetAttributeHasValue(set1, ATK_TEXT_ATTR_FG_COLOR, "120,121,122"));
-
- set2 = atk_text_get_run_attributes(childText, 43, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 43);
- g_assert_cmpint(endOffset, ==, 80);
- /* Checks that default attributes of text are not returned when called to atk_text_get_run_attributes. */
- g_assert(!atkAttributeSetAttributeHasValue(set2, ATK_TEXT_ATTR_FG_COLOR, "120,121,122"));
- g_assert(atkAttributeSetAttributeHasValue(set2, ATK_TEXT_ATTR_UNDERLINE, "single"));
- g_assert(atkAttributeSetAttributeHasValue(set2, ATK_TEXT_ATTR_BG_COLOR, "80,81,82"));
- atk_attribute_set_free(set1);
- atk_attribute_set_free(set2);
- g_object_unref(child);
-
- child = atk_object_ref_accessible_child(object, 2);
- g_assert(child && ATK_IS_TEXT(child));
- childText = ATK_TEXT(child);
-
- set1 = atk_text_get_run_attributes(childText, 0, &startOffset, &endOffset);
- set2 = atk_text_get_run_attributes(childText, 3, &startOffset, &endOffset);
- g_assert(atkAttributeSetAreEqual(set1, set2));
- atk_attribute_set_free(set2);
-
- set2 = atk_text_get_run_attributes(childText, 1, &startOffset, &endOffset);
- set3 = atk_text_get_run_attributes(childText, 5, &startOffset, &endOffset);
- g_assert(atkAttributeSetAreEqual(set2, set3));
- g_assert(!atkAttributeSetAreEqual(set1, set2));
- atk_attribute_set_free(set3);
-
- set3 = atk_text_get_run_attributes(childText, 2, &startOffset, &endOffset);
- set4 = atk_text_get_run_attributes(childText, 6, &startOffset, &endOffset);
- g_assert(atkAttributeSetAreEqual(set3, set4));
- g_assert(!atkAttributeSetAreEqual(set1, set3));
- g_assert(!atkAttributeSetAreEqual(set2, set3));
- atk_attribute_set_free(set1);
- atk_attribute_set_free(set2);
- atk_attribute_set_free(set3);
- atk_attribute_set_free(set4);
- g_object_unref(child);
-
- child = atk_object_ref_accessible_child(object, 3);
- g_assert(child && ATK_IS_TEXT(child));
- childText = ATK_TEXT(child);
- set1 = atk_text_get_run_attributes(childText, 24, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 21);
- g_assert_cmpint(endOffset, ==, 25);
- g_assert(atkAttributeSetAttributeHasValue(set1, ATK_TEXT_ATTR_STRIKETHROUGH, "true"));
-
- set2 = atk_text_get_run_attributes(childText, 25, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 25);
- g_assert_cmpint(endOffset, ==, 30);
- g_assert(atkAttributeSetAreEqual(set2, 0));
-
- set3 = atk_text_get_default_attributes(childText);
- g_assert(atkAttributeSetAttributeHasValue(set3, ATK_TEXT_ATTR_JUSTIFICATION, "center"));
- atk_attribute_set_free(set1);
- atk_attribute_set_free(set2);
- atk_attribute_set_free(set3);
-
- g_object_unref(child);
-}
-
-static gchar* textSelectionChangedResult = 0;
-
-static void textSelectionChangedCallback(AtkText* text, gpointer data)
-{
- g_assert(ATK_IS_TEXT(text));
-
- g_free(textSelectionChangedResult);
- AtkRole role = atk_object_get_role(ATK_OBJECT(text));
- int startOffset = 0;
- int endOffset = 0;
- atk_text_get_selection(ATK_TEXT(text), 0, &startOffset, &endOffset);
- textSelectionChangedResult = g_strdup_printf("|%s|%d|%d|", atk_role_get_name(role), startOffset, endOffset);
-}
-
-static void testWebkitAtkTextSelections()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, textForSelections, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- AtkText* paragraph1 = ATK_TEXT(atk_object_ref_accessible_child(object, 0));
- g_assert(ATK_IS_TEXT(paragraph1));
- g_signal_connect(paragraph1, "text-selection-changed", G_CALLBACK(textSelectionChangedCallback), 0);
-
- AtkText* paragraph2 = ATK_TEXT(atk_object_ref_accessible_child(object, 1));
- g_assert(ATK_IS_TEXT(paragraph2));
- g_signal_connect(paragraph2, "text-selection-changed", G_CALLBACK(textSelectionChangedCallback), 0);
-
- AtkText* link = ATK_TEXT(atk_object_ref_accessible_child(ATK_OBJECT(paragraph2), 0));
- g_assert(ATK_IS_TEXT(link));
-
- AtkObject* list = atk_object_ref_accessible_child(object, 2);
- g_assert(ATK_OBJECT(list));
-
- AtkText* listItem = ATK_TEXT(atk_object_ref_accessible_child(list, 0));
- g_assert(ATK_IS_TEXT(listItem));
-
- /* First paragraph (simple text). */
-
- /* Basic initial checks. */
- g_assert_cmpint(atk_text_get_n_selections(paragraph1), ==, 0);
-
- gint startOffset;
- gint endOffset;
- gchar* selectedText = atk_text_get_selection(paragraph1, 0, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 0);
- g_assert_cmpint(endOffset, ==, 0);
- g_assert_cmpstr(selectedText, ==, 0);
- g_free (selectedText);
-
- /* Try removing a non existing (yet) selection. */
- gboolean result = atk_text_remove_selection(paragraph1, 0);
- g_assert(!result);
-
- /* Try setting a 0-char selection. */
- result = atk_text_set_selection(paragraph1, 0, 5, 5);
- g_assert(result);
-
- /* Make a selection and test it. */
- result = atk_text_set_selection(paragraph1, 0, 5, 25);
- g_assert(result);
- g_assert_cmpint(atk_text_get_n_selections(paragraph1), ==, 1);
- g_assert_cmpstr(textSelectionChangedResult, ==, "|paragraph|5|25|");
- selectedText = atk_text_get_selection(paragraph1, 0, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 5);
- g_assert_cmpint(endOffset, ==, 25);
- g_assert_cmpstr(selectedText, ==, "agraph with plain te");
- g_free (selectedText);
-
- /* Try removing the selection from other AtkText object (should fail). */
- result = atk_text_remove_selection(paragraph2, 0);
- g_assert(!result);
-
- /* Remove the selection and test everything again. */
- result = atk_text_remove_selection(paragraph1, 0);
- g_assert(result);
- g_assert_cmpint(atk_text_get_n_selections(paragraph1), ==, 0);
- selectedText = atk_text_get_selection(paragraph1, 0, &startOffset, &endOffset);
- /* Now offsets should be the same, set to the last position of the caret. */
- g_assert_cmpint(startOffset, ==, endOffset);
- g_assert_cmpint(startOffset, ==, 25);
- g_assert_cmpint(endOffset, ==, 25);
- g_assert_cmpstr(selectedText, ==, 0);
- g_free (selectedText);
-
- /* Second paragraph (text + link + text). */
-
- /* Set a selection partially covering the link and test it. */
- result = atk_text_set_selection(paragraph2, 0, 7, 21);
- g_assert(result);
-
- /* Test the paragraph first. */
- g_assert_cmpint(atk_text_get_n_selections(paragraph2), ==, 1);
- selectedText = atk_text_get_selection(paragraph2, 0, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 7);
- g_assert_cmpint(endOffset, ==, 21);
- g_assert_cmpstr(selectedText, ==, "raph with a li");
- g_free (selectedText);
-
- /* Now test just the link. */
- g_assert_cmpint(atk_text_get_n_selections(link), ==, 1);
- selectedText = atk_text_get_selection(link, 0, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 0);
- g_assert_cmpint(endOffset, ==, 4);
- g_assert_cmpstr(selectedText, ==, "a li");
- g_free (selectedText);
-
- /* Make a selection after the link and check selection for the whole paragraph. */
- result = atk_text_set_selection(paragraph2, 0, 27, 37);
- g_assert(result);
- g_assert_cmpint(atk_text_get_n_selections(paragraph2), ==, 1);
- g_assert_cmpstr(textSelectionChangedResult, ==, "|paragraph|27|37|");
- selectedText = atk_text_get_selection(paragraph2, 0, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 27);
- g_assert_cmpint(endOffset, ==, 37);
- g_assert_cmpstr(selectedText, ==, "the middle");
- g_free (selectedText);
-
- /* Remove selections and text everything again. */
- result = atk_text_remove_selection(paragraph2, 0);
- g_assert(result);
- g_assert_cmpint(atk_text_get_n_selections(paragraph2), ==, 0);
- selectedText = atk_text_get_selection(paragraph2, 0, &startOffset, &endOffset);
- /* Now offsets should be the same (no selection). */
- g_assert_cmpint(startOffset, ==, endOffset);
- g_assert_cmpstr(selectedText, ==, 0);
- g_free (selectedText);
-
- g_assert_cmpint(atk_text_get_n_selections(link), ==, 0);
- selectedText = atk_text_get_selection(link, 0, &startOffset, &endOffset);
- /* Now offsets should be the same (no selection). */
- g_assert_cmpint(startOffset, ==, endOffset);
- g_assert_cmpstr(selectedText, ==, 0);
- g_free (selectedText);
-
- /* List item */
-
- g_assert(atk_object_get_role(list) == ATK_ROLE_LIST);
- g_assert_cmpint(atk_object_get_n_accessible_children(list), ==, 1);
-
- /* It's not possible to select text inside an item's marker. */
- result = atk_text_set_selection (listItem, 0, 0, 9);
- g_assert(!result);
- result = atk_text_set_selection (listItem, 0, 9, 1);
- g_assert(!result);
-
- /* It should be possible to select text inside an item's text. */
- result = atk_text_set_selection (listItem, 0, 3, 9);
- g_assert(result);
-
- g_assert_cmpint(atk_text_get_n_selections(listItem), ==, 1);
- selectedText = atk_text_get_selection(listItem, 0, &startOffset, &endOffset);
- g_assert_cmpint(startOffset, ==, 3);
- g_assert_cmpint(endOffset, ==, 9);
- g_assert_cmpstr(selectedText, ==, "A list");
- g_free (selectedText);
-
- g_free(textSelectionChangedResult);
-
- g_object_unref(paragraph1);
- g_object_unref(paragraph2);
- g_object_unref(link);
- g_object_unref(list);
- g_object_unref(listItem);
- g_object_unref(webView);
-}
-
-static void testWebkitAtkGetExtents()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, centeredContents, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- AtkText* shortText1 = ATK_TEXT(atk_object_ref_accessible_child(object, 0));
- g_assert(ATK_IS_TEXT(shortText1));
- AtkText* longText = ATK_TEXT(atk_object_ref_accessible_child(object, 1));
- g_assert(ATK_IS_TEXT(longText));
- AtkText* shortText2 = ATK_TEXT(atk_object_ref_accessible_child(object, 2));
- g_assert(ATK_IS_TEXT(shortText2));
- AtkText* multilineText = ATK_TEXT(atk_object_ref_accessible_child(object, 3));
- g_assert(ATK_IS_TEXT(multilineText));
-
- /* Start with window extents. */
- AtkTextRectangle sline_window1, sline_window2, lline_window, mline_window;
- atk_text_get_range_extents(shortText1, 0, 10, ATK_XY_WINDOW, &sline_window1);
- atk_text_get_range_extents(longText, 0, 44, ATK_XY_WINDOW, &lline_window);
- atk_text_get_range_extents(shortText2, 0, 10, ATK_XY_WINDOW, &sline_window2);
- atk_text_get_range_extents(multilineText, 0, 60, ATK_XY_WINDOW, &mline_window);
-
- /* Check vertical line position. */
- g_assert_cmpint(sline_window1.y + sline_window1.height, <=, lline_window.y);
- g_assert_cmpint(lline_window.y + lline_window.height + sline_window2.height, <=, mline_window.y);
-
- /* Paragraphs 1 and 3 have identical text and alignment. */
- g_assert_cmpint(sline_window1.x, ==, sline_window2.x);
- g_assert_cmpint(sline_window1.width, ==, sline_window2.width);
- g_assert_cmpint(sline_window1.height, ==, sline_window2.height);
-
- /* All lines should be the same height; line 2 is the widest line. */
- g_assert_cmpint(sline_window1.height, ==, lline_window.height);
- g_assert_cmpint(sline_window1.width, <, lline_window.width);
-
- /* Make sure the character extents jive with the range extents. */
- gint x;
- gint y;
- gint width;
- gint height;
-
- /* First paragraph (short text). */
- atk_text_get_character_extents(shortText1, 0, &x, &y, &width, &height, ATK_XY_WINDOW);
- g_assert_cmpint(x, ==, sline_window1.x);
- g_assert_cmpint(y, ==, sline_window1.y);
- g_assert_cmpint(height, ==, sline_window1.height);
-
- atk_text_get_character_extents(shortText1, 9, &x, &y, &width, &height, ATK_XY_WINDOW);
- g_assert_cmpint(x, ==, sline_window1.x + sline_window1.width - width);
- g_assert_cmpint(y, ==, sline_window1.y);
- g_assert_cmpint(height, ==, sline_window1.height);
-
- /* Second paragraph (long text). */
- atk_text_get_character_extents(longText, 0, &x, &y, &width, &height, ATK_XY_WINDOW);
- g_assert_cmpint(x, ==, lline_window.x);
- g_assert_cmpint(y, ==, lline_window.y);
- g_assert_cmpint(height, ==, lline_window.height);
-
- atk_text_get_character_extents(longText, 43, &x, &y, &width, &height, ATK_XY_WINDOW);
- g_assert_cmpint(x, ==, lline_window.x + lline_window.width - width);
- g_assert_cmpint(y, ==, lline_window.y);
- g_assert_cmpint(height, ==, lline_window.height);
-
- /* Third paragraph (short text). */
- atk_text_get_character_extents(shortText2, 0, &x, &y, &width, &height, ATK_XY_WINDOW);
- g_assert_cmpint(x, ==, sline_window2.x);
- g_assert_cmpint(y, ==, sline_window2.y);
- g_assert_cmpint(height, ==, sline_window2.height);
-
- atk_text_get_character_extents(shortText2, 9, &x, &y, &width, &height, ATK_XY_WINDOW);
- g_assert_cmpint(x, ==, sline_window2.x + sline_window2.width - width);
- g_assert_cmpint(y, ==, sline_window2.y);
- g_assert_cmpint(height, ==, sline_window2.height);
-
- /* Four paragraph (3 lines multi-line text). */
- atk_text_get_character_extents(multilineText, 0, &x, &y, &width, &height, ATK_XY_WINDOW);
- g_assert_cmpint(x, ==, mline_window.x);
- g_assert_cmpint(y, ==, mline_window.y);
- g_assert_cmpint(3 * height, ==, mline_window.height);
-
- atk_text_get_character_extents(multilineText, 59, &x, &y, &width, &height, ATK_XY_WINDOW);
- /* Last line won't fill the whole width of the rectangle. */
- g_assert_cmpint(x, <=, mline_window.x + mline_window.width - width);
- g_assert_cmpint(y, ==, mline_window.y + mline_window.height - height);
- g_assert_cmpint(height, <=, mline_window.height);
-
- /* Check that extent for a full line are the same height than for
- a partial section of the same line */
- gint startOffset;
- gint endOffset;
-
-#if !ATK_CHECK_VERSION(2, 10, 0)
- gchar* text = atk_text_get_text_at_offset(multilineText, 0, ATK_TEXT_BOUNDARY_LINE_START, &startOffset, &endOffset);
- g_free(text);
-#else
- gchar* text = atk_text_get_string_at_offset(multilineText, 0, ATK_TEXT_GRANULARITY_LINE, &startOffset, &endOffset);
- g_free(text);
-#endif
-
- AtkTextRectangle fline_window;
- AtkTextRectangle afline_window;
- atk_text_get_range_extents(multilineText, startOffset, endOffset, ATK_XY_WINDOW, &fline_window);
- atk_text_get_range_extents(multilineText, startOffset, endOffset - 1, ATK_XY_WINDOW, &afline_window);
- g_assert_cmpint(fline_window.x, ==, afline_window.x);
- g_assert_cmpint(fline_window.y, ==, afline_window.y);
- g_assert_cmpint(fline_window.height, ==, afline_window.height);
-
- g_object_unref(shortText1);
- g_object_unref(shortText2);
- g_object_unref(longText);
- g_object_unref(multilineText);
- g_object_unref(webView);
-}
-
-static void testWebkitAtkLayoutAndDataTables()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, layoutAndDataTables, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- /* Check the non-layout table (data table). */
-
- AtkObject* table1 = atk_object_ref_accessible_child(object, 0);
- g_assert(ATK_IS_TABLE(table1));
- AtkAttributeSet* set1 = atk_object_get_attributes(table1);
- g_assert(set1);
- g_assert(!atkAttributeSetContainsAttributeName(set1, "layout-guess"));
- atk_attribute_set_free(set1);
-
- /* Check the layout table. */
-
- AtkObject* table2 = atk_object_ref_accessible_child(object, 1);
- g_assert(ATK_IS_TABLE(table2));
- AtkAttributeSet* set2 = atk_object_get_attributes(table2);
- g_assert(set2);
- g_assert(atkAttributeSetContainsAttributeName(set2, "layout-guess"));
- g_assert(atkAttributeSetAttributeNameHasValue(set2, "layout-guess", "true"));
- atk_attribute_set_free(set2);
-
- g_object_unref(table1);
- g_object_unref(table2);
- g_object_unref(webView);
-}
-
-static void testWebkitAtkLinksWithInlineImages()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, linksWithInlineImages, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- /* First paragraph (link at the beginning). */
- AtkObject* paragraph = atk_object_ref_accessible_child(object, 0);
- g_assert(ATK_IS_TEXT(paragraph));
- gint startOffset;
- gint endOffset;
-
-#if !ATK_CHECK_VERSION(2, 10, 0)
- gchar* text = atk_text_get_text_at_offset(ATK_TEXT(paragraph), 0, ATK_TEXT_BOUNDARY_LINE_START, &startOffset, &endOffset);
- g_assert(text);
- g_assert_cmpstr(text, ==, "foo bar baz");
- g_assert_cmpint(startOffset, ==, 0);
- g_assert_cmpint(endOffset, ==, 11);
- g_free(text);
-#else
- gchar* text = atk_text_get_string_at_offset(ATK_TEXT(paragraph), 0, ATK_TEXT_GRANULARITY_LINE, &startOffset, &endOffset);
- g_assert(text);
- g_assert_cmpstr(text, ==, "foo bar baz");
- g_assert_cmpint(startOffset, ==, 0);
- g_assert_cmpint(endOffset, ==, 11);
- g_free(text);
-#endif
-
- g_object_unref(paragraph);
-
- /* Second paragraph (link in the middle). */
- paragraph = atk_object_ref_accessible_child(object, 1);
- g_assert(ATK_IS_TEXT(paragraph));
-
-#if !ATK_CHECK_VERSION(2, 10, 0)
- text = atk_text_get_text_at_offset(ATK_TEXT(paragraph), 0, ATK_TEXT_BOUNDARY_LINE_START, &startOffset, &endOffset);
- g_assert(text);
- g_assert_cmpstr(text, ==, "foo bar baz");
- g_assert_cmpint(startOffset, ==, 0);
- g_assert_cmpint(endOffset, ==, 11);
- g_free(text);
-#else
- text = atk_text_get_string_at_offset(ATK_TEXT(paragraph), 0, ATK_TEXT_GRANULARITY_LINE, &startOffset, &endOffset);
- g_assert(text);
- g_assert_cmpstr(text, ==, "foo bar baz");
- g_assert_cmpint(startOffset, ==, 0);
- g_assert_cmpint(endOffset, ==, 11);
- g_free(text);
-#endif
-
- g_object_unref(paragraph);
-
- /* Third paragraph (link at the end). */
- paragraph = atk_object_ref_accessible_child(object, 2);
- g_assert(ATK_IS_TEXT(paragraph));
-
-#if !ATK_CHECK_VERSION(2, 10, 0)
- text = atk_text_get_text_at_offset(ATK_TEXT(paragraph), 0, ATK_TEXT_BOUNDARY_LINE_START, &startOffset, &endOffset);
- g_assert(text);
- g_assert_cmpstr(text, ==, "foo bar baz");
- g_assert_cmpint(startOffset, ==, 0);
- g_assert_cmpint(endOffset, ==, 11);
- g_free(text);
-#else
- text = atk_text_get_string_at_offset(ATK_TEXT(paragraph), 0, ATK_TEXT_GRANULARITY_LINE, &startOffset, &endOffset);
- g_assert(text);
- g_assert_cmpstr(text, ==, "foo bar baz");
- g_assert_cmpint(startOffset, ==, 0);
- g_assert_cmpint(endOffset, ==, 11);
- g_free(text);
-#endif
-
- g_object_unref(paragraph);
- g_object_unref(webView);
-}
-
-static void testWebkitAtkHypertextAndHyperlinks()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, hypertextAndHyperlinks, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- AtkObject* paragraph1 = atk_object_ref_accessible_child(object, 0);
- g_assert(ATK_OBJECT(paragraph1));
- g_assert(atk_object_get_role(paragraph1) == ATK_ROLE_PARAGRAPH);
- g_assert(ATK_IS_HYPERTEXT(paragraph1));
-
- /* No links in the first paragraph. */
- gint nLinks = atk_hypertext_get_n_links(ATK_HYPERTEXT(paragraph1));
- g_assert_cmpint(nLinks, ==, 0);
-
- AtkObject* paragraph2 = atk_object_ref_accessible_child(object, 1);
- g_assert(ATK_OBJECT(paragraph2));
- g_assert(atk_object_get_role(paragraph2) == ATK_ROLE_PARAGRAPH);
- g_assert(ATK_IS_HYPERTEXT(paragraph2));
-
- /* Check links in the second paragraph.
- nLinks = atk_hypertext_get_n_links(ATK_HYPERTEXT(paragraph2));
- g_assert_cmpint(nLinks, ==, 3); */
-
- AtkHyperlink* hLink1 = atk_hypertext_get_link(ATK_HYPERTEXT(paragraph2), 0);
- g_assert(ATK_HYPERLINK(hLink1));
- AtkObject* hLinkObject1 = atk_hyperlink_get_object(hLink1, 0);
- g_assert(ATK_OBJECT(hLinkObject1));
- g_assert(atk_object_get_role(hLinkObject1) == ATK_ROLE_LINK);
- g_assert_cmpint(atk_hyperlink_get_start_index(hLink1), ==, 0);
- g_assert_cmpint(atk_hyperlink_get_end_index(hLink1), ==, 6);
- g_assert_cmpint(atk_hyperlink_get_n_anchors(hLink1), ==, 1);
- g_assert_cmpstr(atk_hyperlink_get_uri(hLink1, 0), ==, "http://foo.bar.baz/");
-
- AtkHyperlink* hLink2 = atk_hypertext_get_link(ATK_HYPERTEXT(paragraph2), 1);
- g_assert(ATK_HYPERLINK(hLink2));
- AtkObject* hLinkObject2 = atk_hyperlink_get_object(hLink2, 0);
- g_assert(ATK_OBJECT(hLinkObject2));
- g_assert(atk_object_get_role(hLinkObject2) == ATK_ROLE_LINK);
- g_assert_cmpint(atk_hyperlink_get_start_index(hLink2), ==, 12);
- g_assert_cmpint(atk_hyperlink_get_end_index(hLink2), ==, 32);
- g_assert_cmpint(atk_hyperlink_get_n_anchors(hLink2), ==, 1);
- g_assert_cmpstr(atk_hyperlink_get_uri(hLink2, 0), ==, "http://bar.baz.foo/");
-
- AtkHyperlink* hLink3 = atk_hypertext_get_link(ATK_HYPERTEXT(paragraph2), 2);
- g_assert(ATK_HYPERLINK(hLink3));
- AtkObject* hLinkObject3 = atk_hyperlink_get_object(hLink3, 0);
- g_assert(ATK_OBJECT(hLinkObject3));
- g_assert(atk_object_get_role(hLinkObject3) == ATK_ROLE_LINK);
- g_assert_cmpint(atk_hyperlink_get_start_index(hLink3), ==, 65);
- g_assert_cmpint(atk_hyperlink_get_end_index(hLink3), ==, 75);
- g_assert_cmpint(atk_hyperlink_get_n_anchors(hLink3), ==, 1);
- g_assert_cmpstr(atk_hyperlink_get_uri(hLink3, 0), ==, "http://baz.foo.bar/");
-
- AtkObject* list = atk_object_ref_accessible_child(object, 2);
- g_assert(ATK_OBJECT(list));
- g_assert(atk_object_get_role(list) == ATK_ROLE_LIST);
- g_assert_cmpint(atk_object_get_n_accessible_children(list), ==, 1);
-
- AtkObject* listItem = atk_object_ref_accessible_child(list, 0);
- g_assert(ATK_IS_TEXT(listItem));
- g_assert(ATK_IS_HYPERTEXT(listItem));
-
- AtkHyperlink* hLinkInListItem = atk_hypertext_get_link(ATK_HYPERTEXT(listItem), 0);
- g_assert(ATK_HYPERLINK(hLinkInListItem));
- AtkObject* hLinkObject = atk_hyperlink_get_object(hLinkInListItem, 0);
- g_assert(ATK_OBJECT(hLinkObject));
- g_assert(atk_object_get_role(hLinkObject) == ATK_ROLE_LINK);
- g_assert_cmpint(atk_hyperlink_get_start_index(hLinkInListItem), ==, 20);
- g_assert_cmpint(atk_hyperlink_get_end_index(hLinkInListItem), ==, 43);
- g_assert_cmpint(atk_hyperlink_get_n_anchors(hLinkInListItem), ==, 1);
- g_assert_cmpstr(atk_hyperlink_get_uri(hLinkInListItem, 0), ==, "http://foo.bar.baz/");
-
- /* Finally check the AtkAction interface for a given AtkHyperlink. */
- g_assert(ATK_IS_ACTION(hLink1));
- g_assert_cmpint(atk_action_get_n_actions(ATK_ACTION(hLink1)), ==, 1);
- g_assert_cmpstr(atk_action_get_keybinding(ATK_ACTION(hLink1), 0), ==, "");
- g_assert_cmpstr(atk_action_get_name(ATK_ACTION(hLink1), 0), ==, "jump");
- g_assert(atk_action_do_action(ATK_ACTION(hLink1), 0));
-
- g_object_unref(paragraph1);
- g_object_unref(paragraph2);
- g_object_unref(list);
- g_object_unref(listItem);
- g_object_unref(webView);
-}
-
-static void testWebkitAtkListsOfItems()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, listsOfItems, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- /* Unordered list. */
-
- AtkObject* uList = atk_object_ref_accessible_child(object, 0);
- g_assert(ATK_OBJECT(uList));
- g_assert(atk_object_get_role(uList) == ATK_ROLE_LIST);
- g_assert_cmpint(atk_object_get_n_accessible_children(uList), ==, 3);
-
- AtkObject* item1 = atk_object_ref_accessible_child(uList, 0);
- AtkObject* item2 = atk_object_ref_accessible_child(uList, 1);
- AtkObject* item3 = atk_object_ref_accessible_child(uList, 2);
-
- g_assert_cmpint(atk_object_get_n_accessible_children(item1), ==, 0);
- g_assert_cmpint(atk_object_get_n_accessible_children(item2), ==, 1);
- g_assert_cmpint(atk_object_get_n_accessible_children(item3), ==, 1);
-
- g_object_unref(item1);
- g_object_unref(item2);
- g_object_unref(item3);
-
- /* Ordered list. */
-
- AtkObject* oList = atk_object_ref_accessible_child(object, 1);
- g_assert(ATK_OBJECT(oList));
- g_assert(atk_object_get_role(oList) == ATK_ROLE_LIST);
- g_assert_cmpint(atk_object_get_n_accessible_children(oList), ==, 3);
-
- item1 = atk_object_ref_accessible_child(oList, 0);
- item2 = atk_object_ref_accessible_child(oList, 1);
- item3 = atk_object_ref_accessible_child(oList, 2);
-
- g_assert_cmpint(atk_object_get_n_accessible_children(item1), ==, 0);
- g_assert_cmpint(atk_object_get_n_accessible_children(item2), ==, 1);
- g_assert_cmpint(atk_object_get_n_accessible_children(item3), ==, 1);
-
- g_object_unref(item1);
- g_object_unref(item2);
- g_object_unref(item3);
-
- g_object_unref(uList);
- g_object_unref(oList);
- g_object_unref(webView);
-}
-
-typedef enum {
- TEXT_CHANGE_INSERT = 1,
- TEXT_CHANGE_REMOVE = 2
-} TextChangeType;
-
-static gchar* textChangedResult = 0;
-
-static void textChangedCb(AtkText* text, gint pos, gint len, gchar* modifiedText, gpointer data)
-{
- g_assert(text && ATK_IS_OBJECT(text));
-
- TextChangeType type = GPOINTER_TO_INT(data);
- g_free(textChangedResult);
- textChangedResult = g_strdup_printf("|%d|%d|%d|'%s'|", type, pos, len, modifiedText);
-}
-
-static void testWebkitAtkTextChangedNotifications()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, formWithTextInputs, 0, 0, 0);
-
- AtkObject* object = getWebAreaObject(webView);
- g_assert(object);
-
- AtkObject* form = atk_object_ref_accessible_child(object, 0);
- g_assert(ATK_IS_OBJECT(form));
-
- /* First check normal text entries. */
- AtkObject* textEntry = atk_object_ref_accessible_child(form, 0);
- g_assert(ATK_IS_EDITABLE_TEXT(textEntry));
- g_assert(atk_object_get_role(ATK_OBJECT(textEntry)) == ATK_ROLE_ENTRY);
-
- g_signal_connect(textEntry, "text-insert",
- G_CALLBACK(textChangedCb),
- GINT_TO_POINTER(TEXT_CHANGE_INSERT));
- g_signal_connect(textEntry, "text-remove",
- G_CALLBACK(textChangedCb),
- GINT_TO_POINTER(TEXT_CHANGE_REMOVE));
-
- gint pos = 0;
- atk_editable_text_insert_text(ATK_EDITABLE_TEXT(textEntry), "foo bar baz", 11, &pos);
- char* text = atk_text_get_text(ATK_TEXT(textEntry), 0, -1);
- g_assert_cmpstr(text, ==, "foo bar baz");
- g_assert_cmpstr(textChangedResult, ==, "|1|0|11|'foo bar baz'|");
- g_free(text);
-
- atk_editable_text_delete_text(ATK_EDITABLE_TEXT(textEntry), 4, 7);
- text = atk_text_get_text(ATK_TEXT(textEntry), 0, -1);
- g_assert_cmpstr(text, ==, "foo baz");
- g_assert_cmpstr(textChangedResult, ==, "|2|4|3|'bar'|");
- g_free(text);
-
- pos = 4;
- atk_editable_text_insert_text(ATK_EDITABLE_TEXT(textEntry), "qux quux tobeignored", 8, &pos);
- text = atk_text_get_text(ATK_TEXT(textEntry), 0, -1);
- g_assert_cmpstr(text, ==, "foo qux quux baz");
- g_assert_cmpstr(textChangedResult, ==, "|1|4|8|'qux quux'|");
- g_free(text);
-
- /* Now check for password entries. */
- AtkObject* passwordEntry = atk_object_ref_accessible_child(form, 1);
- g_assert(ATK_IS_EDITABLE_TEXT(passwordEntry));
- g_assert(atk_object_get_role(ATK_OBJECT(passwordEntry)) == ATK_ROLE_PASSWORD_TEXT);
-
- g_signal_connect(passwordEntry, "text-insert",
- G_CALLBACK(textChangedCb),
- GINT_TO_POINTER(TEXT_CHANGE_INSERT));
- g_signal_connect(passwordEntry, "text-remove",
- G_CALLBACK(textChangedCb),
- GINT_TO_POINTER(TEXT_CHANGE_REMOVE));
-
- pos = 0;
- /* A single bullet character is '\342\200\242' */
- atk_editable_text_insert_text(ATK_EDITABLE_TEXT(passwordEntry), "foobar", 6, &pos);
- g_assert_cmpstr(textChangedResult, ==, "|1|0|6|'\342\200\242\342\200\242\342\200\242\342\200\242\342\200\242\342\200\242'|");
- text = atk_text_get_text(ATK_TEXT(passwordEntry), 0, -1);
- g_assert_cmpstr(text, ==, "\342\200\242\342\200\242\342\200\242\342\200\242\342\200\242\342\200\242");
- g_free(text);
-
- atk_editable_text_delete_text(ATK_EDITABLE_TEXT(passwordEntry), 2, 4);
- g_assert_cmpstr(textChangedResult, ==, "|2|2|2|'\342\200\242\342\200\242'|");
-
- text = atk_text_get_text(ATK_TEXT(passwordEntry), 0, -1);
- g_assert_cmpstr(text, ==, "\342\200\242\342\200\242\342\200\242\342\200\242");
- g_free(text);
-
- pos = 3;
- atk_editable_text_insert_text(ATK_EDITABLE_TEXT(passwordEntry), "qux tobeignored", 3, &pos);
- g_assert_cmpstr(textChangedResult, ==, "|1|3|3|'\342\200\242\342\200\242\342\200\242'|");
-
- text = atk_text_get_text(ATK_TEXT(passwordEntry), 0, -1);
- g_assert_cmpstr(text, ==, "\342\200\242\342\200\242\342\200\242\342\200\242\342\200\242\342\200\242\342\200\242");
- g_free(text);
-
- g_free(textChangedResult);
-
- g_object_unref(form);
- g_object_unref(textEntry);
- g_object_unref(passwordEntry);
- g_object_unref(webView);
-}
-
-static void testWebkitAtkParentForRootObject()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, contents, 0, 0, 0);
-
- /* We need a parent container widget for the webview. */
- GtkWidget* parentContainer = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- g_object_ref_sink(parentContainer);
- gtk_container_add(GTK_CONTAINER(parentContainer), GTK_WIDGET(webView));
-
- AtkObject* axParent = gtk_widget_get_accessible(parentContainer);
- g_assert(ATK_IS_OBJECT(axParent));
-
- AtkObject* axRoot = gtk_widget_get_accessible(GTK_WIDGET(webView));
- g_assert(ATK_IS_OBJECT(axRoot));
-
- /* The child for the parent container's accessibility object
- should be the accessibility object for the WebView's root. */
- AtkObject* axParentChild = atk_object_ref_accessible_child(axParent, 0);
- g_assert(axParentChild == axRoot);
-
- /* Bottom-up navigation should match top-down one. */
- g_assert(atk_object_get_parent(axParentChild) == axParent);
-
- g_object_unref(axParentChild);
- g_object_unref(parentContainer);
-}
-
-static void testWebkitAtkSetParentForObject()
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- GtkAllocation allocation = { 0, 0, 800, 600 };
- gtk_widget_size_allocate(GTK_WIDGET(webView), &allocation);
- webkit_web_view_load_string(webView, contents, 0, 0, 0);
-
- /* Put the webview in a parent container widget to check that the
- normal behaviour keeps working as expected by default. */
- GtkWidget* parentContainer = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- g_object_ref_sink(parentContainer);
- gtk_container_add(GTK_CONTAINER(parentContainer), GTK_WIDGET(webView));
-
- AtkObject* axRoot = gtk_widget_get_accessible(GTK_WIDGET(webView));
- g_assert(ATK_IS_OBJECT(axRoot));
-
- AtkObject* axParent = gtk_widget_get_accessible(parentContainer);
- g_assert(ATK_IS_OBJECT(axParent));
-
- /* The parent of the root object is the parent container's a11y object. */
- g_assert(atk_object_get_parent(axRoot) == axParent);
-
- /* We now need to use something as a an alternative parent for
- the a11y object associated with the root of the DOM tree. */
- GtkWidget* alternativeParent = gtk_button_new();
- g_object_ref_sink(alternativeParent);
-
- AtkObject* axAlternativeParent = gtk_widget_get_accessible(alternativeParent);
- g_assert(ATK_IS_OBJECT(axAlternativeParent));
-
- /* Manually set the alternative parent's accessibility object as
- the parent for the WebKit accessibility root object and check. */
- atk_object_set_parent(axRoot, axAlternativeParent);
- g_assert(atk_object_get_parent(axRoot) == axAlternativeParent);
-
- g_object_unref(alternativeParent);
- g_object_unref(parentContainer);
-}
-
-#ifdef GTK_API_VERSION_2
-static void initializeTestingFramework(int argc, char** argv)
-{
- /* Ensure GAIL is the only module loaded. */
- g_setenv("GTK_MODULES", "gail", TRUE);
-
- /* Following lines were taken from gtk_test_init(). */
- g_test_init(&argc, &argv, 0);
- gtk_disable_setlocale();
- setlocale(LC_ALL, "C");
-
- gtk_init(&argc, &argv);
-}
-#endif
-
-int main(int argc, char** argv)
-{
-#ifdef GTK_API_VERSION_2
- /* We can't just call to gtk_test_init() in this case because its
- implementation makes sure that no GTK+ module will be loaded, and
- we will need to load GAIL for tests that need to use AtkObjects
- from non-WebKit GtkWidgets (e.g parentForRootObject).*/
- initializeTestingFramework(argc, argv);
-#else
- gtk_test_init(&argc, &argv, NULL);
-#endif
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/atk/caretOffsets", testWebkitAtkCaretOffsets);
- g_test_add_func("/webkit/atk/caretOffsetsAndExtranousWhiteSpaces", testWebkitAtkCaretOffsetsAndExtranousWhiteSpaces);
- g_test_add_func("/webkit/atk/comboBox", testWebkitAtkComboBox);
- g_test_add_func("/webkit/atk/documentLoadingEvents", testWebkitAtkDocumentLoadingEvents);
- g_test_add_func("/webkit/atk/embeddedObjects", testWebkitAtkEmbeddedObjects);
- g_test_add_func("/webkit/atk/getHeadersInTable", testWebkitAtkGetHeadersInTable);
- g_test_add_func("/webkit/atk/textAttributes", testWebkitAtkTextAttributes);
- g_test_add_func("/webkit/atk/textSelections", testWebkitAtkTextSelections);
- g_test_add_func("/webkit/atk/getExtents", testWebkitAtkGetExtents);
- g_test_add_func("/webkit/atk/hypertextAndHyperlinks", testWebkitAtkHypertextAndHyperlinks);
- g_test_add_func("/webkit/atk/layoutAndDataTables", testWebkitAtkLayoutAndDataTables);
- g_test_add_func("/webkit/atk/linksWithInlineImages", testWebkitAtkLinksWithInlineImages);
- g_test_add_func("/webkit/atk/listsOfItems", testWebkitAtkListsOfItems);
- g_test_add_func("/webkit/atk/textChangedNotifications", testWebkitAtkTextChangedNotifications);
- g_test_add_func("/webkit/atk/parentForRootObject", testWebkitAtkParentForRootObject);
- g_test_add_func("/webkit/atk/setParentForObject", testWebkitAtkSetParentForObject);
- return g_test_run ();
-}
-
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testatkroles.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testatkroles.c
deleted file mode 100644
index 88817cf8a..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testatkroles.c
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * Copyright © 2010 Joanmarie Diggs
- * Copyright © 2010 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-/* Non form roles */
-#define HTML_DOCUMENT_FRAME "<html><body>This is a test.</body></html>"
-#define HTML_HEADING "<html><body><h1>1</h1><h2>2</h2><h3>3</h3><h4>4</h4><h5>5</h5><h6>6</h6></body></html>"
-#define HTML_IMAGE "<html><body><img src='foobar.png' alt='This is a test.'/></body></html>"
-#define HTML_LINK_TEXT "<html><body><a href='foobar.html'>This is a test.</a></body></html>"
-#define HTML_LIST "<html><body><ul><li>1</li><li>2</li></ul><ol><li>1</li><li>2</li></ol></body></html>"
-#define HTML_PARAGRAPH "<html><body><p>This is a test.</p></body></html>"
-#define HTML_SECTION "<html><body><div>This is a test.</div></body></html>"
-#define HTML_TABLE "<html><body><table border='1'><tr><td>This is</td><td>a test.</td></tr></table></body></html>"
-#define HTML_SEPARATOR "<html><body><hr/></body></html>"
-#define HTML_COMBOBOX "<html><body><select size='1'><option>one</option><option>two</option><option>three</option></select></body></html>"
-/* Form roles */
-#define HTML_FORM "<html><body><form>This is a test.</form></body></html>"
-#define HTML_CHECK_BOX "<html><body><input type='checkbox' />This is a test.</body></html>"
-#define HTML_LABELED_ENTRY "<html><body><label for='foo'>Name:</label><input type='text' id='foo' /></body></html>"
-#define HTML_LISTBOX "<html><body><select size='3'><option>one</option><option>two</option><option>three</option></select></body></html>"
-#define HTML_PASSWORD_TEXT "<html><body><input type='password' /></body></html>"
-#define HTML_PUSH_BUTTON "<html><body><input type='submit' value='ok' />This is a test.</body></html>"
-#define HTML_RADIO_BUTTON "<html><body><input type='radio' />This is a test.</body></html>"
-
-typedef struct {
- AtkObject* document;
- AtkObject* obj;
- AtkRole role;
- GtkWidget* webView;
- GtkAllocation alloc;
- GMainLoop* loop;
-} AtkRolesFixture;
-
-static gboolean finish_loading(AtkRolesFixture* fixture)
-{
- if (g_main_loop_is_running(fixture->loop))
- g_main_loop_quit(fixture->loop);
-
- // With the change to support WK2 accessibility, the root object
- // has changed and it's no longer the document frame, but a scroll
- // pane containing the document frame as its only child. See the
- // bug 72390 for more details on this change.
- // https://bugs.webkit.org/show_bug.cgi?id=72390
- AtkObject* rootObject = gtk_widget_get_accessible(fixture->webView);
- fixture->document = atk_object_ref_accessible_child(rootObject, 0);
- g_assert(fixture->document);
-
- // Remove the reference added by ref_accessible_child() and
- // return, since we don't need to keep that extra ref at all.
- g_object_unref(fixture->document);
- return FALSE;
-}
-
-static void atk_roles_fixture_setup(AtkRolesFixture* fixture, gconstpointer data)
-{
- fixture->loop = g_main_loop_new(NULL, TRUE);
- fixture->alloc = (GtkAllocation) { 0, 0, 800, 600 };
- fixture->webView = webkit_web_view_new();
- g_object_ref_sink(fixture->webView);
-
- gtk_widget_size_allocate(fixture->webView, &fixture->alloc);
-
- if (data != NULL)
- webkit_web_view_load_string(WEBKIT_WEB_VIEW (fixture->webView), (const char*) data, NULL, NULL, NULL);
-
- g_idle_add((GSourceFunc) finish_loading, fixture);
- g_main_loop_run(fixture->loop);
-}
-
-static void atk_roles_fixture_teardown(AtkRolesFixture* fixture, gconstpointer data)
-{
- g_object_unref(fixture->webView);
- g_main_loop_unref(fixture->loop);
-}
-
-static void get_child_and_test_role(AtkObject* obj, gint pos, AtkRole role)
-{
- AtkObject* child;
- AtkRole child_role;
-
- child = atk_object_ref_accessible_child(obj, pos);
- g_assert(child);
- child_role = atk_object_get_role(child);
- g_assert(child_role == role);
-
- g_object_unref(child);
-}
-
-static void test_webkit_atk_get_role_document_frame(AtkRolesFixture* fixture, gconstpointer data)
-{
- fixture->role = atk_object_get_role(fixture->document);
- g_assert(fixture->role == ATK_ROLE_DOCUMENT_WEB);
-}
-
-static void test_webkit_atk_get_role_heading(AtkRolesFixture* fixture, gconstpointer data)
-{
- get_child_and_test_role(fixture->document, 0, ATK_ROLE_HEADING);
- get_child_and_test_role(fixture->document, 1, ATK_ROLE_HEADING);
- get_child_and_test_role(fixture->document, 2, ATK_ROLE_HEADING);
- get_child_and_test_role(fixture->document, 3, ATK_ROLE_HEADING);
- get_child_and_test_role(fixture->document, 4, ATK_ROLE_HEADING);
- get_child_and_test_role(fixture->document, 5, ATK_ROLE_HEADING);
-}
-
-static void test_webkit_atk_get_role_image(AtkRolesFixture* fixture, gconstpointer data)
-{
- // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of.
- fixture->obj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(fixture->obj);
-
- get_child_and_test_role(fixture->obj, 0, ATK_ROLE_IMAGE);
-
- g_object_unref(fixture->obj);
-}
-
-static void test_webkit_atk_get_role_link(AtkRolesFixture* fixture, gconstpointer data)
-{
- // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of.
- fixture->obj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(fixture->obj);
-
- get_child_and_test_role(fixture->obj, 0, ATK_ROLE_LINK);
-
- g_object_unref(fixture->obj);
-}
-
-static void test_webkit_atk_get_role_list_and_item(AtkRolesFixture* fixture, gconstpointer data)
-{
- AtkObject* listObj;
-
- listObj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(listObj);
- fixture->role = atk_object_get_role(listObj);
- g_assert(fixture->role == ATK_ROLE_LIST);
-
- get_child_and_test_role(listObj, 0, ATK_ROLE_LIST_ITEM);
- get_child_and_test_role(listObj, 1, ATK_ROLE_LIST_ITEM);
- g_object_unref(listObj);
-
- listObj = atk_object_ref_accessible_child(fixture->document, 1);
- g_assert(listObj);
- fixture->role = atk_object_get_role(listObj);
- g_assert(fixture->role == ATK_ROLE_LIST);
-
- get_child_and_test_role(listObj, 0, ATK_ROLE_LIST_ITEM);
- get_child_and_test_role(listObj, 1, ATK_ROLE_LIST_ITEM);
- g_object_unref(listObj);
-}
-
-static void test_webkit_atk_get_role_paragraph(AtkRolesFixture* fixture, gconstpointer data)
-{
- get_child_and_test_role(fixture->document, 0, ATK_ROLE_PARAGRAPH);
-}
-
-static void test_webkit_atk_get_role_section(AtkRolesFixture* fixture, gconstpointer data)
-{
- get_child_and_test_role(fixture->document, 0, ATK_ROLE_SECTION);
-}
-
-// Does not yet test table cells because of bug 30895.
-static void test_webkit_atk_get_role_table(AtkRolesFixture* fixture, gconstpointer data)
-{
- get_child_and_test_role(fixture->document, 0, ATK_ROLE_TABLE);
-}
-
-static void test_webkit_atk_get_role_separator(AtkRolesFixture *fixture, gconstpointer data)
-{
- get_child_and_test_role(fixture->document, 0, ATK_ROLE_SEPARATOR);
-}
-
-static void test_webkit_atk_get_role_combobox(AtkRolesFixture *fixture, gconstpointer data)
-{
- AtkObject* comboboxMenu;
-
- // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of.
- fixture->obj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(fixture->obj);
-
- fixture->obj = atk_object_ref_accessible_child(fixture->obj, 0);
- g_assert(fixture->obj);
- fixture->role = atk_object_get_role(fixture->obj);
- g_assert(fixture->role == ATK_ROLE_COMBO_BOX);
-
- comboboxMenu = atk_object_ref_accessible_child(fixture->obj, 0);
- g_assert(comboboxMenu);
- fixture->role = atk_object_get_role(comboboxMenu);
- g_assert(fixture->role == ATK_ROLE_MENU);
-
- get_child_and_test_role(comboboxMenu, 0, ATK_ROLE_MENU_ITEM);
- get_child_and_test_role(comboboxMenu, 1, ATK_ROLE_MENU_ITEM);
- get_child_and_test_role(comboboxMenu, 2, ATK_ROLE_MENU_ITEM);
-
- g_object_unref(fixture->obj);
- g_object_unref(comboboxMenu);
-}
-
-/* Form roles */
-static void test_webkit_atk_get_role_form(AtkRolesFixture *fixture, gconstpointer data)
-{
- get_child_and_test_role(fixture->document, 0, ATK_ROLE_FORM);
-}
-
-static void test_webkit_atk_get_role_check_box(AtkRolesFixture* fixture, gconstpointer data)
-{
- // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of.
- fixture->obj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(fixture->obj);
-
- get_child_and_test_role(fixture->obj, 0, ATK_ROLE_CHECK_BOX);
-
- g_object_unref(fixture->obj);
-}
-
-static void test_webkit_atk_get_role_entry(AtkRolesFixture* fixture, gconstpointer data)
-{
- // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of.
- fixture->obj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(fixture->obj);
-
- get_child_and_test_role(fixture->obj, 1, ATK_ROLE_ENTRY);
-
- g_object_unref(fixture->obj);
-}
-
-static void test_webkit_atk_get_role_label(AtkRolesFixture* fixture, gconstpointer data)
-{
- // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of.
- fixture->obj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(fixture->obj);
-
- get_child_and_test_role(fixture->obj, 0, ATK_ROLE_LABEL);
-
- g_object_unref(fixture->obj);
-}
-
-static void test_webkit_atk_get_role_listbox(AtkRolesFixture* fixture, gconstpointer data)
-{
- AtkObject* listboxObj;
- // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of.
- fixture->obj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(fixture->obj);
-
- listboxObj = atk_object_ref_accessible_child(fixture->obj, 0);
- g_assert(listboxObj);
- fixture->role = atk_object_get_role(listboxObj);
- g_assert(fixture->role == ATK_ROLE_LIST);
-
- get_child_and_test_role(listboxObj, 0, ATK_ROLE_LIST_ITEM);
- get_child_and_test_role(listboxObj, 1, ATK_ROLE_LIST_ITEM);
- get_child_and_test_role(listboxObj, 2, ATK_ROLE_LIST_ITEM);
-
- g_object_unref(fixture->obj);
- g_object_unref(listboxObj);
-}
-
-static void test_webkit_atk_get_role_password_text(AtkRolesFixture* fixture, gconstpointer data)
-{
- // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of.
- fixture->obj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(fixture->obj);
-
- get_child_and_test_role(fixture->obj, 0, ATK_ROLE_PASSWORD_TEXT);
-
- g_object_unref(fixture->obj);
-}
-
-static void test_webkit_atk_get_role_push_button(AtkRolesFixture* fixture, gconstpointer data)
-{
- // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of.
- fixture->obj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(fixture->obj);
-
- get_child_and_test_role(fixture->obj, 0, ATK_ROLE_PUSH_BUTTON);
-
- g_object_unref(fixture->obj);
-}
-
-static void test_webkit_atk_get_role_radio_button(AtkRolesFixture* fixture, gconstpointer data)
-{
- // This is an extraneous object of ATK_ROLE_PANEL which we should get rid of.
- fixture->obj = atk_object_ref_accessible_child(fixture->document, 0);
- g_assert(fixture->obj);
-
- get_child_and_test_role(fixture->obj, 0, ATK_ROLE_RADIO_BUTTON);
-
- g_object_unref(fixture->obj);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_document_frame",
- AtkRolesFixture, HTML_DOCUMENT_FRAME,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_document_frame,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_heading",
- AtkRolesFixture, HTML_HEADING,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_heading,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_image",
- AtkRolesFixture, HTML_IMAGE,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_image,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_link",
- AtkRolesFixture, HTML_LINK_TEXT,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_link,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_list_and_item",
- AtkRolesFixture, HTML_LIST,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_list_and_item,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_paragraph",
- AtkRolesFixture, HTML_PARAGRAPH,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_paragraph,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_section",
- AtkRolesFixture, HTML_SECTION,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_section,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_table",
- AtkRolesFixture, HTML_TABLE,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_table,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_separator",
- AtkRolesFixture, HTML_SEPARATOR,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_separator,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_combobox",
- AtkRolesFixture, HTML_COMBOBOX,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_combobox,
- atk_roles_fixture_teardown);
-
- /* Form roles */
- g_test_add("/webkit/atk/test_webkit_atk_get_role_form",
- AtkRolesFixture, HTML_FORM,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_form,
- atk_roles_fixture_teardown);
- g_test_add("/webkit/atk/test_webkit_atk_get_role_check_box",
- AtkRolesFixture, HTML_CHECK_BOX,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_check_box,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_entry",
- AtkRolesFixture, HTML_LABELED_ENTRY,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_entry,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_label",
- AtkRolesFixture, HTML_LABELED_ENTRY,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_label,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_listbox",
- AtkRolesFixture, HTML_LISTBOX,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_listbox,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_password_text",
- AtkRolesFixture, HTML_PASSWORD_TEXT,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_password_text,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_push_button",
- AtkRolesFixture, HTML_PUSH_BUTTON,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_push_button,
- atk_roles_fixture_teardown);
-
- g_test_add("/webkit/atk/test_webkit_atk_get_role_radio_button",
- AtkRolesFixture, HTML_RADIO_BUTTON,
- atk_roles_fixture_setup,
- test_webkit_atk_get_role_radio_button,
- atk_roles_fixture_teardown);
-
- return g_test_run();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testcontextmenu.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testcontextmenu.c
deleted file mode 100644
index bc941a756..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testcontextmenu.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright (C) 2012 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2,1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <webkit/webkit.h>
-
-typedef struct {
- char *data;
- guint flag;
-} TestInfo;
-
-static GMainLoop *loop;
-
-typedef struct {
- WebKitWebView *webView;
- TestInfo *info;
-} ContextMenuFixture;
-
-static TestInfo *testInfoNew(const char *data, guint flag)
-{
- TestInfo *info = g_slice_new(TestInfo);
- info->data = g_strdup(data);
- info->flag = flag;
-
- return info;
-}
-
-static void testInfoDestroy(TestInfo *info)
-{
- g_free(info->data);
- g_slice_free(TestInfo, info);
-}
-
-static void contextMenuFixtureSetup(ContextMenuFixture *fixture, gconstpointer data)
-{
- fixture->webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- loop = g_main_loop_new(NULL, TRUE);
- fixture->info = (TestInfo *)data;
-}
-
-static void contextMenuFixtureTeardown(ContextMenuFixture *fixture, gconstpointer data)
-{
- g_object_unref(fixture->webView);
- g_main_loop_unref(loop);
- testInfoDestroy(fixture->info);
-}
-
-static GList *checkAction(GList *iter, WebKitContextMenuAction action)
-{
- GtkMenuItem *item = (GtkMenuItem *)iter->data;
-
- g_assert(GTK_IS_MENU_ITEM(item));
- g_assert(webkit_context_menu_item_get_action(item) == action);
-
- return iter->next;
-}
-
-static GList *checkActionWithSubmenu(GList *iter, WebKitContextMenuAction action)
-{
- GtkMenuItem *item = (GtkMenuItem *)iter->data;
-
- g_assert(GTK_IS_MENU_ITEM(item));
- g_assert(webkit_context_menu_item_get_action(item) == action);
- g_assert(GTK_IS_MENU(gtk_menu_item_get_submenu(item)));
-
- return iter->next;
-}
-
-static GList *checkSeparator(GList *iter)
-{
- GtkMenuItem *item = (GtkMenuItem *)iter->data;
-
- g_assert(GTK_IS_SEPARATOR_MENU_ITEM(item));
-
- return iter->next;
-}
-
-static gboolean contextMenuCallback(WebKitWebView *webView, GtkWidget *defaultMenu, WebKitHitTestResult *hitTestResult, gboolean keyboardMode, gpointer userData)
-{
- TestInfo *info = (TestInfo *)userData;
- guint context;
- GList *items;
- GList *iter;
-
- /* Check signal parameters */
- g_assert(WEBKIT_IS_WEB_VIEW(webView));
- g_assert(GTK_IS_MENU(defaultMenu));
- g_assert(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult));
- g_assert(!keyboardMode);
-
- g_object_get(hitTestResult, "context", &context, NULL);
- g_assert(context & info->flag);
-
- items = gtk_container_get_children(GTK_CONTAINER(defaultMenu));
- switch (info->flag) {
- case WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT:
- iter = items;
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_GO_BACK);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_STOP);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_RELOAD);
- g_assert(!iter);
-
- break;
- case WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE:
- iter = items;
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_IMAGE_IN_NEW_WINDOW);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_IMAGE_TO_DISK);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_TO_CLIPBOARD);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_IMAGE_URL_TO_CLIPBOARD);
- g_assert(!iter);
-
- break;
- case WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE:
- iter = items;
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_CUT);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_PASTE);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_DELETE);
- iter = checkSeparator(iter);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_SELECT_ALL);
- iter = checkSeparator(iter);
- iter = checkActionWithSubmenu(iter, WEBKIT_CONTEXT_MENU_ACTION_INPUT_METHODS);
- iter = checkActionWithSubmenu(iter, WEBKIT_CONTEXT_MENU_ACTION_UNICODE);
- g_assert(!iter);
-
- break;
- case WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK:
- iter = items;
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_OPEN_LINK_IN_NEW_WINDOW);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_DOWNLOAD_LINK_TO_DISK);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_COPY_LINK_TO_CLIPBOARD);
- g_assert(!iter);
-
- break;
- default:
- g_assert_not_reached();
- }
-
- g_list_free(items);
- g_main_loop_quit(loop);
-
- return TRUE;
-}
-
-static void pushEvent(WebKitWebView *webView)
-{
- GdkEvent *event = gdk_event_new(GDK_BUTTON_PRESS);
-#if GTK_CHECK_VERSION(3, 0, 0)
- GdkDeviceManager *deviceManager;
-#endif
-
- event->any.window = g_object_ref(gtk_widget_get_window(GTK_WIDGET(webView)));
- event->any.send_event = FALSE;
- event->button.time = GDK_CURRENT_TIME;
- event->button.button = 3;
- event->button.x = event->button.y = 5;
- event->button.x_root = event->button.x;
- event->button.y_root = event->button.y;
-#if GTK_CHECK_VERSION(3, 0, 0)
- deviceManager = gdk_display_get_device_manager(gdk_display_get_default());
- event->button.device = gdk_device_manager_get_client_pointer(deviceManager);
-#endif
-
- gdk_event_put(event);
- gdk_event_free(event);
-}
-
-static void loadStatusCallback(WebKitWebView *webView, GParamSpec *spec, gpointer data)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
- TestInfo *info = (TestInfo *)data;
-
- g_assert(status != WEBKIT_LOAD_FAILED);
-
- if (status != WEBKIT_LOAD_FINISHED)
- return;
-
- g_signal_connect(webView, "context-menu", G_CALLBACK(contextMenuCallback), info);
- pushEvent(webView);
-}
-
-static gboolean mapEventCallback(GtkWidget *widget, GdkEvent *event, gpointer data)
-{
- gtk_widget_grab_focus(widget);
- ContextMenuFixture *fixture = (ContextMenuFixture *)data;
- webkit_web_view_load_string(fixture->webView,
- fixture->info->data,
- "text/html",
- "utf-8",
- "file://");
- g_signal_connect(fixture->webView, "notify::load-status", G_CALLBACK(loadStatusCallback), fixture->info);
- return FALSE;
-}
-
-static void testContextMenu(ContextMenuFixture *fixture, gconstpointer data)
-{
- GtkAllocation allocation = { 0, 0, 50, 50 };
- GtkWidget *window = gtk_window_new(GTK_WINDOW_POPUP);
-
- gtk_window_resize(GTK_WINDOW(window), 50, 50);
- gtk_window_move(GTK_WINDOW(window), 0, 0);
- gtk_widget_size_allocate(GTK_WIDGET(fixture->webView), &allocation);
- gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(fixture->webView));
- g_signal_connect(window, "map-event", G_CALLBACK(mapEventCallback), fixture);
- gtk_widget_show_all(window);
-
- g_main_loop_run(loop);
-}
-
-static gboolean contextMenuCustomItemCallback(WebKitWebView *webView, GtkWidget *defaultMenu, WebKitHitTestResult *hitTestResult, gboolean keyboardMode, gpointer userData)
-{
- TestInfo *info = (TestInfo *)userData;
- guint context;
- GList *items;
- GList *iter;
- GtkWidget *menuItem;
- GtkAction *action;
-
- /* Check signal parameters */
- g_assert(WEBKIT_IS_WEB_VIEW(webView));
- g_assert(GTK_IS_MENU(defaultMenu));
- g_assert(WEBKIT_IS_HIT_TEST_RESULT(hitTestResult));
- g_assert(!keyboardMode);
-
- g_object_get(hitTestResult, "context", &context, NULL);
- g_assert(context & info->flag);
-
- action = gtk_action_new("TestAction", "Custom Action", "Custom Action Tooltip", NULL);
- menuItem = gtk_action_create_menu_item(action);
- g_object_unref(action);
-
- gtk_menu_shell_append(GTK_MENU_SHELL(defaultMenu), menuItem);
- gtk_widget_show(menuItem);
-
- items = gtk_container_get_children(GTK_CONTAINER(defaultMenu));
- iter = items;
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_GO_BACK);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_STOP);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_RELOAD);
- iter = checkAction(iter, WEBKIT_CONTEXT_MENU_ACTION_NO_ACTION);
- g_assert(!iter);
-
- g_list_free(items);
- g_main_loop_quit(loop);
-
- return TRUE;
-}
-
-static void testContextMenuCustomItem(ContextMenuFixture *fixture, gconstpointer data)
-{
- GtkWidget *window = gtk_window_new(GTK_WINDOW_POPUP);
- gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(fixture->webView));
- gtk_widget_show_all(window);
- gtk_widget_grab_focus(GTK_WIDGET(fixture->webView));
-
- webkit_web_view_load_string(fixture->webView,
- fixture->info->data,
- "text/html",
- "utf-8",
- "file://");
- g_signal_connect(fixture->webView, "context-menu", G_CALLBACK(contextMenuCustomItemCallback), fixture->info);
- pushEvent(fixture->webView);
-}
-
-int main(int argc, char **argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- // Get rid of runtime warnings about deprecated properties and signals, since they break the tests.
- g_setenv("G_ENABLE_DIAGNOSTIC", "0", TRUE);
-
- g_test_bug_base("https://bugs.webkit.org/");
-
- g_test_add("/webkit/testcontextmenu/document", ContextMenuFixture,
- testInfoNew("<html><body><h1>WebKitGTK+!</h1></body></html>",
- WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT),
- contextMenuFixtureSetup, testContextMenu, contextMenuFixtureTeardown);
- /* We hardcode all elements to be at 0,0 so that we know where to generate the button events */
- g_test_add("/webkit/testcontextmenu/image", ContextMenuFixture,
- testInfoNew("<html><body><img style='position:absolute; left:0; top:0' src='0xdeadbeef' width=50 height=50></img></body></html>",
- WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE),
- contextMenuFixtureSetup, testContextMenu, contextMenuFixtureTeardown);
- g_test_add("/webkit/testcontextmenu/editable", ContextMenuFixture,
- testInfoNew("<html><body><input style='position:absolute; left:0; top:0' size='35'></input>></body></html>",
- WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE),
- contextMenuFixtureSetup, testContextMenu, contextMenuFixtureTeardown);
- g_test_add("/webkit/testcontextmenu/link", ContextMenuFixture,
- testInfoNew("<html><body><a style='position:absolute; left:0; top:0' href='http://www.example.com'>HELLO WORLD</a></body></html>",
- WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK),
- contextMenuFixtureSetup, testContextMenu, contextMenuFixtureTeardown);
- g_test_add("/webkit/testcontextmenu/customitem", ContextMenuFixture,
- testInfoNew("<html><body><h1>WebKitGTK+!</h1></body></html>",
- WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT),
- contextMenuFixtureSetup, testContextMenuCustomItem, contextMenuFixtureTeardown);
-
- return g_test_run();
-}
-
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testcopyandpaste.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testcopyandpaste.c
deleted file mode 100644
index bb38ea66b..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testcopyandpaste.c
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * Copyright (C) 2010 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2,1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <glib/gstdio.h>
-#include <webkit/webkit.h>
-#include <JavaScriptCore/JSStringRef.h>
-#include <JavaScriptCore/JSContextRef.h>
-
-typedef struct {
- char* page;
- char* expectedContent;
-} TestInfo;
-
-typedef struct {
- GtkWidget* window;
- WebKitWebView* webView;
- GMainLoop* loop;
- TestInfo* info;
-} CopyAndPasteFixture;
-
-TestInfo*
-test_info_new(const char* page, const char* expectedContent)
-{
- TestInfo* info;
- info = g_slice_new0(TestInfo);
- info->page = g_strdup(page);
- if (expectedContent)
- info->expectedContent = g_strdup(expectedContent);
- return info;
-}
-
-void
-test_info_destroy(TestInfo* info)
-{
- g_free(info->page);
- g_free(info->expectedContent);
- g_slice_free(TestInfo, info);
-}
-
-static void copy_and_paste_fixture_setup(CopyAndPasteFixture* fixture, gconstpointer data)
-{
- fixture->loop = g_main_loop_new(NULL, TRUE);
-
- fixture->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- fixture->webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
-
- gtk_container_add(GTK_CONTAINER(fixture->window), GTK_WIDGET(fixture->webView));
-}
-
-static void copy_and_paste_fixture_teardown(CopyAndPasteFixture* fixture, gconstpointer data)
-{
- gtk_widget_destroy(fixture->window);
- g_main_loop_unref(fixture->loop);
- test_info_destroy(fixture->info);
-}
-
-static void load_status_cb(WebKitWebView* webView, GParamSpec* spec, gpointer data)
-{
- CopyAndPasteFixture* fixture = (CopyAndPasteFixture*)data;
- WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
- if (status != WEBKIT_LOAD_FINISHED)
- return;
-
- GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
- gtk_clipboard_clear(clipboard);
-
- webkit_web_view_copy_clipboard(webView);
-
- gchar* text = gtk_clipboard_wait_for_text(clipboard);
- g_assert(text || !fixture->info->expectedContent);
- g_assert(!text || !strcmp(text, fixture->info->expectedContent));
- g_free(text);
-
- // Verify that the markup starts with the proper content-type meta tag prefix.
- GtkSelectionData* selectionData = gtk_clipboard_wait_for_contents(clipboard, gdk_atom_intern("text/html", FALSE));
- if (selectionData) {
- static const char* markupPrefix = "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">";
- char* markup = g_strndup((const char*) gtk_selection_data_get_data(selectionData),
- gtk_selection_data_get_length(selectionData));
- g_assert(strlen(markupPrefix) <= strlen(markup));
- g_assert(!strncmp(markupPrefix, markup, strlen(markupPrefix)));
- g_free(markup);
- }
-
- g_assert(!gtk_clipboard_wait_is_uris_available(clipboard));
- g_assert(!gtk_clipboard_wait_is_image_available(clipboard));
-
- g_main_loop_quit(fixture->loop);
-}
-
-gboolean map_event_cb(GtkWidget *widget, GdkEvent* event, gpointer data)
-{
- CopyAndPasteFixture* fixture = (CopyAndPasteFixture*)data;
- webkit_web_view_load_string(fixture->webView, fixture->info->page,
- "text/html", "utf-8", "file://");
- return FALSE;
-}
-
-static void test_copy_and_paste(CopyAndPasteFixture* fixture, gconstpointer data)
-{
- fixture->info = (TestInfo*)data;
- g_signal_connect(fixture->window, "map-event",
- G_CALLBACK(map_event_cb), fixture);
-
- gtk_widget_show(fixture->window);
- gtk_widget_show(GTK_WIDGET(fixture->webView));
- gtk_window_present(GTK_WINDOW(fixture->window));
- gtk_widget_grab_focus(GTK_WIDGET(fixture->webView));
-
- g_signal_connect(fixture->webView, "notify::load-status",
- G_CALLBACK(load_status_cb), fixture);
-
- g_main_loop_run(fixture->loop);
-}
-
-static CopyAndPasteFixture* currentFixture;
-static JSValueRef runPasteTestCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
-{
- gtk_widget_grab_focus(GTK_WIDGET(currentFixture->webView));
-
- // Simulate a paste keyboard sequence.
- GdkEvent* event = gdk_event_new(GDK_KEY_PRESS);
- event->key.keyval = gdk_unicode_to_keyval('v');
- event->key.state = GDK_CONTROL_MASK;
- event->key.window = gtk_widget_get_window(GTK_WIDGET(currentFixture->webView));
- g_object_ref(event->key.window);
-#ifndef GTK_API_VERSION_2
- GdkDeviceManager* manager = gdk_display_get_device_manager(gdk_window_get_display(event->key.window));
- gdk_event_set_device(event, gdk_device_manager_get_client_pointer(manager));
-#endif
-
- GdkKeymapKey* keys;
- gint n_keys;
- if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), event->key.keyval, &keys, &n_keys)) {
- event->key.hardware_keycode = keys[0].keycode;
- g_free(keys);
- }
-
- gtk_main_do_event(event);
- event->key.type = GDK_KEY_RELEASE;
- gtk_main_do_event(event);
- gdk_event_free(event);
-
- JSStringRef scriptString = JSStringCreateWithUTF8CString("document.body.innerHTML;");
- JSValueRef value = JSEvaluateScript(context, scriptString, 0, 0, 0, 0);
- JSStringRelease(scriptString);
-
- g_assert(JSValueIsString(context, value));
- JSStringRef actual = JSValueToStringCopy(context, value, exception);
- g_assert(!exception || !*exception);
- g_assert(currentFixture->info->expectedContent);
- JSStringRef expected = JSStringCreateWithUTF8CString(currentFixture->info->expectedContent);
- g_assert(JSStringIsEqual(expected, actual));
-
- JSStringRelease(expected);
- JSStringRelease(actual);
- g_main_loop_quit(currentFixture->loop);
- return JSValueMakeUndefined(context);
-}
-
-static void window_object_cleared_callback(WebKitWebView* web_view, WebKitWebFrame* web_frame, JSGlobalContextRef context, JSObjectRef window_object, gpointer data)
-{
- JSStringRef name = JSStringCreateWithUTF8CString("runTest");
- JSObjectRef testComplete = JSObjectMakeFunctionWithCallback(context, name, runPasteTestCallback);
- JSObjectSetProperty(context, window_object, name, testComplete, kJSPropertyAttributeNone, 0);
- JSStringRelease(name);
-}
-
-static void pasting_test_get_data_callback(GtkClipboard* clipboard, GtkSelectionData* selection_data, guint info, gpointer data)
-{
- gtk_selection_data_set(selection_data, gdk_atom_intern("text/html", FALSE), 8, (const guchar*) data, strlen((char*)data) + 1);
-}
-
-static void pasting_test_clear_data_callback(GtkClipboard* clipboard, gpointer data)
-{
- g_free(data);
-}
-
-static void test_pasting_markup(CopyAndPasteFixture* fixture, gconstpointer data)
-{
- fixture->info = (TestInfo*)data;
- currentFixture = fixture;
-
- GtkTargetList* targetList = gtk_target_list_new(0, 0);
- gtk_target_list_add(targetList, gdk_atom_intern("text/html", FALSE), 0, 0);
-
- int numberOfTargets = 1;
- GtkTargetEntry* targetTable = gtk_target_table_new_from_list(targetList, &numberOfTargets);
- gtk_clipboard_set_with_data(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
- targetTable, numberOfTargets,
- pasting_test_get_data_callback,
- pasting_test_clear_data_callback,
- g_strdup(fixture->info->expectedContent));
- gtk_target_list_unref(targetList);
- gtk_target_table_free(targetTable, numberOfTargets);
-
- g_signal_connect(fixture->window, "map-event",
- G_CALLBACK(map_event_cb), fixture);
- g_signal_connect(fixture->webView, "window-object-cleared",
- G_CALLBACK(window_object_cleared_callback), fixture);
-
- gtk_widget_show(fixture->window);
- gtk_widget_show(GTK_WIDGET(fixture->webView));
- gtk_window_present(GTK_WINDOW(fixture->window));
-
- g_main_loop_run(fixture->loop);
-}
-
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- const char* selected_span_html = "<html><body>"
- "<span id=\"mainspan\">All work and no play <span>make Jack a dull</span> boy.</span>"
- "<script>document.getSelection().collapse();\n"
- "document.getSelection().selectAllChildren(document.getElementById('mainspan'));\n"
- "</script></body></html>";
- const char* no_selection_html = "<html><body>"
- "<span id=\"mainspan\">All work and no play <span>make Jack a dull</span> boy</span>"
- "<script>document.getSelection().collapse();\n"
- "</script></body></html>";
-
- g_test_add("/webkit/copyandpaste/selection", CopyAndPasteFixture,
- test_info_new(selected_span_html, "All work and no play make Jack a dull boy."),
- copy_and_paste_fixture_setup,
- test_copy_and_paste,
- copy_and_paste_fixture_teardown);
- g_test_add("/webkit/copyandpaste/no-selection", CopyAndPasteFixture,
- test_info_new(no_selection_html, 0),
- copy_and_paste_fixture_setup,
- test_copy_and_paste,
- copy_and_paste_fixture_teardown);
-
- const char* paste_test_html = "<html>"
- "<body onLoad=\"document.body.focus(); runTest();\" contentEditable=\"true\">"
- "</body></html>";
- g_test_add("/webkit/copyandpaste/paste-markup", CopyAndPasteFixture,
- test_info_new(paste_test_html, "bobby"),
- copy_and_paste_fixture_setup,
- test_pasting_markup,
- copy_and_paste_fixture_teardown);
-
- return g_test_run();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdocument.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdocument.c
deleted file mode 100644
index 8e46c030d..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdocument.c
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * Copyright (C) 2010 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "test_utils.h"
-
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-#define HTML_DOCUMENT_TITLE "<html><head><title>This is the title</title></head><body></body></html>"
-#define HTML_DOCUMENT_ELEMENTS "<html><body><ul><li>1</li><li>2</li><li>3</li></ul></body></html>"
-#define HTML_DOCUMENT_ELEMENTS_CLASS "<html><body><div class=\"test\"></div><div class=\"strange\"></div><div class=\"test\"></div></body></html>"
-#define HTML_DOCUMENT_ELEMENTS_ID "<html><body><div id=\"testok\"></div><div id=\"testbad\">first</div><div id=\"testbad\">second</div></body></html>"
-#define HTML_DOCUMENT_LINKS "<html><head><title>Title</title></head><body><a href=\"about:blank\">blank</a><a href=\"http://www.google.com\">google</a><a href=\"http://www.webkit.org\">webkit</a></body></html>"
-#define HTML_DOCUMENT_IFRAME "<html><head><title>IFrame</title></head><body><iframe id='iframe'></iframe><div id='test'></div></body></html>"
-#define HTML_DOCUMENT_TABLE "<html><body><table id=\"table\"></table></body></html>"
-#define HTML_DOCUMENT_EVALUATE "<html><head><title></title></head><body><div>First div</div><div>Second div</div></body></html>"
-
-typedef struct {
- GtkWidget* webView;
- GMainLoop* loop;
-} DomDocumentFixture;
-
-static gboolean finish_loading(DomDocumentFixture* fixture)
-{
- if (g_main_loop_is_running(fixture->loop))
- g_main_loop_quit(fixture->loop);
-
- return FALSE;
-}
-
-static void dom_document_fixture_setup(DomDocumentFixture* fixture, gconstpointer data)
-{
- fixture->loop = g_main_loop_new(NULL, TRUE);
- fixture->webView = webkit_web_view_new();
- g_object_ref_sink(fixture->webView);
-
- if (data != NULL)
- webkit_web_view_load_string(WEBKIT_WEB_VIEW (fixture->webView), (const char*) data, NULL, NULL, NULL);
-
- g_idle_add((GSourceFunc)finish_loading, fixture);
- g_main_loop_run(fixture->loop);
-}
-
-static void dom_document_fixture_teardown(DomDocumentFixture* fixture, gconstpointer data)
-{
- if (fixture->webView)
- g_object_unref(fixture->webView);
- g_main_loop_unref(fixture->loop);
-}
-
-static void test_dom_document_title(DomDocumentFixture* fixture, gconstpointer data)
-{
- g_assert(fixture);
- WebKitWebView* view = (WebKitWebView*)fixture->webView;
- g_assert(view);
- WebKitDOMDocument* document = webkit_web_view_get_dom_document(view);
- g_assert(document);
- gchar* title = webkit_dom_document_get_title(document);
- g_assert(title);
- g_assert_cmpstr(title, ==, "This is the title");
- g_free(title);
- webkit_dom_document_set_title(document, "This is the second title");
- title = webkit_dom_document_get_title(document);
- g_assert(title);
- g_assert_cmpstr(title, ==, "This is the second title");
- g_free(title);
-}
-
-static void test_dom_document_get_elements_by_tag_name(DomDocumentFixture* fixture, gconstpointer data)
-{
- g_assert(fixture);
- WebKitWebView* view = (WebKitWebView*)fixture->webView;
- g_assert(view);
- WebKitDOMDocument* document = webkit_web_view_get_dom_document(view);
- g_assert(document);
- WebKitDOMNodeList* list = webkit_dom_document_get_elements_by_tag_name(document, "li");
- g_assert(list);
- gulong length = webkit_dom_node_list_get_length(list);
- g_assert_cmpint(length, ==, 3);
-
- guint i;
-
- for (i = 0; i < length; i++) {
- WebKitDOMNode* item = webkit_dom_node_list_item(list, i);
- g_assert(item);
- WebKitDOMElement* element = (WebKitDOMElement*)item;
- g_assert(element);
- g_assert_cmpstr(webkit_dom_element_get_tag_name(element), ==, "LI");
- WebKitDOMHTMLElement* htmlElement = (WebKitDOMHTMLElement*)element;
- char* n = g_strdup_printf("%d", i+1);
- g_assert_cmpstr(webkit_dom_html_element_get_inner_text(htmlElement), ==, n);
- g_free(n);
- }
-
- g_object_unref(list);
-}
-
-static void test_dom_document_get_elements_by_class_name(DomDocumentFixture* fixture, gconstpointer data)
-{
- g_assert(fixture);
- WebKitWebView* view = (WebKitWebView*)fixture->webView;
- g_assert(view);
- WebKitDOMDocument* document = webkit_web_view_get_dom_document(view);
- g_assert(document);
- WebKitDOMNodeList* list = webkit_dom_document_get_elements_by_class_name(document, "test");
- g_assert(list);
- gulong length = webkit_dom_node_list_get_length(list);
- g_assert_cmpint(length, ==, 2);
-
- guint i;
-
- for (i = 0; i < length; i++) {
- WebKitDOMNode* item = webkit_dom_node_list_item(list, i);
- g_assert(item);
- WebKitDOMElement* element = (WebKitDOMElement*)item;
- g_assert(element);
- g_assert_cmpstr(webkit_dom_element_get_tag_name(element), ==, "DIV");
- }
-
- g_object_unref(list);
-}
-
-static void test_dom_document_get_element_by_id(DomDocumentFixture* fixture, gconstpointer data)
-{
- g_assert(fixture);
- WebKitWebView* view = (WebKitWebView*)fixture->webView;
- g_assert(view);
- WebKitDOMDocument* document = webkit_web_view_get_dom_document(view);
- g_assert(document);
- WebKitDOMElement* element = webkit_dom_document_get_element_by_id(document, "testok");
- g_assert(element);
- element = webkit_dom_document_get_element_by_id(document, "this-id-does-not-exist");
- g_assert(element == 0);
- /* The DOM spec says the return value is undefined when there's
- * more than one element with the same id; in our case the first
- * one will be returned */
- element = webkit_dom_document_get_element_by_id(document, "testbad");
- g_assert(element);
- WebKitDOMHTMLElement* htmlElement = (WebKitDOMHTMLElement*)element;
- g_assert_cmpstr(webkit_dom_html_element_get_inner_text(htmlElement), ==, "first");
-}
-
-static void test_dom_document_get_links(DomDocumentFixture* fixture, gconstpointer data)
-{
- g_assert(fixture);
- WebKitWebView* view = (WebKitWebView*)fixture->webView;
- g_assert(view);
- WebKitDOMDocument* document = webkit_web_view_get_dom_document(view);
- g_assert(document);
- WebKitDOMHTMLCollection *collection = webkit_dom_document_get_links(document);
- g_assert(collection);
- gulong length = webkit_dom_html_collection_get_length(collection);
- g_assert_cmpint(length, ==, 3);
-
- guint i;
-
- for (i = 0; i < length; i++) {
- static const char* names[] = { "blank", "google", "webkit" };
- static const char* uris[] = { "about:blank", "http://www.google.com/", "http://www.webkit.org/" };
- WebKitDOMNode *node = webkit_dom_html_collection_item(collection, i);
- g_assert(node);
- WebKitDOMElement* element = (WebKitDOMElement*)node;
- g_assert_cmpstr(webkit_dom_element_get_tag_name(element), ==, "A");
- WebKitDOMHTMLElement *htmlElement = (WebKitDOMHTMLElement*)element;
- g_assert_cmpstr(webkit_dom_html_element_get_inner_text(htmlElement), ==, names[i]);
- WebKitDOMHTMLAnchorElement *anchor = (WebKitDOMHTMLAnchorElement*)element;
- g_assert_cmpstr(webkit_dom_html_anchor_element_get_href(anchor), ==, uris[i]);
- }
- g_object_unref(collection);
-}
-
-static void test_dom_document_insert_row(DomDocumentFixture* fixture, gconstpointer data)
-{
- g_assert(fixture);
- WebKitWebView* view = (WebKitWebView*)fixture->webView;
- g_assert(view);
- WebKitDOMDocument* document = webkit_web_view_get_dom_document(view);
- g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
- WebKitDOMElement* table = webkit_dom_document_get_element_by_id(document, "table");
- g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(table));
- WebKitDOMHTMLCollection* rows = webkit_dom_html_table_element_get_rows(WEBKIT_DOM_HTML_TABLE_ELEMENT(table));
- g_assert(WEBKIT_DOM_IS_HTML_COLLECTION(rows));
-
- // Table is initially empty.
- g_assert_cmpint(webkit_dom_html_collection_get_length(rows), ==, 0);
- WebKitDOMHTMLElement* row = webkit_dom_html_table_element_insert_row(WEBKIT_DOM_HTML_TABLE_ELEMENT(table), -1, NULL);
- g_assert(WEBKIT_DOM_IS_HTML_TABLE_ROW_ELEMENT(row));
- rows = webkit_dom_html_table_element_get_rows(WEBKIT_DOM_HTML_TABLE_ELEMENT(table));
- g_assert(WEBKIT_DOM_IS_HTML_COLLECTION(rows));
- g_assert_cmpint(webkit_dom_html_collection_get_length(rows), ==, 1);
-}
-
-static void test_dom_document_evaluate(DomDocumentFixture* fixture, gconstpointer data)
-{
- g_assert(fixture);
- WebKitWebView* view = (WebKitWebView*)fixture->webView;
- g_assert(view);
- WebKitDOMDocument* document = webkit_web_view_get_dom_document(view);
- g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
- WebKitDOMNodeList* list = webkit_dom_document_get_elements_by_tag_name(document, "html");
- g_assert(list);
- gulong length = webkit_dom_node_list_get_length(list);
- g_assert_cmpint(length, ==, 1);
- WebKitDOMNode* html = webkit_dom_node_list_item(list, 0);
- g_assert(WEBKIT_DOM_IS_NODE(html));
-
- WebKitDOMXPathResult* result = webkit_dom_document_evaluate(document, "//div", html, NULL, 0, NULL, NULL);
- g_assert(WEBKIT_DOM_IS_XPATH_RESULT(result));
-
- int i = 0;
- WebKitDOMNode* node;
- while ( (node = webkit_dom_xpath_result_iterate_next(result, NULL)) != NULL) {
- g_assert(node);
- WebKitDOMElement* element = (WebKitDOMElement*)node;
- g_assert_cmpstr(webkit_dom_element_get_tag_name(element), ==, "DIV");
- i++;
- }
- g_assert_cmpint(i, ==, 2);
-
- g_object_unref(list);
-}
-
-static void weak_notify(gpointer data, GObject* zombie)
-{
- guint* count = (guint*)data;
- (*count)++;
-}
-
-static void test_dom_document_garbage_collection(DomDocumentFixture* fixture, gconstpointer data)
-{
- guint count = 0;
- g_assert(fixture);
- WebKitWebView* view = (WebKitWebView*)fixture->webView;
- g_assert(view);
- WebKitDOMDocument* document = webkit_web_view_get_dom_document(view);
- g_assert(document);
- g_object_weak_ref(G_OBJECT(document), (GWeakNotify)weak_notify, &count);
- WebKitDOMHTMLHeadElement* head = webkit_dom_document_get_head(document);
- g_assert(head);
- g_object_weak_ref(G_OBJECT(head), (GWeakNotify)weak_notify, &count);
- WebKitDOMHTMLElement* body = webkit_dom_document_get_body(document);
- g_assert(body);
- g_object_weak_ref(G_OBJECT(body), (GWeakNotify)weak_notify, &count);
- WebKitDOMHTMLCollection *collection = webkit_dom_document_get_links(document);
- g_assert(collection);
- g_object_weak_ref(G_OBJECT(collection), (GWeakNotify)weak_notify, &count);
-
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(view), HTML_DOCUMENT_LINKS, NULL, NULL, NULL);
-
- while (g_main_context_pending(NULL))
- g_main_context_iteration(NULL, FALSE);
-
- g_assert_cmpuint(count, ==, 3);
-
- g_object_unref(collection);
- g_assert_cmpuint(count, ==, 4);
-
- count = 0;
-
- document = webkit_web_view_get_dom_document(view);
- g_assert(document);
- g_object_weak_ref(G_OBJECT(document), (GWeakNotify)weak_notify, &count);
- head = webkit_dom_document_get_head(document);
- g_assert(head);
- g_object_weak_ref(G_OBJECT(head), (GWeakNotify)weak_notify, &count);
- body = webkit_dom_document_get_body(document);
- g_assert(body);
- g_object_weak_ref(G_OBJECT(body), (GWeakNotify)weak_notify, &count);
- collection = webkit_dom_document_get_links(document);
- g_assert(collection);
- g_object_weak_ref(G_OBJECT(collection), (GWeakNotify)weak_notify, &count);
- /* Ask twice for the same object */
- WebKitDOMHTMLCollection* collection2 = webkit_dom_document_get_links(document);
- g_assert(collection2);
- g_object_weak_ref(G_OBJECT(collection2), (GWeakNotify)weak_notify, &count);
-
- g_object_unref(document);
- g_object_unref(head);
- g_object_unref(body);
- g_object_unref(collection);
- g_object_unref(collection2);
-
- g_assert_cmpuint(count, ==, 5);
-
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(view), HTML_DOCUMENT_IFRAME, NULL, NULL, NULL);
-
- while (g_main_context_pending(NULL))
- g_main_context_iteration(NULL, FALSE);
-
- count = 0;
-
- document = webkit_web_view_get_dom_document(view);
- body = webkit_dom_document_get_body(document);
- WebKitDOMElement* p = webkit_dom_document_create_element(document, "P", NULL);
- webkit_dom_node_append_child(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(p), NULL);
- g_object_weak_ref(G_OBJECT(p), (GWeakNotify)weak_notify, &count);
- /* This is wrong, p is transfer none and owned by the cache, but we shouldn't crash in that case. */
- g_object_unref(p);
-
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(view), HTML_DOCUMENT_IFRAME, NULL, NULL, NULL);
-
- while (g_main_context_pending(NULL))
- g_main_context_iteration(NULL, FALSE);
-
- g_assert_cmpuint(count, ==, 1);
-
- count = 0;
-
- document = webkit_web_view_get_dom_document(view);
- WebKitDOMElement* div = webkit_dom_document_get_element_by_id(document, "test");
- g_assert(div);
- g_object_weak_ref(G_OBJECT(div), (GWeakNotify)weak_notify, &count);
- WebKitDOMElement* iframe = webkit_dom_document_get_element_by_id(document, "iframe");
- g_assert(iframe);
-
- webkit_dom_element_set_attribute(iframe, "src", "data:<html><head></head></html>", NULL);
-
- while (g_main_context_pending(NULL))
- g_main_context_iteration(NULL, FALSE);
-
- WebKitDOMDocument* iframeDocument = webkit_dom_html_iframe_element_get_content_document(WEBKIT_DOM_HTML_IFRAME_ELEMENT(iframe));
- g_assert(iframeDocument);
- head = webkit_dom_document_get_head(iframeDocument);
- g_assert(head);
- g_object_weak_ref(G_OBJECT(head), (GWeakNotify)weak_notify, &count);
-
- webkit_dom_element_set_attribute(iframe, "src", "about:blank", NULL);
-
- while (g_main_context_pending(NULL))
- g_main_context_iteration(NULL, FALSE);
-
- g_assert_cmpuint(count, ==, 1);
-
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(view), HTML_DOCUMENT_LINKS, NULL, NULL, NULL);
-
- while (g_main_context_pending(NULL))
- g_main_context_iteration(NULL, FALSE);
-
- g_assert_cmpuint(count, ==, 2);
-
- count = 0;
-
- document = webkit_web_view_get_dom_document(view);
- g_assert(document);
- g_object_weak_ref(G_OBJECT(document), (GWeakNotify)weak_notify, &count);
- /* Ask twice for the Document */
- WebKitDOMDocument* document2 = webkit_web_view_get_dom_document(view);
- g_assert(document2);
- g_object_weak_ref(G_OBJECT(document2), (GWeakNotify)weak_notify, &count);
- head = webkit_dom_document_get_head(document);
- g_assert(head);
- g_object_weak_ref(G_OBJECT(head), (GWeakNotify)weak_notify, &count);
- body = webkit_dom_document_get_body(document);
- g_assert(body);
- g_object_weak_ref(G_OBJECT(body), (GWeakNotify)weak_notify, &count);
- collection = webkit_dom_document_get_links(document);
- g_assert(collection);
- g_object_weak_ref(G_OBJECT(collection), (GWeakNotify)weak_notify, &count);
-
- gtk_widget_destroy(fixture->webView);
- fixture->webView = NULL;
-
- g_assert_cmpuint(count, ==, 4);
-
- g_object_unref(collection);
-
- g_assert_cmpuint(count, ==, 5);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
-
- g_test_add("/webkit/domdocument/test_title",
- DomDocumentFixture, HTML_DOCUMENT_TITLE,
- dom_document_fixture_setup,
- test_dom_document_title,
- dom_document_fixture_teardown);
-
- g_test_add("/webkit/domdocument/test_get_elements_by_tag_name",
- DomDocumentFixture, HTML_DOCUMENT_ELEMENTS,
- dom_document_fixture_setup,
- test_dom_document_get_elements_by_tag_name,
- dom_document_fixture_teardown);
-
- g_test_add("/webkit/domdocument/test_get_elements_by_class_name",
- DomDocumentFixture, HTML_DOCUMENT_ELEMENTS_CLASS,
- dom_document_fixture_setup,
- test_dom_document_get_elements_by_class_name,
- dom_document_fixture_teardown);
-
- g_test_add("/webkit/domdocument/test_get_element_by_id",
- DomDocumentFixture, HTML_DOCUMENT_ELEMENTS_ID,
- dom_document_fixture_setup,
- test_dom_document_get_element_by_id,
- dom_document_fixture_teardown);
-
- g_test_add("/webkit/domdocument/test_get_links",
- DomDocumentFixture, HTML_DOCUMENT_LINKS,
- dom_document_fixture_setup,
- test_dom_document_get_links,
- dom_document_fixture_teardown);
-
- g_test_add("/webkit/domdocument/test_table_insert_row",
- DomDocumentFixture, HTML_DOCUMENT_TABLE,
- dom_document_fixture_setup,
- test_dom_document_insert_row,
- dom_document_fixture_teardown);
-
- g_test_add("/webkit/domdocument/test_document_evaluate",
- DomDocumentFixture, HTML_DOCUMENT_EVALUATE,
- dom_document_fixture_setup,
- test_dom_document_evaluate,
- dom_document_fixture_teardown);
-
- g_test_add("/webkit/domdocument/test_garbage_collection",
- DomDocumentFixture, HTML_DOCUMENT_LINKS,
- dom_document_fixture_setup,
- test_dom_document_garbage_collection,
- dom_document_fixture_teardown);
-
- return g_test_run();
-}
-
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdomwindow.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdomwindow.c
deleted file mode 100644
index 14fcd186a..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdomwindow.c
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (C) 2010 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "test_utils.h"
-
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-#define HTML_DOCUMENT "<html><head><title></title></head><style type='text/css'>#test { font-size: 16px; }</style><body><p id='test'>test</p></body></html>"
-
-typedef struct {
- GtkWidget* webView;
- GtkWidget* window;
- WebKitDOMDOMWindow* domWindow;
- GMainLoop* loop;
-
- gboolean loaded;
- gboolean clicked;
- gconstpointer data;
-} DomDomviewFixture;
-
-static gboolean finish_loading(DomDomviewFixture* fixture)
-{
- if (g_main_loop_is_running(fixture->loop))
- g_main_loop_quit(fixture->loop);
-
- return FALSE;
-}
-
-static void dom_domview_fixture_setup(DomDomviewFixture* fixture, gconstpointer data)
-{
- fixture->loop = g_main_loop_new(NULL, TRUE);
- fixture->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- fixture->webView = webkit_web_view_new();
- fixture->data = data;
-
- gtk_container_add(GTK_CONTAINER(fixture->window), GTK_WIDGET(fixture->webView));
-}
-
-static void dom_domview_fixture_teardown(DomDomviewFixture* fixture, gconstpointer data)
-{
- gtk_widget_destroy(fixture->window);
- g_main_loop_unref(fixture->loop);
-}
-
-static void dom_dom_window_fixture_setup(DomDomviewFixture* fixture, gconstpointer data)
-{
- fixture->loop = g_main_loop_new(NULL, TRUE);
- fixture->webView = webkit_web_view_new();
- g_object_ref_sink(fixture->webView);
-
- if (data != NULL)
- webkit_web_view_load_string(WEBKIT_WEB_VIEW (fixture->webView), (const char*) data, NULL, NULL, NULL);
-
- g_idle_add((GSourceFunc)finish_loading, fixture);
- g_main_loop_run(fixture->loop);
-}
-
-static void dom_dom_window_fixture_teardown(DomDomviewFixture* fixture, gconstpointer data)
-{
- if (fixture->webView)
- g_object_unref(fixture->webView);
- g_main_loop_unref(fixture->loop);
-}
-
-static gboolean loadedCallback(WebKitDOMDOMWindow* view, WebKitDOMEvent* event, DomDomviewFixture* fixture)
-{
- g_assert(fixture->loaded == FALSE);
- fixture->loaded = TRUE;
-
- return FALSE;
-}
-
-static gboolean clickedCallback(WebKitDOMDOMWindow* view, WebKitDOMEvent* event, DomDomviewFixture* fixture)
-{
- WebKitDOMEventTarget* target;
- gushort phase;
-
- g_assert(event);
- g_assert(WEBKIT_DOM_IS_EVENT(event));
-
- // We should catch this in the bubbling up phase, since we are connecting to the toplevel object
- phase = webkit_dom_event_get_event_phase(event);
- g_assert_cmpint(phase, ==, 3);
-
- target = webkit_dom_event_get_current_target(event);
- g_assert(target == WEBKIT_DOM_EVENT_TARGET(view));
-
- g_assert(fixture->clicked == FALSE);
- fixture->clicked = TRUE;
-
- finish_loading(fixture);
-
- return FALSE;
-}
-
-gboolean map_event_cb(GtkWidget *widget, GdkEvent* event, DomDomviewFixture* fixture)
-{
- webkit_web_view_load_string(WEBKIT_WEB_VIEW (fixture->webView), (const char*)fixture->data, NULL, NULL, NULL);
-
- return FALSE;
-}
-
-static void load_event_callback(WebKitWebView* webView, GParamSpec* spec, DomDomviewFixture* fixture)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
- if (status == WEBKIT_LOAD_FINISHED) {
- webkit_dom_event_target_add_event_listener(WEBKIT_DOM_EVENT_TARGET(fixture->domWindow), "click", G_CALLBACK(clickedCallback), false, fixture);
-
- g_assert(fixture->clicked == FALSE);
- gtk_test_widget_click(GTK_WIDGET(fixture->webView), 1, 0);
- }
-
-}
-
-static void test_dom_domview_signals(DomDomviewFixture* fixture, gconstpointer data)
-{
- g_assert(fixture);
- WebKitWebView* view = (WebKitWebView*)fixture->webView;
- g_assert(view);
- WebKitDOMDocument* document = webkit_web_view_get_dom_document(view);
- g_assert(document);
- WebKitDOMDOMWindow* domWindow = webkit_dom_document_get_default_view(document);
- g_assert(domWindow);
-
- fixture->domWindow = domWindow;
-
- webkit_dom_event_target_add_event_listener(WEBKIT_DOM_EVENT_TARGET(fixture->domWindow), "load", G_CALLBACK(loadedCallback), false, fixture);
- g_signal_connect(fixture->window, "map-event", G_CALLBACK(map_event_cb), fixture);
- g_signal_connect(fixture->webView, "notify::load-status", G_CALLBACK(load_event_callback), fixture);
-
- gtk_widget_show_all(fixture->window);
- gtk_window_present(GTK_WINDOW(fixture->window));
-
- g_main_loop_run(fixture->loop);
-
- g_assert(fixture->loaded);
- g_assert(fixture->clicked);
-}
-
-static gboolean
-clicked_cb(WebKitDOMEventTarget* target, WebKitDOMEvent* event, DomDomviewFixture* fixture)
-{
- g_assert(fixture->clicked == FALSE);
- fixture->clicked = TRUE;
- finish_loading(fixture);
- return FALSE;
-}
-
-static void load_status_callback(WebKitWebView* webView, GParamSpec* spec, DomDomviewFixture* fixture)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
- if (status == WEBKIT_LOAD_FINISHED) {
- WebKitDOMDocument* document;
- WebKitDOMDOMWindow* domWindow;
- WebKitDOMElement* element;
- WebKitDOMEvent* event;
- glong clientX, clientY;
-
- document = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(fixture->webView));
- g_assert(document);
- domWindow = webkit_dom_document_get_default_view(document);
- g_assert(domWindow);
- fixture->domWindow = domWindow;
-
- element = webkit_dom_document_get_element_by_id(document, "test");
- g_assert(element);
- event = webkit_dom_document_create_event(document, "MouseEvent", NULL);
- g_assert(event);
- g_assert(WEBKIT_DOM_IS_EVENT(event));
- g_assert(WEBKIT_DOM_IS_MOUSE_EVENT(event));
- clientX = webkit_dom_element_get_client_left(element);
- clientY = webkit_dom_element_get_client_top(element);
- webkit_dom_mouse_event_init_mouse_event(WEBKIT_DOM_MOUSE_EVENT(event),
- "click", TRUE, TRUE,
- fixture->domWindow, 0, 0, 0, clientX, clientY,
- FALSE, FALSE, FALSE, FALSE,
- 1, WEBKIT_DOM_EVENT_TARGET(element));
- webkit_dom_event_target_add_event_listener(WEBKIT_DOM_EVENT_TARGET(element), "click", G_CALLBACK(clicked_cb), false, fixture);
- g_assert(fixture->clicked == FALSE);
- webkit_dom_event_target_dispatch_event(WEBKIT_DOM_EVENT_TARGET(element), event, NULL);
- }
-
-}
-
-static void test_dom_domview_dispatch_event(DomDomviewFixture* fixture, gconstpointer data)
-{
- g_signal_connect(fixture->window, "map-event", G_CALLBACK(map_event_cb), fixture);
- g_signal_connect(fixture->webView, "notify::load-status", G_CALLBACK(load_status_callback), fixture);
-
- gtk_widget_show_all(fixture->window);
- gtk_window_present(GTK_WINDOW(fixture->window));
-
- g_main_loop_run (fixture->loop);
- g_assert(fixture->clicked);
-}
-
-static void test_dom_dom_window_get_computed_style(DomDomviewFixture* fixture, gconstpointer data)
-{
- WebKitDOMDocument* document = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(fixture->webView));
- g_assert(document);
- WebKitDOMDOMWindow* domWindow = webkit_dom_document_get_default_view(document);
- g_assert(domWindow);
-
- WebKitDOMElement* element = webkit_dom_document_get_element_by_id(document, "test");
- g_assert(element);
- g_assert(WEBKIT_DOM_IS_ELEMENT(element));
- WebKitDOMCSSStyleDeclaration* cssStyle = webkit_dom_dom_window_get_computed_style(domWindow, element, NULL);
- gchar* fontSize = webkit_dom_css_style_declaration_get_property_value(cssStyle, "font-size");
- g_assert_cmpstr(fontSize, ==, "16px");
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
-
- g_test_add("/webkit/domdomview/signals",
- DomDomviewFixture, HTML_DOCUMENT,
- dom_domview_fixture_setup,
- test_dom_domview_signals,
- dom_domview_fixture_teardown);
-
- g_test_add("/webkit/domdomview/dispatch_event",
- DomDomviewFixture, HTML_DOCUMENT,
- dom_domview_fixture_setup,
- test_dom_domview_dispatch_event,
- dom_domview_fixture_teardown);
-
- g_test_add("/webkit/domdomwindow/get_computed_style",
- DomDomviewFixture, HTML_DOCUMENT,
- dom_dom_window_fixture_setup,
- test_dom_dom_window_get_computed_style,
- dom_dom_window_fixture_teardown);
-
- return g_test_run();
-}
-
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testdomnode.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testdomnode.c
deleted file mode 100644
index ed4bcbdaa..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testdomnode.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (C) 2010 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "test_utils.h"
-
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-#define HTML_DOCUMENT_HIERARCHY_NAVIGATION "<html><head><title>This is the title</title></head><body><p>1</p><p>2</p><p>3</p></body></html>"
-#define HTML_DOCUMENT_NODE_INSERTION "<html><body></body></html>"
-
-typedef struct {
- GtkWidget* webView;
- GMainLoop* loop;
-} DomNodeFixture;
-
-static gboolean finish_loading(DomNodeFixture* fixture)
-{
- if (g_main_loop_is_running(fixture->loop))
- g_main_loop_quit(fixture->loop);
-
- return FALSE;
-}
-
-static void dom_node_fixture_setup(DomNodeFixture* fixture, gconstpointer data)
-{
- fixture->loop = g_main_loop_new(NULL, TRUE);
- fixture->webView = webkit_web_view_new();
- g_object_ref_sink(fixture->webView);
-
- if (data != NULL)
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(fixture->webView), (const char*)data, NULL, NULL, NULL);
-
- g_idle_add((GSourceFunc)finish_loading, fixture);
- g_main_loop_run(fixture->loop);
-}
-
-static void dom_node_fixture_teardown(DomNodeFixture* fixture, gconstpointer data)
-{
- g_object_unref(fixture->webView);
- g_main_loop_unref(fixture->loop);
-}
-
-static void test_dom_node_hierarchy_navigation(DomNodeFixture* fixture, gconstpointer data)
-{
- WebKitDOMDocument* document;
- WebKitDOMHTMLHeadElement* head;
- WebKitDOMHTMLBodyElement* body;
- WebKitDOMNodeList* list;
- WebKitDOMNode* ptr;
- gulong i, length;
-
- document = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(fixture->webView));
- g_assert(document);
- g_assert(WEBKIT_DOM_IS_DOCUMENT(document));
- head = webkit_dom_document_get_head(document);
- g_assert(head);
- g_assert(WEBKIT_DOM_IS_HTML_HEAD_ELEMENT(head));
-
- /* Title, head's child */
- g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(head)));
- list = webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(head));
- g_assert_cmpint(webkit_dom_node_list_get_length(list), ==, 1);
- ptr = webkit_dom_node_list_item(list, 0);
- g_assert(ptr);
- g_assert(WEBKIT_DOM_IS_HTML_TITLE_ELEMENT(ptr));
- g_object_unref(list);
-
- /* Body, Head sibling */
- ptr = webkit_dom_node_get_next_sibling(WEBKIT_DOM_NODE(head));
- g_assert(ptr);
- body = WEBKIT_DOM_HTML_BODY_ELEMENT(ptr);
- g_assert(WEBKIT_DOM_IS_HTML_BODY_ELEMENT(body));
-
- /* There is no third sibling */
- ptr = webkit_dom_node_get_next_sibling(ptr);
- g_assert(ptr == NULL);
-
- /* Body's previous sibling is Head */
- ptr = webkit_dom_node_get_previous_sibling(WEBKIT_DOM_NODE(body));
- g_assert(ptr);
- g_assert(WEBKIT_DOM_IS_HTML_HEAD_ELEMENT(ptr));
-
- /* Body has 3 children */
- g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
- list = webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body));
- length = webkit_dom_node_list_get_length(list);
- g_assert_cmpint(length, ==, 3);
-
- /* The three of them are P tags */
- for (i = 0; i < length; i++) {
- ptr = webkit_dom_node_list_item(list, i);
- g_assert(ptr);
- g_assert(WEBKIT_DOM_IS_HTML_PARAGRAPH_ELEMENT(ptr));
- }
-
- /* Go backwards */
- for (i = 0; ptr; ptr = webkit_dom_node_get_previous_sibling(ptr), i++)
- /* Nothing */;
-
- g_assert_cmpint(i, ==, 3);
- g_object_unref(list);
-}
-
-static void test_dom_node_insertion(DomNodeFixture* fixture, gconstpointer data)
-{
- WebKitDOMDocument* document;
- WebKitDOMHTMLElement* body;
- WebKitDOMElement* p, *div;
- WebKitDOMNodeList* list;
- WebKitDOMNode* node;
-
- document = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(fixture->webView));
- g_assert(document);
- body = webkit_dom_document_get_body(document);
- g_assert(body);
- g_assert(WEBKIT_DOM_IS_HTML_ELEMENT(body));
-
- /* Body shouldn't have any children at this point */
- g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)) == FALSE);
-
- /* Insert one P element */
- p = webkit_dom_document_create_element(document, "P", NULL);
- webkit_dom_node_append_child(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(p), NULL);
-
- /* Now it should have one, the same that we inserted */
- g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
- list = webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body));
- g_assert_cmpint(webkit_dom_node_list_get_length(list), ==, 1);
- node = webkit_dom_node_list_item(list, 0);
- g_assert(node);
- g_assert(webkit_dom_node_is_same_node(WEBKIT_DOM_NODE(p), node));
- g_object_unref(list);
-
- /* Replace the P tag with a DIV tag */
- div = webkit_dom_document_create_element(document, "DIV", NULL);
- webkit_dom_node_replace_child(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(div), WEBKIT_DOM_NODE(p), NULL);
- g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
- list = webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body));
- g_assert_cmpint(webkit_dom_node_list_get_length(list), ==, 1);
- node = webkit_dom_node_list_item(list, 0);
- g_assert(node);
- g_assert(webkit_dom_node_is_same_node(WEBKIT_DOM_NODE(div), node));
- g_object_unref(list);
-
- /* Now remove the tag */
- webkit_dom_node_remove_child(WEBKIT_DOM_NODE(body), node, NULL);
- list = webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body));
- g_assert_cmpint(webkit_dom_node_list_get_length(list), ==, 0);
- g_object_unref(list);
-
- /* Test insert_before */
-
- /* If refChild is null, insert newChild as last element of parent */
- div = webkit_dom_document_create_element(document, "DIV", NULL);
- webkit_dom_node_insert_before(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(div), NULL, NULL);
- g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
- list = webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body));
- g_assert_cmpint(webkit_dom_node_list_get_length(list), ==, 1);
- node = webkit_dom_node_list_item(list, 0);
- g_assert(node);
- g_assert(webkit_dom_node_is_same_node(WEBKIT_DOM_NODE(div), node));
- g_object_unref(list);
-
- /* Now insert a 'p' before 'div' */
- p = webkit_dom_document_create_element(document, "P", NULL);
- webkit_dom_node_insert_before(WEBKIT_DOM_NODE(body), WEBKIT_DOM_NODE(p), WEBKIT_DOM_NODE(div), NULL);
- g_assert(webkit_dom_node_has_child_nodes(WEBKIT_DOM_NODE(body)));
- list = webkit_dom_node_get_child_nodes(WEBKIT_DOM_NODE(body));
- g_assert_cmpint(webkit_dom_node_list_get_length(list), ==, 2);
- node = webkit_dom_node_list_item(list, 0);
- g_assert(node);
- g_assert(webkit_dom_node_is_same_node(WEBKIT_DOM_NODE(p), node));
- node = webkit_dom_node_list_item(list, 1);
- g_assert(node);
- g_assert(webkit_dom_node_is_same_node(WEBKIT_DOM_NODE(div), node));
- g_object_unref(list);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
-
- g_test_add("/webkit/domnode/test_hierarchy_navigation",
- DomNodeFixture, HTML_DOCUMENT_HIERARCHY_NAVIGATION,
- dom_node_fixture_setup,
- test_dom_node_hierarchy_navigation,
- dom_node_fixture_teardown);
-
- g_test_add("/webkit/domnode/test_insertion",
- DomNodeFixture, HTML_DOCUMENT_NODE_INSERTION,
- dom_node_fixture_setup,
- test_dom_node_insertion,
- dom_node_fixture_teardown);
-
- return g_test_run();
-}
-
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testdownload.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testdownload.c
deleted file mode 100644
index e34d63230..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testdownload.c
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (C) 2009 Christian Dywan <christian@twotoasts.de>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2,1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <unistd.h>
-#include <glib/gstdio.h>
-#include <webkit/webkit.h>
-
-GMainLoop* loop;
-char* temporaryFilename = NULL;
-WebKitDownload* theDownload = NULL;
-
-static void
-test_webkit_download_create(void)
-{
- WebKitNetworkRequest* request;
- WebKitDownload* download;
- const gchar* uri = "http://example.com";
- gchar* tmpDir;
-
- request = webkit_network_request_new(uri);
- download = webkit_download_new(request);
- g_object_unref(request);
- g_assert_cmpstr(webkit_download_get_uri(download), ==, uri);
- g_assert(webkit_download_get_network_request(download) == request);
- g_assert(g_strrstr(uri, webkit_download_get_suggested_filename(download)));
- g_assert(webkit_download_get_status(download) == WEBKIT_DOWNLOAD_STATUS_CREATED);
- g_assert(!webkit_download_get_total_size(download));
- g_assert(!webkit_download_get_current_size(download));
- g_assert(!webkit_download_get_progress(download));
- g_assert(!webkit_download_get_elapsed_time(download));
- tmpDir = g_filename_to_uri(g_get_tmp_dir(), NULL, NULL);
- webkit_download_set_destination_uri(download, tmpDir);
- g_assert_cmpstr(tmpDir, ==, webkit_download_get_destination_uri(download));;
- g_free(tmpDir);
- g_object_unref(download);
-}
-
-static gboolean
-navigation_policy_decision_requested_cb(WebKitWebView* web_view,
- WebKitWebFrame* web_frame,
- WebKitNetworkRequest* request,
- WebKitWebNavigationAction* action,
- WebKitWebPolicyDecision* decision,
- gpointer data)
-{
- webkit_web_policy_decision_download(decision);
- return TRUE;
-}
-
-static void
-notify_status_cb(GObject* object, GParamSpec* pspec, gpointer data)
-{
- WebKitDownload* download = WEBKIT_DOWNLOAD(object);
- switch (webkit_download_get_status(download)) {
- case WEBKIT_DOWNLOAD_STATUS_FINISHED:
- case WEBKIT_DOWNLOAD_STATUS_ERROR:
- g_main_loop_quit(loop);
- break;
- case WEBKIT_DOWNLOAD_STATUS_CANCELLED:
- g_assert_not_reached();
- break;
- default:
- break;
- }
-}
-
-static gboolean
-set_filename(gchar* filename)
-{
- gchar *uri = g_filename_to_uri(filename, NULL, NULL);
-
- webkit_download_set_destination_uri(theDownload, uri);
- g_free(uri);
-
- webkit_download_start(theDownload);
- return FALSE;
-}
-
-static void
-handle_download_requested_cb(WebKitDownload* download,
- gboolean* beenThere,
- gboolean asynch)
-{
- theDownload = download;
- *beenThere = TRUE;
-
- if (temporaryFilename) {
- if (asynch) {
- g_idle_add((GSourceFunc)set_filename, temporaryFilename);
- } else {
- gchar *uri = g_filename_to_uri(temporaryFilename, NULL, NULL);
- if (uri)
- webkit_download_set_destination_uri(download, uri);
- g_free(uri);
- }
- }
-
- g_signal_connect(download, "notify::status",
- G_CALLBACK(notify_status_cb), NULL);
-}
-
-static gboolean
-download_requested_cb(WebKitWebView* web_view,
- WebKitDownload* download,
- gboolean* beenThere)
-{
- handle_download_requested_cb(download, beenThere, FALSE);
- return TRUE;
-}
-
-static gboolean
-download_requested_asynch_cb(WebKitWebView* web_view,
- WebKitDownload* download,
- gboolean* beenThere)
-{
- handle_download_requested_cb(download, beenThere, TRUE);
- return TRUE;
-}
-
-static void
-test_webkit_download_perform(gboolean asynch)
-{
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- GCallback downloadRequestCallback = NULL;
-
- g_object_ref_sink(G_OBJECT(webView));
-
- g_signal_connect(webView, "navigation-policy-decision-requested",
- G_CALLBACK(navigation_policy_decision_requested_cb),
- NULL);
-
- if (asynch)
- downloadRequestCallback = G_CALLBACK(download_requested_asynch_cb);
- else
- downloadRequestCallback = G_CALLBACK(download_requested_cb);
-
- gboolean beenThere = FALSE;
- g_signal_connect(webView, "download-requested",
- downloadRequestCallback, &beenThere);
-
- /* Preparation; FIXME: we should move this code to a test
- * utilities file, because we have a very similar one in
- * testwebframe.c */
- GError *error = NULL;
- gchar* filename;
- int fd = g_file_open_tmp("webkit-testwebdownload-XXXXXX", &filename, &error);
- close(fd);
-
- if (error)
- g_critical("Failed to open a temporary file for writing: %s.", error->message);
-
- if (g_unlink(filename) == -1)
- g_critical("Failed to delete the temporary file: %s.", g_strerror(errno));
-
- theDownload = NULL;
- temporaryFilename = filename;
-
- loop = g_main_loop_new(NULL, TRUE);
- webkit_web_view_load_uri(webView, "http://gnome.org/");
- g_main_loop_run(loop);
-
- g_assert_cmpint(beenThere, ==, TRUE);
-
- g_assert_cmpint(g_file_test(temporaryFilename, G_FILE_TEST_IS_REGULAR), ==, TRUE);
-
- g_unlink(temporaryFilename);
- g_free(temporaryFilename);
- temporaryFilename = NULL;
-
- g_main_loop_unref(loop);
- g_object_unref(webView);
-}
-
-static void
-test_webkit_download_synch(void)
-{
- test_webkit_download_perform(FALSE);
-}
-
-static void
-test_webkit_download_asynch(void)
-{
- test_webkit_download_perform(TRUE);
-}
-
-static gboolean mime_type_policy_decision_requested_cb(WebKitWebView* view, WebKitWebFrame* frame,
- WebKitNetworkRequest* request, const char* mime_type,
- WebKitWebPolicyDecision* decision, gpointer data)
-{
- webkit_web_policy_decision_download(decision);
- return TRUE;
-}
-
-static void idle_quit_loop_cb(WebKitWebView* web_view, GParamSpec* pspec, gpointer data)
-{
- if (webkit_web_view_get_load_status(web_view) == WEBKIT_LOAD_FINISHED ||
- webkit_web_view_get_load_status(web_view) == WEBKIT_LOAD_FAILED)
- g_main_loop_quit(loop);
-}
-
-static void
-test_webkit_download_data(void)
-{
- gboolean beenThere = FALSE;
- WebKitWebView* webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
-
- g_signal_connect(webView, "download-requested",
- G_CALLBACK(download_requested_cb),
- &beenThere);
-
- g_signal_connect(webView, "notify::load-status",
- G_CALLBACK(idle_quit_loop_cb),
- NULL);
-
- g_signal_connect(webView, "mime-type-policy-decision-requested",
- G_CALLBACK(mime_type_policy_decision_requested_cb),
- NULL);
-
- loop = g_main_loop_new(NULL, TRUE);
-
- /* We're testing for a crash, so just not crashing is a pass */
- webkit_web_view_load_uri(webView, "data:application/octect-stream,");
- g_main_loop_run(loop);
-
- g_assert_cmpint(beenThere, ==, TRUE);
-
- g_main_loop_unref(loop);
- g_object_unref(webView);
-}
-
-static void notifyDownloadStatusCallback(GObject *object, GParamSpec *pspec, gpointer data)
-{
- WebKitDownload *download = WEBKIT_DOWNLOAD(object);
- WebKitNetworkResponse *response = webkit_download_get_network_response(download);
- SoupMessage *message = webkit_network_response_get_message(response);
-
- switch (webkit_download_get_status(download)) {
- case WEBKIT_DOWNLOAD_STATUS_ERROR:
- g_assert_cmpint(message->status_code, ==, 404);
- g_main_loop_quit(loop);
- break;
- case WEBKIT_DOWNLOAD_STATUS_FINISHED:
- case WEBKIT_DOWNLOAD_STATUS_CANCELLED:
- g_assert_not_reached();
- break;
- default:
- break;
- }
-}
-
-static void serverCallback(SoupServer *server, SoupMessage *message, const char *path, GHashTable *query, SoupClientContext *context, gpointer userData)
-{
- if (message->method != SOUP_METHOD_GET) {
- soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED);
- return;
- }
-
- soup_message_set_status(message, SOUP_STATUS_NOT_FOUND);
- soup_message_body_complete(message->response_body);
-}
-
-static void test_webkit_download_not_found(void)
-{
- SoupServer *server = soup_server_new(SOUP_SERVER_PORT, 0, NULL);
- soup_server_run_async(server);
- soup_server_add_handler(server, NULL, serverCallback, NULL, NULL);
- SoupURI *baseURI = soup_uri_new("http://127.0.0.1/");
- soup_uri_set_port(baseURI, soup_server_get_port(server));
-
- SoupURI *uri = soup_uri_new_with_base(baseURI, "/foo");
- char *uriString = soup_uri_to_string(uri, FALSE);
- soup_uri_free(uri);
-
- loop = g_main_loop_new(NULL, TRUE);
- WebKitNetworkRequest *request = webkit_network_request_new(uriString);
- g_free (uriString);
- WebKitDownload *download = webkit_download_new(request);
- g_object_unref(request);
-
- webkit_download_set_destination_uri(download, "file:///tmp/foo");
- g_signal_connect(download, "notify::status", G_CALLBACK(notifyDownloadStatusCallback), NULL);
-
- webkit_download_start(download);
- g_main_loop_run(loop);
-
- g_object_unref(download);
- g_main_loop_unref(loop);
- soup_uri_free(baseURI);
- g_object_unref(server);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- // Get rid of runtime warnings about deprecated properties and signals, since they break the tests.
- g_setenv("G_ENABLE_DIAGNOSTIC", "0", TRUE);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/download/create", test_webkit_download_create);
- g_test_add_func("/webkit/download/synch", test_webkit_download_synch);
- g_test_add_func("/webkit/download/asynch", test_webkit_download_asynch);
- g_test_add_func("/webkit/download/data", test_webkit_download_data);
- g_test_add_func("/webkit/download/not-found", test_webkit_download_not_found);
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testfavicondatabase.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testfavicondatabase.c
deleted file mode 100644
index 393732b85..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testfavicondatabase.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2012 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "test_utils.h"
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <string.h>
-#include <webkit/webkit.h>
-
-const int gIconSize = 16;
-
-GMainLoop *loop;
-char *baseURI;
-
-static void
-serverCallback(SoupServer *server, SoupMessage *message, const char *path, GHashTable *query, SoupClientContext *context, void *data)
-{
- if (message->method != SOUP_METHOD_GET) {
- soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED);
- return;
- }
-
- soup_message_set_status(message, SOUP_STATUS_OK);
-
- char *contents;
- gsize length;
- if (g_str_equal(path, "/favicon.ico")) {
- GError *error = NULL;
-
- g_file_get_contents("blank.ico", &contents, &length, &error);
- g_assert(!error);
- } else {
- contents = g_strdup("<html><body>test</body></html>");
- length = strlen(contents);
- }
-
- soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, contents, length);
- soup_message_body_complete(message->response_body);
-}
-
-static void deleteDatabaseFileIfExists(const char *databasePath)
-{
- if (!g_file_test(databasePath, G_FILE_TEST_IS_DIR))
- return;
-
- char *databaseFilename = g_build_filename(databasePath, "WebpageIcons.db", NULL);
- if (g_unlink(databaseFilename) == -1) {
- g_free(databaseFilename);
- return;
- }
-
- g_free(databaseFilename);
- g_rmdir(databasePath);
-}
-
-static void testWebKitFaviconDatabaseSetPath()
-{
- char *databasePath = g_build_filename(g_get_tmp_dir(), "webkit-testfavicondatabase", NULL);
- deleteDatabaseFileIfExists(databasePath);
-
- WebKitFaviconDatabase *database = webkit_get_favicon_database();
- webkit_favicon_database_set_path(database, databasePath);
-
- g_assert_cmpstr(databasePath, ==, webkit_favicon_database_get_path(database));
-
- g_free(databasePath);
-}
-
-// See the comment in main() function that goes with this same guard.
-#ifdef NDEBUG
-
-static void faviconDatabaseGetValidFaviconCallback(GObject *sourceObject, GAsyncResult *result, void *userData)
-{
- gboolean *beenHere = (gboolean*)userData;
- GError *error = NULL;
- GdkPixbuf *icon = webkit_favicon_database_get_favicon_pixbuf_finish(WEBKIT_FAVICON_DATABASE(sourceObject), result, &error);
- g_assert(icon);
- g_object_unref(icon);
-
- *beenHere = TRUE;
-
- g_main_loop_quit(loop);
-}
-
-static void faviconDatabaseGetInvalidFaviconCallback(GObject *sourceObject, GAsyncResult *result, void *userData)
-{
- gboolean *beenHere = (gboolean*)userData;
- GError *error = NULL;
- GdkPixbuf *icon = webkit_favicon_database_get_favicon_pixbuf_finish(WEBKIT_FAVICON_DATABASE(sourceObject), result, &error);
- g_assert(!icon);
-
- *beenHere = TRUE;
-
- g_main_loop_quit(loop);
-}
-
-static void faviconDatabaseGetFaviconCancelledCallback(GObject *sourceObject, GAsyncResult *result, void *userData)
-{
- gboolean *beenHere = (gboolean*)userData;
- GError *error = NULL;
- GdkPixbuf *icon = webkit_favicon_database_get_favicon_pixbuf_finish(WEBKIT_FAVICON_DATABASE(sourceObject), result, &error);
- g_assert(!icon);
- g_assert(error && g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED));
-
- *beenHere = TRUE;
-
- g_main_loop_quit(loop);
-}
-
-static inline void quitMainLoopIfLoadCompleted(gboolean *iconOrPageLoaded)
-{
- if (*iconOrPageLoaded)
- g_main_loop_quit(loop);
- else
- *iconOrPageLoaded = TRUE;
-}
-
-static void idleQuitLoopCallback(WebKitWebView *webView, GParamSpec *paramSpec, gboolean *iconOrPageLoaded)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
-
- if (status == WEBKIT_LOAD_FINISHED || status == WEBKIT_LOAD_FAILED)
- quitMainLoopIfLoadCompleted(iconOrPageLoaded);
-}
-
-static void webkitWebViewIconLoaded(WebKitFaviconDatabase *database, const char *frameURI, gboolean *iconOrPageLoaded)
-{
- quitMainLoopIfLoadCompleted(iconOrPageLoaded);
-}
-
-static void loadURI(const char *uri)
-{
- WebKitWebView *view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- gboolean iconOrPageLoaded = FALSE;
-
- webkit_web_view_load_uri(view, uri);
-
- g_signal_connect(view, "notify::load-status", G_CALLBACK(idleQuitLoopCallback), &iconOrPageLoaded);
- g_signal_connect(view, "icon-loaded", G_CALLBACK(webkitWebViewIconLoaded), &iconOrPageLoaded);
-
- g_main_loop_run(loop);
-
- g_signal_handlers_disconnect_matched(view, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, &iconOrPageLoaded);
-}
-
-static gboolean faviconDatabaseGetValidFaviconIdle(void *userData)
-{
- webkit_favicon_database_get_favicon_pixbuf(webkit_get_favicon_database(), baseURI,
- gIconSize, gIconSize, NULL,
- faviconDatabaseGetValidFaviconCallback, userData);
- return FALSE;
-}
-
-static gboolean faviconDatabaseGetInvalidFaviconIdle(void *userData)
-{
- webkit_favicon_database_get_favicon_pixbuf(webkit_get_favicon_database(), "http://www.webkitgtk.org/",
- gIconSize, gIconSize, NULL,
- faviconDatabaseGetInvalidFaviconCallback, userData);
- return FALSE;
-}
-
-static gboolean faviconDatabaseGetFaviconCancelledIdle(void *userData)
-{
- GCancellable *cancellable = g_cancellable_new();
- webkit_favicon_database_get_favicon_pixbuf(webkit_get_favicon_database(), baseURI,
- gIconSize, gIconSize, cancellable,
- faviconDatabaseGetFaviconCancelledCallback, userData);
- g_cancellable_cancel(cancellable);
- g_object_unref(cancellable);
- return FALSE;
-}
-
-static void testWebKitFaviconDatabaseGetFavicon()
-{
- gboolean beenToIconCallback;
-
- loop = g_main_loop_new(NULL, TRUE);
-
- /* Load uri to make sure favicon is added to database. */
- loadURI(baseURI);
-
- beenToIconCallback = FALSE;
- g_idle_add((GSourceFunc)faviconDatabaseGetValidFaviconIdle, &beenToIconCallback);
- g_main_loop_run(loop);
- g_assert(beenToIconCallback);
-
- beenToIconCallback = FALSE;
- g_idle_add((GSourceFunc)faviconDatabaseGetInvalidFaviconIdle, &beenToIconCallback);
- g_main_loop_run(loop);
- g_assert(beenToIconCallback);
-
- beenToIconCallback = FALSE;
- g_idle_add((GSourceFunc)faviconDatabaseGetFaviconCancelledIdle, &beenToIconCallback);
- g_main_loop_run(loop);
- g_assert(beenToIconCallback);
-}
-
-static void testWebKitFaviconDatabaseGetFaviconURI()
-{
- char *iconURI = webkit_favicon_database_get_favicon_uri(webkit_get_favicon_database(), baseURI);
- char *expectedURI = g_strdup_printf("%sfavicon.ico", baseURI);
- g_assert_cmpstr(iconURI, ==, expectedURI);
- g_free(expectedURI);
- g_free(iconURI);
-}
-
-#endif
-
-static void testWebKitFaviconDatabaseRemoveAll(void)
-{
- WebKitFaviconDatabase *database = webkit_get_favicon_database();
- webkit_favicon_database_clear(database);
- char *iconURI = webkit_favicon_database_get_favicon_uri(database, baseURI);
- g_assert(!iconURI);
- g_free(iconURI);
-}
-
-static void testWebKitFaviconDatabaseCloseDatabase(void)
-{
- WebKitFaviconDatabase *database = webkit_get_favicon_database();
- char *databasePath = g_strdup(webkit_favicon_database_get_path(database));
- webkit_favicon_database_set_path(database, 0);
- deleteDatabaseFileIfExists(databasePath);
- g_free(databasePath);
-}
-
-int main(int argc, char **argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- // Get rid of runtime warnings about deprecated properties and signals, since they break the tests.
- g_setenv("G_ENABLE_DIAGNOSTIC", "0", TRUE);
-
- /* This hopefully makes the test independent of the path it's called from. */
- testutils_relative_chdir("Tools/TestWebKitAPI/Tests/WebKitGtk/resources/test.html", argv[0]);
-
- SoupServer *server = soup_server_new(SOUP_SERVER_PORT, 0, NULL);
- soup_server_run_async(server);
-
- soup_server_add_handler(server, NULL, serverCallback, NULL, NULL);
-
- SoupURI *soupURI = soup_uri_new("http://127.0.0.1/");
- soup_uri_set_port(soupURI, soup_server_get_port(server));
-
- baseURI = soup_uri_to_string(soupURI, FALSE);
- soup_uri_free(soupURI);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/favicondatabase/set-path", testWebKitFaviconDatabaseSetPath);
-
- // These two tests will trigger an ASSERTION on debug builds due
- // to http://webkit.org/b/67582. Remove the guards once the bug is fixed.
-#ifdef NDEBUG
- g_test_add_func("/webkit/favicondatabase/get-favicon", testWebKitFaviconDatabaseGetFavicon);
- g_test_add_func("/webkit/favicondatabase/get-favicon-uri", testWebKitFaviconDatabaseGetFaviconURI);
-#endif
-
- g_test_add_func("/webkit/favicondatabase/remove-all", testWebKitFaviconDatabaseRemoveAll);
- g_test_add_func("/webkit/favicondatabase/close-db", testWebKitFaviconDatabaseCloseDatabase);
-
- return g_test_run();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testglobals.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testglobals.c
deleted file mode 100644
index 4b9ec4fcf..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testglobals.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2010 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <gtk/gtk.h>
-#include <libsoup/soup.h>
-#include <webkit/webkit.h>
-
-// Make sure the session is initialized properly when webkit_get_default_session() is called.
-static void test_globals_default_session()
-{
- g_test_bug("36754");
-
- SoupSession* session = webkit_get_default_session();
- soup_session_remove_feature_by_type(session, WEBKIT_TYPE_SOUP_AUTH_DIALOG);
-
- // This makes sure our initialization ran.
- g_assert(soup_session_get_feature(session, SOUP_TYPE_CONTENT_DECODER) != NULL);
-
- // Creating a WebView should make sure the session is
- // initialized, and not mess with our changes.
- WebKitWebView* web_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(web_view);
- g_object_unref(web_view);
-
- // These makes sure our modification was kept.
- g_assert(soup_session_get_feature(session, SOUP_TYPE_CONTENT_DECODER) != NULL);
- g_assert(soup_session_get_feature(session, WEBKIT_TYPE_SOUP_AUTH_DIALOG) == NULL);
-}
-
-static void test_globals_security_policy()
-{
- // Check default policy for well known schemes.
- WebKitSecurityPolicy policy = webkit_get_security_policy_for_uri_scheme("http");
- guint mask = WEBKIT_SECURITY_POLICY_CORS_ENABLED;
- g_assert_cmpuint(policy & mask, ==, mask);
-
- policy = webkit_get_security_policy_for_uri_scheme("https");
- mask = WEBKIT_SECURITY_POLICY_SECURE | WEBKIT_SECURITY_POLICY_CORS_ENABLED;
- g_assert_cmpuint(policy & mask, ==, mask);
-
- policy = webkit_get_security_policy_for_uri_scheme("file");
- mask = WEBKIT_SECURITY_POLICY_LOCAL;
- g_assert_cmpuint(policy & mask, ==, mask);
-
- policy = webkit_get_security_policy_for_uri_scheme("data");
- mask = WEBKIT_SECURITY_POLICY_NO_ACCESS_TO_OTHER_SCHEME | WEBKIT_SECURITY_POLICY_SECURE;
- g_assert_cmpuint(policy & mask, ==, mask);
-
- policy = webkit_get_security_policy_for_uri_scheme("about");
- mask = WEBKIT_SECURITY_POLICY_NO_ACCESS_TO_OTHER_SCHEME | WEBKIT_SECURITY_POLICY_SECURE | WEBKIT_SECURITY_POLICY_EMPTY_DOCUMENT;
- g_assert_cmpuint(policy & mask, ==, mask);
-
- // Custom scheme.
- policy = webkit_get_security_policy_for_uri_scheme("foo");
- g_assert(!policy);
-
- policy |= WEBKIT_SECURITY_POLICY_LOCAL;
- webkit_set_security_policy_for_uri_scheme("foo", policy);
- g_assert_cmpuint(webkit_get_security_policy_for_uri_scheme("foo"), ==, policy);
-
- policy |= WEBKIT_SECURITY_POLICY_NO_ACCESS_TO_OTHER_SCHEME;
- webkit_set_security_policy_for_uri_scheme("foo", policy);
- g_assert_cmpuint(webkit_get_security_policy_for_uri_scheme("foo"), ==, policy);
-
- policy |= WEBKIT_SECURITY_POLICY_DISPLAY_ISOLATED;
- webkit_set_security_policy_for_uri_scheme("foo", policy);
- g_assert_cmpuint(webkit_get_security_policy_for_uri_scheme("foo"), ==, policy);
-
- policy |= WEBKIT_SECURITY_POLICY_SECURE;
- webkit_set_security_policy_for_uri_scheme("foo", policy);
- g_assert_cmpuint(webkit_get_security_policy_for_uri_scheme("foo"), ==, policy);
-
- policy |= WEBKIT_SECURITY_POLICY_CORS_ENABLED;
- webkit_set_security_policy_for_uri_scheme("foo", policy);
- g_assert_cmpuint(webkit_get_security_policy_for_uri_scheme("foo"), ==, policy);
-
- policy |= WEBKIT_SECURITY_POLICY_EMPTY_DOCUMENT;
- webkit_set_security_policy_for_uri_scheme("foo", policy);
- g_assert_cmpuint(webkit_get_security_policy_for_uri_scheme("foo"), ==, policy);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/globals/default_session",
- test_globals_default_session);
- g_test_add_func("/webkit/globals/security-policy",
- test_globals_security_policy);
- return g_test_run();
-}
-
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testhittestresult.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testhittestresult.c
deleted file mode 100644
index eac34c47b..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testhittestresult.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (C) 2009 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2,1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <unistd.h>
-#include <glib/gstdio.h>
-#include <webkit/webkit.h>
-
-typedef struct {
- char* data;
- guint flag;
-} TestInfo;
-
-static GMainLoop* loop;
-
-typedef struct {
- WebKitWebView* webView;
- TestInfo* info;
-} HitTestResultFixture;
-
-TestInfo*
-test_info_new(const char* data, guint flag)
-{
- TestInfo* info;
-
- info = g_slice_new(TestInfo);
- info->data = g_strdup(data);
- info->flag = flag;
-
- return info;
-}
-
-void
-test_info_destroy(TestInfo* info)
-{
- g_free(info->data);
- g_slice_free(TestInfo, info);
-}
-
-static void hit_test_result_fixture_setup(HitTestResultFixture* fixture, gconstpointer data)
-{
- fixture->webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(fixture->webView);
- loop = g_main_loop_new(NULL, TRUE);
- fixture->info = (TestInfo*)data;
-}
-
-static void hit_test_result_fixture_teardown(HitTestResultFixture* fixture, gconstpointer data)
-{
- g_object_unref(fixture->webView);
- g_main_loop_unref(loop);
- test_info_destroy(fixture->info);
-}
-
-static void
-load_status_cb(WebKitWebView* webView,
- GParamSpec* spec,
- gpointer data)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
- TestInfo* info = (TestInfo*)data;
-
- if (status == WEBKIT_LOAD_FINISHED) {
- WebKitHitTestResult* result;
- guint context;
- GdkEvent* event = gdk_event_new(GDK_BUTTON_PRESS);
- WebKitDOMNode* node;
- gint x, y;
-
- /* Close enough to 0,0 */
- event->button.x = 5;
- event->button.y = 5;
-
- result = webkit_web_view_get_hit_test_result(webView, (GdkEventButton*) event);
- gdk_event_free(event);
- g_assert(result);
-
- g_object_get(result, "context", &context, NULL);
- g_assert(context & info->flag);
-
- g_object_get(result, "inner-node", &node, NULL);
- g_assert(node);
- g_assert(WEBKIT_DOM_IS_NODE(node));
-
- g_object_get(result, "x", &x, "y", &y, NULL);
- g_assert_cmpint(x, ==, 5);
- g_assert_cmpint(y, ==, 5);
-
- /* We can only test these node types at the moment. In the
- * input case there seems to be an extra layer with a DIV on
- * top of the input, which gets assigned to the inner-node.
- * tag */
- if (info->flag == WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT)
- g_assert(WEBKIT_DOM_IS_HTML_HTML_ELEMENT(node));
- else if (info->flag == WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE)
- g_assert(WEBKIT_DOM_IS_HTML_IMAGE_ELEMENT(node));
- else if (info->flag == WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK) {
- /* The hit test will give us the inner text node, we want
- * the A tag */
- WebKitDOMNode* parent = webkit_dom_node_get_parent_node(node);
- g_assert(WEBKIT_DOM_IS_HTML_ANCHOR_ELEMENT(parent));
- }
-
- g_object_unref(result);
- g_main_loop_quit(loop);
- }
-}
-
-static void
-test_webkit_hit_test_result(HitTestResultFixture* fixture, gconstpointer data)
-{
- TestInfo* info = (TestInfo*)data;
- GtkAllocation allocation = { 0, 0, 50, 50 };
-
- webkit_web_view_load_string(fixture->webView,
- info->data,
- "text/html",
- "utf-8",
- "file://");
- gtk_widget_size_allocate(GTK_WIDGET(fixture->webView), &allocation);
- g_signal_connect(fixture->webView, "notify::load-status", G_CALLBACK(load_status_cb), info);
- g_main_loop_run(loop);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
- // Get rid of runtime warnings about deprecated properties and signals, since they break the tests.
- g_setenv("G_ENABLE_DIAGNOSTIC", "0", TRUE);
-
- g_test_bug_base("https://bugs.webkit.org/");
-
- g_test_add("/webkit/hittestresult/document", HitTestResultFixture,
- test_info_new("<html><body><h1>WebKitGTK+!</h1></body></html>",
- WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT),
- hit_test_result_fixture_setup, test_webkit_hit_test_result, hit_test_result_fixture_teardown);
- /* We hardcode all elements to be at 0,0 so that we know where to
- * generate the button events */
- g_test_add("/webkit/hittestresult/image", HitTestResultFixture,
- test_info_new("<html><body><img style='position:absolute; left:0; top:0'src='0xdeadbeef' width=50 height=50></img></body></html>",
- WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE),
- hit_test_result_fixture_setup, test_webkit_hit_test_result, hit_test_result_fixture_teardown);
- g_test_add("/webkit/hittestresult/editable", HitTestResultFixture,
- test_info_new("<html><body><input style='position:absolute; left:0; top:0' size='35'></input>></body></html>",
- WEBKIT_HIT_TEST_RESULT_CONTEXT_EDITABLE),
- hit_test_result_fixture_setup, test_webkit_hit_test_result, hit_test_result_fixture_teardown);
- g_test_add("/webkit/hittestresult/link", HitTestResultFixture,
- test_info_new("<html><body><a style='position:absolute; left:0; top:0' href='http://www.example.com'>HELLO WORLD</a></body></html>",
- WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK),
- hit_test_result_fixture_setup, test_webkit_hit_test_result, hit_test_result_fixture_teardown);
-
- return g_test_run ();
-}
-
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testhttpbackend.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testhttpbackend.c
deleted file mode 100644
index 93776879b..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testhttpbackend.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2009 Gustavo Noronha Silva
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <unistd.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-// Not yet public API
-SoupMessage* webkit_network_request_get_message(WebKitNetworkRequest* request);
-
-static gboolean navigation_policy_decision_requested_cb(WebKitWebView* web_view,
- WebKitWebFrame* web_frame,
- WebKitNetworkRequest* request,
- WebKitWebNavigationAction* action,
- WebKitWebPolicyDecision* decision,
- gpointer data)
-{
- SoupMessage* message = webkit_network_request_get_message(request);
-
- /* 1 -> webkit_network_request_with_core_request
- *
- * The SoupMessage is created exclusively for the emission of this
- * signal.
- */
- g_assert_cmpint(G_OBJECT(message)->ref_count, ==, 1);
-
- return FALSE;
-}
-
-static void test_soup_message_lifetime()
-{
- WebKitWebView* web_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
-
- g_object_ref_sink(web_view);
-
- g_signal_connect(web_view, "navigation-policy-decision-requested",
- G_CALLBACK(navigation_policy_decision_requested_cb),
- NULL);
-
- /* load_uri will trigger the navigation-policy-decision-requested
- * signal emission;
- */
- webkit_web_view_load_uri(web_view, "http://127.0.0.1/");
-
- g_object_unref(web_view);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/soupmessage/lifetime", test_soup_message_lifetime);
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testkeyevents.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testkeyevents.c
deleted file mode 100644
index acd01f35f..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testkeyevents.c
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- * Copyright (C) 2009, 2010 Martin Robinson <mrobinson@webkit.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2,1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <glib/gstdio.h>
-#include <webkit/webkit.h>
-#include <JavaScriptCore/JSStringRef.h>
-#include <JavaScriptCore/JSContextRef.h>
-
-typedef struct {
- char* page;
- char* text;
- gboolean shouldBeHandled;
-} TestInfo;
-
-typedef struct {
- GtkWidget* window;
- WebKitWebView* webView;
- GMainLoop* loop;
- TestInfo* info;
-} KeyEventFixture;
-
-TestInfo*
-test_info_new(const char* page, gboolean shouldBeHandled)
-{
- TestInfo* info;
-
- info = g_slice_new(TestInfo);
- info->page = g_strdup(page);
- info->shouldBeHandled = shouldBeHandled;
- info->text = 0;
-
- return info;
-}
-
-void
-test_info_destroy(TestInfo* info)
-{
- g_free(info->page);
- g_free(info->text);
- g_slice_free(TestInfo, info);
-}
-
-static void key_event_fixture_setup(KeyEventFixture* fixture, gconstpointer data)
-{
- fixture->loop = g_main_loop_new(NULL, TRUE);
-
- fixture->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- fixture->webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
-
- gtk_container_add(GTK_CONTAINER(fixture->window), GTK_WIDGET(fixture->webView));
-}
-
-static void key_event_fixture_teardown(KeyEventFixture* fixture, gconstpointer data)
-{
- gtk_widget_destroy(fixture->window);
- g_main_loop_unref(fixture->loop);
- test_info_destroy(fixture->info);
-}
-
-static gboolean key_press_event_cb(WebKitWebView* webView, GdkEvent* event, gpointer data)
-{
- KeyEventFixture* fixture = (KeyEventFixture*)data;
- gboolean handled = GTK_WIDGET_GET_CLASS(fixture->webView)->key_press_event(GTK_WIDGET(fixture->webView), &event->key);
- g_assert_cmpint(handled, ==, fixture->info->shouldBeHandled);
-
- return FALSE;
-}
-
-static gboolean key_release_event_cb(WebKitWebView* webView, GdkEvent* event, gpointer data)
-{
- // WebCore never seems to mark keyup events as handled.
- KeyEventFixture* fixture = (KeyEventFixture*)data;
- gboolean handled = GTK_WIDGET_GET_CLASS(fixture->webView)->key_press_event(GTK_WIDGET(fixture->webView), &event->key);
- g_assert(!handled);
-
- g_main_loop_quit(fixture->loop);
-
- return FALSE;
-}
-
-static void test_keypress_events_load_status_cb(WebKitWebView* webView, GParamSpec* spec, gpointer data)
-{
- KeyEventFixture* fixture = (KeyEventFixture*)data;
- WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
- if (status == WEBKIT_LOAD_FINISHED) {
- g_signal_connect(fixture->webView, "key-press-event",
- G_CALLBACK(key_press_event_cb), fixture);
- g_signal_connect(fixture->webView, "key-release-event",
- G_CALLBACK(key_release_event_cb), fixture);
- if (!gtk_test_widget_send_key(GTK_WIDGET(fixture->webView),
- gdk_unicode_to_keyval('a'), 0))
- g_assert_not_reached();
- }
-
-}
-
-gboolean map_event_cb(GtkWidget *widget, GdkEvent* event, gpointer data)
-{
- KeyEventFixture* fixture = (KeyEventFixture*)data;
- webkit_web_view_load_string(fixture->webView, fixture->info->page,
- "text/html", "utf-8", "file://");
- return FALSE;
-}
-
-static void setup_keyevent_test(KeyEventFixture* fixture, gconstpointer data, GCallback load_event_callback)
-{
- fixture->info = (TestInfo*)data;
- g_signal_connect(fixture->window, "map-event",
- G_CALLBACK(map_event_cb), fixture);
-
- gtk_widget_grab_focus(GTK_WIDGET(fixture->webView));
- gtk_widget_show(fixture->window);
- gtk_widget_show(GTK_WIDGET(fixture->webView));
- gtk_window_present(GTK_WINDOW(fixture->window));
-
- g_signal_connect(fixture->webView, "notify::load-status",
- load_event_callback, fixture);
-
- g_main_loop_run(fixture->loop);
-}
-
-static void test_keypress_events(KeyEventFixture* fixture, gconstpointer data)
-{
- setup_keyevent_test(fixture, data, G_CALLBACK(test_keypress_events_load_status_cb));
-}
-
-static gboolean element_text_equal_to(JSContextRef context, const gchar* text)
-{
- JSStringRef scriptString = JSStringCreateWithUTF8CString(
- "window.document.getElementById(\"in\").value;");
- JSValueRef value = JSEvaluateScript(context, scriptString, 0, 0, 0, 0);
- JSStringRelease(scriptString);
-
- // If the value isn't a string, the element is probably a div
- // so grab the innerText instead.
- if (!JSValueIsString(context, value)) {
- JSStringRef scriptString = JSStringCreateWithUTF8CString(
- "window.document.getElementById(\"in\").innerText;");
- value = JSEvaluateScript(context, scriptString, 0, 0, 0, 0);
- JSStringRelease(scriptString);
- }
-
- g_assert(JSValueIsString(context, value));
- JSStringRef inputString = JSValueToStringCopy(context, value, 0);
- g_assert(inputString);
-
- gint size = JSStringGetMaximumUTF8CStringSize(inputString);
- gchar* cString = g_malloc(size);
- JSStringGetUTF8CString(inputString, cString, size);
- JSStringRelease(inputString);
-
- gboolean result = g_utf8_collate(cString, text) == 0;
- g_free(cString);
- return result;
-}
-
-static void test_ime_load_status_cb(WebKitWebView* webView, GParamSpec* spec, gpointer data)
-{
- KeyEventFixture* fixture = (KeyEventFixture*)data;
- WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
- if (status != WEBKIT_LOAD_FINISHED)
- return;
-
- JSGlobalContextRef context = webkit_web_frame_get_global_context(
- webkit_web_view_get_main_frame(webView));
- g_assert(context);
-
- GtkIMContext* imContext = 0;
- g_object_get(webView, "im-context", &imContext, NULL);
- g_assert(imContext);
-
- // Test that commits that happen outside of key events
- // change the text field immediately. This closely replicates
- // the behavior of SCIM.
- g_assert(element_text_equal_to(context, ""));
- g_signal_emit_by_name(imContext, "commit", "a");
- g_assert(element_text_equal_to(context, "a"));
- g_signal_emit_by_name(imContext, "commit", "b");
- g_assert(element_text_equal_to(context, "ab"));
- g_signal_emit_by_name(imContext, "commit", "c");
- g_assert(element_text_equal_to(context, "abc"));
-
- g_object_unref(imContext);
- g_main_loop_quit(fixture->loop);
-}
-
-static void test_ime(KeyEventFixture* fixture, gconstpointer data)
-{
- setup_keyevent_test(fixture, data, G_CALLBACK(test_ime_load_status_cb));
-}
-
-static gboolean verify_contents(gpointer data)
-{
- KeyEventFixture* fixture = (KeyEventFixture*)data;
- JSGlobalContextRef context = webkit_web_frame_get_global_context(
- webkit_web_view_get_main_frame(fixture->webView));
- g_assert(context);
-
- g_assert(element_text_equal_to(context, fixture->info->text));
- g_main_loop_quit(fixture->loop);
- return FALSE;
-}
-
-static void test_blocking_load_status_cb(WebKitWebView* webView, GParamSpec* spec, gpointer data)
-{
- KeyEventFixture* fixture = (KeyEventFixture*)data;
- WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
- if (status != WEBKIT_LOAD_FINISHED)
- return;
-
- // The first keypress event should not modify the field.
- fixture->info->text = g_strdup("bc");
- if (!gtk_test_widget_send_key(GTK_WIDGET(fixture->webView),
- gdk_unicode_to_keyval('a'), 0))
- g_assert_not_reached();
- if (!gtk_test_widget_send_key(GTK_WIDGET(fixture->webView),
- gdk_unicode_to_keyval('b'), 0))
- g_assert_not_reached();
- if (!gtk_test_widget_send_key(GTK_WIDGET(fixture->webView),
- gdk_unicode_to_keyval('c'), 0))
- g_assert_not_reached();
-
- g_idle_add(verify_contents, fixture);
-}
-
-static void test_blocking(KeyEventFixture* fixture, gconstpointer data)
-{
- setup_keyevent_test(fixture, data, G_CALLBACK(test_blocking_load_status_cb));
-}
-
-#if defined(GDK_WINDOWING_X11)
-static void test_xim_load_status_cb(WebKitWebView* webView, GParamSpec* spec, gpointer data)
-{
- KeyEventFixture* fixture = (KeyEventFixture*)data;
- WebKitLoadStatus status = webkit_web_view_get_load_status(webView);
- if (status != WEBKIT_LOAD_FINISHED)
- return;
-
- GtkIMContext* imContext = 0;
- g_object_get(webView, "im-context", &imContext, NULL);
- g_assert(imContext);
-
- gchar* originalId = g_strdup(gtk_im_multicontext_get_context_id(GTK_IM_MULTICONTEXT(imContext)));
- gtk_im_multicontext_set_context_id(GTK_IM_MULTICONTEXT(imContext), "xim");
-
- // Test that commits that happen outside of key events
- // change the text field immediately. This closely replicates
- // the behavior of SCIM.
- fixture->info->text = g_strdup("debian");
- if (!gtk_test_widget_send_key(GTK_WIDGET(fixture->webView),
- gdk_unicode_to_keyval('d'), 0))
- g_assert_not_reached();
- if (!gtk_test_widget_send_key(GTK_WIDGET(fixture->webView),
- gdk_unicode_to_keyval('e'), 0))
- g_assert_not_reached();
- if (!gtk_test_widget_send_key(GTK_WIDGET(fixture->webView),
- gdk_unicode_to_keyval('b'), 0))
- g_assert_not_reached();
- if (!gtk_test_widget_send_key(GTK_WIDGET(fixture->webView),
- gdk_unicode_to_keyval('i'), 0))
- g_assert_not_reached();
- if (!gtk_test_widget_send_key(GTK_WIDGET(fixture->webView),
- gdk_unicode_to_keyval('a'), 0))
- g_assert_not_reached();
- if (!gtk_test_widget_send_key(GTK_WIDGET(fixture->webView),
- gdk_unicode_to_keyval('n'), 0))
- g_assert_not_reached();
-
- gtk_im_multicontext_set_context_id(GTK_IM_MULTICONTEXT(imContext), originalId);
- g_free(originalId);
- g_object_unref(imContext);
-
- g_idle_add(verify_contents, fixture);
-}
-
-static void test_xim(KeyEventFixture* fixture, gconstpointer data)
-{
- setup_keyevent_test(fixture, data, G_CALLBACK(test_xim_load_status_cb));
-}
-#endif
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
-
-
- // We'll test input on a slew of different node types. Key events to
- // text inputs and editable divs should be marked as handled. Key events
- // to buttons and links should not.
- const char* textinput_html = "<html><body><input id=\"in\" type=\"text\">"
- "<script>document.getElementById('in').focus();</script></body></html>";
- const char* button_html = "<html><body><input id=\"in\" type=\"button\">"
- "<script>document.getElementById('in').focus();</script></body></html>";
- const char* link_html = "<html><body><a href=\"http://www.gnome.org\" id=\"in\">"
- "LINKY MCLINKERSON</a><script>document.getElementById('in').focus();</script>"
- "</body></html>";
- const char* div_html = "<html><body><div id=\"in\" contenteditable=\"true\">"
- "<script>document.getElementById('in').focus();</script></body></html>";
-
- // These are similar to the blocks above, but they should block the first
- // keypress modifying the editable node.
- const char* textinput_html_blocking = "<html><body>"
- "<input id=\"in\" type=\"text\" "
- "onkeypress=\"if (first) {event.preventDefault();first=false;}\">"
- "<script>first = true;\ndocument.getElementById('in').focus();</script>\n"
- "</script></body></html>";
- const char* div_html_blocking = "<html><body>"
- "<div id=\"in\" contenteditable=\"true\" "
- "onkeypress=\"if (first) {event.preventDefault();first=false;}\">"
- "<script>first = true; document.getElementById('in').focus();</script>\n"
- "</script></body></html>";
-
- g_test_add("/webkit/keyevents/event-textinput", KeyEventFixture,
- test_info_new(textinput_html, TRUE),
- key_event_fixture_setup,
- test_keypress_events,
- key_event_fixture_teardown);
- g_test_add("/webkit/keyevents/event-buttons", KeyEventFixture,
- test_info_new(button_html, FALSE),
- key_event_fixture_setup,
- test_keypress_events,
- key_event_fixture_teardown);
- g_test_add("/webkit/keyevents/event-link", KeyEventFixture,
- test_info_new(link_html, FALSE),
- key_event_fixture_setup,
- test_keypress_events,
- key_event_fixture_teardown);
- g_test_add("/webkit/keyevent/event-div", KeyEventFixture,
- test_info_new(div_html, TRUE),
- key_event_fixture_setup,
- test_keypress_events,
- key_event_fixture_teardown);
- g_test_add("/webkit/keyevent/ime-textinput", KeyEventFixture,
- test_info_new(textinput_html, TRUE),
- key_event_fixture_setup,
- test_ime,
- key_event_fixture_teardown);
- g_test_add("/webkit/keyevent/ime-div", KeyEventFixture,
- test_info_new(div_html, TRUE),
- key_event_fixture_setup,
- test_ime,
- key_event_fixture_teardown);
- g_test_add("/webkit/keyevent/block-textinput", KeyEventFixture,
- test_info_new(textinput_html_blocking, TRUE),
- key_event_fixture_setup,
- test_blocking,
- key_event_fixture_teardown);
- g_test_add("/webkit/keyevent/block-div", KeyEventFixture,
- test_info_new(div_html_blocking, TRUE),
- key_event_fixture_setup,
- test_blocking,
- key_event_fixture_teardown);
-#if defined(GDK_WINDOWING_X11)
- g_test_add("/webkit/keyevent/xim-textinput", KeyEventFixture,
- test_info_new(textinput_html, TRUE),
- key_event_fixture_setup,
- test_xim,
- key_event_fixture_teardown);
- g_test_add("/webkit/keyevent/xim-div", KeyEventFixture,
- test_info_new(div_html, TRUE),
- key_event_fixture_setup,
- test_xim,
- key_event_fixture_teardown);
-#endif
-
- return g_test_run();
-}
-
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testloading.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testloading.c
deleted file mode 100644
index 95246ec28..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testloading.c
+++ /dev/null
@@ -1,437 +0,0 @@
-/*
- * Copyright (C) 2009, 2010 Gustavo Noronha Silva
- * Copyright (C) 2009 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <gtk/gtk.h>
-#include <libsoup/soup.h>
-#include <string.h>
-#include <webkit/webkit.h>
-
-/* This string has to be rather big because of the cancelled test - it
- * looks like soup refuses to send or receive a too small chunk */
-#define HTML_STRING "<html><body>Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!Testing!</body></html>"
-
-SoupURI* base_uri;
-
-/* For real request testing */
-static void
-server_callback(SoupServer* server, SoupMessage* msg,
- const char* path, GHashTable* query,
- SoupClientContext* context, gpointer data)
-{
- if (msg->method != SOUP_METHOD_GET) {
- soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED);
- return;
- }
-
- soup_message_set_status(msg, SOUP_STATUS_OK);
-
- if (g_str_equal(path, "/test_loading_status") || g_str_equal(path, "/test_loading_status2"))
- soup_message_body_append(msg->response_body, SOUP_MEMORY_STATIC, HTML_STRING, strlen(HTML_STRING));
- else if (g_str_equal(path, "/test_load_error")) {
- soup_message_set_status(msg, SOUP_STATUS_CANT_CONNECT);
- } else if (g_str_equal(path, "/test_loading_cancelled")) {
- soup_message_headers_set_encoding(msg->response_headers, SOUP_ENCODING_CHUNKED);
- soup_message_body_append(msg->response_body, SOUP_MEMORY_STATIC, HTML_STRING, strlen(HTML_STRING));
- soup_server_unpause_message(server, msg);
- return;
- }
-
- soup_message_body_complete(msg->response_body);
-}
-
-typedef struct {
- WebKitWebView* webView;
- GMainLoop *loop;
- gboolean has_been_provisional;
- gboolean has_been_committed;
- gboolean has_been_first_visually_non_empty_layout;
- gboolean has_been_finished;
- gboolean has_been_failed;
- gboolean has_been_load_error;
-} WebLoadingFixture;
-
-static void web_loading_fixture_setup(WebLoadingFixture* fixture, gconstpointer data)
-{
- fixture->webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- fixture->loop = g_main_loop_new(NULL, TRUE);
- g_object_ref_sink(fixture->webView);
- fixture->has_been_provisional = FALSE;
- fixture->has_been_committed = FALSE;
- fixture->has_been_first_visually_non_empty_layout = FALSE;
- fixture->has_been_finished = FALSE;
- fixture->has_been_failed = FALSE;
- fixture->has_been_load_error = FALSE;
-}
-
-static void web_loading_fixture_teardown(WebLoadingFixture* fixture, gconstpointer data)
-{
- g_object_unref(fixture->webView);
- g_main_loop_unref(fixture->loop);
-}
-
-static char* get_uri_for_path(const char* path)
-{
- SoupURI* uri;
- char* uri_string;
-
- uri = soup_uri_new_with_base(base_uri, path);
- uri_string = soup_uri_to_string(uri, FALSE);
- soup_uri_free (uri);
-
- return uri_string;
-}
-
-static void load_finished_cb(WebKitWebView* web_view, WebKitWebFrame* web_frame, WebLoadingFixture* fixture)
-{
- g_assert(fixture->has_been_provisional);
- g_assert(fixture->has_been_committed);
- g_assert(fixture->has_been_first_visually_non_empty_layout);
-
- g_main_loop_quit(fixture->loop);
-}
-
-
-static void status_changed_cb(GObject* object, GParamSpec* pspec, WebLoadingFixture* fixture)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status(WEBKIT_WEB_VIEW(object));
-
- switch (status) {
- case WEBKIT_LOAD_PROVISIONAL:
- g_assert(!fixture->has_been_provisional);
- g_assert(!fixture->has_been_committed);
- g_assert(!fixture->has_been_first_visually_non_empty_layout);
- fixture->has_been_provisional = TRUE;
- break;
- case WEBKIT_LOAD_COMMITTED:
- g_assert(fixture->has_been_provisional);
- g_assert(!fixture->has_been_committed);
- g_assert(!fixture->has_been_first_visually_non_empty_layout);
- fixture->has_been_committed = TRUE;
- break;
- case WEBKIT_LOAD_FIRST_VISUALLY_NON_EMPTY_LAYOUT:
- g_assert(fixture->has_been_provisional);
- g_assert(fixture->has_been_committed);
- g_assert(!fixture->has_been_first_visually_non_empty_layout);
- fixture->has_been_first_visually_non_empty_layout = TRUE;
- break;
- case WEBKIT_LOAD_FINISHED:
- g_assert(fixture->has_been_provisional);
- g_assert(fixture->has_been_committed);
- g_assert(fixture->has_been_first_visually_non_empty_layout);
- break;
- default:
- g_assert_not_reached();
- }
-}
-
-static void test_loading_status(WebLoadingFixture* fixture, gconstpointer data)
-{
- char* uri_string;
-
- g_assert_cmpint(webkit_web_view_get_load_status(fixture->webView), ==, WEBKIT_LOAD_PROVISIONAL);
-
- g_object_connect(G_OBJECT(fixture->webView),
- "signal::notify::load-status", G_CALLBACK(status_changed_cb), fixture,
- "signal::load-finished", G_CALLBACK(load_finished_cb), fixture,
- NULL);
-
- uri_string = get_uri_for_path("/test_loading_status");
-
- /* load_uri will trigger the navigation-policy-decision-requested
- * signal emission;
- */
- webkit_web_view_load_uri(fixture->webView, uri_string);
- g_free(uri_string);
-
- g_main_loop_run(fixture->loop);
-}
-
-static void load_error_status_changed_cb(GObject* object, GParamSpec* pspec, WebLoadingFixture* fixture)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status(WEBKIT_WEB_VIEW(object));
-
- switch(status) {
- case WEBKIT_LOAD_PROVISIONAL:
- g_assert(!fixture->has_been_provisional);
- fixture->has_been_provisional = TRUE;
- break;
- case WEBKIT_LOAD_COMMITTED:
- g_assert(!fixture->has_been_committed);
- fixture->has_been_committed = TRUE;
- break;
- case WEBKIT_LOAD_FINISHED:
- g_assert(fixture->has_been_provisional);
- g_assert(fixture->has_been_load_error);
- g_assert(fixture->has_been_failed);
- g_assert(!fixture->has_been_finished);
- fixture->has_been_finished = TRUE;
- break;
- case WEBKIT_LOAD_FAILED:
- g_assert(!fixture->has_been_failed);
- fixture->has_been_failed = TRUE;
- g_main_loop_quit(fixture->loop);
- break;
- default:
- break;
- }
-}
-
-static gboolean load_error_cb(WebKitWebView* webView, WebKitWebFrame* frame, const char* uri, GError *error, WebLoadingFixture* fixture)
-{
- g_assert(fixture->has_been_provisional);
- g_assert(!fixture->has_been_load_error);
- fixture->has_been_load_error = TRUE;
-
- return FALSE;
-}
-
-static void test_loading_error(WebLoadingFixture* fixture, gconstpointer data)
-{
- char* uri_string;
-
- g_test_bug("28842");
-
- g_signal_connect(fixture->webView, "load-error", G_CALLBACK(load_error_cb), fixture);
- g_signal_connect(fixture->webView, "notify::load-status", G_CALLBACK(load_error_status_changed_cb), fixture);
-
- uri_string = get_uri_for_path("/test_load_error");
- webkit_web_view_load_uri(fixture->webView, uri_string);
- g_free(uri_string);
-
- g_main_loop_run(fixture->loop);
-
- g_assert(fixture->has_been_provisional);
- g_assert(!fixture->has_been_committed);
- g_assert(fixture->has_been_load_error);
- g_assert(fixture->has_been_failed);
- g_assert(!fixture->has_been_finished);
-}
-
-/* Cancelled load */
-
-static gboolean load_cancelled_cb(WebKitWebView* webView, WebKitWebFrame* frame, const char* uri, GError *error, WebLoadingFixture* fixture)
-{
- g_assert(fixture->has_been_provisional);
- g_assert(fixture->has_been_failed);
- g_assert(!fixture->has_been_load_error);
- g_assert(error->code == WEBKIT_NETWORK_ERROR_CANCELLED);
- fixture->has_been_load_error = TRUE;
-
- return TRUE;
-}
-
-static gboolean stop_load (gpointer data)
-{
- webkit_web_view_stop_loading(WEBKIT_WEB_VIEW(data));
- return FALSE;
-}
-
-static void load_cancelled_status_changed_cb(GObject* object, GParamSpec* pspec, WebLoadingFixture* fixture)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status(WEBKIT_WEB_VIEW(object));
-
- switch(status) {
- case WEBKIT_LOAD_PROVISIONAL:
- g_assert(!fixture->has_been_provisional);
- g_assert(!fixture->has_been_failed);
- fixture->has_been_provisional = TRUE;
- break;
- case WEBKIT_LOAD_COMMITTED:
- g_idle_add (stop_load, object);
- break;
- case WEBKIT_LOAD_FAILED:
- g_assert(fixture->has_been_provisional);
- g_assert(!fixture->has_been_failed);
- g_assert(!fixture->has_been_load_error);
- fixture->has_been_failed = TRUE;
- g_main_loop_quit(fixture->loop);
- break;
- case WEBKIT_LOAD_FINISHED:
- g_assert_not_reached();
- break;
- default:
- break;
- }
-}
-
-static void test_loading_cancelled(WebLoadingFixture* fixture, gconstpointer data)
-{
- char* uri_string;
-
- g_test_bug("29644");
-
- g_signal_connect(fixture->webView, "load-error", G_CALLBACK(load_cancelled_cb), fixture);
- g_signal_connect(fixture->webView, "notify::load-status", G_CALLBACK(load_cancelled_status_changed_cb), fixture);
-
- uri_string = get_uri_for_path("/test_loading_cancelled");
- webkit_web_view_load_uri(fixture->webView, uri_string);
- g_free(uri_string);
-
- g_main_loop_run(fixture->loop);
-}
-
-static void load_goback_status_changed_cb(GObject* object, GParamSpec* pspec, WebLoadingFixture* fixture)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status(WEBKIT_WEB_VIEW(object));
-
- switch(status) {
- case WEBKIT_LOAD_PROVISIONAL:
- g_assert(!fixture->has_been_provisional);
- fixture->has_been_provisional = TRUE;
- break;
- case WEBKIT_LOAD_COMMITTED:
- g_assert(fixture->has_been_provisional);
- fixture->has_been_committed = TRUE;
- break;
- case WEBKIT_LOAD_FAILED:
- g_assert_not_reached();
- break;
- case WEBKIT_LOAD_FINISHED:
- g_assert(fixture->has_been_provisional);
- g_assert(fixture->has_been_committed);
- fixture->has_been_finished = TRUE;
- g_main_loop_quit(fixture->loop);
- break;
- default:
- break;
- }
-}
-
-static void load_wentback_status_changed_cb(GObject* object, GParamSpec* pspec, WebLoadingFixture* fixture)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status(WEBKIT_WEB_VIEW(object));
- char* uri_string;
- char* uri_string2;
-
- uri_string = get_uri_for_path("/test_loading_status");
- uri_string2 = get_uri_for_path("/test_loading_status2");
-
- switch(status) {
- case WEBKIT_LOAD_PROVISIONAL:
- g_assert_cmpstr(webkit_web_view_get_uri(fixture->webView), ==, uri_string2);
- break;
- case WEBKIT_LOAD_COMMITTED:
- g_assert_cmpstr(webkit_web_view_get_uri(fixture->webView), ==, uri_string);
- break;
- case WEBKIT_LOAD_FAILED:
- g_assert_not_reached();
- break;
- case WEBKIT_LOAD_FINISHED:
- g_assert_cmpstr(webkit_web_view_get_uri(fixture->webView), ==, uri_string);
- g_main_loop_quit(fixture->loop);
- break;
- default:
- break;
- }
-
- g_free(uri_string);
- g_free(uri_string2);
-}
-
-static void load_error_test(WebKitWebView* webview, WebKitWebFrame* frame, const char* uri, GError* error)
-{
- g_debug("Error: %s", error->message);
-}
-
-static void test_loading_goback(WebLoadingFixture* fixture, gconstpointer data)
-{
- char* uri_string;
-
- g_signal_connect(fixture->webView, "notify::load-status", G_CALLBACK(load_goback_status_changed_cb), fixture);
-
- g_signal_connect(fixture->webView, "load-error", G_CALLBACK(load_error_test), fixture);
-
- uri_string = get_uri_for_path("/test_loading_status");
- webkit_web_view_load_uri(fixture->webView, uri_string);
- g_free(uri_string);
-
- g_main_loop_run(fixture->loop);
-
- fixture->has_been_provisional = FALSE;
- fixture->has_been_committed = FALSE;
- fixture->has_been_first_visually_non_empty_layout = FALSE;
- fixture->has_been_finished = FALSE;
- fixture->has_been_failed = FALSE;
- fixture->has_been_load_error = FALSE;
-
- uri_string = get_uri_for_path("/test_loading_status2");
- webkit_web_view_load_uri(fixture->webView, uri_string);
- g_free(uri_string);
-
- g_main_loop_run(fixture->loop);
-
- g_signal_handlers_disconnect_by_func(fixture->webView, load_goback_status_changed_cb, fixture);
-
- fixture->has_been_provisional = FALSE;
- fixture->has_been_committed = FALSE;
- fixture->has_been_first_visually_non_empty_layout = FALSE;
- fixture->has_been_finished = FALSE;
- fixture->has_been_failed = FALSE;
- fixture->has_been_load_error = FALSE;
-
- g_signal_connect(fixture->webView, "notify::load-status", G_CALLBACK(load_wentback_status_changed_cb), fixture);
- webkit_web_view_go_back(fixture->webView);
-
- g_main_loop_run(fixture->loop);
-
- g_signal_handlers_disconnect_by_func(fixture->webView, load_wentback_status_changed_cb, fixture);
-}
-
-int main(int argc, char** argv)
-{
- SoupServer* server;
-
- gtk_test_init(&argc, &argv, NULL);
- // Get rid of runtime warnings about deprecated properties and signals, since they break the tests.
- g_setenv("G_ENABLE_DIAGNOSTIC", "0", TRUE);
-
- server = soup_server_new(SOUP_SERVER_PORT, 0, NULL);
- soup_server_run_async(server);
-
- soup_server_add_handler(server, NULL, server_callback, NULL, NULL);
-
- base_uri = soup_uri_new("http://127.0.0.1/");
- soup_uri_set_port(base_uri, soup_server_get_port(server));
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add("/webkit/loading/status",
- WebLoadingFixture, NULL,
- web_loading_fixture_setup,
- test_loading_status,
- web_loading_fixture_teardown);
- g_test_add("/webkit/loading/error",
- WebLoadingFixture, NULL,
- web_loading_fixture_setup,
- test_loading_error,
- web_loading_fixture_teardown);
- g_test_add("/webkit/loading/cancelled",
- WebLoadingFixture, NULL,
- web_loading_fixture_setup,
- test_loading_cancelled,
- web_loading_fixture_teardown);
- g_test_add("/webkit/loading/goback",
- WebLoadingFixture, NULL,
- web_loading_fixture_setup,
- test_loading_goback,
- web_loading_fixture_teardown);
- return g_test_run();
-}
-
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testmimehandling.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testmimehandling.c
deleted file mode 100644
index 82568caf2..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testmimehandling.c
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2009 Jan Michael Alonzo
- * Copyright (C) 2009 Gustavo Noronha Silva
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "test_utils.h"
-
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <libsoup/soup.h>
-#include <string.h>
-#include <webkit/webkit.h>
-#include <unistd.h>
-
-GMainLoop* loop;
-SoupSession *session;
-char* base_uri;
-
-/* For real request testing */
-static void
-server_callback(SoupServer *server, SoupMessage *msg,
- const char *path, GHashTable *query,
- SoupClientContext *context, gpointer data)
-{
- if (msg->method != SOUP_METHOD_GET) {
- soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED);
- return;
- }
-
- soup_message_set_status(msg, SOUP_STATUS_OK);
-
- /* PDF */
- if (g_str_equal(path, "/pdf")) {
- char* contents;
- gsize length;
- GError* error = NULL;
-
- g_file_get_contents("test.pdf", &contents, &length, &error);
- g_assert(!error);
-
- soup_message_body_append(msg->response_body, SOUP_MEMORY_TAKE, contents, length);
- } else if (g_str_equal(path, "/html")) {
- char* contents;
- gsize length;
- GError* error = NULL;
-
- g_file_get_contents("test.html", &contents, &length, &error);
- g_assert(!error);
-
- soup_message_body_append(msg->response_body, SOUP_MEMORY_TAKE, contents, length);
- } else if (g_str_equal(path, "/text")) {
- char* contents;
- gsize length;
- GError* error = NULL;
-
- soup_message_headers_append(msg->response_headers, "Content-Disposition", "attachment; filename=test.txt");
-
- g_file_get_contents("test.txt", &contents, &length, &error);
- g_assert(!error);
-
- soup_message_body_append(msg->response_body, SOUP_MEMORY_TAKE, contents, length);
- }
-
- soup_message_body_complete(msg->response_body);
-}
-
-static void idle_quit_loop_cb(WebKitWebView* web_view, GParamSpec* pspec, gpointer data)
-{
- if (webkit_web_view_get_load_status(web_view) == WEBKIT_LOAD_FINISHED ||
- webkit_web_view_get_load_status(web_view) == WEBKIT_LOAD_FAILED)
- g_main_loop_quit(loop);
-}
-
-static gboolean mime_type_policy_decision_requested_cb(WebKitWebView* view, WebKitWebFrame* frame,
- WebKitNetworkRequest* request, const char* mime_type,
- WebKitWebPolicyDecision* decision, gpointer data)
-{
- char* type = (char*)data;
-
- if (g_str_equal(type, "pdf")) {
- g_assert_cmpstr(mime_type, ==, "application/pdf");
- g_assert(!webkit_web_view_can_show_mime_type(view, mime_type));
- } else if (g_str_equal(type, "html")) {
- g_assert_cmpstr(mime_type, ==, "text/html");
- g_assert(webkit_web_view_can_show_mime_type(view, mime_type));
- } else if (g_str_equal(type, "text")) {
- WebKitNetworkResponse* response = webkit_web_frame_get_network_response(frame);
- SoupMessage* message = webkit_network_response_get_message(response);
- char* disposition;
-
- g_assert(message);
- soup_message_headers_get_content_disposition(message->response_headers,
- &disposition, NULL);
- g_object_unref(response);
-
- g_assert_cmpstr(disposition, ==, "attachment");
- g_free(disposition);
-
- g_assert_cmpstr(mime_type, ==, "text/plain");
- g_assert(webkit_web_view_can_show_mime_type(view, mime_type));
- }
-
- g_free(type);
-
- return FALSE;
-}
-
-static void testRemoteMimeType(const void* data)
-{
- const char* name = (const char*) data;
- WebKitWebView* view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(G_OBJECT(view));
-
- loop = g_main_loop_new(NULL, TRUE);
-
- g_object_connect(G_OBJECT(view),
- "signal::notify::load-status", idle_quit_loop_cb, NULL,
- "signal::mime-type-policy-decision-requested", mime_type_policy_decision_requested_cb, g_strdup(name),
- NULL);
-
- char* effective_uri = g_strdup_printf("%s%s", base_uri, name);
- webkit_web_view_load_uri(view, effective_uri);
- g_free(effective_uri);
-
- g_main_loop_run(loop);
-
- g_object_unref(view);
-}
-
-static void testLocalMimeType(const void* data)
-{
- const char* typeName = (const char*) data;
- WebKitWebView* view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(G_OBJECT(view));
-
- loop = g_main_loop_new(NULL, TRUE);
-
- g_object_connect(G_OBJECT(view),
- "signal::notify::load-status", idle_quit_loop_cb, NULL,
- "signal::mime-type-policy-decision-requested", mime_type_policy_decision_requested_cb, g_strdup(typeName),
- NULL);
-
- gchar* filename = g_strdup_printf("test.%s", typeName);
- GFile* file = g_file_new_for_path(filename);
- g_free(filename);
-
- gchar* fileURI = g_file_get_uri(file);
- g_object_unref(file);
-
- webkit_web_view_load_uri(view, fileURI);
- g_free(fileURI);
-
- g_main_loop_run(loop);
- g_object_unref(view);
-}
-
-int main(int argc, char** argv)
-{
- SoupServer* server;
- SoupURI* soup_uri;
-
- gtk_test_init(&argc, &argv, NULL);
-
- // Get rid of runtime warnings about deprecated properties and signals, since they break the tests.
- g_setenv("G_ENABLE_DIAGNOSTIC", "0", TRUE);
-
- /* Hopefully make test independent of the path it's called from. */
- testutils_relative_chdir("Tools/TestWebKitAPI/Tests/WebKitGtk/resources/test.html", argv[0]);
-
- server = soup_server_new(SOUP_SERVER_PORT, 0, NULL);
- soup_server_run_async(server);
-
- soup_server_add_handler(server, NULL, server_callback, NULL, NULL);
-
- soup_uri = soup_uri_new("http://127.0.0.1/");
- soup_uri_set_port(soup_uri, soup_server_get_port(server));
-
- base_uri = soup_uri_to_string(soup_uri, FALSE);
- soup_uri_free(soup_uri);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_data_func("/webkit/mime/remote-PDF", "pdf", testRemoteMimeType);
- g_test_add_data_func("/webkit/mime/remote-HTML", "html", testRemoteMimeType);
- g_test_add_data_func("/webkit/mime/remote-TEXT", "text", testRemoteMimeType);
- g_test_add_data_func("/webkit/mime/local-PDF", "pdf", testLocalMimeType);
- g_test_add_data_func("/webkit/mime/local-HTML", "html", testLocalMimeType);
- g_test_add_data_func("/webkit/mime/local-TEXT", "text", testLocalMimeType);
-
- return g_test_run();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkrequest.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkrequest.c
deleted file mode 100644
index 1b2c90f2d..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkrequest.c
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2009 Gustavo Noronha Silva
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <unistd.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <stdlib.h>
-#include <webkit/webkit.h>
-
-static void test_network_request_create_destroy()
-{
- WebKitNetworkRequest* request;
- SoupMessage* message;
-
- /* Test creation with URI */
- request = WEBKIT_NETWORK_REQUEST(g_object_new(WEBKIT_TYPE_NETWORK_REQUEST, "uri", "http://debian.org/", NULL));
- g_assert(WEBKIT_IS_NETWORK_REQUEST(request));
- message = webkit_network_request_get_message(request);
- g_assert(!message);
- g_object_unref(request);
-
- /* Test creation with SoupMessage */
- message = soup_message_new("GET", "http://debian.org/");
- request = WEBKIT_NETWORK_REQUEST(g_object_new(WEBKIT_TYPE_NETWORK_REQUEST, "message", message, NULL));
- g_assert(WEBKIT_IS_NETWORK_REQUEST(request));
- g_assert_cmpint(G_OBJECT(message)->ref_count, ==, 2);
- g_object_unref(request);
- g_assert_cmpint(G_OBJECT(message)->ref_count, ==, 1);
- g_object_unref(message);
-
- /* Test creation with both SoupMessage and URI */
- message = soup_message_new("GET", "http://debian.org/");
- request = WEBKIT_NETWORK_REQUEST(g_object_new(WEBKIT_TYPE_NETWORK_REQUEST, "message", message, "uri", "http://gnome.org/", NULL));
- g_assert(WEBKIT_IS_NETWORK_REQUEST(request));
- g_assert_cmpint(G_OBJECT(message)->ref_count, ==, 2);
- g_assert_cmpstr(webkit_network_request_get_uri(request), ==, "http://gnome.org/");
- g_object_unref(request);
- g_assert_cmpint(G_OBJECT(message)->ref_count, ==, 1);
- g_object_unref(message);
-}
-
-static void test_network_request_properties()
-{
- WebKitNetworkRequest* request;
- SoupMessage* message;
- gchar* soupURI;
-
- /* Test URI is set correctly when creating with URI */
- request = webkit_network_request_new("http://debian.org/");
- g_assert(WEBKIT_IS_NETWORK_REQUEST(request));
- g_assert_cmpstr(webkit_network_request_get_uri(request), ==, "http://debian.org/");
- g_object_unref(request);
-
- /* Test URI is set correctly when creating with Message */
- message = soup_message_new("GET", "http://debian.org/");
- request = WEBKIT_NETWORK_REQUEST(g_object_new(WEBKIT_TYPE_NETWORK_REQUEST, "message", message, NULL));
- g_assert(WEBKIT_IS_NETWORK_REQUEST(request));
- g_object_unref(message);
-
- message = webkit_network_request_get_message(request);
- soupURI = soup_uri_to_string(soup_message_get_uri(message), FALSE);
- g_assert_cmpstr(soupURI, ==, "http://debian.org/");
- g_free(soupURI);
-
- g_assert_cmpstr(webkit_network_request_get_uri(request), ==, "http://debian.org/");
- g_object_unref(request);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/networkrequest/createdestroy", test_network_request_create_destroy);
- g_test_add_func("/webkit/networkrequest/properties", test_network_request_properties);
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkresponse.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkresponse.c
deleted file mode 100644
index b806aa111..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkresponse.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2009 Gustavo Noronha Silva
- * Copyright (C) 2009 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <unistd.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <stdlib.h>
-#include <webkit/webkit.h>
-
-static void test_network_response_create_destroy()
-{
- WebKitNetworkResponse* response;
- SoupMessage* message;
-
- /* Test creation with URI */
- response = WEBKIT_NETWORK_RESPONSE(g_object_new(WEBKIT_TYPE_NETWORK_RESPONSE, "uri", "http://debian.org/", NULL));
- g_assert(WEBKIT_IS_NETWORK_RESPONSE(response));
- message = webkit_network_response_get_message(response);
- g_assert(!message);
- g_object_unref(response);
-
- /* Test creation with SoupMessage */
- message = soup_message_new("GET", "http://debian.org/");
- response = WEBKIT_NETWORK_RESPONSE(g_object_new(WEBKIT_TYPE_NETWORK_RESPONSE, "message", message, NULL));
- g_assert(WEBKIT_IS_NETWORK_RESPONSE(response));
- g_assert_cmpint(G_OBJECT(message)->ref_count, ==, 2);
- g_object_unref(response);
- g_assert_cmpint(G_OBJECT(message)->ref_count, ==, 1);
- g_object_unref(message);
-
- /* Test creation with both SoupMessage and URI */
- message = soup_message_new("GET", "http://debian.org/");
- response = WEBKIT_NETWORK_RESPONSE(g_object_new(WEBKIT_TYPE_NETWORK_RESPONSE, "message", message, "uri", "http://gnome.org/", NULL));
- g_assert(WEBKIT_IS_NETWORK_RESPONSE(response));
- g_assert_cmpint(G_OBJECT(message)->ref_count, ==, 2);
- g_assert_cmpstr(webkit_network_response_get_uri(response), ==, "http://gnome.org/");
- g_object_unref(response);
- g_assert_cmpint(G_OBJECT(message)->ref_count, ==, 1);
- g_object_unref(message);
-}
-
-static void test_network_response_properties()
-{
- WebKitNetworkResponse* response;
- SoupMessage* message;
- gchar* soupURI;
-
- /* Test URI is set correctly when creating with URI */
- response = webkit_network_response_new("http://debian.org/");
- g_assert(WEBKIT_IS_NETWORK_RESPONSE(response));
- g_assert_cmpstr(webkit_network_response_get_uri(response), ==, "http://debian.org/");
- g_object_unref(response);
-
- /* Test URI is set correctly when creating with Message */
- message = soup_message_new("GET", "http://debian.org/");
- response = WEBKIT_NETWORK_RESPONSE(g_object_new(WEBKIT_TYPE_NETWORK_RESPONSE, "message", message, NULL));
- g_assert(WEBKIT_IS_NETWORK_RESPONSE(response));
- g_object_unref(message);
-
- message = webkit_network_response_get_message(response);
- soupURI = soup_uri_to_string(soup_message_get_uri(message), FALSE);
- g_assert_cmpstr(soupURI, ==, "http://debian.org/");
- g_free(soupURI);
-
- g_assert_cmpstr(webkit_network_response_get_uri(response), ==, "http://debian.org/");
- g_object_unref(response);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/networkresponse/createdestroy", test_network_response_create_destroy);
- g_test_add_func("/webkit/networkresponse/properties", test_network_response_properties);
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebbackforwardlist.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebbackforwardlist.c
deleted file mode 100644
index 7782d4070..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebbackforwardlist.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Copyright (C) 2008 Holger Hans Peter Freyther
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-static void test_webkit_web_history_item_lifetime(void)
-{
- WebKitWebView* webView;
- WebKitWebBackForwardList* backForwardList;
- WebKitWebHistoryItem* currentItem;
- WebKitWebHistoryItem* forwardItem;
- WebKitWebHistoryItem* backItem;
- WebKitWebHistoryItem* nthItem;
- WebKitWebHistoryItem* item1;
- WebKitWebHistoryItem* item2;
- WebKitWebHistoryItem* item3;
- WebKitWebHistoryItem* item4;
- GList* backList = NULL;
- GList* forwardList = NULL;
- g_test_bug("19898");
-
- webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- backForwardList = webkit_web_view_get_back_forward_list(webView);
- g_assert_cmpint(G_OBJECT(backForwardList)->ref_count, ==, 1);
-
- /* add test items */
- item1 = webkit_web_history_item_new_with_data("http://example.com/1/", "Site 1");
- webkit_web_back_forward_list_add_item(backForwardList, item1);
- g_object_unref(item1);
-
- item2 = webkit_web_history_item_new_with_data("http://example.com/2/", "Site 2");
- webkit_web_back_forward_list_add_item(backForwardList, item2);
- g_object_unref(item2);
-
- item3 = webkit_web_history_item_new_with_data("http://example.com/3/", "Site 3");
- webkit_web_back_forward_list_add_item(backForwardList, item3);
- g_object_unref(item3);
-
- item4 = webkit_web_history_item_new_with_data("http://example.com/4/", "Site 4");
- webkit_web_back_forward_list_add_item(backForwardList, item4);
- g_object_unref(item4);
-
- /* make sure these functions don't add unnecessary ref to the history item */
- backItem = webkit_web_back_forward_list_get_back_item(backForwardList);
- g_object_ref(backItem);
- g_assert_cmpint(G_OBJECT(backItem)->ref_count, ==, 2);
- g_object_unref(backItem);
- g_assert_cmpint(G_OBJECT(backItem)->ref_count, ==, 1);
-
- currentItem = webkit_web_back_forward_list_get_current_item(backForwardList);
- g_object_ref(currentItem);
- g_assert_cmpint(G_OBJECT(currentItem)->ref_count, ==, 2);
- g_object_unref(currentItem);
- g_assert_cmpint(G_OBJECT(currentItem)->ref_count, ==, 1);
-
- webkit_web_back_forward_list_go_to_item(backForwardList, item2);
- forwardItem = webkit_web_back_forward_list_get_forward_item(backForwardList);
- g_object_ref(forwardItem);
- g_assert_cmpint(G_OBJECT(forwardItem)->ref_count, ==, 2);
- g_object_unref(forwardItem);
- g_assert_cmpint(G_OBJECT(forwardItem)->ref_count, ==, 1);
-
- nthItem = webkit_web_back_forward_list_get_nth_item(backForwardList, 1);
- g_object_ref(nthItem);
- g_assert_cmpint(G_OBJECT(nthItem)->ref_count, ==, 2);
- g_object_unref(nthItem);
- g_assert_cmpint(G_OBJECT(nthItem)->ref_count, ==, 1);
-
- backList = webkit_web_back_forward_list_get_back_list_with_limit(backForwardList, 5);
- for (; backList; backList = backList->next)
- g_assert_cmpint(G_OBJECT(backList->data)->ref_count, ==, 1);
-
- forwardList = webkit_web_back_forward_list_get_forward_list_with_limit(backForwardList, 5);
- for (; forwardList; forwardList = forwardList->next)
- g_assert_cmpint(G_OBJECT(forwardList->data)->ref_count, ==, 1);
-
- g_list_free(forwardList);
- g_list_free(backList);
- g_assert_cmpint(G_OBJECT(item1)->ref_count, ==, 1);
- g_assert_cmpint(G_OBJECT(item2)->ref_count, ==, 1);
- g_assert_cmpint(G_OBJECT(item3)->ref_count, ==, 1);
- g_assert_cmpint(G_OBJECT(item4)->ref_count, ==, 1);
- g_assert_cmpint(G_OBJECT(backForwardList)->ref_count, ==, 1);
- g_object_unref(webView);
-}
-
-static void test_webkit_web_back_forward_list_order(void)
-{
- WebKitWebView* webView;
- WebKitWebBackForwardList* webBackForwardList;
- WebKitWebHistoryItem* item1;
- WebKitWebHistoryItem* item2;
- WebKitWebHistoryItem* item3;
- WebKitWebHistoryItem* item4;
- WebKitWebHistoryItem* currentItem;
- GList* backList = NULL;
- GList* forwardList = NULL;
- g_test_bug("22694");
-
- webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
-
- webkit_web_view_set_maintains_back_forward_list(webView, TRUE);
- webBackForwardList = webkit_web_view_get_back_forward_list(webView);
- g_assert(webBackForwardList);
-
- // Check that there is no item.
- g_assert(!webkit_web_back_forward_list_get_current_item(webBackForwardList));
- g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 0);
- g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 0);
- g_assert(!webkit_web_view_can_go_forward(webView));
- g_assert(!webkit_web_view_can_go_back(webView));
-
- // Add a new items
- item1 = webkit_web_history_item_new_with_data("http://example.com/1/", "Site 1");
- webkit_web_back_forward_list_add_item(webBackForwardList, item1);
- g_object_unref(item1);
- g_assert(webkit_web_back_forward_list_contains_item(webBackForwardList, item1));
-
- item2 = webkit_web_history_item_new_with_data("http://example.com/2/", "Site 2");
- webkit_web_back_forward_list_add_item(webBackForwardList, item2);
- g_object_unref(item2);
- g_assert(webkit_web_back_forward_list_contains_item(webBackForwardList, item2));
-
- item3 = webkit_web_history_item_new_with_data("http://example.com/3/", "Site 3");
- webkit_web_back_forward_list_add_item(webBackForwardList, item3);
- g_object_unref(item3);
- g_assert(webkit_web_back_forward_list_contains_item(webBackForwardList, item3));
-
- item4 = webkit_web_history_item_new_with_data("http://example.com/4/", "Site 4");
- webkit_web_back_forward_list_add_item(webBackForwardList, item4);
- g_object_unref(item4);
- g_assert(webkit_web_back_forward_list_contains_item(webBackForwardList, item4));
-
- // check the back list order
- backList = webkit_web_back_forward_list_get_back_list_with_limit(webBackForwardList, 5);
- g_assert(backList);
-
- currentItem = WEBKIT_WEB_HISTORY_ITEM(backList->data);
- g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/3/");
- g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Site 3");
- backList = backList->next;
-
- currentItem = WEBKIT_WEB_HISTORY_ITEM(backList->data);
- g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/2/");
- g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Site 2");
- backList = backList->next;
-
- currentItem = WEBKIT_WEB_HISTORY_ITEM(backList->data);
- g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/1/");
- g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Site 1");
- g_list_free(backList);
-
- // check the forward list order
- g_assert(webkit_web_view_go_to_back_forward_item(webView, item1));
- forwardList = webkit_web_back_forward_list_get_forward_list_with_limit(webBackForwardList,5);
- g_assert(forwardList);
-
- currentItem = WEBKIT_WEB_HISTORY_ITEM(forwardList->data);
- g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/4/");
- g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Site 4");
- forwardList = forwardList->next;
-
- currentItem = WEBKIT_WEB_HISTORY_ITEM(forwardList->data);
- g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/3/");
- g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Site 3");
- forwardList = forwardList->next;
-
- currentItem = WEBKIT_WEB_HISTORY_ITEM(forwardList->data);
- g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/2/");
- g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Site 2");
-
- g_list_free(forwardList);
- g_object_unref(webView);
-}
-
-static void test_webkit_web_back_forward_list_add_item(void)
-{
- WebKitWebView* webView;
- WebKitWebBackForwardList* webBackForwardList;
- WebKitWebHistoryItem* addItem1;
- WebKitWebHistoryItem* addItem2;
- WebKitWebHistoryItem* backItem;
- WebKitWebHistoryItem* currentItem;
- g_test_bug("22988");
-
- webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
-
- webkit_web_view_set_maintains_back_forward_list(webView, TRUE);
- webBackForwardList = webkit_web_view_get_back_forward_list(webView);
- g_assert(webBackForwardList);
-
- // Check that there is no item.
- g_assert(!webkit_web_back_forward_list_get_current_item(webBackForwardList));
- g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 0);
- g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 0);
- g_assert(!webkit_web_view_can_go_forward(webView));
- g_assert(!webkit_web_view_can_go_back(webView));
-
- // Add a new item
- addItem1 = webkit_web_history_item_new_with_data("http://example.com/", "Added site");
- webkit_web_back_forward_list_add_item(webBackForwardList, addItem1);
- g_object_unref(addItem1);
- g_assert(webkit_web_back_forward_list_contains_item(webBackForwardList, addItem1));
-
- // Check that the added item is the current item.
- currentItem = webkit_web_back_forward_list_get_current_item(webBackForwardList);
- g_assert(currentItem);
- g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 0);
- g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 0);
- g_assert(!webkit_web_view_can_go_forward(webView));
- g_assert(!webkit_web_view_can_go_back(webView));
- g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/");
- g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Added site");
-
- // Add another item.
- addItem2 = webkit_web_history_item_new_with_data("http://example.com/2/", "Added site 2");
- webkit_web_back_forward_list_add_item(webBackForwardList, addItem2);
- g_object_unref(addItem2);
- g_assert(webkit_web_back_forward_list_contains_item(webBackForwardList, addItem2));
-
- // Check that the added item is new current item.
- currentItem = webkit_web_back_forward_list_get_current_item(webBackForwardList);
- g_assert(currentItem);
- g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 0);
- g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 1);
- g_assert(!webkit_web_view_can_go_forward(webView));
- g_assert(webkit_web_view_can_go_back(webView));
- g_assert_cmpstr(webkit_web_history_item_get_uri(currentItem), ==, "http://example.com/2/");
- g_assert_cmpstr(webkit_web_history_item_get_title(currentItem), ==, "Added site 2");
-
- backItem = webkit_web_back_forward_list_get_back_item(webBackForwardList);
- g_assert(backItem);
- g_assert_cmpstr(webkit_web_history_item_get_uri(backItem), ==, "http://example.com/");
- g_assert_cmpstr(webkit_web_history_item_get_title(backItem), ==, "Added site");
-
- // Go to the first added item.
- g_assert(webkit_web_view_go_to_back_forward_item(webView, addItem1));
- g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 1);
- g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 0);
- g_assert(webkit_web_view_can_go_forward(webView));
- g_assert(!webkit_web_view_can_go_back(webView));
-
- g_object_unref(webView);
-}
-
-static void test_webkit_web_back_forward_list_clear(void)
-{
- WebKitWebView* webView;
- WebKitWebBackForwardList* webBackForwardList;
- WebKitWebHistoryItem* addItem;
- g_test_bug("36173");
-
- webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
-
- webBackForwardList = webkit_web_view_get_back_forward_list(webView);
- g_assert(webBackForwardList);
-
- // Check that there is no item.
- g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 0);
- g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 0);
- g_assert(!webkit_web_back_forward_list_get_current_item(webBackForwardList));
- g_assert(!webkit_web_view_can_go_forward(webView));
- g_assert(!webkit_web_view_can_go_back(webView));
-
- // Check that clearing the empty list does not modify counters
- webkit_web_back_forward_list_clear(webBackForwardList);
- g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 0);
- g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 0);
- g_assert(!webkit_web_back_forward_list_get_current_item(webBackForwardList));
- g_assert(!webkit_web_view_can_go_forward(webView));
- g_assert(!webkit_web_view_can_go_back(webView));
-
- // Add a new item
- addItem = webkit_web_history_item_new_with_data("http://example.com/", "Added site");
- webkit_web_back_forward_list_add_item(webBackForwardList, addItem);
- g_object_unref(addItem);
- g_assert(webkit_web_back_forward_list_contains_item(webBackForwardList, addItem));
-
- // Check that after clearing the list the added item is no longer in the list
- webkit_web_back_forward_list_clear(webBackForwardList);
- g_assert(!webkit_web_back_forward_list_contains_item(webBackForwardList, addItem));
-
- // Check that after clearing it, the list is empty
- g_assert_cmpint(webkit_web_back_forward_list_get_forward_length(webBackForwardList), ==, 0);
- g_assert_cmpint(webkit_web_back_forward_list_get_back_length(webBackForwardList), ==, 0);
- g_assert(!webkit_web_back_forward_list_get_current_item(webBackForwardList));
- g_assert(!webkit_web_view_can_go_forward(webView));
- g_assert(!webkit_web_view_can_go_back(webView));
-
- g_object_unref(webView);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/webbackforwardlist/add_item", test_webkit_web_back_forward_list_add_item);
- g_test_add_func("/webkit/webbackforwardlist/list_order", test_webkit_web_back_forward_list_order);
- g_test_add_func("/webkit/webhistoryitem/lifetime", test_webkit_web_history_item_lifetime);
- g_test_add_func("/webkit/webbackforwardlist/clear", test_webkit_web_back_forward_list_clear);
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebdatasource.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebdatasource.c
deleted file mode 100644
index 056625744..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebdatasource.c
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (C) 2009 Jan Michael Alonzo
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-static const gshort defaultTimeout = 10;
-guint waitTimer;
-gboolean shouldWait;
-
-typedef struct {
- WebKitWebView* webView;
- WebKitWebFrame* mainFrame;
-} WebDataSourceFixture;
-
-static void test_webkit_web_data_source_get_initial_request()
-{
- WebKitWebView* view;
- WebKitWebFrame* frame;
- WebKitWebDataSource* dataSource;
- WebKitNetworkRequest* initialRequest;
-
- view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(view);
- frame = webkit_web_view_get_main_frame(view);
-
- WebKitNetworkRequest* request = webkit_network_request_new("http://www.google.com");
- webkit_web_frame_load_request(frame, request);
- g_object_unref(request);
-
- dataSource = webkit_web_frame_get_provisional_data_source(frame);
- g_assert(dataSource);
- initialRequest = webkit_web_data_source_get_initial_request(dataSource);
- g_assert_cmpstr(webkit_network_request_get_uri(initialRequest), ==, "http://www.google.com/");
-
- g_object_unref(view);
-}
-
-static void notify_load_status_unreachable_cb(WebKitWebView* view, GParamSpec* pspec, GMainLoop* loop)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status (view);
- WebKitWebFrame* frame = webkit_web_view_get_main_frame(view);
-
- g_assert(status != WEBKIT_LOAD_FINISHED);
-
- if (status != WEBKIT_LOAD_FAILED)
- return;
-
- WebKitWebDataSource* datasource = webkit_web_frame_get_data_source(frame);
-
- g_assert_cmpstr("http://this.host.does.not.exist/doireallyexist.html", ==,
- webkit_web_data_source_get_unreachable_uri(datasource));
-
- g_main_loop_quit(loop);
-}
-
-static void notify_load_status_cb(WebKitWebView* view, GParamSpec* pspec, GMainLoop* loop)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status (view);
- WebKitWebFrame* frame = webkit_web_view_get_main_frame(view);
- WebKitWebDataSource* dataSource = webkit_web_frame_get_data_source(frame);
-
- if (status == WEBKIT_LOAD_COMMITTED) {
- g_assert(webkit_web_data_source_is_loading(dataSource));
- return;
- }
- else if (status != WEBKIT_LOAD_FINISHED)
- return;
-
- /* Test get_request */
- g_test_message("Testing webkit_web_data_source_get_request");
- WebKitNetworkRequest* request = webkit_web_data_source_get_request(dataSource);
- g_assert_cmpstr(webkit_network_request_get_uri(request), ==, "http://www.webkit.org/");
-
- /* Test get_main_resource */
- g_test_message("Testing webkit_web_data_source_get_main_resource");
- WebKitWebResource* resource = webkit_web_data_source_get_main_resource(dataSource);
- g_assert_cmpstr("text/html", ==, webkit_web_resource_get_mime_type(resource));
- g_assert_cmpstr("http://www.webkit.org/", ==, webkit_web_resource_get_uri(resource));
-
- /* Test get_data. We just test if data has certain size for the mean time */
- g_test_message("Testing webkit_web_data_source_get_data has certain size");
- GString* data = webkit_web_data_source_get_data(dataSource);
- g_assert(data->len > 100);
-
- /* FIXME: Add test for get_encoding */
-
- g_main_loop_quit(loop);
-}
-
-static gboolean wait_timer_fired(GMainLoop* loop)
-{
- waitTimer = 0;
- g_main_loop_quit(loop);
-
- return FALSE;
-}
-
-static void test_webkit_web_data_source()
-{
- WebKitWebView* view;
- GMainLoop* loop;
-
- view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(view);
- loop = g_main_loop_new(NULL, TRUE);
- g_signal_connect(view, "notify::load-status", G_CALLBACK(notify_load_status_cb), loop);
- webkit_web_view_load_uri(view, "http://www.webkit.org");
-
- waitTimer = g_timeout_add_seconds(defaultTimeout, (GSourceFunc)wait_timer_fired, loop);
-
- g_main_loop_run(loop);
-
- if (waitTimer)
- g_source_remove(waitTimer);
-
- waitTimer = 0;
-
- g_main_loop_unref(loop);
- g_object_unref(view);
-}
-
-static void notify_load_status_lifetime_cb(WebKitWebView* view, GParamSpec* pspec, GMainLoop* loop)
-{
- WebKitLoadStatus status = webkit_web_view_get_load_status (view);
- WebKitWebFrame* frame = webkit_web_view_get_main_frame(view);
- WebKitWebDataSource* dataSource = webkit_web_frame_get_data_source(frame);
-
- if (status == WEBKIT_LOAD_COMMITTED) {
- g_assert(webkit_web_data_source_is_loading(dataSource));
- return;
- } else if (status != WEBKIT_LOAD_FINISHED)
- return;
-
- g_main_loop_quit(loop);
-}
-
-static void test_webkit_web_data_source_lifetime()
-{
- WebKitWebView* view;
- GMainLoop* loop;
-
- view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(view);
- loop = g_main_loop_new(NULL, TRUE);
- g_signal_connect(view, "notify::load-status", G_CALLBACK(notify_load_status_lifetime_cb), loop);
- webkit_web_view_load_uri(view, "http://www.webkit.org");
-
- waitTimer = g_timeout_add_seconds(defaultTimeout, (GSourceFunc)wait_timer_fired, loop);
-
- g_main_loop_run(loop);
-
- WebKitWebDataSource* dataSource = webkit_web_frame_get_data_source(webkit_web_view_get_main_frame(view));
- GList* subResources = webkit_web_data_source_get_subresources(dataSource);
- gint numberOfResources = g_list_length(subResources);
- g_list_free(subResources);
-
- g_assert_cmpint(webkit_web_view_get_load_status(view), ==, WEBKIT_LOAD_FINISHED);
-
- webkit_web_view_load_uri(view, "http://gnome.org");
-
- g_assert_cmpint(webkit_web_view_get_load_status(view), ==, WEBKIT_LOAD_PROVISIONAL);
-
- webkit_web_view_stop_loading(view);
-
- g_assert_cmpint(webkit_web_view_get_load_status(view), ==, WEBKIT_LOAD_FAILED);
-
- subResources = webkit_web_data_source_get_subresources(dataSource);
- g_assert_cmpint(numberOfResources, ==, g_list_length(subResources));
- g_list_free(subResources);
-
- if (waitTimer)
- g_source_remove(waitTimer);
-
- waitTimer = 0;
-
- g_main_loop_unref(loop);
- g_object_unref(view);
-}
-
-static void test_webkit_web_data_source_unreachable_uri()
-{
- /* FIXME: this test fails currently. */
- return;
-
- WebKitWebView* view;
- GMainLoop* loop;
-
- view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(view);
- loop = g_main_loop_new(NULL, TRUE);
- g_signal_connect(view, "notify::load-status", G_CALLBACK(notify_load_status_unreachable_cb), loop);
- webkit_web_view_load_uri(view, "http://this.host.does.not.exist/doireallyexist.html");
-
- waitTimer = g_timeout_add_seconds(defaultTimeout, (GSourceFunc)wait_timer_fired, loop);
-
- g_main_loop_run(loop);
-
- if (waitTimer)
- g_source_remove(waitTimer);
-
- waitTimer = 0;
-
- g_main_loop_unref(loop);
- g_object_unref(view);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_bug("24758");
- g_test_add_func("/webkit/webdatasource/get_initial_request",
- test_webkit_web_data_source_get_initial_request);
- g_test_add_func("/webkit/webdatasource/api",
- test_webkit_web_data_source);
- g_test_add_func("/webkit/webdatasource/unreachable_uri",
- test_webkit_web_data_source_unreachable_uri);
- g_test_add_func("/webkit/webdatasource/lifetime",
- test_webkit_web_data_source_lifetime);
-
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebframe.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebframe.c
deleted file mode 100644
index 1131873d4..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebframe.c
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2008 Holger Hans Peter Freyther
- * Copyright (C) 2009 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <unistd.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-static int numberOfFramesCreated = 0;
-
-static void createFrameSignalTestFrameCreatedCallback(WebKitWebView* webView, WebKitWebFrame* frame, gpointer data)
-{
- numberOfFramesCreated++;
-}
-
-static gboolean createFrameSignalTestTimeout(gpointer data)
-{
- g_assert_cmpint(numberOfFramesCreated, ==, 2);
- g_main_loop_quit((GMainLoop*) data);
- return FALSE;
-}
-
-static void test_webkit_web_frame_created_signal(void)
-{
- GtkWidget* webView;
- GtkWidget* window;
- GMainLoop* loop = g_main_loop_new(NULL, TRUE);
-
- window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-
- webView = webkit_web_view_new();
- g_signal_connect(webView, "frame-created", G_CALLBACK(createFrameSignalTestFrameCreatedCallback), loop);
-
- // We want to ensure that exactly two create-frame signals are
- // fired and no more, so we set a timeout here. There does not appear
- // to be a simple way via the API to figure out when all frames have
- // loaded.
- g_timeout_add(500, createFrameSignalTestTimeout, loop);
-
- gtk_container_add(GTK_CONTAINER(window), webView);
- gtk_widget_show(window);
- gtk_widget_show(webView);
-
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(webView),
- "<html><body>Frames!"
- "<iframe></iframe>"
- "<iframe></iframe>"
- "</body></html>",
- "text/html", "utf-8", "file://");
- g_main_loop_run(loop);
-}
-
-static void test_webkit_web_frame_create_destroy(void)
-{
- GtkWidget *webView;
- GtkWidget *window;
-
- g_test_bug("21837");
- webView = webkit_web_view_new();
- g_object_ref_sink(webView);
- g_assert_cmpint(G_OBJECT(webView)->ref_count, ==, 1);
- // This crashed with the original version
- g_object_unref(webView);
-
- g_test_bug("25042");
- window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- webView = webkit_web_view_new();
- gtk_container_add(GTK_CONTAINER(window), webView);
- gtk_widget_show(window);
- gtk_widget_show(webView);
- gtk_widget_destroy(webView);
-}
-
-static void test_webkit_web_frame_lifetime(void)
-{
- WebKitWebView* webView;
- WebKitWebFrame* webFrame;
- g_test_bug("21837");
-
- webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- g_assert_cmpint(G_OBJECT(webView)->ref_count, ==, 1);
- webFrame = webkit_web_view_get_main_frame(webView);
- g_assert_cmpint(G_OBJECT(webFrame)->ref_count, ==, 1);
-
- // Add dummy reference on the WebKitWebFrame to keep it alive
- g_object_ref(webFrame);
- g_assert_cmpint(G_OBJECT(webFrame)->ref_count, ==, 2);
-
- // This crashed with the original version
- g_object_unref(webView);
-
- // Make sure that the frame got deleted as well. We did this
- // by adding an extra ref on the WebKitWebFrame and we should
- // be the one holding the last reference.
- g_assert_cmpint(G_OBJECT(webFrame)->ref_count, ==, 1);
- g_object_unref(webFrame);
-}
-
-static gboolean print_requested_cb(WebKitWebView* webView, WebKitWebFrame* webFrame, GMainLoop* loop)
-{
- g_object_set_data(G_OBJECT(webView), "signal-handled", GINT_TO_POINTER(TRUE));
- g_main_loop_quit(loop);
- return TRUE;
-}
-
-static void print_timeout(GMainLoop* loop)
-{
- if (g_main_loop_is_running(loop))
- g_main_loop_quit(loop);
-}
-
-static void test_webkit_web_frame_printing(void)
-{
- WebKitWebView* webView;
-
- webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(webView);
- g_assert_cmpint(G_OBJECT(webView)->ref_count, ==, 1);
-
- webkit_web_view_load_string(webView,
- "<html><body><h1>WebKitGTK+!</h1></body></html>",
- "text/html",
- "utf-8",
- "file://");
-
- GMainLoop* loop = g_main_loop_new(NULL, TRUE);
-
- // Does javascript print() work correctly?
- g_signal_connect(webView, "print-requested",
- G_CALLBACK(print_requested_cb),
- loop);
-
- g_object_set_data(G_OBJECT(webView), "signal-handled", GINT_TO_POINTER(FALSE));
- webkit_web_view_execute_script (webView, "print();");
-
- // Give javascriptcore some time to process the print request, but
- // prepare a timeout to avoid it running forever in case the signal is
- // never emitted.
- g_timeout_add(1000, (GSourceFunc)print_timeout, loop);
- g_main_loop_run(loop);
-
- g_assert_cmpint(GPOINTER_TO_INT(g_object_get_data(G_OBJECT(webView), "signal-handled")), ==, TRUE);
-
- // Does printing directly to a file?
- GError *error = NULL;
- gchar* temporaryFilename = NULL;
- gint fd = g_file_open_tmp ("webkit-testwebframe-XXXXXX", &temporaryFilename, &error);
- close(fd);
-
- if (error) {
- g_critical("Failed to open a temporary file for writing: %s.", error->message);
- g_error_free(error);
- goto cleanup;
- }
-
- // We delete the file, so that we can easily figure out that the
- // file got printed;
- if (g_unlink(temporaryFilename) == -1) {
- g_warning("Failed to delete the temporary file: %s.\nThis may cause the test to be bogus.", g_strerror(errno));
- }
-
- WebKitWebFrame* webFrame = webkit_web_view_get_main_frame(webView);
- GtkPrintOperation* operation = gtk_print_operation_new();
- GtkPrintOperationAction action = GTK_PRINT_OPERATION_ACTION_EXPORT;
- GtkPrintOperationResult result;
-
- gtk_print_operation_set_export_filename(operation, temporaryFilename);
- result = webkit_web_frame_print_full (webFrame, operation, action, NULL);
-
- g_assert_cmpint(result, ==, GTK_PRINT_OPERATION_RESULT_APPLY);
- g_assert_cmpint(g_file_test(temporaryFilename, G_FILE_TEST_IS_REGULAR), ==, TRUE);
-
- g_unlink(temporaryFilename);
- g_object_unref(operation);
-cleanup:
- g_object_unref(webView);
- g_free(temporaryFilename);
-}
-
-static void test_webkit_web_frame_response()
-{
- WebKitWebFrame* frame = g_object_new(WEBKIT_TYPE_WEB_FRAME, NULL);
- WebKitNetworkResponse* response = webkit_web_frame_get_network_response(frame);
- g_assert(!response);
- g_object_unref(frame);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/webview/create_destroy", test_webkit_web_frame_create_destroy);
- g_test_add_func("/webkit/webview/frame-created_signal", test_webkit_web_frame_created_signal);
- g_test_add_func("/webkit/webframe/lifetime", test_webkit_web_frame_lifetime);
- g_test_add_func("/webkit/webview/printing", test_webkit_web_frame_printing);
- g_test_add_func("/webkit/webview/response", test_webkit_web_frame_response);
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebhistoryitem.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebhistoryitem.c
deleted file mode 100644
index 82e191c20..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebhistoryitem.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2009 Jan Michael Alonzo
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-typedef struct {
- WebKitWebHistoryItem* item;
-} WebHistoryItemFixture;
-
-static void web_history_item_fixture_setup(WebHistoryItemFixture* fixture,
- gconstpointer data)
-{
- fixture->item = webkit_web_history_item_new_with_data("http://example.com/", "Example1");
- g_assert_cmpint(G_OBJECT(fixture->item)->ref_count, == , 1);
- g_assert(fixture->item != NULL);
-}
-
-static void web_history_item_fixture_teardown(WebHistoryItemFixture* fixture,
- gconstpointer data)
-{
- g_assert(fixture->item != NULL);
- g_assert_cmpint(G_OBJECT(fixture->item)->ref_count, ==, 1);
-}
-
-static void test_webkit_web_history_item_get_data(WebHistoryItemFixture* fixture,
- gconstpointer data)
-{
- g_assert_cmpstr(webkit_web_history_item_get_title(fixture->item), ==, "Example1");
- g_assert_cmpstr(webkit_web_history_item_get_uri(fixture->item), ==, "http://example.com/");
-}
-
-static void test_webkit_web_history_item_alternate_title(WebHistoryItemFixture* fixture,
- gconstpointer data)
-{
- webkit_web_history_item_set_alternate_title(fixture->item, "Alternate title");
- g_assert_cmpstr(webkit_web_history_item_get_alternate_title(fixture->item), ==, "Alternate title");
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add("/webkit/webhistoryitem/get_data",
- WebHistoryItemFixture, 0, web_history_item_fixture_setup,
- test_webkit_web_history_item_get_data, web_history_item_fixture_teardown);
- g_test_add("/webkit/webhistoryitem/alternate_title",
- WebHistoryItemFixture, 0, web_history_item_fixture_setup,
- test_webkit_web_history_item_alternate_title, web_history_item_fixture_teardown);
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebinspector.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebinspector.c
deleted file mode 100644
index a74382ff3..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebinspector.c
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (C) 2012 Gustavo Noronha Silva <gns@gnome.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "test_utils.h"
-
-#include <string.h>
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-GMainLoop *loop;
-GtkWidget *window;
-
-static gboolean quitLoop(gpointer data)
-{
- g_main_loop_quit(loop);
- return TRUE;
-}
-
-/* Ignore simple translation-related messages and upgrade other
- * messages to warnings.
- */
-static gboolean consoleMessageCallback(WebKitWebView* webView, const char* message, unsigned int line, const char* sourceId)
-{
- if (strstr(message, "Localized string") || strstr(message, "Protocol Error: the message is for non-existing domain 'Profiler'") ||
- strstr(message, "Didn't find a TreeElement for a representedObject"))
- return TRUE;
-
- g_warning("Console: %s @%d: %s\n", sourceId, line, message);
- return TRUE;
-}
-
-static WebKitWebView* inspectElementCallback(WebKitWebInspector *inspector, WebKitWebView *inspectedWebView, int *timesElementInspected)
-{
- *timesElementInspected = *timesElementInspected + 1;
-
- window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-
- GtkWidget *newWebView = webkit_web_view_new();
- gtk_container_add(GTK_CONTAINER(window), newWebView);
-
- g_signal_connect(newWebView, "console-message",
- G_CALLBACK(consoleMessageCallback), NULL);
-
- return WEBKIT_WEB_VIEW(newWebView);
-}
-
-static gboolean closeInspector(WebKitWebInspector *inspector, int *timesClosed)
-{
- *timesClosed = *timesClosed + 1;
-
- gtk_widget_destroy(window);
- return TRUE;
-}
-
-static gboolean showInspector(WebKitWebInspector *inspector, gpointer data)
-{
- g_idle_add(quitLoop, NULL);
- return TRUE;
-}
-
-static void loadFinished(WebKitWebView *webView, WebKitWebFrame *frame, gboolean *isLoadFinished)
-{
- *isLoadFinished = TRUE;
- if (g_main_loop_is_running(loop))
- g_main_loop_quit(loop);
-}
-
-static void test_webkit_web_inspector_close_and_inspect()
-{
- WebKitWebView *webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- loop = g_main_loop_new(NULL, TRUE);
-
- gboolean isLoadFinished = FALSE;
- g_signal_connect(webView, "load-finished", G_CALLBACK(loadFinished), &isLoadFinished);
- webkit_web_view_load_string(webView,
- "<html><body><p>woohoo</p></body></html>",
- "text/html", "UTF-8", "file://");
- if (!isLoadFinished)
- g_main_loop_run(loop);
-
- g_object_set(webkit_web_view_get_settings(webView), "enable-developer-extras", TRUE, NULL);
- WebKitWebInspector *inspector = webkit_web_view_get_inspector(webView);
-
- int timesElementInspected = 0;
- int timesClosed = 0;
- g_object_connect(inspector,
- "signal::inspect-web-view", G_CALLBACK(inspectElementCallback), &timesElementInspected,
- "signal::show-window", G_CALLBACK(showInspector), NULL,
- "signal::close-window", G_CALLBACK(closeInspector), &timesClosed,
- NULL);
-
- webkit_web_inspector_inspect_coordinates(inspector, 0.0, 0.0);
- g_assert_cmpint(timesElementInspected, ==, 1);
-
- g_main_loop_run(loop);
-
- webkit_web_inspector_close(inspector);
- g_assert_cmpint(timesClosed, ==, 1);
-
- webkit_web_inspector_inspect_coordinates(inspector, 0.0, 0.0);
- g_assert_cmpint(timesElementInspected, ==, 2);
-
- g_main_loop_run(loop);
-
- gtk_widget_destroy(GTK_WIDGET(webView));
- g_assert_cmpint(timesClosed, ==, 2);
-
- g_main_loop_unref(loop);
-}
-
-static void test_webkit_web_inspector_destroy_inspected_web_view()
-{
- WebKitWebView *webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- loop = g_main_loop_new(NULL, TRUE);
-
- gboolean isLoadFinished = FALSE;
- g_signal_connect(webView, "load-finished", G_CALLBACK(loadFinished), &isLoadFinished);
- webkit_web_view_load_string(webView,
- "<html><body><p>woohoo</p></body></html>",
- "text/html", "UTF-8", "file://");
- if (!isLoadFinished)
- g_main_loop_run(loop);
-
- g_object_set(webkit_web_view_get_settings(webView), "enable-developer-extras", TRUE, NULL);
- WebKitWebInspector *inspector = webkit_web_view_get_inspector(webView);
-
- int timesElementInspected = 0;
- int timesClosed = 0;
- g_object_connect(inspector,
- "signal::inspect-web-view", G_CALLBACK(inspectElementCallback), &timesElementInspected,
- "signal::show-window", G_CALLBACK(showInspector), NULL,
- "signal::close-window", G_CALLBACK(closeInspector), &timesClosed,
- NULL);
-
- webkit_web_inspector_inspect_coordinates(inspector, 0.0, 0.0);
- g_assert_cmpint(timesElementInspected, ==, 1);
-
- g_main_loop_run(loop);
-
- gtk_widget_destroy(GTK_WIDGET(webView));
- g_assert_cmpint(timesClosed, ==, 1);
-
- g_main_loop_unref(loop);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/webinspector/destroy-inspected-web-view", test_webkit_web_inspector_destroy_inspected_web_view);
- g_test_add_func("/webkit/webinspector/close-and-inspect", test_webkit_web_inspector_close_and_inspect);
-
- return g_test_run();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebplugindatabase.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebplugindatabase.c
deleted file mode 100644
index 652811b13..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebplugindatabase.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2010 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <errno.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-/* This function is not public, so we need an extern declaration */
-extern void webkit_web_settings_add_extra_plugin_directory(WebKitWebView* view, const gchar* directory);
-
-static void test_webkit_web_plugin_database_get_plugins()
-{
- WebKitWebView* view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- WebKitWebPluginDatabase* database;
- GSList* pluginList, *p;
- gboolean found = FALSE;
- gboolean enabled = FALSE;
-
- webkit_web_settings_add_extra_plugin_directory(view, TEST_PLUGIN_DIR);
- g_object_ref_sink(G_OBJECT(view));
-
- database = webkit_get_web_plugin_database();
- pluginList = webkit_web_plugin_database_get_plugins(database);
- for (p = pluginList; p; p = p->next) {
- WebKitWebPlugin* plugin = (WebKitWebPlugin*)p->data;
- if (!g_strcmp0(webkit_web_plugin_get_name(plugin), "WebKit Test PlugIn") &&
- !g_strcmp0(webkit_web_plugin_get_description(plugin), "Simple Netscape® plug-in that handles test content for WebKit")) {
- found = TRUE;
- enabled = webkit_web_plugin_get_enabled(plugin);
- webkit_web_plugin_set_enabled(plugin, FALSE);
- }
- }
- webkit_web_plugin_database_plugins_list_free(pluginList);
- g_assert(found);
- g_assert(enabled);
-
- webkit_web_plugin_database_refresh(database);
- pluginList = webkit_web_plugin_database_get_plugins(database);
-
- for (p = pluginList; p; p = p->next) {
- WebKitWebPlugin* plugin = (WebKitWebPlugin*)p->data;
- if (!g_strcmp0(webkit_web_plugin_get_name(plugin), "WebKit Test PlugIn") &&
- !g_strcmp0(webkit_web_plugin_get_description(plugin), "Simple Netscape® plug-in that handles test content for WebKit"))
- enabled = webkit_web_plugin_get_enabled(plugin);
- }
- webkit_web_plugin_database_plugins_list_free(pluginList);
- g_assert(!enabled);
-
- g_object_unref(view);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/webplugindatabase/getplugins", test_webkit_web_plugin_database_get_plugins);
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebresource.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebresource.c
deleted file mode 100644
index 35d09476d..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebresource.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * Copyright (C) 2009 Jan Michael Alonzo
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <libsoup/soup.h>
-#include <string.h>
-#include <webkit/webkit.h>
-
-#define INDEX_HTML "<html></html>"
-#define MAIN_HTML "<html><head><script language=\"javascript\" src=\"/javascript.js\"></script></head><body><h1>hah</h1></html>"
-#define JAVASCRIPT "function blah () { var a = 1; }"
-
-GMainLoop* loop;
-SoupSession *session;
-char *base_uri;
-WebKitWebResource* main_resource;
-WebKitWebResource* sub_resource;
-
-typedef struct {
- WebKitWebResource* webResource;
- WebKitWebView* webView;
-} WebResourceFixture;
-
-/* For real request testing */
-static void
-server_callback (SoupServer *server, SoupMessage *msg,
- const char *path, GHashTable *query,
- SoupClientContext *context, gpointer data)
-{
- if (msg->method != SOUP_METHOD_GET) {
- soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
- return;
- }
-
- soup_message_set_status (msg, SOUP_STATUS_OK);
-
- /* Redirect */
- if (g_str_equal (path, "/")) {
- soup_message_set_status (msg, SOUP_STATUS_MOVED_PERMANENTLY);
-
- soup_message_headers_append (msg->response_headers,
- "Location", "/index.html");
- } else if (g_str_equal (path, "/index.html")) {
- soup_message_body_append (msg->response_body,
- SOUP_MEMORY_COPY,
- INDEX_HTML,
- strlen (INDEX_HTML));
- } else if (g_str_equal (path, "/main.html")) {
- soup_message_body_append (msg->response_body,
- SOUP_MEMORY_COPY,
- MAIN_HTML,
- strlen (MAIN_HTML));
- } else if (g_str_equal (path, "/javascript.js")) {
- soup_message_body_append (msg->response_body,
- SOUP_MEMORY_COPY,
- JAVASCRIPT,
- strlen (JAVASCRIPT));
- }
-
-
- soup_message_body_complete (msg->response_body);
-}
-
-static void web_resource_fixture_setup(WebResourceFixture* fixture, gconstpointer data)
-{
- fixture->webView = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(fixture->webView);
- const gchar* webData = "<html></html>";
- fixture->webResource = webkit_web_resource_new(webData, strlen(webData), "http://example.com/", "text/html", "utf8", "Example.com");
- g_assert(fixture->webResource);
-}
-
-static void web_resource_fixture_teardown(WebResourceFixture* fixture, gconstpointer data)
-{
- g_assert(fixture->webResource);
- g_object_unref(fixture->webResource);
- g_object_unref(fixture->webView);
-}
-
-static void test_webkit_web_resource_get_url(WebResourceFixture* fixture, gconstpointer data)
-{
- gchar* url;
- g_object_get(G_OBJECT(fixture->webResource), "uri", &url, NULL);
- g_assert_cmpstr(url, ==, "http://example.com/");
- g_assert_cmpstr(webkit_web_resource_get_uri(fixture->webResource) ,==,"http://example.com/");
- g_free(url);
-}
-
-static void test_webkit_web_resource_get_data(WebResourceFixture* fixture, gconstpointer data)
-{
- GString* charData = webkit_web_resource_get_data(fixture->webResource);
- g_assert_cmpstr(charData->str, ==, "<html></html>");
-}
-
-static void test_webkit_web_resource_get_mime_type(WebResourceFixture* fixture, gconstpointer data)
-{
- gchar* mime_type;
- g_object_get(G_OBJECT(fixture->webResource), "mime-type", &mime_type, NULL);
- g_assert_cmpstr(mime_type, ==, "text/html");
- g_assert_cmpstr(webkit_web_resource_get_mime_type(fixture->webResource),==,"text/html");
- g_free(mime_type);
-}
-
-static void test_webkit_web_resource_get_encoding(WebResourceFixture* fixture, gconstpointer data)
-{
- gchar* text_encoding;
- g_object_get(G_OBJECT(fixture->webResource), "encoding", &text_encoding, NULL);
- g_assert_cmpstr(text_encoding, ==, "utf8");
- g_assert_cmpstr(webkit_web_resource_get_encoding(fixture->webResource),==,"utf8");
- g_free(text_encoding);
-}
-
-static void test_webkit_web_resource_get_frame_name(WebResourceFixture* fixture, gconstpointer data)
-{
- gchar* frame_name;
- g_object_get(G_OBJECT(fixture->webResource), "frame-name", &frame_name, NULL);
- g_assert_cmpstr(frame_name, ==, "Example.com");
- g_assert_cmpstr(webkit_web_resource_get_frame_name(fixture->webResource),==,"Example.com");
- g_free(frame_name);
-}
-
-static void resource_request_starting_cb(WebKitWebView* web_view, WebKitWebFrame* web_frame, WebKitWebResource* web_resource, WebKitNetworkRequest* request, WebKitNetworkResponse* response, gpointer data)
-{
- gint* been_there = data;
- *been_there = *been_there + 1;
-
- if (*been_there == 1) {
- g_assert(!main_resource);
- main_resource = g_object_ref(web_resource);
-
- g_assert_cmpstr(webkit_web_resource_get_uri(web_resource), ==, base_uri);
-
- /* This should be a redirect, so the response must be NULL */
- g_assert(!response);
- } else if (*been_there == 2) {
- char* uri = g_strdup_printf("%sindex.html", base_uri);
-
- g_assert_cmpstr(webkit_web_resource_get_uri(web_resource), ==, uri);
-
- /* Cancel the request. */
- webkit_network_request_set_uri(request, "about:blank");
-
- g_free(uri);
- }
-}
-
-static void notify_load_status_cb(WebKitWebView* web_view, GParamSpec* pspec, gpointer data)
-{
- if (webkit_web_view_get_load_status(web_view) == WEBKIT_LOAD_FINISHED) {
- gboolean* been_there = data;
- *been_there = TRUE;
-
- g_assert_cmpstr(webkit_web_view_get_uri(web_view), ==, "about:blank");
-
- g_main_loop_quit(loop);
- }
-}
-
-static void test_web_resource_loading()
-{
- WebKitWebView* web_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- gint been_to_resource_request_starting = 0;
- gboolean been_to_load_finished = FALSE;
- WebKitWebFrame* web_frame;
- WebKitWebDataSource* data_source;
-
- loop = g_main_loop_new(NULL, TRUE);
-
- g_object_ref_sink(web_view);
-
- g_signal_connect(web_view, "resource-request-starting",
- G_CALLBACK(resource_request_starting_cb),
- &been_to_resource_request_starting);
-
- g_signal_connect(web_view, "notify::load-status",
- G_CALLBACK(notify_load_status_cb),
- &been_to_load_finished);
-
- webkit_web_view_load_uri(web_view, base_uri);
-
- /* We won't get finished immediately, because of the redirect */
- g_main_loop_run(loop);
-
- web_frame = webkit_web_view_get_main_frame(web_view);
- data_source = webkit_web_frame_get_data_source(web_frame);
-
- g_assert(main_resource);
- g_assert(webkit_web_data_source_get_main_resource(data_source) == main_resource);
- g_object_unref(main_resource);
-
- g_assert_cmpint(been_to_resource_request_starting, ==, 2);
- g_assert_cmpint(been_to_load_finished, ==, TRUE);
-
- g_object_unref(web_view);
- g_main_loop_unref(loop);
-}
-
-static void resource_request_starting_sub_cb(WebKitWebView* web_view, WebKitWebFrame* web_frame, WebKitWebResource* web_resource, WebKitNetworkRequest* request, WebKitNetworkResponse* response, gpointer data)
-{
- if (!main_resource)
- main_resource = g_object_ref(web_resource);
- else if (!sub_resource)
- sub_resource = g_object_ref(web_resource);
-}
-
-static void notify_load_status_sub_cb(WebKitWebView* web_view, GParamSpec* pspec, gpointer data)
-{
- if (webkit_web_view_get_load_status(web_view) == WEBKIT_LOAD_FINISHED)
- g_main_loop_quit(loop);
-}
-
-static gboolean idle_quit_loop_cb(gpointer data)
-{
- g_main_loop_quit(loop);
- return FALSE;
-}
-
-static void test_web_resource_sub_resource_loading()
-{
- WebKitWebView* web_view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- WebKitWebFrame* web_frame;
- WebKitWebDataSource* data_source;
- GList* sub_resources;
- char* uri = g_strdup_printf("%smain.html", base_uri);
-
- main_resource = NULL;
-
- loop = g_main_loop_new(NULL, TRUE);
-
- g_object_ref_sink(web_view);
-
- g_signal_connect(web_view, "resource-request-starting",
- G_CALLBACK(resource_request_starting_sub_cb),
- NULL);
-
- g_signal_connect(web_view, "notify::load-status",
- G_CALLBACK(notify_load_status_sub_cb),
- NULL);
-
- webkit_web_view_load_uri(web_view, uri);
-
- g_main_loop_run(loop);
-
- /* The main resource should be loaded; now let's wait for the sub-resource to load */
- g_idle_add(idle_quit_loop_cb, NULL);
- g_main_loop_run(loop);
-
- g_assert(main_resource && sub_resource);
- g_assert(main_resource != sub_resource);
-
- web_frame = webkit_web_view_get_main_frame(web_view);
- data_source = webkit_web_frame_get_data_source(web_frame);
-
- g_assert(webkit_web_data_source_get_main_resource(data_source) == main_resource);
- g_object_unref(main_resource);
-
- sub_resources = webkit_web_data_source_get_subresources(data_source);
- // Expected resources: javascripts.js, favicon.ico
- g_assert(sub_resources);
- g_assert(sub_resources->next);
- g_assert(!sub_resources->next->next);
-
- // Test that the object we got from the data source is the same
- // that went through resource-request-starting. Note that the order is
- // not important (and not guaranteed since the resources are stored in a
- // hashtable).
- g_assert(WEBKIT_WEB_RESOURCE(sub_resources->data) == sub_resource
- || WEBKIT_WEB_RESOURCE(sub_resources->next->data) == sub_resource);
-
- g_object_unref(web_view);
- g_main_loop_unref(loop);
-}
-
-int main(int argc, char** argv)
-{
- SoupServer* server;
- SoupURI* soup_uri;
-
- gtk_test_init(&argc, &argv, NULL);
-
- // Get rid of runtime warnings about deprecated properties and signals, since they break the tests.
- g_setenv("G_ENABLE_DIAGNOSTIC", "0", TRUE);
-
- server = soup_server_new(SOUP_SERVER_PORT, 0, NULL);
- soup_server_run_async(server);
-
- soup_server_add_handler(server, NULL, server_callback, NULL, NULL);
-
- soup_uri = soup_uri_new("http://127.0.0.1/");
- soup_uri_set_port(soup_uri, soup_server_get_port(server));
-
- base_uri = soup_uri_to_string(soup_uri, FALSE);
- soup_uri_free(soup_uri);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add("/webkit/webresource/get_url",
- WebResourceFixture, 0, web_resource_fixture_setup,
- test_webkit_web_resource_get_url, web_resource_fixture_teardown);
- g_test_add("/webkit/webresource/get_mime_type",
- WebResourceFixture, 0, web_resource_fixture_setup,
- test_webkit_web_resource_get_mime_type, web_resource_fixture_teardown);
- g_test_add("/webkit/webresource/get_text_encoding_name",
- WebResourceFixture, 0, web_resource_fixture_setup,
- test_webkit_web_resource_get_encoding, web_resource_fixture_teardown);
- g_test_add("/webkit/webresource/get_frame_name",
- WebResourceFixture, 0, web_resource_fixture_setup,
- test_webkit_web_resource_get_frame_name, web_resource_fixture_teardown);
- g_test_add("/webkit/webresource/get_data",
- WebResourceFixture, 0, web_resource_fixture_setup,
- test_webkit_web_resource_get_data, web_resource_fixture_teardown);
-
- g_test_add_func("/webkit/webresource/loading", test_web_resource_loading);
- g_test_add_func("/webkit/webresource/sub_resource_loading", test_web_resource_sub_resource_loading);
-
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebsettings.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebsettings.c
deleted file mode 100644
index e557e133c..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebsettings.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2009 Jan Michael Alonzo
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-static void test_webkit_web_settings_copy(void)
-{
- WebKitWebSettings *settings = webkit_web_settings_new();
-
- // Set some non-default settings to verify that settings are properly copied.
- g_object_set(settings,
- "enable-webgl", TRUE,
- "enable-fullscreen", TRUE,
- "auto-load-images", FALSE,
- "default-encoding", "utf-8",
- "enable-mediasource", TRUE,
- NULL);
-
- WebKitWebSettings *copy = webkit_web_settings_copy(settings);
-
- gboolean enableWebGL = FALSE;
- gboolean enableFullscreen = FALSE;
- gboolean autoLoadImages = FALSE;
- gboolean enableMediaSource = FALSE;
- char *defaultEncoding = 0;
- g_object_get(copy,
- "enable-fullscreen", &enableFullscreen,
- "enable-webgl", &enableWebGL,
- "auto-load-images", &autoLoadImages,
- "default-encoding", &defaultEncoding,
- "enable-mediasource", &enableMediaSource,
- NULL);
-
- g_assert(enableWebGL);
- g_assert(enableFullscreen);
- g_assert(!autoLoadImages);
- g_assert_cmpstr(defaultEncoding, ==, "utf-8");
- g_assert(enableMediaSource);
- g_free(defaultEncoding);
-}
-
-static void test_webkit_web_settings_user_agent(void)
-{
- WebKitWebSettings *settings;
- GtkWidget *webView;
- char *defaultUserAgent;
- char *userAgent = 0;
- g_test_bug("17375");
-
- webView = webkit_web_view_new();
- g_object_ref_sink(webView);
-
- settings = webkit_web_view_get_settings(WEBKIT_WEB_VIEW(webView));
- defaultUserAgent = g_strdup(webkit_web_settings_get_user_agent(settings));
-
- g_assert(g_strstr_len(defaultUserAgent, -1, "Version/8.0 Safari/"));
- g_assert(g_strstr_len(defaultUserAgent, -1, "Version/8.0") < g_strstr_len(defaultUserAgent, -1, "Safari/"));
-
- // test a custom UA string
- userAgent = 0;
- g_object_set(settings, "user-agent", "testwebsettings/0.1", NULL);
- g_object_get(settings,"user-agent", &userAgent, NULL);
- g_assert_cmpstr(userAgent, ==, "testwebsettings/0.1");
- g_free(userAgent);
-
- // setting it to NULL or an empty value should give us the default UA string
- userAgent = 0;
- g_object_set(settings, "user-agent", 0, NULL);
- g_object_get(settings,"user-agent", &userAgent, NULL);
- g_assert_cmpstr(userAgent, ==, defaultUserAgent);
- g_free(userAgent);
-
- userAgent = 0;
- g_object_set(settings, "user-agent", "", NULL);
- g_object_get(settings,"user-agent", &userAgent, NULL);
- g_assert_cmpstr(userAgent, ==, defaultUserAgent);
- g_free(userAgent);
-
- g_free(defaultUserAgent);
- g_object_unref(webView);
-}
-
-int main(int argc, char **argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/websettings/user_agent", test_webkit_web_settings_user_agent);
- g_test_add_func("/webkit/websettings/copy", test_webkit_web_settings_copy);
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebview.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebview.c
deleted file mode 100644
index 86057867c..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwebview.c
+++ /dev/null
@@ -1,749 +0,0 @@
-/*
- * Copyright (C) 2008 Holger Hans Peter Freyther
- * Copyright (C) 2009, 2010 Collabora Ltd.
- * Copyright (C) 2012 Igalia S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "test_utils.h"
-
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gdk/gdk.h>
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-GMainLoop* loop;
-SoupSession *session;
-char* base_uri;
-
-/* For real request testing */
-static void
-server_callback(SoupServer* server, SoupMessage* msg,
- const char* path, GHashTable* query,
- SoupClientContext* context, gpointer data)
-{
- if (msg->method != SOUP_METHOD_GET) {
- soup_message_set_status(msg, SOUP_STATUS_NOT_IMPLEMENTED);
- return;
- }
-
- soup_message_set_status(msg, SOUP_STATUS_OK);
-
- if (g_str_equal(path, "/favicon.ico")) {
- char* contents;
- gsize length;
- GError* error = NULL;
-
- g_file_get_contents("blank.ico", &contents, &length, &error);
- g_assert(!error);
-
- soup_message_body_append(msg->response_body, SOUP_MEMORY_TAKE, contents, length);
- } else if (g_str_equal(path, "/bigdiv.html")) {
- char* contents = g_strdup("<html><body><a id=\"link\" href=\"http://abc.def\">test</a><div style=\"background-color: green; height: 1200px;\"></div></body></html>");
- soup_message_body_append(msg->response_body, SOUP_MEMORY_TAKE, contents, strlen(contents));
- } else if (g_str_equal(path, "/iframe.html")) {
- char* contents = g_strdup("<html><body id=\"some-content\"><div style=\"background-color: green; height: 50px;\"></div><iframe src=\"bigdiv.html\"></iframe></body></html>");
- soup_message_body_append(msg->response_body, SOUP_MEMORY_TAKE, contents, strlen(contents));
- } else {
- char* contents = g_strdup("<html><body>test</body></html>");
- soup_message_body_append(msg->response_body, SOUP_MEMORY_TAKE, contents, strlen(contents));
- }
-
- soup_message_body_complete(msg->response_body);
-}
-
-static void idle_quit_loop_cb(WebKitWebView* web_view, GParamSpec* pspec, gpointer data)
-{
- if (webkit_web_view_get_load_status(web_view) == WEBKIT_LOAD_FINISHED ||
- webkit_web_view_get_load_status(web_view) == WEBKIT_LOAD_FAILED)
- g_main_loop_quit(loop);
-}
-
-static gboolean timeout_cb(gpointer data)
-{
- g_error("Didn't get icon-uri before timing out.");
- return FALSE;
-}
-
-static void icon_uri_changed_cb(WebKitWebView* web_view, GParamSpec* pspec, gpointer data)
-{
- char* expected_uri;
-
- g_assert_cmpstr(g_param_spec_get_name(pspec), ==, "icon-uri");
-
- expected_uri = g_strdup_printf("%sfavicon.ico", base_uri);
- g_assert_cmpstr(webkit_web_view_get_icon_uri(web_view), ==, expected_uri);
- g_free(expected_uri);
-
- g_main_loop_quit(loop);
-}
-
-static void icon_loaded_cb(WebKitWebView* web_view, char* icon_uri, gpointer data)
-{
- gboolean* been_here = (gboolean*)data;
- char* expected_uri = g_strdup_printf("%sfavicon.ico", base_uri);
- g_assert_cmpstr(icon_uri, ==, expected_uri);
- g_free(expected_uri);
-
- g_assert_cmpstr(icon_uri, ==, webkit_web_view_get_icon_uri(web_view));
-
- *been_here = TRUE;
-}
-
-static void test_webkit_web_view_icon_uri()
-{
- gboolean been_to_icon_loaded = FALSE;
- WebKitWebView* view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- g_object_ref_sink(G_OBJECT(view));
-
- loop = g_main_loop_new(NULL, TRUE);
-
- g_object_connect(G_OBJECT(view),
- "signal::notify::icon-uri", icon_uri_changed_cb, NULL,
- "signal::icon-loaded", icon_loaded_cb, &been_to_icon_loaded,
- NULL);
-
- webkit_web_view_load_uri(view, base_uri);
-
- guint timeout_id = g_timeout_add(500, timeout_cb, 0);
-
- g_main_loop_run(loop);
-
- g_source_remove(timeout_id);
-
- g_assert(been_to_icon_loaded);
-
- g_object_unref(view);
-}
-
-static gboolean map_event_cb(GtkWidget *widget, GdkEvent* event, gpointer data)
-{
- GMainLoop* loop = (GMainLoop*)data;
- g_main_loop_quit(loop);
-
- return FALSE;
-}
-
-static gboolean quit_after_short_delay_cb(gpointer data)
-{
- g_main_loop_quit((GMainLoop*)data);
- return FALSE;
-}
-
-static void test_webkit_web_view_grab_focus()
-{
- char* uri = g_strconcat(base_uri, "iframe.html", NULL);
- GtkWidget* window = gtk_window_new(GTK_WINDOW_POPUP);
- GtkWidget* scrolled_window = gtk_scrolled_window_new(NULL, NULL);
- WebKitWebView* view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- GtkAdjustment* adjustment;
-
- gtk_window_set_default_size(GTK_WINDOW(window), 400, 200);
-
- gtk_container_add(GTK_CONTAINER(window), scrolled_window);
- gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(view));
-
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-
- loop = g_main_loop_new(NULL, TRUE);
-
- g_signal_connect(view, "notify::load-status", G_CALLBACK(idle_quit_loop_cb), NULL);
-
- /* Wait for window to show up */
- gtk_widget_show_all(window);
- g_signal_connect(window, "map-event",
- G_CALLBACK(map_event_cb), loop);
- g_main_loop_run(loop);
-
- /* Load a page with a big div that will cause scrollbars to appear */
- webkit_web_view_load_uri(view, uri);
- g_main_loop_run(loop);
-
- adjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(scrolled_window));
- g_assert_cmpfloat(gtk_adjustment_get_value(adjustment), ==, 0.0);
-
- /* Since webkit_web_view_execute_script does not return a value,
- it is impossible to know if an inner document has focus after
- a node of it was focused via .focus() method.
- The code below is an workaround: if the node has focus, a scroll
- action is performed and afterward it is checked if the adjustment
- has to be different from 0.
- */
- char script[] = "var innerDoc = document.defaultView.frames[0].document; \
- innerDoc.getElementById(\"link\").focus(); \
- if (innerDoc.hasFocus()) \
- window.scrollBy(0, 100);";
-
- /* Focus an element using JavaScript */
- webkit_web_view_execute_script(view, script);
-
- /* Adjustments update asynchronously, so we must wait a bit. */
- g_timeout_add(100, quit_after_short_delay_cb, loop);
- g_main_loop_run(loop);
-
- /* Make sure the ScrolledWindow noticed the scroll */
- g_assert_cmpfloat(gtk_adjustment_get_value(adjustment), !=, 0.0);
-
- g_free(uri);
- gtk_widget_destroy(window);
-}
-
-static void do_test_webkit_web_view_adjustments(gboolean with_page_cache)
-{
- char* effective_uri = g_strconcat(base_uri, "bigdiv.html", NULL);
- char* second_uri = g_strconcat(base_uri, "iframe.html", NULL);
- GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- GtkWidget* scrolled_window = gtk_scrolled_window_new(NULL, NULL);
- WebKitWebView* view = WEBKIT_WEB_VIEW(webkit_web_view_new());
- GtkAdjustment* adjustment;
- double lower;
- double upper;
-
- if (with_page_cache) {
- WebKitWebSettings* settings = webkit_web_view_get_settings(view);
- g_object_set(settings, "enable-page-cache", TRUE, NULL);
- }
-
- gtk_window_set_default_size(GTK_WINDOW(window), 400, 200);
-
- gtk_container_add(GTK_CONTAINER(window), scrolled_window);
- gtk_container_add(GTK_CONTAINER(scrolled_window), GTK_WIDGET(view));
-
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-
- loop = g_main_loop_new(NULL, TRUE);
-
- g_object_connect(G_OBJECT(view),
- "signal::notify::load-status", idle_quit_loop_cb, NULL,
- NULL);
-
- /* Wait for window to show up */
- gtk_widget_show_all(window);
- g_signal_connect(window, "map-event",
- G_CALLBACK(map_event_cb), loop);
- g_main_loop_run(loop);
-
- /* Load a page with a big div that will cause scrollbars to appear */
- webkit_web_view_load_uri(view, effective_uri);
- g_main_loop_run(loop);
-
- /* Adjustments update asynchronously, so we must wait a bit. */
- g_timeout_add(100, quit_after_short_delay_cb, loop);
- g_main_loop_run(loop);
-
- adjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(scrolled_window));
- g_assert_cmpfloat(gtk_adjustment_get_value(adjustment), ==, 0.0);
-
- lower = gtk_adjustment_get_lower(adjustment);
- upper = gtk_adjustment_get_upper(adjustment);
-
- /* Scroll the view using JavaScript */
- webkit_web_view_execute_script(view, "window.scrollBy(0, 100)");
-
- /* Adjustments update asynchronously, so we must wait a bit. */
- g_timeout_add(100, quit_after_short_delay_cb, loop);
- g_main_loop_run(loop);
-
- /* Make sure the ScrolledWindow noticed the scroll */
- g_assert_cmpfloat(gtk_adjustment_get_value(adjustment), ==, 100.0);
-
- /* Load a second URI */
- webkit_web_view_load_uri(view, second_uri);
- g_main_loop_run(loop);
-
- /* The page loaded but the adjustments may not be updated yet. Wait a bit. */
- g_timeout_add(100, quit_after_short_delay_cb, loop);
- g_main_loop_run(loop);
-
- /* Make sure the scrollbar has been reset */
- g_assert_cmpfloat(gtk_adjustment_get_value(adjustment), ==, 0.0);
-
- /* Go back */
- webkit_web_view_go_back(view);
-
- /* When using page cache, go_back will return syncronously */
- if (!with_page_cache)
- g_main_loop_run(loop);
-
- /* Make sure GTK+ has time to process the changes in size, for the adjusments */
- while (gtk_events_pending())
- gtk_main_iteration();
-
- /* Make sure upper and lower bounds have been restored correctly */
- g_assert_cmpfloat(lower, ==, gtk_adjustment_get_lower(adjustment));
- g_assert_cmpfloat(upper, ==, gtk_adjustment_get_upper(adjustment));
- g_assert_cmpfloat(gtk_adjustment_get_value(adjustment), ==, 100.0);
-
- g_free(effective_uri);
- g_free(second_uri);
-
- gtk_widget_destroy(window);
-}
-
-static void test_webkit_web_view_adjustments()
-{
- /* Test this with page cache disabled, and enabled. */
- do_test_webkit_web_view_adjustments(FALSE);
- do_test_webkit_web_view_adjustments(TRUE);
-}
-
-gboolean delayed_destroy(gpointer data)
-{
- gtk_widget_destroy(GTK_WIDGET(data));
- g_main_loop_quit(loop);
- return FALSE;
-}
-
-static void test_webkit_web_view_destroy()
-{
- GtkWidget* window;
- GtkWidget* web_view;
-
- window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- web_view = webkit_web_view_new();
-
- gtk_container_add(GTK_CONTAINER(window), web_view);
-
- gtk_widget_show_all(window);
-
- loop = g_main_loop_new(NULL, TRUE);
-
- g_signal_connect(window, "map-event",
- G_CALLBACK(map_event_cb), loop);
- g_main_loop_run(loop);
-
- g_idle_add(delayed_destroy, web_view);
- g_main_loop_run(loop);
-
- gtk_widget_destroy(window);
-}
-
-static void test_webkit_web_view_window_features()
-{
- GtkWidget* window;
- GtkWidget* web_view;
-
- window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- web_view = webkit_web_view_new();
-
- gtk_container_add(GTK_CONTAINER(window), web_view);
-
- gtk_widget_show_all(window);
-
- loop = g_main_loop_new(NULL, TRUE);
-
- g_signal_connect(window, "map-event",
- G_CALLBACK(map_event_cb), loop);
- g_main_loop_run(loop);
-
- /* Bug #36144 */
- g_object_set(G_OBJECT(web_view), "window-features", NULL, NULL);
-
- gtk_widget_destroy(window);
-}
-
-static void test_webkit_web_view_in_offscreen_window_does_not_crash()
-{
- loop = g_main_loop_new(NULL, TRUE);
-
- GtkWidget *window = gtk_offscreen_window_new();
- GtkWidget *web_view = webkit_web_view_new();
-
- gtk_container_add(GTK_CONTAINER(window), web_view);
- gtk_widget_show_all(window);
- g_signal_connect(web_view, "notify::load-status", G_CALLBACK(idle_quit_loop_cb), NULL);
- webkit_web_view_load_uri(WEBKIT_WEB_VIEW(web_view), base_uri);
-
- g_main_loop_run(loop);
-
- gtk_widget_destroy(window);
- g_main_loop_unref(loop);
-}
-
-static void test_webkit_web_view_does_not_steal_focus()
-{
- loop = g_main_loop_new(NULL, TRUE);
-
- GtkWidget *window = gtk_offscreen_window_new();
- GtkWidget *webView = webkit_web_view_new();
- GtkWidget *entry = gtk_entry_new();
-
-#ifdef GTK_API_VERSION_2
- GtkWidget *box = gtk_hbox_new(FALSE, 0);
-#else
- GtkWidget *box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
-#endif
-
- gtk_container_add(GTK_CONTAINER(box), webView);
- gtk_container_add(GTK_CONTAINER(box), entry);
- gtk_container_add(GTK_CONTAINER(window), box);
- gtk_widget_show_all(window);
-
- gtk_widget_grab_focus(entry);
- g_assert(gtk_widget_is_focus(entry));
-
- g_signal_connect(webView, "notify::load-status", G_CALLBACK(idle_quit_loop_cb), NULL);
- webkit_web_view_load_html_string(WEBKIT_WEB_VIEW(webView),
- "<html><body>"
- " <input id=\"entry\" type=\"text\"/>"
- " <script>"
- " document.getElementById(\"entry\").focus();"
- " </script>"
- "</body></html>", "file://");
-
- g_main_loop_run(loop);
-
- g_assert(gtk_widget_is_focus(entry));
-
- gtk_widget_destroy(window);
- g_main_loop_unref(loop);
-}
-
-static gboolean emitKeyStroke(WebKitWebView* webView)
-{
- GdkEvent* pressEvent = gdk_event_new(GDK_KEY_PRESS);
- pressEvent->key.keyval = GDK_KEY_f;
- GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(webView));
- pressEvent->key.window = window;
- g_object_ref(pressEvent->key.window);
-
-#ifndef GTK_API_VERSION_2
- GdkDeviceManager* manager = gdk_display_get_device_manager(gdk_window_get_display(window));
- gdk_event_set_device(pressEvent, gdk_device_manager_get_client_pointer(manager));
-#endif
-
- // When synthesizing an event, an invalid hardware_keycode value
- // can cause it to be badly processed by Gtk+.
- GdkKeymapKey* keys;
- gint n_keys;
- if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), GDK_KEY_f, &keys, &n_keys)) {
- pressEvent->key.hardware_keycode = keys[0].keycode;
- g_free(keys);
- }
-
- GdkEvent* releaseEvent = gdk_event_copy(pressEvent);
- gtk_main_do_event(pressEvent);
- gdk_event_free(pressEvent);
- releaseEvent->key.type = GDK_KEY_RELEASE;
- gtk_main_do_event(releaseEvent);
- gdk_event_free(releaseEvent);
-
- return FALSE;
-}
-
-static gboolean entering_fullscreen_cb(WebKitWebView* webView, GObject* element, gboolean blocked)
-{
- if (blocked)
- g_main_loop_quit(loop);
- else
- g_timeout_add(200, (GSourceFunc) emitKeyStroke, webView);
- return blocked;
-}
-
-static gboolean leaving_fullscreen_cb(WebKitWebView* webView, GObject* element, gpointer data)
-{
- g_main_loop_quit(loop);
- return FALSE;
-}
-
-static void test_webkit_web_view_fullscreen(gconstpointer blocked)
-{
- GtkWidget* window;
- GtkWidget* web_view;
- WebKitWebSettings *settings;
-
- window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- web_view = webkit_web_view_new();
-
- settings = webkit_web_view_get_settings(WEBKIT_WEB_VIEW(web_view));
- g_object_set(settings, "enable-fullscreen", TRUE, NULL);
- webkit_web_view_set_settings(WEBKIT_WEB_VIEW(web_view), settings);
-
- gtk_container_add(GTK_CONTAINER(window), web_view);
-
- gtk_widget_show_all(window);
-
- loop = g_main_loop_new(NULL, TRUE);
-
- g_signal_connect(web_view, "entering-fullscreen", G_CALLBACK(entering_fullscreen_cb), (gpointer) blocked);
- g_signal_connect(web_view, "leaving-fullscreen", G_CALLBACK(leaving_fullscreen_cb), NULL);
-
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(web_view), "<html><body>"
- "<script>"
- "var eventName = 'keypress';"
- "document.addEventListener(eventName, function () {"
- " document.documentElement.webkitRequestFullScreen();"
- "}, false);"
- "</script></body></html>", NULL, NULL, NULL);
-
- g_timeout_add(100, (GSourceFunc) emitKeyStroke, WEBKIT_WEB_VIEW(web_view));
- g_main_loop_run(loop);
-
- gtk_widget_destroy(window);
-}
-
-static gboolean checkMimeTypeForFilter(GtkFileFilter* filter, const gchar* mimeType)
-{
- GtkFileFilterInfo filter_info;
- filter_info.contains = GTK_FILE_FILTER_MIME_TYPE;
- filter_info.mime_type = mimeType;
- return gtk_file_filter_filter(filter, &filter_info);
-}
-
-static gboolean runFileChooserCbNoMultiselNoMime(WebKitWebView* webview, WebKitFileChooserRequest* request, gpointer data)
-{
- g_assert(!webkit_file_chooser_request_get_select_multiple(request));
-
- const gchar* const* mimeTypes = webkit_file_chooser_request_get_mime_types(request);
- g_assert(!mimeTypes);
- GtkFileFilter* filter = webkit_file_chooser_request_get_mime_types_filter(request);
- g_assert(!filter);
-
- const gchar* const* selectedFiles = webkit_file_chooser_request_get_selected_files(request);
- g_assert(!selectedFiles);
-
- g_main_loop_quit(loop);
- return TRUE;
-}
-
-static gboolean runFileChooserCbMultiselNoMime(WebKitWebView* webview, WebKitFileChooserRequest* request, gpointer data)
-{
- g_assert(webkit_file_chooser_request_get_select_multiple(request));
-
- const gchar* const* mimeTypes = webkit_file_chooser_request_get_mime_types(request);
- g_assert(!mimeTypes);
- GtkFileFilter* filter = webkit_file_chooser_request_get_mime_types_filter(request);
- g_assert(!filter);
- const gchar* const* selectedFiles = webkit_file_chooser_request_get_selected_files(request);
- g_assert(!selectedFiles);
-
- // Select some files.
- const gchar* filesToSelect[4] = { "/foo", "/foo/bar", "/foo/bar/baz", 0 };
- webkit_file_chooser_request_select_files(request, filesToSelect);
-
- // Check the files that have been just selected.
- selectedFiles = webkit_file_chooser_request_get_selected_files(request);
- g_assert(selectedFiles);
- g_assert_cmpstr(selectedFiles[0], ==, "/foo");
- g_assert_cmpstr(selectedFiles[1], ==, "/foo/bar");
- g_assert_cmpstr(selectedFiles[2], ==, "/foo/bar/baz");
- g_assert(!selectedFiles[3]);
-
- g_main_loop_quit(loop);
- return TRUE;
-}
-
-static gboolean runFileChooserCbSelectionRetained(WebKitWebView* webview, WebKitFileChooserRequest* request, gpointer data)
-{
- const gchar* const* selectedFiles = webkit_file_chooser_request_get_selected_files(request);
- g_assert(selectedFiles);
- g_assert_cmpstr(selectedFiles[0], ==, "/foo");
- g_assert_cmpstr(selectedFiles[1], ==, "/foo/bar");
- g_assert_cmpstr(selectedFiles[2], ==, "/foo/bar/baz");
- g_assert(!selectedFiles[3]);
-
- g_main_loop_quit(loop);
- return TRUE;
-}
-
-static gboolean runFileChooserCbNoMultiselAcceptTypes(WebKitWebView* webview, WebKitFileChooserRequest* request, gpointer data)
-{
- g_assert(!webkit_file_chooser_request_get_select_multiple(request));
-
- const gchar* const* mimeTypes = webkit_file_chooser_request_get_mime_types(request);
- g_assert(mimeTypes);
- g_assert_cmpstr(mimeTypes[0], ==, "audio/*");
- g_assert_cmpstr(mimeTypes[1], ==, "video/*");
- g_assert_cmpstr(mimeTypes[2], ==, "image/*");
- g_assert(!mimeTypes[3]);
-
- GtkFileFilter* filter = webkit_file_chooser_request_get_mime_types_filter(request);
- g_assert(GTK_IS_FILE_FILTER(filter));
- g_assert(checkMimeTypeForFilter(filter, "audio/*"));
- g_assert(checkMimeTypeForFilter(filter, "video/*"));
- g_assert(checkMimeTypeForFilter(filter, "image/*"));
-
- const gchar* const* selectedFiles = webkit_file_chooser_request_get_selected_files(request);
- g_assert(!selectedFiles);
-
- g_main_loop_quit(loop);
- return TRUE;
-}
-
-void doMouseButtonEvent(GtkWidget* widget, GdkEventType eventType, int x, int y, unsigned int button, unsigned int modifiers)
-{
- g_assert(gtk_widget_get_realized(widget));
-
- GdkEvent* event = gdk_event_new(eventType);
- event->button.window = gtk_widget_get_window(widget);
- g_object_ref(event->button.window);
-
- event->button.time = GDK_CURRENT_TIME;
- event->button.x = x;
- event->button.y = y;
- event->button.axes = 0;
- event->button.state = modifiers;
- event->button.button = button;
-
-#ifndef GTK_API_VERSION_2
- event->button.device = gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gtk_widget_get_display(widget)));
-#endif
-
- int xRoot, yRoot;
- gdk_window_get_root_coords(gtk_widget_get_window(widget), x, y, &xRoot, &yRoot);
- event->button.x_root = xRoot;
- event->button.y_root = yRoot;
- gtk_main_do_event(event);
-}
-
-static void clickMouseButton(GtkWidget* widget, int x, int y, unsigned int button, unsigned int modifiers)
-{
- doMouseButtonEvent(widget, GDK_BUTTON_PRESS, x, y, button, modifiers);
- doMouseButtonEvent(widget, GDK_BUTTON_RELEASE, x, y, button, modifiers);
-}
-
-static gboolean clickMouseButtonAndWaitForFileChooserRequest(WebKitWebView* webView)
-{
- clickMouseButton(GTK_WIDGET(webView), 5, 5, 1, 0);
- return TRUE;
-}
-
-static void test_webkit_web_view_file_chooser()
-{
- const gchar* htmlFormatBase = "<html><body>"
- "<input style='position:absolute;left:0;top:0;margin:0;padding:0' type='file' %s/>"
- "</body></html>";
-
- GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- GtkWidget* webView = webkit_web_view_new();
- gtk_container_add(GTK_CONTAINER(window), webView);
- gtk_widget_show_all(window);
-
- loop = g_main_loop_new(NULL, TRUE);
-
- // Multiple selections not allowed, no MIME filtering.
- gulong handler = g_signal_connect(webView, "run-file-chooser", G_CALLBACK(runFileChooserCbNoMultiselNoMime), NULL);
- gchar* htmlFormat = g_strdup_printf(htmlFormatBase, "");
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(webView), htmlFormat, NULL, NULL, NULL);
- g_free(htmlFormat);
-
- g_timeout_add(100, (GSourceFunc) clickMouseButtonAndWaitForFileChooserRequest, WEBKIT_WEB_VIEW(webView));
- g_main_loop_run(loop);
-
- g_signal_handler_disconnect(webView, handler);
-
- // Multiple selections allowed, no MIME filtering, some pre-selected files.
- handler = g_signal_connect(webView, "run-file-chooser", G_CALLBACK(runFileChooserCbMultiselNoMime), NULL);
- htmlFormat = g_strdup_printf(htmlFormatBase, "multiple");
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(webView), htmlFormat, NULL, NULL, NULL);
- g_free(htmlFormat);
-
- g_timeout_add(100, (GSourceFunc) clickMouseButtonAndWaitForFileChooserRequest, WEBKIT_WEB_VIEW(webView));
- g_main_loop_run(loop);
-
- g_signal_handler_disconnect(webView, handler);
-
- // Perform another request to check if the list of files selected
- // in the previous step appears now as part of the new request.
- handler = g_signal_connect(webView, "run-file-chooser", G_CALLBACK(runFileChooserCbSelectionRetained), NULL);
- g_timeout_add(100, (GSourceFunc) clickMouseButtonAndWaitForFileChooserRequest, WEBKIT_WEB_VIEW(webView));
- g_main_loop_run(loop);
-
- g_signal_handler_disconnect(webView, handler);
-
- // Multiple selections not allowed, only accept images, audio and video files.
- handler = g_signal_connect(webView, "run-file-chooser", G_CALLBACK(runFileChooserCbNoMultiselAcceptTypes), NULL);
- htmlFormat = g_strdup_printf(htmlFormatBase, "accept='audio/*,video/*,image/*'");
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(webView), htmlFormat, NULL, NULL, NULL);
- g_free(htmlFormat);
-
- g_timeout_add(100, (GSourceFunc) clickMouseButtonAndWaitForFileChooserRequest, WEBKIT_WEB_VIEW(webView));
- g_main_loop_run(loop);
-
- g_signal_handler_disconnect(webView, handler);
- gtk_widget_destroy(window);
-}
-
-static void test_webkit_web_view_source_mode()
-{
- GtkWidget* web_view;
-
- web_view = webkit_web_view_new();
-
- webkit_web_view_load_string(WEBKIT_WEB_VIEW(web_view), "<html><body></body></html>", NULL, NULL, NULL);
-
- g_assert(!webkit_web_view_get_view_source_mode(WEBKIT_WEB_VIEW(web_view)));
-
- webkit_web_view_set_view_source_mode(WEBKIT_WEB_VIEW(web_view), TRUE);
-
- g_assert(webkit_web_view_get_view_source_mode(WEBKIT_WEB_VIEW(web_view)));
-
- webkit_web_view_set_view_source_mode(WEBKIT_WEB_VIEW(web_view), FALSE);
-
- g_assert(!webkit_web_view_get_view_source_mode(WEBKIT_WEB_VIEW(web_view)));
-
- gtk_widget_destroy(web_view);
-}
-
-int main(int argc, char** argv)
-{
- SoupServer* server;
- SoupURI* soup_uri;
-
- gtk_test_init(&argc, &argv, NULL);
-
- // Get rid of runtime warnings about deprecated properties and signals, since they break the tests.
- g_setenv("G_ENABLE_DIAGNOSTIC", "0", TRUE);
-
- /* Hopefully make test independent of the path it's called from. */
- testutils_relative_chdir("Tools/TestWebKitAPI/Tests/WebKitGtk/resources/test.html", argv[0]);
-
- server = soup_server_new(SOUP_SERVER_PORT, 0, NULL);
- soup_server_run_async(server);
-
- soup_server_add_handler(server, NULL, server_callback, NULL, NULL);
-
- soup_uri = soup_uri_new("http://127.0.0.1/");
- soup_uri_set_port(soup_uri, soup_server_get_port(server));
-
- base_uri = soup_uri_to_string(soup_uri, FALSE);
- soup_uri_free(soup_uri);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/webview/icon-uri", test_webkit_web_view_icon_uri);
- g_test_add_func("/webkit/webview/adjustments", test_webkit_web_view_adjustments);
- g_test_add_func("/webkit/webview/destroy", test_webkit_web_view_destroy);
- g_test_add_func("/webkit/webview/grab_focus", test_webkit_web_view_grab_focus);
- g_test_add_func("/webkit/webview/window-features", test_webkit_web_view_window_features);
- g_test_add_func("/webkit/webview/webview-in-offscreen-window-does-not-crash", test_webkit_web_view_in_offscreen_window_does_not_crash);
- g_test_add_func("/webkit/webview/webview-does-not-steal-focus", test_webkit_web_view_does_not_steal_focus);
- g_test_add_data_func("/webkit/webview/fullscreen", GINT_TO_POINTER(FALSE), test_webkit_web_view_fullscreen);
- g_test_add_data_func("/webkit/webview/fullscreen-blocked", GINT_TO_POINTER(TRUE), test_webkit_web_view_fullscreen);
- g_test_add_func("/webkit/webview/file-chooser", test_webkit_web_view_file_chooser);
- g_test_add_func("/webkit/webview/source-mode", test_webkit_web_view_source_mode);
-
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwindow.c b/Tools/TestWebKitAPI/Tests/WebKitGtk/testwindow.c
deleted file mode 100644
index 5eda47b12..000000000
--- a/Tools/TestWebKitAPI/Tests/WebKitGtk/testwindow.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2009 Collabora Ltd.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include <gtk/gtk.h>
-#include <webkit/webkit.h>
-
-static void notify_load_status_cb(WebKitWebView* web_view, GParamSpec* pspec, gpointer data)
-{
- if (webkit_web_view_get_load_status(web_view) == WEBKIT_LOAD_FINISHED) {
- GMainLoop* loop = (GMainLoop*)data;
-
- g_main_loop_quit(loop);
- }
-}
-
-static void test_webkit_window_scrollbar_policy(void)
-{
- GMainLoop* loop;
- GtkWidget* scrolledWindow;
- GtkWidget* webView;
- WebKitWebFrame* mainFrame;
- GtkPolicyType horizontalPolicy;
- GtkPolicyType verticalPolicy;
-
- loop = g_main_loop_new(NULL, TRUE);
-
- scrolledWindow = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledWindow),
- GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-
- webView = webkit_web_view_new();
- g_object_ref_sink(webView);
-
- g_signal_connect(webView, "notify::load-status",
- G_CALLBACK(notify_load_status_cb), loop);
-
- gtk_container_add(GTK_CONTAINER(scrolledWindow), webView);
-
- mainFrame = webkit_web_view_get_main_frame(WEBKIT_WEB_VIEW(webView));
-
- /* Test we correctly apply policy for not having scrollbars; This
- * case is special, because we turn the policy from NEVER to
- * AUTOMATIC, since we cannot easily represent the same thing
- * using GtkScrolledWindow */
- webkit_web_view_load_html_string(WEBKIT_WEB_VIEW(webView),
- "<html><body>WebKit!</body><script>document.getElementsByTagName('body')[0].style.overflow = 'hidden';</script></html>",
- "file://");
-
- g_main_loop_run(loop);
-
- gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(scrolledWindow),
- &horizontalPolicy, &verticalPolicy);
-
- g_assert(horizontalPolicy == GTK_POLICY_AUTOMATIC);
- g_assert(verticalPolicy == GTK_POLICY_AUTOMATIC);
-
- g_assert(GTK_POLICY_NEVER == webkit_web_frame_get_horizontal_scrollbar_policy(mainFrame));
- g_assert(GTK_POLICY_NEVER == webkit_web_frame_get_vertical_scrollbar_policy(mainFrame));
-
- /* Test we correctly apply policy for always having scrollbars */
- webkit_web_view_load_html_string(WEBKIT_WEB_VIEW(webView),
- "<html><body>WebKit!</body><script>document.getElementsByTagName('body')[0].style.overflow = 'scroll';</script></html>",
- "file://");
-
- g_main_loop_run(loop);
-
- gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(scrolledWindow),
- &horizontalPolicy, &verticalPolicy);
-
- g_assert(horizontalPolicy == GTK_POLICY_ALWAYS);
- g_assert(verticalPolicy == GTK_POLICY_ALWAYS);
-
- g_assert(horizontalPolicy == webkit_web_frame_get_horizontal_scrollbar_policy(mainFrame));
- g_assert(verticalPolicy == webkit_web_frame_get_vertical_scrollbar_policy(mainFrame));
-
- /* Test we correctly apply policy for having scrollbars when needed */
- webkit_web_view_load_html_string(WEBKIT_WEB_VIEW(webView),
- "<html><body>WebKit!</body><script>document.getElementsByTagName('body')[0].style.overflow = 'auto';</script></html>",
- "file://");
-
- g_main_loop_run(loop);
-
- gtk_scrolled_window_get_policy(GTK_SCROLLED_WINDOW(scrolledWindow),
- &horizontalPolicy, &verticalPolicy);
-
- g_assert(horizontalPolicy == GTK_POLICY_AUTOMATIC);
- g_assert(verticalPolicy == GTK_POLICY_AUTOMATIC);
-
- g_assert(horizontalPolicy == webkit_web_frame_get_horizontal_scrollbar_policy(mainFrame));
- g_assert(verticalPolicy == webkit_web_frame_get_vertical_scrollbar_policy(mainFrame));
-
- g_object_unref(webView);
-}
-
-int main(int argc, char** argv)
-{
- gtk_test_init(&argc, &argv, NULL);
-
- g_test_bug_base("https://bugs.webkit.org/");
- g_test_add_func("/webkit/window/scrollbar_policy", test_webkit_window_scrollbar_policy);
- return g_test_run ();
-}
diff --git a/Tools/TestWebKitAPI/TestsController.cpp b/Tools/TestWebKitAPI/TestsController.cpp
index 29dcc714e..913305d7b 100644
--- a/Tools/TestWebKitAPI/TestsController.cpp
+++ b/Tools/TestWebKitAPI/TestsController.cpp
@@ -30,9 +30,33 @@
namespace TestWebKitAPI {
-TestsController& TestsController::shared()
+class Printer : public ::testing::EmptyTestEventListener {
+ virtual void OnTestPartResult(const ::testing::TestPartResult& test_part_result)
+ {
+ if (!test_part_result.failed())
+ return;
+
+ std::stringstream stream;
+ stream << "\n" << test_part_result.file_name() << ":" << test_part_result.line_number() << "\n" << test_part_result.summary() << "\n\n";
+ failures += stream.str();
+ }
+
+ virtual void OnTestEnd(const ::testing::TestInfo& test_info)
+ {
+ if (test_info.result()->Passed())
+ std::cout << "**PASS** " << test_info.test_case_name() << "." << test_info.name() << "\n";
+ else
+ std::cout << "**FAIL** " << test_info.test_case_name() << "." << test_info.name() << "\n" << failures;
+
+ failures = std::string();
+ }
+
+ std::string failures;
+};
+
+TestsController& TestsController::singleton()
{
- static TestsController& shared = *new TestsController;
+ static NeverDestroyed<TestsController> shared;
return shared;
}
@@ -48,6 +72,11 @@ TestsController::TestsController()
bool TestsController::run(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
+
+ ::testing::TestEventListeners& listeners = ::testing::UnitTest::GetInstance()->listeners();
+ delete listeners.Release(listeners.default_result_printer());
+ listeners.Append(new Printer);
+
return !RUN_ALL_TESTS();
}
diff --git a/Tools/TestWebKitAPI/TestsController.h b/Tools/TestWebKitAPI/TestsController.h
index c73e3ac4d..ea8496853 100644
--- a/Tools/TestWebKitAPI/TestsController.h
+++ b/Tools/TestWebKitAPI/TestsController.h
@@ -26,17 +26,21 @@
#ifndef TestsController_h
#define TestsController_h
+#include <wtf/NeverDestroyed.h>
+
namespace TestWebKitAPI {
class TestsController {
public:
- static TestsController& shared();
+ static TestsController& singleton();
bool run(int argc, char** argv);
private:
TestsController();
~TestsController();
+
+ friend class WTF::NeverDestroyed<TestsController>;
};
} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/Utilities.h b/Tools/TestWebKitAPI/Utilities.h
new file mode 100644
index 000000000..f77d25c71
--- /dev/null
+++ b/Tools/TestWebKitAPI/Utilities.h
@@ -0,0 +1,36 @@
+/*
+ * 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. 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 INC. 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.
+ */
+
+#pragma once
+
+namespace TestWebKitAPI {
+namespace Util {
+
+// Runs a platform runloop until the 'done' is true.
+void run(bool* done);
+void sleep(double seconds);
+
+} // namespace Util
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/WKWebViewConfigurationExtras.h b/Tools/TestWebKitAPI/WKWebViewConfigurationExtras.h
new file mode 100644
index 000000000..782da85d4
--- /dev/null
+++ b/Tools/TestWebKitAPI/WKWebViewConfigurationExtras.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015 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. 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 INC. 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 <WebKit/WKWebViewConfiguration.h>
+
+#if WK_API_ENABLED
+
+@interface WKWebViewConfiguration (TestWebKitAPIExtras)
++ (instancetype)testwebkitapi_configurationWithTestPlugInClassName:(NSString *)className;
+@end
+
+#endif // WK_API_ENABLED
diff --git a/Tools/TestWebKitAPI/WTFStringUtilities.h b/Tools/TestWebKitAPI/WTFStringUtilities.h
index 29a876788..ecba9c4b2 100644
--- a/Tools/TestWebKitAPI/WTFStringUtilities.h
+++ b/Tools/TestWebKitAPI/WTFStringUtilities.h
@@ -28,8 +28,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef WTFStringUtilities_h
-#define WTFStringUtilities_h
+#pragma once
#include <wtf/Assertions.h>
#include <wtf/text/CString.h>
@@ -45,4 +44,12 @@ inline std::ostream& operator<<(std::ostream& os, const String& string)
}
-#endif // WTFStringUtilities_h
+template<size_t length>
+static String utf16String(const char16_t (&url)[length])
+{
+ StringBuilder builder;
+ builder.reserveCapacity(length - 1);
+ for (size_t i = 0; i < length - 1; ++i)
+ builder.append(static_cast<UChar>(url[i]));
+ return builder.toString();
+}
diff --git a/Tools/TestWebKitAPI/config.h b/Tools/TestWebKitAPI/config.h
index 0fb19e1c3..c5ce18bc0 100644
--- a/Tools/TestWebKitAPI/config.h
+++ b/Tools/TestWebKitAPI/config.h
@@ -23,17 +23,14 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H
-#ifdef BUILDING_WITH_CMAKE
+#if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H && defined(BUILDING_WITH_CMAKE)
#include "cmakeconfig.h"
-#else
-#include "autotoolsconfig.h"
-#endif
#endif
-#include <wtf/Platform.h>
-#include <wtf/ExportMacros.h>
#include <runtime/JSExportMacros.h>
+#ifndef BUILDING_JSCONLY__
+#include <WebCore/PlatformExportMacros.h>
+#endif
#if defined(__APPLE__) && __APPLE__
@@ -52,24 +49,24 @@
#endif
#if PLATFORM(WIN_CAIRO)
-#undef WTF_USE_CG
-#define WTF_USE_CAIRO 1
-#define WTF_USE_CURL 1
+#undef USE_CG
+#define USE_CAIRO 1
+#define USE_CURL 1
#ifndef _WINSOCKAPI_
#define _WINSOCKAPI_ // Prevent inclusion of winsock.h in windows.h
#endif
-#elif !OS(WINCE)
-#define WTF_USE_CG 1
-#undef WTF_USE_CAIRO
-#undef WTF_USE_CURL
+#else
+#define USE_CG 1
+#undef USE_CAIRO
+#undef USE_CURL
#endif
#endif // PLATFORM(WIN)
#include <stdint.h>
-#if !PLATFORM(IOS) && !PLATFORM(WIN) && !(PLATFORM(GTK) && !defined(BUILDING_WEBKIT2__))
-#include <WebKit2/WebKit2_C.h>
+#if !PLATFORM(IOS) && !PLATFORM(WIN) && !defined(BUILDING_JSCONLY__)
+#include <WebKit/WebKit2_C.h>
#endif
#ifdef __clang__
@@ -87,6 +84,13 @@
#pragma clang diagnostic pop
#endif
-#if PLATFORM(MAC) && defined(__OBJC__)
+#if PLATFORM(COCOA) && defined(__OBJC__)
+// FIXME: Get Cocoa tests working with CMake on Mac.
+#if !defined(BUILDING_WITH_CMAKE)
#import <WebKit/WebKit.h>
#endif
+#endif
+
+#if !PLATFORM(IOS) && !defined(BUILDING_JSCONLY__)
+#define WK_HAVE_C_SPI 1
+#endif
diff --git a/Tools/TestWebKitAPI/gtk/PlatformUtilitiesGtk.cpp b/Tools/TestWebKitAPI/gtk/PlatformUtilitiesGtk.cpp
index ee65dcab2..f7b231fcc 100644
--- a/Tools/TestWebKitAPI/gtk/PlatformUtilitiesGtk.cpp
+++ b/Tools/TestWebKitAPI/gtk/PlatformUtilitiesGtk.cpp
@@ -27,8 +27,8 @@
#include "PlatformUtilities.h"
#include <gtk/gtk.h>
-#include <wtf/gobject/GRefPtr.h>
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/glib/GUniquePtr.h>
namespace TestWebKitAPI {
namespace Util {
@@ -68,7 +68,7 @@ static char* getFilenameFromEnvironmentVariableAsUTF8(const char* variableName)
WKStringRef createInjectedBundlePath()
{
GUniquePtr<char> injectedBundlePath(getFilenameFromEnvironmentVariableAsUTF8("TEST_WEBKIT_API_WEBKIT2_INJECTED_BUNDLE_PATH"));
- GUniquePtr<char> injectedBundleFilename(g_build_filename(injectedBundlePath.get(), "libTestWebKitAPIInjectedBundle.la", nullptr));
+ GUniquePtr<char> injectedBundleFilename(g_build_filename(injectedBundlePath.get(), "libTestWebKitAPIInjectedBundle.so", nullptr));
return WKStringCreateWithUTF8CString(injectedBundleFilename.get());
}
diff --git a/Tools/TestWebKitAPI/gtk/PlatformWebViewGtk.cpp b/Tools/TestWebKitAPI/gtk/PlatformWebViewGtk.cpp
index 03160419e..0feb2b54a 100644
--- a/Tools/TestWebKitAPI/gtk/PlatformWebViewGtk.cpp
+++ b/Tools/TestWebKitAPI/gtk/PlatformWebViewGtk.cpp
@@ -27,18 +27,35 @@
#include "PlatformWebView.h"
#include <WebCore/GUniquePtrGtk.h>
+#include <WebKit/WKRetainPtr.h>
+#include <WebKit/WKView.h>
#include <gtk/gtk.h>
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GUniquePtr.h>
namespace TestWebKitAPI {
PlatformWebView::PlatformWebView(WKContextRef contextRef, WKPageGroupRef pageGroupRef)
{
- m_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- m_view = WKViewCreate(contextRef, pageGroupRef);
- gtk_container_add(GTK_CONTAINER(m_window), GTK_WIDGET(m_view));
- gtk_widget_show(GTK_WIDGET(m_view));
- gtk_widget_show(m_window);
+ WKRetainPtr<WKPageConfigurationRef> configuration = adoptWK(WKPageConfigurationCreate());
+ WKPageConfigurationSetContext(configuration.get(), contextRef);
+ WKPageConfigurationSetPageGroup(configuration.get(), pageGroupRef);
+
+ initialize(configuration.get());
+}
+
+PlatformWebView::PlatformWebView(WKPageConfigurationRef configuration)
+{
+ initialize(configuration);
+}
+
+PlatformWebView::PlatformWebView(WKPageRef relatedPage)
+{
+ WKRetainPtr<WKPageConfigurationRef> configuration = adoptWK(WKPageConfigurationCreate());
+ WKPageConfigurationSetContext(configuration.get(), WKPageGetContext(relatedPage));
+ WKPageConfigurationSetPageGroup(configuration.get(), WKPageGetPageGroup(relatedPage));
+ WKPageConfigurationSetRelatedPage(configuration.get(), relatedPage);
+
+ initialize(configuration.get());
}
PlatformWebView::~PlatformWebView()
@@ -46,6 +63,15 @@ PlatformWebView::~PlatformWebView()
gtk_widget_destroy(m_window);
}
+void PlatformWebView::initialize(WKPageConfigurationRef configuration)
+{
+ m_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ m_view = WKViewCreate(configuration);
+ gtk_container_add(GTK_CONTAINER(m_window), GTK_WIDGET(m_view));
+ gtk_widget_show(GTK_WIDGET(m_view));
+ gtk_widget_show(m_window);
+}
+
WKPageRef PlatformWebView::page() const
{
return WKViewGetPage(m_view);
@@ -122,7 +148,7 @@ void PlatformWebView::simulateRightClick(unsigned x, unsigned y)
doMouseButtonEvent(viewWidget, GDK_BUTTON_RELEASE, x, y, 3);
}
-void PlatformWebView::simulateMouseMove(unsigned x, unsigned y)
+void PlatformWebView::simulateMouseMove(unsigned x, unsigned y, WKEventModifiers)
{
GUniquePtr<GdkEvent> event(gdk_event_new(GDK_MOTION_NOTIFY));
event->motion.x = x;
diff --git a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.cpp b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.cpp
index 211fa8b82..4a260b812 100644
--- a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.cpp
+++ b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.cpp
@@ -39,7 +39,7 @@ static void loadChangedCallback(WebKitWebView* webView, WebKitLoadEvent loadEven
break;
case WEBKIT_LOAD_COMMITTED: {
g_assert(webkit_web_view_is_loading(webView));
- g_assert_cmpstr(test->m_activeURI.data(), ==, webkit_web_view_get_uri(webView));
+ test->m_activeURI = webkit_web_view_get_uri(webView);
// Check that on committed we always have a main resource with a response.
WebKitWebResource* resource = webkit_web_view_get_main_resource(webView);
@@ -50,9 +50,15 @@ static void loadChangedCallback(WebKitWebView* webView, WebKitLoadEvent loadEven
break;
}
case WEBKIT_LOAD_FINISHED:
- g_assert(!webkit_web_view_is_loading(webView));
- if (!test->m_loadFailed)
+ if (!test->m_loadFailed) {
+ g_assert(!webkit_web_view_is_loading(webView));
g_assert_cmpstr(test->m_activeURI.data(), ==, webkit_web_view_get_uri(webView));
+ } else if (!g_error_matches(test->m_error.get(), WEBKIT_NETWORK_ERROR, WEBKIT_NETWORK_ERROR_CANCELLED)) {
+ // When a new load is started before the previous one has finished, we receive the load-finished signal
+ // of the ongoing load while we already have a provisional URL for the new load. This is the only case
+ // where isloading is true when the load has finished.
+ g_assert(!webkit_web_view_is_loading(webView));
+ }
test->loadFinished();
break;
default:
@@ -63,19 +69,24 @@ static void loadChangedCallback(WebKitWebView* webView, WebKitLoadEvent loadEven
static void loadFailedCallback(WebKitWebView* webView, WebKitLoadEvent loadEvent, const char* failingURI, GError* error, LoadTrackingTest* test)
{
test->m_loadFailed = true;
+
+ g_assert(error);
test->m_error.reset(g_error_copy(error));
+ if (!g_error_matches(error, WEBKIT_NETWORK_ERROR, WEBKIT_NETWORK_ERROR_CANCELLED)) {
+ // When a new load is started before the previous one has finished, we receive the load-failed signal
+ // of the ongoing load while we already have a provisional URL for the new load. This is the only case
+ // where is-loading is true when the load has failed.
+ g_assert(!webkit_web_view_is_loading(webView));
+ }
+
switch (loadEvent) {
case WEBKIT_LOAD_STARTED:
- g_assert(!webkit_web_view_is_loading(webView));
- g_assert_cmpstr(test->m_activeURI.data(), ==, webkit_web_view_get_uri(webView));
- g_assert(error);
+ g_assert_cmpstr(test->m_activeURI.data(), ==, failingURI);
test->provisionalLoadFailed(failingURI, error);
break;
case WEBKIT_LOAD_COMMITTED:
- g_assert(!webkit_web_view_is_loading(webView));
g_assert_cmpstr(test->m_activeURI.data(), ==, webkit_web_view_get_uri(webView));
- g_assert(error);
test->loadFailed(failingURI, error);
break;
default:
@@ -83,6 +94,16 @@ static void loadFailedCallback(WebKitWebView* webView, WebKitLoadEvent loadEvent
}
}
+static gboolean loadFailedWithTLSErrorsCallback(WebKitWebView* webView, const char* failingURI, GTlsCertificate* certificate, GTlsCertificateFlags tlsErrors, LoadTrackingTest* test)
+{
+ test->m_loadFailed = true;
+ g_assert(!webkit_web_view_is_loading(webView));
+ g_assert_cmpstr(test->m_activeURI.data(), ==, failingURI);
+ g_assert(G_IS_TLS_CERTIFICATE(certificate));
+ g_assert(tlsErrors);
+ return test->loadFailedWithTLSErrors(failingURI, certificate, tlsErrors);
+}
+
static void estimatedProgressChangedCallback(GObject*, GParamSpec*, LoadTrackingTest* test)
{
test->estimatedProgressChanged();
@@ -94,6 +115,7 @@ LoadTrackingTest::LoadTrackingTest()
{
g_signal_connect(m_webView, "load-changed", G_CALLBACK(loadChangedCallback), this);
g_signal_connect(m_webView, "load-failed", G_CALLBACK(loadFailedCallback), this);
+ g_signal_connect(m_webView, "load-failed-with-tls-errors", G_CALLBACK(loadFailedWithTLSErrorsCallback), this);
g_signal_connect(m_webView, "notify::estimated-load-progress", G_CALLBACK(estimatedProgressChangedCallback), this);
g_assert(!webkit_web_view_get_uri(m_webView));
@@ -143,6 +165,12 @@ void LoadTrackingTest::loadFailed(const gchar* failingURI, GError* error)
m_loadEvents.append(LoadFailed);
}
+bool LoadTrackingTest::loadFailedWithTLSErrors(const gchar* /*failingURI*/, GTlsCertificate*, GTlsCertificateFlags)
+{
+ m_loadEvents.append(LoadFailedWithTLSErrors);
+ return false;
+}
+
void LoadTrackingTest::estimatedProgressChanged()
{
double progress = webkit_web_view_get_estimated_load_progress(m_webView);
@@ -152,56 +180,57 @@ void LoadTrackingTest::estimatedProgressChanged()
void LoadTrackingTest::loadURI(const char* uri)
{
- m_loadEvents.clear();
- m_estimatedProgress = 0;
- m_error.reset();
+ reset();
WebViewTest::loadURI(uri);
}
void LoadTrackingTest::loadHtml(const char* html, const char* baseURI)
{
- m_loadEvents.clear();
- m_estimatedProgress = 0;
- m_error.reset();
+ reset();
WebViewTest::loadHtml(html, baseURI);
}
void LoadTrackingTest::loadPlainText(const char* plainText)
{
- m_loadEvents.clear();
- m_estimatedProgress = 0;
- m_error.reset();
+ reset();
WebViewTest::loadPlainText(plainText);
}
+void LoadTrackingTest::loadBytes(GBytes* bytes, const char* mimeType, const char* encoding, const char* baseURI)
+{
+ reset();
+ WebViewTest::loadBytes(bytes, mimeType, encoding, baseURI);
+}
+
void LoadTrackingTest::loadRequest(WebKitURIRequest* request)
{
- m_loadEvents.clear();
- m_estimatedProgress = 0;
- m_error.reset();
+ reset();
WebViewTest::loadRequest(request);
}
void LoadTrackingTest::reload()
{
- m_loadEvents.clear();
- m_estimatedProgress = 0;
- m_error.reset();
+ reset();
webkit_web_view_reload(m_webView);
}
void LoadTrackingTest::goBack()
{
- m_loadEvents.clear();
- m_estimatedProgress = 0;
- m_error.reset();
+ reset();
WebViewTest::goBack();
}
void LoadTrackingTest::goForward()
{
+ reset();
+ WebViewTest::goForward();
+}
+
+void LoadTrackingTest::reset()
+{
+ m_runLoadUntilCompletion = false;
+ m_loadFailed = false;
m_loadEvents.clear();
m_estimatedProgress = 0;
m_error.reset();
- WebViewTest::goForward();
}
diff --git a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.h b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.h
index d0ed1e57f..d6f3129b0 100644
--- a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.h
+++ b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/LoadTrackingTest.h
@@ -34,6 +34,7 @@ public:
virtual void provisionalLoadStarted();
virtual void provisionalLoadReceivedServerRedirect();
virtual void provisionalLoadFailed(const gchar* failingURI, GError*);
+ virtual bool loadFailedWithTLSErrors(const gchar* failingURI, GTlsCertificate*, GTlsCertificateFlags);
virtual void loadCommitted();
virtual void loadFinished();
virtual void loadFailed(const char* failingURI, GError*);
@@ -43,9 +44,11 @@ public:
void loadHtml(const char* html, const char* baseURI);
void loadPlainText(const char* plainText);
void loadRequest(WebKitURIRequest*);
+ void loadBytes(GBytes*, const char* mimeType, const char* encoding, const char* baseURI);
void reload();
void goBack();
void goForward();
+ void reset();
void setRedirectURI(const char* uri) { m_redirectURI = uri; }
@@ -55,7 +58,8 @@ public:
ProvisionalLoadFailed,
LoadCommitted,
LoadFinished,
- LoadFailed
+ LoadFailed,
+ LoadFailedWithTLSErrors
};
bool m_runLoadUntilCompletion;
bool m_loadFailed;
diff --git a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.cpp b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.cpp
index 61331a3d3..80809400d 100644
--- a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.cpp
+++ b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.cpp
@@ -22,12 +22,19 @@
#include <glib/gstdio.h>
#include <gtk/gtk.h>
-#include <webkit2/webkit2.h>
-#include <wtf/gobject/GUniquePtr.h>
+
+uint32_t Test::s_webExtensionID = 0;
void beforeAll();
void afterAll();
+static GUniquePtr<char> testDataDirectory(g_dir_make_tmp("WebKit2GtkTests-XXXXXX", nullptr));
+
+const char* Test::dataDirectory()
+{
+ return testDataDirectory.get();
+}
+
static void registerGResource(void)
{
GUniquePtr<char> resourcesPath(g_build_filename(WEBKIT_EXEC_PATH, "TestWebKitAPI", "WebKit2Gtk", "resources", "webkit2gtk-tests-resources.gresource", nullptr));
@@ -45,7 +52,10 @@ static void removeNonEmptyDirectory(const char* directoryPath)
const char* fileName;
while ((fileName = g_dir_read_name(directory))) {
GUniquePtr<char> filePath(g_build_filename(directoryPath, fileName, nullptr));
- g_unlink(filePath.get());
+ if (g_file_test(filePath.get(), G_FILE_TEST_IS_DIR))
+ removeNonEmptyDirectory(filePath.get());
+ else
+ g_unlink(filePath.get());
}
g_dir_close(directory);
g_rmdir(directoryPath);
@@ -66,15 +76,12 @@ int main(int argc, char** argv)
registerGResource();
- GUniquePtr<char> diskCacheTempDirectory(g_dir_make_tmp("WebKit2TestsDiskCache-XXXXXX", 0));
- g_assert(diskCacheTempDirectory.get());
- webkit_web_context_set_disk_cache_directory(webkit_web_context_get_default(), diskCacheTempDirectory.get());
-
beforeAll();
int returnValue = g_test_run();
afterAll();
- removeNonEmptyDirectory(diskCacheTempDirectory.get());
+ removeNonEmptyDirectory(testDataDirectory.get());
return returnValue;
}
+
diff --git a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.h b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.h
index 9fab0b2ff..f68af2a96 100644
--- a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.h
+++ b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.h
@@ -22,8 +22,10 @@
#include <cairo.h>
#include <glib-object.h>
+#include <webkit2/webkit2.h>
#include <wtf/HashSet.h>
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/glib/GUniquePtr.h>
#include <wtf/text/CString.h>
#define MAKE_GLIB_TEST_FIXTURE(ClassName) \
@@ -41,6 +43,25 @@
g_test_add(testPath.get(), ClassName, 0, ClassName::setUp, testFunc, ClassName::tearDown); \
}
+#define MAKE_GLIB_TEST_FIXTURE_WITH_SETUP_TEARDOWN(ClassName, setup, teardown) \
+ static void setUp(ClassName* fixture, gconstpointer data) \
+ { \
+ if (setup) \
+ setup(); \
+ new (fixture) ClassName; \
+ } \
+ static void tearDown(ClassName* fixture, gconstpointer data) \
+ { \
+ fixture->~ClassName(); \
+ if (teardown) \
+ teardown(); \
+ } \
+ static void add(const char* suiteName, const char* testName, void (*testFunc)(ClassName*, const void*)) \
+ { \
+ GUniquePtr<gchar> testPath(g_strdup_printf("/webkit2/%s/%s", suiteName, testName)); \
+ g_test_add(testPath.get(), ClassName, 0, ClassName::setUp, testFunc, ClassName::tearDown); \
+ }
+
#define ASSERT_CMP_CSTRING(s1, cmp, s2) \
do { \
CString __s1 = (s1); \
@@ -56,8 +77,33 @@ class Test {
public:
MAKE_GLIB_TEST_FIXTURE(Test);
+ static const char* dataDirectory();
+
+ static void initializeWebExtensionsCallback(WebKitWebContext* context, Test* test)
+ {
+ test->initializeWebExtensions();
+ }
+
+ Test()
+ {
+ GUniquePtr<char> localStorageDirectory(g_build_filename(dataDirectory(), "local-storage", nullptr));
+ GUniquePtr<char> indexedDBDirectory(g_build_filename(dataDirectory(), "indexeddb", nullptr));
+ GUniquePtr<char> diskCacheDirectory(g_build_filename(dataDirectory(), "disk-cache", nullptr));
+ GUniquePtr<char> applicationCacheDirectory(g_build_filename(dataDirectory(), "appcache", nullptr));
+ GUniquePtr<char> webSQLDirectory(g_build_filename(dataDirectory(), "websql", nullptr));
+ GRefPtr<WebKitWebsiteDataManager> websiteDataManager = adoptGRef(webkit_website_data_manager_new(
+ "local-storage-directory", localStorageDirectory.get(), "indexeddb-directory", indexedDBDirectory.get(),
+ "disk-cache-directory", diskCacheDirectory.get(), "offline-application-cache-directory", applicationCacheDirectory.get(),
+ "websql-directory", webSQLDirectory.get(), nullptr));
+
+ m_webContext = adoptGRef(webkit_web_context_new_with_website_data_manager(websiteDataManager.get()));
+ g_signal_connect(m_webContext.get(), "initialize-web-extensions", G_CALLBACK(initializeWebExtensionsCallback), this);
+ }
+
~Test()
{
+ g_signal_handlers_disconnect_matched(m_webContext.get(), G_SIGNAL_MATCH_DATA, 0, 0, nullptr, nullptr, this);
+ m_webContext = nullptr;
if (m_watchedObjects.isEmpty())
return;
@@ -70,6 +116,12 @@ public:
g_assert(m_watchedObjects.isEmpty());
}
+ virtual void initializeWebExtensions()
+ {
+ webkit_web_context_set_web_extensions_directory(m_webContext.get(), WEBKIT_TEST_WEB_EXTENSIONS_DIR);
+ webkit_web_context_set_web_extensions_initialization_user_data(m_webContext.get(), g_variant_new_uint32(++s_webExtensionID));
+ }
+
static void objectFinalized(Test* test, GObject* finalizedObject)
{
test->m_watchedObjects.remove(finalizedObject);
@@ -81,16 +133,24 @@ public:
g_object_weak_ref(object, reinterpret_cast<GWeakNotify>(objectFinalized), this);
}
- static CString getWebKit1TestResoucesDir()
- {
- GUniquePtr<char> resourcesDir(g_build_filename(WEBKIT_SRC_DIR, "Tools", "TestWebKitAPI", "Tests", "WebKitGtk", "resources", nullptr));
- return resourcesDir.get();
- }
- static CString getResourcesDir()
+ enum ResourcesDir {
+ WebKit2GTKResources,
+ WebKit2Resources,
+ };
+
+ static CString getResourcesDir(ResourcesDir resourcesDir = WebKit2GTKResources)
{
- GUniquePtr<char> resourcesDir(g_build_filename(WEBKIT_SRC_DIR, "Tools", "TestWebKitAPI", "Tests", "WebKit2Gtk", "resources", nullptr));
- return resourcesDir.get();
+ switch (resourcesDir) {
+ case WebKit2GTKResources: {
+ GUniquePtr<char> resourcesDir(g_build_filename(WEBKIT_SRC_DIR, "Tools", "TestWebKitAPI", "Tests", "WebKit2Gtk", "resources", nullptr));
+ return resourcesDir.get();
+ }
+ case WebKit2Resources: {
+ GUniquePtr<char> resourcesDir(g_build_filename(WEBKIT_SRC_DIR, "Tools", "TestWebKitAPI", "Tests", "WebKit2", nullptr));
+ return resourcesDir.get();
+ }
+ }
}
void addLogFatalFlag(unsigned flag)
@@ -119,6 +179,8 @@ public:
}
HashSet<GObject*> m_watchedObjects;
+ GRefPtr<WebKitWebContext> m_webContext;
+ static uint32_t s_webExtensionID;
};
#endif // TestMain_h
diff --git a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.cpp b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.cpp
index 35bcf1bd6..88456ce4f 100644
--- a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.cpp
+++ b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.cpp
@@ -20,53 +20,23 @@
#include "config.h"
#include "WebKitTestBus.h"
-#include <wtf/gobject/GUniquePtr.h>
-#include <wtf/text/WTFString.h>
-
WebKitTestBus::WebKitTestBus()
- : m_pid(-1)
+ : m_bus(adoptGRef(g_test_dbus_new(G_TEST_DBUS_NONE)))
{
}
-bool WebKitTestBus::run()
+WebKitTestBus::~WebKitTestBus()
{
- // FIXME: Use GTestDBus when we bump glib to 2.34.
- GUniquePtr<char> dbusLaunch(g_find_program_in_path("dbus-launch"));
- if (!dbusLaunch) {
- g_warning("Error starting DBUS daemon: dbus-launch not found in path");
- return false;
- }
-
- GUniqueOutPtr<char> output;
- GUniqueOutPtr<GError> error;
- if (!g_spawn_command_line_sync(dbusLaunch.get(), &output.outPtr(), 0, 0, &error.outPtr())) {
- g_warning("Error starting DBUS daemon: %s", error->message);
- return false;
- }
-
- String outputString = String::fromUTF8(output.get());
- Vector<String> lines;
- outputString.split(UChar('\n'), /* allowEmptyEntries */ false, lines);
- for (size_t i = 0; i < lines.size(); ++i) {
- char** keyValue = g_strsplit(lines[i].utf8().data(), "=", 2);
- g_assert_cmpuint(g_strv_length(keyValue), ==, 2);
- if (!g_strcmp0(keyValue[0], "DBUS_SESSION_BUS_ADDRESS")) {
- m_address = keyValue[1];
- g_setenv("DBUS_SESSION_BUS_ADDRESS", keyValue[1], TRUE);
- } else if (!g_strcmp0(keyValue[0], "DBUS_SESSION_BUS_PID"))
- m_pid = g_ascii_strtoll(keyValue[1], 0, 10);
- g_strfreev(keyValue);
- }
-
- return m_pid > 0;
+ g_test_dbus_down(m_bus.get());
}
-WebKitTestBus::~WebKitTestBus()
+bool WebKitTestBus::run()
{
- g_unsetenv("DBUS_SESSION_BUS_ADDRESS");
-
- if (m_pid != -1)
- kill(m_pid, SIGTERM);
+ CString display = g_getenv("DISPLAY");
+ g_test_dbus_up(m_bus.get());
+ m_address = g_test_dbus_get_bus_address(m_bus.get());
+ g_setenv("DISPLAY", display.data(), FALSE);
+ return !m_address.isNull();
}
GDBusConnection* WebKitTestBus::getOrCreateConnection()
@@ -77,7 +47,8 @@ GDBusConnection* WebKitTestBus::getOrCreateConnection()
g_assert(!m_address.isNull());
m_connection = adoptGRef(g_dbus_connection_new_for_address_sync(m_address.data(),
static_cast<GDBusConnectionFlags>(G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION),
- 0, 0, 0));
+ nullptr, nullptr, nullptr));
+ g_assert(m_connection.get());
return m_connection.get();
}
@@ -88,19 +59,19 @@ static void onNameAppeared(GDBusConnection*, const char*, const char*, gpointer
GDBusProxy* WebKitTestBus::createProxy(const char* serviceName, const char* objectPath, const char* interfaceName, GMainLoop* mainLoop)
{
- unsigned watcherID = g_bus_watch_name_on_connection(getOrCreateConnection(), serviceName, G_BUS_NAME_WATCHER_FLAGS_NONE, onNameAppeared, 0, mainLoop, 0);
+ unsigned watcherID = g_bus_watch_name_on_connection(getOrCreateConnection(), serviceName, G_BUS_NAME_WATCHER_FLAGS_NONE, onNameAppeared, nullptr, mainLoop, nullptr);
g_main_loop_run(mainLoop);
g_bus_unwatch_name(watcherID);
GDBusProxy* proxy = g_dbus_proxy_new_sync(
connection(),
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
- 0, // GDBusInterfaceInfo
+ nullptr, // GDBusInterfaceInfo
serviceName,
objectPath,
interfaceName,
- 0, // GCancellable
- 0);
+ nullptr, // GCancellable
+ nullptr);
g_assert(proxy);
return proxy;
}
diff --git a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.h b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.h
index b9f856b27..b8a8e6041 100644
--- a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.h
+++ b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.h
@@ -21,13 +21,13 @@
#define WebKitTestBus_h
#include <gio/gio.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/glib/GRefPtr.h>
#include <wtf/text/CString.h>
class WebKitTestBus {
public:
WebKitTestBus();
- virtual ~WebKitTestBus();
+ ~WebKitTestBus();
bool run();
GDBusProxy* createProxy(const char* serviceName, const char* objectPath, const char* interfaceName, GMainLoop*);
@@ -36,7 +36,7 @@ public:
private:
GDBusConnection* getOrCreateConnection();
- pid_t m_pid;
+ GRefPtr<GTestDBus> m_bus;
CString m_address;
GRefPtr<GDBusConnection> m_connection;
};
diff --git a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.cpp b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.cpp
index 8736771fa..de9466c39 100644
--- a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.cpp
+++ b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.cpp
@@ -21,13 +21,19 @@
#include "WebKitTestServer.h"
#include "TestMain.h"
-#include <wtf/gobject/GUniquePtr.h>
+#include <wtf/Threading.h>
+#include <wtf/glib/GUniquePtr.h>
-WebKitTestServer::WebKitTestServer(ServerType type)
+WebKitTestServer::WebKitTestServer(ServerOptions options)
{
+ if (options & ServerRunInThread) {
+ WTF::initializeThreading();
+ m_queue = WorkQueue::create("WebKitTestServer");
+ }
+
GUniquePtr<char> sslCertificateFile;
GUniquePtr<char> sslKeyFile;
- if (type == ServerHTTPS) {
+ if (options & ServerHTTPS) {
CString resourcesDir = Test::getResourcesDir();
sslCertificateFile.reset(g_build_filename(resourcesDir.data(), "test-cert.pem", NULL));
sslKeyFile.reset(g_build_filename(resourcesDir.data(), "test-key.pem", NULL));
@@ -37,9 +43,10 @@ WebKitTestServer::WebKitTestServer(ServerType type)
soup_address_resolve_sync(address.get(), 0);
m_soupServer = adoptGRef(soup_server_new(SOUP_SERVER_INTERFACE, address.get(),
+ SOUP_SERVER_ASYNC_CONTEXT, m_queue ? m_queue->runLoop().mainContext() : nullptr,
SOUP_SERVER_SSL_CERT_FILE, sslCertificateFile.get(),
SOUP_SERVER_SSL_KEY_FILE, sslKeyFile.get(), nullptr));
- m_baseURI = type == ServerHTTPS ? soup_uri_new("https://127.0.0.1/") : soup_uri_new("http://127.0.0.1/");
+ m_baseURI = options & ServerHTTPS ? soup_uri_new("https://127.0.0.1/") : soup_uri_new("http://127.0.0.1/");
soup_uri_set_port(m_baseURI, soup_server_get_port(m_soupServer.get()));
}
@@ -50,8 +57,15 @@ WebKitTestServer::~WebKitTestServer()
void WebKitTestServer::run(SoupServerCallback serverCallback)
{
- soup_server_run_async(m_soupServer.get());
- soup_server_add_handler(m_soupServer.get(), 0, serverCallback, 0, 0);
+ if (m_queue) {
+ m_queue->dispatch([this, serverCallback] {
+ soup_server_run_async(m_soupServer.get());
+ soup_server_add_handler(m_soupServer.get(), nullptr, serverCallback, nullptr, nullptr);
+ });
+ } else {
+ soup_server_run_async(m_soupServer.get());
+ soup_server_add_handler(m_soupServer.get(), nullptr, serverCallback, nullptr, nullptr);
+ }
}
CString WebKitTestServer::getURIForPath(const char* path)
diff --git a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.h b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.h
index 502f7fad0..58f019fab 100644
--- a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.h
+++ b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestServer.h
@@ -22,18 +22,20 @@
#include <libsoup/soup.h>
#include <webkit2/webkit2.h>
-#include <wtf/gobject/GRefPtr.h>
+#include <wtf/WorkQueue.h>
+#include <wtf/glib/GRefPtr.h>
#include <wtf/text/CString.h>
class WebKitTestServer {
public:
- enum ServerType {
- ServerHTTP,
- ServerHTTPS
+ enum ServerOptions {
+ ServerHTTP = 0,
+ ServerHTTPS = 1 << 1,
+ ServerRunInThread = 1 << 2,
};
- WebKitTestServer(ServerType = ServerHTTP);
+ WebKitTestServer(ServerOptions = ServerHTTP);
virtual ~WebKitTestServer();
SoupURI* baseURI() { return m_baseURI; }
@@ -44,6 +46,7 @@ public:
private:
GRefPtr<SoupServer> m_soupServer;
SoupURI* m_baseURI;
+ RefPtr<WorkQueue> m_queue;
};
#endif // WebKitTestServer_h
diff --git a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp
index f08bb4694..7071910e4 100644
--- a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp
+++ b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp
@@ -24,15 +24,15 @@
#include <JavaScriptCore/JSRetainPtr.h>
#include <WebCore/GUniquePtrGtk.h>
+bool WebViewTest::shouldInitializeWebViewInConstructor = true;
+
WebViewTest::WebViewTest()
- : m_webView(WEBKIT_WEB_VIEW(g_object_ref_sink(webkit_web_view_new())))
- , m_mainLoop(g_main_loop_new(0, TRUE))
- , m_parentWindow(0)
- , m_javascriptResult(0)
- , m_resourceDataSize(0)
- , m_surface(0)
+ : m_userContentManager(adoptGRef(webkit_user_content_manager_new()))
+ , m_mainLoop(g_main_loop_new(nullptr, TRUE))
{
- assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_webView));
+ if (shouldInitializeWebViewInConstructor)
+ initializeWebView();
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_userContentManager.get()));
}
WebViewTest::~WebViewTest()
@@ -47,10 +47,31 @@ WebViewTest::~WebViewTest()
g_main_loop_unref(m_mainLoop);
}
+void WebViewTest::initializeWebView()
+{
+ g_assert(!m_webView);
+ m_webView = WEBKIT_WEB_VIEW(g_object_ref_sink(g_object_new(WEBKIT_TYPE_WEB_VIEW, "web-context", m_webContext.get(), "user-content-manager", m_userContentManager.get(), nullptr)));
+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(m_webView));
+
+ g_signal_connect(m_webView, "web-process-crashed", G_CALLBACK(WebViewTest::webProcessCrashed), this);
+}
+
+gboolean WebViewTest::webProcessCrashed(WebKitWebView*, WebViewTest* test)
+{
+ if (test->m_expectedWebProcessCrash) {
+ test->m_expectedWebProcessCrash = false;
+ return FALSE;
+ }
+ g_assert_not_reached();
+ return TRUE;
+}
+
void WebViewTest::loadURI(const char* uri)
{
m_activeURI = uri;
webkit_web_view_load_uri(m_webView, uri);
+ g_assert(webkit_web_view_is_loading(m_webView));
+ g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data());
}
void WebViewTest::loadHtml(const char* html, const char* baseURI)
@@ -60,29 +81,49 @@ void WebViewTest::loadHtml(const char* html, const char* baseURI)
else
m_activeURI = baseURI;
webkit_web_view_load_html(m_webView, html, baseURI);
+ g_assert(webkit_web_view_is_loading(m_webView));
+ g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data());
}
void WebViewTest::loadPlainText(const char* plainText)
{
m_activeURI = "about:blank";
webkit_web_view_load_plain_text(m_webView, plainText);
+ g_assert(webkit_web_view_is_loading(m_webView));
+ g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data());
+}
+
+void WebViewTest::loadBytes(GBytes* bytes, const char* mimeType, const char* encoding, const char* baseURI)
+{
+ if (!baseURI)
+ m_activeURI = "about:blank";
+ else
+ m_activeURI = baseURI;
+ webkit_web_view_load_bytes(m_webView, bytes, mimeType, encoding, baseURI);
+ g_assert(webkit_web_view_is_loading(m_webView));
+ g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data());
}
void WebViewTest::loadRequest(WebKitURIRequest* request)
{
m_activeURI = webkit_uri_request_get_uri(request);
webkit_web_view_load_request(m_webView, request);
+ g_assert(webkit_web_view_is_loading(m_webView));
+ g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data());
}
void WebViewTest::loadAlternateHTML(const char* html, const char* contentURI, const char* baseURI)
{
m_activeURI = contentURI;
webkit_web_view_load_alternate_html(m_webView, html, contentURI, baseURI);
+ g_assert(webkit_web_view_is_loading(m_webView));
+ g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data());
}
void WebViewTest::goBack()
{
- if (webkit_web_view_can_go_back(m_webView)) {
+ bool canGoBack = webkit_web_view_can_go_back(m_webView);
+ if (canGoBack) {
WebKitBackForwardList* list = webkit_web_view_get_back_forward_list(m_webView);
WebKitBackForwardListItem* item = webkit_back_forward_list_get_nth_item(list, -1);
m_activeURI = webkit_back_forward_list_item_get_original_uri(item);
@@ -90,11 +131,16 @@ void WebViewTest::goBack()
// Call go_back even when can_go_back returns FALSE to check nothing happens.
webkit_web_view_go_back(m_webView);
+ if (canGoBack) {
+ g_assert(webkit_web_view_is_loading(m_webView));
+ g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data());
+ }
}
void WebViewTest::goForward()
{
- if (webkit_web_view_can_go_forward(m_webView)) {
+ bool canGoForward = webkit_web_view_can_go_forward(m_webView);
+ if (canGoForward) {
WebKitBackForwardList* list = webkit_web_view_get_back_forward_list(m_webView);
WebKitBackForwardListItem* item = webkit_back_forward_list_get_nth_item(list, 1);
m_activeURI = webkit_back_forward_list_item_get_original_uri(item);
@@ -102,12 +148,18 @@ void WebViewTest::goForward()
// Call go_forward even when can_go_forward returns FALSE to check nothing happens.
webkit_web_view_go_forward(m_webView);
+ if (canGoForward) {
+ g_assert(webkit_web_view_is_loading(m_webView));
+ g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data());
+ }
}
void WebViewTest::goToBackForwardListItem(WebKitBackForwardListItem* item)
{
m_activeURI = webkit_back_forward_list_item_get_original_uri(item);
webkit_web_view_go_to_back_forward_list_item(m_webView, item);
+ g_assert(webkit_web_view_is_loading(m_webView));
+ g_assert_cmpstr(webkit_web_view_get_uri(m_webView), ==, m_activeURI.data());
}
void WebViewTest::quitMainLoop()
@@ -122,15 +174,12 @@ void WebViewTest::quitMainLoopAfterProcessingPendingEvents()
quitMainLoop();
}
-static gboolean quitMainLoopIdleCallback(WebViewTest* test)
-{
- test->quitMainLoop();
- return FALSE;
-}
-
void WebViewTest::wait(double seconds)
{
- g_timeout_add_seconds(seconds, reinterpret_cast<GSourceFunc>(quitMainLoopIdleCallback), this);
+ g_timeout_add(seconds * 1000, [](gpointer userData) -> gboolean {
+ static_cast<WebViewTest*>(userData)->quitMainLoop();
+ return G_SOURCE_REMOVE;
+ }, this);
g_main_loop_run(m_mainLoop);
}
@@ -217,6 +266,16 @@ void WebViewTest::selectAll()
webkit_web_view_execute_editing_command(m_webView, "SelectAll");
}
+bool WebViewTest::isEditable()
+{
+ return webkit_web_view_is_editable(m_webView);
+}
+
+void WebViewTest::setEditable(bool editable)
+{
+ webkit_web_view_set_editable(m_webView, editable);
+}
+
static void resourceGetDataCallback(GObject* object, GAsyncResult* result, gpointer userData)
{
size_t dataSize;
@@ -274,6 +333,15 @@ void WebViewTest::clickMouseButton(int x, int y, unsigned button, unsigned mouse
doMouseButtonEvent(GDK_BUTTON_RELEASE, x, y, button, mouseModifiers);
}
+void WebViewTest::emitPopupMenuSignal()
+{
+ GtkWidget* viewWidget = GTK_WIDGET(m_webView);
+ g_assert(gtk_widget_get_realized(viewWidget));
+
+ gboolean handled;
+ g_signal_emit_by_name(viewWidget, "popup-menu", &handled);
+}
+
void WebViewTest::keyStroke(unsigned keyVal, unsigned keyModifiers)
{
g_assert(m_parentWindow);
diff --git a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h
index 93a78a4d7..cfcc6c7dc 100644
--- a/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h
+++ b/Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h
@@ -31,10 +31,14 @@ public:
WebViewTest();
virtual ~WebViewTest();
+ static bool shouldInitializeWebViewInConstructor;
+ void initializeWebView();
+
virtual void loadURI(const char* uri);
virtual void loadHtml(const char* html, const char* baseURI);
virtual void loadPlainText(const char* plainText);
virtual void loadRequest(WebKitURIRequest*);
+ virtual void loadBytes(GBytes*, const char* mimeType, const char* encoding, const char* baseURI);
void loadAlternateHTML(const char* html, const char* contentURI, const char* baseURI);
void goBack();
void goForward();
@@ -52,10 +56,15 @@ public:
void selectAll();
const char* mainResourceData(size_t& mainResourceDataSize);
+ bool isEditable();
+ void setEditable(bool);
+
void mouseMoveTo(int x, int y, unsigned mouseModifiers = 0);
void clickMouseButton(int x, int y, unsigned button = 1, unsigned mouseModifiers = 0);
void keyStroke(unsigned keyVal, unsigned keyModifiers = 0);
+ void emitPopupMenuSignal();
+
WebKitJavascriptResult* runJavaScriptAndWaitUntilFinished(const char* javascript, GError**);
WebKitJavascriptResult* runJavaScriptFromGResourceAndWaitUntilFinished(const char* resource, GError**);
@@ -70,16 +79,24 @@ public:
bool runWebProcessTest(const char* suiteName, const char* testName);
- WebKitWebView* m_webView;
+ // Prohibit overrides because this is called when the web view is created
+ // in our constructor, before a derived class's vtable is ready.
+ void initializeWebExtensions() final { Test::initializeWebExtensions(); }
+
+ static gboolean webProcessCrashed(WebKitWebView*, WebViewTest*);
+
+ GRefPtr<WebKitUserContentManager> m_userContentManager;
+ WebKitWebView* m_webView { nullptr };
GMainLoop* m_mainLoop;
CString m_activeURI;
- GtkWidget* m_parentWindow;
+ GtkWidget* m_parentWindow { nullptr };
CString m_expectedTitle;
- WebKitJavascriptResult* m_javascriptResult;
- GError** m_javascriptError;
- GUniquePtr<char> m_resourceData;
- size_t m_resourceDataSize;
- cairo_surface_t* m_surface;
+ WebKitJavascriptResult* m_javascriptResult { nullptr };
+ GError** m_javascriptError { nullptr };
+ GUniquePtr<char> m_resourceData { nullptr };
+ size_t m_resourceDataSize { 0 };
+ cairo_surface_t* m_surface { nullptr };
+ bool m_expectedWebProcessCrash { false };
private:
void doMouseButtonEvent(GdkEventType, int, int, unsigned, unsigned);
diff --git a/Tools/TestWebKitAPI/gtk/main.cpp b/Tools/TestWebKitAPI/gtk/main.cpp
index 1b7fef64f..2c6856595 100644
--- a/Tools/TestWebKitAPI/gtk/main.cpp
+++ b/Tools/TestWebKitAPI/gtk/main.cpp
@@ -32,5 +32,5 @@ int main(int argc, char** argv)
{
gtk_init(&argc, &argv);
- return TestWebKitAPI::TestsController::shared().run(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE;
+ return TestWebKitAPI::TestsController::singleton().run(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE;
}
diff --git a/Tools/TestWebKitAPI/jsconly/PlatformUtilitiesJSCOnly.cpp b/Tools/TestWebKitAPI/jsconly/PlatformUtilitiesJSCOnly.cpp
new file mode 100644
index 000000000..41dc6b920
--- /dev/null
+++ b/Tools/TestWebKitAPI/jsconly/PlatformUtilitiesJSCOnly.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 Yusuke Suzuki <utatane.tea@gmail.com>
+ *
+ * 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.
+ */
+
+#include "config.h"
+#include "PlatformUtilities.h"
+
+#include <wtf/CurrentTime.h>
+#include <wtf/RunLoop.h>
+
+#if USE(GLIB_EVENT_LOOP)
+#include <glib.h>
+#include <wtf/glib/GRefPtr.h>
+#endif
+
+namespace TestWebKitAPI {
+namespace Util {
+
+void run(bool* done)
+{
+ while (!*done) {
+#if USE(GLIB_EVENT_LOOP)
+ g_main_context_iteration(RunLoop::current().mainContext(), false);
+#else
+ WTF::RunLoop::iterate();
+#endif
+ }
+}
+
+void sleep(double seconds)
+{
+ WTF::sleep(seconds);
+}
+
+} // namespace Util
+} // namespace TestWebKitAPI
diff --git a/Tools/TestWebKitAPI/jsconly/main.cpp b/Tools/TestWebKitAPI/jsconly/main.cpp
new file mode 100644
index 000000000..22b12cf4b
--- /dev/null
+++ b/Tools/TestWebKitAPI/jsconly/main.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2016 Yusuke Suzuki <utatane.tea@gmail.com>
+ *
+ * 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.
+ */
+
+#include "config.h"
+#include "TestsController.h"
+
+int main(int argc, char** argv)
+{
+ return TestWebKitAPI::TestsController::singleton().run(argc, argv) ? EXIT_SUCCESS : EXIT_FAILURE;
+}