Index: test/cctest/test-regexp.cc |
=================================================================== |
--- test/cctest/test-regexp.cc (revision 3689) |
+++ test/cctest/test-regexp.cc (working copy) |
@@ -1650,8 +1650,165 @@ |
ASSERT_EQ(30, list->at(0).to()); |
} |
+// Checks whether a character is in the set represented by a list of ranges. |
+static bool CharacterInSet(ZoneList<CharacterRange>* set, uc16 value) { |
+ for (int i = 0; i < set->length(); i++) { |
+ CharacterRange range = set->at(i); |
+ if (range.from() <= value && value <= range.to()) { |
+ return true; |
+ } |
+ } |
+ return false; |
+} |
+TEST(CharacterRangeMerge) { |
+ ZoneScope zone_scope(DELETE_ON_EXIT); |
+ ZoneList<CharacterRange> l1(4); |
+ ZoneList<CharacterRange> l2(4); |
+ // Create all combinations of intersections of ranges, both singletons and |
+ // longer. |
+ int offset = 0; |
+ |
+ // The five kinds of singleton intersections: |
+ // X |
+ // Y - outside before |
+ // Y - outside touching start |
+ // Y - overlap |
+ // Y - outside touching end |
+ // Y - outside after |
+ |
+ for (int i = 0; i < 5; i++) { |
+ l1.Add(CharacterRange::Singleton(offset + 2)); |
+ l2.Add(CharacterRange::Singleton(offset + i)); |
+ offset += 6; |
+ } |
+ |
+ // The seven kinds of singleton/non-singleton intersections: |
+ // XXX |
+ // Y - outside before |
+ // Y - outside touching start |
+ // Y - inside touching start |
+ // Y - entirely inside |
+ // Y - inside touching end |
+ // Y - outside touching end |
+ // Y - disjoint after |
+ |
+ for (int i = 0; i < 7; i++) { |
+ l1.Add(CharacterRange::Range(offset + 2, offset + 4)); |
+ l2.Add(CharacterRange::Singleton(offset + i)); |
+ offset += 8; |
+ } |
+ |
+ // The eleven kinds of non-singleton intersections: |
+ // |
+ // XXXXXXXX |
+ // YYYY - outside before. |
+ // YYYY - outside touching start. |
+ // YYYY - overlapping start |
+ // YYYY - inside touching start |
+ // YYYY - entirely inside |
+ // YYYY - inside touching end |
+ // YYYY - overlapping end |
+ // YYYY - outside touching end |
+ // YYYY - outside after |
+ // YYYYYYYY - identical |
+ // YYYYYYYYYYYY - containing entirely. |
+ |
+ for (int i = 0; i < 9; i++) { |
+ l1.Add(CharacterRange::Range(offset + 6, offset + 15)); // Length 8. |
+ l2.Add(CharacterRange::Range(offset + 2 * i, offset + 2 * i + 3)); |
+ offset += 22; |
+ } |
+ l1.Add(CharacterRange::Range(offset + 6, offset + 15)); |
+ l2.Add(CharacterRange::Range(offset + 6, offset + 15)); |
+ offset += 22; |
+ l1.Add(CharacterRange::Range(offset + 6, offset + 15)); |
+ l2.Add(CharacterRange::Range(offset + 4, offset + 17)); |
+ offset += 22; |
+ |
+ // Different kinds of multi-range overlap: |
+ // XXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXX |
+ // YYYY Y YYYY Y YYYY Y YYYY Y YYYY Y YYYY Y |
+ |
+ l1.Add(CharacterRange::Range(offset, offset + 21)); |
+ l1.Add(CharacterRange::Range(offset + 31, offset + 52)); |
+ for (int i = 0; i < 6; i++) { |
+ l2.Add(CharacterRange::Range(offset + 2, offset + 5)); |
+ l2.Add(CharacterRange::Singleton(offset + 8)); |
+ offset += 9; |
+ } |
+ |
+ ASSERT(CharacterRange::IsCanonical(&l1)); |
+ ASSERT(CharacterRange::IsCanonical(&l2)); |
+ |
+ ZoneList<CharacterRange> first_only(4); |
+ ZoneList<CharacterRange> second_only(4); |
+ ZoneList<CharacterRange> both(4); |
+ |
+ // Merge one direction. |
+ CharacterRange::Merge(&l1, &l2, &first_only, &second_only, &both); |
+ |
+ CHECK(CharacterRange::IsCanonical(&first_only)); |
+ CHECK(CharacterRange::IsCanonical(&second_only)); |
+ CHECK(CharacterRange::IsCanonical(&both)); |
+ |
+ for (uc16 i = 0; i < offset; i++) { |
+ bool in_first = CharacterInSet(&l1, i); |
+ bool in_second = CharacterInSet(&l2, i); |
+ CHECK((in_first && !in_second) == CharacterInSet(&first_only, i)); |
+ CHECK((!in_first && in_second) == CharacterInSet(&second_only, i)); |
+ CHECK((in_first && in_second) == CharacterInSet(&both, i)); |
+ } |
+ |
+ first_only.Clear(); |
+ second_only.Clear(); |
+ both.Clear(); |
+ |
+ // Merge other direction. |
+ CharacterRange::Merge(&l2, &l1, &second_only, &first_only, &both); |
+ |
+ CHECK(CharacterRange::IsCanonical(&first_only)); |
+ CHECK(CharacterRange::IsCanonical(&second_only)); |
+ CHECK(CharacterRange::IsCanonical(&both)); |
+ |
+ for (uc16 i = 0; i < offset; i++) { |
+ bool in_first = CharacterInSet(&l1, i); |
+ bool in_second = CharacterInSet(&l2, i); |
+ CHECK((in_first && !in_second) == CharacterInSet(&first_only, i)); |
+ CHECK((!in_first && in_second) == CharacterInSet(&second_only, i)); |
+ CHECK((in_first && in_second) == CharacterInSet(&both, i)); |
+ } |
+ |
+ first_only.Clear(); |
+ second_only.Clear(); |
+ both.Clear(); |
+ |
+ // Merge but don't record all combinations. |
+ CharacterRange::Merge(&l1, &l2, NULL, NULL, &both); |
+ |
+ CHECK(CharacterRange::IsCanonical(&both)); |
+ |
+ for (uc16 i = 0; i < offset; i++) { |
+ bool in_first = CharacterInSet(&l1, i); |
+ bool in_second = CharacterInSet(&l2, i); |
+ CHECK((in_first && in_second) == CharacterInSet(&both, i)); |
+ } |
+ |
+ // Merge into same set. |
+ ZoneList<CharacterRange> all(4); |
+ CharacterRange::Merge(&l1, &l2, &all, &all, &all); |
+ |
+ CHECK(CharacterRange::IsCanonical(&all)); |
+ |
+ for (uc16 i = 0; i < offset; i++) { |
+ bool in_first = CharacterInSet(&l1, i); |
+ bool in_second = CharacterInSet(&l2, i); |
+ CHECK((in_first || in_second) == CharacterInSet(&all, i)); |
+ } |
+} |
+ |
+ |
TEST(Graph) { |
V8::Initialize(NULL); |
Execute("\\b\\w+\\b", false, true, true); |