Changeset 253009 in webkit


Ignore:
Timestamp:
Dec 2, 2019 2:30:59 PM (4 years ago)
Author:
commit-queue@webkit.org
Message:

Add helper methods for description and equality to text manipulation SPI
https://bugs.webkit.org/show_bug.cgi?id=204758
<rdar://problem/57438200>

Patch by Louie Livon-Bemel <Louie Livon-Bemel> on 2019-12-02
Reviewed by Wenson Hsieh.

Source/WebKit:

I originally added some category methods to _WKTextManipulationItem and _WKTextManipulationToken within Safari
to make working with these classes easier. However it makes more sense to just move these methods into
the main class. One method is for checking if two instances are equal (including identifiers) and optionally
checking if the content itself is equal. The other methods are for debug descriptions for lldb, and a
method to get a description that preserves privacy; when logging the instance, the content of the webpage
should be redacted.

Tests: Tests are added as API tests.

  • UIProcess/API/Cocoa/_WKTextManipulationItem.h:
    • Assume everything is non-null unless otherwise specified.
    • Allow the identifier to be nil, but not the array of tokens.
    • Add a method to check the equality to another item, optionally including a check for the content of each token being equal.
    • Add a -debugDescription method that includes the content of tokens for use in lldb. This NSObject declaration is marked optional, so redeclare it here.
    • No need to add a -description declaration since it exists on NSObject already.
  • UIProcess/API/Cocoa/_WKTextManipulationItem.mm:

(-[_WKTextManipulationItem isEqual:]):

The standard NSObject equality check should call our method with equal content.

(-[_WKTextManipulationItem isEqualToTextManipulationItem:includingContentEquality:]):

  • If the other item is nil, the identifiers aren't equal or the number of tokens are mismatched, these items aren't equal.
  • Just to be safe, only iterate the smaller of the token arrays so we don't crash.
  • Check if each token is equal, passing along the includingContentEquality parameter.

(-[_WKTextManipulationItem description]):

The general description should not include the webpage content.

(-[_WKTextManipulationItem debugDescription]):

Include the webpage content, since this is for lldb.

(-[_WKTextManipulationItem _descriptionPreservingPrivacy:]):

Include the standard description format, and each token on its own line. If we're including the content
then use token.debugDescription.

  • UIProcess/API/Cocoa/_WKTextManipulationToken.h:
    • Also assume everything is non-null.
    • Identifier and Content can be nil.
    • Declare a -debugDescription method.
    • Declare a method to check equality, with or without the content.
  • UIProcess/API/Cocoa/_WKTextManipulationToken.mm:

(isEqualOrBothNil):

Helper that checks equality but considers two nil values to be equal as well.

(-[_WKTextManipulationToken isEqual:]):

The standard NSObject equality check should call our method with equal content.

(-[_WKTextManipulationToken isEqualToTextManipulationToken:includingContentEquality:]):

Check that the exclusions are equal, the identifiers are equal (considering two nils to be equal), and the
content if necessary.

(-[_WKTextManipulationToken description]):
(-[_WKTextManipulationToken debugDescription]):
(-[_WKTextManipulationToken _descriptionPreservingPrivacy:]):

If we're preserving privacy, log the content length rather than the content string itself.

Tools:

Add tests for the new methods. Most are equality tests for various situations, and are moved over from the
Safari unit tests I had for the category methods that had the same purpose.

  • TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm:

(TestWebKitAPI::TEST):

  • Add test to make sure the content isn't included in the regular -description, but the identifier is. And That -debugDescription does include the contents.
  • Add many tests equality for various situations, testing both with and without content equality.

(TestWebKitAPI::createTextManipulationToken):

Add a helper for creating a token in one line.

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r253005 r253009  
     12019-12-02  Louie Livon-Bemel  <llivonbemel@apple.com>
     2
     3        Add helper methods for description and equality to text manipulation SPI
     4        https://bugs.webkit.org/show_bug.cgi?id=204758
     5        <rdar://problem/57438200>
     6
     7        Reviewed by Wenson Hsieh.
     8
     9        I originally added some category methods to _WKTextManipulationItem and _WKTextManipulationToken within Safari
     10        to make working with these classes easier. However it makes more sense to just move these methods into
     11        the main class. One method is for checking if two instances are equal (including identifiers) and optionally
     12        checking if the content itself is equal. The other methods are for debug descriptions for lldb, and a
     13        method to get a description that preserves privacy; when logging the instance, the content of the webpage
     14        should be redacted.
     15
     16        Tests: Tests are added as API tests.
     17
     18        * UIProcess/API/Cocoa/_WKTextManipulationItem.h:
     19            - Assume everything is non-null unless otherwise specified.
     20            - Allow the identifier to be nil, but not the array of tokens.
     21            - Add a method to check the equality to another item, optionally including a check for the content of each
     22              token being equal.
     23            - Add a -debugDescription method that includes the content of tokens for use in lldb. This NSObject
     24              declaration is marked optional, so redeclare it here.
     25            - No need to add a -description declaration since it exists on NSObject already.
     26        * UIProcess/API/Cocoa/_WKTextManipulationItem.mm:
     27        (-[_WKTextManipulationItem isEqual:]):
     28            The standard NSObject equality check should call our method with equal content.
     29        (-[_WKTextManipulationItem isEqualToTextManipulationItem:includingContentEquality:]):
     30            - If the other item is nil, the identifiers aren't equal or the number of tokens are mismatched, these
     31              items aren't equal.
     32            - Just to be safe, only iterate the smaller of the token arrays so we don't crash.
     33            - Check if each token is equal, passing along the `includingContentEquality` parameter.
     34        (-[_WKTextManipulationItem description]):
     35            The general description should not include the webpage content.
     36        (-[_WKTextManipulationItem debugDescription]):
     37            Include the webpage content, since this is for lldb.
     38        (-[_WKTextManipulationItem _descriptionPreservingPrivacy:]):
     39            Include the standard description format, and each token on its own line. If we're including the content
     40            then use `token.debugDescription`.
     41        * UIProcess/API/Cocoa/_WKTextManipulationToken.h:
     42            - Also assume everything is non-null.
     43            - Identifier and Content can be nil.
     44            - Declare a -debugDescription method.
     45            - Declare a method to check equality, with or without the content.
     46        * UIProcess/API/Cocoa/_WKTextManipulationToken.mm:
     47        (isEqualOrBothNil):
     48            Helper that checks equality but considers two nil values to be equal as well.
     49        (-[_WKTextManipulationToken isEqual:]):
     50            The standard NSObject equality check should call our method with equal content.
     51        (-[_WKTextManipulationToken isEqualToTextManipulationToken:includingContentEquality:]):
     52            Check that the exclusions are equal, the identifiers are equal (considering two nils to be equal), and the
     53            content if necessary.
     54        (-[_WKTextManipulationToken description]):
     55        (-[_WKTextManipulationToken debugDescription]):
     56        (-[_WKTextManipulationToken _descriptionPreservingPrivacy:]):
     57            If we're preserving privacy, log the content length rather than the content string itself.
     58
    1592019-12-02  Wenson Hsieh  <wenson_hsieh@apple.com>
    260
  • trunk/Source/WebKit/UIProcess/API/Cocoa/_WKTextManipulationItem.h

    r251574 r253009  
    3030@class _WKTextManipulationToken;
    3131
     32NS_ASSUME_NONNULL_BEGIN
     33
    3234WK_CLASS_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA))
    3335@interface _WKTextManipulationItem : NSObject
    3436
    3537- (instancetype)init NS_UNAVAILABLE;
    36 - (instancetype)initWithIdentifier:(NSString *)identifier tokens:(NSArray<_WKTextManipulationToken *> *)tokens;
     38- (instancetype)initWithIdentifier:(nullable NSString *)identifier tokens:(NSArray<_WKTextManipulationToken *> *)tokens;
    3739
    38 @property (nonatomic, readonly, copy) NSString *identifier;
     40@property (nonatomic, readonly, nullable, copy) NSString *identifier;
    3941@property (nonatomic, readonly, copy) NSArray<_WKTextManipulationToken *> *tokens;
    4042
     43- (BOOL)isEqualToTextManipulationItem:(nullable _WKTextManipulationItem *)otherItem includingContentEquality:(BOOL)includingContentEquality;
     44@property (nonatomic, readonly, copy) NSString *debugDescription;
     45
    4146@end
     47
     48NS_ASSUME_NONNULL_END
  • trunk/Source/WebKit/UIProcess/API/Cocoa/_WKTextManipulationItem.mm

    r251574 r253009  
    2727#import "_WKTextManipulationItem.h"
    2828
     29#import "_WKTextManipulationToken.h"
    2930#import <wtf/RetainPtr.h>
    3031
     
    5455}
    5556
     57- (BOOL)isEqual:(id)object
     58{
     59    if (self == object)
     60        return YES;
     61
     62    if (![object isKindOfClass:[self class]])
     63        return NO;
     64
     65    return [self isEqualToTextManipulationItem:object includingContentEquality:YES];
     66}
     67
     68- (BOOL)isEqualToTextManipulationItem:(_WKTextManipulationItem *)otherItem includingContentEquality:(BOOL)includingContentEquality
     69{
     70    if (!otherItem)
     71        return NO;
     72
     73    if (!(self.identifier == otherItem.identifier || [self.identifier isEqualToString:otherItem.identifier]) || self.tokens.count != otherItem.tokens.count)
     74        return NO;
     75
     76    __block BOOL tokensAreEqual = YES;
     77    NSUInteger count = std::min(self.tokens.count, otherItem.tokens.count);
     78    [self.tokens enumerateObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, count)] options:0 usingBlock:^(_WKTextManipulationToken *token, NSUInteger index, BOOL* stop) {
     79        _WKTextManipulationToken *otherToken = otherItem.tokens[index];
     80        if (![token isEqualToTextManipulationToken:otherToken includingContentEquality:includingContentEquality]) {
     81            tokensAreEqual = NO;
     82            *stop = YES;
     83        }
     84    }];
     85
     86    return tokensAreEqual;
     87}
     88
     89- (NSString *)description
     90{
     91    return [self _descriptionPreservingPrivacy:YES];
     92}
     93
     94- (NSString *)debugDescription
     95{
     96    return [self _descriptionPreservingPrivacy:NO];
     97}
     98
     99- (NSString *)_descriptionPreservingPrivacy:(BOOL)preservePrivacy
     100{
     101    NSMutableArray<NSString *> *recursiveDescriptions = [NSMutableArray array];
     102    [self.tokens enumerateObjectsUsingBlock:^(_WKTextManipulationToken *token, NSUInteger index, BOOL* stop) {
     103        NSString *description = preservePrivacy ? token.description : token.debugDescription;
     104        [recursiveDescriptions addObject:description];
     105    }];
     106    NSString *tokenDescription = [NSString stringWithFormat:@"[\n\t%@\n]", [recursiveDescriptions componentsJoinedByString:@",\n\t"]];
     107    NSString *description = [NSString stringWithFormat:@"<%@: %p; identifier = %@ tokens = %@>", self.class, self, self.identifier, tokenDescription];
     108    return description;
     109}
     110
    56111@end
  • trunk/Source/WebKit/UIProcess/API/Cocoa/_WKTextManipulationToken.h

    r251600 r253009  
    2828#import <Foundation/Foundation.h>
    2929
     30NS_ASSUME_NONNULL_BEGIN
     31
    3032WK_CLASS_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA))
    3133@interface _WKTextManipulationToken : NSObject
    3234
    33 @property (nonatomic, copy) NSString *identifier;
    34 @property (nonatomic, copy) NSString *content;
     35@property (nonatomic, nullable, copy) NSString *identifier;
     36@property (nonatomic, nullable, copy) NSString *content;
    3537@property (nonatomic, getter=isExcluded) BOOL excluded;
    3638
     39- (BOOL)isEqualToTextManipulationToken:(nullable _WKTextManipulationToken *)otherToken includingContentEquality:(BOOL)includingContentEquality;
     40@property (nonatomic, copy, readonly) NSString *debugDescription;
     41
    3742@end
     43
     44NS_ASSUME_NONNULL_END
  • trunk/Source/WebKit/UIProcess/API/Cocoa/_WKTextManipulationToken.mm

    r251600 r253009  
    2828
    2929@implementation _WKTextManipulationToken
     30
     31static BOOL isEqualOrBothNil(id a, id b)
     32{
     33    if (a == b)
     34        return YES;
     35
     36    return [a isEqual:b];
     37}
     38
     39- (BOOL)isEqual:(id)object
     40{
     41    if (self == object)
     42        return YES;
     43
     44    if (![object isKindOfClass:[self class]])
     45        return NO;
     46
     47    return [self isEqualToTextManipulationToken:object includingContentEquality:YES];
     48}
     49
     50- (BOOL)isEqualToTextManipulationToken:(_WKTextManipulationToken *)otherToken includingContentEquality:(BOOL)includingContentEquality
     51{
     52    if (!otherToken)
     53        return NO;
     54
     55    BOOL equalIdentifiers = isEqualOrBothNil(self.identifier, otherToken.identifier);
     56    BOOL equalExclusion = self.isExcluded == otherToken.isExcluded;
     57    BOOL equalContent = !includingContentEquality || isEqualOrBothNil(self.content, otherToken.content);
     58
     59    return equalIdentifiers && equalExclusion && equalContent;
     60}
     61
     62- (NSString *)description
     63{
     64    return [self _descriptionPreservingPrivacy:YES];
     65}
     66
     67- (NSString *)debugDescription
     68{
     69    return [self _descriptionPreservingPrivacy:NO];
     70}
     71
     72- (NSString *)_descriptionPreservingPrivacy:(BOOL)preservePrivacy
     73{
     74    NSMutableString *description = [NSMutableString stringWithFormat:@"<%@: %p; identifier = %@; isExcluded = %i", self.class, self, self.identifier, self.isExcluded];
     75    if (preservePrivacy)
     76        [description appendFormat:@"; content length = %lu", (unsigned long)self.content.length];
     77    else
     78        [description appendFormat:@"; content = %@", self.content];
     79
     80    [description appendString:@">"];
     81
     82    return [[description copy] autorelease];
     83}
     84
    3085@end
  • trunk/Tools/ChangeLog

    r252991 r253009  
     12019-12-02  Louie Livon-Bemel  <llivonbemel@apple.com>
     2
     3        Add helper methods for description and equality to text manipulation SPI
     4        https://bugs.webkit.org/show_bug.cgi?id=204758
     5        <rdar://problem/57438200>
     6
     7        Reviewed by Wenson Hsieh.
     8
     9        Add tests for the new methods. Most are equality tests for various situations, and are moved over from the
     10        Safari unit tests I had for the category methods that had the same purpose.
     11
     12        * TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm:
     13        (TestWebKitAPI::TEST):
     14            - Add test to make sure the content isn't included in the regular -description, but the identifier is. And
     15              That -debugDescription does include the contents.
     16            - Add many tests equality for various situations, testing both with and without content equality.
     17        (TestWebKitAPI::createTextManipulationToken):
     18            Add a helper for creating a token in one line.
     19
    1202019-12-02  Daniel Bates  <dabates@apple.com>
    221
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm

    r251600 r253009  
    425425}
    426426
     427// MARK: - _WKTextManipulationToken Tests
     428
     429TEST(TextManipulation, TextManipulationTokenDebugDescription)
     430{
     431    auto token = adoptNS([[_WKTextManipulationToken alloc] init]);
     432    [token setIdentifier:@"foo_is_the_identifier"];
     433    [token setContent:@"bar_is_the_content"];
     434
     435    NSString *description = [token description];
     436    EXPECT_TRUE([description containsString:@"foo_is_the_identifier"]);
     437    EXPECT_FALSE([description containsString:@"bar_is_the_content"]);
     438
     439    NSString *debugDescription = [token debugDescription];
     440    EXPECT_TRUE([debugDescription containsString:@"foo_is_the_identifier"]);
     441    EXPECT_TRUE([debugDescription containsString:@"bar_is_the_content"]);
     442}
     443
     444TEST(TextManipulation, TextManipulationTokenNotEqualToNil)
     445{
     446    auto tokenA = adoptNS([[_WKTextManipulationToken alloc] init]);
     447    [tokenA setIdentifier:@"A"];
     448    [tokenA setContent:@"A"];
     449
     450    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:nil includingContentEquality:YES]);
     451    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:nil includingContentEquality:NO]);
     452
     453    [tokenA setIdentifier:nil];
     454    [tokenA setContent:nil];
     455    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:nil includingContentEquality:YES]);
     456    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:nil includingContentEquality:NO]);
     457}
     458
     459TEST(TextManipulation, TextManipulationTokenEqualityWithEqualIdentifiers)
     460{
     461    auto token1 = adoptNS([[_WKTextManipulationToken alloc] init]);
     462    [token1 setIdentifier:@"A"];
     463    auto token2 = adoptNS([[_WKTextManipulationToken alloc] init]);
     464    [token2 setIdentifier:@"A"];
     465
     466    EXPECT_TRUE([token1 isEqualToTextManipulationToken:token2.get() includingContentEquality:YES]);
     467    EXPECT_TRUE([token1 isEqualToTextManipulationToken:token2.get() includingContentEquality:NO]);
     468
     469    // Same identifiers, different content.
     470    [token1 setContent:@"1"];
     471    [token2 setContent:@"2"];
     472    EXPECT_FALSE([token1 isEqualToTextManipulationToken:token2.get() includingContentEquality:YES]);
     473    EXPECT_TRUE([token1 isEqualToTextManipulationToken:token2.get() includingContentEquality:NO]);
     474
     475    // Same identifiers, different exclusion.
     476    [token1 setExcluded:NO];
     477    [token2 setExcluded:YES];
     478    [token1 setContent:nil];
     479    [token2 setContent:nil];
     480    EXPECT_FALSE([token1 isEqualToTextManipulationToken:token2.get() includingContentEquality:YES]);
     481    EXPECT_FALSE([token1 isEqualToTextManipulationToken:token2.get() includingContentEquality:NO]);
     482
     483    // Same identifiers, different exclusion and different content.
     484    [token1 setContent:@"1"];
     485    [token2 setContent:@"2"];
     486    EXPECT_FALSE([token1 isEqualToTextManipulationToken:token2.get() includingContentEquality:YES]);
     487    EXPECT_FALSE([token1 isEqualToTextManipulationToken:token2.get() includingContentEquality:NO]);
     488}
     489
     490TEST(TextManipulation, TextManipulationTokenEqualityWithDifferentIdentifiers)
     491{
     492    auto tokenA = adoptNS([[_WKTextManipulationToken alloc] init]);
     493    [tokenA setIdentifier:@"A"];
     494    auto tokenB = adoptNS([[_WKTextManipulationToken alloc] init]);
     495    [tokenB setIdentifier:@"B"];
     496
     497    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:YES]);
     498    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:NO]);
     499
     500    // Different identifiers, same content.
     501    [tokenA setContent:@"content"];
     502    [tokenB setContent:@"content"];
     503    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:YES]);
     504    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:NO]);
     505
     506    // Different identifiers, same exclusion.
     507    [tokenA setContent:nil];
     508    [tokenB setContent:nil];
     509    [tokenA setExcluded:YES];
     510    [tokenB setExcluded:YES];
     511    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:YES]);
     512    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:NO]);
     513
     514    // Different identifiers, same content and same exclusion.
     515    [tokenA setContent:@"content"];
     516    [tokenB setContent:@"content"];
     517    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:YES]);
     518    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:NO]);
     519}
     520
     521TEST(TextManipulation, TextManipulationTokenEqualityWithNilIdentifiers)
     522{
     523    auto tokenA = adoptNS([[_WKTextManipulationToken alloc] init]);
     524    EXPECT_NULL([tokenA identifier]);
     525    auto tokenB = adoptNS([[_WKTextManipulationToken alloc] init]);
     526    [tokenB setIdentifier:@"B"];
     527    auto tokenC = adoptNS([[_WKTextManipulationToken alloc] init]);
     528    EXPECT_NULL([tokenC identifier]);
     529
     530    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:YES]);
     531    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:NO]);
     532    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenC.get() includingContentEquality:YES]);
     533    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenC.get() includingContentEquality:NO]);
     534
     535    // Equal content.
     536    [tokenA setContent:@"content"];
     537    [tokenB setContent:@"content"];
     538    [tokenC setContent:@"content"];
     539    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:YES]);
     540    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:NO]);
     541    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenC.get() includingContentEquality:YES]);
     542    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenC.get() includingContentEquality:NO]);
     543
     544    // Different content.
     545    [tokenA setContent:@"contentA"];
     546    [tokenB setContent:@"contentB"];
     547    [tokenC setContent:@"contentC"];
     548    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:YES]);
     549    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:NO]);
     550    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenC.get() includingContentEquality:YES]);
     551    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenC.get() includingContentEquality:NO]);
     552}
     553
     554TEST(TextManipulation, TextManipulationTokenEqualityWithEmptyIdentifiers)
     555{
     556    auto tokenA = adoptNS([[_WKTextManipulationToken alloc] init]);
     557    [tokenA setIdentifier:@""];
     558    auto tokenB = adoptNS([[_WKTextManipulationToken alloc] init]);
     559    [tokenB setIdentifier:@"B"];
     560    auto tokenC = adoptNS([[_WKTextManipulationToken alloc] init]);
     561    [tokenC setIdentifier:@""];
     562
     563    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:YES]);
     564    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:NO]);
     565    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenC.get() includingContentEquality:YES]);
     566    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenC.get() includingContentEquality:NO]);
     567
     568    // Equal content.
     569    [tokenA setContent:@"content"];
     570    [tokenB setContent:@"content"];
     571    [tokenC setContent:@"content"];
     572    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:YES]);
     573    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:NO]);
     574    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenC.get() includingContentEquality:YES]);
     575    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenC.get() includingContentEquality:NO]);
     576
     577    // Different content.
     578    [tokenA setContent:@"contentA"];
     579    [tokenB setContent:@"contentB"];
     580    [tokenC setContent:@"contentC"];
     581    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:YES]);
     582    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:NO]);
     583    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenC.get() includingContentEquality:YES]);
     584    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenC.get() includingContentEquality:NO]);
     585}
     586
     587TEST(TextManipulation, TextManipulationTokenWithNilContent)
     588{
     589    auto tokenA = adoptNS([[_WKTextManipulationToken alloc] init]);
     590    [tokenA setIdentifier:@"A"];
     591    auto tokenB = adoptNS([[_WKTextManipulationToken alloc] init]);
     592    [tokenB setIdentifier:@"A"];
     593
     594    EXPECT_NULL([tokenA content]);
     595    EXPECT_NULL([tokenB content]);
     596    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:YES]);
     597    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:NO]);
     598
     599    [tokenB setContent:@""];
     600    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:YES]);
     601    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:NO]);
     602
     603    [tokenB setContent:@"B"];
     604    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:YES]);
     605    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:NO]);
     606}
     607
     608TEST(TextManipulation, TextManipulationTokenWithEmptyContent)
     609{
     610    auto tokenA = adoptNS([[_WKTextManipulationToken alloc] init]);
     611    [tokenA setIdentifier:@"A"];
     612    [tokenA setContent:@""];
     613    auto tokenB = adoptNS([[_WKTextManipulationToken alloc] init]);
     614    [tokenB setIdentifier:@"A"];
     615    [tokenB setContent:@""];
     616
     617    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:YES]);
     618    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:NO]);
     619
     620    [tokenB setContent:nil];
     621    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:YES]);
     622    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:NO]);
     623
     624    [tokenB setContent:@"B"];
     625    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:YES]);
     626    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:NO]);
     627}
     628
     629TEST(TextManipulation, TextManipulationTokenWithIdenticalContent)
     630{
     631    auto tokenA = adoptNS([[_WKTextManipulationToken alloc] init]);
     632    [tokenA setIdentifier:@"A"];
     633    [tokenA setContent:@"content"];
     634    auto tokenB = adoptNS([[_WKTextManipulationToken alloc] init]);
     635    [tokenB setIdentifier:@"A"];
     636    [tokenB setContent:@"content"];
     637
     638    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:YES]);
     639    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:NO]);
     640}
     641
     642TEST(TextManipulation, TextManipulationTokenWithPointerEqualContent)
     643{
     644    auto tokenA = adoptNS([[_WKTextManipulationToken alloc] init]);
     645    [tokenA setIdentifier:@"A"];
     646    auto tokenB = adoptNS([[_WKTextManipulationToken alloc] init]);
     647    [tokenB setIdentifier:@"A"];
     648
     649    NSString *contentString = @"content";
     650    [tokenA setContent:contentString];
     651    [tokenB setContent:contentString];
     652
     653    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:YES]);
     654    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:NO]);
     655}
     656
     657TEST(TextManipulation, TextManipulationTokenWithTrailingSpace)
     658{
     659    auto tokenA = adoptNS([[_WKTextManipulationToken alloc] init]);
     660    [tokenA setIdentifier:@"A"];
     661    [tokenA setContent:@"content"];
     662    auto tokenB = adoptNS([[_WKTextManipulationToken alloc] init]);
     663    [tokenB setIdentifier:@"A"];
     664    [tokenB setContent:@"content "];
     665
     666    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:YES]);
     667    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:NO]);
     668}
     669
     670TEST(TextManipulation, TextManipulationTokenEqualToSelf)
     671{
     672    auto token = adoptNS([[_WKTextManipulationToken alloc] init]);
     673    [token setIdentifier:@"A"];
     674    [token setContent:@"content"];
     675
     676    EXPECT_TRUE([token isEqualToTextManipulationToken:token.get() includingContentEquality:YES]);
     677    EXPECT_TRUE([token isEqualToTextManipulationToken:token.get() includingContentEquality:NO]);
     678    EXPECT_TRUE([token isEqual:token.get()]);
     679}
     680
     681TEST(TextManipulation, TextManipulationTokenNSObjectEqualityWithOtherToken)
     682{
     683    auto tokenA = adoptNS([[_WKTextManipulationToken alloc] init]);
     684    [tokenA setIdentifier:@"A"];
     685    [tokenA setContent:@"content"];
     686    auto tokenB = adoptNS([[_WKTextManipulationToken alloc] init]);
     687    [tokenB setIdentifier:@"A"];
     688    [tokenB setContent:@"content"];
     689    auto tokenC = adoptNS([[_WKTextManipulationToken alloc] init]);
     690    [tokenC setIdentifier:@"A"];
     691    [tokenC setContent:@"content "];
     692
     693    EXPECT_TRUE([tokenA isEqualToTextManipulationToken:tokenB.get() includingContentEquality:YES]);
     694    EXPECT_TRUE([tokenA isEqual:tokenB.get()]);
     695
     696    EXPECT_FALSE([tokenA isEqualToTextManipulationToken:tokenC.get() includingContentEquality:YES]);
     697    EXPECT_FALSE([tokenA isEqual:tokenC.get()]);
     698}
     699
     700TEST(TextManipulation, TextManipulationTokenNSObjectEqualityWithNonToken)
     701{
     702    auto token = adoptNS([[_WKTextManipulationToken alloc] init]);
     703    [token setIdentifier:@"A"];
     704    [token setContent:@"content"];
     705    NSString *string = @"content";
     706
     707    EXPECT_FALSE([token isEqual:string]);
     708    EXPECT_FALSE([token isEqual:nil]);
     709}
     710
     711// MARK: - _WKTextManipulationItem Tests
     712
     713static RetainPtr<_WKTextManipulationToken> createTextManipulationToken(NSString *identifier, BOOL excluded, NSString *content)
     714{
     715    auto token = adoptNS([[_WKTextManipulationToken alloc] init]);
     716    [token setIdentifier:identifier];
     717    [token setExcluded:excluded];
     718    [token setContent:content];
     719    return token;
     720}
     721
     722TEST(TextManipulation, TextManipulationItemDebugDescription)
     723{
     724    auto tokenA = createTextManipulationToken(@"public_identifier_A", NO, @"private_content_A");
     725    auto tokenB = createTextManipulationToken(@"public_identifier_B", NO, @"private_content_B");
     726    auto item = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"public_item_identifier" tokens:@[ tokenA.get(), tokenB.get() ]]);
     727
     728    NSString *debugDescription = [item debugDescription];
     729    EXPECT_TRUE([debugDescription containsString:@"public_identifier_A"]);
     730    EXPECT_TRUE([debugDescription containsString:@"public_identifier_B"]);
     731    EXPECT_TRUE([debugDescription containsString:@"private_content_A"]);
     732    EXPECT_TRUE([debugDescription containsString:@"private_content_B"]);
     733    EXPECT_TRUE([debugDescription containsString:@"public_item_identifier"]);
     734
     735    NSString *description = [item description];
     736    EXPECT_TRUE([description containsString:@"public_identifier_A"]);
     737    EXPECT_TRUE([description containsString:@"public_identifier_B"]);
     738    EXPECT_FALSE([description containsString:@"private_content_A"]);
     739    EXPECT_FALSE([description containsString:@"private_content_B"]);
     740    EXPECT_TRUE([description containsString:@"public_item_identifier"]);
     741}
     742
     743TEST(TextManipulation, TextManipulationItemEqualityToNilItem)
     744{
     745    auto item = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:@[ ]]);
     746
     747    EXPECT_FALSE([item isEqualToTextManipulationItem:nil includingContentEquality:YES]);
     748    EXPECT_FALSE([item isEqualToTextManipulationItem:nil includingContentEquality:NO]);
     749}
     750
     751TEST(TextManipulation, TextManipulationItemEqualityToSelf)
     752{
     753    auto token = createTextManipulationToken(@"A", NO, @"token");
     754    auto item = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"B" tokens:@[ token.get() ]]);
     755
     756    EXPECT_TRUE([item isEqualToTextManipulationItem:item.get() includingContentEquality:YES]);
     757    EXPECT_TRUE([item isEqualToTextManipulationItem:item.get() includingContentEquality:NO]);
     758    EXPECT_TRUE([item isEqual:item.get()]);
     759}
     760
     761TEST(TextManipulation, TextManipulationItemBasicEquality)
     762{
     763    auto token1 = createTextManipulationToken(@"1", NO, @"token1");
     764    auto token2 = createTextManipulationToken(@"1", NO, @"token1");
     765    auto itemA = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:@[ token1.get() ]]);
     766    auto itemB = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:@[ token2.get() ]]);
     767
     768    EXPECT_TRUE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:YES]);
     769    EXPECT_TRUE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:NO]);
     770}
     771
     772TEST(TextManipulation, TextManipulationItemBasicEqualityWithMultipleTokens)
     773{
     774    auto tokenA1 = createTextManipulationToken(@"1", NO, @"token1");
     775    auto tokenA2 = createTextManipulationToken(@"2", NO, @"token2");
     776    auto tokenB1 = createTextManipulationToken(@"1", NO, @"token1");
     777    auto tokenB2 = createTextManipulationToken(@"2", NO, @"token2");
     778
     779    auto itemA = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:@[ tokenA1.get(), tokenA2.get() ]]);
     780    auto itemB = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:@[ tokenB1.get(), tokenB2.get() ]]);
     781
     782    EXPECT_TRUE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:YES]);
     783    EXPECT_TRUE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:NO]);
     784}
     785
     786TEST(TextManipulation, TextManipulationItemEqualitySimilarTokensWithDifferentContent)
     787{
     788    auto token1 = createTextManipulationToken(@"1", NO, @"token1");
     789    auto token2 = createTextManipulationToken(@"1", NO, @"token2");
     790    auto itemA = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:@[ token1.get() ]]);
     791    auto itemB = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:@[ token2.get() ]]);
     792
     793    EXPECT_FALSE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:YES]);
     794    EXPECT_TRUE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:NO]);
     795}
     796
     797TEST(TextManipulation, TextManipulationItemEqualityWithOutOfOrderTokens)
     798{
     799    auto tokenA1 = createTextManipulationToken(@"1", NO, @"token1");
     800    auto tokenA2 = createTextManipulationToken(@"2", NO, @"token2");
     801    auto tokenB1 = createTextManipulationToken(@"1", NO, @"token1");
     802    auto tokenB2 = createTextManipulationToken(@"2", NO, @"token2");
     803
     804    auto itemA = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:@[ tokenA1.get(), tokenA2.get() ]]);
     805    auto itemB = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:@[ tokenB2.get(), tokenB1.get() ]]);
     806
     807    EXPECT_FALSE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:YES]);
     808    EXPECT_FALSE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:NO]);
     809}
     810
     811TEST(TextManipulation, TextManipulationItemEqualityWithPointerEqualTokens)
     812{
     813    auto token1 = createTextManipulationToken(@"1", NO, @"token1");
     814    auto token2 = createTextManipulationToken(@"2", NO, @"token2");
     815
     816    auto itemA = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:@[ token1.get(), token2.get() ]]);
     817    auto itemB = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:@[ token1.get(), token2.get() ]]);
     818
     819    EXPECT_TRUE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:YES]);
     820    EXPECT_TRUE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:NO]);
     821}
     822
     823TEST(TextManipulation, TextManipulationItemEqualityWithPointerEqualTokenArrays)
     824{
     825    auto token1 = createTextManipulationToken(@"1", NO, @"token1");
     826    auto token2 = createTextManipulationToken(@"2", NO, @"token2");
     827    NSArray<_WKTextManipulationToken *> *tokens = @[ token1.get(), token2.get() ];
     828
     829    auto itemA = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:tokens]);
     830    auto itemB = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:tokens]);
     831
     832    EXPECT_TRUE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:YES]);
     833    EXPECT_TRUE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:NO]);
     834}
     835
     836TEST(TextManipulation, TextManipulationItemEqualityWithMismatchedTokenCounts)
     837{
     838    auto tokenA1 = createTextManipulationToken(@"1", NO, @"token1");
     839    auto tokenA2 = createTextManipulationToken(@"2", NO, @"token2");
     840    auto tokenA3 = createTextManipulationToken(@"3", NO, @"token3");
     841    auto tokenB1 = createTextManipulationToken(@"1", NO, @"token1");
     842    auto tokenB2 = createTextManipulationToken(@"2", NO, @"token2");
     843
     844    auto itemA = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:@[ tokenA1.get(), tokenA2.get(), tokenA3.get() ]]);
     845    auto itemB = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:@[ tokenB1.get(), tokenB2.get() ]]);
     846
     847    EXPECT_FALSE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:YES]);
     848    EXPECT_FALSE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:NO]);
     849
     850    EXPECT_FALSE([itemB isEqualToTextManipulationItem:itemA.get() includingContentEquality:YES]);
     851    EXPECT_FALSE([itemB isEqualToTextManipulationItem:itemA.get() includingContentEquality:NO]);
     852}
     853
     854TEST(TextManipulation, TextManipulationItemEqualityWithDifferentTokenIdentifiers)
     855{
     856    auto tokenA = createTextManipulationToken(@"A", NO, @"token");
     857    auto tokenB = createTextManipulationToken(@"B", NO, @"token");
     858    auto itemA = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:@[ tokenA.get() ]]);
     859    auto itemB = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:@[ tokenB.get() ]]);
     860
     861    EXPECT_FALSE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:YES]);
     862    EXPECT_FALSE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:NO]);
     863}
     864
     865TEST(TextManipulation, TextManipulationItemEqualityWithNilIdentifiers)
     866{
     867    auto token = createTextManipulationToken(@"A", NO, @"token");
     868    auto itemA = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:nil tokens:@[ token.get() ]]);
     869    auto itemB = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:nil tokens:@[ token.get() ]]);
     870
     871    EXPECT_TRUE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:YES]);
     872    EXPECT_TRUE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:NO]);
     873}
     874
     875TEST(TextManipulation, TextManipulationItemEqualityWithDifferentTokenExclusions)
     876{
     877    auto tokenA = createTextManipulationToken(@"1", NO, @"token");
     878    auto tokenB = createTextManipulationToken(@"1", YES, @"token");
     879    auto itemA = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:@[ tokenA.get() ]]);
     880    auto itemB = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:@[ tokenB.get() ]]);
     881
     882    EXPECT_FALSE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:YES]);
     883    EXPECT_FALSE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:NO]);
     884}
     885
     886TEST(TextManipulation, TextManipulationItemNSObjectEqualityWithOtherItem)
     887{
     888    auto tokenA1 = createTextManipulationToken(@"1", NO, @"token1");
     889    auto tokenA2 = createTextManipulationToken(@"2", NO, @"token2");
     890    auto tokenB1 = createTextManipulationToken(@"1", NO, @"token1");
     891    auto tokenB2 = createTextManipulationToken(@"2", NO, @"token2");
     892
     893    auto itemA = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:@[ tokenA1.get(), tokenA2.get() ]]);
     894    auto itemB = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:@[ tokenB1.get(), tokenB2.get() ]]);
     895
     896    EXPECT_TRUE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:YES]);
     897    EXPECT_TRUE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:NO]);
     898    EXPECT_TRUE([itemA isEqual:itemB.get()]);
     899
     900    [tokenB2 setContent:@"something else"];
     901
     902    EXPECT_FALSE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:YES]);
     903    EXPECT_TRUE([itemA isEqualToTextManipulationItem:itemB.get() includingContentEquality:NO]);
     904    EXPECT_FALSE([itemA isEqual:itemB.get()]);
     905}
     906
     907TEST(TextManipulation, TextManipulationItemNSObjectEqualityWithNonToken)
     908{
     909    auto token = createTextManipulationToken(@"1", NO, @"token1");
     910    auto item = adoptNS([[_WKTextManipulationItem alloc] initWithIdentifier:@"A" tokens:@[ token.get() ]]);
     911    NSString *string = @"content";
     912
     913    EXPECT_FALSE([token isEqual:string]);
     914    EXPECT_FALSE([token isEqual:nil]);
     915}
     916
    427917} // namespace TestWebKitAPI
    428918
Note: See TracChangeset for help on using the changeset viewer.