From 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c Mon Sep 17 00:00:00 2001 From: Lorry Tar Creator Date: Tue, 27 Jun 2017 06:07:23 +0000 Subject: webkitgtk-2.16.5 --- Tools/TestWebKitAPI/CMakeLists.txt | 232 ++ Tools/TestWebKitAPI/Counters.cpp | 36 + Tools/TestWebKitAPI/Counters.h | 99 + .../ForwardingHeaders/WebCore/LayoutUnit.h | 4 + Tools/TestWebKitAPI/GNUmakefile.am | 934 ------- Tools/TestWebKitAPI/InjectedBundleController.cpp | 7 +- Tools/TestWebKitAPI/InjectedBundleController.h | 4 +- Tools/TestWebKitAPI/InjectedBundleMain.cpp | 9 +- Tools/TestWebKitAPI/InjectedBundleTest.h | 2 +- Tools/TestWebKitAPI/JavaScriptTest.cpp | 9 +- Tools/TestWebKitAPI/JavaScriptTest.h | 13 +- Tools/TestWebKitAPI/PlatformGTK.cmake | 158 ++ Tools/TestWebKitAPI/PlatformJSCOnly.cmake | 21 + Tools/TestWebKitAPI/PlatformUtilities.cpp | 12 +- Tools/TestWebKitAPI/PlatformUtilities.h | 33 +- Tools/TestWebKitAPI/PlatformWebView.h | 45 +- Tools/TestWebKitAPI/Test.h | 16 +- .../Tests/JavaScriptCore/VMInspector.cpp | 689 ----- Tools/TestWebKitAPI/Tests/WTF/AtomicString.cpp | 9 +- Tools/TestWebKitAPI/Tests/WTF/BloomFilter.cpp | 250 ++ .../Tests/WTF/CheckedArithmeticOperations.cpp | 554 +++- Tools/TestWebKitAPI/Tests/WTF/Condition.cpp | 257 ++ Tools/TestWebKitAPI/Tests/WTF/Consume.cpp | 141 + Tools/TestWebKitAPI/Tests/WTF/CrossThreadTask.cpp | 150 ++ Tools/TestWebKitAPI/Tests/WTF/DateMath.cpp | 208 ++ .../Tests/WTF/DeletedAddressOfOperator.h | 84 + Tools/TestWebKitAPI/Tests/WTF/Deque.cpp | 191 ++ Tools/TestWebKitAPI/Tests/WTF/EnumTraits.cpp | 55 + Tools/TestWebKitAPI/Tests/WTF/Expected.cpp | 512 ++++ Tools/TestWebKitAPI/Tests/WTF/Functional.cpp | 218 -- Tools/TestWebKitAPI/Tests/WTF/HashCountedSet.cpp | 468 ++++ Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp | 780 +++++- Tools/TestWebKitAPI/Tests/WTF/HashSet.cpp | 354 ++- Tools/TestWebKitAPI/Tests/WTF/LEBDecoder.cpp | 241 ++ Tools/TestWebKitAPI/Tests/WTF/ListHashSet.cpp | 98 +- Tools/TestWebKitAPI/Tests/WTF/Lock.cpp | 189 ++ Tools/TestWebKitAPI/Tests/WTF/MediaTime.cpp | 65 +- Tools/TestWebKitAPI/Tests/WTF/MetaAllocator.cpp | 6 +- Tools/TestWebKitAPI/Tests/WTF/NakedPtr.cpp | 238 ++ Tools/TestWebKitAPI/Tests/WTF/OptionSet.cpp | 297 +++ Tools/TestWebKitAPI/Tests/WTF/Optional.cpp | 150 ++ Tools/TestWebKitAPI/Tests/WTF/ParkingLot.cpp | 273 ++ Tools/TestWebKitAPI/Tests/WTF/RedBlackTree.cpp | 2 +- Tools/TestWebKitAPI/Tests/WTF/Ref.cpp | 57 +- Tools/TestWebKitAPI/Tests/WTF/RefCounter.cpp | 170 ++ Tools/TestWebKitAPI/Tests/WTF/RefLogger.cpp | 37 + Tools/TestWebKitAPI/Tests/WTF/RefLogger.h | 10 +- Tools/TestWebKitAPI/Tests/WTF/RefPtr.cpp | 58 +- Tools/TestWebKitAPI/Tests/WTF/RunLoop.cpp | 166 ++ Tools/TestWebKitAPI/Tests/WTF/Scope.cpp | 53 + Tools/TestWebKitAPI/Tests/WTF/ScopedLambda.cpp | 51 + Tools/TestWebKitAPI/Tests/WTF/SetForScope.cpp | 47 + Tools/TestWebKitAPI/Tests/WTF/StringBuilder.cpp | 25 +- .../TestWebKitAPI/Tests/WTF/StringConcatenate.cpp | 121 + Tools/TestWebKitAPI/Tests/WTF/StringHasher.cpp | 63 +- Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp | 550 +++- Tools/TestWebKitAPI/Tests/WTF/StringOperators.cpp | 16 + Tools/TestWebKitAPI/Tests/WTF/StringView.cpp | 928 +++++++ .../Tests/WTF/SynchronizedFixedQueue.cpp | 229 ++ Tools/TestWebKitAPI/Tests/WTF/TemporaryChange.cpp | 47 - .../TestWebKitAPI/Tests/WTF/TextBreakIterator.cpp | 146 + Tools/TestWebKitAPI/Tests/WTF/Time.cpp | 318 +++ Tools/TestWebKitAPI/Tests/WTF/UniqueRef.cpp | 93 + Tools/TestWebKitAPI/Tests/WTF/Variant.cpp | 228 ++ Tools/TestWebKitAPI/Tests/WTF/Vector.cpp | 430 ++- Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp | 364 +++ Tools/TestWebKitAPI/Tests/WTF/WeakPtr.cpp | 193 ++ Tools/TestWebKitAPI/Tests/WTF/WorkQueue.cpp | 236 ++ .../TestWebKitAPI/Tests/WTF/darwin/OSObjectPtr.cpp | 66 + Tools/TestWebKitAPI/Tests/WTF/glib/GUniquePtr.cpp | 195 ++ .../TestWebKitAPI/Tests/WTF/glib/WorkQueueGLib.cpp | 71 + .../TestWebKitAPI/Tests/WTF/gobject/GUniquePtr.cpp | 195 -- .../Tests/WebCore/AffineTransform.cpp | 1024 +++++++ Tools/TestWebKitAPI/Tests/WebCore/CARingBuffer.cpp | 251 ++ Tools/TestWebKitAPI/Tests/WebCore/CSSParser.cpp | 84 + .../Tests/WebCore/CalculationValue.cpp | 283 ++ Tools/TestWebKitAPI/Tests/WebCore/Color.cpp | 190 ++ .../Tests/WebCore/ComplexTextController.cpp | 391 +++ .../Tests/WebCore/ContentExtensions.cpp | 2795 ++++++++++++++++++++ Tools/TestWebKitAPI/Tests/WebCore/DFACombiner.cpp | 121 + Tools/TestWebKitAPI/Tests/WebCore/DFAHelpers.h | 67 + Tools/TestWebKitAPI/Tests/WebCore/DFAMinimizer.cpp | 121 + .../TestWebKitAPI/Tests/WebCore/ExtendedColor.cpp | 162 ++ Tools/TestWebKitAPI/Tests/WebCore/FileSystem.cpp | 122 + Tools/TestWebKitAPI/Tests/WebCore/FloatPoint.cpp | 598 +++++ Tools/TestWebKitAPI/Tests/WebCore/FloatRect.cpp | 783 ++++++ Tools/TestWebKitAPI/Tests/WebCore/FloatSize.cpp | 328 +++ Tools/TestWebKitAPI/Tests/WebCore/GridPosition.cpp | 73 + .../Tests/WebCore/HTMLParserIdioms.cpp | 164 ++ Tools/TestWebKitAPI/Tests/WebCore/IntPoint.cpp | 283 ++ Tools/TestWebKitAPI/Tests/WebCore/IntRect.cpp | 615 +++++ Tools/TestWebKitAPI/Tests/WebCore/IntSize.cpp | 332 +++ Tools/TestWebKitAPI/Tests/WebCore/LayoutUnit.cpp | 42 +- .../Tests/WebCore/ParsedContentRange.cpp | 98 + Tools/TestWebKitAPI/Tests/WebCore/PublicSuffix.cpp | 78 + Tools/TestWebKitAPI/Tests/WebCore/SampleMap.cpp | 224 ++ .../TestWebKitAPI/Tests/WebCore/SecurityOrigin.cpp | 146 + Tools/TestWebKitAPI/Tests/WebCore/SharedBuffer.cpp | 163 ++ .../Tests/WebCore/SharedBufferTest.cpp | 56 + .../TestWebKitAPI/Tests/WebCore/SharedBufferTest.h | 46 + Tools/TestWebKitAPI/Tests/WebCore/TimeRanges.cpp | 291 ++ .../Tests/WebCore/TransformationMatrix.cpp | 1317 +++++++++ Tools/TestWebKitAPI/Tests/WebCore/URL.cpp | 54 +- Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp | 1305 +++++++++ .../Tests/WebCore/UserAgentQuirks.cpp | 96 + .../Tests/WebCore/YouTubePluginReplacement.cpp | 86 + .../Tests/WebCore/gtk/UserAgentQuirks.cpp | 63 - .../TestWebKitAPI/Tests/WebKit2/18-characters.html | 0 .../TestWebKitAPI/Tests/WebKit2/AboutBlankLoad.cpp | 5 + Tools/TestWebKitAPI/Tests/WebKit2/Ahem.ttf | Bin 0 -> 12480 bytes .../Tests/WebKit2/CanHandleRequest.cpp | 7 +- .../Tests/WebKit2/CanHandleRequest_Bundle.cpp | 7 +- .../Tests/WebKit2/CloseFromWithinCreatePage.cpp | 94 + .../Tests/WebKit2/CloseThenTerminate.cpp | 5 + .../TestWebKitAPI/Tests/WebKit2/CookieManager.cpp | 9 +- .../WKViewIsActiveSetIsActive.cpp | 131 + .../WKViewIsActiveSetIsActive_Bundle.cpp | 52 + .../WKViewRestoreZoomAndScrollBackForward.cpp | 129 + .../WKViewUserViewportToContents.cpp | 148 ++ .../WebKit2/CoordinatedGraphics/backforward1.html | 5 + .../WebKit2/CoordinatedGraphics/backforward2.html | 1 + .../Tests/WebKit2/DOMWindowExtensionBasic.cpp | 7 +- .../WebKit2/DOMWindowExtensionBasic_Bundle.cpp | 19 +- .../Tests/WebKit2/DOMWindowExtensionNoCache.cpp | 5 + .../WebKit2/DOMWindowExtensionNoCache_Bundle.cpp | 19 +- .../Tests/WebKit2/DidAssociateFormControls.cpp | 5 + .../WebKit2/DidAssociateFormControls_Bundle.cpp | 13 +- .../Tests/WebKit2/DidNotHandleKeyDown.cpp | 7 +- .../DidRemoveFrameFromHiearchyInPageCache.cpp | 109 + ...idRemoveFrameFromHiearchyInPageCache_Bundle.cpp | 75 + .../WebKit2/DocumentStartUserScriptAlertCrash.cpp | 7 +- .../DocumentStartUserScriptAlertCrash_Bundle.cpp | 13 +- .../WebKit2/DownloadDecideDestinationCrash.cpp | 9 +- .../Tests/WebKit2/EnumerateMediaDevices.cpp | 84 + .../EphemeralSessionPushStateNoHistoryCallback.cpp | 87 + .../Tests/WebKit2/EvaluateJavaScript.cpp | 9 +- .../TestWebKitAPI/Tests/WebKit2/EventModifiers.cpp | 82 + Tools/TestWebKitAPI/Tests/WebKit2/FailedLoad.cpp | 7 +- Tools/TestWebKitAPI/Tests/WebKit2/Find.cpp | 7 +- Tools/TestWebKitAPI/Tests/WebKit2/ForceRepaint.cpp | 7 +- Tools/TestWebKitAPI/Tests/WebKit2/FrameHandle.cpp | 70 + .../Tests/WebKit2/FrameMIMETypeHTML.cpp | 7 +- .../Tests/WebKit2/FrameMIMETypePNG.cpp | 7 +- Tools/TestWebKitAPI/Tests/WebKit2/Geolocation.cpp | 55 +- ...njectedBundleInitializationUserDataCallback.cpp | 7 +- ...BundleInitializationUserDataCallback_Bundle.cpp | 7 +- .../Tests/WebKit2/HitTestResultNodeHandle.cpp | 7 +- .../WebKit2/HitTestResultNodeHandle_Bundle.cpp | 13 +- .../Tests/WebKit2/InjectedBundleBasic.cpp | 7 +- .../Tests/WebKit2/InjectedBundleBasic_Bundle.cpp | 7 +- .../Tests/WebKit2/InjectedBundleFrameHitTest.cpp | 7 +- .../WebKit2/InjectedBundleFrameHitTest_Bundle.cpp | 17 +- ...tedBundleInitializationUserDataCallbackWins.cpp | 7 +- ...leInitializationUserDataCallbackWins_Bundle.cpp | 7 +- .../InjectedBundleMakeAllShadowRootsOpen.cpp | 109 + ...InjectedBundleMakeAllShadowRootsOpen_Bundle.cpp | 98 + .../LayoutMilestonesWithAllContentInFrame.cpp | 9 +- .../TestWebKitAPI/Tests/WebKit2/LimitTitleSize.cpp | 79 + .../LoadAlternateHTMLStringWithNonDirectoryURL.cpp | 37 +- .../LoadCanceledNoServerRedirectCallback.cpp | 11 +- ...LoadCanceledNoServerRedirectCallback_Bundle.cpp | 11 +- .../Tests/WebKit2/LoadPageOnCrash.cpp | 7 +- .../Tests/WebKit2/MenuTypesForMouseEvents.cpp | 149 ++ .../TestWebKitAPI/Tests/WebKit2/ModalAlertsSPI.cpp | 123 + .../Tests/WebKit2/MouseMoveAfterCrash.cpp | 9 +- .../Tests/WebKit2/MouseMoveAfterCrash_Bundle.cpp | 5 + .../WebKit2/NewFirstVisuallyNonEmptyLayout.cpp | 7 +- .../NewFirstVisuallyNonEmptyLayoutFails.cpp | 9 +- .../NewFirstVisuallyNonEmptyLayoutFails_Bundle.cpp | 9 +- .../NewFirstVisuallyNonEmptyLayoutForImages.cpp | 7 +- ...FirstVisuallyNonEmptyLayoutForImages_Bundle.cpp | 9 +- .../NewFirstVisuallyNonEmptyLayoutFrames.cpp | 11 +- ...NewFirstVisuallyNonEmptyLayoutFrames_Bundle.cpp | 9 +- .../NewFirstVisuallyNonEmptyLayout_Bundle.cpp | 9 +- Tools/TestWebKitAPI/Tests/WebKit2/PageGroup.cpp | 80 + .../TestWebKitAPI/Tests/WebKit2/PageLoadBasic.cpp | 27 +- ...PageLoadDidChangeLocationWithinPageForFrame.cpp | 7 +- Tools/TestWebKitAPI/Tests/WebKit2/ParentFrame.cpp | 7 +- .../Tests/WebKit2/ParentFrame_Bundle.cpp | 11 +- .../WebKit2/PasteboardNotifications_Bundle.cpp | 89 + .../Tests/WebKit2/PendingAPIRequestURL.cpp | 167 ++ .../Tests/WebKit2/PreventEmptyUserAgent.cpp | 9 +- .../PrivateBrowsingPushStateNoHistoryCallback.cpp | 32 +- .../ProvisionalURLAfterWillSendRequestCallback.cpp | 89 + ...ionalURLAfterWillSendRequestCallback_Bundle.cpp | 85 + .../Tests/WebKit2/ReloadPageAfterCrash.cpp | 7 +- .../WebKit2/ResizeReversePaginatedWebView.cpp | 11 +- .../Tests/WebKit2/ResizeWindowAfterCrash.cpp | 7 +- .../WebKit2/ResponsivenessTimerDoesntFireEarly.cpp | 5 + .../ResponsivenessTimerDoesntFireEarly_Bundle.cpp | 5 + .../RestoreSessionStateContainingFormData.cpp | 17 +- .../RestoreSessionStateWithoutNavigation.cpp | 105 + .../Tests/WebKit2/ScrollPinningBehaviors.cpp | 13 +- .../WebKit2/ShouldGoToBackForwardListItem.cpp | 7 +- .../ShouldGoToBackForwardListItem_Bundle.cpp | 9 +- .../ShouldKeepCurrentBackForwardListItemInList.cpp | 163 ++ .../Tests/WebKit2/SpacebarScrolling.cpp | 27 +- .../StopLoadingDuringDidFailProvisionalLoad.cpp | 83 + ...pLoadingDuringDidFailProvisionalLoad_bundle.cpp | 81 + .../TestWebKitAPI/Tests/WebKit2/TerminateTwice.cpp | 4 + .../WebKit2/TextFieldDidBeginAndEndEditing.cpp | 137 + .../TextFieldDidBeginAndEndEditing_Bundle.cpp | 76 + Tools/TestWebKitAPI/Tests/WebKit2/UserMedia.cpp | 85 + Tools/TestWebKitAPI/Tests/WebKit2/UserMessage.cpp | 13 +- .../Tests/WebKit2/UserMessage_Bundle.cpp | 5 + .../Tests/WebKit2/WKBundleFileHandle.cpp | 86 + .../Tests/WebKit2/WKBundleFileHandle_Bundle.cpp | 99 + .../Tests/WebKit2/WKImageCreateCGImageCrash.cpp | 41 + .../Tests/WebKit2/WKPageConfiguration.cpp | 132 + .../WKPageCopySessionStateWithFiltering.cpp | 136 + .../Tests/WebKit2/WKPageGetScaleFactorNotZero.cpp | 15 +- .../Tests/WebKit2/WKPageIsPlayingAudio.cpp | 152 ++ .../TestWebKitAPI/Tests/WebKit2/WKPreferences.cpp | 39 +- Tools/TestWebKitAPI/Tests/WebKit2/WKRetainPtr.cpp | 58 + Tools/TestWebKitAPI/Tests/WebKit2/WKString.cpp | 4 + .../Tests/WebKit2/WKStringJSString.cpp | 7 +- Tools/TestWebKitAPI/Tests/WebKit2/WebArchive.cpp | 135 + .../Tests/WebKit2/WebArchive_Bundle.cpp | 69 + .../WebKit2/WebCoreStatisticsWithNoWebProcess.cpp | 55 + Tools/TestWebKitAPI/Tests/WebKit2/WillLoad.cpp | 11 +- .../Tests/WebKit2/WillLoad_Bundle.cpp | 15 +- .../Tests/WebKit2/WillSendSubmitEvent.cpp | 5 + .../Tests/WebKit2/WillSendSubmitEvent_Bundle.cpp | 9 +- .../Tests/WebKit2/all-content-in-one-iframe.html | 1 + .../Tests/WebKit2/associate-form-controls.html | 31 + .../Tests/WebKit2/auto-submitting-form.html | 20 + .../Tests/WebKit2/autoplay-check-frame.html | 16 + .../Tests/WebKit2/autoplay-check-in-iframe.html | 16 + .../Tests/WebKit2/autoplay-check.html | 20 + .../Tests/WebKit2/autoplay-no-audio-check.html | 20 + .../Tests/WebKit2/autoplay-with-controls.html | 19 + Tools/TestWebKitAPI/Tests/WebKit2/bundle-file.html | 16 + .../WebKit2/chinese-character-with-image.html | 15 + .../WebKit2/close-from-within-create-page.html | 16 + .../Tests/WebKit2/closed-shadow-tree-test.html | 28 + .../Tests/WebKit2/contentBlockerCheck.html | 13 + .../Tests/WebKit2/custom-protocol-sync-xhr.html | 6 + .../Tests/WebKit2/enumerateMediaDevices.html | 24 + Tools/TestWebKitAPI/Tests/WebKit2/execCopy.html | 15 + .../Tests/WebKit2/file-with-anchor.html | 19 + .../TestWebKitAPI/Tests/WebKit2/file-with-mse.html | 41 + .../Tests/WebKit2/file-with-video.html | 18 + Tools/TestWebKitAPI/Tests/WebKit2/find.html | 5 + Tools/TestWebKitAPI/Tests/WebKit2/findRanges.html | 11 + .../WebKit2/geolocationGetCurrentPosition.html | 3 + ...locationGetCurrentPositionWithHighAccuracy.html | 3 + .../Tests/WebKit2/geolocationWatchPosition.html | 3 + .../geolocationWatchPositionWithHighAccuracy.html | 3 + .../TestWebKitAPI/Tests/WebKit2/getUserMedia.html | 14 + .../Tests/WebKit2/gtk/InputMethodFilter.cpp | 258 ++ Tools/TestWebKitAPI/Tests/WebKit2/icon.png | Bin 0 -> 36541 bytes .../Tests/WebKit2/input-focus-blur.html | 28 + .../Tests/WebKit2/js-play-with-controls.html | 20 + .../WebKit2/link-with-download-attribute.html | 10 + .../Tests/WebKit2/link-with-title.html | 5 + .../Tests/WebKit2/lots-of-iframes.html | 35 + .../Tests/WebKit2/lots-of-images.html | 17 + .../Tests/WebKit2/lots-of-text-vertical-lr.html | 3 + .../TestWebKitAPI/Tests/WebKit2/lots-of-text.html | 3 + .../TestWebKitAPI/Tests/WebKit2/many-iframes.html | 15 + .../modal-alerts-in-new-about-blank-window.html | 13 + .../Tests/WebKit2/mouse-button-listener.html | 30 + .../Tests/WebKit2/mouse-move-listener.html | 16 + .../Tests/WebKit2/no-autoplay-with-controls.html | 25 + .../Tests/WebKit2/open-and-close-window.html | 11 + Tools/TestWebKitAPI/Tests/WebKit2/push-state.html | 3 + .../Tests/WebKit2/set-long-title.html | 10 + .../WebKit2/should-open-external-schemes.html | 21 + .../WebKit2/simple-accelerated-compositing.html | 5 + Tools/TestWebKitAPI/Tests/WebKit2/simple-form.html | 11 + .../TestWebKitAPI/Tests/WebKit2/simple-iframe.html | 6 + Tools/TestWebKitAPI/Tests/WebKit2/simple-tall.html | 7 + Tools/TestWebKitAPI/Tests/WebKit2/simple.html | 5 + Tools/TestWebKitAPI/Tests/WebKit2/simple2.html | 5 + Tools/TestWebKitAPI/Tests/WebKit2/simple3.html | 5 + .../Tests/WebKit2/spacebar-scrolling.html | 26 + Tools/TestWebKitAPI/Tests/WebKit2/test-mse.mp4 | Bin 0 -> 80933 bytes .../Tests/WebKit2/test-without-audio-track.mp4 | Bin 0 -> 189906 bytes Tools/TestWebKitAPI/Tests/WebKit2/test.mp4 | Bin 0 -> 192844 bytes Tools/TestWebKitAPI/Tests/WebKit2/webfont.html | 15 + Tools/TestWebKitAPI/Tests/WebKit2Cocoa/AllAhem.svg | 111 + .../Tests/WebKit2Cocoa/ApplicationCache.db | Bin 0 -> 4096 bytes .../Tests/WebKit2Cocoa/ApplicationCache.db-shm | Bin 0 -> 32768 bytes .../Tests/WebKit2Cocoa/ApplicationCache.db-wal | Bin 0 -> 168952 bytes .../WebKit2Cocoa/BundleEditingDelegateProtocol.h | 40 + .../Tests/WebKit2Cocoa/BundleRangeHandleProtocol.h | 35 + .../Tests/WebKit2Cocoa/ContentFiltering.h | 28 + .../Tests/WebKit2Cocoa/ContentFiltering.html | 6 + .../Tests/WebKit2Cocoa/CookieMessage.html | 4 + .../Tests/WebKit2Cocoa/DownloadRequestBlobURL.html | 16 + .../WebKit2Cocoa/DownloadRequestOriginalURL.html | 10 + .../WebKit2Cocoa/DownloadRequestOriginalURL2.html | 6 + .../DownloadRequestOriginalURLFrame.html | 10 + .../Tests/WebKit2Cocoa/FullscreenDelegate.html | 31 + .../WebKit2Cocoa/FullscreenLayoutConstraints.html | 31 + .../WebKit2Cocoa/FullscreenTopContentInset.html | 31 + .../Tests/WebKit2Cocoa/IDBDeleteRecovery.html | 14 + .../Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3 | Bin 0 -> 4096 bytes .../WebKit2Cocoa/IDBDeleteRecovery.sqlite3-shm | Bin 0 -> 32768 bytes .../WebKit2Cocoa/IDBDeleteRecovery.sqlite3-wal | Bin 0 -> 164832 bytes .../Tests/WebKit2Cocoa/IDBIndexUpgradeToV2.html | 21 + .../Tests/WebKit2Cocoa/IndexUpgrade.blob | 1 + .../Tests/WebKit2Cocoa/IndexUpgrade.sqlite3 | Bin 0 -> 65536 bytes .../IndexedDBDatabaseProcessKill-1.html | 33 + .../WebKit2Cocoa/IndexedDBMultiProcess-1.html | 46 + .../WebKit2Cocoa/IndexedDBMultiProcess-2.html | 92 + .../WebKit2Cocoa/IndexedDBMultiProcess-3.html | 21 + .../Tests/WebKit2Cocoa/IndexedDBPersistence-1.html | 35 + .../Tests/WebKit2Cocoa/IndexedDBPersistence-2.html | 22 + .../Tests/WebKit2Cocoa/LineBreaking.html | 45 + .../Tests/WebKit2Cocoa/LocalStorageClear.html | 6 + .../WebKit2Cocoa/LocalStorageNullEntries.html | 6 + .../LocalStorageNullEntries.localstorage | Bin 0 -> 12288 bytes .../LocalStorageNullEntries.localstorage-shm | Bin 0 -> 32768 bytes .../WebKit2Cocoa/LocalStorageQuirkEnabled.html | 10 + .../Tests/WebKit2Cocoa/RemoteObjectRegistry.h | 51 + .../Tests/WebKit2Cocoa/StoreBlobToBeDeleted.html | 41 + .../Tests/WebKit2Cocoa/UserContentWorldProtocol.h | 37 + .../WebKit2Cocoa/WebProcessKillIDBCleanup-1.html | 67 + .../WebKit2Cocoa/WebProcessKillIDBCleanup-2.html | 25 + .../Tests/WebKit2Cocoa/autofocused-text-input.html | 3 + .../WebKit2Cocoa/autoplaying-video-with-audio.html | 34 + .../Tests/WebKit2Cocoa/blinking-div.html | 23 + .../WebKit2Cocoa/change-video-source-on-click.html | 33 + .../WebKit2Cocoa/change-video-source-on-end.html | 35 + .../duplicate-completion-handler-calls.html | 9 + .../Tests/WebKit2Cocoa/editable-body.html | 7 + .../WebKit2Cocoa/enormous-video-with-sound.html | 15 + .../Tests/WebKit2Cocoa/focus-inputs.html | 15 + .../full-size-autoplaying-video-with-audio.html | 23 + .../input-field-in-scrollable-document.html | 36 + .../large-input-field-focus-onload.html | 38 + ...rge-video-hides-controls-after-seek-to-end.html | 40 + .../WebKit2Cocoa/large-video-mutes-onplaying.html | 16 + .../Tests/WebKit2Cocoa/large-video-offscreen.html | 29 + .../large-video-playing-scroll-away.html | 36 + .../large-video-seek-after-ending.html | 21 + ...eo-seek-to-beginning-and-play-after-ending.html | 23 + .../WebKit2Cocoa/large-video-test-now-playing.html | 33 + .../Tests/WebKit2Cocoa/large-video-with-audio.html | 12 + .../Tests/WebKit2Cocoa/large-video-with-audio.mp4 | Bin 0 -> 1088986 bytes .../WebKit2Cocoa/large-video-without-audio.html | 29 + .../large-videos-autoplaying-click-to-pause.html | 47 + .../large-videos-autoplaying-scroll-to-video.html | 35 + .../large-videos-paused-video-hides-controls.html | 38 + ...-videos-playing-muted-video-hides-controls.html | 36 + .../large-videos-playing-video-keeps-controls.html | 35 + .../large-videos-with-audio-autoplay.html | 18 + .../WebKit2Cocoa/large-videos-with-audio.html | 18 + .../WebKit2Cocoa/open-multiple-external-url.html | 66 + .../Tests/WebKit2Cocoa/page-with-csp-iframe.html | 14 + .../Tests/WebKit2Cocoa/page-with-csp.html | 15 + .../WebKit2Cocoa/page-without-csp-iframe.html | 11 + .../Tests/WebKit2Cocoa/page-without-csp.html | 12 + .../Tests/WebKit2Cocoa/play-audio-on-click.html | 54 + .../skinny-autoplaying-video-with-audio.html | 23 + .../WebKit2Cocoa/text-and-password-inputs.html | 39 + .../wide-autoplaying-video-with-audio.html | 23 + .../Tests/WebKit2Gtk/AutocleanupsTest.cpp | 72 + .../TestWebKitAPI/Tests/WebKit2Gtk/CMakeLists.txt | 135 + .../Tests/WebKit2Gtk/DOMDOMWindowTest.cpp | 221 ++ .../Tests/WebKit2Gtk/DOMNodeFilterTest.cpp | 204 ++ .../TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeTest.cpp | 122 +- .../Tests/WebKit2Gtk/DOMXPathNSResolverTest.cpp | 124 + .../TestWebKitAPI/Tests/WebKit2Gtk/EditorTest.cpp | 131 + Tools/TestWebKitAPI/Tests/WebKit2Gtk/FrameTest.cpp | 3 + .../Tests/WebKit2Gtk/TestAuthentication.cpp | 36 +- .../Tests/WebKit2Gtk/TestAutocleanups.cpp | 70 + .../Tests/WebKit2Gtk/TestBackForwardList.cpp | 137 + .../Tests/WebKit2Gtk/TestConsoleMessage.cpp | 155 ++ .../Tests/WebKit2Gtk/TestContextMenu.cpp | 370 ++- .../Tests/WebKit2Gtk/TestCookieManager.cpp | 71 +- .../Tests/WebKit2Gtk/TestDOMDOMWindow.cpp | 152 ++ .../TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNode.cpp | 37 +- .../Tests/WebKit2Gtk/TestDOMNodeFilter.cpp | 55 + .../Tests/WebKit2Gtk/TestDOMXPathNSResolver.cpp | 52 + .../Tests/WebKit2Gtk/TestDownloads.cpp | 351 ++- .../TestWebKitAPI/Tests/WebKit2Gtk/TestEditor.cpp | 42 + Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestFrame.cpp | 2 - .../Tests/WebKit2Gtk/TestInspector.cpp | 17 +- .../Tests/WebKit2Gtk/TestInspectorServer.cpp | 12 +- .../Tests/WebKit2Gtk/TestLoaderClient.cpp | 211 +- .../Tests/WebKit2Gtk/TestMultiprocess.cpp | 77 +- .../Tests/WebKit2Gtk/TestPrinting.cpp | 207 +- .../Tests/WebKit2Gtk/TestResources.cpp | 108 +- Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestSSL.cpp | 210 +- .../Tests/WebKit2Gtk/TestUIClient.cpp | 469 +++- .../Tests/WebKit2Gtk/TestWebExtensions.cpp | 130 +- .../Tests/WebKit2Gtk/TestWebKitAccessibility.cpp | 5 +- .../Tests/WebKit2Gtk/TestWebKitFaviconDatabase.cpp | 69 +- .../Tests/WebKit2Gtk/TestWebKitFindController.cpp | 2 +- .../Tests/WebKit2Gtk/TestWebKitPolicyClient.cpp | 15 +- .../Tests/WebKit2Gtk/TestWebKitSecurityOrigin.cpp | 142 + .../Tests/WebKit2Gtk/TestWebKitSettings.cpp | 23 +- .../WebKit2Gtk/TestWebKitUserContentManager.cpp | 360 +++ .../Tests/WebKit2Gtk/TestWebKitWebContext.cpp | 412 ++- .../Tests/WebKit2Gtk/TestWebKitWebView.cpp | 561 +++- .../Tests/WebKit2Gtk/TestWebKitWebViewGroup.cpp | 206 -- .../Tests/WebKit2Gtk/TestWebViewEditor.cpp | 328 ++- .../Tests/WebKit2Gtk/TestWebsiteData.cpp | 537 ++++ .../Tests/WebKit2Gtk/WebExtensionTest.cpp | 199 +- .../Tests/WebKit2Gtk/WebProcessTest.cpp | 33 +- .../Tests/WebKit2Gtk/WebProcessTest.h | 4 +- .../Tests/WebKit2Gtk/resources/blank.ico | Bin 0 -> 198 bytes .../Tests/WebKit2Gtk/resources/boring.html | 1 + .../Tests/WebKit2Gtk/resources/link-title.js | 1 + .../Tests/WebKit2Gtk/resources/silence.mpg | Bin 0 -> 33227 bytes .../Tests/WebKit2Gtk/resources/simple.json | 1 + .../Tests/WebKit2Gtk/resources/test-cert.pem | 13 + .../Tests/WebKit2Gtk/resources/test-key.pem | 16 + .../Tests/WebKit2Gtk/resources/track.ogg | Bin 0 -> 3869 bytes .../resources/webkit2gtk-tests.gresource.xml | 7 + .../CustomProtocolsInvalidScheme_Bundle.cpp | 66 + .../PreventImageLoadWithAutoResizing_Bundle.cpp | 69 + Tools/TestWebKitAPI/Tests/WebKitGtk/test_utils.c | 51 - .../Tests/WebKitGtk/testapplicationcache.c | 49 - Tools/TestWebKitAPI/Tests/WebKitGtk/testatk.c | 1476 ----------- Tools/TestWebKitAPI/Tests/WebKitGtk/testatkroles.c | 426 --- .../Tests/WebKitGtk/testcontextmenu.c | 317 --- .../Tests/WebKitGtk/testcopyandpaste.c | 266 -- .../Tests/WebKitGtk/testdomdocument.c | 445 ---- .../Tests/WebKitGtk/testdomdomwindow.c | 258 -- Tools/TestWebKitAPI/Tests/WebKitGtk/testdomnode.c | 219 -- Tools/TestWebKitAPI/Tests/WebKitGtk/testdownload.c | 325 --- .../Tests/WebKitGtk/testfavicondatabase.c | 279 -- Tools/TestWebKitAPI/Tests/WebKitGtk/testglobals.c | 110 - .../Tests/WebKitGtk/testhittestresult.c | 171 -- .../Tests/WebKitGtk/testhttpbackend.c | 75 - .../TestWebKitAPI/Tests/WebKitGtk/testkeyevents.c | 390 --- Tools/TestWebKitAPI/Tests/WebKitGtk/testloading.c | 437 --- .../Tests/WebKitGtk/testmimehandling.c | 206 -- .../Tests/WebKitGtk/testnetworkrequest.c | 96 - .../Tests/WebKitGtk/testnetworkresponse.c | 97 - .../Tests/WebKitGtk/testwebbackforwardlist.c | 326 --- .../Tests/WebKitGtk/testwebdatasource.c | 242 -- Tools/TestWebKitAPI/Tests/WebKitGtk/testwebframe.c | 220 -- .../Tests/WebKitGtk/testwebhistoryitem.c | 70 - .../Tests/WebKitGtk/testwebinspector.c | 173 -- .../Tests/WebKitGtk/testwebplugindatabase.c | 78 - .../Tests/WebKitGtk/testwebresource.c | 334 --- .../Tests/WebKitGtk/testwebsettings.c | 110 - Tools/TestWebKitAPI/Tests/WebKitGtk/testwebview.c | 749 ------ Tools/TestWebKitAPI/Tests/WebKitGtk/testwindow.c | 119 - .../TestWebKitAPI/Tests/gtk/InputMethodFilter.cpp | 310 --- Tools/TestWebKitAPI/TestsController.cpp | 33 +- Tools/TestWebKitAPI/TestsController.h | 6 +- Tools/TestWebKitAPI/Utilities.h | 36 + Tools/TestWebKitAPI/WKWebViewConfigurationExtras.h | 34 + Tools/TestWebKitAPI/WTFStringUtilities.h | 13 +- Tools/TestWebKitAPI/config.h | 38 +- Tools/TestWebKitAPI/gtk/PlatformUtilitiesGtk.cpp | 6 +- Tools/TestWebKitAPI/gtk/PlatformWebViewGtk.cpp | 40 +- .../gtk/WebKit2Gtk/LoadTrackingTest.cpp | 83 +- .../gtk/WebKit2Gtk/LoadTrackingTest.h | 6 +- Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.cpp | 23 +- Tools/TestWebKitAPI/gtk/WebKit2Gtk/TestMain.h | 80 +- .../TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.cpp | 59 +- Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebKitTestBus.h | 6 +- .../gtk/WebKit2Gtk/WebKitTestServer.cpp | 26 +- .../gtk/WebKit2Gtk/WebKitTestServer.h | 13 +- Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.cpp | 100 +- Tools/TestWebKitAPI/gtk/WebKit2Gtk/WebViewTest.h | 31 +- Tools/TestWebKitAPI/gtk/main.cpp | 2 +- .../jsconly/PlatformUtilitiesJSCOnly.cpp | 57 + Tools/TestWebKitAPI/jsconly/main.cpp | 32 + 465 files changed, 37865 insertions(+), 12031 deletions(-) create mode 100644 Tools/TestWebKitAPI/CMakeLists.txt create mode 100644 Tools/TestWebKitAPI/Counters.cpp create mode 100644 Tools/TestWebKitAPI/Counters.h create mode 100644 Tools/TestWebKitAPI/ForwardingHeaders/WebCore/LayoutUnit.h delete mode 100644 Tools/TestWebKitAPI/GNUmakefile.am create mode 100644 Tools/TestWebKitAPI/PlatformGTK.cmake create mode 100644 Tools/TestWebKitAPI/PlatformJSCOnly.cmake delete mode 100644 Tools/TestWebKitAPI/Tests/JavaScriptCore/VMInspector.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/BloomFilter.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/Condition.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/Consume.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/CrossThreadTask.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/DateMath.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/DeletedAddressOfOperator.h create mode 100644 Tools/TestWebKitAPI/Tests/WTF/Deque.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/EnumTraits.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/Expected.cpp delete mode 100644 Tools/TestWebKitAPI/Tests/WTF/Functional.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/HashCountedSet.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/LEBDecoder.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/Lock.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/NakedPtr.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/OptionSet.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/Optional.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/ParkingLot.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/RefCounter.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/RefLogger.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/RunLoop.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/Scope.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/ScopedLambda.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/SetForScope.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/StringConcatenate.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/StringView.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp delete mode 100644 Tools/TestWebKitAPI/Tests/WTF/TemporaryChange.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/TextBreakIterator.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/Time.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/UniqueRef.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/Variant.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/WTFString.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/WeakPtr.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/WorkQueue.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/darwin/OSObjectPtr.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/glib/GUniquePtr.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WTF/glib/WorkQueueGLib.cpp delete mode 100644 Tools/TestWebKitAPI/Tests/WTF/gobject/GUniquePtr.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/AffineTransform.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/CARingBuffer.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/CSSParser.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/CalculationValue.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/Color.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/ComplexTextController.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/ContentExtensions.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/DFACombiner.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/DFAHelpers.h create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/DFAMinimizer.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/ExtendedColor.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/FileSystem.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/FloatPoint.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/FloatRect.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/FloatSize.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/GridPosition.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/HTMLParserIdioms.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/IntPoint.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/IntRect.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/IntSize.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/ParsedContentRange.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/PublicSuffix.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/SampleMap.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/SecurityOrigin.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/SharedBuffer.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/SharedBufferTest.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/SharedBufferTest.h create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/TimeRanges.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/TransformationMatrix.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/URLParser.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/UserAgentQuirks.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebCore/YouTubePluginReplacement.cpp delete mode 100644 Tools/TestWebKitAPI/Tests/WebCore/gtk/UserAgentQuirks.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/18-characters.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/Ahem.ttf create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/CloseFromWithinCreatePage.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewIsActiveSetIsActive.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewIsActiveSetIsActive_Bundle.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewRestoreZoomAndScrollBackForward.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/WKViewUserViewportToContents.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/backforward1.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/CoordinatedGraphics/backforward2.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/DidRemoveFrameFromHiearchyInPageCache.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/DidRemoveFrameFromHiearchyInPageCache_Bundle.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/EnumerateMediaDevices.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/EphemeralSessionPushStateNoHistoryCallback.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/EventModifiers.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/FrameHandle.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleMakeAllShadowRootsOpen.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/InjectedBundleMakeAllShadowRootsOpen_Bundle.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/LimitTitleSize.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/MenuTypesForMouseEvents.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/ModalAlertsSPI.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/PageGroup.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/PasteboardNotifications_Bundle.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/PendingAPIRequestURL.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/ProvisionalURLAfterWillSendRequestCallback.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/ProvisionalURLAfterWillSendRequestCallback_Bundle.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/RestoreSessionStateWithoutNavigation.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/ShouldKeepCurrentBackForwardListItemInList.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/StopLoadingDuringDidFailProvisionalLoad.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/StopLoadingDuringDidFailProvisionalLoad_bundle.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/TextFieldDidBeginAndEndEditing.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/TextFieldDidBeginAndEndEditing_Bundle.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/UserMedia.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/WKBundleFileHandle.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/WKBundleFileHandle_Bundle.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/WKImageCreateCGImageCrash.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/WKPageConfiguration.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/WKPageCopySessionStateWithFiltering.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/WKPageIsPlayingAudio.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/WKRetainPtr.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/WebArchive.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/WebArchive_Bundle.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/WebCoreStatisticsWithNoWebProcess.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/all-content-in-one-iframe.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/associate-form-controls.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/auto-submitting-form.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/autoplay-check-frame.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/autoplay-check-in-iframe.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/autoplay-check.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/autoplay-no-audio-check.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/autoplay-with-controls.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/bundle-file.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/chinese-character-with-image.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/close-from-within-create-page.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/closed-shadow-tree-test.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/contentBlockerCheck.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/custom-protocol-sync-xhr.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/enumerateMediaDevices.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/execCopy.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/file-with-anchor.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/file-with-mse.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/file-with-video.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/find.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/findRanges.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/geolocationGetCurrentPosition.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/geolocationGetCurrentPositionWithHighAccuracy.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/geolocationWatchPosition.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/geolocationWatchPositionWithHighAccuracy.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/getUserMedia.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/gtk/InputMethodFilter.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/icon.png create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/input-focus-blur.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/js-play-with-controls.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/link-with-download-attribute.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/link-with-title.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/lots-of-iframes.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/lots-of-images.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/lots-of-text-vertical-lr.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/lots-of-text.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/many-iframes.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/modal-alerts-in-new-about-blank-window.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/mouse-button-listener.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/mouse-move-listener.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/no-autoplay-with-controls.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/open-and-close-window.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/push-state.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/set-long-title.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/should-open-external-schemes.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/simple-accelerated-compositing.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/simple-form.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/simple-iframe.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/simple-tall.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/simple.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/simple2.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/simple3.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/spacebar-scrolling.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/test-mse.mp4 create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/test-without-audio-track.mp4 create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/test.mp4 create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2/webfont.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/AllAhem.svg create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ApplicationCache.db create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ApplicationCache.db-shm create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ApplicationCache.db-wal create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/BundleEditingDelegateProtocol.h create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/BundleRangeHandleProtocol.h create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.h create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/ContentFiltering.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/CookieMessage.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestBlobURL.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURL.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURL2.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/DownloadRequestOriginalURLFrame.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenDelegate.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenLayoutConstraints.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/FullscreenTopContentInset.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3 create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3-shm create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBDeleteRecovery.sqlite3-wal create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IDBIndexUpgradeToV2.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexUpgrade.blob create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexUpgrade.sqlite3 create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBDatabaseProcessKill-1.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-1.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-2.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBMultiProcess-3.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBPersistence-1.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/IndexedDBPersistence-2.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LineBreaking.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageClear.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.localstorage create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageNullEntries.localstorage-shm create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/LocalStorageQuirkEnabled.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/RemoteObjectRegistry.h create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/StoreBlobToBeDeleted.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/UserContentWorldProtocol.h create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebProcessKillIDBCleanup-1.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebProcessKillIDBCleanup-2.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/autofocused-text-input.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/autoplaying-video-with-audio.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/blinking-div.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/change-video-source-on-click.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/change-video-source-on-end.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/duplicate-completion-handler-calls.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/editable-body.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/enormous-video-with-sound.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/focus-inputs.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/full-size-autoplaying-video-with-audio.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/input-field-in-scrollable-document.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-input-field-focus-onload.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-hides-controls-after-seek-to-end.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-mutes-onplaying.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-offscreen.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-playing-scroll-away.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-seek-after-ending.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-seek-to-beginning-and-play-after-ending.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-test-now-playing.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-with-audio.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-with-audio.mp4 create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-video-without-audio.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-click-to-pause.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-autoplaying-scroll-to-video.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-paused-video-hides-controls.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-muted-video-hides-controls.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-playing-video-keeps-controls.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-with-audio-autoplay.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/large-videos-with-audio.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/open-multiple-external-url.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/page-with-csp-iframe.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/page-with-csp.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/page-without-csp-iframe.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/page-without-csp.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/play-audio-on-click.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/skinny-autoplaying-video-with-audio.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/text-and-password-inputs.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Cocoa/wide-autoplaying-video-with-audio.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/AutocleanupsTest.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/CMakeLists.txt create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMDOMWindowTest.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMNodeFilterTest.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/DOMXPathNSResolverTest.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/EditorTest.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestAutocleanups.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestConsoleMessage.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMDOMWindow.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMNodeFilter.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestDOMXPathNSResolver.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestEditor.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitSecurityOrigin.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitUserContentManager.cpp delete mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebKitWebViewGroup.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestWebsiteData.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/blank.ico create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/boring.html create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/link-title.js create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/silence.mpg create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/simple.json create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-cert.pem create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/test-key.pem create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/track.ogg create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2Gtk/resources/webkit2gtk-tests.gresource.xml create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2ObjC/CustomProtocolsInvalidScheme_Bundle.cpp create mode 100644 Tools/TestWebKitAPI/Tests/WebKit2ObjC/PreventImageLoadWithAutoResizing_Bundle.cpp delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/test_utils.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testapplicationcache.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testatk.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testatkroles.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testcontextmenu.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testcopyandpaste.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdocument.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testdomdomwindow.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testdomnode.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testdownload.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testfavicondatabase.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testglobals.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testhittestresult.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testhttpbackend.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testkeyevents.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testloading.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testmimehandling.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkrequest.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testnetworkresponse.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testwebbackforwardlist.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testwebdatasource.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testwebframe.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testwebhistoryitem.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testwebinspector.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testwebplugindatabase.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testwebresource.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testwebsettings.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testwebview.c delete mode 100644 Tools/TestWebKitAPI/Tests/WebKitGtk/testwindow.c delete mode 100644 Tools/TestWebKitAPI/Tests/gtk/InputMethodFilter.cpp create mode 100644 Tools/TestWebKitAPI/Utilities.h create mode 100644 Tools/TestWebKitAPI/WKWebViewConfigurationExtras.h create mode 100644 Tools/TestWebKitAPI/jsconly/PlatformUtilitiesJSCOnly.cpp create mode 100644 Tools/TestWebKitAPI/jsconly/main.cpp (limited to 'Tools/TestWebKitAPI') 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::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 +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 +#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 +#include #include #include @@ -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 +#include #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 #include -#include -#include +#include +#include #include 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 injectedBundlePath(AdoptWK, createInjectedBundlePath()); @@ -76,14 +78,16 @@ std::string toSTD(WKRetainPtr string) return toSTD(string.get()); } -std::string toSTD(const char* string) +WKRetainPtr toWK(const char* utf8String) { - return std::string(string); + return WKRetainPtr(AdoptWK, WKStringCreateWithUTF8CString(utf8String)); } -WKRetainPtr toWK(const char* utf8String) +#endif // WK_HAVE_C_SPI + +std::string toSTD(const char* string) { - return WKRetainPtr(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 +#ifndef BUILDING_JSCONLY__ +#include +#include +#endif + +#include "Utilities.h" #include -#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); -std::string toSTD(const char*); -#if PLATFORM(MAC) -std::string toSTD(NSString *); -#endif WKRetainPtr toWK(const char* utf8String); +#endif // WK_HAVE_C_SPI + template 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 #endif -#ifdef __APPLE__ +#if PLATFORM(MAC) +#include +#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 + namespace TestWebKitAPI { #define EXPECT_NOT_NULL(expression) \ @@ -40,6 +42,18 @@ namespace TestWebKitAPI { #define ASSERT_NULL(expression) \ ASSERT_TRUE(!(expression)) +template +static inline ::testing::AssertionResult assertStrongEnum(const char* expected_expression, const char* actual_expression, T expected, T actual) +{ + static_assert(std::is_enum::value, "T is not an enum type"); + typedef typename std::underlying_type::type UnderlyingStorageType; + return ::testing::internal::CmpHelperEQ(expected_expression, actual_expression, static_cast(expected), static_cast(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 -#include -#include - -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 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 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 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(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 +#include +#include + +namespace TestWebKitAPI { + +static Vector generateRandomHashes(size_t hashCount) +{ + Vector hashes; + for (unsigned i = 0; i < hashCount; ++i) + hashes.append(static_cast(randomNumber() * std::numeric_limits::max())); + return hashes; +} + +static Vector generateRandomDigests(size_t hashCount) +{ + Vector hashes; + SHA1 sha1; + for (unsigned i = 0; i < hashCount; ++i) { + double random = randomNumber(); + sha1.addBytes(reinterpret_cast(&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 +static void resetOverflow(Checked& value) +{ + value.reset(); + value = 100; + value *= std::numeric_limits::max(); +} + +#define CheckedArithmeticTest(type, Coercer, MixedSignednessTester) \ TEST(WTF, Checked_##type) \ { \ - Checked value; \ - EXPECT_EQ(coerceLiteral(0), value.unsafeGet()); \ - EXPECT_EQ(std::numeric_limits::max(), (value + std::numeric_limits::max()).unsafeGet()); \ - EXPECT_EQ(std::numeric_limits::max(), (std::numeric_limits::max() + value).unsafeGet()); \ - EXPECT_EQ(std::numeric_limits::min(), (value + std::numeric_limits::min()).unsafeGet()); \ - EXPECT_EQ(std::numeric_limits::min(), (std::numeric_limits::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::min(); \ - EXPECT_EQ(true, (Checked(value - coerceLiteral(1))).hasOverflowed()); \ - EXPECT_EQ(true, !((value--).hasOverflowed())); \ - EXPECT_EQ(true, value.hasOverflowed()); \ - value = std::numeric_limits::max(); \ - EXPECT_EQ(true, !value.hasOverflowed()); \ - EXPECT_EQ(true, (Checked(value + coerceLiteral(1))).hasOverflowed()); \ - EXPECT_EQ(true, !(value++).hasOverflowed()); \ - EXPECT_EQ(true, value.hasOverflowed()); \ - value = std::numeric_limits::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(0)).safeGet(_value)); \ - _value = 0; \ - EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked(0) * value).safeGet(_value)); \ - _value = 0; \ - EXPECT_EQ(true, CheckedState::DidOverflow == (value * Checked(std::numeric_limits::max())).safeGet(_value)); \ - _value = 0; \ - EXPECT_EQ(true, CheckedState::DidOverflow == (Checked(std::numeric_limits::max()) * value).safeGet(_value)); \ - value = 0; \ - _value = 0; \ - EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked(std::numeric_limits::max())).safeGet(_value)); \ - _value = 0; \ - EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked(std::numeric_limits::max()) * value).safeGet(_value)); \ - value = 1; \ - _value = 0; \ - EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked(std::numeric_limits::max())).safeGet(_value)); \ - _value = 0; \ - EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked(std::numeric_limits::max()) * value).safeGet(_value)); \ - _value = 0; \ - value = 0; \ - EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked(std::numeric_limits::max())).safeGet(_value)); \ - _value = 0; \ - EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked(std::numeric_limits::max()) * (type)0).safeGet(_value)); \ - _value = 0; \ - value = 1; \ - EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked(std::numeric_limits::max())).safeGet(_value)); \ - _value = 0; \ - EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked(std::numeric_limits::max()) * (type)1).safeGet(_value)); \ - _value = 0; \ - value = 2; \ - EXPECT_EQ(true, CheckedState::DidOverflow == (value * Checked(std::numeric_limits::max())).safeGet(_value)); \ - _value = 0; \ - EXPECT_EQ(true, CheckedState::DidOverflow == (Checked(std::numeric_limits::max()) * (type)2).safeGet(_value)); \ - value = 10; \ - EXPECT_EQ(true, (value * Checked(std::numeric_limits::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::min(); \ - MixedSignednessTest(EXPECT_EQ(true, (Checked(value - 1)).hasOverflowed())); \ - MixedSignednessTest(EXPECT_EQ(true, !(value--).hasOverflowed())); \ - MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \ - value = std::numeric_limits::max(); \ - MixedSignednessTest(EXPECT_EQ(true, !value.hasOverflowed())); \ - MixedSignednessTest(EXPECT_EQ(true, (Checked(value + 1)).hasOverflowed())); \ - MixedSignednessTest(EXPECT_EQ(true, !(value++).hasOverflowed())); \ - MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \ - value = std::numeric_limits::max(); \ - MixedSignednessTest(EXPECT_EQ(true, (value += 1).hasOverflowed())); \ - MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \ - value = std::numeric_limits::min(); \ - MixedSignednessTest(EXPECT_EQ(true, (value - 1U).hasOverflowed())); \ - MixedSignednessTest(EXPECT_EQ(true, !(value--).hasOverflowed())); \ - MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \ - value = std::numeric_limits::max(); \ - MixedSignednessTest(EXPECT_EQ(true, !value.hasOverflowed())); \ - MixedSignednessTest(EXPECT_EQ(true, (Checked(value + 1U)).hasOverflowed())); \ - MixedSignednessTest(EXPECT_EQ(true, !(value++).hasOverflowed())); \ - MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \ - value = std::numeric_limits::max(); \ - MixedSignednessTest(EXPECT_EQ(true, (value += 1U).hasOverflowed())); \ - MixedSignednessTest(EXPECT_EQ(true, value.hasOverflowed())); \ + typedef Coercer CoercerType; \ + typedef MixedSignednessTester MixedSignednessTesterType; \ + CheckedArithmeticTester::run(); \ } + +#define coerceLiteral(x) Coercer::coerce(x) + +template +class CheckedArithmeticTester { +public: + static void run() + { + Checked value; + EXPECT_EQ(coerceLiteral(0), value.unsafeGet()); + EXPECT_EQ(std::numeric_limits::max(), (value + std::numeric_limits::max()).unsafeGet()); + EXPECT_EQ(std::numeric_limits::max(), (std::numeric_limits::max() + value).unsafeGet()); + EXPECT_EQ(std::numeric_limits::min(), (value + std::numeric_limits::min()).unsafeGet()); + EXPECT_EQ(std::numeric_limits::min(), (std::numeric_limits::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::min(); + EXPECT_EQ(true, (Checked(value - coerceLiteral(1))).hasOverflowed()); + EXPECT_EQ(true, !((value--).hasOverflowed())); + EXPECT_EQ(true, value.hasOverflowed()); + value = std::numeric_limits::max(); + EXPECT_EQ(true, !value.hasOverflowed()); + EXPECT_EQ(true, (Checked(value + coerceLiteral(1))).hasOverflowed()); + EXPECT_EQ(true, !(value++).hasOverflowed()); + EXPECT_EQ(true, value.hasOverflowed()); + value = std::numeric_limits::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(0)).safeGet(_value)); + _value = 0; + EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked(0) * value).safeGet(_value)); + _value = 0; + EXPECT_EQ(true, CheckedState::DidOverflow == (value * Checked(std::numeric_limits::max())).safeGet(_value)); + _value = 0; + EXPECT_EQ(true, CheckedState::DidOverflow == (Checked(std::numeric_limits::max()) * value).safeGet(_value)); + value = 0; + _value = 0; + EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked(std::numeric_limits::max())).safeGet(_value)); + _value = 0; + EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked(std::numeric_limits::max()) * value).safeGet(_value)); + value = 1; + _value = 0; + EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked(std::numeric_limits::max())).safeGet(_value)); + _value = 0; + EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked(std::numeric_limits::max()) * value).safeGet(_value)); + _value = 0; + value = 0; + EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked(std::numeric_limits::max())).safeGet(_value)); + _value = 0; + EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked(std::numeric_limits::max()) * (type)0).safeGet(_value)); + _value = 0; + value = 1; + EXPECT_EQ(true, CheckedState::DidNotOverflow == (value * Checked(std::numeric_limits::max())).safeGet(_value)); + _value = 0; + EXPECT_EQ(true, CheckedState::DidNotOverflow == (Checked(std::numeric_limits::max()) * (type)1).safeGet(_value)); + _value = 0; + value = 2; + EXPECT_EQ(true, CheckedState::DidOverflow == (value * Checked(std::numeric_limits::max())).safeGet(_value)); + _value = 0; + EXPECT_EQ(true, CheckedState::DidOverflow == (Checked(std::numeric_limits::max()) * (type)2).safeGet(_value)); + value = 10; + EXPECT_EQ(true, (value * Checked(std::numeric_limits::max())).hasOverflowed()); + + + Checked nvalue; // to hold a not overflowed value. + Checked 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(_value))); + EXPECT_EQ(false, (nvalue == value)); + EXPECT_EQ(true, (nvalue == _value)); + EXPECT_EQ(false, (nvalue == Checked(std::numeric_limits::max()))); + EXPECT_EQ(false, (nvalue == std::numeric_limits::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(_value))); + EXPECT_EQ(true, (nvalue != value)); + EXPECT_EQ(false, (nvalue != _value)); + EXPECT_EQ(true, (nvalue != Checked(std::numeric_limits::max()))); + EXPECT_EQ(true, (nvalue != std::numeric_limits::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(_largeValue))); + EXPECT_EQ(false, (nvalue < Checked(_value))); + EXPECT_EQ(false, (nvalue < Checked(_smallValue))); + EXPECT_EQ(true, (nvalue < _largeValue)); + EXPECT_EQ(false, (nvalue < _value)); + EXPECT_EQ(false, (nvalue < _smallValue)); + EXPECT_EQ(true, (nvalue < Checked(std::numeric_limits::max()))); + EXPECT_EQ(true, (nvalue < std::numeric_limits::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(_largeValue))); + EXPECT_EQ(true, (nvalue <= Checked(_value))); + EXPECT_EQ(false, (nvalue <= Checked(_smallValue))); + EXPECT_EQ(true, (nvalue <= _largeValue)); + EXPECT_EQ(true, (nvalue <= _value)); + EXPECT_EQ(false, (nvalue <= _smallValue)); + EXPECT_EQ(true, (nvalue <= Checked(std::numeric_limits::max()))); + EXPECT_EQ(true, (nvalue <= std::numeric_limits::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(_largeValue))); + EXPECT_EQ(false, (nvalue > Checked(_value))); + EXPECT_EQ(true, (nvalue > Checked(_smallValue))); + EXPECT_EQ(false, (nvalue > _largeValue)); + EXPECT_EQ(false, (nvalue > _value)); + EXPECT_EQ(true, (nvalue > _smallValue)); + EXPECT_EQ(false, (nvalue > Checked(std::numeric_limits::max()))); + EXPECT_EQ(false, (nvalue > std::numeric_limits::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(_largeValue))); + EXPECT_EQ(true, (nvalue >= Checked(_value))); + EXPECT_EQ(true, (nvalue >= Checked(_smallValue))); + EXPECT_EQ(false, (nvalue >= _largeValue)); + EXPECT_EQ(true, (nvalue >= _value)); + EXPECT_EQ(true, (nvalue >= _smallValue)); + EXPECT_EQ(false, (nvalue >= Checked(std::numeric_limits::max()))); + EXPECT_EQ(false, (nvalue >= std::numeric_limits::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(_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::max()), ovalue.didCrash())); + EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == Checked(std::numeric_limits::max())), ovalue.didCrash())); + EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue == std::numeric_limits::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(_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::max()), ovalue.didCrash())); + EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != Checked(std::numeric_limits::max())), ovalue.didCrash())); + EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue != std::numeric_limits::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(_largeValue)), ovalue.didCrash())); + EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < Checked(_value)), ovalue.didCrash())); + EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < Checked(_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(std::numeric_limits::max())), ovalue.didCrash())); + EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue < std::numeric_limits::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(_largeValue)), ovalue.didCrash())); + EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= Checked(_value)), ovalue.didCrash())); + EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= Checked(_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(std::numeric_limits::max())), ovalue.didCrash())); + EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue <= std::numeric_limits::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(_largeValue)), ovalue.didCrash())); + EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > Checked(_value)), ovalue.didCrash())); + EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > Checked(_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(std::numeric_limits::max())), ovalue.didCrash())); + EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue > std::numeric_limits::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(_largeValue)), ovalue.didCrash())); + EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= Checked(_value)), ovalue.didCrash())); + EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= Checked(_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(std::numeric_limits::max())), ovalue.didCrash())); + EXPECT_EQ(true, (resetOverflow(ovalue), unused = (ovalue >= std::numeric_limits::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 +class AllowMixedSignednessTest { +public: + static void run() + { + Checked 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::min(); + EXPECT_EQ(true, (Checked(value - 1)).hasOverflowed()); + EXPECT_EQ(true, !(value--).hasOverflowed()); + EXPECT_EQ(true, value.hasOverflowed()); + value = std::numeric_limits::max(); + EXPECT_EQ(true, !value.hasOverflowed()); + EXPECT_EQ(true, (Checked(value + 1)).hasOverflowed()); + EXPECT_EQ(true, !(value++).hasOverflowed()); + EXPECT_EQ(true, value.hasOverflowed()); + value = std::numeric_limits::max(); + EXPECT_EQ(true, (value += 1).hasOverflowed()); + EXPECT_EQ(true, value.hasOverflowed()); + value = std::numeric_limits::min(); + EXPECT_EQ(true, (value - 1U).hasOverflowed()); + EXPECT_EQ(true, !(value--).hasOverflowed()); + EXPECT_EQ(true, value.hasOverflowed()); + value = std::numeric_limits::max(); + EXPECT_EQ(true, !value.hasOverflowed()); + EXPECT_EQ(true, (Checked(value + 1U)).hasOverflowed()); + EXPECT_EQ(true, !(value++).hasOverflowed()); + EXPECT_EQ(true, value.hasOverflowed()); + value = std::numeric_limits::max(); + EXPECT_EQ(true, (value += 1U).hasOverflowed()); + EXPECT_EQ(true, value.hasOverflowed()); + } +}; + +template +class IgnoreMixedSignednessTest { +public: + static void run() { } +}; + +template class CoerceLiteralToUnsigned { +public: + static unsigned coerce(type x) { return static_cast(x); } +}; + +template 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(std::numeric_limits::max())); + EXPECT_TRUE(WTF::isInBounds(std::numeric_limits::min())); + + // bigger precision, unsigned, signed + EXPECT_TRUE(WTF::isInBounds(std::numeric_limits::max())); + EXPECT_FALSE(WTF::isInBounds(std::numeric_limits::min())); + + EXPECT_FALSE(WTF::isInBounds((int32_t)-1)); + EXPECT_FALSE(WTF::isInBounds((int32_t)-1)); + EXPECT_FALSE(WTF::isInBounds((int)-1)); + + EXPECT_TRUE(WTF::isInBounds((int32_t)1)); + EXPECT_TRUE(WTF::isInBounds((int16_t)1)); + EXPECT_TRUE(WTF::isInBounds((int)1)); + + EXPECT_TRUE(WTF::isInBounds((int32_t)0)); + EXPECT_TRUE(WTF::isInBounds((int32_t)0)); + EXPECT_TRUE(WTF::isInBounds((int16_t)0)); + EXPECT_TRUE(WTF::isInBounds((int)0)); + + EXPECT_TRUE(WTF::isInBounds(std::numeric_limits::max())); + EXPECT_TRUE(WTF::isInBounds(std::numeric_limits::max())); + EXPECT_TRUE(WTF::isInBounds(std::numeric_limits::max())); + + // bigger precision, signed, unsigned + EXPECT_TRUE(WTF::isInBounds(std::numeric_limits::max())); + EXPECT_FALSE(WTF::isInBounds(std::numeric_limits::max())); + EXPECT_TRUE(WTF::isInBounds((uint32_t)0)); + + // bigger precision, unsigned, unsigned + EXPECT_TRUE(WTF::isInBounds(std::numeric_limits::max())); + EXPECT_TRUE(WTF::isInBounds(std::numeric_limits::min())); + + // lower precision, signed signed + EXPECT_FALSE(WTF::isInBounds(std::numeric_limits::max())); + EXPECT_FALSE(WTF::isInBounds(std::numeric_limits::min())); + EXPECT_TRUE(WTF::isInBounds((int32_t)-1)); + EXPECT_TRUE(WTF::isInBounds((int32_t)0)); + EXPECT_TRUE(WTF::isInBounds((int32_t)1)); + // lower precision, unsigned, signed + EXPECT_FALSE(WTF::isInBounds(std::numeric_limits::max())); + EXPECT_FALSE(WTF::isInBounds(std::numeric_limits::min())); + EXPECT_FALSE(WTF::isInBounds((int32_t)-1)); + EXPECT_TRUE(WTF::isInBounds((int32_t)0)); + EXPECT_TRUE(WTF::isInBounds((int32_t)1)); + // lower precision, signed, unsigned + EXPECT_FALSE(WTF::isInBounds(std::numeric_limits::max())); + EXPECT_TRUE(WTF::isInBounds((uint32_t)0)); + EXPECT_TRUE(WTF::isInBounds((uint32_t)1)); + // lower precision, unsigned, unsigned + EXPECT_FALSE(WTF::isInBounds(std::numeric_limits::max())); + EXPECT_TRUE(WTF::isInBounds((uint32_t)0)); + EXPECT_TRUE(WTF::isInBounds((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 +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace WTF; + +namespace TestWebKitAPI { + +namespace { + +const bool verbose = false; + +enum NotifyStyle { + AlwaysNotifyOne, + TacticallyNotifyAll +}; + +template +void wait(Condition& condition, std::unique_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 queue; + bool shouldContinue = true; + Lock lock; + Condition emptyCondition; + Condition fullCondition; + + Vector consumerThreads; + Vector producerThreads; + + Vector received; + Lock receivedLock; + + for (unsigned i = numConsumers; i--;) { + ThreadIdentifier threadIdentifier = createThread( + "Consumer thread", + [&] () { + for (;;) { + unsigned result; + unsigned shouldNotify = false; + { + std::unique_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 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 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 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 +#include + +template +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 +#include +#include +#include + +namespace TestWebKitAPI { + +static size_t totalDestructorCalls; +static size_t totalIsolatedCopyCalls; + +static HashCountedSet defaultConstructorSet; +static HashCountedSet nameConstructorSet; +static HashCountedSet copyConstructorSet; +static HashCountedSet 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 { *"" }; + 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("-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("-1-0")); + ASSERT_EQ(1u, copyConstructorSet.count("-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("-2-1")); + ASSERT_EQ(1u, moveConstructorSet.count("-2-2")); + ASSERT_EQ(1u, moveConstructorSet.count("-1-1")); + ASSERT_EQ(1u, moveConstructorSet.count("-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 + +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 +#include + +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 : public GenericHashTraits { + static const bool emptyValueIsZero = true; + + static void constructDeletedValue(DeletedAddressOfOperator& slot) { slot = DeletedAddressOfOperator(std::numeric_limits::max()); } + static bool isDeletedValue(const DeletedAddressOfOperator& slot) { return slot.value() == std::numeric_limits::max(); } +}; + +template<> struct DefaultHash { + 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 + +namespace TestWebKitAPI { + +TEST(WTF_Deque, Iterator) +{ + Deque deque; + deque.append(11); + deque.prepend(10); + deque.append(12); + deque.append(13); + + Deque::iterator it = deque.begin(); + Deque::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 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 deque; + deque.append(11); + deque.prepend(10); + deque.append(12); + deque.append(13); + + Deque::reverse_iterator it = deque.rbegin(); + Deque::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 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 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 deque; + + for (unsigned i = 0; i < 10; ++i) + deque.append(MoveOnly(i)); + + EXPECT_EQ(10u, deque.size()); + + Deque 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 deque1; + + for (unsigned i = 0; i < 10; ++i) + deque1.append(MoveOnly(i)); + + EXPECT_EQ(10u, deque1.size()); + + Deque 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 + +enum class TestEnum { + A, + B, + C, +}; + +namespace WTF { +template<> struct EnumTraits { + using values = EnumValues; +}; +} + +namespace TestWebKitAPI { + +static_assert(WTF::isValidEnum(0), ""); +static_assert(!WTF::isValidEnum(-1), ""); +static_assert(!WTF::isValidEnum(3), ""); + +TEST(WTF_EnumTraits, IsValidEnum) +{ + EXPECT_TRUE(isValidEnum(0)); + EXPECT_FALSE(isValidEnum(-1)); + EXPECT_FALSE(isValidEnum(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 +#include + +#include +#include + +namespace WTF { + +template std::ostream& operator<<(std::ostream& os, const UnexpectedType& u) +{ + return os << u.value(); +} + +template std::ostream& operator<<(std::ostream& os, const Expected& e) +{ + if (e.hasValue()) + return os << e.value(); + return os << e.error(); +} + +template std::ostream& operator<<(std::ostream& os, const Expected& 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(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 E; + typedef Expected EV; + typedef Expected FooChar; + typedef Expected 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(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(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(message)); + FooString e1(makeUnexpected(message)); + FooString e2(makeUnexpected(std::string())); + EXPECT_EQ(e0.error(), std::string(message)); + EXPECT_EQ(e0, e1); + EXPECT_NE(e0, e2); + FooString* e4 = new FooString(makeUnexpected(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 E; + typedef Expected EV; + typedef Expected 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(oops); + EXPECT_FALSE(e.hasValue()); + EXPECT_EQ(e.error(), oops); + EXPECT_EQ(e.getUnexpected().value(), oops); + } + { + auto e = makeExpectedFromError(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(message)); + String e1(makeUnexpected(message)); + String e2(makeUnexpected(std::string())); + EXPECT_EQ(e0.error(), std::string(message)); + EXPECT_EQ(e0, e1); + EXPECT_NE(e0, e2); + String* e4 = new String(makeUnexpected(message)); + String* e5 = new String(*e4); + EXPECT_EQ(e0, *e4); + delete e4; + EXPECT_EQ(e0, *e5); + delete e5; + } +} + +TEST(WTF_Expected, comparison) +{ + typedef Expected Ex; + typedef Expected 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 NT; + typedef Expected TN; + typedef Expected NN; + typedef Expected 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 E; + std::unordered_map 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 E; + std::unordered_map 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, int> expected = Ref(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> expected = makeExpected, int>(Ref(a)); + EXPECT_TRUE(expected.hasValue()); + EXPECT_EQ(&a, expected.value().ptr()); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + RefLogger a("a"); + Expected> expected = makeUnexpected(Ref(a)); + EXPECT_FALSE(expected.hasValue()); + EXPECT_EQ(&a, expected.error().ptr()); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + RefLogger a("a"); + Expected> expected = makeUnexpected(Ref(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 -#include - -namespace TestWebKitAPI { - -static int returnFortyTwo() -{ - return 42; -} - -TEST(FunctionalTest, Basic) -{ - Function emptyFunction; - ASSERT_TRUE(emptyFunction.isNull()); - - Function 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 multiplyFourByTwoFunction = bind(multiplyByTwo, 4); - ASSERT_EQ(8, multiplyFourByTwoFunction()); - - Function 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 multiplyFourByTwoFunction = bind(multiply, 4, 2); - ASSERT_EQ(8, multiplyFourByTwoFunction()); - - Function 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 function1 = bind(&A::f, &a); - ASSERT_EQ(10, function1()); - - Function 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 function1 = bind(&B::f, &b); - function1(); - - Function 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 { -public: - static PassRefPtr 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 five = Number::create(5); - Function multiplyFiveByTwoFunction = bind(multiplyNumberByTwo, five); - ASSERT_EQ(10, multiplyFiveByTwoFunction()); - - Function multiplyFourByTwoFunction = bind(multiplyNumberByTwo, Number::create(4)); - ASSERT_EQ(8, multiplyFourByTwoFunction()); - - RefPtr six = Number::create(6); - Function multiplySixByTwoFunction = bind(multiplyNumberByTwo, six.release()); - ASSERT_FALSE(six); - ASSERT_EQ(12, multiplySixByTwoFunction()); -} - -namespace RefAndDerefTests { - - template struct RefCounted { - void ref(); - void deref(); - }; - struct Connection : RefCounted { }; - COMPILE_ASSERT(WTF::HasRefAndDeref::value, class_has_ref_and_deref); - - struct NoRefOrDeref { }; - COMPILE_ASSERT(!WTF::HasRefAndDeref::value, class_has_no_ref_or_deref); - - struct RefOnly { void ref(); }; - COMPILE_ASSERT(!WTF::HasRefAndDeref::value, class_has_ref_only); - - struct DerefOnly { void deref(); }; - COMPILE_ASSERT(!WTF::HasRefAndDeref::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 +#include +#include + +namespace TestWebKitAPI { + +typedef WTF::HashCountedSet 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 { + static const int minimumTableSize = 8; +}; + +typedef HashCountedSet::Hash, TestDoubleHashTraits> DoubleHashCountedSet; + +static int bucketForKey(double key) +{ + return DefaultHash::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 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 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 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 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> hashCountedSet; + + auto uniquePtr = std::make_unique(); + 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> hashCountedSet; + + auto uniquePtr = std::make_unique(); + 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::TestingScope deleterCounterScope; + + HashCountedSet>> hashCountedSet; + + std::unique_ptr> uniquePtr(new ConstructorDestructorCounter(), DeleterCounter()); + hashCountedSet.add(WTFMove(uniquePtr)); + + EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount); + EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount); + + EXPECT_EQ(0u, DeleterCounter::deleterCount()); + + hashCountedSet.clear(); + + EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount); + EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount); + + EXPECT_EQ(1u, DeleterCounter::deleterCount()); +} + +TEST(WTF_HashCountedSet, UniquePtrKey_FindUsingRawPointer) +{ + HashCountedSet> hashCountedSet; + + auto uniquePtr = std::make_unique(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> hashCountedSet; + + auto uniquePtr = std::make_unique(5); + int* ptr = uniquePtr.get(); + hashCountedSet.add(WTFMove(uniquePtr)); + + EXPECT_EQ(true, hashCountedSet.contains(ptr)); +} + +TEST(WTF_HashCountedSet, UniquePtrKey_GetUsingRawPointer) +{ + HashCountedSet> hashCountedSet; + + auto uniquePtr = std::make_unique(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> hashCountedSet; + + auto uniquePtr = std::make_unique(); + 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> hashCountedSet; + + DerivedRefLogger a("a"); + RefPtr 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> hashCountedSet; + + DerivedRefLogger a("a"); + RefPtr ptr(&a); + hashCountedSet.add(WTFMove(ptr)); + + EXPECT_STREQ("ref(a) ", takeLogStr().c_str()); +} + +TEST(WTF_HashCountedSet, RefPtrKey_AddUsingMove) +{ + HashCountedSet> hashCountedSet; + + DerivedRefLogger a("a"); + RefPtr ptr(&a); + hashCountedSet.add(WTFMove(ptr)); + + EXPECT_STREQ("ref(a) ", takeLogStr().c_str()); +} + +TEST(WTF_HashCountedSet, RefPtrKey_AddUsingRaw) +{ + HashCountedSet> hashCountedSet; + + DerivedRefLogger a("a"); + RefPtr 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> hashCountedSet; + + DerivedRefLogger a("a"); + + { + RefPtr ptr(&a); + hashCountedSet.add(ptr); + } + + EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str()); + + { + RefPtr 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> hashCountedSet; + + DerivedRefLogger a("a"); + + { + RefPtr ptr(&a); + hashCountedSet.add(ptr); + } + + EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str()); + + { + RefPtr 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> hashCountedSet; + + DerivedRefLogger a("a"); + + { + RefPtr ptr(&a); + hashCountedSet.add(ptr); + } + + EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str()); + + { + RefPtr 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 #include +#include #include 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 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, int> map; + + auto uniquePtr = std::make_unique(); + 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::TestingScope deleterCounterScope; + + HashMap>, int> map; + + std::unique_ptr> uniquePtr(new ConstructorDestructorCounter(), DeleterCounter()); + map.add(WTFMove(uniquePtr), 2); + + EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount); + EXPECT_EQ(0u, ConstructorDestructorCounter::destructionCount); + + EXPECT_EQ(0u, DeleterCounter::deleterCount()); + + map.clear(); + + EXPECT_EQ(1u, ConstructorDestructorCounter::constructionCount); + EXPECT_EQ(1u, ConstructorDestructorCounter::destructionCount); + + EXPECT_EQ(1u, DeleterCounter::deleterCount()); +} + +TEST(WTF_HashMap, UniquePtrKey_FindUsingRawPointer) +{ + HashMap, int> map; + + auto uniquePtr = std::make_unique(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, int> map; + + auto uniquePtr = std::make_unique(5); + int* ptr = uniquePtr.get(); + map.add(WTFMove(uniquePtr), 2); + + EXPECT_EQ(true, map.contains(ptr)); +} + +TEST(WTF_HashMap, UniquePtrKey_GetUsingRawPointer) +{ + HashMap, int> map; + + auto uniquePtr = std::make_unique(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, int> map; + + auto uniquePtr = std::make_unique(); + 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, int> map; + + auto uniquePtr = std::make_unique(); + 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, int> map; + + DerivedRefLogger a("a"); + RefPtr ptr(&a); + map.add(ptr, 0); + + ASSERT_STREQ("ref(a) ref(a) ", takeLogStr().c_str()); +} + +TEST(WTF_HashMap, RefPtrKey_AddUsingRelease) +{ + HashMap, int> map; + + DerivedRefLogger a("a"); + RefPtr ptr(&a); + map.add(WTFMove(ptr), 0); + + EXPECT_STREQ("ref(a) ", takeLogStr().c_str()); +} + +TEST(WTF_HashMap, RefPtrKey_AddUsingMove) +{ + HashMap, int> map; + + DerivedRefLogger a("a"); + RefPtr ptr(&a); + map.add(WTFMove(ptr), 0); + + EXPECT_STREQ("ref(a) ", takeLogStr().c_str()); +} + +TEST(WTF_HashMap, RefPtrKey_AddUsingRaw) +{ + HashMap, int> map; + + DerivedRefLogger a("a"); + RefPtr ptr(&a); + map.add(ptr.get(), 0); + + EXPECT_STREQ("ref(a) ref(a) ", takeLogStr().c_str()); +} + +TEST(WTF_HashMap, RefPtrKey_AddKeyAlreadyPresent) +{ + HashMap, int> map; + + DerivedRefLogger a("a"); + + { + RefPtr ptr(&a); + map.add(ptr, 0); + } + + EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str()); + + { + RefPtr 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, int> map; + + DerivedRefLogger a("a"); + + { + RefPtr ptr(&a); + map.add(ptr, 0); + } + + EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str()); + + { + RefPtr 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, int> map; + + DerivedRefLogger a("a"); + + { + RefPtr ptr(&a); + map.add(ptr, 0); + } + + EXPECT_STREQ("ref(a) ref(a) deref(a) ", takeLogStr().c_str()); + + { + RefPtr 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, int> map; + + DerivedRefLogger a("a"); + RefPtr ptr(&a); + map.set(ptr, 0); + + ASSERT_STREQ("ref(a) ref(a) ", takeLogStr().c_str()); +} + +TEST(WTF_HashMap, RefPtrKey_SetUsingRelease) +{ + HashMap, int> map; + + DerivedRefLogger a("a"); + RefPtr ptr(&a); + map.set(WTFMove(ptr), 0); + + EXPECT_STREQ("ref(a) ", takeLogStr().c_str()); +} + + +TEST(WTF_HashMap, RefPtrKey_SetUsingMove) +{ + HashMap, int> map; + + DerivedRefLogger a("a"); + RefPtr ptr(&a); + map.set(WTFMove(ptr), 0); + + EXPECT_STREQ("ref(a) ", takeLogStr().c_str()); +} + +TEST(WTF_HashMap, RefPtrKey_SetUsingRaw) +{ + HashMap, int> map; + + DerivedRefLogger a("a"); + RefPtr ptr(&a); + map.set(ptr.get(), 0); + + EXPECT_STREQ("ref(a) ref(a) ", takeLogStr().c_str()); +} + +TEST(WTF_HashMap, RefPtrKey_SetKeyAlreadyPresent) +{ + HashMap, int> map; + + DerivedRefLogger a("a"); + + RefPtr ptr(&a); + map.set(ptr, 0); + + EXPECT_STREQ("ref(a) ref(a) ", takeLogStr().c_str()); + + { + RefPtr 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, int> map; + + DerivedRefLogger a("a"); + + RefPtr ptr(&a); + map.set(ptr, 0); + + EXPECT_STREQ("ref(a) ref(a) ", takeLogStr().c_str()); + + { + RefPtr 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, int> map; + + DerivedRefLogger a("a"); + + RefPtr ptr(&a); + map.set(ptr, 0); + + EXPECT_STREQ("ref(a) ref(a) ", takeLogStr().c_str()); + + { + RefPtr 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 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 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> map; + { + auto addResult = map.ensure(1, [] { return std::make_unique(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(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> map; + + { + DerivedRefLogger a("a"); + + map.ensure(1, [&] { return RefPtr(&a); }); + EXPECT_STREQ("ref(a) ", takeLogStr().c_str()); + + map.ensure(1, [&] { return RefPtr(&a); }); + EXPECT_STREQ("", takeLogStr().c_str()); + } +} + +class ObjectWithRefLogger { +public: + ObjectWithRefLogger(Ref&& logger) + : m_logger(WTFMove(logger)) + { + } + + Ref m_logger; +}; + + +void testMovingUsingEnsure(Ref&& logger) +{ + HashMap> map; + + map.ensure(1, [&] { return std::make_unique(WTFMove(logger)); }); +} + +void testMovingUsingAdd(Ref&& logger) +{ + HashMap> map; + + auto& slot = map.add(1, nullptr).iterator->value; + slot = std::make_unique(WTFMove(logger)); +} + +TEST(WTF_HashMap, Ensure_LambdasCapturingByReference) +{ + { + DerivedRefLogger a("a"); + Ref ref(a); + testMovingUsingEnsure(WTFMove(ref)); + + EXPECT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + } + + { + DerivedRefLogger a("a"); + Ref 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 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* bucketAddress { nullptr }; + const DerefObserver* observedBucket { nullptr }; + }; + + auto observer = std::make_unique(); + + HashMap, 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::hashTableDeletedValue()); + EXPECT_EQ(observer->count, 0u); +} + +TEST(WTF_HashMap, Ref_Key) +{ + { + HashMap, int> map; + + RefLogger a("a"); + Ref ref(a); + map.add(WTFMove(ref), 1); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap, int> map; + + RefLogger a("a"); + Ref ref(a); + map.set(WTFMove(ref), 1); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap, int> map; + + RefLogger a("a"); + Ref refA(a); + map.add(WTFMove(refA), 1); + + Ref refA2(a); + map.set(WTFMove(refA2), 1); + } + + ASSERT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap, int> map; + + RefLogger a("a"); + Ref ref(a); + map.ensure(WTFMove(ref), []() { + return 1; + }); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap, int> map; + + RefLogger a("a"); + Ref 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, int> map; + + RefLogger a("a"); + Ref ref(a); + map.add(WTFMove(ref), 1); + + map.remove(&a); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap, int> map; + + RefLogger a("a"); + Ref 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, int> map; + for (int i = 0; i < 64; ++i) { + Ref 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> map; + + RefLogger a("a"); + Ref ref(a); + map.add(1, WTFMove(ref)); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap> map; + + RefLogger a("a"); + Ref ref(a); + map.set(1, WTFMove(ref)); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap> map; + + RefLogger a("a"); + Ref refA(a); + map.add(1, WTFMove(refA)); + + RefLogger b("b"); + Ref refB(b); + map.set(1, WTFMove(refB)); + } + + ASSERT_STREQ("ref(a) ref(b) deref(a) deref(b) ", takeLogStr().c_str()); + + { + HashMap> map; + + RefLogger a("a"); + Ref 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> map; + + auto emptyGet = map.get(1); + ASSERT_TRUE(emptyGet == nullptr); + } + + { + HashMap> map; + + RefLogger a("a"); + Ref ref(a); + map.add(1, WTFMove(ref)); + + auto aOut = map.take(1); + ASSERT_TRUE(static_cast(aOut)); + ASSERT_EQ(&a, aOut.value().ptr()); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap> map; + + auto emptyTake = map.take(1); + ASSERT_FALSE(static_cast(emptyTake)); + } + + { + HashMap> map; + + RefLogger a("a"); + Ref ref(a); + map.add(1, WTFMove(ref)); + map.remove(1); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap> map; + + RefLogger a("a"); + map.ensure(1, [&]() mutable { + Ref ref(a); + return ref; + }); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashMap> map; + for (int i = 0; i < 64; ++i) { + Ref 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 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 - +#include namespace TestWebKitAPI { @@ -43,7 +46,7 @@ void testInitialCapacity() HashSet::Hash, InitialCapacityTestHashTraits > 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 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> set; + + auto uniquePtr = std::make_unique(); + 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> set; + + auto uniquePtr = std::make_unique(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> set; + + auto uniquePtr = std::make_unique(5); + int* ptr = uniquePtr.get(); + set.add(WTFMove(uniquePtr)); + + EXPECT_EQ(true, set.contains(ptr)); +} + +TEST(WTF_HashSet, UniquePtrKey_RemoveUsingRawPointer) +{ + ConstructorDestructorCounter::TestingScope scope; + + HashSet> set; + + auto uniquePtr = std::make_unique(); + 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> set; + + auto uniquePtr = std::make_unique(); + 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 foo; + HashSet bar(foo); + + EXPECT_EQ(0u, bar.capacity()); + EXPECT_EQ(0u, bar.size()); + } + { + HashSet foo({ 1, 5, 64, 42 }); + EXPECT_EQ(4u, foo.size()); + foo.remove(1); + foo.remove(5); + foo.remove(42); + foo.remove(64); + HashSet bar(foo); + + EXPECT_EQ(0u, bar.capacity()); + EXPECT_EQ(0u, bar.size()); + } +} + +TEST(WTF_HashSet, CopyAllocateAtLeastMinimumCapacity) +{ + HashSet foo({ 42 }); + EXPECT_EQ(1u, foo.size()); + HashSet 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 source; + for (unsigned i = 1; i < size + 1; ++i) + source.add(i); + + HashSet copy1(source); + HashSet copy2(source); + HashSet 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* bucketAddress { nullptr }; + const DerefObserver* observedBucket { nullptr }; + }; + + auto observer = std::make_unique(); + + HashSet> 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::hashTableDeletedValue()); + EXPECT_EQ(observer->count, 0u); +} + + +TEST(WTF_HashSet, UniquePtrNotZeroedBeforeDestructor) +{ + struct DestructorObserver { + ~DestructorObserver() + { + observe(); + } + std::function observe; + }; + + const std::unique_ptr* bucketAddress = nullptr; + const DestructorObserver* observedBucket = nullptr; + std::unique_ptr observer(new DestructorObserver { [&]() { + observedBucket = bucketAddress->get(); + }}); + + const DestructorObserver* observerAddress = observer.get(); + + HashSet> 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(-1)); +} + +TEST(WTF_HashSet, Ref) +{ + { + HashSet> set; + + RefLogger a("a"); + Ref ref(a); + set.add(WTFMove(ref)); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashSet> set; + + RefLogger a("a"); + Ref ref(a); + set.add(ref.copyRef()); + } + + ASSERT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str()); + + { + HashSet> set; + + RefLogger a("a"); + Ref ref(a); + set.add(WTFMove(ref)); + set.remove(&a); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashSet> set; + + RefLogger a("a"); + Ref ref(a); + set.add(WTFMove(ref)); + + auto aOut = set.take(&a); + ASSERT_TRUE(static_cast(aOut)); + ASSERT_EQ(&a, aOut.value().ptr()); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashSet> set; + + RefLogger a("a"); + Ref ref(a); + set.add(WTFMove(ref)); + + auto aOut = set.takeAny(); + ASSERT_TRUE(static_cast(aOut)); + ASSERT_EQ(&a, aOut.value().ptr()); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashSet> set; + auto emptyTake = set.takeAny(); + ASSERT_FALSE(static_cast(emptyTake)); + } + + { + HashSet> set; + + RefLogger a("a"); + Ref ref(a); + set.add(WTFMove(ref)); + + ASSERT_TRUE(set.contains(&a)); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + HashSet> set; + for (int i = 0; i < 64; ++i) { + Ref 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 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 +#include + +namespace TestWebKitAPI { + +static void testUInt32LEBDecode(std::initializer_list data, size_t startOffset, bool expectedStatus, uint32_t expectedResult, size_t expectedOffset) +{ + Vector 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 data, size_t startOffset, bool expectedStatus, uint64_t expectedResult, size_t expectedOffset) +{ + Vector 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 data, size_t startOffset, bool expectedStatus, int32_t expectedResult, size_t expectedOffset) +{ + Vector 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 data, size_t startOffset, bool expectedStatus, int64_t expectedResult, size_t expectedOffset) +{ + Vector 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::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::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::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::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 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 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 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 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 +#include +#include +#include + +using namespace WTF; + +namespace TestWebKitAPI { + +struct LockInspector { + template + static bool isFullyReset(LockType& lock) + { + return lock.isFullyReset(); + } +}; + +template +void runLockTest(unsigned numThreadGroups, unsigned numThreadsPerGroup, unsigned workPerCriticalSection, unsigned numIterations) +{ + std::unique_ptr locks = std::make_unique(numThreadGroups); + std::unique_ptr words = std::make_unique(numThreadGroups); + std::unique_ptr threads = std::make_unique(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(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(1, 1, 1, 10000000); +} + +TEST(WTF_WordLock, UncontendedLongSection) +{ + runLockTest(1, 1, 10000, 1000); +} + +TEST(WTF_WordLock, ContendedShortSection) +{ + if (skipSlow()) + return; + runLockTest(1, 10, 1, 5000000); +} + +TEST(WTF_WordLock, ContendedLongSection) +{ + if (skipSlow()) + return; + runLockTest(1, 10, 10000, 10000); +} + +TEST(WTF_WordLock, ManyContendedShortSections) +{ + if (skipSlow()) + return; + runLockTest(10, 10, 1, 500000); +} + +TEST(WTF_WordLock, ManyContendedLongSections) +{ + if (skipSlow()) + return; + runLockTest(10, 10, 10000, 500); +} + +TEST(WTF_Lock, UncontendedShortSection) +{ + runLockTest(1, 1, 1, 10000000); +} + +TEST(WTF_Lock, UncontendedLongSection) +{ + runLockTest(1, 1, 10000, 1000); +} + +TEST(WTF_Lock, ContendedShortSection) +{ + if (skipSlow()) + return; + runLockTest(1, 10, 1, 10000000); +} + +TEST(WTF_Lock, ContendedLongSection) +{ + if (skipSlow()) + return; + runLockTest(1, 10, 10000, 10000); +} + +TEST(WTF_Lock, ManyContendedShortSections) +{ + if (skipSlow()) + return; + runLockTest(10, 10, 1, 500000); +} + +TEST(WTF_Lock, ManyContendedLongSections) +{ + if (skipSlow()) + return; + runLockTest(10, 10, 10000, 1000); +} + +TEST(WTF_Lock, ManyContendedLongerSections) +{ + if (skipSlow()) + return; + runLockTest(10, 10, 100000, 1); +} + +TEST(WTF_Lock, SectionAddressCollision) +{ + if (skipSlow()) + return; + runLockTest(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 +#include #include using namespace std; -#if COMPILER(MSVC) -// Work around Visual Studio 2008's lack of an INFINITY or NAN definition. -#include -#if !defined(INFINITY) -#define INFINITY (numeric_limits::infinity()) -#endif -#if !defined(NAN) -#define NAN (numeric_limits::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::infinity()), MediaTime::positiveInfiniteTime()); + EXPECT_EQ(MediaTime::createWithFloat(-std::numeric_limits::infinity()), MediaTime::negativeInfiniteTime()); + EXPECT_EQ(MediaTime::createWithFloat(std::numeric_limits::quiet_NaN()), MediaTime::invalidTime()); + + EXPECT_EQ(MediaTime::createWithDouble(std::numeric_limits::infinity()), MediaTime::positiveInfiniteTime()); + EXPECT_EQ(MediaTime::createWithDouble(-std::numeric_limits::infinity()), MediaTime::negativeInfiniteTime()); + EXPECT_EQ(MediaTime::createWithDouble(std::numeric_limits::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::max(), 2) + MediaTime(numeric_limits::max(), 2)).timeScale(), 1); - EXPECT_EQ((MediaTime(numeric_limits::min(), 2) - MediaTime(numeric_limits::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::max(), 2) + MediaTime(numeric_limits::max(), 2)).timeScale(), 1U); + EXPECT_EQ((MediaTime(numeric_limits::min(), 2) - MediaTime(numeric_limits::max(), 2)).timeScale(), 1U); EXPECT_EQ(MediaTime(numeric_limits::max(), 1) + MediaTime(numeric_limits::max(), 1), MediaTime::positiveInfiniteTime()); EXPECT_EQ(MediaTime(numeric_limits::min(), 1) + MediaTime(numeric_limits::min(), 1), MediaTime::negativeInfiniteTime()); EXPECT_EQ(MediaTime(numeric_limits::min(), 1) - MediaTime(numeric_limits::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 #include +#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 + +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 empty; + ASSERT_EQ(nullptr, empty.get()); + + { + NakedPtr ptr(&a); + ASSERT_EQ(&a, ptr.get()); + ASSERT_EQ(&a, &*ptr); + ASSERT_EQ(&a.name, &ptr->name); + } + + { + NakedPtr ptr = &a; + ASSERT_EQ(&a, ptr.get()); + } + + { + NakedPtr p1 = &a; + NakedPtr p2(p1); + ASSERT_EQ(&a, p1.get()); + ASSERT_EQ(&a, p2.get()); + } + + { + NakedPtr p1 = &a; + NakedPtr p2 = p1; + ASSERT_EQ(&a, p1.get()); + ASSERT_EQ(&a, p2.get()); + } + + { + NakedPtr p1 = &a; + NakedPtr p2 = WTFMove(p1); + ASSERT_EQ(&a, p1.get()); + ASSERT_EQ(&a, p2.get()); + } + + { + NakedPtr p1 = &a; + NakedPtr p2(WTFMove(p1)); + ASSERT_EQ(&a, p1.get()); + ASSERT_EQ(&a, p2.get()); + } + + { + NakedPtr p1 = &a; + NakedPtr p2 = p1; + ASSERT_EQ(&a, p1.get()); + ASSERT_EQ(&a, p2.get()); + } + + { + NakedPtr p1 = &a; + NakedPtr p2 = WTFMove(p1); + ASSERT_EQ(&a, p1.get()); + ASSERT_EQ(&a, p2.get()); + } + + { + NakedPtr 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 p1(&a); + NakedPtr 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 ptr(&a); + ASSERT_EQ(&a, ptr.get()); + ptr = &b; + ASSERT_EQ(&b, ptr.get()); + } + + { + NakedPtr ptr(&a); + ASSERT_EQ(&a, ptr.get()); + ptr = nullptr; + ASSERT_EQ(nullptr, ptr.get()); + } + + { + NakedPtr p1(&a); + NakedPtr 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 p1(&a); + NakedPtr 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 ptr(&a); + ASSERT_EQ(&a, ptr.get()); + ptr = &c; + ASSERT_EQ(&c, ptr.get()); + } + + { + NakedPtr p1(&a); + NakedPtr 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 ptr(&a); + ASSERT_EQ(&a, ptr.get()); + ptr = ptr; + ASSERT_EQ(&a, ptr.get()); + } + + { + NakedPtr 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 p1(&a); + NakedPtr 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 p1(&a); + NakedPtr 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 nakedPtrFoo(RefLogger& logger) +{ + return NakedPtr(&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 + +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 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 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 set { ExampleFlags::A, ExampleFlags::B }; + + EXPECT_TRUE((set == OptionSet { ExampleFlags::A, ExampleFlags::B })); + EXPECT_TRUE((set == OptionSet { ExampleFlags::B, ExampleFlags::A })); + EXPECT_FALSE(set == ExampleFlags::B); +} + +TEST(WTF_OptionSet, NotEqual) +{ + OptionSet set = ExampleFlags::A; + + EXPECT_TRUE(set != ExampleFlags::B); + EXPECT_FALSE(set != ExampleFlags::A); +} + +TEST(WTF_OptionSet, Minus) +{ + OptionSet set { ExampleFlags::A, ExampleFlags::B, ExampleFlags::C }; + + EXPECT_TRUE(((set - ExampleFlags::A) == OptionSet { ExampleFlags::B, ExampleFlags::C })); + EXPECT_TRUE(((set - ExampleFlags::D) == OptionSet { ExampleFlags::A, ExampleFlags::B, ExampleFlags::C })); + EXPECT_TRUE((set - set).isEmpty()); +} + +TEST(WTF_OptionSet, ContainsTwoFlags) +{ + OptionSet 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 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 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 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 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::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 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::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 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::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 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::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 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::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 set { ExampleFlags::C, ExampleFlags::B }; + OptionSet::iterator it1 = set.begin(); + OptionSet::iterator it2 = it1; + ++it1; + EXPECT_STRONG_ENUM_EQ(ExampleFlags::C, *it1); + EXPECT_STRONG_ENUM_EQ(ExampleFlags::B, *it2); +} + +TEST(WTF_OptionSet, IterateOverOptionSetThatContainsTwoFlags) +{ + OptionSet set { ExampleFlags::A, ExampleFlags::C }; + OptionSet::iterator it = set.begin(); + OptionSet::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 set { ExampleFlags::D, ExampleFlags::E }; + OptionSet::iterator it = set.begin(); + OptionSet::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 set { ThirtyTwoBitFlags::A }; + OptionSet::iterator it = set.begin(); + OptionSet::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 set { SixtyFourBitFlags::A }; + OptionSet::iterator it = set.begin(); + OptionSet::iterator end = set.end(); + EXPECT_TRUE(it != end); + ++it; + EXPECT_TRUE(it == end); +} + +TEST(WTF_OptionSet, IterationOrderTheSameRegardlessOfInsertionOrder) +{ + OptionSet set1 = ExampleFlags::C; + set1 |= ExampleFlags::A; + + OptionSet set2 = ExampleFlags::A; + set2 |= ExampleFlags::C; + + OptionSet::iterator it1 = set1.begin(); + OptionSet::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 + +namespace TestWebKitAPI { + +TEST(WTF_Optional, Disengaged) +{ + { + std::optional optional; + + EXPECT_FALSE(static_cast(optional)); + } + + { + std::optional optional { std::nullopt }; + + EXPECT_FALSE(static_cast(optional)); + } +} + +TEST(WTF_Optional, Engaged) +{ + std::optional optional { 10 }; + + EXPECT_TRUE(static_cast(optional)); + EXPECT_EQ(10, optional.value()); +} + +TEST(WTF_Optional, Destructor) +{ + static bool didCallDestructor = false; + struct A { + ~A() + { + EXPECT_FALSE(didCallDestructor); + didCallDestructor = true; + } + }; + + { + std::optional optional { std::in_place }; + + EXPECT_TRUE(static_cast(optional)); + } + + EXPECT_TRUE(didCallDestructor); +} + +TEST(WTF_Optional, Callback) +{ + bool called = false; + std::optional 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 unengaged1; + std::optional unengaged2; + + std::optional engaged1 { 1 }; + std::optional engaged2 { 2 }; + std::optional 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 unengaged1; + std::optional unengaged2; + + std::optional engaged1 { 1 }; + std::optional engaged2 { 2 }; + std::optional 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 +#include +#include +#include +#include +#include +#include +#include +#include + +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 locker(lock); + awake.add(currentThread()); + lastAwoken = currentThread(); + condition.notify_one(); + })); + } + } + + void unparkOne(unsigned singleUnparkIndex) + { + EXPECT_EQ(0u, lastAwoken); + + unsigned numWaitingOnAddress = 0; + Vector 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 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 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 semaphore; + std::mutex lock; + std::condition_variable condition; + HashSet awake; + Vector threads; + ThreadIdentifier lastAwoken { 0 }; +}; + +void runParkingTest(unsigned numLatches, unsigned delay, unsigned numThreads, unsigned numSingleUnparks) +{ + std::unique_ptr tests = std::make_unique(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 #include #include @@ -38,14 +37,14 @@ TEST(WTF_Ref, Basic) { Ref 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 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 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 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 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 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 passWithPassRef(PassRef reference) +static Ref passWithRef(Ref&& reference) { - return reference; + return WTFMove(reference); } -RefPtr passWithPassRefPtr(PassRefPtr reference) +static RefPtr passWithPassRefPtr(PassRefPtr reference) { return reference; } @@ -115,32 +114,48 @@ TEST(WTF_Ref, ReturnValue) DerivedRefLogger c("c"); { - Ref ptr(passWithPassRef(a)); - ASSERT_EQ(&a, &ptr.get()); + Ref ptr(passWithRef(Ref(a))); + ASSERT_EQ(&a, ptr.ptr()); } ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); { Ref 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 ptr(passWithPassRef(a)); + RefPtr ptr(passWithRef(a)); ASSERT_EQ(&a, ptr.get()); } ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); { - RefPtr ptr(passWithPassRefPtr(passWithPassRef(a))); + RefPtr ptr(passWithPassRefPtr(passWithRef(a))); ASSERT_EQ(&a, ptr.get()); } ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + RefPtr ptr(&a); + RefPtr ptr2(WTFMove(ptr)); + ASSERT_EQ(nullptr, ptr.get()); + ASSERT_EQ(&a, ptr2.get()); + } + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); + + { + Ref derivedReference(a); + Ref 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 +#include +#include + +namespace TestWebKitAPI { + +static const int IncrementExpected = 0xC0FFEE1; +static const int DecrementExpected = 0xC0FFEE2; +static const int CallbackNotExpected = 0xDECAF; + +enum TestCounterType { }; +typedef RefCounter TestCounter; +typedef TestCounter::Token TokenType; + +TEST(WTF, RefCounter) +{ + // RefCounter API is pretty simple, containing the following 4 methods to test: + // + // 1) RefCounter(std::function); + // 2) ~RefCounter(); + // 3) Ref 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(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(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(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(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(counter.value())); + // Testing (3k) - deref using a Ref rather than a RefPtr. + + callbackValue = DecrementExpected; + } + EXPECT_EQ(1, callbackValue); + EXPECT_EQ(1, static_cast(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(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(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(counter.value())); + // Testing (3h) - ref without callback + TokenType incTo1(counter.count()); + // Testing (4c) - value as read after the ref. + EXPECT_EQ(1, static_cast(counter.value())); + // Testing (3i) - deref without callback + incTo1 = nullptr; + // Testing (4c) - value as read after the deref. + EXPECT_EQ(0, static_cast(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 +#include #include namespace TestWebKitAPI { @@ -69,7 +71,7 @@ TEST(WTF_RefPtr, Basic) { RefPtr p1 = &a; - RefPtr p2 = std::move(p1); + RefPtr p2 = WTFMove(p1); ASSERT_EQ(nullptr, p1.get()); ASSERT_EQ(&a, p2.get()); } @@ -77,7 +79,7 @@ TEST(WTF_RefPtr, Basic) { RefPtr p1 = &a; - RefPtr p2(std::move(p1)); + RefPtr p2(WTFMove(p1)); ASSERT_EQ(nullptr, p1.get()); ASSERT_EQ(&a, p2.get()); } @@ -93,7 +95,7 @@ TEST(WTF_RefPtr, Basic) { RefPtr p1 = &a; - RefPtr p2 = std::move(p1); + RefPtr p2 = WTFMove(p1); ASSERT_EQ(nullptr, p1.get()); ASSERT_EQ(&a, p2.get()); } @@ -102,7 +104,7 @@ TEST(WTF_RefPtr, Basic) { RefPtr 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 passRef(a); - RefPtr ptr = std::move(passRef); + Ref passRef(a); + RefPtr 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 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 { + static Ref create() { return adoptRef(*new ConstRefCounted); } +}; + +const ConstRefCounted& returnConstRefCountedRef() +{ + static NeverDestroyed instance; + return instance.get(); +} +ConstRefCounted& returnRefCountedRef() +{ + static NeverDestroyed instance; + return instance.get(); +} + +TEST(WTF_RefPtr, Const) +{ + // This test passes if it compiles without an error. + auto a = ConstRefCounted::create(); + Ref b = WTFMove(a); + RefPtr c = b.ptr(); + Ref d = returnConstRefCountedRef(); + RefPtr e = &returnConstRefCountedRef(); + RefPtr f = ConstRefCounted::create(); + RefPtr g = f; + RefPtr h(f); + Ref 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 + +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(); + 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 { + public: + DerivedTimer(bool& testFinished) + : RunLoop::Timer(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 { + public: + DerivedTimer(bool& testFinished) + : RunLoop::Timer(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 + +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 +#include + +using namespace WTF; + +namespace TestWebKitAPI { + +// This test relies on this module being compiled with -fno-elide-constructors +TEST(WTF_ScopedLambda, NoRVOLivenessBug) +{ + Vector vector; + for (unsigned i = 0; i < 10; ++i) + vector.append(i); + + auto lambda = scopedLambda( + [=] (size_t i) -> int { + return vector[i]; + }); + + for (unsigned i = 0; i < 10; ++i) + EXPECT_EQ(i, static_cast(lambda(i))); +} + +} // namespace TestWebKitAPI + diff --git a/Tools/TestWebKitAPI/Tests/WTF/SetForScope.cpp b/Tools/TestWebKitAPI/Tests/WTF/SetForScope.cpp new file mode 100644 index 000000000..92e3494d6 --- /dev/null +++ b/Tools/TestWebKitAPI/Tests/WTF/SetForScope.cpp @@ -0,0 +1,47 @@ +/* + * 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 + +namespace TestWebKitAPI { + +TEST(WTF, SetForScopeNested) +{ + bool originallyFalse = false; + { + SetForScope change1OriginallyFalse(originallyFalse, true); + EXPECT_TRUE(originallyFalse); + { + SetForScope change2OriginallyFalse(originallyFalse, false); + EXPECT_FALSE(originallyFalse); + } + EXPECT_TRUE(originallyFalse); + } + EXPECT_FALSE(originallyFalse); +} + +} // namespace TestWebKitAPI 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 +#include + +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 +#include 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 +#include +#include #include namespace TestWebKitAPI { @@ -33,14 +34,14 @@ namespace TestWebKitAPI { TEST(WTF, StringImplCreationFromLiteral) { // Constructor using the template to determine the size. - RefPtr 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 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(programmaticString->characters8())); @@ -48,27 +49,16 @@ TEST(WTF, StringImplCreationFromLiteral) // Constructor without explicit size. const char* stringWithoutLengthLiteral = "No Size Literal"; - RefPtr 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(programmaticStringNoLength->characters8())); ASSERT_TRUE(programmaticStringNoLength->is8Bit()); } -TEST(WTF, StringImplFromLiteralLoop16BitConversion) -{ - RefPtr controlString = StringImpl::create("Template Literal"); - for (size_t i = 0; i < 10; ++i) { - RefPtr 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 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("")); + 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("")); + auto b = StringImpl::create(reinterpret_cast("")); + ASSERT_TRUE(equalIgnoringASCIICase(a.ptr(), b.ptr())); + ASSERT_TRUE(equalIgnoringASCIICase(b.ptr(), a.ptr())); +} + +static Ref 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(0), referenceA->findIgnoringASCIICase(referenceA.ptr())); + EXPECT_EQ(static_cast(0), referenceB->findIgnoringASCIICase(referenceB.ptr())); + + // A and B are distinct by the non-ascii character é/É. + EXPECT_EQ(static_cast(notFound), referenceA->findIgnoringASCIICase(referenceB.ptr())); + EXPECT_EQ(static_cast(notFound), referenceB->findIgnoringASCIICase(referenceA.ptr())); + + // Find the prefix. + EXPECT_EQ(static_cast(0), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("a").ptr())); + EXPECT_EQ(static_cast(0), referenceA->findIgnoringASCIICase(stringFromUTF8("abcé").ptr())); + EXPECT_EQ(static_cast(0), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("A").ptr())); + EXPECT_EQ(static_cast(0), referenceA->findIgnoringASCIICase(stringFromUTF8("ABCé").ptr())); + EXPECT_EQ(static_cast(0), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("a").ptr())); + EXPECT_EQ(static_cast(0), referenceB->findIgnoringASCIICase(stringFromUTF8("abcÉ").ptr())); + EXPECT_EQ(static_cast(0), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("A").ptr())); + EXPECT_EQ(static_cast(0), referenceB->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr())); + + // Not a prefix. + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("x").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("accé").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("abcÉ").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("X").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ABDé").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("y").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("accÉ").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("abcé").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("Y").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ABdÉ").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ABCé").ptr())); + + // Find the infix. + EXPECT_EQ(static_cast(2), referenceA->findIgnoringASCIICase(stringFromUTF8("cée").ptr())); + EXPECT_EQ(static_cast(3), referenceA->findIgnoringASCIICase(stringFromUTF8("ée").ptr())); + EXPECT_EQ(static_cast(2), referenceA->findIgnoringASCIICase(stringFromUTF8("cé").ptr())); + EXPECT_EQ(static_cast(2), referenceA->findIgnoringASCIICase(stringFromUTF8("c").ptr())); + EXPECT_EQ(static_cast(3), referenceA->findIgnoringASCIICase(stringFromUTF8("é").ptr())); + EXPECT_EQ(static_cast(2), referenceA->findIgnoringASCIICase(stringFromUTF8("Cée").ptr())); + EXPECT_EQ(static_cast(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éE").ptr())); + EXPECT_EQ(static_cast(2), referenceA->findIgnoringASCIICase(stringFromUTF8("Cé").ptr())); + EXPECT_EQ(static_cast(2), referenceA->findIgnoringASCIICase(stringFromUTF8("C").ptr())); + + EXPECT_EQ(static_cast(2), referenceB->findIgnoringASCIICase(stringFromUTF8("cÉe").ptr())); + EXPECT_EQ(static_cast(3), referenceB->findIgnoringASCIICase(stringFromUTF8("Ée").ptr())); + EXPECT_EQ(static_cast(2), referenceB->findIgnoringASCIICase(stringFromUTF8("cÉ").ptr())); + EXPECT_EQ(static_cast(2), referenceB->findIgnoringASCIICase(stringFromUTF8("c").ptr())); + EXPECT_EQ(static_cast(3), referenceB->findIgnoringASCIICase(stringFromUTF8("É").ptr())); + EXPECT_EQ(static_cast(2), referenceB->findIgnoringASCIICase(stringFromUTF8("CÉe").ptr())); + EXPECT_EQ(static_cast(3), referenceB->findIgnoringASCIICase(stringFromUTF8("ÉE").ptr())); + EXPECT_EQ(static_cast(2), referenceB->findIgnoringASCIICase(stringFromUTF8("CÉ").ptr())); + EXPECT_EQ(static_cast(2), referenceB->findIgnoringASCIICase(stringFromUTF8("C").ptr())); + + // Not an infix. + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("céd").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Ée").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("bé").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("x").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("É").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("CÉe").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("éd").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("CÉ").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Y").ptr())); + + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("cée").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("Éc").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("cé").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("W").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("é").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("bÉe").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éE").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("BÉ").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("z").ptr())); + + // Find the suffix. + EXPECT_EQ(static_cast(6), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("g").ptr())); + EXPECT_EQ(static_cast(4), referenceA->findIgnoringASCIICase(stringFromUTF8("efg").ptr())); + EXPECT_EQ(static_cast(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éefg").ptr())); + EXPECT_EQ(static_cast(6), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("G").ptr())); + EXPECT_EQ(static_cast(4), referenceA->findIgnoringASCIICase(stringFromUTF8("EFG").ptr())); + EXPECT_EQ(static_cast(3), referenceA->findIgnoringASCIICase(stringFromUTF8("éEFG").ptr())); + + EXPECT_EQ(static_cast(6), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("g").ptr())); + EXPECT_EQ(static_cast(4), referenceB->findIgnoringASCIICase(stringFromUTF8("efg").ptr())); + EXPECT_EQ(static_cast(3), referenceB->findIgnoringASCIICase(stringFromUTF8("Éefg").ptr())); + EXPECT_EQ(static_cast(6), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("G").ptr())); + EXPECT_EQ(static_cast(4), referenceB->findIgnoringASCIICase(stringFromUTF8("EFG").ptr())); + EXPECT_EQ(static_cast(3), referenceB->findIgnoringASCIICase(stringFromUTF8("ÉEFG").ptr())); + + // Not a suffix. + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("X").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("edg").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("Éefg").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(StringImpl::createFromLiteral("w").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("dFG").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceA->findIgnoringASCIICase(stringFromUTF8("ÉEFG").ptr())); + + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("Z").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("ffg").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éefg").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(StringImpl::createFromLiteral("r").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("EgG").ptr())); + EXPECT_EQ(static_cast(WTF::notFound), referenceB->findIgnoringASCIICase(stringFromUTF8("éEFG").ptr())); +} + +TEST(WTF, StringImplFindIgnoringASCIICaseWithValidOffset) +{ + auto reference = stringFromUTF8("ABCÉEFGaBcéeFG"); + EXPECT_EQ(static_cast(0), reference->findIgnoringASCIICase(stringFromUTF8("ABC").ptr(), 0)); + EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(stringFromUTF8("ABC").ptr(), 1)); + EXPECT_EQ(static_cast(0), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), 0)); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), 1)); + EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(stringFromUTF8("ABCé").ptr(), 0)); + EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(stringFromUTF8("ABCé").ptr(), 1)); +} + +TEST(WTF, StringImplFindIgnoringASCIICaseWithInvalidOffset) +{ + auto reference = stringFromUTF8("ABCÉEFGaBcéeFG"); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABC").ptr(), 15)); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABC").ptr(), 16)); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), 17)); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), 42)); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(stringFromUTF8("ABCÉ").ptr(), std::numeric_limits::max())); +} + +TEST(WTF, StringImplFindIgnoringASCIICaseOnNull) +{ + auto reference = stringFromUTF8("ABCÉEFG"); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(nullptr)); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 0)); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 3)); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 7)); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 8)); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(nullptr, 42)); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(nullptr, std::numeric_limits::max())); +} + +TEST(WTF, StringImplFindIgnoringASCIICaseOnEmpty) +{ + auto reference = stringFromUTF8("ABCÉEFG"); + auto empty = StringImpl::create(reinterpret_cast("")); + EXPECT_EQ(static_cast(0), reference->findIgnoringASCIICase(empty.ptr())); + EXPECT_EQ(static_cast(0), reference->findIgnoringASCIICase(empty.ptr(), 0)); + EXPECT_EQ(static_cast(3), reference->findIgnoringASCIICase(empty.ptr(), 3)); + EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(empty.ptr(), 7)); + EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(empty.ptr(), 8)); + EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(empty.ptr(), 42)); + EXPECT_EQ(static_cast(7), reference->findIgnoringASCIICase(empty.ptr(), std::numeric_limits::max())); +} + +TEST(WTF, StringImplFindIgnoringASCIICaseWithPatternLongerThanReference) +{ + auto reference = stringFromUTF8("ABCÉEFG"); + auto pattern = stringFromUTF8("XABCÉEFG"); + EXPECT_EQ(static_cast(WTF::notFound), reference->findIgnoringASCIICase(pattern.ptr())); + EXPECT_EQ(static_cast(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("")); + ASSERT_FALSE(empty->startsWithIgnoringASCIICase(nullptr)); +} + +TEST(WTF, StringImplStartsWithIgnoringASCIICaseWithEmpty) +{ + auto reference = StringImpl::createFromLiteral("aBcDeFG"); + auto empty = StringImpl::create(reinterpret_cast("")); + 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("")); + ASSERT_FALSE(empty->endsWithIgnoringASCIICase(nullptr)); +} + +TEST(WTF, StringImplEndsWithIgnoringASCIICaseWithEmpty) +{ + auto reference = StringImpl::createFromLiteral("aBcDeFG"); + auto empty = StringImpl::create(reinterpret_cast("")); + 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(0), emptyString.length()); + + UChar ucharArray[] = { 't', 'e', 's', 't', '\0' }; + String concatenation16 = ucharArray + emptyString; + ASSERT_EQ(static_cast(4), concatenation16.length()); + ASSERT_TRUE(concatenation16 == String(ucharArray)); + + LChar lcharArray[] = { 't', 'e', 's', 't', '\0' }; + String concatenation8 = lcharArray + emptyString; + ASSERT_EQ(static_cast(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 +#include + +namespace TestWebKitAPI { + +StringView stringViewFromLiteral(const char* characters) +{ + return StringView(reinterpret_cast(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 expected) +{ + std::vector actual; + for (auto graphemeCluster : graphemeClusters) + actual.push_back(graphemeCluster); + return actual == expected; +} + +bool compareLoopIterations(StringView::CodePoints codePoints, std::vector expected) +{ + std::vector actual; + for (auto codePoint : codePoints) + actual.push_back(codePoint); + return actual == expected; +} + +static bool compareLoopIterations(StringView::CodeUnits codeUnits, std::vector expected) +{ + std::vector actual; + for (auto codeUnit : codeUnits) + actual.push_back(codeUnit); + return actual == expected; +} + +static void build(StringBuilder& builder, std::vector 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 vectorFromSplitResult(const StringView::SplitResult& substrings) +{ + Vector 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 actual = vectorFromSplitResult(a.split('T')); + Vector 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 actual = vectorFromSplitResult(a.split(' ')); + Vector 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 a = StringImpl::createFromLiteral("aBcDeFG"); + RefPtr b = StringImpl::createFromLiteral("ABCDEFG"); + RefPtr c = StringImpl::createFromLiteral("abcdefg"); + const char d[] = "aBcDeFG"; + RefPtr empty = StringImpl::create(reinterpret_cast("")); + RefPtr shorter = StringImpl::createFromLiteral("abcdef"); + RefPtr 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 a = StringImpl::create(reinterpret_cast("")); + RefPtr b = StringImpl::create(reinterpret_cast("")); + StringView stringViewA(*a.get()); + StringView stringViewB(*b.get()); + ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewB)); + ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewA)); +} + +TEST(WTF, StringViewEqualIgnoringASCIICaseWithLatin1Characters) +{ + RefPtr a = StringImpl::create(reinterpret_cast("aBcéeFG")); + RefPtr b = StringImpl::create(reinterpret_cast("ABCÉEFG")); + RefPtr c = StringImpl::create(reinterpret_cast("ABCéEFG")); + RefPtr d = StringImpl::create(reinterpret_cast("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(0), referenceA.findIgnoringASCIICase(referenceA)); + EXPECT_EQ(static_cast(0), referenceB.findIgnoringASCIICase(referenceB)); + + // A and B are distinct by the non-ascii character é/É. + EXPECT_EQ(static_cast(notFound), referenceA.findIgnoringASCIICase(referenceB)); + EXPECT_EQ(static_cast(notFound), referenceB.findIgnoringASCIICase(referenceA)); + + String tempStringHolder; + // Find the prefix. + EXPECT_EQ(static_cast(0), referenceA.findIgnoringASCIICase(stringViewFromLiteral("a"))); + EXPECT_EQ(static_cast(0), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "abcé"))); + EXPECT_EQ(static_cast(0), referenceA.findIgnoringASCIICase(stringViewFromLiteral("A"))); + EXPECT_EQ(static_cast(0), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCé"))); + EXPECT_EQ(static_cast(0), referenceB.findIgnoringASCIICase(stringViewFromLiteral("a"))); + EXPECT_EQ(static_cast(0), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "abcÉ"))); + EXPECT_EQ(static_cast(0), referenceB.findIgnoringASCIICase(stringViewFromLiteral("A"))); + EXPECT_EQ(static_cast(0), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"))); + + // Not a prefix. + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromLiteral("x"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "accé"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "abcÉ"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromLiteral("X"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABDé"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromLiteral("y"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "accÉ"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "abcé"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromLiteral("Y"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABdÉ"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCé"))); + + // Find the infix. + EXPECT_EQ(static_cast(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cée"))); + EXPECT_EQ(static_cast(3), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ée"))); + EXPECT_EQ(static_cast(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cé"))); + EXPECT_EQ(static_cast(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "c"))); + EXPECT_EQ(static_cast(3), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "é"))); + EXPECT_EQ(static_cast(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Cée"))); + EXPECT_EQ(static_cast(3), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éE"))); + EXPECT_EQ(static_cast(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Cé"))); + EXPECT_EQ(static_cast(2), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "C"))); + + EXPECT_EQ(static_cast(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cÉe"))); + EXPECT_EQ(static_cast(3), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Ée"))); + EXPECT_EQ(static_cast(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cÉ"))); + EXPECT_EQ(static_cast(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "c"))); + EXPECT_EQ(static_cast(3), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "É"))); + EXPECT_EQ(static_cast(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "CÉe"))); + EXPECT_EQ(static_cast(3), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ÉE"))); + EXPECT_EQ(static_cast(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "CÉ"))); + EXPECT_EQ(static_cast(2), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "C"))); + + // Not an infix. + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "céd"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Ée"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "bé"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "x"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "É"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "CÉe"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éd"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "CÉ"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Y"))); + + EXPECT_EQ(static_cast(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cée"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Éc"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "cé"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "W"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "é"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "bÉe"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éE"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "BÉ"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "z"))); + + // Find the suffix. + EXPECT_EQ(static_cast(6), referenceA.findIgnoringASCIICase(stringViewFromLiteral("g"))); + EXPECT_EQ(static_cast(4), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "efg"))); + EXPECT_EQ(static_cast(3), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éefg"))); + EXPECT_EQ(static_cast(6), referenceA.findIgnoringASCIICase(stringViewFromLiteral("G"))); + EXPECT_EQ(static_cast(4), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "EFG"))); + EXPECT_EQ(static_cast(3), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éEFG"))); + + EXPECT_EQ(static_cast(6), referenceB.findIgnoringASCIICase(stringViewFromLiteral("g"))); + EXPECT_EQ(static_cast(4), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "efg"))); + EXPECT_EQ(static_cast(3), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Éefg"))); + EXPECT_EQ(static_cast(6), referenceB.findIgnoringASCIICase(stringViewFromLiteral("G"))); + EXPECT_EQ(static_cast(4), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "EFG"))); + EXPECT_EQ(static_cast(3), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ÉEFG"))); + + // Not a suffix. + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromLiteral("X"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "edg"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "Éefg"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromLiteral("w"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "dFG"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceA.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ÉEFG"))); + + EXPECT_EQ(static_cast(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromLiteral("Z"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ffg"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "éefg"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromLiteral("r"))); + EXPECT_EQ(static_cast(WTF::notFound), referenceB.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "EgG"))); + EXPECT_EQ(static_cast(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(0), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABC"), 0)); + EXPECT_EQ(static_cast(7), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABC"), 1)); + EXPECT_EQ(static_cast(0), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"), 0)); + EXPECT_EQ(static_cast(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"), 1)); + EXPECT_EQ(static_cast(7), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCé"), 0)); + EXPECT_EQ(static_cast(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(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABC"), 15)); + EXPECT_EQ(static_cast(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABC"), 16)); + EXPECT_EQ(static_cast(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"), 17)); + EXPECT_EQ(static_cast(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"), 42)); + EXPECT_EQ(static_cast(WTF::notFound), reference.findIgnoringASCIICase(stringViewFromUTF8(tempStringHolder, "ABCÉ"), std::numeric_limits::max())); +} + +TEST(WTF, StringViewFindIgnoringASCIICaseOnEmpty) +{ + String referenceHolder; + StringView reference = stringViewFromUTF8(referenceHolder, "ABCÉEFG"); + StringView empty = stringViewFromLiteral(""); + EXPECT_EQ(static_cast(0), reference.findIgnoringASCIICase(empty)); + EXPECT_EQ(static_cast(0), reference.findIgnoringASCIICase(empty, 0)); + EXPECT_EQ(static_cast(3), reference.findIgnoringASCIICase(empty, 3)); + EXPECT_EQ(static_cast(7), reference.findIgnoringASCIICase(empty, 7)); + EXPECT_EQ(static_cast(7), reference.findIgnoringASCIICase(empty, 8)); + EXPECT_EQ(static_cast(7), reference.findIgnoringASCIICase(empty, 42)); + EXPECT_EQ(static_cast(7), reference.findIgnoringASCIICase(empty, std::numeric_limits::max())); +} + +TEST(WTF, StringViewFindIgnoringASCIICaseWithPatternLongerThanReference) +{ + String referenceHolder; + StringView reference = stringViewFromUTF8(referenceHolder, "ABCÉEFG"); + String patternHolder; + StringView pattern = stringViewFromUTF8(patternHolder, "ABCÉEFGA"); + + EXPECT_EQ(static_cast(WTF::notFound), reference.findIgnoringASCIICase(pattern)); + EXPECT_EQ(static_cast(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 +#include + +#include +#include +#include +#include +#include + +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 +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 m_lowerQueue; + SynchronizedFixedQueue m_upperQueue; + RefPtr m_produceQueue; + RefPtr 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/TemporaryChange.cpp b/Tools/TestWebKitAPI/Tests/WTF/TemporaryChange.cpp deleted file mode 100644 index 3ba0f15bd..000000000 --- a/Tools/TestWebKitAPI/Tests/WTF/TemporaryChange.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 - -namespace TestWebKitAPI { - -TEST(WTF, TemporaryChangeNested) -{ - bool originallyFalse = false; - { - TemporaryChange change1OriginallyFalse(originallyFalse, true); - EXPECT_TRUE(originallyFalse); - { - TemporaryChange change2OriginallyFalse(originallyFalse, false); - EXPECT_FALSE(originallyFalse); - } - EXPECT_TRUE(originallyFalse); - } - EXPECT_FALSE(originallyFalse); -} - -} // namespace TestWebKitAPI 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 + +namespace TestWebKitAPI { + +static String makeUTF16(std::vector input) +{ + return { input.data(), static_cast(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 +#include +#include +#include +#include +#include + +namespace WTF { + +std::basic_ostream& operator<<(std::basic_ostream& out, Seconds value) +{ + out << toCString(value).data(); + return out; +} + +std::basic_ostream& operator<<(std::basic_ostream& out, WallTime value) +{ + out << toCString(value).data(); + return out; +} + +std::basic_ostream& operator<<(std::basic_ostream& out, MonotonicTime value) +{ + out << toCString(value).data(); + return out; +} + +std::basic_ostream& operator<<(std::basic_ostream& 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 +#include + +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(WTFMove(a)) + { } + UniqueRef a; +}; +class D : public A { }; + +void function(const UniqueRef a) +{ + const A& b = a.get(); + const A* c = &a; + UNUSED_PARAM(b); + UNUSED_PARAM(c); +} + +TEST(WTF, UniqueRef) +{ + UniqueRef a = makeUniqueRef(); + UniqueRef b = makeUniqueRef(1, 2, 3); + B& c = b.get(); + const B& d = b.get(); + B* e = &b; + const B* f = &b; + UniqueRef j = WTFMove(a); + + Vector> v; + v.append(makeUniqueRef(4, 5, 6)); + v.append(makeUniqueRef(7, 8, 9)); + UniqueRef g = v.takeLast(); + ASSERT_EQ(g->b, 8); + ASSERT_EQ(v.last()->b, 5); + + C h(makeUniqueRef()); + C i(makeUniqueRef()); + + 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 +#include +#include +#include +#include + +namespace TestWebKitAPI { + +TEST(WTF_Variant, Initial) +{ + Variant v1; + EXPECT_TRUE(v1.index() == 0); + EXPECT_TRUE(WTF::get(v1) == 0); + + struct T { + T() : value(15) { } + int value; + }; + + Variant v2; + EXPECT_TRUE(v2.index() == 0); + EXPECT_TRUE(WTF::get(v2).value == 15); +} + +TEST(WTF_Variant, Basic) +{ + Variant variant = 1; + EXPECT_TRUE(variant.index() == 0); + EXPECT_TRUE(WTF::get(variant) == 1); + EXPECT_TRUE(*WTF::get_if(variant) == 1); + EXPECT_TRUE(WTF::get_if(variant) == nullptr); + EXPECT_TRUE(WTF::holds_alternative(variant)); + EXPECT_FALSE(WTF::holds_alternative(variant)); + + variant = 1.0; + EXPECT_TRUE(variant.index() == 1); + EXPECT_TRUE(WTF::get(variant) == 1); + EXPECT_TRUE(*WTF::get_if(variant) == 1.0); + EXPECT_TRUE(WTF::get_if(variant) == nullptr); + EXPECT_TRUE(WTF::holds_alternative(variant)); + EXPECT_FALSE(WTF::holds_alternative(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 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 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 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(); + Variant, 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 ref(&a); + Variant, int> v = ref; + } + + ASSERT_STREQ("ref(a) ref(a) deref(a) deref(a) ", takeLogStr().c_str()); + + { + RefLogger a("a"); + RefPtr ref(&a); + Variant, int> v = WTFMove(ref); + } + + ASSERT_STREQ("ref(a) deref(a) ", takeLogStr().c_str()); +} + +TEST(WTF_Variant, Ref) +{ + { + RefLogger a("a"); + Ref ref(a); + Variant, 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 +#include namespace TestWebKitAPI { @@ -34,8 +35,8 @@ TEST(WTF_Vector, Basic) { Vector 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 vector; @@ -94,6 +95,103 @@ TEST(WTF_Vector, InitializerList) EXPECT_EQ(4, vector[3]); } +TEST(WTF_Vector, InitializeFromOtherInitialCapacity) +{ + Vector vector = { 1, 3, 2, 4 }; + Vector 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 vector = { 1, 3, 2, 4 }; + Vector 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 vector = { 4, 3, 2, 1 }; + Vector 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 vector = { 4, 3, 2, 1 }; + Vector 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 vector = { 3, 4, 2, 1 }; + Vector 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 vector = { 3, 4, 2, 1 }; + Vector 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 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 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 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, 1>, 1> a; + Vector, 1>, 1> b; + Vector, 1>, 1> c; + + EXPECT_EQ(0U, a.size()); + EXPECT_EQ(0U, b.size()); + EXPECT_EQ(0U, c.size()); + + Vector x; + x.append(42); + + EXPECT_EQ(1U, x.size()); + EXPECT_EQ(42, x[0]); + + Vector, 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 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({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({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::canMoveWithMemcpy, "Should use a memcpy-able type"); + Vector 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({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({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({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({3, 2, 4, 2, 2, 2, 4, 4, 3})); + + // Using a non memcpy-able type. + static_assert(!VectorTraits::canMoveWithMemcpy, "Should use a non memcpy-able type"); + Vector vExpected; + Vector 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 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({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({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({2, 1, 2, 1, 2, 2, 1, 1, 1})); +} + +TEST(WTF_Vector, RemoveAllMatching) +{ + Vector 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({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({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 +#include +#include +#include + +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 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 + +namespace TestWebKitAPI { + +TEST(WTF_WeakPtr, Basic) +{ + int dummy = 5; + WeakPtrFactory* factory = new WeakPtrFactory(&dummy); + WeakPtr weakPtr1 = factory->createWeakPtr(); + WeakPtr weakPtr2 = factory->createWeakPtr(); + WeakPtr 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 weakPtr; + { + WeakPtrFactory 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* factory1 = new WeakPtrFactory(&dummy1); + WeakPtrFactory* factory2 = new WeakPtrFactory(&dummy2); + WeakPtr weakPtr1 = factory1->createWeakPtr(); + WeakPtr 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 factory(&dummy); + WeakPtr weakPtr1 = factory.createWeakPtr(); + WeakPtr weakPtr2 = factory.createWeakPtr(); + WeakPtr 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 factory(nullptr); + WeakPtr weakPtr = factory.createWeakPtr(); + EXPECT_NULL(weakPtr.get()); + factory.revokeAll(); + EXPECT_NULL(weakPtr.get()); +} + +struct Foo { + void bar() { }; +}; + +TEST(WTF_WeakPtr, Dereference) +{ + Foo f; + WeakPtrFactory factory(&f); + WeakPtr weakPtr = factory.createWeakPtr(); + weakPtr->bar(); +} + +TEST(WTF_WeakPtr, Forget) +{ + int dummy = 5; + int dummy2 = 7; + + WeakPtrFactory outerFactory(&dummy2); + WeakPtr weakPtr1, weakPtr2, weakPtr3, weakPtr4; + { + WeakPtrFactory 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 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 weakPtr5 = weakPtr4; + EXPECT_EQ(weakPtr4.get(), &dummy2); + EXPECT_EQ(weakPtr5.get(), &dummy2); + weakPtr5.clear(); + EXPECT_NULL(weakPtr5.get()); + WeakPtr weakPtr6 = weakPtr5; + EXPECT_NULL(weakPtr6.get()); + EXPECT_EQ(weakPtr5.get(), weakPtr6.get()); + + WeakPtr 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 +#include +#include +#include +#include +#include + +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 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(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 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(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 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(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 + +#include +#include + +namespace TestWebKitAPI { + +TEST(OSObjectPtr, AdoptOSObject) +{ + OSObjectPtr 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 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/glib/GUniquePtr.cpp b/Tools/TestWebKitAPI/Tests/WTF/glib/GUniquePtr.cpp new file mode 100644 index 000000000..11f02c7b0 --- /dev/null +++ b/Tools/TestWebKitAPI/Tests/WTF/glib/GUniquePtr.cpp @@ -0,0 +1,195 @@ +/* + * 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 + +inline std::ostringstream& log() +{ + static std::ostringstream log; + return log; +} + +inline std::string takeLogStr() +{ + std::string string = log().str(); + log().str(""); + return string; +} + +static void (* _g_free)(void*) = g_free; +#define g_free(x) \ + log() << "g_free(" << ptr << ");"; \ + _g_free(x); + +static void (* _g_error_free)(GError*) = g_error_free; +#define g_error_free(x) \ + log() << "g_error_free(" << ptr << ");"; \ + _g_error_free(x); + +static void (* _g_list_free)(GList*) = g_list_free; +#define g_list_free(x) \ + log() << "g_list_free(" << ptr << ");"; \ + _g_list_free(x); + +static void (* _g_slist_free)(GSList*) = g_slist_free; +#define g_slist_free(x) \ + log() << "g_slist_free(" << ptr << ");"; \ + _g_slist_free(x); + +static void (* _g_pattern_spec_free)(GPatternSpec*) = g_pattern_spec_free; +#define g_pattern_spec_free(x) \ + log() << "g_pattern_spec_free(" << ptr << ");"; \ + _g_pattern_spec_free(x); + +static void (* _g_dir_close)(GDir*) = g_dir_close; +#define g_dir_close(x) \ + log() << "g_dir_close(" << ptr << ");"; \ + _g_dir_close(x); + +static void (* _g_timer_destroy)(GTimer*) = g_timer_destroy; +#define g_timer_destroy(x) \ + log() << "g_timer_destroy(" << ptr << ");"; \ + _g_timer_destroy(x); + +static void (* _g_key_file_free)(GKeyFile*) = g_key_file_free; +#define g_key_file_free(x) \ + log() << "g_key_file_free(" << ptr << ");"; \ + _g_key_file_free(x); + +#include + +namespace TestWebKitAPI { + +TEST(WTF_GUniquePtr, Basic) +{ + std::ostringstream actual; + + { + GUniquePtr a(g_strdup("a")); + actual << "g_free(" << a.get() << ");"; + } + ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); + actual.str(""); + + { + GUniquePtr a(g_error_new_literal(G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "a")); + actual << "g_error_free(" << a.get() << ");"; + } + ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); + actual.str(""); + + { + GUniquePtr a(g_list_prepend(nullptr, g_strdup("a"))); + actual << "g_list_free(" << a.get() << ");"; + } + ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); + actual.str(""); + + { + GUniquePtr a(g_slist_prepend(nullptr, g_strdup("a"))); + actual << "g_slist_free(" << a.get() << ");"; + } + ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); + actual.str(""); + + { + GUniquePtr a(g_pattern_spec_new("a")); + actual << "g_pattern_spec_free(" << a.get() << ");"; + } + ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); + actual.str(""); + + { + GUniquePtr a(g_dir_open("/tmp", 0, nullptr)); + actual << "g_dir_close(" << a.get() << ");"; + } + ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); + actual.str(""); + + { + GUniquePtr a(g_timer_new()); + actual << "g_timer_destroy(" << a.get() << ");"; + } + ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); + actual.str(""); + + { + GUniquePtr a(g_key_file_new()); + actual << "g_key_file_free(" << a.get() << ");"; + } + ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); + actual.str(""); +} + +static void returnOutChar(char** outChar) +{ + *outChar = g_strdup("a"); +} + +TEST(WTF_GUniquePtr, OutPtr) +{ + std::ostringstream actual; + + { + GUniqueOutPtr a; + ASSERT_EQ(nullptr, a.get()); + } + ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); + actual.str(""); + + { + GUniqueOutPtr a; + returnOutChar(&a.outPtr()); + actual << "g_free(" << a.get() << ");"; + } + ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); + actual.str(""); + + { + GUniqueOutPtr a; + returnOutChar(&a.outPtr()); + actual << "g_free(" << a.get() << ");"; + returnOutChar(&a.outPtr()); + ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); + actual.str(""); + actual << "g_free(" << a.get() << ");"; + } + ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); + actual.str(""); + + { + GUniqueOutPtr a; + returnOutChar(&a.outPtr()); + GUniquePtr b = a.release(); + ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); + actual << "g_free(" << b.get() << ");"; + } + ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); + actual.str(""); +} + +} // 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 +#include +#include +#include +#include +#include +#include + +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 currentDirectory(g_get_current_dir()); + GRefPtr 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(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/WTF/gobject/GUniquePtr.cpp b/Tools/TestWebKitAPI/Tests/WTF/gobject/GUniquePtr.cpp deleted file mode 100644 index 8942f8657..000000000 --- a/Tools/TestWebKitAPI/Tests/WTF/gobject/GUniquePtr.cpp +++ /dev/null @@ -1,195 +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 - -inline std::ostringstream& log() -{ - static std::ostringstream log; - return log; -} - -inline std::string takeLogStr() -{ - std::string string = log().str(); - log().str(""); - return string; -} - -static void (* _g_free)(void*) = g_free; -#define g_free(x) \ - log() << "g_free(" << ptr << ");"; \ - _g_free(x); - -static void (* _g_error_free)(GError*) = g_error_free; -#define g_error_free(x) \ - log() << "g_error_free(" << ptr << ");"; \ - _g_error_free(x); - -static void (* _g_list_free)(GList*) = g_list_free; -#define g_list_free(x) \ - log() << "g_list_free(" << ptr << ");"; \ - _g_list_free(x); - -static void (* _g_slist_free)(GSList*) = g_slist_free; -#define g_slist_free(x) \ - log() << "g_slist_free(" << ptr << ");"; \ - _g_slist_free(x); - -static void (* _g_pattern_spec_free)(GPatternSpec*) = g_pattern_spec_free; -#define g_pattern_spec_free(x) \ - log() << "g_pattern_spec_free(" << ptr << ");"; \ - _g_pattern_spec_free(x); - -static void (* _g_dir_close)(GDir*) = g_dir_close; -#define g_dir_close(x) \ - log() << "g_dir_close(" << ptr << ");"; \ - _g_dir_close(x); - -static void (* _g_timer_destroy)(GTimer*) = g_timer_destroy; -#define g_timer_destroy(x) \ - log() << "g_timer_destroy(" << ptr << ");"; \ - _g_timer_destroy(x); - -static void (* _g_key_file_free)(GKeyFile*) = g_key_file_free; -#define g_key_file_free(x) \ - log() << "g_key_file_free(" << ptr << ");"; \ - _g_key_file_free(x); - -#include - -namespace TestWebKitAPI { - -TEST(WTF_GUniquePtr, Basic) -{ - std::ostringstream actual; - - { - GUniquePtr a(g_strdup("a")); - actual << "g_free(" << a.get() << ");"; - } - ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); - actual.str(""); - - { - GUniquePtr a(g_error_new_literal(G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "a")); - actual << "g_error_free(" << a.get() << ");"; - } - ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); - actual.str(""); - - { - GUniquePtr a(g_list_prepend(nullptr, g_strdup("a"))); - actual << "g_list_free(" << a.get() << ");"; - } - ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); - actual.str(""); - - { - GUniquePtr a(g_slist_prepend(nullptr, g_strdup("a"))); - actual << "g_slist_free(" << a.get() << ");"; - } - ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); - actual.str(""); - - { - GUniquePtr a(g_pattern_spec_new("a")); - actual << "g_pattern_spec_free(" << a.get() << ");"; - } - ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); - actual.str(""); - - { - GUniquePtr a(g_dir_open("/tmp", 0, nullptr)); - actual << "g_dir_close(" << a.get() << ");"; - } - ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); - actual.str(""); - - { - GUniquePtr a(g_timer_new()); - actual << "g_timer_destroy(" << a.get() << ");"; - } - ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); - actual.str(""); - - { - GUniquePtr a(g_key_file_new()); - actual << "g_key_file_free(" << a.get() << ");"; - } - ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); - actual.str(""); -} - -static void returnOutChar(char** outChar) -{ - *outChar = g_strdup("a"); -} - -TEST(WTF_GUniquePtr, OutPtr) -{ - std::ostringstream actual; - - { - GUniqueOutPtr a; - ASSERT_EQ(nullptr, a.get()); - } - ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); - actual.str(""); - - { - GUniqueOutPtr a; - returnOutChar(&a.outPtr()); - actual << "g_free(" << a.get() << ");"; - } - ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); - actual.str(""); - - { - GUniqueOutPtr a; - returnOutChar(&a.outPtr()); - actual << "g_free(" << a.get() << ");"; - returnOutChar(&a.outPtr()); - ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); - actual.str(""); - actual << "g_free(" << a.get() << ");"; - } - ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); - actual.str(""); - - { - GUniqueOutPtr a; - returnOutChar(&a.outPtr()); - GUniquePtr b = a.release(); - ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); - actual << "g_free(" << b.get() << ");"; - } - ASSERT_STREQ(actual.str().c_str(), takeLogStr().c_str()); - actual.str(""); -} - -} // 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#if USE(CG) +#include +#endif + +#if PLATFORM(WIN) +#include +#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 +#include + +using namespace WebCore; + +namespace TestWebKitAPI { + +class CARingBufferTest : public testing::Test { +public: + + virtual void SetUp() + { + WTF::initializeMainThread(); + m_ringBuffer = std::make_unique(); + } + + // 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(1, m_description.numberOfChannelStreams())); + m_bufferList = std::unique_ptr(static_cast(::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(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 m_bufferList; + std::unique_ptr 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(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(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 +class MixingTest { +public: + static void run(CARingBufferTest& test) + { + const int sampleCount = 64; + + CAAudioStreamDescription::PCMFormat format; + if (std::is_same::value) + format = CAAudioStreamDescription::PCMFormat::Float32; + else if (std::is_same::value) + format = CAAudioStreamDescription::PCMFormat::Float64; + else if (std::is_same::value) + format = CAAudioStreamDescription::PCMFormat::Int32; + else if (std::is_same::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(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(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::run(*this); +} + +TEST_F(CARingBufferTest, DoubleMixing) +{ + MixingTest::run(*this); +} + +TEST_F(CARingBufferTest, Int32Mixing) +{ + MixingTest::run(*this); +} + +TEST_F(CARingBufferTest, Int16Mixing) +{ + MixingTest::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 +#include +#include + +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 value = properties->getPropertyCSSValue(testCase.propertyID); + + ASSERT_TRUE(value->isValueList()); + EXPECT_EQ(computeNumberOfTracks(*downcast(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 + +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 createTestValue() +{ + auto node = std::make_unique(); + return WebCore::CalculationValue::create(WTFMove(node), WebCore::ValueRangeAll); +} + +TEST(CalculationValue, LengthConstruction) +{ + RefPtr 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 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 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 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 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 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 + +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 +#include +#include +#include +#include + +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 advances = { FloatSize(), FloatSize(21.640625, 0.0), FloatSize(42.3046875, 0.0), FloatSize(55.8984375, 0.0), FloatSize(22.34375, 0.0) }; + Vector origins = { FloatPoint(-15.15625, 18.046875), FloatPoint(), FloatPoint(), FloatPoint(), FloatPoint() }; +#else + Vector 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 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> 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 advances = { FloatSize(), FloatSize(21.640625, 0.0), FloatSize(42.3046875, 0.0), FloatSize(55.8984375, 0.0), FloatSize(22.34375, 0.0) }; + Vector origins = { FloatPoint(-15.15625, 18.046875), FloatPoint(), FloatPoint(), FloatPoint(), FloatPoint() }; +#else + Vector 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 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> 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 advances = { FloatSize(76.347656, 0.000000), FloatSize(0.000000, 0.000000) }; + Vector origins = { FloatPoint(), FloatPoint(-23.281250, -8.398438) }; +#else + Vector advances = { FloatSize(53.066406, -8.398438), FloatSize(23.281250, 8.398438) }; + Vector 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> 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 advances = { FloatSize(76.347656, 0.000000), FloatSize(0.000000, 0.000000) }; + Vector origins = { FloatPoint(), FloatPoint(-23.281250, -8.398438) }; +#else + Vector advances = { FloatSize(53.066406, -8.398438), FloatSize(23.281250, 8.398438) }; + Vector 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> 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> 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> 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> 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 advances = { FloatSize(1, 0), FloatSize(2, 0), FloatSize(4, 0), FloatSize(8, 0), FloatSize(16, 0) }; +#if USE_LAYOUT_SPECIFIC_ADVANCES + Vector origins = { FloatPoint(), FloatPoint(), FloatPoint(), FloatPoint(), FloatPoint() }; +#else + Vector 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> 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 actions; + Vector filtersWithoutDomains; + Vector filtersWithDomains; + Vector 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&& 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&& 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&& bytecode) override + { + EXPECT_FALSE(finalized); + EXPECT_EQ(m_data.domainFilters.size(), 0ull); + m_data.filtersWithDomains.appendVector(bytecode); + } + + void writeDomainFiltersBytecode(Vector&& 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 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 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 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 createNFAs(ContentExtensions::CombinedURLFilters& combinedURLFilters) +{ + Vector nfas; + + combinedURLFilters.processNFAs(std::numeric_limits::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& 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 nfas = createNFAs(combinedURLFilters); + EXPECT_EQ(1ul, nfas.size()); + EXPECT_EQ(12ul, nfas.first().nodes.size()); + + ContentExtensions::DFA dfa = ContentExtensions::NFAToDFA::convert(nfas.first()); + Vector 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 nfas = createNFAs(combinedURLFilters); + + EXPECT_EQ(1ul, nfas.size()); + EXPECT_EQ(17ul, nfas.first().nodes.size()); + + ContentExtensions::DFA dfa = ContentExtensions::NFAToDFA::convert(nfas.first()); + Vector 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 nfas = createNFAs(combinedURLFilters); + EXPECT_EQ(1ul, nfas.size()); + EXPECT_EQ(7ul, nfas.first().nodes.size()); + + ContentExtensions::DFA dfa = ContentExtensions::NFAToDFA::convert(nfas.first()); + Vector 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 nfas; + combinedURLFilters.processNFAs(std::numeric_limits::max(), [&](ContentExtensions::NFA&& nfa) { + nfas.append(WTFMove(nfa)); + }); + EXPECT_EQ(nfas.size(), 1ull); + + Vector dfas; + for (auto& nfa : nfas) + dfas.append(ContentExtensions::NFAToDFA::convert(nfa)); + EXPECT_EQ(dfas.size(), 1ull); + + Vector combinedBytecode; + for (const auto& dfa : dfas) { + Vector 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 nfas; + combinedURLFilters.processNFAs(i, [&](ContentExtensions::NFA&& nfa) { + nfas.append(WTFMove(nfa)); + }); + EXPECT_EQ(nfas.size(), expectedNFACounts[i]); + + Vector dfas; + for (auto& nfa : nfas) + dfas.append(ContentExtensions::NFAToDFA::convert(nfa)); + + Vector combinedBytecode; + for (const auto& dfa : dfas) { + Vector 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 +#include + +using namespace WebCore; +using namespace ContentExtensions; + +namespace TestWebKitAPI { + +class DFACombinerTest : public testing::Test { +public: + virtual void SetUp() + { + WTF::initializeMainThread(); + } +}; + +Vector combine(Vector dfas, unsigned minimumSize) +{ + DFACombiner combiner; + for (DFA& dfa : dfas) + combiner.addDFA(WTFMove(dfa)); + + Vector output; + combiner.combineDFAs(minimumSize, [&output](DFA&& dfa) { + output.append(dfa); + }); + return output; +} + +TEST_F(DFACombinerTest, Basic) +{ + Vector dfas = { buildDFAFromPatterns({ "foo"}), buildDFAFromPatterns({ "bar"}) }; + Vector combinedDFAs = combine(dfas, 10000); + EXPECT_EQ(static_cast(1), combinedDFAs.size()); + + DFA reference = buildDFAFromPatterns({ "foo", "bar"}); + reference.minimize(); + EXPECT_EQ(countLiveNodes(reference), countLiveNodes(combinedDFAs.first())); +} + + +TEST_F(DFACombinerTest, IdenticalDFAs) +{ + Vector dfas = { buildDFAFromPatterns({ "foo"}), buildDFAFromPatterns({ "foo"}) }; + Vector combinedDFAs = combine(dfas, 10000); + EXPECT_EQ(static_cast(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(0), counter); +} + +TEST_F(DFACombinerTest, SingleInput) +{ + Vector dfas = { buildDFAFromPatterns({ "WebKit"}) }; + Vector combinedDFAs = combine(dfas, 10000); + EXPECT_EQ(static_cast(1), combinedDFAs.size()); + + DFA reference = buildDFAFromPatterns({ "WebKit"}); + reference.minimize(); + EXPECT_EQ(countLiveNodes(reference), countLiveNodes(combinedDFAs.first())); +} + +TEST_F(DFACombinerTest, InputTooLargeForMinimumSize) +{ + Vector dfas = { buildDFAFromPatterns({ "foo"}), buildDFAFromPatterns({ "bar"}) }; + Vector combinedDFAs = combine(dfas, 2); + EXPECT_EQ(static_cast(2), combinedDFAs.size()); + EXPECT_EQ(static_cast(4), countLiveNodes(combinedDFAs[0])); + EXPECT_EQ(static_cast(4), countLiveNodes(combinedDFAs[1])); +} + +TEST_F(DFACombinerTest, CombinedInputReachesMinimumSize) +{ + Vector dfas = { buildDFAFromPatterns({ "foo"}), buildDFAFromPatterns({ "bar"}), buildDFAFromPatterns({ "WebKit"}) }; + Vector combinedDFAs = combine(dfas, 5); + EXPECT_EQ(static_cast(2), combinedDFAs.size()); + EXPECT_EQ(static_cast(7), countLiveNodes(combinedDFAs[0])); + EXPECT_EQ(static_cast(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 +#include +#include +#include + +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 createNFAs(ContentExtensions::CombinedURLFilters& combinedURLFilters) +{ + Vector nfas; + + combinedURLFilters.processNFAs(std::numeric_limits::max(), [&](ContentExtensions::NFA&& nfa) { + nfas.append(WTFMove(nfa)); + }); + + return nfas; +} + +static ContentExtensions::DFA buildDFAFromPatterns(Vector patterns) +{ + ContentExtensions::CombinedURLFilters combinedURLFilters; + ContentExtensions::URLFilterParser parser(combinedURLFilters); + + for (const char* pattern : patterns) + parser.addPattern(pattern, false, 0); + Vector 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 + +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(8), countLiveNodes(dfa)); + dfa.minimize(); + EXPECT_EQ(static_cast(7), countLiveNodes(dfa)); +} + +TEST_F(DFAMinimizerTest, MergeSuffixes) +{ + ContentExtensions::DFA dfa = buildDFAFromPatterns({ ".*aaa", ".*aab", ".*aba", ".*abb", ".*baa", ".*bab", ".*bba", ".*bbb"}); + EXPECT_EQ(static_cast(12), countLiveNodes(dfa)); + dfa.minimize(); + EXPECT_EQ(static_cast(4), countLiveNodes(dfa)); +} + +TEST_F(DFAMinimizerTest, MergeInfixes) +{ + ContentExtensions::DFA dfa = buildDFAFromPatterns({ ".*aaakit", ".*aabkit", ".*abakit", ".*abbkit", ".*baakit", ".*babkit", ".*bbakit", ".*bbbkit"}); + EXPECT_EQ(static_cast(15), countLiveNodes(dfa)); + dfa.minimize(); + EXPECT_EQ(static_cast(7), countLiveNodes(dfa)); +} + +TEST_F(DFAMinimizerTest, FallbackTransitionsWithDifferentiatorDoNotMerge1) +{ + ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^a.a", "^b.a", "^bac", "^bbc", "^BCC"}); + EXPECT_EQ(static_cast(6), countLiveNodes(dfa)); + dfa.minimize(); + EXPECT_EQ(static_cast(6), countLiveNodes(dfa)); +} + +TEST_F(DFAMinimizerTest, FallbackTransitionsWithDifferentiatorDoNotMerge2) +{ + ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^bbc", "^BCC", "^a.a", "^b.a"}); + EXPECT_EQ(static_cast(6), countLiveNodes(dfa)); + dfa.minimize(); + EXPECT_EQ(static_cast(6), countLiveNodes(dfa)); +} + +TEST_F(DFAMinimizerTest, FallbackTransitionsWithDifferentiatorDoNotMerge3) +{ + ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^a.c", "^b.c", "^baa", "^bba", "^BCA"}); + EXPECT_EQ(static_cast(6), countLiveNodes(dfa)); + dfa.minimize(); + EXPECT_EQ(static_cast(6), countLiveNodes(dfa)); +} + +TEST_F(DFAMinimizerTest, FallbackTransitionsWithDifferentiatorDoNotMerge4) +{ + ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^baa", "^bba", "^BCA", "^a.c", "^b.c"}); + EXPECT_EQ(static_cast(6), countLiveNodes(dfa)); + dfa.minimize(); + EXPECT_EQ(static_cast(6), countLiveNodes(dfa)); +} + +TEST_F(DFAMinimizerTest, FallbackTransitionsToOtherNodeInSameGroupDoesNotDifferentiateGroup) +{ + ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^aac", "^a.c", "^b.c"}); + EXPECT_EQ(static_cast(5), countLiveNodes(dfa)); + dfa.minimize(); + EXPECT_EQ(static_cast(4), countLiveNodes(dfa)); +} + +TEST_F(DFAMinimizerTest, SimpleFallBackTransitionDifferentiator1) +{ + ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^a.bc.de", "^a.bd.ef"}); + EXPECT_EQ(static_cast(11), countLiveNodes(dfa)); + dfa.minimize(); + EXPECT_EQ(static_cast(11), countLiveNodes(dfa)); +} + +TEST_F(DFAMinimizerTest, SimpleFallBackTransitionDifferentiator2) +{ + ContentExtensions::DFA dfa = buildDFAFromPatterns({ "^cb.", "^db.b"}); + EXPECT_EQ(static_cast(7), countLiveNodes(dfa)); + dfa.minimize(); + EXPECT_EQ(static_cast(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 + +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 +#include +#include + +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(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 +#include +#include +#include +#include +#include + +#if USE(CG) +#include +#endif + +#if PLATFORM(WIN) +#include +#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 +#include +#include +#include + +#if USE(CG) +#include +#endif + +#if PLATFORM(WIN) +#include +#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::max() / 2, infinite.x()); + EXPECT_FLOAT_EQ(-std::numeric_limits::max() / 2, infinite.y()); + EXPECT_FLOAT_EQ(std::numeric_limits::max(), infinite.width()); + EXPECT_FLOAT_EQ(std::numeric_limits::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::max() / 2, cgInfiniteRect.origin.x); + EXPECT_FLOAT_EQ(-std::numeric_limits::max() / 2, cgInfiniteRect.origin.y); + EXPECT_FLOAT_EQ(std::numeric_limits::max(), cgInfiniteRect.size.width); + EXPECT_FLOAT_EQ(std::numeric_limits::max(), cgInfiniteRect.size.height); +#else + EXPECT_FLOAT_EQ(-std::numeric_limits::max(), cgInfiniteRect.origin.x); + EXPECT_FLOAT_EQ(-std::numeric_limits::max(), cgInfiniteRect.origin.y); + EXPECT_FLOAT_EQ(std::numeric_limits::max(), cgInfiniteRect.origin.x + cgInfiniteRect.size.width); + EXPECT_FLOAT_EQ(std::numeric_limits::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::max(), d2dInfiniteRect.left); + EXPECT_FLOAT_EQ(-std::numeric_limits::max(), d2dInfiniteRect.top); + EXPECT_FLOAT_EQ(std::numeric_limits::max(), d2dInfiniteRect.right); + EXPECT_FLOAT_EQ(std::numeric_limits::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 +#include +#include + +#if USE(CG) +#include +#endif + +#if PLATFORM(WIN) +#include +#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 + +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 +#include + +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 +#include +#include + +#if USE(CG) +#include +#endif + +#if PLATFORM(WIN) +#include +#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 +#include +#include +#include + +#if USE(CG) +#include +#endif + +#if PLATFORM(WIN) +#include +#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 +#include + +#if USE(CG) +#include +#endif + +#if PLATFORM(WIN) +#include +#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 @@ -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 +#include + +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 +#include + +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 +#include + +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 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> divide(const MediaTime& presentationTime) final { return { }; } + Ref createNonDisplayingCopy() const final { + return create(m_presentationTime, m_decodeTime, m_duration, static_cast(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 +#include +#include +#include + +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 o1 = SecurityOrigin::create("http", "example.com", std::optional(80)); + Ref o2 = SecurityOrigin::create("http", "example.com", std::optional()); + Ref o3 = SecurityOrigin::createFromString("http://example.com"); + Ref o4 = SecurityOrigin::createFromString("http://example.com:80"); + Ref o5 = SecurityOrigin::create(URL(URL(), "http://example.com")); + Ref 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 +#include +#include + +using namespace WebCore; + +namespace TestWebKitAPI { + +TEST_F(SharedBufferTest, createWithContentsOfMissingFile) +{ + RefPtr buffer = SharedBuffer::createWithContentsOfFile(String("not_existing_file")); + ASSERT_NULL(buffer); +} + +TEST_F(SharedBufferTest, createWithContentsOfExistingFile) +{ + RefPtr 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 buffer = SharedBuffer::createWithContentsOfFile(tempEmptyFilePath()); + ASSERT_NOT_NULL(buffer); + EXPECT_TRUE(buffer->isEmpty()); +} + +TEST_F(SharedBufferTest, copyBufferCreatedWithContentsOfExistingFile) +{ + RefPtr buffer = SharedBuffer::createWithContentsOfFile(tempFilePath()); + ASSERT_NOT_NULL(buffer); + RefPtr 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 buffer = SharedBuffer::createWithContentsOfFile(tempFilePath()); + ASSERT_NOT_NULL(buffer); + buffer->clear(); + EXPECT_TRUE(!buffer->size()); + EXPECT_TRUE(!buffer->data()); +} + +TEST_F(SharedBufferTest, appendBufferCreatedWithContentsOfExistingFile) +{ + RefPtr 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::create(testData0, strlen(testData0)); + sharedBuffer->append(testData1, strlen(testData1)); + sharedBuffer->append(testData2, strlen(testData2)); + RefPtr 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 vector0(0x4000, 'a'); + Vector vector1(0x4000, 'b'); + Vector vector2(0x4000, 'c'); + + RefPtr sharedBuffer = SharedBuffer::adoptVector(vector0); + sharedBuffer->append(vector1); + sharedBuffer->append(vector2); + RefPtr 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(arrayBuffer->data())[position]); + ++position; + } + for (int i = 0; i < 0x4000; ++i) { + EXPECT_EQ('b', static_cast(arrayBuffer->data())[position]); + ++position; + } + for (int i = 0; i < 0x4000; ++i) { + EXPECT_EQ('c', static_cast(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::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 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 +#include + +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 + +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 + +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 rangeA = TimeRanges::create(); + RefPtr 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 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 ranges = TimeRanges::create(0, 2); + + ASSERT_RANGE("{ [0,2) }", ranges); + + ranges->intersectWith(*ranges.get()); + + ASSERT_RANGE("{ [0,2) }", ranges); +} + +TEST(TimeRanges, IntersectWith_IdenticalRange) +{ + RefPtr rangesA = TimeRanges::create(0, 2); + RefPtr 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 rangesA = TimeRanges::create(0, 2); + RefPtr 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 rangesA = TimeRanges::create(); + RefPtr 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 rangesA = TimeRanges::create(); + RefPtr 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 rangesA = TimeRanges::create(); + RefPtr 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 rangesA = TimeRanges::create(); + RefPtr 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 rangesA = TimeRanges::create(); + RefPtr 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 rangesA = TimeRanges::create(); + RefPtr 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 rangesA = TimeRanges::create(); + RefPtr 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 +#include +#include +#include +#include +#include +#include + +#if USE(CG) +#include +#endif + +#if USE(CA) +#include +#endif + +#if PLATFORM(WIN) +#include +#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 +#include #include 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 +#include +#include + +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({'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 +#include + +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 +#include +#include + +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 -#include - -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 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 Binary files /dev/null and b/Tools/TestWebKitAPI/Tests/WebKit2/Ahem.ttf 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 +#include 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 +#include 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 + +namespace TestWebKitAPI { + +static bool testDone; +static std::unique_ptr 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(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 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 preferences(AdoptWK, WKPreferencesCreate()); + WKPageGroupRef pageGroup = WKPageGetPageGroup(webView.page()); + WKPreferencesSetUniversalAccessFromFileURLsAllowed(preferences.get(), true); + WKPageGroupSetPreferences(pageGroup, preferences.get()); + + WKRetainPtr 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 -#include +#include +#include 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 +#include +#include +#include + +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 context = adoptWK(WKContextCreate()); + WKRetainPtr 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 context = adoptWK(Util::createContextForInjectedBundleTest("WKViewIsActiveSetIsActiveTest")); + WKRetainPtr 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 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 + +#include + +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 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 +#include +#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 context(AdoptWK, WKContextCreate()); + PlatformWebView webView(context.get()); + WKRetainPtr 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 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 context(AdoptWK, WKContextCreate()); + WKRetainPtr configuration(AdoptWK, WKPageConfigurationCreate()); + WKPageConfigurationSetContext(configuration.get(), context.get()); + + WKRetainPtr 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 @@ + + +
+ + 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 @@ + 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 +#include #include 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 -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -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 -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -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 -#include +#include +#include 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 registrar("DidAssociateFormControlsTest"); @@ -54,7 +57,7 @@ static void didAssociateFormControls(WKBundlePageRef page, WKArrayRef elementHan WKRetainPtr 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 +#include 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 + +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 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 + +namespace TestWebKitAPI { + +class DidRemoveFrameFromHiearchyInPageCacheTest : public InjectedBundleTest { +public: + DidRemoveFrameFromHiearchyInPageCacheTest(const std::string& identifier); + + virtual void didCreatePage(WKBundleRef, WKBundlePageRef); +}; + +static InjectedBundleTest::Register registrar("DidRemoveFrameFromHiearchyInPageCache"); + +static unsigned didRemoveFrameFromHierarchyCount; + +void didRemoveFrameFromHierarchyCallback(WKBundlePageRef page, WKBundleFrameRef, WKTypeRef*, const void*) +{ + didRemoveFrameFromHierarchyCount++; + + WKRetainPtr 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 +#include 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 -#include -#include -#include +#include +#include +#include +#include #include namespace TestWebKitAPI { @@ -53,3 +56,5 @@ public: static InjectedBundleTest::Register 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 +#include 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 +#include +#include +#include +#include +#include + +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 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 +#include + +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 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 -#include +#include +#include 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 context = adoptWK(WKContextCreate()); + + PlatformWebView webView(context.get()); + setClients(webView.page()); + + WKRetainPtr 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 +#include 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 +#include 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 +#include 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 +#include +#include + +namespace TestWebKitAPI { + +static bool done; + +static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo) +{ + done = true; +} + +TEST(WebKit2, FrameHandle) +{ + WKRetainPtr 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 +#include 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 +#include 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 +#include +#include #include #include @@ -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 context(AdoptWK, WKContextCreate()); + WKContextSetMaximumNumberOfProcesses(context.get(), 1); GeolocationTransitionToHighAccuracyStateTracker stateTracker; setupGeolocationProvider(context.get(), &stateTracker); @@ -257,19 +265,20 @@ TEST(WebKit2, GeolocationTransitionToHighAccuracy) setupView(highAccuracyWebView); WKRetainPtr highAccuracyURL(AdoptWK, Util::createURLForResource("geolocationWatchPositionWithHighAccuracy", "html")); WKPageLoadURL(highAccuracyWebView.page(), highAccuracyURL.get()); + Util::run(&stateTracker.enabledHighAccuracy); + + WKRetainPtr 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 context(AdoptWK, WKContextCreate()); + WKContextSetMaximumNumberOfProcesses(context.get(), 1); GeolocationTransitionToLowAccuracyStateTracker stateTracker; setupGeolocationProvider(context.get(), &stateTracker); @@ -331,7 +346,11 @@ TEST(WebKit2, GeolocationTransitionToLowAccuracy) WKRetainPtr 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 +#include 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 +#include namespace TestWebKitAPI { @@ -46,3 +49,5 @@ public: static InjectedBundleTest::Register 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 +#include 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 -#include -#include +#include +#include +#include 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 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 +#include 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 +#include namespace TestWebKitAPI { @@ -47,3 +50,5 @@ public: static InjectedBundleTest::Register 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 +#include 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 -#include -#include -#include -#include +#include +#include +#include +#include +#include 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 +#include 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 +#include namespace TestWebKitAPI { @@ -46,3 +49,5 @@ public: static InjectedBundleTest::Register 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 + +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 pageGroup(AdoptWK, WKPageGroupCreateWithIdentifier(WKStringCreateWithUTF8CString("InjectedBundleMakeAllShadowRootOpenTestPageGroup"))); + + WKRetainPtr 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 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 +#include +#include +#include +#include + +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(userData); + + auto world = WKBundleScriptWorldCreateWorld(); + WKBundleScriptWorldMakeAllShadowRootsOpen(world); + + WKRetainPtr 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 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 -#include +#include +#include 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 + +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 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 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 -#include -#include +#include +#include +#include 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 context(AdoptWK, WKContextCreate()); PlatformWebView webView(context.get()); @@ -53,14 +57,29 @@ TEST(WebKit2, LoadAlternateHTMLStringWithNonDirectoryURL) loaderClient.didFinishLoadForFrame = didFinishLoadForFrame; WKPageSetPageLoaderClient(webView.page(), &loaderClient.base); - WKRetainPtr fileURL(AdoptWK, Util::createURLForResource("simple", "html")); WKRetainPtr alternateHTMLString(AdoptWK, WKStringCreateWithUTF8CString("")); - - // 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 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 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 -#include -#include +#include +#include +#include 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 -#include -#include +#include +#include +#include #include @@ -70,3 +73,5 @@ public: static InjectedBundleTest::Register 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 +#include 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 context(AdoptWK, WKContextCreate()); + PlatformWebView webView(context.get()); + setPageLoaderClient(webView.page()); + + WKRetainPtr 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 +#include +#include + +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 url = adoptWK(WKFrameCopyURL(frame)); + WKRetainPtr urlString = adoptWK(WKURLCopyString(url.get())); + EXPECT_WK_STREQ("about:blank", urlString.get()); + + WKRetainPtr protocol = adoptWK(WKSecurityOriginCopyProtocol(securityOrigin)); + EXPECT_WK_STREQ("file", protocol.get()); + + WKRetainPtr 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 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(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 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 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 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 +#include 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 -#include +#include +#include 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 -#include +#include +#include namespace TestWebKitAPI { @@ -49,3 +52,5 @@ public: static InjectedBundleTest::Register 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 +#include 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 -#include +#include +#include namespace TestWebKitAPI { @@ -49,3 +52,5 @@ public: static InjectedBundleTest::Register 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 -#include +#include +#include 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 -#include +#include +#include namespace TestWebKitAPI { @@ -49,3 +52,5 @@ public: static InjectedBundleTest::Register 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 -#include +#include +#include namespace TestWebKitAPI { @@ -49,3 +52,5 @@ public: static InjectedBundleTest::Register 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 + +#if WK_HAVE_C_SPI + +#import "PlatformUtilities.h" +#import "PlatformWebView.h" +#import "Test.h" +#import +#import +#import + +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 +#include namespace TestWebKitAPI { @@ -151,4 +154,26 @@ TEST(WebKit2, PageLoadBasic) Util::run(&test1Done); } +TEST(WebKit2, PageReload) +{ + WKRetainPtr context(AdoptWK, WKContextCreate()); + PlatformWebView webView(context.get()); + + // Reload test before url loading. + WKPageReload(webView.page()); + WKPageReload(webView.page()); + + WKRetainPtr url(AdoptWK, Util::createURLForResource("simple", "html")); + WKPageLoadURL(webView.page(), url.get()); + + // Reload test after url loading. + WKPageReload(webView.page()); + + WKRetainPtr 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 +#include 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 +#include 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 -#include -#include +#include +#include +#include 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 +#include +#include +#include + +namespace TestWebKitAPI { + +class PasteboardNotificationsTest : public InjectedBundleTest { +public: + PasteboardNotificationsTest(const std::string& identifier); + + virtual void didCreatePage(WKBundleRef, WKBundlePageRef); +}; + +static InjectedBundleTest::Register 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 + +namespace TestWebKitAPI { + +static bool done; + +TEST(WebKit2, PendingAPIRequestURL) +{ + WKRetainPtr 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 activeURL = adoptWK(WKPageCopyActiveURL(webView.page())); + EXPECT_NULL(activeURL.get()); + + WKRetainPtr 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 htmlString = Util::toWK("Hello, World"); + WKRetainPtr 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 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 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 -#include -#include +#include +#include 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 +#include 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 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 +#include +#include + +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 committedURL = adoptWK(WKFrameCopyURL(frame)); + ASSERT_NOT_NULL(committedURL.get()); + WKRetainPtr 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(userData))); + + WKRetainPtr url(AdoptWK, Util::createURLForResource("simple2", "html")); + EXPECT_TRUE(WKURLIsEqual(committedURL.get(), url.get())); + + committedLoad = true; +} + +TEST(WebKit2, ProvisionalURLAfterWillSendRequestCallback) +{ + WKRetainPtr 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 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 +#include +#include + +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 newRequest = request; + return newRequest.leakRef(); + } + + // Change the main frame URL. + WKRetainPtr 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 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 +#include 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 -#include -#include -#include +#include +#include +#include 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 +#include 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 namespace TestWebKitAPI { @@ -49,7 +53,7 @@ static void setPageLoaderClient(WKPageRef page) WKPageSetPageLoaderClient(page, &loaderClient.base); } -static WKRetainPtr createSessionStateContainingFormData(WKContextRef context) +static WKRetainPtr createSessionStateDataContainingFormData(WKContextRef context) { PlatformWebView webView(context); setPageLoaderClient(webView.page()); @@ -62,7 +66,8 @@ static WKRetainPtr createSessionStateContainingFormData(WKContextRef Util::run(&didFinishLoad); didFinishLoad = false; - return adoptWK(WKPageCopySessionState(webView.page(), 0, 0)); + auto sessionState = adoptWK(static_cast(WKPageCopySessionState(webView.page(), reinterpret_cast(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 data = createSessionStateContainingFormData(context.get()); + WKRetainPtr 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 +#include + +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 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(WKPageCopySessionState(webView.page(), reinterpret_cast(1), nullptr))); + return adoptWK(WKSessionStateCopyData(sessionState.get())); +} + +TEST(WebKit2, RestoreSessionStateWithoutNavigation) +{ + WKRetainPtr context(AdoptWK, WKContextCreate()); + + PlatformWebView webView(context.get()); + setPageLoaderClient(webView.page()); + + WKRetainPtr data = createSessionStateData(context.get()); + EXPECT_NOT_NULL(data); + + auto sessionState = adoptWK(WKSessionStateCreateFromData(data.get())); + WKPageRestoreFromSessionStateWithoutNavigation(webView.page(), sessionState.get()); + + Util::run(&didChangeBackForwardList); + + WKRetainPtr 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 -#include -#include -#include -#include +#include +#include +#include +#include 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 +#include 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 -#include +#include +#include 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 url = adoptWK(WKBackForwardListItemCopyURL(item)); + WKRetainPtr 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 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 -#include +#include +#include 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 + +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 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 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 +#include +#include +#include + +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 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 + +namespace TestWebKitAPI { + +struct WebKit2TextFieldBeginAndEditEditingTest : public ::testing::Test { + std::unique_ptr webView; + + WKRetainPtr messageName; + + bool didFinishLoad { false }; + bool didReceiveMessage { false }; + + static void didReceiveMessageFromInjectedBundle(WKContextRef, WKStringRef messageName, WKTypeRef, const void* clientInfo) + { + WebKit2TextFieldBeginAndEditEditingTest& client = *static_cast(const_cast(clientInfo)); + client.messageName = messageName; + client.didReceiveMessage = true; + } + + static void didFinishLoadForFrame(WKPageRef, WKFrameRef, WKTypeRef, const void* clientInfo) + { + WebKit2TextFieldBeginAndEditEditingTest& client = *static_cast(const_cast(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 context = adoptWK(Util::createContextForInjectedBundleTest("TextFieldDidBeginAndEndEditingEventsTest")); + setInjectedBundleClient(context.get(), this); + + webView = std::make_unique(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 + +namespace TestWebKitAPI { + +class TextFieldDidBeginAndEndEditingEventsTest : public InjectedBundleTest { +public: + TextFieldDidBeginAndEndEditingEventsTest(const std::string& identifier); + + virtual void didCreatePage(WKBundleRef, WKBundlePageRef); +}; + +static InjectedBundleTest::Register 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 +#include +#include + +namespace TestWebKitAPI { + +static bool done; + +void decidePolicyForUserMediaPermissionRequestCallBack(WKPageRef, WKFrameRef, WKSecurityOriginRef, WKSecurityOriginRef, WKUserMediaPermissionRequestRef permissionRequest, const void* /* clientInfo */) +{ + WKRetainPtr audioDeviceUIDs = WKUserMediaPermissionRequestAudioDeviceUIDs(permissionRequest); + WKRetainPtr videoDeviceUIDs = WKUserMediaPermissionRequestVideoDeviceUIDs(permissionRequest); + + if (WKArrayGetSize(videoDeviceUIDs.get()) || WKArrayGetSize(audioDeviceUIDs.get())) { + WKRetainPtr videoDeviceUID; + if (WKArrayGetSize(videoDeviceUIDs.get())) + videoDeviceUID = reinterpret_cast(WKArrayGetItemAtIndex(videoDeviceUIDs.get(), 0)); + else + videoDeviceUID = WKStringCreateWithUTF8CString(""); + + WKRetainPtr audioDeviceUID; + if (WKArrayGetSize(audioDeviceUIDs.get())) + audioDeviceUID = reinterpret_cast(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 -#include namespace TestWebKitAPI { @@ -42,7 +43,7 @@ public: } WKRetainPtr context; - OwnPtr webView; + std::unique_ptr webView; WKRetainPtr 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(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 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 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 +#include +#include +#include + +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 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 + +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 + +namespace TestWebKitAPI { + +TEST(WebKit2, WKPageConfigurationEmpty) +{ + WKRetainPtr 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 configuration = adoptWK(WKPageConfigurationCreate()); + WKRetainPtr context = adoptWK(WKContextCreate()); + WKPageConfigurationSetContext(configuration.get(), context.get()); + + PlatformWebView webView(configuration.get()); + setPageLoaderClient(webView.page()); + + WKRetainPtr copiedConfiguration = adoptWK(WKPageCopyPageConfiguration(webView.page())); + ASSERT_EQ(context.get(), WKPageConfigurationGetContext(copiedConfiguration.get())); + + WKRetainPtr url = adoptWK(Util::createURLForResource("simple", "html")); + WKPageLoadURL(webView.page(), url.get()); + + didFinishLoad = false; + Util::run(&didFinishLoad); +} + +TEST(WebKit2, WKPageConfigurationBasicWithDataStore) +{ + WKRetainPtr configuration = adoptWK(WKPageConfigurationCreate()); + WKRetainPtr context = adoptWK(WKContextCreate()); + WKPageConfigurationSetContext(configuration.get(), context.get()); + WKRetainPtr websiteDataStore = WKWebsiteDataStoreGetDefaultDataStore(); + WKPageConfigurationSetWebsiteDataStore(configuration.get(), websiteDataStore.get()); + + PlatformWebView webView(configuration.get()); + setPageLoaderClient(webView.page()); + + WKRetainPtr copiedConfiguration = adoptWK(WKPageCopyPageConfiguration(webView.page())); + ASSERT_EQ(context.get(), WKPageConfigurationGetContext(copiedConfiguration.get())); + ASSERT_EQ(WKWebsiteDataStoreGetDefaultDataStore(), WKPageConfigurationGetWebsiteDataStore(copiedConfiguration.get())); + + WKRetainPtr url = adoptWK(Util::createURLForResource("simple", "html")); + WKPageLoadURL(webView.page(), url.get()); + + didFinishLoad = false; + Util::run(&didFinishLoad); +} + +TEST(WebKit2, WKPageConfigurationBasicWithNonPersistentDataStore) +{ + WKRetainPtr configuration = adoptWK(WKPageConfigurationCreate()); + WKRetainPtr context = adoptWK(WKContextCreate()); + WKPageConfigurationSetContext(configuration.get(), context.get()); + WKRetainPtr websiteDataStore = adoptWK(WKWebsiteDataStoreCreateNonPersistentDataStore()); + WKPageConfigurationSetWebsiteDataStore(configuration.get(), websiteDataStore.get()); + + PlatformWebView webView(configuration.get()); + setPageLoaderClient(webView.page()); + + WKRetainPtr copiedConfiguration = adoptWK(WKPageCopyPageConfiguration(webView.page())); + ASSERT_EQ(context.get(), WKPageConfigurationGetContext(copiedConfiguration.get())); + ASSERT_EQ(websiteDataStore.get(), WKPageConfigurationGetWebsiteDataStore(copiedConfiguration.get())); + + WKRetainPtr 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 sessionStateWithFirstItemRemoved; +static WKRetainPtr 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(value); + + WKRetainPtr url = adoptWK(WKBackForwardListItemCopyURL(backForwardListItem)); + WKRetainPtr 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(WKPageCopySessionState(webView.page(), reinterpret_cast(1), filterFirstItemCallback))); + sessionStateWithAllItemsRemoved = adoptWK(static_cast(WKPageCopySessionState(webView.page(), reinterpret_cast(1), filterAllItemsCallback))); +} + +TEST(WebKit2, WKPageCopySessionStateWithFiltering) +{ + WKRetainPtr 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 createSessionState(WKContextRef context) +static WKRetainPtr createSessionState(WKContextRef context) { PlatformWebView webView(context); setPageLoaderClient(webView.page()); @@ -57,7 +60,7 @@ static WKRetainPtr createSessionState(WKContextRef context) Util::run(&didFinishLoad); didFinishLoad = false; - return adoptWK(WKPageCopySessionState(webView.page(), 0, 0)); + return adoptWK(static_cast(WKPageCopySessionState(webView.page(), reinterpret_cast(1), nullptr))); } TEST(WebKit2, WKPageGetScaleFactorNotZero) @@ -67,13 +70,15 @@ TEST(WebKit2, WKPageGetScaleFactorNotZero) PlatformWebView webView(context.get()); setPageLoaderClient(webView.page()); - WKRetainPtr 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 +#include +#include +#include +#include +#include + +// 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 context = adoptWK(WKContextCreate()); + + PlatformWebView webView(context.get()); + setUpClients(webView.page()); + + WKRetainPtr 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 context = adoptWK(WKContextCreate()); + + WKRetainPtr 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 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 -#include +#include +#include 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 + +namespace TestWebKitAPI { + +TEST(WebKit2, WKRetainPtr) +{ + WKRetainPtr string1 = adoptWK(WKStringCreateWithUTF8CString("a")); + WKRetainPtr string2 = adoptWK(WKStringCreateWithUTF8CString("a")); + WKRetainPtr string3 = adoptWK(WKStringCreateWithUTF8CString("a")); + WKRetainPtr string4 = adoptWK(WKStringCreateWithUTF8CString("a")); + + HashMap, 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 + +#if WK_HAVE_C_SPI + +#include #include 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 +#include +#include +#include + +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(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 data = adoptCF(CFDataCreate(0, bytes, size)); + RetainPtr 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 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 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 +#include + +namespace TestWebKitAPI { + +class WebArchiveTest : public InjectedBundleTest { +public: + WebArchiveTest(const std::string& identifier); + +private: + virtual void didReceiveMessage(WKBundleRef, WKStringRef messageName, WKTypeRef messageBody); +}; + +static InjectedBundleTest::Register 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(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 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 -#include namespace TestWebKitAPI { @@ -41,7 +42,7 @@ public: } WKRetainPtr context; - OwnPtr webView; + std::unique_ptr webView; WKRetainPtr messageName; WKRetainPtr 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(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 -#include +#include +#include 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 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 +#include namespace TestWebKitAPI { @@ -42,7 +45,7 @@ static InjectedBundleTest::Register 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 @@ + 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 @@ + + + + + + + + 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 @@ + + + + + +
+ + + + +
+ + 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 @@ + + + + + +
Link to anchor
+ In between.
+ Anchor
+ After the anchor.
+ + 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 @@ + + + + + + +

+ +

+

+ +

+ + 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 @@ + + + + + +

+ +

+

+ +

+ + 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 @@ + + + Test search. Hello Hello Hello! + + 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 @@ + +Test search. Hello world, Hello crazy world, Hello! + + 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 @@ + 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 @@ + 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 @@ + 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 @@ + 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 @@ + diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/gtk/InputMethodFilter.cpp b/Tools/TestWebKitAPI/Tests/WebKit2/gtk/InputMethodFilter.cpp new file mode 100644 index 000000000..4a0e684d6 --- /dev/null +++ b/Tools/TestWebKitAPI/Tests/WebKit2/gtk/InputMethodFilter.cpp @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2012 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 +#include +#include +#include +#include +#include + +using namespace WebKit; + +namespace TestWebKitAPI { + +class TestInputMethodFilter : public InputMethodFilter { +public: + TestInputMethodFilter() + : m_testWindow(gtk_window_new(GTK_WINDOW_POPUP)) + { + setTestingMode(true); + + gtk_widget_show(m_testWindow); + gtk_im_context_set_client_window(context(), gtk_widget_get_window(m_testWindow)); + + setEnabled(true); + } + + ~TestInputMethodFilter() + { + gtk_widget_destroy(m_testWindow); + } + + 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); + 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 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; + + filterKeyEvent(&event->key); + gdk_event_free(event); + } + + void sendPressAndReleaseKeyEventPairToFilter(unsigned gdkKeyValue, unsigned modifiers = 0) + { + sendKeyEventToFilter(gdkKeyValue, GDK_KEY_PRESS, modifiers); + sendKeyEventToFilter(gdkKeyValue, GDK_KEY_RELEASE, modifiers); + } + +private: + GtkWidget* m_testWindow; +}; + +TEST(WebKit2, InputMethodFilterSimple) +{ + TestInputMethodFilter inputMethodFilter; + inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_g); + inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_t); + inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_k); + + const Vector& events = inputMethodFilter.events(); + + ASSERT_EQ(6, events.size()); + ASSERT_EQ(String("sendSimpleKeyEvent type=press keycode=67 text='g'"), events[0]); + ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=67"), events[1]); + ASSERT_EQ(String("sendSimpleKeyEvent type=press keycode=74 text='t'"), events[2]); + ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=74"), events[3]); + ASSERT_EQ(String("sendSimpleKeyEvent type=press keycode=6b text='k'"), events[4]); + ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=6b"), events[5]); +} + +TEST(WebKit2, InputMethodFilterUnicodeSequence) +{ + TestInputMethodFilter inputMethodFilter; + + // This is simple unicode hex entry of the characters, u, 0, 0, f, 4 pressed with + // the shift and controls keys held down. In reality, these values are not typical + // of an actual hex entry, because they'd be transformed by the shift modifier according + // to the keyboard layout. For instance, on a US keyboard a 0 with the shift key pressed + // is a right parenthesis. Using these values prevents having to work out what the + // transformed characters are based on the current keyboard layout. + inputMethodFilter.sendKeyEventToFilter(GDK_KEY_Control_L, GDK_KEY_PRESS); + inputMethodFilter.sendKeyEventToFilter(GDK_KEY_Shift_L, GDK_KEY_PRESS, GDK_CONTROL_MASK); + + inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_U, GDK_SHIFT_MASK | GDK_CONTROL_MASK); + inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_0, GDK_SHIFT_MASK | GDK_CONTROL_MASK); + inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_0, GDK_SHIFT_MASK | GDK_CONTROL_MASK); + inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_F, GDK_SHIFT_MASK | GDK_CONTROL_MASK); + inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_4, GDK_SHIFT_MASK | GDK_CONTROL_MASK); + + inputMethodFilter.sendKeyEventToFilter(GDK_KEY_Shift_L, GDK_KEY_RELEASE, GDK_CONTROL_MASK | GDK_SHIFT_MASK); + inputMethodFilter.sendKeyEventToFilter(GDK_KEY_Control_L, GDK_KEY_RELEASE, GDK_CONTROL_MASK); + + const Vector& events = inputMethodFilter.events(); + ASSERT_EQ(21, events.size()); + ASSERT_EQ(String("sendSimpleKeyEvent type=press keycode=ffe3"), events[0]); + ASSERT_EQ(String("sendSimpleKeyEvent type=press keycode=ffe1"), events[1]); + ASSERT_EQ(String("sendKeyEventWithCompositionResults type=press keycode=85"), events[2]); + ASSERT_EQ(String("setPreedit text='u' cursorOffset=1"), events[3]); + ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=55"), events[4]); + ASSERT_EQ(String("sendKeyEventWithCompositionResults type=press keycode=48"), events[5]); + ASSERT_EQ(String("setPreedit text='u0' cursorOffset=2"), events[6]); + ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=30"), events[7]); + ASSERT_EQ(String("sendKeyEventWithCompositionResults type=press keycode=48"), events[8]); + ASSERT_EQ(String("setPreedit text='u00' cursorOffset=3"), events[9]); + ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=30"), events[10]); + ASSERT_EQ(String("sendKeyEventWithCompositionResults type=press keycode=70"), events[11]); + ASSERT_EQ(String("setPreedit text='u00F' cursorOffset=4"), events[12]); + ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=46"), events[13]); + ASSERT_EQ(String("sendKeyEventWithCompositionResults type=press keycode=52"), events[14]); + ASSERT_EQ(String("setPreedit text='u00F4' cursorOffset=5"), events[15]); + ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=34"), events[16]); + ASSERT_EQ(String("confirmComposition 'ô'"), events[17]); + ASSERT_EQ(String("setPreedit text='' cursorOffset=0"), events[18]); + ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=ffe1"), events[19]); + ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=ffe3"), events[20]); +} + +TEST(WebKit2, InputMethodFilterComposeKey) +{ + TestInputMethodFilter inputMethodFilter; + + inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_Multi_key); + inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_apostrophe); + inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_o); + + const Vector& events = inputMethodFilter.events(); + ASSERT_EQ(5, events.size()); + ASSERT_EQ(String("sendKeyEventWithCompositionResults type=press keycode=39"), events[0]); + ASSERT_EQ(String("setPreedit text='' cursorOffset=0"), events[1]); + ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=27"), events[2]); + ASSERT_EQ(String("sendSimpleKeyEvent type=press keycode=6f text='ó'"), events[3]); + ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=6f"), events[4]); +} + +typedef void (*GetPreeditStringCallback) (GtkIMContext*, gchar**, PangoAttrList**, int*); +static void temporaryGetPreeditStringOverride(GtkIMContext*, char** string, PangoAttrList** attrs, int* cursorPosition) +{ + *string = g_strdup("preedit of doom, bringer of cheese"); + *cursorPosition = 3; +} + +TEST(WebKit2, InputMethodFilterContextEventsWithoutKeyEvents) +{ + TestInputMethodFilter inputMethodFilter; + + // This is a bit of a hack to avoid mocking out the entire InputMethodContext, by + // simply replacing the get_preedit_string virtual method for the length of this test. + GtkIMContext* context = inputMethodFilter.context(); + GtkIMContextClass* contextClass = GTK_IM_CONTEXT_GET_CLASS(context); + GetPreeditStringCallback previousCallback = contextClass->get_preedit_string; + contextClass->get_preedit_string = temporaryGetPreeditStringOverride; + + g_signal_emit_by_name(context, "preedit-changed"); + g_signal_emit_by_name(context, "commit", "commit text"); + + contextClass->get_preedit_string = previousCallback; + + const Vector& events = inputMethodFilter.events(); + ASSERT_EQ(6, events.size()); + ASSERT_EQ(String("sendKeyEventWithCompositionResults type=press keycode=16777215 (faked)"), events[0]); + ASSERT_EQ(String("setPreedit text='preedit of doom, bringer of cheese' cursorOffset=3"), events[1]); + ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=ffffff (faked)"), events[2]); + ASSERT_EQ(String("sendKeyEventWithCompositionResults type=press keycode=16777215 (faked)"), events[3]); + ASSERT_EQ(String("confirmComposition 'commit text'"), events[4]); + ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=ffffff (faked)"), events[5]); +} + +static bool gSawContextReset = false; +typedef void (*ResetCallback) (GtkIMContext*); +static void temporaryResetOverride(GtkIMContext*) +{ + gSawContextReset = true; +} + +static void verifyCanceledComposition(const Vector& events) +{ + ASSERT_EQ(3, events.size()); + ASSERT_EQ(String("sendKeyEventWithCompositionResults type=press keycode=39"), events[0]); + ASSERT_EQ(String("setPreedit text='' cursorOffset=0"), events[1]); + ASSERT_EQ(String("sendSimpleKeyEvent type=release keycode=27"), events[2]); + ASSERT(gSawContextReset); +} + +TEST(WebKit2, InputMethodFilterContextFocusOutDuringOngoingComposition) +{ + TestInputMethodFilter inputMethodFilter; + + // See comment above about this technique. + GtkIMContext* context = inputMethodFilter.context(); + GtkIMContextClass* contextClass = GTK_IM_CONTEXT_GET_CLASS(context); + ResetCallback previousCallback = contextClass->reset; + contextClass->reset = temporaryResetOverride; + + gSawContextReset = false; + inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_Multi_key); + inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_apostrophe); + inputMethodFilter.notifyFocusedOut(); + + verifyCanceledComposition(inputMethodFilter.events()); + + contextClass->reset = previousCallback; +} + +TEST(WebKit2, InputMethodFilterContextMouseClickDuringOngoingComposition) +{ + TestInputMethodFilter inputMethodFilter; + + // See comment above about this technique. + GtkIMContext* context = inputMethodFilter.context(); + GtkIMContextClass* contextClass = GTK_IM_CONTEXT_GET_CLASS(context); + ResetCallback previousCallback = contextClass->reset; + contextClass->reset = temporaryResetOverride; + + gSawContextReset = false; + inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_Multi_key); + inputMethodFilter.sendPressAndReleaseKeyEventPairToFilter(GDK_KEY_apostrophe); + inputMethodFilter.notifyMouseButtonPress(); + + verifyCanceledComposition(inputMethodFilter.events()); + + contextClass->reset = previousCallback; +} + +} // namespace TestWebKitAPI diff --git a/Tools/TestWebKitAPI/Tests/WebKit2/icon.png b/Tools/TestWebKitAPI/Tests/WebKit2/icon.png new file mode 100644 index 000000000..79e459894 Binary files /dev/null and b/Tools/TestWebKitAPI/Tests/WebKit2/icon.png 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 @@ + + + +
+ + + + + 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 @@ + + + + + + +