github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/dbnode/persist/fs/msgpack/roundtrip_test.go (about)

     1  // Copyright (c) 2016 Uber Technologies, Inc
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE
    20  
    21  package msgpack
    22  
    23  import (
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/m3db/m3/src/dbnode/persist"
    28  	"github.com/m3db/m3/src/dbnode/persist/schema"
    29  	xtest "github.com/m3db/m3/src/x/test"
    30  	xhash "github.com/m3db/m3/src/x/test/hash"
    31  
    32  	"github.com/stretchr/testify/require"
    33  )
    34  
    35  var (
    36  	testIndexInfo = schema.IndexInfo{
    37  		BlockStart:   time.Now().UnixNano(),
    38  		BlockSize:    int64(2 * time.Hour),
    39  		Entries:      2000000,
    40  		MajorVersion: schema.MajorVersion,
    41  		Summaries: schema.IndexSummariesInfo{
    42  			Summaries: 123,
    43  		},
    44  		BloomFilter: schema.IndexBloomFilterInfo{
    45  			NumElementsM: 2075674,
    46  			NumHashesK:   7,
    47  		},
    48  		SnapshotTime: time.Now().UnixNano(),
    49  		FileType:     persist.FileSetSnapshotType,
    50  		SnapshotID:   []byte("some_bytes"),
    51  		VolumeIndex:  1,
    52  		MinorVersion: schema.MinorVersion,
    53  	}
    54  
    55  	testIndexEntryChecksum = int64(2611877657)
    56  	testIndexEntry         = schema.IndexEntry{
    57  		Index:         234,
    58  		ID:            []byte("testIndexEntry"),
    59  		Size:          5456,
    60  		Offset:        2390423,
    61  		DataChecksum:  134245634534,
    62  		IndexChecksum: testIndexEntryChecksum,
    63  		EncodedTags:   []byte("testEncodedTags"),
    64  	}
    65  
    66  	testIndexSummary = schema.IndexSummary{
    67  		Index:            234,
    68  		ID:               []byte("testIndexSummary"),
    69  		IndexEntryOffset: 2390423,
    70  	}
    71  
    72  	testLogInfo = schema.LogInfo{
    73  		Index: 234,
    74  	}
    75  
    76  	testLogEntry = schema.LogEntry{
    77  		Create:     time.Now().UnixNano(),
    78  		Index:      9345,
    79  		Metadata:   []byte("testMetadata"),
    80  		Timestamp:  time.Now().Add(time.Minute).UnixNano(),
    81  		Value:      903.234,
    82  		Unit:       9,
    83  		Annotation: []byte("testAnnotation"),
    84  	}
    85  
    86  	testLogMetadata = schema.LogMetadata{
    87  		ID:          []byte("testLogMetadata"),
    88  		Namespace:   []byte("testNamespace"),
    89  		Shard:       123,
    90  		EncodedTags: []byte("testLogMetadataTags"),
    91  	}
    92  )
    93  
    94  func TestIndexInfoRoundtrip(t *testing.T) {
    95  	var (
    96  		enc = NewEncoder()
    97  		dec = NewDecoder(nil)
    98  	)
    99  	require.NoError(t, enc.EncodeIndexInfo(testIndexInfo))
   100  	dec.Reset(NewByteDecoderStream(enc.Bytes()))
   101  	res, err := dec.DecodeIndexInfo()
   102  	require.NoError(t, err)
   103  	require.Equal(t, testIndexInfo, res)
   104  }
   105  
   106  // Make sure the V5 decoding code can handle the V1 file format.
   107  func TestIndexInfoRoundTripBackwardsCompatibilityV1(t *testing.T) {
   108  	var (
   109  		opts = LegacyEncodingOptions{EncodeLegacyIndexInfoVersion: LegacyEncodingIndexVersionV1}
   110  		enc  = newEncoder(opts)
   111  		dec  = newDecoder(opts, nil)
   112  	)
   113  
   114  	// Set the default values on the fields that did not exist in V1,
   115  	// as well as the fields that were added in versions after V1,
   116  	// and then restore them at the end of the test - This is required
   117  	// because the new decoder won't try and read the new fields from
   118  	// the old file format
   119  	var (
   120  		currSnapshotTime = testIndexInfo.SnapshotTime
   121  		currFileType     = testIndexInfo.FileType
   122  		currSnapshotID   = testIndexInfo.SnapshotID
   123  		currVolumeIndex  = testIndexInfo.VolumeIndex
   124  		currMinorVersion = testIndexInfo.MinorVersion
   125  	)
   126  	testIndexInfo.SnapshotTime = 0
   127  	testIndexInfo.FileType = 0
   128  	testIndexInfo.SnapshotID = nil
   129  	testIndexInfo.VolumeIndex = 0
   130  	testIndexInfo.MinorVersion = 0
   131  	defer func() {
   132  		testIndexInfo.SnapshotTime = currSnapshotTime
   133  		testIndexInfo.FileType = currFileType
   134  		testIndexInfo.SnapshotID = currSnapshotID
   135  		testIndexInfo.VolumeIndex = currVolumeIndex
   136  		testIndexInfo.MinorVersion = currMinorVersion
   137  	}()
   138  
   139  	enc.EncodeIndexInfo(testIndexInfo)
   140  	dec.Reset(NewByteDecoderStream(enc.Bytes()))
   141  	res, err := dec.DecodeIndexInfo()
   142  	require.NoError(t, err)
   143  	require.Equal(t, testIndexInfo, res)
   144  }
   145  
   146  // Make sure the V1 decoder code can handle the V5 file format.
   147  func TestIndexInfoRoundTripForwardsCompatibilityV1(t *testing.T) {
   148  	var (
   149  		opts = LegacyEncodingOptions{DecodeLegacyIndexInfoVersion: LegacyEncodingIndexVersionV1}
   150  		enc  = newEncoder(opts)
   151  		dec  = newDecoder(opts, nil)
   152  	)
   153  
   154  	// Set the default values on the fields that did not exist in V1
   155  	// and then restore them at the end of the test - This is required
   156  	// because the old decoder won't read the new fields
   157  	var (
   158  		currSnapshotTime = testIndexInfo.SnapshotTime
   159  		currFileType     = testIndexInfo.FileType
   160  		currSnapshotID   = testIndexInfo.SnapshotID
   161  		currVolumeIndex  = testIndexInfo.VolumeIndex
   162  		currMinorVersion = testIndexInfo.MinorVersion
   163  	)
   164  
   165  	enc.EncodeIndexInfo(testIndexInfo)
   166  
   167  	// Make sure to zero them before we compare, but after we have
   168  	// encoded the data
   169  	testIndexInfo.SnapshotTime = 0
   170  	testIndexInfo.FileType = 0
   171  	testIndexInfo.SnapshotID = nil
   172  	testIndexInfo.VolumeIndex = 0
   173  	testIndexInfo.MinorVersion = 0
   174  	defer func() {
   175  		testIndexInfo.SnapshotTime = currSnapshotTime
   176  		testIndexInfo.FileType = currFileType
   177  		testIndexInfo.SnapshotID = currSnapshotID
   178  		testIndexInfo.VolumeIndex = currVolumeIndex
   179  		testIndexInfo.MinorVersion = currMinorVersion
   180  	}()
   181  
   182  	dec.Reset(NewByteDecoderStream(enc.Bytes()))
   183  	res, err := dec.DecodeIndexInfo()
   184  	require.NoError(t, err)
   185  	require.Equal(t, testIndexInfo, res)
   186  }
   187  
   188  // Make sure the V5 decoding code can handle the V2 file format.
   189  func TestIndexInfoRoundTripBackwardsCompatibilityV2(t *testing.T) {
   190  	var (
   191  		opts = LegacyEncodingOptions{EncodeLegacyIndexInfoVersion: LegacyEncodingIndexVersionV2}
   192  		enc  = newEncoder(opts)
   193  		dec  = newDecoder(opts, nil)
   194  	)
   195  
   196  	// Set the default values on the fields that did not exist in V2,
   197  	// and then restore them at the end of the test - This is required
   198  	// because the new decoder won't try and read the new fields from
   199  	// the old file format.
   200  	var (
   201  		currSnapshotTime = testIndexInfo.SnapshotTime
   202  		currFileType     = testIndexInfo.FileType
   203  		currSnapshotID   = testIndexInfo.SnapshotID
   204  		currVolumeIndex  = testIndexInfo.VolumeIndex
   205  		currMinorVersion = testIndexInfo.MinorVersion
   206  	)
   207  	testIndexInfo.SnapshotTime = 0
   208  	testIndexInfo.FileType = 0
   209  	testIndexInfo.SnapshotID = nil
   210  	testIndexInfo.VolumeIndex = 0
   211  	testIndexInfo.MinorVersion = 0
   212  	defer func() {
   213  		testIndexInfo.SnapshotTime = currSnapshotTime
   214  		testIndexInfo.FileType = currFileType
   215  		testIndexInfo.SnapshotID = currSnapshotID
   216  		testIndexInfo.VolumeIndex = currVolumeIndex
   217  		testIndexInfo.MinorVersion = currMinorVersion
   218  	}()
   219  
   220  	enc.EncodeIndexInfo(testIndexInfo)
   221  	dec.Reset(NewByteDecoderStream(enc.Bytes()))
   222  	res, err := dec.DecodeIndexInfo()
   223  	require.NoError(t, err)
   224  	require.Equal(t, testIndexInfo, res)
   225  }
   226  
   227  // Make sure the V2 decoder code can handle the V5 file format.
   228  func TestIndexInfoRoundTripForwardsCompatibilityV2(t *testing.T) {
   229  	var (
   230  		opts = LegacyEncodingOptions{DecodeLegacyIndexInfoVersion: LegacyEncodingIndexVersionV2}
   231  		enc  = newEncoder(opts)
   232  		dec  = newDecoder(opts, nil)
   233  	)
   234  
   235  	// Set the default values on the fields that did not exist in V2
   236  	// and then restore them at the end of the test - This is required
   237  	// because the old decoder won't read the new fields.
   238  	currSnapshotID := testIndexInfo.SnapshotID
   239  	currVolumeIndex := testIndexInfo.VolumeIndex
   240  	currMinorVersion := testIndexInfo.MinorVersion
   241  
   242  	enc.EncodeIndexInfo(testIndexInfo)
   243  
   244  	// Make sure to zero them before we compare, but after we have
   245  	// encoded the data.
   246  	testIndexInfo.SnapshotID = nil
   247  	testIndexInfo.VolumeIndex = 0
   248  	testIndexInfo.MinorVersion = 0
   249  	defer func() {
   250  		testIndexInfo.SnapshotID = currSnapshotID
   251  		testIndexInfo.VolumeIndex = currVolumeIndex
   252  		testIndexInfo.MinorVersion = currMinorVersion
   253  	}()
   254  
   255  	dec.Reset(NewByteDecoderStream(enc.Bytes()))
   256  	res, err := dec.DecodeIndexInfo()
   257  	require.NoError(t, err)
   258  	require.Equal(t, testIndexInfo, res)
   259  }
   260  
   261  // Make sure the V5 decoding code can handle the V3 file format.
   262  func TestIndexInfoRoundTripBackwardsCompatibilityV3(t *testing.T) {
   263  	var (
   264  		opts = LegacyEncodingOptions{EncodeLegacyIndexInfoVersion: LegacyEncodingIndexVersionV3}
   265  		enc  = newEncoder(opts)
   266  		dec  = newDecoder(opts, nil)
   267  	)
   268  
   269  	// Set the default values on the fields that did not exist in V3,
   270  	// and then restore them at the end of the test - This is required
   271  	// because the new decoder won't try and read the new fields from
   272  	// the old file format.
   273  	var (
   274  		currVolumeIndex  = testIndexInfo.VolumeIndex
   275  		currMinorVersion = testIndexInfo.MinorVersion
   276  	)
   277  	testIndexInfo.VolumeIndex = 0
   278  	testIndexInfo.MinorVersion = 0
   279  	defer func() {
   280  		testIndexInfo.VolumeIndex = currVolumeIndex
   281  		testIndexInfo.MinorVersion = currMinorVersion
   282  	}()
   283  
   284  	enc.EncodeIndexInfo(testIndexInfo)
   285  	dec.Reset(NewByteDecoderStream(enc.Bytes()))
   286  	res, err := dec.DecodeIndexInfo()
   287  	require.NoError(t, err)
   288  	require.Equal(t, testIndexInfo, res)
   289  }
   290  
   291  // Make sure the V3 decoder code can handle the V5 file format.
   292  func TestIndexInfoRoundTripForwardsCompatibilityV3(t *testing.T) {
   293  	var (
   294  		opts = LegacyEncodingOptions{DecodeLegacyIndexInfoVersion: LegacyEncodingIndexVersionV3}
   295  		enc  = newEncoder(opts)
   296  		dec  = newDecoder(opts, nil)
   297  	)
   298  
   299  	// Set the default values on the fields that did not exist in V3
   300  	// and then restore them at the end of the test - This is required
   301  	// because the old decoder won't read the new fields.
   302  	currVolumeIndex := testIndexInfo.VolumeIndex
   303  	currMinorVersion := testIndexInfo.MinorVersion
   304  
   305  	enc.EncodeIndexInfo(testIndexInfo)
   306  
   307  	// Make sure to zero them before we compare, but after we have
   308  	// encoded the data.
   309  	testIndexInfo.VolumeIndex = 0
   310  	testIndexInfo.MinorVersion = 0
   311  	defer func() {
   312  		testIndexInfo.VolumeIndex = currVolumeIndex
   313  		testIndexInfo.MinorVersion = currMinorVersion
   314  	}()
   315  
   316  	dec.Reset(NewByteDecoderStream(enc.Bytes()))
   317  	res, err := dec.DecodeIndexInfo()
   318  	require.NoError(t, err)
   319  	require.Equal(t, testIndexInfo, res)
   320  }
   321  
   322  // Make sure the V5 decoding code can handle the V4 file format.
   323  func TestIndexInfoRoundTripBackwardsCompatibilityV4(t *testing.T) {
   324  	var (
   325  		opts = LegacyEncodingOptions{EncodeLegacyIndexInfoVersion: LegacyEncodingIndexVersionV4}
   326  		enc  = newEncoder(opts)
   327  		dec  = newDecoder(opts, nil)
   328  	)
   329  
   330  	// Set the default values on the fields that did not exist in V4,
   331  	// and then restore them at the end of the test - This is required
   332  	// because the new decoder won't try and read the new fields from
   333  	// the old file format.
   334  	currMinorVersion := testIndexInfo.MinorVersion
   335  
   336  	testIndexInfo.MinorVersion = 0
   337  	defer func() {
   338  		testIndexInfo.MinorVersion = currMinorVersion
   339  	}()
   340  
   341  	enc.EncodeIndexInfo(testIndexInfo)
   342  	dec.Reset(NewByteDecoderStream(enc.Bytes()))
   343  	res, err := dec.DecodeIndexInfo()
   344  	require.NoError(t, err)
   345  	require.Equal(t, testIndexInfo, res)
   346  }
   347  
   348  // Make sure the V4 decoder code can handle the V5 file format.
   349  func TestIndexInfoRoundTripForwardsCompatibilityV4(t *testing.T) {
   350  	var (
   351  		opts = LegacyEncodingOptions{DecodeLegacyIndexInfoVersion: LegacyEncodingIndexVersionV4}
   352  		enc  = newEncoder(opts)
   353  		dec  = newDecoder(opts, nil)
   354  	)
   355  
   356  	// Set the default values on the fields that did not exist in V4
   357  	// and then restore them at the end of the test - This is required
   358  	// because the old decoder won't read the new fields.
   359  	currMinorVersion := testIndexInfo.MinorVersion
   360  
   361  	enc.EncodeIndexInfo(testIndexInfo)
   362  
   363  	// Make sure to zero them before we compare, but after we have
   364  	// encoded the data.
   365  	testIndexInfo.MinorVersion = 0
   366  	defer func() {
   367  		testIndexInfo.MinorVersion = currMinorVersion
   368  	}()
   369  
   370  	dec.Reset(NewByteDecoderStream(enc.Bytes()))
   371  	res, err := dec.DecodeIndexInfo()
   372  	require.NoError(t, err)
   373  	require.Equal(t, testIndexInfo, res)
   374  }
   375  
   376  func TestIndexEntryRoundtrip(t *testing.T) {
   377  	var (
   378  		enc = NewEncoder()
   379  		dec = NewDecoder(nil)
   380  	)
   381  	require.NoError(t, enc.EncodeIndexEntry(testIndexEntry))
   382  	dec.Reset(NewByteDecoderStream(enc.Bytes()))
   383  	res, err := dec.DecodeIndexEntry(nil)
   384  	require.NoError(t, err)
   385  	require.Equal(t, testIndexEntry, res)
   386  }
   387  
   388  // Make sure the V3 decoding code can handle the V1 file format.
   389  func TestIndexEntryRoundTripBackwardsCompatibilityV1(t *testing.T) {
   390  	ctrl := xtest.NewController(t)
   391  	defer ctrl.Finish()
   392  
   393  	var (
   394  		opts = LegacyEncodingOptions{
   395  			EncodeLegacyIndexEntryVersion: LegacyEncodingIndexEntryVersionV1,
   396  			DecodeLegacyIndexEntryVersion: LegacyEncodingIndexEntryVersionCurrent}
   397  		enc = newEncoder(opts)
   398  		dec = newDecoder(opts, NewDecodingOptions().SetIndexEntryHasher(xhash.NewParsedIndexHasher(t)))
   399  	)
   400  
   401  	// Set the default values on the fields that did not exist in V1
   402  	// and then restore them at the end of the test - This is required
   403  	// because the new decoder won't try and read the new fields from
   404  	// the old file format.
   405  	currEncodedTags := testIndexEntry.EncodedTags
   406  
   407  	testIndexEntry.EncodedTags = nil
   408  
   409  	defer func() {
   410  		testIndexEntry.EncodedTags = currEncodedTags
   411  	}()
   412  
   413  	err := enc.EncodeIndexEntry(testIndexEntry)
   414  	require.NoError(t, err)
   415  
   416  	bytes := enc.Bytes()
   417  	dec.Reset(NewByteDecoderStream(bytes))
   418  	res, err := dec.DecodeIndexEntry(nil)
   419  	require.NoError(t, err)
   420  	expected := testIndexEntry
   421  	expected.IndexChecksum = 0
   422  	require.Equal(t, expected, res)
   423  }
   424  
   425  // Make sure the V1 decoder code can handle the V3 file format.
   426  func TestIndexEntryRoundTripForwardsCompatibilityV1(t *testing.T) {
   427  	ctrl := xtest.NewController(t)
   428  	defer ctrl.Finish()
   429  
   430  	var (
   431  		opts = LegacyEncodingOptions{
   432  			DecodeLegacyIndexEntryVersion: LegacyEncodingIndexEntryVersionV1}
   433  		enc = newEncoder(opts)
   434  		dec = newDecoder(opts, NewDecodingOptions().SetIndexEntryHasher(xhash.NewParsedIndexHasher(t)))
   435  	)
   436  
   437  	// Set the default values on the fields that did not exist in V1
   438  	// and then restore them at the end of the test - This is required
   439  	// because the old decoder won't read the new fields.
   440  	currEncodedTags := testIndexEntry.EncodedTags
   441  
   442  	err := enc.EncodeIndexEntry(testIndexEntry)
   443  	require.NoError(t, err)
   444  
   445  	// Make sure to zero them before we compare, but after we have
   446  	// encoded the data.
   447  	expected := testIndexEntry
   448  	expected.EncodedTags = nil
   449  	defer func() {
   450  		expected.EncodedTags = currEncodedTags
   451  	}()
   452  
   453  	dec.Reset(NewByteDecoderStream(enc.Bytes()))
   454  	res, err := dec.DecodeIndexEntry(nil)
   455  	require.NoError(t, err)
   456  
   457  	expected.IndexChecksum = 0
   458  	require.Equal(t, expected, res)
   459  }
   460  
   461  // Make sure the V3 decoding code can handle the V2 file format.
   462  func TestIndexEntryRoundTripBackwardsCompatibilityV2(t *testing.T) {
   463  	var (
   464  		opts = LegacyEncodingOptions{EncodeLegacyIndexEntryVersion: LegacyEncodingIndexEntryVersionV2,
   465  			DecodeLegacyIndexEntryVersion: LegacyEncodingIndexEntryVersionCurrent}
   466  		enc = newEncoder(opts)
   467  		dec = newDecoder(opts, NewDecodingOptions().SetIndexEntryHasher(xhash.NewParsedIndexHasher(t)))
   468  	)
   469  
   470  	// The additional field added to V3 is the index entry checksum that's transparently used by the encoder
   471  	// and decoder and is never set on the IndexEntry struct. Therefore, no need to zero out any field in the struct
   472  	// to make a comparison.
   473  
   474  	err := enc.EncodeIndexEntry(testIndexEntry)
   475  	require.NoError(t, err)
   476  	dec.Reset(NewByteDecoderStream(enc.Bytes()))
   477  	res, err := dec.DecodeIndexEntry(nil)
   478  	require.NoError(t, err)
   479  	expected := testIndexEntry
   480  	expected.IndexChecksum = 0
   481  	require.Equal(t, expected, res)
   482  }
   483  
   484  // Make sure the V2 decoder code can handle the V3 file format.
   485  func TestIndexEntryRoundTripForwardsCompatibilityV2(t *testing.T) {
   486  	var (
   487  		opts = LegacyEncodingOptions{DecodeLegacyIndexEntryVersion: LegacyEncodingIndexEntryVersionV2}
   488  		enc  = newEncoder(opts)
   489  		dec  = newDecoder(opts, NewDecodingOptions().SetIndexEntryHasher(xhash.NewParsedIndexHasher(t)))
   490  	)
   491  
   492  	// The additional field added to V3 is the index entry checksum that's transparently used by the encoder
   493  	// and decoder and is never set on the IndexEntry struct. Therefore, no need to zero out any field in the struct
   494  	// to make a comparison.
   495  
   496  	err := enc.EncodeIndexEntry(testIndexEntry)
   497  	require.NoError(t, err)
   498  	dec.Reset(NewByteDecoderStream(enc.Bytes()))
   499  	res, err := dec.DecodeIndexEntry(nil)
   500  	require.NoError(t, err)
   501  	expected := testIndexEntry
   502  	expected.IndexChecksum = 0
   503  	require.Equal(t, expected, res)
   504  }
   505  
   506  func TestIndexSummaryRoundtrip(t *testing.T) {
   507  	var (
   508  		enc = NewEncoder()
   509  		dec = NewDecoder(nil)
   510  	)
   511  	require.NoError(t, enc.EncodeIndexSummary(testIndexSummary))
   512  	dec.Reset(NewByteDecoderStream(enc.Bytes()))
   513  	res, _, err := dec.DecodeIndexSummary()
   514  	require.NoError(t, err)
   515  	require.Equal(t, testIndexSummary, res)
   516  }
   517  
   518  func TestLogInfoRoundtrip(t *testing.T) {
   519  	var (
   520  		enc = NewEncoder()
   521  		dec = NewDecoder(nil)
   522  	)
   523  	require.NoError(t, enc.EncodeLogInfo(testLogInfo))
   524  	dec.Reset(NewByteDecoderStream(enc.Bytes()))
   525  	res, err := dec.DecodeLogInfo()
   526  	require.NoError(t, err)
   527  	require.Equal(t, testLogInfo, res)
   528  }
   529  
   530  func TestLogEntryRoundtrip(t *testing.T) {
   531  	var (
   532  		enc = NewEncoder()
   533  		dec = NewDecoder(nil)
   534  	)
   535  	require.NoError(t, enc.EncodeLogEntry(testLogEntry))
   536  	dec.Reset(NewByteDecoderStream(enc.Bytes()))
   537  	res, err := dec.DecodeLogEntry()
   538  	require.NoError(t, err)
   539  	require.Equal(t, testLogEntry, res)
   540  }
   541  
   542  func TestLogEntryRoundtripUniqueIndexAndRemaining(t *testing.T) {
   543  	var (
   544  		enc = NewEncoder()
   545  		dec = NewDecoder(nil)
   546  	)
   547  	require.NoError(t, enc.EncodeLogEntry(testLogEntry))
   548  	dec.Reset(NewByteDecoderStream(enc.Bytes()))
   549  	create, idx, err := dec.DecodeLogEntryUniqueIndex()
   550  	require.NoError(t, err)
   551  
   552  	res, err := dec.DecodeLogEntryRemaining(create, idx)
   553  	require.NoError(t, err)
   554  
   555  	res.Index = idx
   556  	require.Equal(t, testLogEntry, res)
   557  }
   558  
   559  func TestLogMetadataRoundtrip(t *testing.T) {
   560  	var (
   561  		enc = NewEncoder()
   562  		dec = NewDecoder(nil)
   563  	)
   564  	require.NoError(t, enc.EncodeLogMetadata(testLogMetadata))
   565  	dec.Reset(NewByteDecoderStream(enc.Bytes()))
   566  	res, err := dec.DecodeLogMetadata()
   567  	require.NoError(t, err)
   568  	require.Equal(t, testLogMetadata, res)
   569  }
   570  
   571  func TestMultiTypeRoundtripStress(t *testing.T) {
   572  	var (
   573  		enc      = NewEncoder()
   574  		hasher   = xhash.NewParsedIndexHasher(t)
   575  		dec      = NewDecoder(NewDecodingOptions().SetIndexEntryHasher(hasher))
   576  		iter     = 10000
   577  		res      interface{}
   578  		err      error
   579  		expected []interface{}
   580  		output   []interface{}
   581  	)
   582  	for i := 0; i < iter; i++ {
   583  		switch i % 5 {
   584  		case 0:
   585  			require.NoError(t, enc.EncodeIndexInfo(testIndexInfo))
   586  			expected = append(expected, testIndexInfo)
   587  		case 1:
   588  			require.NoError(t, enc.EncodeIndexEntry(testIndexEntry))
   589  			expected = append(expected, testIndexEntry)
   590  		case 2:
   591  			require.NoError(t, enc.EncodeLogInfo(testLogInfo))
   592  			expected = append(expected, testLogInfo)
   593  		case 3:
   594  			require.NoError(t, enc.EncodeLogEntry(testLogEntry))
   595  			expected = append(expected, testLogEntry)
   596  		case 4:
   597  			require.NoError(t, enc.EncodeLogMetadata(testLogMetadata))
   598  			expected = append(expected, testLogMetadata)
   599  		}
   600  	}
   601  
   602  	dec.Reset(NewByteDecoderStream(enc.Bytes()))
   603  	for i := 0; i < iter; i++ {
   604  		switch i % 5 {
   605  		case 0:
   606  			res, err = dec.DecodeIndexInfo()
   607  		case 1:
   608  			res, err = dec.DecodeIndexEntry(nil)
   609  		case 2:
   610  			res, err = dec.DecodeLogInfo()
   611  		case 3:
   612  			res, err = dec.DecodeLogEntry()
   613  		case 4:
   614  			res, err = dec.DecodeLogMetadata()
   615  		}
   616  		require.NoError(t, err)
   617  		output = append(output, res)
   618  	}
   619  
   620  	require.Equal(t, expected, output)
   621  }