1// Copyright 2007-2008 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28#include <stdlib.h> 29 30#include "src/v8.h" 31 32#include "src/liveedit.h" 33#include "test/cctest/cctest.h" 34 35 36using namespace v8::internal; 37 38// Anonymous namespace. 39namespace { 40 41class StringCompareInput : public Comparator::Input { 42 public: 43 StringCompareInput(const char* s1, const char* s2) : s1_(s1), s2_(s2) { 44 } 45 int GetLength1() { 46 return StrLength(s1_); 47 } 48 int GetLength2() { 49 return StrLength(s2_); 50 } 51 bool Equals(int index1, int index2) { 52 return s1_[index1] == s2_[index2]; 53 } 54 55 private: 56 const char* s1_; 57 const char* s2_; 58}; 59 60 61class DiffChunkStruct : public ZoneObject { 62 public: 63 DiffChunkStruct(int pos1_param, int pos2_param, 64 int len1_param, int len2_param) 65 : pos1(pos1_param), pos2(pos2_param), 66 len1(len1_param), len2(len2_param), next(NULL) {} 67 int pos1; 68 int pos2; 69 int len1; 70 int len2; 71 DiffChunkStruct* next; 72}; 73 74 75class ListDiffOutputWriter : public Comparator::Output { 76 public: 77 explicit ListDiffOutputWriter(DiffChunkStruct** next_chunk_pointer, 78 Zone* zone) 79 : next_chunk_pointer_(next_chunk_pointer), zone_(zone) { 80 (*next_chunk_pointer_) = NULL; 81 } 82 void AddChunk(int pos1, int pos2, int len1, int len2) { 83 current_chunk_ = new(zone_) DiffChunkStruct(pos1, pos2, len1, len2); 84 (*next_chunk_pointer_) = current_chunk_; 85 next_chunk_pointer_ = ¤t_chunk_->next; 86 } 87 private: 88 DiffChunkStruct** next_chunk_pointer_; 89 DiffChunkStruct* current_chunk_; 90 Zone* zone_; 91}; 92 93 94void CompareStringsOneWay(const char* s1, const char* s2, 95 int expected_diff_parameter = -1) { 96 StringCompareInput input(s1, s2); 97 98 Zone zone(CcTest::i_isolate()); 99 100 DiffChunkStruct* first_chunk; 101 ListDiffOutputWriter writer(&first_chunk, &zone); 102 103 Comparator::CalculateDifference(&input, &writer); 104 105 int len1 = StrLength(s1); 106 int len2 = StrLength(s2); 107 108 int pos1 = 0; 109 int pos2 = 0; 110 111 int diff_parameter = 0; 112 113 for (DiffChunkStruct* chunk = first_chunk; 114 chunk != NULL; 115 chunk = chunk->next) { 116 int diff_pos1 = chunk->pos1; 117 int similar_part_length = diff_pos1 - pos1; 118 int diff_pos2 = pos2 + similar_part_length; 119 120 DCHECK_EQ(diff_pos2, chunk->pos2); 121 122 for (int j = 0; j < similar_part_length; j++) { 123 DCHECK(pos1 + j < len1); 124 DCHECK(pos2 + j < len2); 125 DCHECK_EQ(s1[pos1 + j], s2[pos2 + j]); 126 } 127 diff_parameter += chunk->len1 + chunk->len2; 128 pos1 = diff_pos1 + chunk->len1; 129 pos2 = diff_pos2 + chunk->len2; 130 } 131 { 132 // After last chunk. 133 int similar_part_length = len1 - pos1; 134 DCHECK_EQ(similar_part_length, len2 - pos2); 135 USE(len2); 136 for (int j = 0; j < similar_part_length; j++) { 137 DCHECK(pos1 + j < len1); 138 DCHECK(pos2 + j < len2); 139 DCHECK_EQ(s1[pos1 + j], s2[pos2 + j]); 140 } 141 } 142 143 if (expected_diff_parameter != -1) { 144 DCHECK_EQ(expected_diff_parameter, diff_parameter); 145 } 146} 147 148 149void CompareStrings(const char* s1, const char* s2, 150 int expected_diff_parameter = -1) { 151 CompareStringsOneWay(s1, s2, expected_diff_parameter); 152 CompareStringsOneWay(s2, s1, expected_diff_parameter); 153} 154 155} // Anonymous namespace. 156 157 158// --- T h e A c t u a l T e s t s 159 160TEST(LiveEditDiffer) { 161 CompareStrings("zz1zzz12zz123zzz", "zzzzzzzzzz", 6); 162 CompareStrings("zz1zzz12zz123zzz", "zz0zzz0zz0zzz", 9); 163 CompareStrings("123456789", "987654321", 16); 164 CompareStrings("zzz", "yyy", 6); 165 CompareStrings("zzz", "zzz12", 2); 166 CompareStrings("zzz", "21zzz", 2); 167 CompareStrings("cat", "cut", 2); 168 CompareStrings("ct", "cut", 1); 169 CompareStrings("cat", "ct", 1); 170 CompareStrings("cat", "cat", 0); 171 CompareStrings("", "", 0); 172 CompareStrings("cat", "", 3); 173 CompareStrings("a cat", "a capybara", 7); 174 CompareStrings("abbabababababaaabbabababababbabbbbbbbababa", 175 "bbbbabababbbabababbbabababababbabbababa"); 176} 177