// Copyright 2007-2008 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials provided // with the distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <stdlib.h> #include "src/v8.h" #include "src/liveedit.h" #include "test/cctest/cctest.h" using namespace v8::internal; // Anonymous namespace. namespace { class StringCompareInput : public Comparator::Input { public: StringCompareInput(const char* s1, const char* s2) : s1_(s1), s2_(s2) { } int GetLength1() { return StrLength(s1_); } int GetLength2() { return StrLength(s2_); } bool Equals(int index1, int index2) { return s1_[index1] == s2_[index2]; } private: const char* s1_; const char* s2_; }; class DiffChunkStruct : public ZoneObject { public: DiffChunkStruct(int pos1_param, int pos2_param, int len1_param, int len2_param) : pos1(pos1_param), pos2(pos2_param), len1(len1_param), len2(len2_param), next(NULL) {} int pos1; int pos2; int len1; int len2; DiffChunkStruct* next; }; class ListDiffOutputWriter : public Comparator::Output { public: explicit ListDiffOutputWriter(DiffChunkStruct** next_chunk_pointer, Zone* zone) : next_chunk_pointer_(next_chunk_pointer), zone_(zone) { (*next_chunk_pointer_) = NULL; } void AddChunk(int pos1, int pos2, int len1, int len2) { current_chunk_ = new(zone_) DiffChunkStruct(pos1, pos2, len1, len2); (*next_chunk_pointer_) = current_chunk_; next_chunk_pointer_ = ¤t_chunk_->next; } private: DiffChunkStruct** next_chunk_pointer_; DiffChunkStruct* current_chunk_; Zone* zone_; }; void CompareStringsOneWay(const char* s1, const char* s2, int expected_diff_parameter = -1) { StringCompareInput input(s1, s2); Zone zone(CcTest::i_isolate()); DiffChunkStruct* first_chunk; ListDiffOutputWriter writer(&first_chunk, &zone); Comparator::CalculateDifference(&input, &writer); int len1 = StrLength(s1); int len2 = StrLength(s2); int pos1 = 0; int pos2 = 0; int diff_parameter = 0; for (DiffChunkStruct* chunk = first_chunk; chunk != NULL; chunk = chunk->next) { int diff_pos1 = chunk->pos1; int similar_part_length = diff_pos1 - pos1; int diff_pos2 = pos2 + similar_part_length; ASSERT_EQ(diff_pos2, chunk->pos2); for (int j = 0; j < similar_part_length; j++) { ASSERT(pos1 + j < len1); ASSERT(pos2 + j < len2); ASSERT_EQ(s1[pos1 + j], s2[pos2 + j]); } diff_parameter += chunk->len1 + chunk->len2; pos1 = diff_pos1 + chunk->len1; pos2 = diff_pos2 + chunk->len2; } { // After last chunk. int similar_part_length = len1 - pos1; ASSERT_EQ(similar_part_length, len2 - pos2); USE(len2); for (int j = 0; j < similar_part_length; j++) { ASSERT(pos1 + j < len1); ASSERT(pos2 + j < len2); ASSERT_EQ(s1[pos1 + j], s2[pos2 + j]); } } if (expected_diff_parameter != -1) { ASSERT_EQ(expected_diff_parameter, diff_parameter); } } void CompareStrings(const char* s1, const char* s2, int expected_diff_parameter = -1) { CompareStringsOneWay(s1, s2, expected_diff_parameter); CompareStringsOneWay(s2, s1, expected_diff_parameter); } } // Anonymous namespace. // --- T h e A c t u a l T e s t s TEST(LiveEditDiffer) { v8::internal::V8::Initialize(NULL); CompareStrings("zz1zzz12zz123zzz", "zzzzzzzzzz", 6); CompareStrings("zz1zzz12zz123zzz", "zz0zzz0zz0zzz", 9); CompareStrings("123456789", "987654321", 16); CompareStrings("zzz", "yyy", 6); CompareStrings("zzz", "zzz12", 2); CompareStrings("zzz", "21zzz", 2); CompareStrings("cat", "cut", 2); CompareStrings("ct", "cut", 1); CompareStrings("cat", "ct", 1); CompareStrings("cat", "cat", 0); CompareStrings("", "", 0); CompareStrings("cat", "", 3); CompareStrings("a cat", "a capybara", 7); CompareStrings("abbabababababaaabbabababababbabbbbbbbababa", "bbbbabababbbabababbbabababababbabbababa"); }