func TestEOFBehavior(T *testing.T) { input := []byte{1, 2, 3, 4} output := make([]byte, len(input)*12) params := enc.NewBrotliParams() params.SetQuality(4) output, err := enc.CompressBuffer(params, input, output) if err != nil { T.Fatal(err) } // Decompress as a stream reader := NewBrotliReader(bytes.NewReader(output)) receiver := make([]byte, len(input)) readBytes, err := reader.Read(receiver) if err != nil { T.Fatal(err) } if readBytes != len(input) { T.Fatalf("Expected to read %d bytes, read %d", len(input), readBytes) } }
func init() { RegisterEncoder(FormatBrotli, "cgo", func(w io.Writer, lvl int) io.WriteCloser { c := enc.NewBrotliParams() c.SetQuality(lvl) return enc.NewBrotliWriter(c, w) }) RegisterDecoder(FormatBrotli, "cgo", func(r io.Reader) io.ReadCloser { return dec.NewBrotliReaderSize(r, 4096) }) }
func main() { // Configure flags flag.StringVar(&compress, "c", "", "compress a file") flag.StringVar(&decompress, "d", "", "decompress a file") flag.StringVar(&output, "o", "", "output file") flag.IntVar(&quality, "q", 9, "compression quality (1-11)") flag.Parse() // Read input var input string if compress != "" { input = compress } else if decompress != "" { input = decompress } else { log.Fatal("You must specify either compress or decompress") } inputData, err := ioutil.ReadFile(input) if err != nil { log.Fatal(err) } // Perform compression or decompression var outputData []byte if compress != "" { params := enc.NewBrotliParams() params.SetQuality(quality) outputData, err = enc.CompressBuffer(params, inputData, nil) } else if decompress != "" { outputData, err = dec.DecompressBuffer(inputData, nil) } if err != nil { log.Fatal(err) } // Write output if output == "" { if compress != "" { output = input + ".bro" } else if decompress != "" { output = input + ".unbro" } } err = ioutil.WriteFile(output, outputData, 0666) if err != nil { log.Fatal(err) } }
// Run roundtrip tests from Brotli repository func TestRoundtrip(T *testing.T) { inputs := []string{ "testdata/alice29.txt", "testdata/asyoulik.txt", "testdata/lcet10.txt", "testdata/plrabn12.txt", "enc/encode.cc", "shared/dictionary.h", "dec/decode.c", } for _, file := range inputs { var err error var input []byte input, err = ioutil.ReadFile(file) if err != nil { T.Error(err) } for _, quality := range []int{1, 6, 9, 11} { T.Logf("Roundtrip testing %s at quality %d", file, quality) params := enc.NewBrotliParams() params.SetQuality(quality) bro := testCompressBuffer(params, input, T) testDecompressBuffer(input, bro, T) testDecompressStream(input, bytes.NewReader(bro), T) // Stream compress buffer := new(bytes.Buffer) testCompressStream(params, input, buffer, T) testDecompressBuffer(input, buffer.Bytes(), T) // Stream roundtrip reader, writer := io.Pipe() go testCompressStream(params, input, writer, T) testDecompressStream(input, reader, T) } } }
func testCompress(s []byte, T *testing.T) { T.Logf("Compressing: %s\n", s) params := enc.NewBrotliParams() buffer1 := make([]byte, len(s)*2) encoded, cerr := enc.CompressBuffer(params, s, buffer1) if cerr != nil { T.Error(cerr) } buffer2 := make([]byte, len(s)) decoded, derr := dec.DecompressBuffer(encoded, buffer2) if derr != nil { T.Error(derr) } if !bytes.Equal(s, decoded) { T.Logf("Decompressed: %s\n", decoded) T.Error("Decoded output does not match original input") } }
func compressFile(inFileName string, outFileName string, level int, verbose bool, standardOutput bool) { var buffer [1024 * 1024 * 32]byte var inFile *os.File var err error if inFileName == "-" { fmt.Printf("Using stdin!\n") inFile = os.Stdin } else { inFile, err = os.Open(inFileName) checkError(err) } defer inFile.Close() var outFile *os.File if !standardOutput { outFile, err = os.Create(outFileName) checkError(err) } else { outFile = os.Stdout } defer outFile.Close() hasher := NewHashWriter() archiveWriter := NewArchiveWriter(hasher, outFile) teeReader := io.TeeReader(inFile, hasher) params := enc.NewBrotliParams() params.SetQuality(level) params.SetLgwin(24) brotliWriter := enc.NewBrotliWriter(params, archiveWriter) defer brotliWriter.Close() // Perform the actual compression io.CopyBuffer(brotliWriter, teeReader, buffer[:]) defer os.Remove(inFileName) }
func TestStreamDecompression(T *testing.T) { input1 := bytes.Repeat([]byte("The quick brown fox jumps over the lazy dog. "), 100000) output1 := make([]byte, len(input1)*2) params := enc.NewBrotliParams() params.SetQuality(4) _, err := enc.CompressBuffer(params, input1, output1) if err != nil { T.Fatal(err) } // Decompress as a stream reader := NewBrotliReader(bytes.NewReader(output1)) decoded := make([]byte, len(input1)) read, err := io.ReadFull(reader, decoded) if err != nil { T.Fatal(err) } if read != len(input1) { T.Errorf("Length of decoded stream (%d) doesn't match input (%d)", read, len(input1)) } T.Logf("Input: %s", input1[:50]) T.Logf("Output: %s", decoded[:50]) if !bytes.Equal(decoded, input1) { T.Error("Decoded output does not match original input") } // Decompress using a shorter buffer reader = NewBrotliReader(bytes.NewReader(output1)) decoded = make([]byte, 500) read, err = reader.Read(decoded) if err != nil { T.Fatal(err) } if read != len(decoded) { T.Errorf("Length of decoded stream (%d) shorter than requested (%d)", read, len(decoded)) } T.Logf("Input: %s", input1[:50]) T.Logf("Output: %s", decoded[:50]) if !bytes.Equal(decoded, input1[:len(decoded)]) { T.Error("Decoded output does not match original input") } // Read next buffer read, err = reader.Read(decoded) if err != nil { T.Fatal(err) } if read != len(decoded) { T.Errorf("Length of decoded stream (%d) shorter than requested (%d)", read, len(decoded)) } T.Logf("Input: %s", input1[len(decoded):len(decoded)+50]) T.Logf("Output: %s", decoded[:50]) if !bytes.Equal(decoded, input1[len(decoded):2*len(decoded)]) { T.Error("Decoded output does not match original input") } }
func (bc *brotliCompressor) Apply(writer io.Writer, quality int32) (io.Writer, error) { params := enc.NewBrotliParams() params.SetQuality(int(quality)) return enc.NewBrotliWriter(params, writer), nil }