FNextPushIdTest.m 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. * Copyright 2021 Google LLC
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import <XCTest/XCTest.h>
  17. #import "FirebaseDatabase/Sources/Utilities/FNextPushId.h"
  18. #import "FirebaseDatabase/Sources/Utilities/FUtilities.h"
  19. #import "FirebaseDatabase/Sources/Utilities/FValidation.h"
  20. @interface FValidation (Test)
  21. + (BOOL)isValidKey:(NSString *)key;
  22. @end
  23. @interface FNextPushIdTest : XCTestCase
  24. @end
  25. @implementation FNextPushIdTest
  26. static NSString *MIN_PUSH_CHAR = @" ";
  27. static NSString *MAX_PUSH_CHAR = @"\uFFFF";
  28. static NSInteger MAX_KEY_LEN = 786;
  29. - (void)testSuccessorSpecialValues {
  30. NSString *maxIntegerKeySuccessor =
  31. [FNextPushId from:@"test" successor:[NSString stringWithFormat:@"%d", INTEGER_32_MAX]];
  32. XCTAssertEqualObjects(maxIntegerKeySuccessor, MIN_PUSH_CHAR,
  33. @"successor(INTEGER_32_MAX) == MIN_PUSH_CHAR");
  34. NSString *maxKey = [@"" stringByPaddingToLength:MAX_KEY_LEN
  35. withString:MAX_PUSH_CHAR
  36. startingAtIndex:0];
  37. NSString *maxKeySuccessor = [FNextPushId from:@"test" successor:maxKey];
  38. XCTAssertEqualObjects(maxKeySuccessor, [FUtilities maxName],
  39. @"successor(MAX_PUSH_CHAR repeated MAX_KEY_LEN times) == MAX_NAME");
  40. }
  41. - (void)testSuccessorBasic {
  42. NSString *actual = [FNextPushId from:@"test" successor:@"abc"];
  43. NSString *expected = [NSString stringWithFormat:@"abc%@", MIN_PUSH_CHAR];
  44. XCTAssertEqualObjects(expected, actual, @"successor(abc) == abc + MIN_PUSH_CHAR");
  45. actual = [FNextPushId from:@"test"
  46. successor:[@"abc" stringByPaddingToLength:MAX_KEY_LEN
  47. withString:MAX_PUSH_CHAR
  48. startingAtIndex:0]];
  49. expected = @"abd";
  50. XCTAssertEqualObjects(expected, actual,
  51. @"successor(abc + MAX_PUSH_CHAR repeated MAX_KEY_LEN - 3 times) == abd");
  52. actual = [FNextPushId from:@"test" successor:[NSString stringWithFormat:@"abc%@", MIN_PUSH_CHAR]];
  53. expected = [NSString stringWithFormat:@"abc%@%@", MIN_PUSH_CHAR, MIN_PUSH_CHAR];
  54. XCTAssertEqualObjects(expected, actual,
  55. @"successor(abc + MIN_PUSH_CHAR) == abc + MIN_PUSH_CHAR + MIN_PUSH_CHAR");
  56. }
  57. - (void)testPredecessorSpecialValues {
  58. NSString *actual = [FNextPushId from:@"test" predecessor:MIN_PUSH_CHAR];
  59. NSString *expected = [NSString stringWithFormat:@"%d", INTEGER_32_MAX];
  60. XCTAssertEqualObjects(expected, actual, @"predecessor(MIN_PUSH_CHAR) == INTEGER_32_MAX");
  61. actual = [FNextPushId from:@"test"
  62. predecessor:[NSString stringWithFormat:@"%ld", INTEGER_32_MIN]];
  63. expected = [FUtilities minName];
  64. XCTAssertEqualObjects(expected, actual, @"predecessor(INTEGER_32_MIN) == MIN_NAME");
  65. }
  66. - (void)testPredecessorBasic {
  67. NSString *actual = [FNextPushId from:@"test" predecessor:@"abc"];
  68. NSString *expected = [@"abb" stringByPaddingToLength:MAX_KEY_LEN
  69. withString:MAX_PUSH_CHAR
  70. startingAtIndex:0];
  71. XCTAssertEqualObjects(
  72. expected, actual,
  73. @"predecessor(abc) = abb + { MAX_PUSH_CHAR repeated MAX_KEY_LEN - 3 times }");
  74. actual = [FNextPushId from:@"test"
  75. predecessor:[NSString stringWithFormat:@"abc%@", MIN_PUSH_CHAR]];
  76. expected = @"abc";
  77. XCTAssertEqualObjects(expected, actual, @"predecessor(abc + MIN_PUSH_CHAR) == abc");
  78. }
  79. - (void)testPredecessorUnicode {
  80. NSString *actual = [FNextPushId from:@"test" predecessor:@"\uE000"];
  81. NSString *expected = [@"\U0010FFFF" stringByPaddingToLength:MAX_KEY_LEN
  82. withString:MAX_PUSH_CHAR
  83. startingAtIndex:0];
  84. XCTAssertEqualObjects(
  85. expected, actual,
  86. @"predecessor(uE000) = U0010FFFF + { MAX_PUSH_CHAR repeated MAX_KEY_LEN - 2 times }");
  87. actual = [FNextPushId from:@"test" predecessor:@"\U00010000"];
  88. expected = [@"\uD7FF" stringByPaddingToLength:MAX_KEY_LEN
  89. withString:MAX_PUSH_CHAR
  90. startingAtIndex:0];
  91. XCTAssertEqualObjects(
  92. expected, actual,
  93. @"predecessor(U00010000) == uD7FF + { MAX_PUSH_CHAR repeated MAX_KEY_LEN - 2 times }");
  94. actual = [FNextPushId from:@"test" predecessor:[[NSString alloc] initWithFormat:@"%C", 0x80]];
  95. expected = [[[NSString alloc] initWithFormat:@"%C", 0x7E] stringByPaddingToLength:MAX_KEY_LEN
  96. withString:MAX_PUSH_CHAR
  97. startingAtIndex:0];
  98. XCTAssertEqualObjects(expected, actual, @"predecessor(u0080) == u007e");
  99. }
  100. - (void)testPredecessorOrdering {
  101. // Start _after_ space because otherwise we have to consider integer interpretation.
  102. for (unichar i = 0x20; i < 0xD800; i++) {
  103. NSString *key = [[NSString alloc] initWithFormat:@"%C", i];
  104. if (![FValidation isValidKey:key]) {
  105. continue;
  106. }
  107. NSString *predecessor = [FNextPushId from:@"test" predecessor:key];
  108. NSComparisonResult r = [FUtilities compareKey:key toKey:predecessor];
  109. XCTAssertEqual(r, NSOrderedDescending);
  110. }
  111. for (NSInteger i = 0xE000; i <= 0xFFFF; i++) {
  112. NSString *key = [[NSString alloc] initWithFormat:@"%C", (unichar)i];
  113. NSString *predecessor = [FNextPushId from:@"test" predecessor:key];
  114. NSComparisonResult r = [FUtilities compareKey:key toKey:predecessor];
  115. XCTAssertEqual(r, NSOrderedDescending);
  116. }
  117. // Unicode code points starting at 0x10000 are exactly the ones that encode
  118. // as surrogate pairs in utf16
  119. for (UTF32Char i = 0x10000; i <= 0x10FFFF; i++) {
  120. UniChar c[2];
  121. CFStringGetSurrogatePairForLongCharacter(i, c);
  122. NSString *key = [[NSString alloc] initWithCharacters:c length:2];
  123. NSString *predecessor = [FNextPushId from:@"test" predecessor:key];
  124. NSComparisonResult r = [FUtilities compareKey:key toKey:predecessor];
  125. XCTAssertEqual(r, NSOrderedDescending);
  126. }
  127. }
  128. - (void)testSuccessorOrdering {
  129. for (unichar i = 0x20; i < 0xD800; i++) {
  130. NSString *key = [[NSString alloc] initWithFormat:@"%C", i];
  131. if (![FValidation isValidKey:key]) {
  132. continue;
  133. }
  134. NSString *successor = [FNextPushId from:@"test" successor:key];
  135. NSComparisonResult r = [FUtilities compareKey:key toKey:successor];
  136. XCTAssertEqual(r, NSOrderedAscending);
  137. }
  138. for (NSInteger i = 0xE000; i <= 0xFFFF; i++) {
  139. NSString *key = [[NSString alloc] initWithFormat:@"%C", (unichar)i];
  140. NSString *successor = [FNextPushId from:@"test" successor:key];
  141. NSComparisonResult r = [FUtilities compareKey:key toKey:successor];
  142. XCTAssertEqual(r, NSOrderedAscending);
  143. }
  144. // Unicode code points starting at 0x10000 are exactly the ones that encode
  145. // as surrogate pairs in utf16
  146. for (UTF32Char i = 0x10000; i <= 0x10FFFF; i++) {
  147. UniChar c[2];
  148. CFStringGetSurrogatePairForLongCharacter(i, c);
  149. NSString *key = [[NSString alloc] initWithCharacters:c length:2];
  150. NSString *successor = [FNextPushId from:@"test" successor:key];
  151. NSComparisonResult r = [FUtilities compareKey:key toKey:successor];
  152. XCTAssertEqual(r, NSOrderedAscending);
  153. }
  154. }
  155. @end