FSTPathTests.m 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * Copyright 2017 Google
  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 "Firestore/Example/Tests/Util/FSTHelpers.h"
  17. #import "Firestore/Source/Model/FSTPath.h"
  18. #import <XCTest/XCTest.h>
  19. NS_ASSUME_NONNULL_BEGIN
  20. @interface FSTFieldPathTests : XCTestCase
  21. @end
  22. @implementation FSTFieldPathTests
  23. - (void)testConstructor {
  24. FSTFieldPath *path = [FSTFieldPath pathWithSegments:@[ @"rooms", @"Eros", @"messages" ]];
  25. XCTAssertEqual(3, path.length);
  26. }
  27. - (void)testIndexing {
  28. FSTFieldPath *path = [FSTFieldPath pathWithSegments:@[ @"rooms", @"Eros", @"messages" ]];
  29. XCTAssertEqualObjects(@"rooms", path.firstSegment);
  30. XCTAssertEqualObjects(@"rooms", [path segmentAtIndex:0]);
  31. XCTAssertEqualObjects(@"rooms", path[0]);
  32. XCTAssertEqualObjects(@"Eros", [path segmentAtIndex:1]);
  33. XCTAssertEqualObjects(@"Eros", path[1]);
  34. XCTAssertEqualObjects(@"messages", [path segmentAtIndex:2]);
  35. XCTAssertEqualObjects(@"messages", path[2]);
  36. XCTAssertEqualObjects(@"messages", path.lastSegment);
  37. }
  38. - (void)testPathByRemovingFirstSegment {
  39. FSTFieldPath *path = [FSTFieldPath pathWithSegments:@[ @"rooms", @"Eros", @"messages" ]];
  40. FSTFieldPath *same = [FSTFieldPath pathWithSegments:@[ @"rooms", @"Eros", @"messages" ]];
  41. FSTFieldPath *second = [FSTFieldPath pathWithSegments:@[ @"Eros", @"messages" ]];
  42. FSTFieldPath *third = [FSTFieldPath pathWithSegments:@[ @"messages" ]];
  43. FSTFieldPath *empty = [FSTFieldPath pathWithSegments:@[]];
  44. XCTAssertEqualObjects(second, path.pathByRemovingFirstSegment);
  45. XCTAssertEqualObjects(third, path.pathByRemovingFirstSegment.pathByRemovingFirstSegment);
  46. XCTAssertEqualObjects(
  47. empty, path.pathByRemovingFirstSegment.pathByRemovingFirstSegment.pathByRemovingFirstSegment);
  48. // unmodified original
  49. XCTAssertEqualObjects(same, path);
  50. }
  51. - (void)testPathByRemovingLastSegment {
  52. FSTFieldPath *path = [FSTFieldPath pathWithSegments:@[ @"rooms", @"Eros", @"messages" ]];
  53. FSTFieldPath *same = [FSTFieldPath pathWithSegments:@[ @"rooms", @"Eros", @"messages" ]];
  54. FSTFieldPath *second = [FSTFieldPath pathWithSegments:@[ @"rooms", @"Eros" ]];
  55. FSTFieldPath *third = [FSTFieldPath pathWithSegments:@[ @"rooms" ]];
  56. FSTFieldPath *empty = [FSTFieldPath pathWithSegments:@[]];
  57. XCTAssertEqualObjects(second, path.pathByRemovingLastSegment);
  58. XCTAssertEqualObjects(third, path.pathByRemovingLastSegment.pathByRemovingLastSegment);
  59. XCTAssertEqualObjects(
  60. empty, path.pathByRemovingLastSegment.pathByRemovingLastSegment.pathByRemovingLastSegment);
  61. // unmodified original
  62. XCTAssertEqualObjects(same, path);
  63. }
  64. - (void)testPathByAppendingSegment {
  65. FSTFieldPath *path = [FSTFieldPath pathWithSegments:@[ @"rooms" ]];
  66. FSTFieldPath *rooms = [FSTFieldPath pathWithSegments:@[ @"rooms" ]];
  67. FSTFieldPath *roomsEros = [FSTFieldPath pathWithSegments:@[ @"rooms", @"eros" ]];
  68. FSTFieldPath *roomsEros1 = [FSTFieldPath pathWithSegments:@[ @"rooms", @"eros", @"1" ]];
  69. XCTAssertEqualObjects(roomsEros, [path pathByAppendingSegment:@"eros"]);
  70. XCTAssertEqualObjects(roomsEros1,
  71. [[path pathByAppendingSegment:@"eros"] pathByAppendingSegment:@"1"]);
  72. // unmodified original
  73. XCTAssertEqualObjects(rooms, path);
  74. FSTFieldPath *sub = [FSTTestFieldPath(@"rooms.eros.1") pathByRemovingFirstSegment];
  75. FSTFieldPath *appended = [sub pathByAppendingSegment:@"2"];
  76. XCTAssertEqualObjects(appended, FSTTestFieldPath(@"eros.1.2"));
  77. }
  78. - (void)testPathComparison {
  79. FSTFieldPath *path1 = [FSTFieldPath pathWithSegments:@[ @"a", @"b", @"c" ]];
  80. FSTFieldPath *path2 = [FSTFieldPath pathWithSegments:@[ @"a", @"b", @"c" ]];
  81. FSTFieldPath *path3 = [FSTFieldPath pathWithSegments:@[ @"x", @"y", @"z" ]];
  82. XCTAssertTrue([path1 isEqual:path2]);
  83. XCTAssertFalse([path1 isEqual:path3]);
  84. FSTFieldPath *empty = [FSTFieldPath pathWithSegments:@[]];
  85. FSTFieldPath *a = [FSTFieldPath pathWithSegments:@[ @"a" ]];
  86. FSTFieldPath *b = [FSTFieldPath pathWithSegments:@[ @"b" ]];
  87. FSTFieldPath *ab = [FSTFieldPath pathWithSegments:@[ @"a", @"b" ]];
  88. XCTAssertEqual(NSOrderedAscending, [empty compare:a]);
  89. XCTAssertEqual(NSOrderedAscending, [a compare:b]);
  90. XCTAssertEqual(NSOrderedAscending, [a compare:ab]);
  91. XCTAssertEqual(NSOrderedDescending, [a compare:empty]);
  92. XCTAssertEqual(NSOrderedDescending, [b compare:a]);
  93. XCTAssertEqual(NSOrderedDescending, [ab compare:a]);
  94. }
  95. - (void)testIsPrefixOfPath {
  96. FSTFieldPath *empty = [FSTFieldPath pathWithSegments:@[]];
  97. FSTFieldPath *a = [FSTFieldPath pathWithSegments:@[ @"a" ]];
  98. FSTFieldPath *ab = [FSTFieldPath pathWithSegments:@[ @"a", @"b" ]];
  99. FSTFieldPath *abc = [FSTFieldPath pathWithSegments:@[ @"a", @"b", @"c" ]];
  100. FSTFieldPath *b = [FSTFieldPath pathWithSegments:@[ @"b" ]];
  101. FSTFieldPath *ba = [FSTFieldPath pathWithSegments:@[ @"b", @"a" ]];
  102. XCTAssertTrue([empty isPrefixOfPath:a]);
  103. XCTAssertTrue([empty isPrefixOfPath:ab]);
  104. XCTAssertTrue([empty isPrefixOfPath:abc]);
  105. XCTAssertTrue([empty isPrefixOfPath:empty]);
  106. XCTAssertTrue([empty isPrefixOfPath:b]);
  107. XCTAssertTrue([empty isPrefixOfPath:ba]);
  108. XCTAssertTrue([a isPrefixOfPath:a]);
  109. XCTAssertTrue([a isPrefixOfPath:ab]);
  110. XCTAssertTrue([a isPrefixOfPath:abc]);
  111. XCTAssertFalse([a isPrefixOfPath:empty]);
  112. XCTAssertFalse([a isPrefixOfPath:b]);
  113. XCTAssertFalse([a isPrefixOfPath:ba]);
  114. XCTAssertFalse([ab isPrefixOfPath:a]);
  115. XCTAssertTrue([ab isPrefixOfPath:ab]);
  116. XCTAssertTrue([ab isPrefixOfPath:abc]);
  117. XCTAssertFalse([ab isPrefixOfPath:empty]);
  118. XCTAssertFalse([ab isPrefixOfPath:b]);
  119. XCTAssertFalse([ab isPrefixOfPath:ba]);
  120. XCTAssertFalse([abc isPrefixOfPath:a]);
  121. XCTAssertFalse([abc isPrefixOfPath:ab]);
  122. XCTAssertTrue([abc isPrefixOfPath:abc]);
  123. XCTAssertFalse([abc isPrefixOfPath:empty]);
  124. XCTAssertFalse([abc isPrefixOfPath:b]);
  125. XCTAssertFalse([abc isPrefixOfPath:ba]);
  126. }
  127. - (void)testInvalidPaths {
  128. XCTAssertThrows(FSTTestFieldPath(@""));
  129. XCTAssertThrows(FSTTestFieldPath(@"."));
  130. XCTAssertThrows(FSTTestFieldPath(@".foo"));
  131. XCTAssertThrows(FSTTestFieldPath(@"foo."));
  132. XCTAssertThrows(FSTTestFieldPath(@"foo..bar"));
  133. }
  134. #define ASSERT_ROUND_TRIP(str, segments) \
  135. do { \
  136. FSTFieldPath *path = [FSTFieldPath pathWithServerFormat:str]; \
  137. XCTAssertEqual([path length], segments); \
  138. NSString *canonical = [path canonicalString]; \
  139. XCTAssertEqualObjects(canonical, str); \
  140. } while (0);
  141. - (void)testCanonicalString {
  142. ASSERT_ROUND_TRIP(@"foo", 1);
  143. ASSERT_ROUND_TRIP(@"foo.bar", 2);
  144. ASSERT_ROUND_TRIP(@"foo.bar.baz", 3);
  145. ASSERT_ROUND_TRIP(@"`.foo\\\\`", 1);
  146. ASSERT_ROUND_TRIP(@"`.foo\\\\`.`.foo`", 2);
  147. ASSERT_ROUND_TRIP(@"foo.`\\``.bar", 3);
  148. }
  149. #undef ASSERT_ROUND_TRIP
  150. - (void)testCanonicalStringOfSubstring {
  151. FSTFieldPath *path = [FSTFieldPath pathWithServerFormat:@"foo.bar.baz"];
  152. XCTAssertEqualObjects([path canonicalString], @"foo.bar.baz");
  153. FSTFieldPath *pathTail = [path pathByRemovingFirstSegment];
  154. XCTAssertEqualObjects([pathTail canonicalString], @"bar.baz");
  155. FSTFieldPath *pathHead = [path pathByRemovingLastSegment];
  156. XCTAssertEqualObjects([pathHead canonicalString], @"foo.bar");
  157. XCTAssertEqualObjects([[pathTail pathByRemovingLastSegment] canonicalString], @"bar");
  158. XCTAssertEqualObjects([[pathHead pathByRemovingFirstSegment] canonicalString], @"bar");
  159. }
  160. @end
  161. NS_ASSUME_NONNULL_END