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  }