Skip to content

Commit f326f80

Browse files
guogerkchristidis
authored andcommitted
[FAB-4113] Improve UT coverage of orderer/ledger/json
Change-Id: I1880b6ac8933d22c986c8d599df5525e219d882e Signed-off-by: Jay Guo <[email protected]> Signed-off-by: Kostas Christidis <[email protected]>
1 parent b8ddc31 commit f326f80

File tree

2 files changed

+175
-8
lines changed

2 files changed

+175
-8
lines changed

orderer/ledger/json/factory.go

+4-8
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,10 @@ func (jlf *jsonLedgerFactory) GetOrCreate(chainID string) (ledger.ReadWriter, er
4747

4848
directory := filepath.Join(jlf.directory, fmt.Sprintf(chainDirectoryFormatString, chainID))
4949

50-
logger.Debugf("Initializing chain at: %s", directory)
50+
logger.Debugf("Initializing chain %s at: %s", chainID, directory)
5151

5252
if err := os.MkdirAll(directory, 0700); err != nil {
53+
logger.Warningf("Failed initializing chain %s: %s", chainID, err)
5354
return nil, err
5455
}
5556

@@ -130,7 +131,7 @@ func (jlf *jsonLedgerFactory) Close() {
130131
func New(directory string) ledger.Factory {
131132
logger.Debugf("Initializing ledger at: %s", directory)
132133
if err := os.MkdirAll(directory, 0700); err != nil {
133-
logger.Fatalf("Could not create directory %s: %s", directory, err)
134+
logger.Panicf("Could not create directory %s: %s", directory, err)
134135
}
135136

136137
jlf := &jsonLedgerFactory{
@@ -152,12 +153,7 @@ func New(directory string) ledger.Factory {
152153
if err != nil {
153154
continue
154155
}
155-
jl, err := jlf.GetOrCreate(chainID)
156-
if err != nil {
157-
logger.Warningf("Failed to initialize chain from %s: %s", chainID, err)
158-
continue
159-
}
160-
jlf.ledgers[chainID] = jl
156+
jlf.GetOrCreate(chainID)
161157
}
162158

163159
return jlf

orderer/ledger/json/factory_test.go

+171
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/*
2+
Copyright IBM Corp. 2016 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package jsonledger
18+
19+
import (
20+
"testing"
21+
22+
"fmt"
23+
"io/ioutil"
24+
"os"
25+
"path"
26+
27+
"github.com/hyperledger/fabric/common/configtx/tool/provisional"
28+
logging "github.com/op/go-logging"
29+
"github.com/stretchr/testify/assert"
30+
)
31+
32+
func init() {
33+
logging.SetLevel(logging.DEBUG, "")
34+
}
35+
36+
// Some tests are skipped because `os.Chmod` does not take effect in the CI. The call
37+
// itself does not fail, but file mod is not changed, which cause tests to fail.
38+
// TODO(jay_guo): re-enable skipped tests once we sort out this problem.
39+
40+
// This test checks that `New` factory should fail if parent directory is read-only
41+
func TestErrorMkdir(t *testing.T) {
42+
name, err := ioutil.TempDir("", "hyperledger_fabric")
43+
assert.Nil(t, err, "Error creating temp dir: %s", err)
44+
defer os.RemoveAll(name)
45+
ledgerPath := path.Join(name, "jsonledger")
46+
assert.NoError(t, ioutil.WriteFile(ledgerPath, nil, 0700))
47+
48+
assert.Panics(t, func() { New(ledgerPath) }, "Should have failed to create factory")
49+
}
50+
51+
// This test checks that `New` factory should fail if factory directory is not readable
52+
func TestErrorReadDir(t *testing.T) {
53+
t.Skip("Temporarily skip this test due to the reason stated at the top of this file")
54+
55+
name, err := ioutil.TempDir("", "hyperledger_fabric")
56+
assert.Nil(t, err, "Error creating temp dir: %s", err)
57+
defer os.RemoveAll(name)
58+
assert.Nil(t, os.Chmod(name, 0200), "Error chmod temp dir")
59+
defer os.Chmod(name, 0700)
60+
61+
assert.Panics(t, func() { New(name) }, "Should have failed to create factory")
62+
}
63+
64+
// This test checks that factory initialization should ignore dir with invalid name and files.
65+
// NOTE: unfortunately this test does not really test intended logic because errors caused by
66+
// constructing a chain from invalid dir or file are ignored anyway. Consider refactoring impl
67+
// to make it more testable.
68+
func TestIgnoreInvalidObjectInDir(t *testing.T) {
69+
name, err := ioutil.TempDir("", "hyperledger_fabric")
70+
assert.Nil(t, err, "Error creating temp dir: %s", err)
71+
defer os.RemoveAll(name)
72+
file, err := ioutil.TempFile(name, "chain_")
73+
assert.Nil(t, err, "Errot creating temp file: %s", err)
74+
defer file.Close()
75+
_, err = ioutil.TempDir(name, "invalid_chain_")
76+
assert.Nil(t, err, "Error creating temp dir: %s", err)
77+
78+
jlf := New(name)
79+
assert.Empty(t, jlf.ChainIDs(), "Expected invalid objects to be ignored while restoring chains from directory")
80+
}
81+
82+
// This test checks that factory initialization panics given invalid chain
83+
func TestInvalidChain(t *testing.T) {
84+
name, err := ioutil.TempDir("", "hyperledger_fabric")
85+
assert.Nil(t, err, "Error creating temp dir: %s", err)
86+
defer os.RemoveAll(name)
87+
88+
chainDir, err := ioutil.TempDir(name, "chain_")
89+
assert.Nil(t, err, "Error creating temp dir: %s", err)
90+
91+
t.Run("ChainDirNotReadable", func(t *testing.T) {
92+
t.Skip("Temporarily skip this test due to the reason stated at the top of this file")
93+
assert.Nil(t, os.Chmod(chainDir, 0200), "Error chmod chain dir")
94+
defer os.Chmod(chainDir, 0700)
95+
assert.Panics(t, func() { New(name) }, "Expected initialization panics if chain dir is not readable")
96+
assert.Nil(t, os.Chmod(chainDir, 0700), "Error chmod chain dir")
97+
})
98+
99+
// Skip Block 0 to trigger MissingBlock error
100+
secondBlock := path.Join(chainDir, fmt.Sprintf(blockFileFormatString, 1))
101+
assert.NoError(t, ioutil.WriteFile(secondBlock, nil, 0700))
102+
103+
t.Run("MissingBlock", func(t *testing.T) {
104+
assert.Panics(t, func() { New(name) }, "Expected initialization panics if block is missing")
105+
})
106+
107+
t.Run("SkipDir", func(t *testing.T) {
108+
invalidBlock := path.Join(chainDir, fmt.Sprintf(blockFileFormatString, 0))
109+
assert.NoError(t, os.Mkdir(invalidBlock, 0700))
110+
assert.Panics(t, func() { New(name) }, "Expected initialization skips directory in chain dir")
111+
assert.NoError(t, os.RemoveAll(invalidBlock))
112+
})
113+
114+
firstBlock := path.Join(chainDir, fmt.Sprintf(blockFileFormatString, 0))
115+
assert.NoError(t, ioutil.WriteFile(firstBlock, nil, 0700))
116+
117+
t.Run("BlockNotReadable", func(t *testing.T) {
118+
t.Skip("Temporarily skip this test due to the reason stated at the top of this file")
119+
assert.NoError(t, os.Chmod(secondBlock, 0200))
120+
defer os.Chmod(secondBlock, 0700)
121+
assert.Panics(t, func() { New(name) }, "Expected initialization panics if block is not readable")
122+
assert.NoError(t, os.Chmod(secondBlock, 0700))
123+
})
124+
125+
t.Run("MalformedBlock", func(t *testing.T) {
126+
assert.Panics(t, func() { New(name) }, "Expected initialization panics if block is malformed")
127+
})
128+
}
129+
130+
// This test checks that file is ignored if the name is not valid
131+
func TestIgnoreInvalidBlockFileName(t *testing.T) {
132+
name, err := ioutil.TempDir("", "hyperledger_fabric")
133+
assert.Nil(t, err, "Error creating temp dir: %s", err)
134+
defer os.RemoveAll(name)
135+
136+
chainDir, err := ioutil.TempDir(name, "chain_")
137+
assert.Nil(t, err, "Error creating temp dir: %s", err)
138+
139+
invalidBlock := path.Join(chainDir, "invalid_block")
140+
assert.NoError(t, ioutil.WriteFile(invalidBlock, nil, 0700))
141+
jfl := New(name)
142+
assert.Equal(t, 1, len(jfl.ChainIDs()), "Expected factory initialized with 1 chain")
143+
144+
chain, err := jfl.GetOrCreate(jfl.ChainIDs()[0])
145+
assert.Nil(t, err, "Should have retrieved chain")
146+
assert.Zero(t, chain.Height(), "Expected chain to be empty")
147+
}
148+
149+
// This test checks that fs error causes creating chain to fail
150+
func TestErrorCreatingChain(t *testing.T) {
151+
t.Skip("Temporarily skip this test due to the reason stated at the top of this file")
152+
153+
name, err := ioutil.TempDir("", "hyperledger_fabric")
154+
assert.Nil(t, err, "Error creating temp dir: %s", err)
155+
defer os.RemoveAll(name)
156+
157+
jlf := New(name)
158+
assert.NoError(t, os.Chmod(name, 0400))
159+
defer os.Chmod(name, 0700)
160+
_, err = jlf.GetOrCreate(provisional.TestChainID)
161+
assert.Error(t, err, "Should have failed to create chain due to fs error")
162+
}
163+
164+
func TestClose(t *testing.T) {
165+
name, err := ioutil.TempDir("", "hyperledger_fabric")
166+
assert.Nil(t, err, "Error creating temp dir: %s", err)
167+
defer os.RemoveAll(name)
168+
169+
jlf := New(name)
170+
assert.NotPanics(t, func() { jlf.Close() }, "Noop should not pannic")
171+
}

0 commit comments

Comments
 (0)