github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/data/bsplitter_simple_test.go (about)

     1  // Copyright 2016 Keybase Inc. All rights reserved.
     2  // Use of this source code is governed by a BSD
     3  // license that can be found in the LICENSE file.
     4  
     5  package data
     6  
     7  import (
     8  	"bytes"
     9  	"testing"
    10  
    11  	"github.com/keybase/client/go/kbfs/kbfscodec"
    12  	"github.com/keybase/client/go/kbfs/kbfscrypto"
    13  	"github.com/stretchr/testify/require"
    14  )
    15  
    16  func TestBsplitterEmptyCopyAll(t *testing.T) {
    17  	bsplit := &BlockSplitterSimple{10, 5, 10, 0}
    18  	fblock := NewFileBlock().(*FileBlock)
    19  	data := []byte{1, 2, 3, 4, 5}
    20  
    21  	if n := bsplit.CopyUntilSplit(fblock, false, data, 0); n != 5 {
    22  		t.Errorf("Did not copy expected number of bytes: %d", n)
    23  	} else if !bytes.Equal(fblock.Contents, data) {
    24  		t.Errorf("Wrong file contents after copy: %v", fblock.Contents)
    25  	}
    26  }
    27  
    28  func TestBsplitterNonemptyCopyAll(t *testing.T) {
    29  	bsplit := &BlockSplitterSimple{10, 5, 10, 0}
    30  	fblock := NewFileBlock().(*FileBlock)
    31  	fblock.Contents = []byte{10, 9}
    32  	data := []byte{1, 2, 3, 4, 5}
    33  
    34  	if n := bsplit.CopyUntilSplit(fblock, false, data, 0); n != 5 {
    35  		t.Errorf("Did not copy expected number of bytes: %d", n)
    36  	} else if !bytes.Equal(fblock.Contents, data) {
    37  		t.Errorf("Wrong file contents after copy: %v", fblock.Contents)
    38  	}
    39  }
    40  
    41  func TestBsplitterAppendAll(t *testing.T) {
    42  	bsplit := &BlockSplitterSimple{10, 5, 10, 0}
    43  	fblock := NewFileBlock().(*FileBlock)
    44  	fblock.Contents = []byte{10, 9}
    45  	data := []byte{1, 2, 3, 4, 5}
    46  
    47  	if n := bsplit.CopyUntilSplit(fblock, false, data, 2); n != 5 {
    48  		t.Errorf("Did not copy expected number of bytes: %d", n)
    49  	} else if !bytes.Equal(fblock.Contents, append([]byte{10, 9}, data...)) {
    50  		t.Errorf("Wrong file contents after copy: %v", fblock.Contents)
    51  	}
    52  }
    53  
    54  func TestBsplitterAppendExact(t *testing.T) {
    55  	bsplit := &BlockSplitterSimple{10, 5, 10, 0}
    56  	fblock := NewFileBlock().(*FileBlock)
    57  	fblock.Contents = []byte{10, 9, 8, 7, 6}
    58  	data := []byte{1, 2, 3, 4, 5}
    59  
    60  	if n := bsplit.CopyUntilSplit(fblock, false, data, 5); n != 5 {
    61  		t.Errorf("Did not copy expected number of bytes: %d", n)
    62  	} else if !bytes.Equal(fblock.Contents,
    63  		append([]byte{10, 9, 8, 7, 6}, data...)) {
    64  		t.Errorf("Wrong file contents after copy: %v", fblock.Contents)
    65  	}
    66  }
    67  
    68  func TestBsplitterSplitOne(t *testing.T) {
    69  	bsplit := &BlockSplitterSimple{10, 5, 10, 0}
    70  	fblock := NewFileBlock().(*FileBlock)
    71  	fblock.Contents = []byte{10, 9, 8, 7, 6}
    72  	data := []byte{1, 2, 3, 4, 5, 6}
    73  
    74  	if n := bsplit.CopyUntilSplit(fblock, false, data, 5); n != 5 {
    75  		t.Errorf("Did not copy expected number of bytes: %d", n)
    76  	} else if !bytes.Equal(fblock.Contents,
    77  		[]byte{10, 9, 8, 7, 6, 1, 2, 3, 4, 5}) {
    78  		t.Errorf("Wrong file contents after copy: %v", fblock.Contents)
    79  	}
    80  }
    81  
    82  func TestBsplitterOverwriteMaxSizeBlock(t *testing.T) {
    83  	bsplit := &BlockSplitterSimple{5, 5, 10, 0}
    84  	fblock := NewFileBlock().(*FileBlock)
    85  	fblock.Contents = []byte{10, 9, 8, 7, 6}
    86  	data := []byte{1, 2, 3, 4, 5, 6, 7, 8}
    87  
    88  	if n := bsplit.CopyUntilSplit(fblock, false, data, 0); n != 5 {
    89  		t.Errorf("Did not copy expected number of bytes: %d", n)
    90  	} else if !bytes.Equal(fblock.Contents, []byte{1, 2, 3, 4, 5}) {
    91  		t.Errorf("Wrong file contents after copy: %v", fblock.Contents)
    92  	}
    93  }
    94  
    95  func TestBsplitterBlockTooBig(t *testing.T) {
    96  	bsplit := &BlockSplitterSimple{3, 5, 10, 0}
    97  	fblock := NewFileBlock().(*FileBlock)
    98  	fblock.Contents = []byte{10, 9, 8, 7, 6}
    99  	data := []byte{1, 2, 3, 4, 5, 6}
   100  
   101  	if n := bsplit.CopyUntilSplit(fblock, false, data, 5); n != 0 {
   102  		t.Errorf("Did not copy expected number of bytes: %d", n)
   103  	} else if !bytes.Equal(fblock.Contents, []byte{10, 9, 8, 7, 6}) {
   104  		t.Errorf("Wrong file contents after copy: %v", fblock.Contents)
   105  	}
   106  }
   107  
   108  func TestBsplitterOffTooBig(t *testing.T) {
   109  	bsplit := &BlockSplitterSimple{10, 5, 10, 0}
   110  	fblock := NewFileBlock().(*FileBlock)
   111  	fblock.Contents = []byte{10, 9, 8, 7, 6}
   112  	data := []byte{1, 2, 3, 4, 5, 6}
   113  
   114  	if n := bsplit.CopyUntilSplit(fblock, false, data, 15); n != 0 {
   115  		t.Errorf("Did not copy expected number of bytes: %d", n)
   116  	} else if !bytes.Equal(fblock.Contents,
   117  		[]byte{10, 9, 8, 7, 6, 0, 0, 0, 0, 0}) {
   118  		t.Errorf("Wrong file contents after copy: %v", fblock.Contents)
   119  	}
   120  }
   121  
   122  func TestBsplitterShouldEmbed(t *testing.T) {
   123  	bsplit := &BlockSplitterSimple{10, 5, 10, 0}
   124  	if !bsplit.ShouldEmbedData(1) {
   125  		t.Errorf("Not embedding a 1-byte block change")
   126  	}
   127  	if !bsplit.ShouldEmbedData(10) {
   128  		t.Errorf("Not embedding a 10-byte block change")
   129  	}
   130  }
   131  
   132  func TestBsplitterShouldNotEmbed(t *testing.T) {
   133  	bsplit := &BlockSplitterSimple{10, 5, 10, 0}
   134  	if bsplit.ShouldEmbedData(11) {
   135  		t.Errorf("Not embedding a 1-byte block change")
   136  	}
   137  }
   138  
   139  func TestBsplitterOverhead(t *testing.T) {
   140  	codec := kbfscodec.NewMsgpack()
   141  	desiredBlockSize := int64(64 * 1024)
   142  	bsplit, err := NewBlockSplitterSimple(desiredBlockSize, 8*1024, codec)
   143  	if err != nil {
   144  		t.Fatalf("Got error making block splitter with overhead: %v", err)
   145  	}
   146  
   147  	// Test that an encoded, padded block matches this desired block size
   148  	block := NewFileBlock().(*FileBlock)
   149  	block.Contents = make([]byte, bsplit.maxSize)
   150  	for i := range block.Contents {
   151  		block.Contents[i] = byte(i)
   152  	}
   153  	encodedBlock, err := codec.Encode(block)
   154  	if err != nil {
   155  		t.Fatalf("Encoding block failed: %v", err)
   156  	}
   157  	paddedBlock, err := kbfscrypto.PadBlock(encodedBlock)
   158  	if err != nil {
   159  		t.Fatalf("Padding block failed: %v", err)
   160  	}
   161  	// first 4 bytes of the padded block encodes the block size
   162  	if g, e := int64(len(paddedBlock)), desiredBlockSize+4; g != e {
   163  		t.Fatalf("Padded block size %d doesn't match desired block size %d",
   164  			g, e)
   165  	}
   166  }
   167  
   168  func TestBsplitterSplitDir(t *testing.T) {
   169  	bsplit := &BlockSplitterSimple{10, 5, 10, 2}
   170  	dblock := NewDirBlock().(*DirBlock)
   171  	dblock.Children["a"] = DirEntry{}
   172  	dblock.Children["b"] = DirEntry{}
   173  	dblock.Children["c"] = DirEntry{}
   174  	dblock.Children["d"] = DirEntry{}
   175  	dblock.Children["e"] = DirEntry{}
   176  	dblock.Children["f"] = DirEntry{}
   177  
   178  	t.Log("Split an even block")
   179  	blocks, newOffset := bsplit.SplitDirIfNeeded(dblock)
   180  	require.Len(t, blocks, 2)
   181  	require.Equal(t, StringOffset("d"), *newOffset)
   182  	require.Len(t, blocks[0].Children, 3)
   183  	require.Contains(t, blocks[0].Children, "a")
   184  	require.Contains(t, blocks[0].Children, "b")
   185  	require.Contains(t, blocks[0].Children, "c")
   186  	require.Len(t, blocks[1].Children, 3)
   187  	require.Contains(t, blocks[1].Children, "d")
   188  	require.Contains(t, blocks[1].Children, "e")
   189  	require.Contains(t, blocks[1].Children, "f")
   190  
   191  	t.Log("Split odd blocks")
   192  	smallerBlocks, newOffset := bsplit.SplitDirIfNeeded(blocks[0])
   193  	require.Len(t, smallerBlocks, 2)
   194  	require.Equal(t, StringOffset("b"), *newOffset)
   195  	require.Len(t, smallerBlocks[0].Children, 1)
   196  	require.Contains(t, smallerBlocks[0].Children, "a")
   197  	require.Len(t, smallerBlocks[1].Children, 2)
   198  	require.Contains(t, smallerBlocks[1].Children, "b")
   199  	require.Contains(t, smallerBlocks[1].Children, "c")
   200  	smallerBlocks, newOffset = bsplit.SplitDirIfNeeded(blocks[1])
   201  	require.Len(t, smallerBlocks, 2)
   202  	require.Equal(t, StringOffset("e"), *newOffset)
   203  	require.Len(t, smallerBlocks[0].Children, 1)
   204  	require.Contains(t, smallerBlocks[0].Children, "d")
   205  	require.Len(t, smallerBlocks[1].Children, 2)
   206  	require.Contains(t, smallerBlocks[1].Children, "e")
   207  	require.Contains(t, smallerBlocks[1].Children, "f")
   208  
   209  	t.Log("Don't split small blocks")
   210  	noSplits, newOffset := bsplit.SplitDirIfNeeded(smallerBlocks[0])
   211  	require.Len(t, noSplits, 1)
   212  	require.Nil(t, newOffset)
   213  	require.Equal(t, smallerBlocks[0], noSplits[0])
   214  	noSplits, newOffset = bsplit.SplitDirIfNeeded(smallerBlocks[1])
   215  	require.Len(t, noSplits, 1)
   216  	require.Nil(t, newOffset)
   217  	require.Equal(t, smallerBlocks[1], noSplits[0])
   218  }