github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/common/ledger/blockledger/fileledger/factory_test.go (about) 1 /* 2 Copyright hechain. 2022 All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package fileledger 8 9 import ( 10 "errors" 11 "fmt" 12 "io/ioutil" 13 "os" 14 "path/filepath" 15 "testing" 16 17 "github.com/hechain20/hechain/common/ledger/blockledger/fileledger/mock" 18 "github.com/hechain20/hechain/common/metrics/disabled" 19 "github.com/hechain20/hechain/orderer/common/filerepo" 20 "github.com/stretchr/testify/require" 21 ) 22 23 //go:generate counterfeiter -o mock/file_ledger_block_store.go --fake-name FileLedgerBlockStore . fileLedgerBlockStore 24 25 type fileLedgerBlockStore interface { 26 FileLedgerBlockStore 27 } 28 29 func TestBlockStoreProviderErrors(t *testing.T) { 30 setup := func(fileRepo *filerepo.Repo) (*fileLedgerFactory, *mock.BlockStoreProvider) { 31 m := &mock.BlockStoreProvider{} 32 33 f := &fileLedgerFactory{ 34 blkstorageProvider: m, 35 ledgers: map[string]*FileLedger{}, 36 removeFileRepo: fileRepo, 37 } 38 return f, m 39 } 40 41 t.Run("list", func(t *testing.T) { 42 f, mockBlockStoreProvider := setup(nil) 43 mockBlockStoreProvider.ListReturns(nil, errors.New("boogie")) 44 require.PanicsWithValue( 45 t, 46 "boogie", 47 func() { f.ChannelIDs() }, 48 "Expected ChannelIDs to panic if storage provider cannot list channel IDs", 49 ) 50 }) 51 52 t.Run("open", func(t *testing.T) { 53 f, mockBlockStoreProvider := setup(nil) 54 mockBlockStoreProvider.OpenReturns(nil, errors.New("woogie")) 55 _, err := f.GetOrCreate("foo") 56 require.EqualError(t, err, "woogie") 57 require.Empty(t, f.ledgers, "Expected no new ledger is created") 58 }) 59 60 t.Run("remove", func(t *testing.T) { 61 dir, err := ioutil.TempDir("", "fileledger") 62 require.NoError(t, err, "Error creating temp dir: %s", err) 63 defer os.RemoveAll(dir) 64 fileRepo, err := filerepo.New(filepath.Join(dir, "pendingops"), "remove") 65 require.NoError(t, err, "Error creating temp file repo: %s", err) 66 67 t.Run("ledger doesn't exist", func(t *testing.T) { 68 f, mockBlockStoreProvider := setup(fileRepo) 69 err := f.Remove("foo") 70 require.NoError(t, err) 71 require.Equal(t, 1, mockBlockStoreProvider.DropCallCount()) 72 channelID := mockBlockStoreProvider.DropArgsForCall(0) 73 require.Equal(t, "foo", channelID) 74 }) 75 76 t.Run("dropping the blockstore fails", func(t *testing.T) { 77 f, mockBlockStoreProvider := setup(fileRepo) 78 mockBlockStore := &mock.FileLedgerBlockStore{} 79 f.ledgers["bar"] = &FileLedger{blockStore: mockBlockStore} 80 mockBlockStoreProvider.DropReturns(errors.New("oogie")) 81 82 err := f.Remove("bar") 83 require.EqualError(t, err, "oogie") 84 require.Equal(t, 1, mockBlockStore.ShutdownCallCount()) 85 require.Equal(t, 1, mockBlockStoreProvider.DropCallCount()) 86 channelID := mockBlockStoreProvider.DropArgsForCall(0) 87 require.Equal(t, "bar", channelID) 88 }) 89 }) 90 } 91 92 func TestMultiReinitialization(t *testing.T) { 93 metricsProvider := &disabled.Provider{} 94 95 dir, err := ioutil.TempDir("", "fileledger") 96 require.NoError(t, err, "Error creating temp dir: %s", err) 97 defer os.RemoveAll(dir) 98 99 f, err := New(dir, metricsProvider) 100 require.NoError(t, err) 101 _, err = f.GetOrCreate("testchannelid") 102 require.NoError(t, err, "Error GetOrCreate channel") 103 require.Equal(t, 1, len(f.ChannelIDs()), "Expected 1 channel") 104 f.Close() 105 106 f, err = New(dir, metricsProvider) 107 require.NoError(t, err) 108 _, err = f.GetOrCreate("foo") 109 require.NoError(t, err, "Error creating channel") 110 require.Equal(t, 2, len(f.ChannelIDs()), "Expected channel to be recovered") 111 f.Close() 112 113 f, err = New(dir, metricsProvider) 114 require.NoError(t, err) 115 _, err = f.GetOrCreate("bar") 116 require.NoError(t, err, "Error creating channel") 117 require.Equal(t, 3, len(f.ChannelIDs()), "Expected channel to be recovered") 118 f.Close() 119 120 bar2FileRepoDir := filepath.Join(dir, "pendingops", "remove", "bar2.remove") 121 _, err = os.Create(bar2FileRepoDir) 122 require.NoError(t, err, "Error creating temp file: %s", err) 123 124 bar2ChainsDir := filepath.Join(dir, "chains", "bar2") 125 err = os.MkdirAll(bar2ChainsDir, 0o700) 126 require.NoError(t, err, "Error creating temp dir: %s", err) 127 _, err = os.Create(filepath.Join(bar2ChainsDir, "blockfile_000000")) 128 require.NoError(t, err, "Error creating temp file: %s", err) 129 130 f, err = New(dir, metricsProvider) 131 require.NoError(t, err) 132 133 err = f.Remove("bar") 134 require.NoError(t, err, "Error removing channel") 135 require.Equal(t, 2, len(f.ChannelIDs())) 136 err = f.Remove("this-isnt-an-existing-channel") 137 require.NoError(t, err, "Error removing channel") 138 require.Equal(t, 2, len(f.ChannelIDs())) 139 140 _, err = os.Stat(bar2ChainsDir) 141 require.EqualError(t, err, fmt.Sprintf("stat %s: no such file or directory", bar2ChainsDir)) 142 143 _, err = os.Stat(bar2FileRepoDir) 144 require.EqualError(t, err, fmt.Sprintf("stat %s: no such file or directory", bar2FileRepoDir)) 145 f.Close() 146 } 147 148 func TestNewErrors(t *testing.T) { 149 metricsProvider := &disabled.Provider{} 150 151 t.Run("creation of filerepo fails", func(t *testing.T) { 152 dir, err := ioutil.TempDir("", "fileledger") 153 require.NoError(t, err, "Error creating temp dir: %s", err) 154 defer os.RemoveAll(dir) 155 156 fileRepoDir := filepath.Join(dir, "pendingops", "remove") 157 err = os.MkdirAll(fileRepoDir, 0o700) 158 require.NoError(t, err, "Error creating temp dir: %s", err) 159 removeFile := filepath.Join(fileRepoDir, "rojo.remove") 160 _, err = os.Create(removeFile) 161 require.NoError(t, err, "Error creating temp file: %s", err) 162 err = os.Chmod(removeFile, 0o444) 163 require.NoError(t, err, "Error changing permissions of temp file: %s", err) 164 err = os.Chmod(filepath.Join(dir, "pendingops", "remove"), 0o444) 165 require.NoError(t, err, "Error changing permissions of temp file: %s", err) 166 167 _, err = New(dir, metricsProvider) 168 require.EqualError(t, err, fmt.Sprintf("error checking if dir [%s] is empty: lstat %s: permission denied", fileRepoDir, removeFile)) 169 }) 170 171 t.Run("removal fails", func(t *testing.T) { 172 dir, err := ioutil.TempDir("", "fileledger") 173 require.NoError(t, err, "Error creating temp dir: %s", err) 174 defer os.RemoveAll(dir) 175 176 fileRepoDir := filepath.Join(dir, "pendingops", "remove") 177 err = os.MkdirAll(fileRepoDir, 0o777) 178 require.NoError(t, err, "Error creating temp dir: %s", err) 179 removeFile := filepath.Join(fileRepoDir, "rojo.remove") 180 _, err = os.Create(removeFile) 181 require.NoError(t, err, "Error creating temp file: %s", err) 182 err = os.Chmod(removeFile, 0o444) 183 require.NoError(t, err, "Error changing permissions of temp file: %s", err) 184 err = os.Chmod(filepath.Join(dir, "pendingops", "remove"), 0o544) 185 require.NoError(t, err, "Error changing permissions of temp file: %s", err) 186 187 _, err = New(dir, metricsProvider) 188 require.EqualError(t, err, fmt.Sprintf("unlinkat %s: permission denied", removeFile)) 189 }) 190 } 191 192 func TestRemove(t *testing.T) { 193 mockBlockStore := &mock.BlockStoreProvider{} 194 dir, err := ioutil.TempDir("", "fileledger") 195 require.NoError(t, err, "Error creating temp dir: %s", err) 196 defer os.RemoveAll(dir) 197 198 fileRepo, err := filerepo.New(filepath.Join(dir, "pendingops"), "remove") 199 require.NoError(t, err, "Error creating temp file repo: %s", err) 200 f := &fileLedgerFactory{ 201 blkstorageProvider: mockBlockStore, 202 ledgers: map[string]*FileLedger{}, 203 removeFileRepo: fileRepo, 204 } 205 defer f.Close() 206 207 t.Run("success", func(t *testing.T) { 208 dest := filepath.Join(dir, "pendingops", "remove", "foo.remove") 209 mockBlockStore.DropCalls(func(string) error { 210 _, err = os.Stat(dest) 211 require.NoError(t, err, "Expected foo.remove to exist") 212 return nil 213 }) 214 err = f.Remove("foo") 215 require.NoError(t, err, "Error removing channel") 216 require.Equal(t, 1, mockBlockStore.DropCallCount(), "Expected 1 Drop() calls") 217 218 _, err = os.Stat(dest) 219 require.EqualError(t, err, fmt.Sprintf("stat %s: no such file or directory", dest)) 220 }) 221 222 t.Run("drop fails", func(t *testing.T) { 223 mockBlockStore.DropReturns(errors.New("oogie")) 224 err = f.Remove("foo") 225 require.EqualError(t, err, "oogie") 226 227 dest := filepath.Join(dir, "pendingops", "remove", "foo.remove") 228 _, err = os.Stat(dest) 229 require.NoError(t, err, "Expected foo.remove to exist") 230 }) 231 232 t.Run("saving to pending ops fails", func(t *testing.T) { 233 os.RemoveAll(dir) 234 mockBlockStore.DropReturns(nil) 235 err = f.Remove("foo") 236 require.EqualError(t, err, fmt.Sprintf("error while creating file:%s/pendingops/remove/foo.remove~: open %s/pendingops/remove/foo.remove~: no such file or directory", dir, dir)) 237 }) 238 }