1package huff0 2 3import ( 4 "bytes" 5 "testing" 6) 7 8func TestDecompress1X(t *testing.T) { 9 for _, test := range testfiles { 10 t.Run(test.name, func(t *testing.T) { 11 var s = &Scratch{} 12 buf0, err := test.fn() 13 if err != nil { 14 t.Fatal(err) 15 } 16 if len(buf0) > BlockSizeMax { 17 buf0 = buf0[:BlockSizeMax] 18 } 19 b, re, err := Compress1X(buf0, s) 20 if err != test.err1X { 21 t.Errorf("want error %v (%T), got %v (%T)", test.err1X, test.err1X, err, err) 22 } 23 if err != nil { 24 t.Log(test.name, err.Error()) 25 return 26 } 27 if b == nil { 28 t.Error("got no output") 29 return 30 } 31 if len(s.OutTable) == 0 { 32 t.Error("got no table definition") 33 } 34 if re { 35 t.Error("claimed to have re-used.") 36 } 37 if len(s.OutData) == 0 { 38 t.Error("got no data output") 39 } 40 41 wantRemain := len(s.OutData) 42 t.Logf("%s: %d -> %d bytes (%.2f:1) %t (table: %d bytes)", test.name, len(buf0), len(b), float64(len(buf0))/float64(len(b)), re, len(s.OutTable)) 43 44 s.Out = nil 45 var remain []byte 46 s, remain, err = ReadTable(b, s) 47 if err != nil { 48 t.Error(err) 49 return 50 } 51 var buf bytes.Buffer 52 if s.matches(s.prevTable, &buf); buf.Len() > 0 { 53 t.Error(buf.String()) 54 } 55 if len(remain) != wantRemain { 56 t.Fatalf("remain mismatch, want %d, got %d bytes", wantRemain, len(remain)) 57 } 58 t.Logf("remain: %d bytes, ok", len(remain)) 59 dc, err := s.Decompress1X(remain) 60 if err != nil { 61 t.Error(err) 62 return 63 } 64 if len(buf0) != len(dc) { 65 t.Errorf(test.name+"decompressed, want size: %d, got %d", len(buf0), len(dc)) 66 if len(buf0) > len(dc) { 67 buf0 = buf0[:len(dc)] 68 } else { 69 dc = dc[:len(buf0)] 70 } 71 if !bytes.Equal(buf0, dc) { 72 if len(dc) > 1024 { 73 t.Log(string(dc[:1024])) 74 t.Errorf(test.name+"decompressed, got delta: \n(in)\t%02x !=\n(out)\t%02x\n", buf0[:1024], dc[:1024]) 75 } else { 76 t.Log(string(dc)) 77 t.Errorf(test.name+"decompressed, got delta: (in) %v != (out) %v\n", buf0, dc) 78 } 79 } 80 return 81 } 82 if !bytes.Equal(buf0, dc) { 83 if len(buf0) > 1024 { 84 t.Log(string(dc[:1024])) 85 } else { 86 t.Log(string(dc)) 87 } 88 //t.Errorf(test.name+": decompressed, got delta: \n%s") 89 t.Errorf(test.name + ": decompressed, got delta") 90 } 91 if !t.Failed() { 92 t.Log("... roundtrip ok!") 93 } 94 }) 95 } 96} 97 98func TestDecompress4X(t *testing.T) { 99 for _, test := range testfiles { 100 t.Run(test.name, func(t *testing.T) { 101 var s = &Scratch{} 102 buf0, err := test.fn() 103 if err != nil { 104 t.Fatal(err) 105 } 106 if len(buf0) > BlockSizeMax { 107 buf0 = buf0[:BlockSizeMax] 108 } 109 b, re, err := Compress4X(buf0, s) 110 if err != test.err4X { 111 t.Errorf("want error %v (%T), got %v (%T)", test.err1X, test.err1X, err, err) 112 } 113 if err != nil { 114 t.Log(test.name, err.Error()) 115 return 116 } 117 if b == nil { 118 t.Error("got no output") 119 return 120 } 121 if len(s.OutTable) == 0 { 122 t.Error("got no table definition") 123 } 124 if re { 125 t.Error("claimed to have re-used.") 126 } 127 if len(s.OutData) == 0 { 128 t.Error("got no data output") 129 } 130 131 wantRemain := len(s.OutData) 132 t.Logf("%s: %d -> %d bytes (%.2f:1) %t (table: %d bytes)", test.name, len(buf0), len(b), float64(len(buf0))/float64(len(b)), re, len(s.OutTable)) 133 134 s.Out = nil 135 var remain []byte 136 s, remain, err = ReadTable(b, s) 137 if err != nil { 138 t.Error(err) 139 return 140 } 141 var buf bytes.Buffer 142 if s.matches(s.prevTable, &buf); buf.Len() > 0 { 143 t.Error(buf.String()) 144 } 145 if len(remain) != wantRemain { 146 t.Fatalf("remain mismatch, want %d, got %d bytes", wantRemain, len(remain)) 147 } 148 t.Logf("remain: %d bytes, ok", len(remain)) 149 dc, err := s.Decompress4X(remain, len(buf0)) 150 if err != nil { 151 t.Error(err) 152 return 153 } 154 if len(buf0) != len(dc) { 155 t.Errorf(test.name+"decompressed, want size: %d, got %d", len(buf0), len(dc)) 156 if len(buf0) > len(dc) { 157 buf0 = buf0[:len(dc)] 158 } else { 159 dc = dc[:len(buf0)] 160 } 161 if !bytes.Equal(buf0, dc) { 162 if len(dc) > 1024 { 163 t.Log(string(dc[:1024])) 164 t.Errorf(test.name+"decompressed, got delta: \n(in)\t%02x !=\n(out)\t%02x\n", buf0[:1024], dc[:1024]) 165 } else { 166 t.Log(string(dc)) 167 t.Errorf(test.name+"decompressed, got delta: (in) %v != (out) %v\n", buf0, dc) 168 } 169 } 170 return 171 } 172 if !bytes.Equal(buf0, dc) { 173 if len(buf0) > 1024 { 174 t.Log(string(dc[:1024])) 175 } else { 176 t.Log(string(dc)) 177 } 178 //t.Errorf(test.name+": decompressed, got delta: \n%s") 179 t.Errorf(test.name + ": decompressed, got delta") 180 } 181 if !t.Failed() { 182 t.Log("... roundtrip ok!") 183 } 184 }) 185 } 186} 187 188func TestRoundtrip1XFuzz(t *testing.T) { 189 for _, test := range testfilesExtended { 190 t.Run(test.name, func(t *testing.T) { 191 var s = &Scratch{} 192 buf0, err := test.fn() 193 if err != nil { 194 t.Fatal(err) 195 } 196 if len(buf0) > BlockSizeMax { 197 buf0 = buf0[:BlockSizeMax] 198 } 199 b, re, err := Compress1X(buf0, s) 200 if err != nil { 201 if err == ErrIncompressible || err == ErrUseRLE || err == ErrTooBig { 202 t.Log(test.name, err.Error()) 203 return 204 } 205 t.Error(test.name, err.Error()) 206 return 207 } 208 if b == nil { 209 t.Error("got no output") 210 return 211 } 212 if len(s.OutTable) == 0 { 213 t.Error("got no table definition") 214 } 215 if re { 216 t.Error("claimed to have re-used.") 217 } 218 if len(s.OutData) == 0 { 219 t.Error("got no data output") 220 } 221 222 wantRemain := len(s.OutData) 223 t.Logf("%s: %d -> %d bytes (%.2f:1) %t (table: %d bytes)", test.name, len(buf0), len(b), float64(len(buf0))/float64(len(b)), re, len(s.OutTable)) 224 225 s.Out = nil 226 var remain []byte 227 s, remain, err = ReadTable(b, s) 228 if err != nil { 229 t.Error(err) 230 return 231 } 232 var buf bytes.Buffer 233 if s.matches(s.prevTable, &buf); buf.Len() > 0 { 234 t.Error(buf.String()) 235 } 236 if len(remain) != wantRemain { 237 t.Fatalf("remain mismatch, want %d, got %d bytes", wantRemain, len(remain)) 238 } 239 t.Logf("remain: %d bytes, ok", len(remain)) 240 dc, err := s.Decompress1X(remain) 241 if err != nil { 242 t.Error(err) 243 return 244 } 245 if len(buf0) != len(dc) { 246 t.Errorf(test.name+"decompressed, want size: %d, got %d", len(buf0), len(dc)) 247 if len(buf0) > len(dc) { 248 buf0 = buf0[:len(dc)] 249 } else { 250 dc = dc[:len(buf0)] 251 } 252 if !bytes.Equal(buf0, dc) { 253 if len(dc) > 1024 { 254 t.Log(string(dc[:1024])) 255 t.Errorf(test.name+"decompressed, got delta: \n(in)\t%02x !=\n(out)\t%02x\n", buf0[:1024], dc[:1024]) 256 } else { 257 t.Log(string(dc)) 258 t.Errorf(test.name+"decompressed, got delta: (in) %v != (out) %v\n", buf0, dc) 259 } 260 } 261 return 262 } 263 if !bytes.Equal(buf0, dc) { 264 if len(buf0) > 1024 { 265 t.Log(string(dc[:1024])) 266 } else { 267 t.Log(string(dc)) 268 } 269 //t.Errorf(test.name+": decompressed, got delta: \n%s") 270 t.Errorf(test.name + ": decompressed, got delta") 271 } 272 if !t.Failed() { 273 t.Log("... roundtrip ok!") 274 } 275 }) 276 } 277} 278 279func TestRoundtrip4XFuzz(t *testing.T) { 280 for _, test := range testfilesExtended { 281 t.Run(test.name, func(t *testing.T) { 282 var s = &Scratch{} 283 buf0, err := test.fn() 284 if err != nil { 285 t.Fatal(err) 286 } 287 if len(buf0) > BlockSizeMax { 288 buf0 = buf0[:BlockSizeMax] 289 } 290 b, re, err := Compress4X(buf0, s) 291 if err != nil { 292 if err == ErrIncompressible || err == ErrUseRLE || err == ErrTooBig { 293 t.Log(test.name, err.Error()) 294 return 295 } 296 t.Error(test.name, err.Error()) 297 return 298 } 299 if b == nil { 300 t.Error("got no output") 301 return 302 } 303 if len(s.OutTable) == 0 { 304 t.Error("got no table definition") 305 } 306 if re { 307 t.Error("claimed to have re-used.") 308 } 309 if len(s.OutData) == 0 { 310 t.Error("got no data output") 311 } 312 313 wantRemain := len(s.OutData) 314 t.Logf("%s: %d -> %d bytes (%.2f:1) %t (table: %d bytes)", test.name, len(buf0), len(b), float64(len(buf0))/float64(len(b)), re, len(s.OutTable)) 315 316 s.Out = nil 317 var remain []byte 318 s, remain, err = ReadTable(b, s) 319 if err != nil { 320 t.Error(err) 321 return 322 } 323 var buf bytes.Buffer 324 if s.matches(s.prevTable, &buf); buf.Len() > 0 { 325 t.Error(buf.String()) 326 } 327 if len(remain) != wantRemain { 328 t.Fatalf("remain mismatch, want %d, got %d bytes", wantRemain, len(remain)) 329 } 330 t.Logf("remain: %d bytes, ok", len(remain)) 331 dc, err := s.Decompress4X(remain, len(buf0)) 332 if err != nil { 333 t.Error(err) 334 return 335 } 336 if len(buf0) != len(dc) { 337 t.Errorf(test.name+"decompressed, want size: %d, got %d", len(buf0), len(dc)) 338 if len(buf0) > len(dc) { 339 buf0 = buf0[:len(dc)] 340 } else { 341 dc = dc[:len(buf0)] 342 } 343 if !bytes.Equal(buf0, dc) { 344 if len(dc) > 1024 { 345 t.Log(string(dc[:1024])) 346 t.Errorf(test.name+"decompressed, got delta: \n(in)\t%02x !=\n(out)\t%02x\n", buf0[:1024], dc[:1024]) 347 } else { 348 t.Log(string(dc)) 349 t.Errorf(test.name+"decompressed, got delta: (in) %v != (out) %v\n", buf0, dc) 350 } 351 } 352 return 353 } 354 if !bytes.Equal(buf0, dc) { 355 if len(buf0) > 1024 { 356 t.Log(string(dc[:1024])) 357 } else { 358 t.Log(string(dc)) 359 } 360 //t.Errorf(test.name+": decompressed, got delta: \n%s") 361 t.Errorf(test.name + ": decompressed, got delta") 362 } 363 if !t.Failed() { 364 t.Log("... roundtrip ok!") 365 } 366 }) 367 } 368} 369 370func BenchmarkDecompress1XTable(b *testing.B) { 371 for _, tt := range testfiles { 372 test := tt 373 if test.err1X != nil { 374 continue 375 } 376 b.Run(test.name, func(b *testing.B) { 377 var s = &Scratch{} 378 s.Reuse = ReusePolicyNone 379 buf0, err := test.fn() 380 if err != nil { 381 b.Fatal(err) 382 } 383 if len(buf0) > BlockSizeMax { 384 buf0 = buf0[:BlockSizeMax] 385 } 386 compressed, _, err := Compress1X(buf0, s) 387 if err != test.err1X { 388 b.Fatal("unexpected error:", err) 389 } 390 s.Out = nil 391 s, remain, _ := ReadTable(compressed, s) 392 s.Decompress1X(remain) 393 b.ResetTimer() 394 b.ReportAllocs() 395 b.SetBytes(int64(len(buf0))) 396 for i := 0; i < b.N; i++ { 397 s, remain, err := ReadTable(compressed, s) 398 if err != nil { 399 b.Fatal(err) 400 } 401 _, err = s.Decompress1X(remain) 402 if err != nil { 403 b.Fatal(err) 404 } 405 } 406 }) 407 } 408} 409 410func BenchmarkDecompress1XNoTable(b *testing.B) { 411 for _, tt := range testfiles { 412 test := tt 413 if test.err1X != nil { 414 continue 415 } 416 b.Run(test.name, func(b *testing.B) { 417 var s = &Scratch{} 418 s.Reuse = ReusePolicyNone 419 buf0, err := test.fn() 420 if err != nil { 421 b.Fatal(err) 422 } 423 if len(buf0) > BlockSizeMax { 424 buf0 = buf0[:BlockSizeMax] 425 } 426 compressed, _, err := Compress1X(buf0, s) 427 if err != test.err1X { 428 b.Fatal("unexpected error:", err) 429 } 430 s.Out = nil 431 s, remain, _ := ReadTable(compressed, s) 432 s.Decompress1X(remain) 433 b.ResetTimer() 434 b.ReportAllocs() 435 b.SetBytes(int64(len(buf0))) 436 for i := 0; i < b.N; i++ { 437 _, err = s.Decompress1X(remain) 438 if err != nil { 439 b.Fatal(err) 440 } 441 } 442 }) 443 } 444} 445 446func BenchmarkDecompress4XNoTable(b *testing.B) { 447 for _, tt := range testfiles { 448 test := tt 449 if test.err4X != nil { 450 continue 451 } 452 b.Run(test.name, func(b *testing.B) { 453 var s = &Scratch{} 454 s.Reuse = ReusePolicyNone 455 buf0, err := test.fn() 456 if err != nil { 457 b.Fatal(err) 458 } 459 if len(buf0) > BlockSizeMax { 460 buf0 = buf0[:BlockSizeMax] 461 } 462 compressed, _, err := Compress4X(buf0, s) 463 if err != test.err1X { 464 b.Fatal("unexpected error:", err) 465 } 466 s.Out = nil 467 s, remain, _ := ReadTable(compressed, s) 468 s.Decompress4X(remain, len(buf0)) 469 b.ResetTimer() 470 b.ReportAllocs() 471 b.SetBytes(int64(len(buf0))) 472 for i := 0; i < b.N; i++ { 473 _, err = s.Decompress4X(remain, len(buf0)) 474 if err != nil { 475 b.Fatal(err) 476 } 477 } 478 }) 479 } 480} 481 482func BenchmarkDecompress4XTable(b *testing.B) { 483 for _, tt := range testfiles { 484 test := tt 485 if test.err4X != nil { 486 continue 487 } 488 b.Run(test.name, func(b *testing.B) { 489 var s = &Scratch{} 490 s.Reuse = ReusePolicyNone 491 buf0, err := test.fn() 492 if err != nil { 493 b.Fatal(err) 494 } 495 if len(buf0) > BlockSizeMax { 496 buf0 = buf0[:BlockSizeMax] 497 } 498 compressed, _, err := Compress4X(buf0, s) 499 if err != test.err1X { 500 b.Fatal("unexpected error:", err) 501 } 502 s.Out = nil 503 b.ResetTimer() 504 b.ReportAllocs() 505 b.SetBytes(int64(len(buf0))) 506 for i := 0; i < b.N; i++ { 507 s, remain, err := ReadTable(compressed, s) 508 if err != nil { 509 b.Fatal(err) 510 } 511 _, err = s.Decompress4X(remain, len(buf0)) 512 if err != nil { 513 b.Fatal(err) 514 } 515 } 516 }) 517 } 518} 519