github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/compress/zlib/writer_test.go (about) 1 // Copyright 2009 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 zlib 6 7 import ( 8 "bytes" 9 "fmt" 10 "internal/testenv" 11 "io" 12 "os" 13 "testing" 14 ) 15 16 var filenames = []string{ 17 "../testdata/gettysburg.txt", 18 "../testdata/e.txt", 19 "../testdata/pi.txt", 20 } 21 22 var data = []string{ 23 "test a reasonable sized string that can be compressed", 24 } 25 26 // Tests that compressing and then decompressing the given file at the given compression level and dictionary 27 // yields equivalent bytes to the original file. 28 func testFileLevelDict(t *testing.T, fn string, level int, d string) { 29 // Read the file, as golden output. 30 golden, err := os.Open(fn) 31 if err != nil { 32 t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err) 33 return 34 } 35 defer golden.Close() 36 b0, err0 := io.ReadAll(golden) 37 if err0 != nil { 38 t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err0) 39 return 40 } 41 testLevelDict(t, fn, b0, level, d) 42 } 43 44 func testLevelDict(t *testing.T, fn string, b0 []byte, level int, d string) { 45 // Make dictionary, if given. 46 var dict []byte 47 if d != "" { 48 dict = []byte(d) 49 } 50 51 // Push data through a pipe that compresses at the write end, and decompresses at the read end. 52 piper, pipew := io.Pipe() 53 defer piper.Close() 54 go func() { 55 defer pipew.Close() 56 zlibw, err := NewWriterLevelDict(pipew, level, dict) 57 if err != nil { 58 t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err) 59 return 60 } 61 defer zlibw.Close() 62 _, err = zlibw.Write(b0) 63 if err != nil { 64 t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err) 65 return 66 } 67 }() 68 zlibr, err := NewReaderDict(piper, dict) 69 if err != nil { 70 t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err) 71 return 72 } 73 defer zlibr.Close() 74 75 // Compare the decompressed data. 76 b1, err1 := io.ReadAll(zlibr) 77 if err1 != nil { 78 t.Errorf("%s (level=%d, dict=%q): %v", fn, level, d, err1) 79 return 80 } 81 if len(b0) != len(b1) { 82 t.Errorf("%s (level=%d, dict=%q): length mismatch %d versus %d", fn, level, d, len(b0), len(b1)) 83 return 84 } 85 for i := 0; i < len(b0); i++ { 86 if b0[i] != b1[i] { 87 t.Errorf("%s (level=%d, dict=%q): mismatch at %d, 0x%02x versus 0x%02x\n", fn, level, d, i, b0[i], b1[i]) 88 return 89 } 90 } 91 } 92 93 func testFileLevelDictReset(t *testing.T, fn string, level int, dict []byte) { 94 var b0 []byte 95 var err error 96 if fn != "" { 97 b0, err = os.ReadFile(fn) 98 if err != nil { 99 t.Errorf("%s (level=%d): %v", fn, level, err) 100 return 101 } 102 } 103 104 // Compress once. 105 buf := new(bytes.Buffer) 106 var zlibw *Writer 107 if dict == nil { 108 zlibw, err = NewWriterLevel(buf, level) 109 } else { 110 zlibw, err = NewWriterLevelDict(buf, level, dict) 111 } 112 if err == nil { 113 _, err = zlibw.Write(b0) 114 } 115 if err == nil { 116 err = zlibw.Close() 117 } 118 if err != nil { 119 t.Errorf("%s (level=%d): %v", fn, level, err) 120 return 121 } 122 out := buf.String() 123 124 // Reset and compress again. 125 buf2 := new(bytes.Buffer) 126 zlibw.Reset(buf2) 127 _, err = zlibw.Write(b0) 128 if err == nil { 129 err = zlibw.Close() 130 } 131 if err != nil { 132 t.Errorf("%s (level=%d): %v", fn, level, err) 133 return 134 } 135 out2 := buf2.String() 136 137 if out2 != out { 138 t.Errorf("%s (level=%d): different output after reset (got %d bytes, expected %d", 139 fn, level, len(out2), len(out)) 140 } 141 } 142 143 func TestWriter(t *testing.T) { 144 for i, s := range data { 145 b := []byte(s) 146 tag := fmt.Sprintf("#%d", i) 147 testLevelDict(t, tag, b, DefaultCompression, "") 148 testLevelDict(t, tag, b, NoCompression, "") 149 testLevelDict(t, tag, b, HuffmanOnly, "") 150 for level := BestSpeed; level <= BestCompression; level++ { 151 testLevelDict(t, tag, b, level, "") 152 } 153 } 154 } 155 156 func TestWriterBig(t *testing.T) { 157 for i, fn := range filenames { 158 testFileLevelDict(t, fn, DefaultCompression, "") 159 testFileLevelDict(t, fn, NoCompression, "") 160 testFileLevelDict(t, fn, HuffmanOnly, "") 161 for level := BestSpeed; level <= BestCompression; level++ { 162 testFileLevelDict(t, fn, level, "") 163 if level >= 1 && testing.Short() && testenv.Builder() == "" { 164 break 165 } 166 } 167 if i == 0 && testing.Short() && testenv.Builder() == "" { 168 break 169 } 170 } 171 } 172 173 func TestWriterDict(t *testing.T) { 174 const dictionary = "0123456789." 175 for i, fn := range filenames { 176 testFileLevelDict(t, fn, DefaultCompression, dictionary) 177 testFileLevelDict(t, fn, NoCompression, dictionary) 178 testFileLevelDict(t, fn, HuffmanOnly, dictionary) 179 for level := BestSpeed; level <= BestCompression; level++ { 180 testFileLevelDict(t, fn, level, dictionary) 181 if level >= 1 && testing.Short() && testenv.Builder() == "" { 182 break 183 } 184 } 185 if i == 0 && testing.Short() && testenv.Builder() == "" { 186 break 187 } 188 } 189 } 190 191 func TestWriterReset(t *testing.T) { 192 const dictionary = "0123456789." 193 for _, fn := range filenames { 194 testFileLevelDictReset(t, fn, NoCompression, nil) 195 testFileLevelDictReset(t, fn, DefaultCompression, nil) 196 testFileLevelDictReset(t, fn, HuffmanOnly, nil) 197 testFileLevelDictReset(t, fn, NoCompression, []byte(dictionary)) 198 testFileLevelDictReset(t, fn, DefaultCompression, []byte(dictionary)) 199 testFileLevelDictReset(t, fn, HuffmanOnly, []byte(dictionary)) 200 if testing.Short() { 201 break 202 } 203 for level := BestSpeed; level <= BestCompression; level++ { 204 testFileLevelDictReset(t, fn, level, nil) 205 } 206 } 207 } 208 209 func TestWriterDictIsUsed(t *testing.T) { 210 var input = []byte("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.") 211 var buf bytes.Buffer 212 compressor, err := NewWriterLevelDict(&buf, BestCompression, input) 213 if err != nil { 214 t.Errorf("error in NewWriterLevelDict: %s", err) 215 return 216 } 217 compressor.Write(input) 218 compressor.Close() 219 const expectedMaxSize = 25 220 output := buf.Bytes() 221 if len(output) > expectedMaxSize { 222 t.Errorf("result too large (got %d, want <= %d bytes). Is the dictionary being used?", len(output), expectedMaxSize) 223 } 224 }