1// Copyright 2012 Aryan Naraghi (aryan.naraghi@gmail.com) 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package difflib 16 17import ( 18 "reflect" 19 "strings" 20 "testing" 21) 22 23var lcsTests = []struct { 24 seq1 string 25 seq2 string 26 lcs int 27}{ 28 {"", "", 0}, 29 {"abc", "abc", 3}, 30 {"mzjawxu", "xmjyauz", 4}, 31 {"human", "chimpanzee", 4}, 32 {"Hello, world!", "Hello, world!", 13}, 33 {"Hello, world!", "H e l l o , w o r l d !", 13}, 34} 35 36func TestLongestCommonSubsequenceMatrix(t *testing.T) { 37 for i, test := range lcsTests { 38 seq1 := strings.Split(test.seq1, "") 39 seq2 := strings.Split(test.seq2, "") 40 matrix := longestCommonSubsequenceMatrix(seq1, seq2) 41 lcs := matrix[len(matrix)-1][len(matrix[0])-1] // Grabs the lower, right value. 42 if lcs != test.lcs { 43 t.Errorf("%d. longestCommonSubsequence(%v, %v)[last][last] => %d, expected %d", 44 i, seq1, seq2, lcs, test.lcs) 45 } 46 } 47} 48 49var numEqualStartAndEndElementsTests = []struct { 50 seq1 string 51 seq2 string 52 start int 53 end int 54}{ 55 {"", "", 0, 0}, 56 {"abc", "", 0, 0}, 57 {"", "abc", 0, 0}, 58 {"abc", "abc", 3, 0}, 59 {"abhelloc", "abbyec", 2, 1}, 60 {"abchello", "abcbye", 3, 0}, 61 {"helloabc", "byeabc", 0, 3}, 62} 63 64func TestNumEqualStartAndEndElements(t *testing.T) { 65 for i, test := range numEqualStartAndEndElementsTests { 66 seq1 := strings.Split(test.seq1, "") 67 seq2 := strings.Split(test.seq2, "") 68 start, end := numEqualStartAndEndElements(seq1, seq2) 69 if start != test.start || end != test.end { 70 t.Errorf("%d. numEqualStartAndEndElements(%v, %v) => (%d, %d), expected (%d, %d)", 71 i, seq1, seq2, start, end, test.start, test.end) 72 } 73 } 74} 75 76var diffTests = []struct { 77 Seq1 string 78 Seq2 string 79 Diff []DiffRecord 80 HtmlDiff string 81}{ 82 { 83 "", 84 "", 85 []DiffRecord{ 86 {"", Common}, 87 }, 88 `<tr><td class="line-num">1</td><td><pre></pre></td><td><pre></pre></td><td class="line-num">1</td></tr> 89`, 90 }, 91 92 { 93 "same", 94 "same", 95 []DiffRecord{ 96 {"same", Common}, 97 }, 98 `<tr><td class="line-num">1</td><td><pre>same</pre></td><td><pre>same</pre></td><td class="line-num">1</td></tr> 99`, 100 }, 101 102 { 103 `one 104two 105three 106`, 107 `one 108two 109three 110`, 111 []DiffRecord{ 112 {"one", Common}, 113 {"two", Common}, 114 {"three", Common}, 115 {"", Common}, 116 }, 117 `<tr><td class="line-num">1</td><td><pre>one</pre></td><td><pre>one</pre></td><td class="line-num">1</td></tr> 118<tr><td class="line-num">2</td><td><pre>two</pre></td><td><pre>two</pre></td><td class="line-num">2</td></tr> 119<tr><td class="line-num">3</td><td><pre>three</pre></td><td><pre>three</pre></td><td class="line-num">3</td></tr> 120<tr><td class="line-num">4</td><td><pre></pre></td><td><pre></pre></td><td class="line-num">4</td></tr> 121`, 122 }, 123 124 { 125 `one 126two 127three 128`, 129 `one 130five 131three 132`, 133 []DiffRecord{ 134 {"one", Common}, 135 {"two", LeftOnly}, 136 {"five", RightOnly}, 137 {"three", Common}, 138 {"", Common}, 139 }, 140 `<tr><td class="line-num">1</td><td><pre>one</pre></td><td><pre>one</pre></td><td class="line-num">1</td></tr> 141<tr><td class="line-num">2</td><td class="deleted"><pre>two</pre></td><td></td><td class="line-num"></td></tr> 142<tr><td class="line-num"></td><td></td><td class="added"><pre>five</pre></td><td class="line-num">2</td></tr> 143<tr><td class="line-num">3</td><td><pre>three</pre></td><td><pre>three</pre></td><td class="line-num">3</td></tr> 144<tr><td class="line-num">4</td><td><pre></pre></td><td><pre></pre></td><td class="line-num">4</td></tr> 145`, 146 }, 147 148 { 149 `Beethoven 150Bach 151Mozart 152Chopin 153`, 154 `Beethoven 155Bach 156Brahms 157Chopin 158Liszt 159Wagner 160`, 161 162 []DiffRecord{ 163 {"Beethoven", Common}, 164 {"Bach", Common}, 165 {"Mozart", LeftOnly}, 166 {"Brahms", RightOnly}, 167 {"Chopin", Common}, 168 {"Liszt", RightOnly}, 169 {"Wagner", RightOnly}, 170 {"", Common}, 171 }, 172 `<tr><td class="line-num">1</td><td><pre>Beethoven</pre></td><td><pre>Beethoven</pre></td><td class="line-num">1</td></tr> 173<tr><td class="line-num">2</td><td><pre>Bach</pre></td><td><pre>Bach</pre></td><td class="line-num">2</td></tr> 174<tr><td class="line-num">3</td><td class="deleted"><pre>Mozart</pre></td><td></td><td class="line-num"></td></tr> 175<tr><td class="line-num"></td><td></td><td class="added"><pre>Brahms</pre></td><td class="line-num">3</td></tr> 176<tr><td class="line-num">4</td><td><pre>Chopin</pre></td><td><pre>Chopin</pre></td><td class="line-num">4</td></tr> 177<tr><td class="line-num"></td><td></td><td class="added"><pre>Liszt</pre></td><td class="line-num">5</td></tr> 178<tr><td class="line-num"></td><td></td><td class="added"><pre>Wagner</pre></td><td class="line-num">6</td></tr> 179<tr><td class="line-num">5</td><td><pre></pre></td><td><pre></pre></td><td class="line-num">7</td></tr> 180`, 181 }, 182 183 { 184 `adagio 185vivace 186staccato legato 187presto 188lento 189`, 190 `adagio adagio 191staccato 192staccato legato 193staccato 194legato 195allegro 196`, 197 []DiffRecord{ 198 {"adagio", LeftOnly}, 199 {"vivace", LeftOnly}, 200 {"adagio adagio", RightOnly}, 201 {"staccato", RightOnly}, 202 {"staccato legato", Common}, 203 {"presto", LeftOnly}, 204 {"lento", LeftOnly}, 205 {"staccato", RightOnly}, 206 {"legato", RightOnly}, 207 {"allegro", RightOnly}, 208 {"", Common}, 209 }, 210 `<tr><td class="line-num">1</td><td class="deleted"><pre>adagio</pre></td><td></td><td class="line-num"></td></tr> 211<tr><td class="line-num">2</td><td class="deleted"><pre>vivace</pre></td><td></td><td class="line-num"></td></tr> 212<tr><td class="line-num"></td><td></td><td class="added"><pre>adagio adagio</pre></td><td class="line-num">1</td></tr> 213<tr><td class="line-num"></td><td></td><td class="added"><pre>staccato</pre></td><td class="line-num">2</td></tr> 214<tr><td class="line-num">3</td><td><pre>staccato legato</pre></td><td><pre>staccato legato</pre></td><td class="line-num">3</td></tr> 215<tr><td class="line-num">4</td><td class="deleted"><pre>presto</pre></td><td></td><td class="line-num"></td></tr> 216<tr><td class="line-num">5</td><td class="deleted"><pre>lento</pre></td><td></td><td class="line-num"></td></tr> 217<tr><td class="line-num"></td><td></td><td class="added"><pre>staccato</pre></td><td class="line-num">4</td></tr> 218<tr><td class="line-num"></td><td></td><td class="added"><pre>legato</pre></td><td class="line-num">5</td></tr> 219<tr><td class="line-num"></td><td></td><td class="added"><pre>allegro</pre></td><td class="line-num">6</td></tr> 220<tr><td class="line-num">6</td><td><pre></pre></td><td><pre></pre></td><td class="line-num">7</td></tr> 221`, 222 }, 223} 224 225func TestDiff(t *testing.T) { 226 for i, test := range diffTests { 227 seq1 := strings.Split(test.Seq1, "\n") 228 seq2 := strings.Split(test.Seq2, "\n") 229 230 diff := Diff(seq1, seq2) 231 if !reflect.DeepEqual(diff, test.Diff) { 232 t.Errorf("%d. Diff(%v, %v) => %v, expected %v", 233 i, seq1, seq2, diff, test.Diff) 234 } 235 236 htmlDiff := HTMLDiff(seq1, seq2) 237 if htmlDiff != test.HtmlDiff { 238 t.Errorf("%d. HtmlDiff(%v, %v) => %v, expected %v", 239 i, seq1, seq2, htmlDiff, test.HtmlDiff) 240 } 241 242 } 243} 244