Skip to content

Commit

Permalink
Mock testing infrastructure enhancements
Browse files Browse the repository at this point in the history
One known piece of common mock infrastructure is the
blockcutter.Receiver and multichain.ConsenterSupport used in both Solo,
and Kafka tests.

This changeset factors these structures out of the solo tests and into
the mock infrastructure.  Because of dependency cycles which were
created, it also breaks the mocks package into subpackages per mock
type.

Change-Id: I924cf18d18ba9e6b1e9853ace105e1c4703ac4aa
Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
  • Loading branch information
Jason Yellick committed Dec 12, 2016
1 parent fcd00a1 commit 4dc372e
Show file tree
Hide file tree
Showing 8 changed files with 273 additions and 137 deletions.
12 changes: 6 additions & 6 deletions orderer/common/blockcutter/blockcutter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"testing"

"github.com/hyperledger/fabric/orderer/common/filter"
"github.com/hyperledger/fabric/orderer/mocks"
mocksharedconfig "github.com/hyperledger/fabric/orderer/mocks/sharedconfig"
cb "github.com/hyperledger/fabric/protos/common"
)

Expand Down Expand Up @@ -74,7 +74,7 @@ var unmatchedTx = &cb.Envelope{Payload: []byte("UNMATCHED")}
func TestNormalBatch(t *testing.T) {
filters := getFilters()
batchSize := 2
r := NewReceiverImpl(&mocks.SharedConfigManager{BatchSizeVal: batchSize}, filters)
r := NewReceiverImpl(&mocksharedconfig.Manager{BatchSizeVal: batchSize}, filters)

batches, committers, ok := r.Ordered(goodTx)

Expand All @@ -101,7 +101,7 @@ func TestNormalBatch(t *testing.T) {
func TestBadMessageInBatch(t *testing.T) {
filters := getFilters()
batchSize := 2
r := NewReceiverImpl(&mocks.SharedConfigManager{BatchSizeVal: batchSize}, filters)
r := NewReceiverImpl(&mocksharedconfig.Manager{BatchSizeVal: batchSize}, filters)

batches, committers, ok := r.Ordered(badTx)

Expand Down Expand Up @@ -137,7 +137,7 @@ func TestBadMessageInBatch(t *testing.T) {
func TestUnmatchedMessageInBatch(t *testing.T) {
filters := getFilters()
batchSize := 2
r := NewReceiverImpl(&mocks.SharedConfigManager{BatchSizeVal: batchSize}, filters)
r := NewReceiverImpl(&mocksharedconfig.Manager{BatchSizeVal: batchSize}, filters)

batches, committers, ok := r.Ordered(unmatchedTx)

Expand Down Expand Up @@ -173,7 +173,7 @@ func TestUnmatchedMessageInBatch(t *testing.T) {
func TestIsolatedEmptyBatch(t *testing.T) {
filters := getFilters()
batchSize := 2
r := NewReceiverImpl(&mocks.SharedConfigManager{BatchSizeVal: batchSize}, filters)
r := NewReceiverImpl(&mocksharedconfig.Manager{BatchSizeVal: batchSize}, filters)

batches, committers, ok := r.Ordered(isolatedTx)

Expand All @@ -197,7 +197,7 @@ func TestIsolatedEmptyBatch(t *testing.T) {
func TestIsolatedPartialBatch(t *testing.T) {
filters := getFilters()
batchSize := 2
r := NewReceiverImpl(&mocks.SharedConfigManager{BatchSizeVal: batchSize}, filters)
r := NewReceiverImpl(&mocksharedconfig.Manager{BatchSizeVal: batchSize}, filters)

batches, committers, ok := r.Ordered(goodTx)

Expand Down
104 changes: 104 additions & 0 deletions orderer/mocks/blockcutter/blockcutter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package mocks

import (
"github.com/hyperledger/fabric/orderer/common/filter"
cb "github.com/hyperledger/fabric/protos/common"
)

import (
"github.com/op/go-logging"
)

var logger = logging.MustGetLogger("orderer/mocks/blockcutter")

// Receiver mocks the blockcutter.Receiver interface
type Receiver struct {
// QueueNext causes Ordered returns nil false when not set to true
QueueNext bool

// IsolatedTx causes Ordered returns [][]{curBatch, []{newTx}}, true when set to true
IsolatedTx bool

// CutNext causes Ordered returns [][]{append(curBatch, newTx)}, true when set to true
CutNext bool

// CurBatch is the currently outstanding messages in the batch
CurBatch []*cb.Envelope

// Block is a channel which is read from before returning from Ordered, it is useful for synchronization
// If you do not wish synchronization for whatever reason, simply close the channel
Block chan struct{}
}

// NewReceiver returns the mock blockcutter.Receiver implemenation
func NewReceiver() *Receiver {
return &Receiver{
QueueNext: true,
IsolatedTx: false,
CutNext: false,
Block: make(chan struct{}),
}
}

func noopCommitters(size int) []filter.Committer {
res := make([]filter.Committer, size)
for i := range res {
res[i] = filter.NoopCommitter
}
return res
}

// Ordered will add or cut the batch according to the state of Receiver, it blocks reading from Block on return
func (mbc *Receiver) Ordered(env *cb.Envelope) ([][]*cb.Envelope, [][]filter.Committer, bool) {
defer func() {
<-mbc.Block
}()

if !mbc.QueueNext {
logger.Debugf("Not queueing message")
return nil, nil, false
}

if mbc.IsolatedTx {
logger.Debugf("Receiver: Returning dual batch")
res := [][]*cb.Envelope{mbc.CurBatch, []*cb.Envelope{env}}
mbc.CurBatch = nil
return res, [][]filter.Committer{noopCommitters(len(res[0])), noopCommitters(len(res[1]))}, true
}

mbc.CurBatch = append(mbc.CurBatch, env)

if mbc.CutNext {
logger.Debugf("Returning regular batch")
res := [][]*cb.Envelope{mbc.CurBatch}
mbc.CurBatch = nil
return res, [][]filter.Committer{noopCommitters(len(res))}, true
}

logger.Debugf("Appending to batch")
return nil, nil, true
}

// Cut terminates the current batch, returning it
func (mbc *Receiver) Cut() ([]*cb.Envelope, []filter.Committer) {
logger.Debugf("Cutting batch")
res := mbc.CurBatch
mbc.CurBatch = nil
return res, noopCommitters(len(res))
}
27 changes: 27 additions & 0 deletions orderer/mocks/blockcutter/blockcutter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package mocks

import (
"testing"

"github.com/hyperledger/fabric/orderer/common/blockcutter"
)

func TestBlockCutterInterface(t *testing.T) {
_ = blockcutter.Receiver(NewReceiver())
}
59 changes: 59 additions & 0 deletions orderer/mocks/multichain/multichain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package multichain

import (
"github.com/hyperledger/fabric/orderer/common/blockcutter"
"github.com/hyperledger/fabric/orderer/common/filter"
"github.com/hyperledger/fabric/orderer/common/sharedconfig"
mockblockcutter "github.com/hyperledger/fabric/orderer/mocks/blockcutter"
mocksharedconfig "github.com/hyperledger/fabric/orderer/mocks/sharedconfig"
cb "github.com/hyperledger/fabric/protos/common"

"github.com/op/go-logging"
)

var logger = logging.MustGetLogger("orderer/mocks/multichain")

// ConsenterSupport is used to mock the multichain.ConsenterSupport interface
// Whenever a block is written, it writes to the Batches channel to allow for synchronization
type ConsenterSupport struct {
// SharedConfigVal is the value returned by SharedConfig()
SharedConfigVal *mocksharedconfig.Manager

// BlockCutterVal is the value returned by BlockCutter()
BlockCutterVal *mockblockcutter.Receiver

// Batches is the channel which WriteBlock writes data to
Batches chan []*cb.Envelope
}

// BlockCutter returns BlockCutterVal
func (mcs *ConsenterSupport) BlockCutter() blockcutter.Receiver {
return mcs.BlockCutterVal
}

// SharedConfig returns SharedConfigVal
func (mcs *ConsenterSupport) SharedConfig() sharedconfig.Manager {
return mcs.SharedConfigVal
}

// WriteBlock writes data to the Batches channel
func (mcs *ConsenterSupport) WriteBlock(data []*cb.Envelope, metadata [][]byte, committers []filter.Committer) {
logger.Debugf("mockWriter: attempting to write batch")
mcs.Batches <- data
}
27 changes: 27 additions & 0 deletions orderer/mocks/multichain/multichain_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package multichain

import (
"testing"

"github.com/hyperledger/fabric/orderer/multichain"
)

func TestConsenterSupportInterface(t *testing.T) {
_ = multichain.ConsenterSupport(&ConsenterSupport{})
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package mocks
package sharedconfig

// MockSharedConfigManager is a mock implementation of sharedconfig.Manager
type SharedConfigManager struct {
// Manager is a mock implementation of sharedconfig.Manager
type Manager struct {
// ConsensusTypeVal is returned as the result of ConsensusType()
ConsensusTypeVal string
// BatchSizeVal is returned as the result of BatchSize()
Expand All @@ -26,18 +26,17 @@ type SharedConfigManager struct {
ChainCreatorsVal []string
}

// ConsensusType returns the configured consensus type
func (scm *SharedConfigManager) ConsensusType() string {
// ConsensusType returns the ConsensusTypeVal
func (scm *Manager) ConsensusType() string {
return scm.ConsensusTypeVal
}

// BatchSize returns the maximum number of messages to include in a block
func (scm *SharedConfigManager) BatchSize() int {
// BatchSize returns the BatchSizeVal
func (scm *Manager) BatchSize() int {
return scm.BatchSizeVal
}

// ChainCreators returns the policy names which are allowed for chain creation
// This field is only set for the system ordering chain
func (scm *SharedConfigManager) ChainCreators() []string {
// ChainCreators returns the ChainCreatorsVal
func (scm *Manager) ChainCreators() []string {
return scm.ChainCreatorsVal
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package mocks
package sharedconfig

import (
"testing"
Expand All @@ -23,5 +23,5 @@ import (
)

func TestSharedConfigInterface(t *testing.T) {
_ = sharedconfig.Manager(&SharedConfigManager{})
_ = sharedconfig.Manager(&Manager{})
}
Loading

0 comments on commit 4dc372e

Please sign in to comment.