Source file src/compress/bzip2/bzip2_test.go

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package bzip2
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/hex"
    10  	"fmt"
    11  	"internal/obscuretestdata"
    12  	"io"
    13  	"os"
    14  	"strings"
    15  	"testing"
    16  )
    17  
    18  func mustDecodeHex(s string) []byte {
    19  	b, err := hex.DecodeString(s)
    20  	if err != nil {
    21  		panic(err)
    22  	}
    23  	return b
    24  }
    25  
    26  func mustLoadFile(f string) []byte {
    27  	if strings.HasSuffix(f, ".base64") {
    28  		tf, err := obscuretestdata.DecodeToTempFile(f)
    29  		if err != nil {
    30  			panic(fmt.Sprintf("obscuretestdata.DecodeToTempFile(%s): %v", f, err))
    31  		}
    32  		f = tf
    33  	}
    34  
    35  	b, err := os.ReadFile(f)
    36  	if err != nil {
    37  		panic(err)
    38  	}
    39  	return b
    40  }
    41  
    42  func trim(b []byte) string {
    43  	const limit = 1024
    44  	if len(b) < limit {
    45  		return fmt.Sprintf("%q", b)
    46  	}
    47  	return fmt.Sprintf("%q...", b[:limit])
    48  }
    49  
    50  func TestReader(t *testing.T) {
    51  	var vectors = []struct {
    52  		desc   string
    53  		input  []byte
    54  		output []byte
    55  		fail   bool
    56  	}{{
    57  		desc: "hello world",
    58  		input: mustDecodeHex("" +
    59  			"425a68393141592653594eece83600000251800010400006449080200031064c" +
    60  			"4101a7a9a580bb9431f8bb9229c28482776741b0",
    61  		),
    62  		output: []byte("hello world\n"),
    63  	}, {
    64  		desc: "concatenated files",
    65  		input: mustDecodeHex("" +
    66  			"425a68393141592653594eece83600000251800010400006449080200031064c" +
    67  			"4101a7a9a580bb9431f8bb9229c28482776741b0425a68393141592653594eec" +
    68  			"e83600000251800010400006449080200031064c4101a7a9a580bb9431f8bb92" +
    69  			"29c28482776741b0",
    70  		),
    71  		output: []byte("hello world\nhello world\n"),
    72  	}, {
    73  		desc: "32B zeros",
    74  		input: mustDecodeHex("" +
    75  			"425a6839314159265359b5aa5098000000600040000004200021008283177245" +
    76  			"385090b5aa5098",
    77  		),
    78  		output: make([]byte, 32),
    79  	}, {
    80  		desc: "1MiB zeros",
    81  		input: mustDecodeHex("" +
    82  			"425a683931415926535938571ce50008084000c0040008200030cc0529a60806" +
    83  			"c4201e2ee48a70a12070ae39ca",
    84  		),
    85  		output: make([]byte, 1<<20),
    86  	}, {
    87  		desc:   "random data",
    88  		input:  mustLoadFile("testdata/pass-random1.bz2"),
    89  		output: mustLoadFile("testdata/pass-random1.bin"),
    90  	}, {
    91  		desc:   "random data - full symbol range",
    92  		input:  mustLoadFile("testdata/pass-random2.bz2"),
    93  		output: mustLoadFile("testdata/pass-random2.bin"),
    94  	}, {
    95  		desc: "random data - uses RLE1 stage",
    96  		input: mustDecodeHex("" +
    97  			"425a6839314159265359d992d0f60000137dfe84020310091c1e280e100e0428" +
    98  			"01099210094806c0110002e70806402000546034000034000000f28300000320" +
    99  			"00d3403264049270eb7a9280d308ca06ad28f6981bee1bf8160727c7364510d7" +
   100  			"3a1e123083421b63f031f63993a0f40051fbf177245385090d992d0f60",
   101  		),
   102  		output: mustDecodeHex("" +
   103  			"92d5652616ac444a4a04af1a8a3964aca0450d43d6cf233bd03233f4ba92f871" +
   104  			"9e6c2a2bd4f5f88db07ecd0da3a33b263483db9b2c158786ad6363be35d17335" +
   105  			"ba",
   106  		),
   107  	}, {
   108  		desc:  "1MiB sawtooth",
   109  		input: mustLoadFile("testdata/pass-sawtooth.bz2"),
   110  		output: func() []byte {
   111  			b := make([]byte, 1<<20)
   112  			for i := range b {
   113  				b[i] = byte(i)
   114  			}
   115  			return b
   116  		}(),
   117  	}, {
   118  		desc:  "RLE2 buffer overrun - issue 5747",
   119  		input: mustLoadFile("testdata/fail-issue5747.bz2.base64"),
   120  		fail:  true,
   121  	}, {
   122  		desc: "out-of-range selector - issue 8363",
   123  		input: mustDecodeHex("" +
   124  			"425a68393141592653594eece83600000251800010400006449080200031064c" +
   125  			"4101a7a9a580bb943117724538509000000000",
   126  		),
   127  		fail: true,
   128  	}, {
   129  		desc: "bad block size - issue 13941",
   130  		input: mustDecodeHex("" +
   131  			"425a683131415926535936dc55330063ffc0006000200020a40830008b0008b8" +
   132  			"bb9229c28481b6e2a998",
   133  		),
   134  		fail: true,
   135  	}, {
   136  		desc: "bad huffman delta",
   137  		input: mustDecodeHex("" +
   138  			"425a6836314159265359b1f7404b000000400040002000217d184682ee48a70a" +
   139  			"12163ee80960",
   140  		),
   141  		fail: true,
   142  	}}
   143  
   144  	for i, v := range vectors {
   145  		rd := NewReader(bytes.NewReader(v.input))
   146  		buf, err := io.ReadAll(rd)
   147  
   148  		if fail := bool(err != nil); fail != v.fail {
   149  			if fail {
   150  				t.Errorf("test %d (%s), unexpected failure: %v", i, v.desc, err)
   151  			} else {
   152  				t.Errorf("test %d (%s), unexpected success", i, v.desc)
   153  			}
   154  		}
   155  		if !v.fail && !bytes.Equal(buf, v.output) {
   156  			t.Errorf("test %d (%s), output mismatch:\ngot  %s\nwant %s", i, v.desc, trim(buf), trim(v.output))
   157  		}
   158  	}
   159  }
   160  
   161  func TestBitReader(t *testing.T) {
   162  	var vectors = []struct {
   163  		nbits uint // Number of bits to read
   164  		value int  // Expected output value (0 for error)
   165  		fail  bool // Expected operation failure?
   166  	}{
   167  		{nbits: 1, value: 1},
   168  		{nbits: 1, value: 0},
   169  		{nbits: 1, value: 1},
   170  		{nbits: 5, value: 11},
   171  		{nbits: 32, value: 0x12345678},
   172  		{nbits: 15, value: 14495},
   173  		{nbits: 3, value: 6},
   174  		{nbits: 6, value: 13},
   175  		{nbits: 1, fail: true},
   176  	}
   177  
   178  	rd := bytes.NewReader([]byte{0xab, 0x12, 0x34, 0x56, 0x78, 0x71, 0x3f, 0x8d})
   179  	br := newBitReader(rd)
   180  	for i, v := range vectors {
   181  		val := br.ReadBits(v.nbits)
   182  		if fail := bool(br.err != nil); fail != v.fail {
   183  			if fail {
   184  				t.Errorf("test %d, unexpected failure: ReadBits(%d) = %v", i, v.nbits, br.err)
   185  			} else {
   186  				t.Errorf("test %d, unexpected success: ReadBits(%d) = nil", i, v.nbits)
   187  			}
   188  		}
   189  		if !v.fail && val != v.value {
   190  			t.Errorf("test %d, mismatching value: ReadBits(%d) = %d, want %d", i, v.nbits, val, v.value)
   191  		}
   192  	}
   193  }
   194  
   195  func TestMTF(t *testing.T) {
   196  	var vectors = []struct {
   197  		idx int   // Input index
   198  		sym uint8 // Expected output symbol
   199  	}{
   200  		{idx: 1, sym: 1}, // [1 0 2 3 4]
   201  		{idx: 0, sym: 1}, // [1 0 2 3 4]
   202  		{idx: 1, sym: 0}, // [0 1 2 3 4]
   203  		{idx: 4, sym: 4}, // [4 0 1 2 3]
   204  		{idx: 1, sym: 0}, // [0 4 1 2 3]
   205  	}
   206  
   207  	mtf := newMTFDecoderWithRange(5)
   208  	for i, v := range vectors {
   209  		sym := mtf.Decode(v.idx)
   210  		t.Log(mtf)
   211  		if sym != v.sym {
   212  			t.Errorf("test %d, symbol mismatch: Decode(%d) = %d, want %d", i, v.idx, sym, v.sym)
   213  		}
   214  	}
   215  }
   216  
   217  func TestZeroRead(t *testing.T) {
   218  	b := mustDecodeHex("425a6839314159265359b5aa5098000000600040000004200021008283177245385090b5aa5098")
   219  	r := NewReader(bytes.NewReader(b))
   220  	if n, err := r.Read(nil); n != 0 || err != nil {
   221  		t.Errorf("Read(nil) = (%d, %v), want (0, nil)", n, err)
   222  	}
   223  }
   224  
   225  var (
   226  	digits = mustLoadFile("testdata/e.txt.bz2")
   227  	newton = mustLoadFile("testdata/Isaac.Newton-Opticks.txt.bz2")
   228  	random = mustLoadFile("testdata/random.data.bz2")
   229  )
   230  
   231  func benchmarkDecode(b *testing.B, compressed []byte) {
   232  	// Determine the uncompressed size of testfile.
   233  	uncompressedSize, err := io.Copy(io.Discard, NewReader(bytes.NewReader(compressed)))
   234  	if err != nil {
   235  		b.Fatal(err)
   236  	}
   237  
   238  	b.SetBytes(uncompressedSize)
   239  	b.ReportAllocs()
   240  	b.ResetTimer()
   241  
   242  	for i := 0; i < b.N; i++ {
   243  		r := bytes.NewReader(compressed)
   244  		io.Copy(io.Discard, NewReader(r))
   245  	}
   246  }
   247  
   248  func BenchmarkDecodeDigits(b *testing.B) { benchmarkDecode(b, digits) }
   249  func BenchmarkDecodeNewton(b *testing.B) { benchmarkDecode(b, newton) }
   250  func BenchmarkDecodeRand(b *testing.B)   { benchmarkDecode(b, random) }
   251  

View as plain text