github.com/driusan/dgit@v0.0.0-20221118233547-f39f0c15edbb/git/delta/calculator_test.go (about) 1 package delta 2 3 import ( 4 "bytes" 5 "container/list" 6 "index/suffixarray" 7 "io/ioutil" 8 "testing" 9 ) 10 11 func TestCalculator(t *testing.T) { 12 tests := []struct { 13 label string 14 src, dst []byte 15 want []instruction 16 }{ 17 { 18 "No intersection", 19 []byte("abc"), 20 []byte("def"), 21 []instruction{insert("def")}, 22 }, 23 { 24 "dst is prefix", 25 []byte("defabc"), 26 []byte("def"), 27 []instruction{copyinst{0, 3}}, 28 }, 29 { 30 "dst is suffix", 31 []byte("abcdef"), 32 []byte("def"), 33 []instruction{copyinst{3, 3}}, 34 }, 35 { 36 "src is substring of dst", 37 []byte("def"), []byte("defabc"), 38 []instruction{copyinst{0, 3}, insert("abc")}, 39 }, 40 { 41 // Mostly to make sure we don't crash if < minCopy 42 "small value", 43 []byte("d"), []byte("d"), 44 []instruction{insert("d")}, 45 }, 46 { 47 "src is embedded in dst", 48 []byte("def"), []byte("abdefab"), 49 []instruction{ 50 insert("ab"), 51 copyinst{0, 3}, 52 insert("ab"), 53 }, 54 }, 55 { 56 "random common substring", 57 []byte("abDxxxAxF"), []byte("AxxxFwX"), 58 []instruction{ 59 insert("A"), 60 copyinst{3, 3}, 61 insert("FwX"), 62 }, 63 }, 64 } 65 66 for _, tc := range tests { 67 idx := suffixarray.New(tc.src) 68 instructions, err := calculate(idx, tc.src, tc.dst, -1) 69 if err != nil { 70 t.Fatal(err) 71 } 72 if identicalInstructions(tc.want, instructions) != true { 73 t.Errorf("%s", tc.label) 74 } 75 } 76 } 77 78 func identicalInstructions(want []instruction, got *list.List) bool { 79 if len(want) != got.Len() { 80 return false 81 } 82 83 i := 0 84 for e := got.Front(); e != nil; e = e.Next() { 85 i1 := want[i] 86 if !i1.equals(e.Value.(instruction)) { 87 return false 88 } 89 i++ 90 } 91 return true 92 } 93 94 func TestCalculatorWriteInsert(t *testing.T) { 95 var buf bytes.Buffer 96 97 i := insert("abc") 98 i.write(&buf) 99 100 // simple insert instructions 101 var want []byte = []byte{3, 97, 98, 99} 102 if got := buf.String(); got != string(want) { 103 t.Errorf("Simple insert: got %s want %s", got, want) 104 } 105 106 buf.Reset() 107 // long insert, needs to generate 2 insert instructions 108 // in the stream. 109 // 13 sequences of 10 characters 110 i = insert("0123456789" + 111 "0123456789" + 112 "0123456789" + 113 "0123456789" + 114 "0123456789" + 115 "0123456789" + 116 "0123456789" + 117 "0123456789" + 118 "0123456789" + 119 "0123456789" + 120 "0123456789" + 121 "0123456789" + 122 "0123456789") 123 i.write(&buf) 124 want = []byte{ 125 // First 127 characters 126 127, 127 // 0-9, x12 128 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 129 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 130 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 131 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 132 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 133 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 134 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 135 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 136 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 137 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 138 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 139 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 140 // 0-6 141 48, 49, 50, 51, 52, 53, 54, 142 // Insert for the remaining characters 143 3, 144 55, 56, 57, 145 } 146 if got := buf.String(); got != string(want) { 147 t.Errorf("Long insert: got %s want %s", got, want) 148 } 149 150 } 151 152 func TestCalculatorWriteCopy(t *testing.T) { 153 tests := []struct { 154 label string 155 i copyinst 156 want []byte 157 }{ 158 { 159 "Length size 1 copy", 160 copyinst{0, 1}, 161 []byte{0x80 | 0x10, 1}, 162 }, 163 { 164 "Length size 2 copy", 165 copyinst{0, 1 << 8}, 166 []byte{0x80 | 0x20, 1}, 167 }, 168 { 169 "Length size 3 copy", 170 // can't use 1 << 16 or we'd hit 171 // the special case 172 copyinst{0, 2 << 16}, 173 []byte{0x80 | 0x40, 2}, 174 }, 175 { 176 "Length size 1 and 2 copy", 177 copyinst{0, (2 << 8) | 1}, 178 []byte{0x80 | 0x10 | 0x20, 1, 2}, 179 }, 180 { 181 "Length size 1 and 3 copy", 182 copyinst{0, (3 << 16) | 1}, 183 []byte{0x80 | 0x10 | 0x40, 1, 3}, 184 }, 185 { 186 "Length size 2 and 3 copy", 187 copyinst{0, (3 << 16) | (2 << 8)}, 188 []byte{0x80 | 0x20 | 0x40, 2, 3}, 189 }, 190 { 191 "Length size 1, 2 and 3 copy", 192 copyinst{0, (3 << 16) | (2 << 8) | 1}, 193 []byte{0x80 | 0x10 | 0x20 | 0x40, 1, 2, 3}, 194 }, 195 { 196 "Length special case size copy", 197 copyinst{0, 0x10000}, 198 []byte{0x80}, 199 }, 200 { 201 "Offset size 1 encoding", 202 copyinst{1, 0x10000}, 203 []byte{0x80 | 0x01, 1}, 204 }, 205 { 206 "Offset size 2 encoding", 207 copyinst{1 << 8, 0x10000}, 208 []byte{0x80 | 0x02, 1}, 209 }, 210 { 211 "Offset size 3 encoding", 212 copyinst{1 << 16, 0x10000}, 213 []byte{0x80 | 0x04, 1}, 214 }, 215 { 216 "Offset size 4 encoding", 217 copyinst{1 << 24, 0x10000}, 218 []byte{0x80 | 0x08, 1}, 219 }, 220 { 221 "Multibyte offset size encoding (bits 1 and 4)", 222 copyinst{4<<24 | 1, 0x10000}, 223 []byte{0x80 | 0x01 | 0x08, 1, 4}, 224 }, 225 { 226 "Mixed offset and length encoding", 227 copyinst{1<<8 | 2, 3}, 228 []byte{ 229 0x80 | 230 0x1 | 0x2 | // offset bits 231 0x10, // length bits 232 2, 1, // offset first 233 3, // length second 234 }, 235 }, 236 } 237 var buf bytes.Buffer 238 239 for _, tc := range tests { 240 buf.Reset() 241 tc.i.write(&buf) 242 243 if got := buf.String(); got != string(tc.want) { 244 t.Errorf("%s: got %v want %v", tc.label, []byte(got), tc.want) 245 } 246 } 247 } 248 249 // Calculate a delta and ensure reading it resolves to the same 250 // value 251 func TestSanityTest(t *testing.T) { 252 // A random 2 instruction from TestCalculator. 253 // src is "def", dst is "defabc". Should result 254 // in both a copy and an insert. 255 // (was tested in TestCalculator) 256 var delta bytes.Buffer 257 base := []byte("def") 258 target := []byte("defabc") 259 Calculate(&delta, base, target, -1) 260 261 resolved := NewReader( 262 bytes.NewReader(delta.Bytes()), 263 bytes.NewReader(base), 264 ) 265 val, err := ioutil.ReadAll(&resolved) 266 if err != nil { 267 t.Fatal(err) 268 } 269 if string(val) != string(target) { 270 t.Errorf("Unexpected delta resolution: got %v want %v", val, target) 271 } 272 273 // "Large" delta, one which gave us problems with the git test suite.. 274 base = make([]byte, 4096) 275 276 for i := range base { 277 base[i] = 'c' 278 } 279 target = []byte(string(base) + "foo") 280 delta.Reset() 281 Calculate(&delta, base, target, -1) 282 283 resolved = NewReader( 284 bytes.NewReader(delta.Bytes()), 285 bytes.NewReader(base), 286 ) 287 val, err = ioutil.ReadAll(&resolved) 288 if err != nil { 289 t.Fatal(err) 290 } 291 if string(val) != string(target) { 292 t.Errorf("Unexpected delta resolution: got %v want %v", val, target) 293 } 294 }