github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/orderer/common/bootstrap/file/bootstrap_test.go (about)

     1  // Copyright IBM Corp. All Rights Reserved.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package file_test
     5  
     6  import (
     7  	"io/ioutil"
     8  	"os"
     9  	"path"
    10  	"testing"
    11  
    12  	"github.com/golang/protobuf/proto"
    13  	cb "github.com/hyperledger/fabric-protos-go/common"
    14  	bootfile "github.com/osdi23p228/fabric/orderer/common/bootstrap/file"
    15  	"github.com/stretchr/testify/assert"
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  const file = "abc.genesis"
    20  const fileBak = file + ".bak"
    21  const fileFake = file + ".fake"
    22  
    23  func TestGenesisBlock(t *testing.T) {
    24  	testDir, err := ioutil.TempDir("", "unittest")
    25  	assert.NoErrorf(t, err, "generate temporary test dir")
    26  	defer os.RemoveAll(testDir)
    27  
    28  	testFile := path.Join(testDir, file)
    29  
    30  	testFileFake := path.Join(testDir, fileFake)
    31  
    32  	t.Run("Bad - No file", func(t *testing.T) {
    33  		assert.Panics(t, func() {
    34  			helper := bootfile.New(testFileFake)
    35  			_ = helper.GenesisBlock()
    36  		}, "No file")
    37  	})
    38  
    39  	t.Run("Bad - Malformed Block", func(t *testing.T) {
    40  		err := ioutil.WriteFile(testFile, []byte("abc"), 0644)
    41  		assert.NoErrorf(t, err, "generate temporary test file: %s", file)
    42  
    43  		assert.Panics(t, func() {
    44  			helper := bootfile.New(testFile)
    45  			_ = helper.GenesisBlock()
    46  		}, "Malformed Block")
    47  	})
    48  
    49  	t.Run("Correct flow", func(t *testing.T) {
    50  		//The original block and file
    51  		expectedNumber := uint64(0)
    52  		expectedBytes := []byte("abc")
    53  		expectedHash := []byte(nil)
    54  
    55  		header := &cb.BlockHeader{
    56  			Number:       expectedNumber,
    57  			PreviousHash: expectedHash,
    58  			DataHash:     expectedBytes,
    59  		}
    60  		data := &cb.BlockData{
    61  			Data: [][]byte{expectedBytes},
    62  		}
    63  		expectedDataLen := len(data.Data)
    64  		metadata := &cb.BlockMetadata{
    65  			Metadata: [][]byte{expectedBytes},
    66  		}
    67  		expectedMetaLen := len(metadata.Metadata)
    68  		block := &cb.Block{
    69  			Header:   header,
    70  			Data:     data,
    71  			Metadata: metadata,
    72  		}
    73  		marshalledBlock, _ := proto.Marshal(block)
    74  		err := ioutil.WriteFile(testFile, marshalledBlock, 0644)
    75  		assert.NoErrorf(t, err, "generate temporary test file: %s", file)
    76  		defer os.Remove(testFile)
    77  
    78  		helper := bootfile.New(testFile)
    79  		outBlock := helper.GenesisBlock()
    80  
    81  		outHeader := outBlock.Header
    82  		assert.Equal(t, expectedNumber, outHeader.Number, "block header Number not read correctly")
    83  		assert.Equal(t, expectedHash, outHeader.PreviousHash, "block header PreviousHash not read correctly")
    84  		assert.Equal(t, expectedBytes, outHeader.DataHash, "block header DataHash not read correctly")
    85  
    86  		outData := outBlock.Data
    87  		assert.Equal(t, expectedDataLen, len(outData.Data), "block len(data) not read correctly")
    88  		assert.Equal(t, expectedBytes, outData.Data[0], "block data not read correctly")
    89  
    90  		outMeta := outBlock.Metadata
    91  		assert.Equal(t, expectedMetaLen, len(outMeta.Metadata), "block len(Metadata) not read correctly")
    92  		assert.Equal(t, expectedBytes, outMeta.Metadata[0], "block Metadata not read correctly")
    93  	})
    94  }
    95  
    96  func TestReplaceGenesisBlockFile(t *testing.T) {
    97  	//The original block and file
    98  	expectedNumber := uint64(0)
    99  	expectedBytes := []byte("abc")
   100  	expectedHash := []byte(nil)
   101  	header := &cb.BlockHeader{
   102  		Number:       expectedNumber,
   103  		PreviousHash: expectedHash,
   104  		DataHash:     expectedBytes,
   105  	}
   106  	data := &cb.BlockData{
   107  		Data: [][]byte{expectedBytes},
   108  	}
   109  	metadata := &cb.BlockMetadata{
   110  		Metadata: [][]byte{expectedBytes},
   111  	}
   112  	block := &cb.Block{
   113  		Header:   header,
   114  		Data:     data,
   115  		Metadata: metadata,
   116  	}
   117  	marshalledBlock, _ := proto.Marshal(block)
   118  
   119  	testDir, err := ioutil.TempDir("", "unittest")
   120  	assert.NoErrorf(t, err, "generate temporary test dir")
   121  	defer os.RemoveAll(testDir)
   122  
   123  	testFile := path.Join(testDir, file)
   124  	err = ioutil.WriteFile(testFile, marshalledBlock, 0644)
   125  	assert.NoErrorf(t, err, "generate temporary test file: %s", file)
   126  
   127  	testFileBak := path.Join(testDir, fileBak)
   128  	testFileFake := path.Join(testDir, fileFake)
   129  
   130  	// The new block
   131  	expectedNumber2 := uint64(1)
   132  	expectedBytes2 := []byte("def")
   133  	expectedHash2 := []byte(nil)
   134  
   135  	header2 := &cb.BlockHeader{
   136  		Number:       expectedNumber2,
   137  		PreviousHash: expectedHash2,
   138  		DataHash:     expectedBytes2,
   139  	}
   140  	data2 := &cb.BlockData{
   141  		Data: [][]byte{expectedBytes2},
   142  	}
   143  	expectedDataLen2 := len(data2.Data)
   144  	metadata2 := &cb.BlockMetadata{
   145  		Metadata: [][]byte{expectedBytes2},
   146  	}
   147  	expectedMetaLen2 := len(metadata2.Metadata)
   148  	block2 := &cb.Block{
   149  		Header:   header2,
   150  		Data:     data2,
   151  		Metadata: metadata2,
   152  	}
   153  
   154  	t.Run("Good", func(t *testing.T) {
   155  		replacer := bootfile.NewReplacer(testFile)
   156  		errWr := replacer.CheckReadWrite()
   157  		require.NoErrorf(t, errWr, "Failed to verify writable: %s", testFile)
   158  
   159  		errRep := replacer.ReplaceGenesisBlockFile(block2)
   160  		defer os.Remove(testFileBak)
   161  		require.NoErrorf(t, errRep, "Failed to replace: %s", testFile)
   162  
   163  		helper := bootfile.New(testFile)
   164  		outBlock := helper.GenesisBlock()
   165  
   166  		outHeader := outBlock.Header
   167  		assert.Equal(t, expectedNumber2, outHeader.Number, "block header Number not read correctly.")
   168  		assert.Equal(t, []uint8([]byte(nil)), outHeader.PreviousHash, "block header PreviousHash not read correctly.")
   169  		assert.Equal(t, expectedBytes2, outHeader.DataHash, "block header DataHash not read correctly.")
   170  
   171  		outData := outBlock.Data
   172  		assert.Equal(t, expectedDataLen2, len(outData.Data), "block len(data) not read correctly.")
   173  		assert.Equal(t, expectedBytes2, outData.Data[0], "block data not read correctly.")
   174  
   175  		outMeta := outBlock.Metadata
   176  		assert.Equal(t, expectedMetaLen2, len(outMeta.Metadata), "block len(Metadata) not read correctly.")
   177  		assert.Equal(t, expectedBytes2, outMeta.Metadata[0], "block Metadata not read correctly.")
   178  	})
   179  
   180  	t.Run("Bad - No original", func(t *testing.T) {
   181  		replacer := bootfile.NewReplacer(testFileFake)
   182  		errWr := replacer.CheckReadWrite()
   183  		assert.Error(t, errWr, "no such file")
   184  		assert.Contains(t, errWr.Error(), "no such file or directory")
   185  
   186  		errRep := replacer.ReplaceGenesisBlockFile(block2)
   187  		assert.Error(t, errRep, "no such file")
   188  		assert.Contains(t, errRep.Error(), "no such file or directory")
   189  	})
   190  
   191  	t.Run("Bad - Not a regular file", func(t *testing.T) {
   192  		replacer := bootfile.NewReplacer(testDir)
   193  		errWr := replacer.CheckReadWrite()
   194  		assert.Error(t, errWr, "not a regular file")
   195  		assert.Contains(t, errWr.Error(), "not a regular file")
   196  
   197  		errRep := replacer.ReplaceGenesisBlockFile(block2)
   198  		assert.Error(t, errRep, "not a regular file")
   199  		assert.Contains(t, errRep.Error(), "not a regular file")
   200  	})
   201  
   202  	t.Run("Bad - backup not writable", func(t *testing.T) {
   203  		replacer := bootfile.NewReplacer(testFile)
   204  
   205  		_, err := os.Create(testFileBak)
   206  		defer os.Remove(testFileBak)
   207  		assert.NoErrorf(t, err, "Failed to create backup")
   208  		err = os.Chmod(testFileBak, 0400)
   209  		assert.NoErrorf(t, err, "Failed to change permission on backup")
   210  
   211  		err = replacer.ReplaceGenesisBlockFile(block2)
   212  		assert.Errorf(t, err, "Fail to replace, backup")
   213  		assert.Contains(t, err.Error(), "permission denied")
   214  		assert.Contains(t, err.Error(), "could not copy genesis block file")
   215  
   216  		err = os.Chmod(testFileBak, 0600)
   217  		assert.NoErrorf(t, err, "Failed to restore permission on backup")
   218  	})
   219  
   220  	t.Run("Bad - source not writable", func(t *testing.T) {
   221  		replacer := bootfile.NewReplacer(testFile)
   222  
   223  		errC := os.Chmod(testFile, 0400)
   224  		assert.NoErrorf(t, errC, "Failed to change permission on origin")
   225  
   226  		errWr := replacer.CheckReadWrite()
   227  		assert.Error(t, errWr, "not writable")
   228  		assert.Contains(t, errWr.Error(), "permission denied")
   229  		assert.Contains(t, errWr.Error(), "cannot be opened for read-write, check permissions")
   230  
   231  		errRep := replacer.ReplaceGenesisBlockFile(block2)
   232  		assert.Errorf(t, errRep, "Fail to replace, unwritable origin")
   233  		assert.Contains(t, errRep.Error(), "permission denied")
   234  		assert.Contains(t, errRep.Error(), "could not write new genesis block into file")
   235  		assert.Contains(t, errRep.Error(), "use backup if necessary")
   236  
   237  		err = os.Chmod(testFile, 0600)
   238  		assert.NoErrorf(t, err, "Failed to restore permission, origin")
   239  	})
   240  
   241  	t.Run("Bad - source not readable", func(t *testing.T) {
   242  		replacer := bootfile.NewReplacer(testFile)
   243  
   244  		errC := os.Chmod(testFile, 0200)
   245  		assert.NoErrorf(t, errC, "Failed to change permission on origin")
   246  
   247  		errWr := replacer.CheckReadWrite()
   248  		assert.Error(t, errWr, "not writable")
   249  		assert.Contains(t, errWr.Error(), "permission denied")
   250  		assert.Contains(t, errWr.Error(), "cannot be opened for read-write, check permissions")
   251  
   252  		errRep := replacer.ReplaceGenesisBlockFile(block2)
   253  		assert.Errorf(t, errRep, "Fail to replace, unwritable origin")
   254  		assert.Contains(t, errRep.Error(), "permission denied")
   255  		assert.Contains(t, errRep.Error(), "could not copy genesis block file")
   256  
   257  		err = os.Chmod(testFile, 0600)
   258  		assert.NoErrorf(t, err, "Failed to restore permission, origin")
   259  	})
   260  }