github.com/nikandfor/tlog@v0.21.3/tlz/compress_test.go (about) 1 package tlz 2 3 import ( 4 "bytes" 5 "encoding/hex" 6 "flag" 7 "io" 8 "io/ioutil" 9 "testing" 10 11 //"github.com/nikandfor/assert" 12 "github.com/nikandfor/errors" 13 "github.com/stretchr/testify/assert" 14 15 "github.com/nikandfor/tlog" 16 "github.com/nikandfor/tlog/low" 17 "github.com/nikandfor/tlog/tlio" 18 "github.com/nikandfor/tlog/tlwire" 19 ) 20 21 var fileFlag = flag.String("test-file", "../log.tlog", "file with tlog logs") 22 23 var ( 24 testData []byte 25 testOff []int 26 testsCount int 27 ) 28 29 func TestLiteral(t *testing.T) { 30 const B = 32 31 32 var buf low.Buf 33 34 w := newEncoder(&buf, B, 1) 35 36 n, err := w.Write([]byte("very_first_message")) 37 assert.Equal(t, 18, n) 38 assert.NoError(t, err) 39 40 t.Logf("buf pos %x ht %x\n%v", w.pos, w.ht, hex.Dump(w.block)) 41 t.Logf("res\n%v", Dump(buf)) 42 t.Logf("res\n%v", hex.Dump(buf)) 43 44 r := &Decoder{ 45 b: buf, 46 } 47 48 p := make([]byte, 100) 49 50 t.Logf("*** read back ***") 51 52 n, err = r.Read(p[:10]) 53 assert.Equal(t, 10, n) 54 assert.NoError(t, err) 55 assert.Equal(t, []byte("very_first"), p[:n]) 56 57 copy(p[:10], zeros) 58 59 n, err = r.Read(p[:10]) 60 assert.Equal(t, 8, n) 61 assert.Equal(t, io.EOF, err) 62 assert.Equal(t, []byte("_message"), p[:n]) 63 } 64 65 func TestCopy(t *testing.T) { 66 const B = 32 67 68 var buf low.Buf 69 70 w := newEncoder(&buf, B, 1) 71 72 st := 0 73 74 n, err := w.Write([]byte("prefix_1234_suffix")) 75 assert.Equal(t, 18, n) 76 assert.NoError(t, err) 77 78 t.Logf("buf pos %x ht %x\n%v", w.pos, w.ht, hex.Dump(w.block)) 79 t.Logf("res\n%v", hex.Dump(buf[st:])) 80 81 st = len(buf) 82 83 n, err = w.Write([]byte("prefix_567_suffix")) 84 assert.Equal(t, 17, n) 85 assert.NoError(t, err) 86 87 t.Logf("buf pos %x ht %x\n%v", w.pos, w.ht, hex.Dump(w.block)) 88 t.Logf("res\n%v", hex.Dump(buf[st:])) 89 90 r := &Decoder{ 91 b: buf, 92 } 93 94 p := make([]byte, 100) 95 96 t.Logf("*** read back ***") 97 98 n, err = r.Read(p[:10]) 99 assert.Equal(t, 10, n) 100 assert.NoError(t, err) 101 assert.Equal(t, []byte("prefix_123"), p[:n]) 102 103 t.Logf("buf pos %x\n%v", r.pos, hex.Dump(r.block)) 104 105 n, err = r.Read(p[:10]) 106 assert.Equal(t, 10, n) 107 assert.NoError(t, err) 108 assert.Equal(t, []byte("4_suffixpr"), p[:n]) 109 110 t.Logf("buf pos %x\n%v", r.pos, hex.Dump(r.block)) 111 112 n, err = r.Read(p[:30]) 113 assert.Equal(t, 15, n) 114 assert.Equal(t, io.EOF, err) 115 assert.Equal(t, []byte("efix_567_suffix"), p[:n]) 116 117 t.Logf("buf pos %x\n%v", r.pos, hex.Dump(r.block)) 118 119 // t.Logf("compression ratio: %.3f", float64(18+17)/float64(len(buf))) 120 } 121 122 func TestDumpOnelineText(t *testing.T) { 123 t.Skip() 124 125 var dump, text low.Buf 126 127 d := NewDumper(&dump) 128 e := newEncoder(d, 1*1024, 2) 129 130 cw := tlog.NewConsoleWriter(tlio.NewMultiWriter(e, &text), tlog.LstdFlags) 131 132 l := tlog.New(cw) 133 tr := l.Start("span_name") 134 135 types := []string{"type_a", "value_b", "qweqew", "asdads"} 136 137 for i := 0; i < 20; i++ { 138 // tr := l.Start("span_name") 139 tr.Printw("some example message", "i", i, "type", types[i%len(types)]) 140 // tr.Finish() 141 } 142 143 t.Logf("text:\n%s", text) 144 t.Logf("dump:\n%s", dump) 145 } 146 147 func TestBug1(t *testing.T) { 148 // tl = tlog.NewTestLogger(t, "", nil) 149 // tlog.DefaultLogger = tl 150 151 var b bytes.Buffer 152 153 p := make([]byte, 1000) 154 d := NewDecoder(&b) 155 156 // tl.Printw("first") 157 158 _, _ = b.Write([]byte{Literal | Meta, MetaReset, 4}) 159 _, _ = b.Write([]byte{Literal | 3, 0x94, 0xa8, 0xfb, Copy | 9}) 160 161 n, err := d.Read(p) 162 assert.ErrorIs(t, err, io.ErrUnexpectedEOF) 163 assert.Equal(t, 3, n) 164 165 // tl.Printw("second") 166 167 _, _ = b.Write([]byte{0xfd, 0x03, 0x65}) // offset 168 169 n, err = d.Read(p) 170 assert.ErrorIs(t, err, io.EOF) 171 assert.Equal(t, 9, n) 172 } 173 174 func TestOnFile(t *testing.T) { 175 err := loadTestFile(t, *fileFlag) 176 if err != nil { 177 t.Skipf("loading data: %v", err) 178 } 179 180 var encoded bytes.Buffer 181 var full bytes.Buffer 182 w := NewEncoderHTSize(tlio.NewMultiWriter(&encoded, &full), 512, 256) 183 r := NewDecoder(&encoded) 184 var buf []byte 185 186 // dumper := tlwire.NewDumper(os.Stderr) 187 188 for i := 0; i < testsCount; i++ { 189 msg := testData[testOff[i]:testOff[i+1]] 190 191 // _, _ = dumper.Write(msg) 192 193 n, err := w.Write(msg) 194 assert.NoError(t, err) 195 assert.Equal(t, len(msg), n) 196 197 for n > len(buf) { 198 buf = append(buf[:cap(buf)], 0, 0, 0, 0, 0, 0, 0, 0) 199 } 200 201 n, err = r.Read(buf[:n]) 202 assert.NoError(t, err) 203 assert.Equal(t, len(msg), n) 204 205 assert.Equal(t, msg, []byte(buf[:n])) 206 207 if t.Failed() { 208 break 209 } 210 } 211 212 r.Reset(&full) 213 buf = buf[:0] 214 215 var dec bytes.Buffer 216 217 n, err := io.Copy(&dec, r) 218 assert.NoError(t, err) 219 assert.Equal(t, int(n), dec.Len()) 220 221 min := dec.Len() 222 assert.Equal(t, testData[:min], dec.Bytes()) 223 224 // t.Logf("metrics: %v bytes %v events %v", mm, dec.Len(), testsCount) 225 } 226 227 func BenchmarkLogCompressOneline(b *testing.B) { 228 b.ReportAllocs() 229 230 var buf low.Buf 231 w := NewEncoder(&buf, 128*1024) 232 var c tlio.CountingIODiscard 233 234 l := tlog.New(io.MultiWriter(w, &c)) 235 tr := l.Start("span_name") 236 237 types := []string{"type_a", "value_b", "qweqew", "asdads"} 238 239 for i := 0; i < b.N; i++ { 240 // tr := l.Start("span_name") 241 tr.Printw("some example message", "i", i, "type", types[i%len(types)]) 242 // tr.Finish() 243 } 244 245 b.SetBytes(c.Bytes.Load() / int64(b.N)) 246 247 b.ReportMetric(float64(c.Bytes.Load())/float64(len(buf)), "ratio") 248 } 249 250 func BenchmarkLogCompressOnelineText(b *testing.B) { 251 b.ReportAllocs() 252 253 var buf low.Buf 254 w := NewEncoder(&buf, 128*1024) 255 var c tlio.CountingIODiscard 256 257 cw := tlog.NewConsoleWriter(io.MultiWriter(w, &c), tlog.LstdFlags) 258 259 l := tlog.New(cw) 260 tr := l.Start("span_name") 261 262 types := []string{"type_a", "value_b", "qweqew", "asdads"} 263 264 for i := 0; i < b.N; i++ { 265 // tr := l.Start("span_name") 266 tr.Printw("some example message", "i", i, "type", types[i%len(types)]) 267 // tr.Finish() 268 } 269 270 b.SetBytes(c.Bytes.Load() / int64(b.N)) 271 272 b.ReportMetric(float64(c.Bytes.Load())/float64(len(buf)), "ratio") 273 } 274 275 const BlockSize, HTSize = 1024 * 1024, 16 * 1024 276 277 func BenchmarkEncodeFile(b *testing.B) { 278 err := loadTestFile(b, *fileFlag) 279 if err != nil { 280 b.Skipf("loading data: %v", err) 281 } 282 283 b.ReportAllocs() 284 b.ResetTimer() 285 286 var c tlio.CountingIODiscard 287 w := NewEncoderHTSize(&c, BlockSize, HTSize) 288 289 // b.Logf("block %x ht %x (%x * %x)", len(w.block), len(w.ht)*int(unsafe.Sizeof(w.ht[0])), len(w.ht), unsafe.Sizeof(w.ht[0])) 290 291 written := 0 292 for i := 0; i < b.N; i++ { 293 j := i % testsCount 294 msg := testData[testOff[j]:testOff[j+1]] 295 296 n, err := w.Write(msg) 297 if err != nil { 298 b.Fatalf("write: %v", err) 299 } 300 if n != len(msg) { 301 b.Fatalf("write %v of %v", n, len(msg)) 302 } 303 304 written += n 305 } 306 307 // b.Logf("total written: %x %x", w.pos, w.pos/len(w.block)) 308 309 b.ReportMetric(float64(written)/float64(c.Bytes.Load()), "ratio") 310 // b.ReportMetric(float64(c.Operations)/float64(b.N), "writes/op") 311 b.SetBytes(int64(written / b.N)) 312 } 313 314 func BenchmarkDecodeFile(b *testing.B) { 315 err := loadTestFile(b, *fileFlag) 316 if err != nil { 317 b.Skipf("loading data: %v", err) 318 } 319 320 encoded := make(low.Buf, 0, len(testData)/2) 321 w := NewEncoderHTSize(&encoded, BlockSize, HTSize) 322 323 const limit = 20000 324 325 written := 0 326 for i := 0; i < testsCount && i < limit; i++ { 327 j := i % testsCount 328 msg := testData[testOff[j]:testOff[j+1]] 329 330 n, err := w.Write(msg) 331 if err != nil { 332 b.Fatalf("write: %v", err) 333 } 334 if n != len(msg) { 335 b.Fatalf("write %v of %v", n, len(msg)) 336 } 337 338 written += n 339 } 340 341 b.ReportAllocs() 342 b.ResetTimer() 343 344 b.ReportMetric(float64(written)/float64(len(encoded)), "ratio") 345 346 // var decoded []byte 347 decoded := make(low.Buf, 0, len(testData)) 348 buf := make([]byte, 4096) 349 r := NewDecoderBytes(encoded) 350 351 for i := 0; i < b.N/testsCount; i++ { 352 r.ResetBytes(encoded) 353 decoded = decoded[:0] 354 355 _, err = io.CopyBuffer(&decoded, r, buf) 356 assert.NoError(b, err) 357 } 358 359 // b.Logf("decoded %x", len(decoded)) 360 361 b.SetBytes(int64(decoded.Len() / testsCount)) 362 363 min := len(testData) 364 if min > decoded.Len() { 365 min = decoded.Len() 366 } 367 assert.Equal(b, testData[:min], decoded.Bytes()) 368 } 369 370 func loadTestFile(tb testing.TB, f string) (err error) { 371 tb.Helper() 372 373 if testData != nil { 374 return 375 } 376 377 testData, err = ioutil.ReadFile(f) 378 if err != nil { 379 return errors.Wrap(err, "open data file") 380 } 381 382 var d tlwire.Decoder 383 testOff = make([]int, 0, len(testData)/100) 384 385 var st int 386 for st < len(testData) { 387 testOff = append(testOff, st) 388 st = d.Skip(testData, st) 389 } 390 testsCount = len(testOff) 391 testOff = append(testOff, st) 392 393 tb.Logf("events loaded: %v", testsCount) 394 395 return 396 } 397 398 func FuzzEncoder(f *testing.F) { 399 f.Add( 400 []byte("prefix_1234_suffix"), 401 []byte("prefix_567_suffix"), 402 []byte("suffix_prefix"), 403 ) 404 405 f.Add( 406 []byte("aaaaaa"), 407 []byte("aaaaaaaaaaaa"), 408 []byte("aaaaaaaaaaaaaaaaaaaaaaaa"), 409 ) 410 411 f.Add( 412 []byte("aaaaab"), 413 []byte("aaaaabaaaaaa"), 414 []byte("aaaaaaaaaaabaaaaaaaaaaaa"), 415 ) 416 417 var ebuf, dbuf bytes.Buffer 418 buf := make([]byte, 16) 419 420 e := NewEncoderHTSize(&ebuf, 512, 32) 421 d := NewDecoder(&dbuf) 422 423 f.Fuzz(func(t *testing.T, p0, p1, p2 []byte) { 424 e.Reset(e.Writer) 425 ebuf.Reset() 426 427 for _, p := range [][]byte{p0, p1, p2} { 428 n, err := e.Write(p) 429 assert.NoError(t, err) 430 assert.Equal(t, len(p), n) 431 } 432 433 d.ResetBytes(ebuf.Bytes()) 434 dbuf.Reset() 435 436 m, err := io.CopyBuffer(&dbuf, d, buf) 437 assert.NoError(t, err) 438 assert.Equal(t, len(p0)+len(p1)+len(p2), int(m)) 439 440 i := 0 441 for _, p := range [][]byte{p0, p1, p2} { 442 assert.Equal(t, p, dbuf.Bytes()[i:i+len(p)]) 443 i += len(p) 444 } 445 446 assert.Equal(t, int(m), i) 447 448 if !t.Failed() { 449 return 450 } 451 452 for i, p := range [][]byte{p0, p1, p2} { 453 t.Logf("p%d\n%s", i, hex.Dump(p)) 454 } 455 456 t.Logf("encoded dump\n%s", Dump(ebuf.Bytes())) 457 }) 458 }