Skip to content

Commit

Permalink
[FAB-8944] Add more unit tests for channel config cache
Browse files Browse the repository at this point in the history
Change-Id: Ic1263079e95793407cd1ac2ebc7d0540a26856c4
Signed-off-by: Divyank Katira <Divyank.Katira@securekey.com>
  • Loading branch information
d1vyank committed Mar 21, 2018
1 parent 38d16da commit 2061a93
Show file tree
Hide file tree
Showing 9 changed files with 275 additions and 24 deletions.
2 changes: 1 addition & 1 deletion pkg/fab/channel/membership/cache.go
Expand Up @@ -51,7 +51,7 @@ func NewRefCache(refresh time.Duration) *lazycache.Cache {
initializer := func(key lazycache.Key) (interface{}, error) {
ck, ok := key.(CacheKey)
if !ok {
return nil, errors.New("Unexpected cache key")
return nil, errors.New("unexpected cache key")
}
return NewRef(refresh, ck.Context(), ck.ChConfigRef()), nil
}
Expand Down
99 changes: 99 additions & 0 deletions pkg/fab/channel/membership/cache_test.go
@@ -0,0 +1,99 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package membership

import (
"fmt"
"testing"
"time"

"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
"github.com/hyperledger/fabric-sdk-go/pkg/fab/mocks"
"github.com/hyperledger/fabric-sdk-go/pkg/util/concurrent/lazyref"
mb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/msp"
"github.com/stretchr/testify/assert"
)

type badKey struct {
s string
}

func (b *badKey) String() string {
return b.s
}

func TestMembershipCache(t *testing.T) {
testChannelID := "test"
goodMSPID := "GoodMSP"

cfg := mocks.NewMockChannelCfg(testChannelID)
cfg.MockMSPs = []*mb.MSPConfig{buildMSPConfig(goodMSPID, []byte(validRootCA))}

ctx := mocks.NewMockProviderContext()

cache := NewRefCache(time.Millisecond * 10)
assert.NotNil(t, cache)

key, err := NewCacheKey(Context{ctx}, lazyref.New(func() (interface{}, error) { return cfg, nil }), testChannelID)
assert.Nil(t, err)
assert.NotNil(t, key)

ch := key.ChannelID()
assert.Equal(t, testChannelID, ch)

r, err := cache.Get(key)
assert.Nil(t, err)
assert.NotNil(t, r)

mem, ok := r.(fab.ChannelMembership)
assert.True(t, ok)

sID := &mb.SerializedIdentity{Mspid: goodMSPID, IdBytes: []byte(certPem)}
goodEndorser, err := proto.Marshal(sID)
assert.Nil(t, err)

err = mem.Validate(goodEndorser)
assert.Nil(t, err)

err = mem.Verify(goodEndorser, []byte("test"), []byte("test1"))
assert.Nil(t, err)
}

func TestMembershipCacheBad(t *testing.T) {
testChannelID := "test"
testErr := fmt.Errorf("bad initializer")

ctx := mocks.NewMockProviderContext()

cache := NewRefCache(time.Millisecond * 10)
assert.NotNil(t, cache)

r, err := cache.Get(&badKey{s: "test"})
assert.NotNil(t, err)
assert.Equal(t, "unexpected cache key", err.Error())
assert.Nil(t, r)

key, err := NewCacheKey(Context{ctx}, lazyref.New(func() (interface{}, error) { return nil, testErr }), testChannelID)
assert.Nil(t, err)
assert.NotNil(t, key)

r, err = cache.Get(key)
assert.Nil(t, err)
assert.NotNil(t, r)

mem, ok := r.(fab.ChannelMembership)
assert.True(t, ok)

err = mem.Validate([]byte("MSP"))
assert.NotNil(t, err)
assert.Contains(t, err.Error(), testErr.Error())

err = mem.Verify([]byte("MSP"), []byte("test"), []byte("test1"))
assert.NotNil(t, err)
assert.Contains(t, err.Error(), testErr.Error())
}
2 changes: 1 addition & 1 deletion pkg/fab/chconfig/cache.go
Expand Up @@ -60,7 +60,7 @@ func NewRefCache(refresh time.Duration) *lazycache.Cache {
initializer := func(key lazycache.Key) (interface{}, error) {
ck, ok := key.(CacheKey)
if !ok {
return nil, errors.New("Unexpected cache key")
return nil, errors.New("unexpected cache key")
}
return NewRef(refresh, ck.Provider(), ck.ChannelID(), ck.Context()), nil
}
Expand Down
84 changes: 84 additions & 0 deletions pkg/fab/chconfig/cache_test.go
@@ -0,0 +1,84 @@
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package chconfig

import (
"fmt"
"testing"
"time"

"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
"github.com/hyperledger/fabric-sdk-go/pkg/fab/mocks"
"github.com/stretchr/testify/assert"

mspmocks "github.com/hyperledger/fabric-sdk-go/pkg/msp/test/mockmsp"
)

const (
badProviderErrMessage = "bad provider"
)

func TestChannelConfigCache(t *testing.T) {
user := mspmocks.NewMockSigningIdentity("user", "user")
clientCtx := mocks.NewMockContext(user)

cache := NewRefCache(time.Millisecond * 10)
assert.NotNil(t, cache)

key, err := NewCacheKey(clientCtx, mockProvider, "test")
assert.Nil(t, err)
assert.NotNil(t, key)

r, err := cache.Get(key)
assert.Nil(t, err)
assert.NotNil(t, r)
}

func TestChannelConfigCacheBad(t *testing.T) {
user := mspmocks.NewMockSigningIdentity("user", "user")
clientCtx := mocks.NewMockContext(user)

cache := NewRefCache(time.Millisecond * 10)
assert.NotNil(t, cache)

r, err := cache.Get(&badKey{s: "test"})
assert.NotNil(t, err)
assert.Equal(t, "unexpected cache key", err.Error())
assert.Nil(t, r)

key, err := NewCacheKey(clientCtx, badProvider, "test")
assert.Nil(t, err)
assert.NotNil(t, key)

cache = NewRefCache(time.Millisecond * 10)
assert.NotNil(t, cache)

r, err = cache.Get(key)
assert.NotNil(t, r)
assert.Nil(t, err)

c, err := r.(*Ref).Get()
assert.NotNil(t, err)
assert.Nil(t, c)
assert.Contains(t, err.Error(), badProviderErrMessage)
}

type badKey struct {
s string
}

func (b *badKey) String() string {
return b.s
}

func mockProvider(channelID string) (fab.ChannelConfig, error) {
return mocks.NewMockChannelConfig(nil, channelID)
}

func badProvider(channelID string) (fab.ChannelConfig, error) {
return nil, fmt.Errorf(badProviderErrMessage)
}
13 changes: 5 additions & 8 deletions pkg/fabsdk/fabsdk_chconfig_test.go
Expand Up @@ -18,11 +18,10 @@ import (
)

const (
sdkValidClientOrg2 = "Org2"
sdkValidClientOrg2 = "org2"
)

// TODO: (divyank) Re-enable.
func testNewDefaultSDK(t *testing.T) {
func TestNewDefaultSDK(t *testing.T) {
// Test New SDK with valid config file
sdk, err := New(configImpl.FromFile(sdkConfigFile))
if err != nil {
Expand All @@ -48,8 +47,7 @@ func verifySDK(t *testing.T, sdk *FabricSDK) {
}
}

// TODO: (divyank) Re-enable.
func testWithConfigOpt(t *testing.T) {
func TestWithConfigOpt(t *testing.T) {
// Test New SDK with valid config file
c, err := configImpl.FromFile(sdkConfigFile)()
if err != nil {
Expand All @@ -64,8 +62,7 @@ func testWithConfigOpt(t *testing.T) {
verifySDK(t, sdk)
}

// TODO: (divyank) Re-enable.
func testNewDefaultTwoValidSDK(t *testing.T) {
func TestNewDefaultTwoValidSDK(t *testing.T) {
sdk1, err := New(configImpl.FromFile(sdkConfigFile))
if err != nil {
t.Fatalf("Error initializing SDK: %s", err)
Expand Down Expand Up @@ -100,7 +97,7 @@ func testNewDefaultTwoValidSDK(t *testing.T) {
}

if client2.Organization != sdkValidClientOrg2 {
t.Fatalf("Unexpected org in config: %s", client1.Organization)
t.Fatalf("Unexpected org in config: %s", client2.Organization)
}

// Get a common client context for the following tests
Expand Down
2 changes: 0 additions & 2 deletions pkg/fabsdk/provider/chpvdr/chprovider.go
Expand Up @@ -39,8 +39,6 @@ func (cp *ChannelProvider) ChannelService(ctx fab.ClientContext, channelID strin

// ChannelService provides Channel clients and maintains contexts for them.
// the identity context is used
//
// TODO: add cache for channel rather than reconstructing each time.
type ChannelService struct {
provider *ChannelProvider
infraProvider fab.InfraProvider
Expand Down
41 changes: 41 additions & 0 deletions pkg/fabsdk/provider/fabpvdr/chconfig_test.go
@@ -0,0 +1,41 @@
// +build testing

/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package fabpvdr

import (
"testing"

"github.com/hyperledger/fabric-sdk-go/pkg/fab/chconfig"
"github.com/hyperledger/fabric-sdk-go/pkg/fab/mocks"
"github.com/stretchr/testify/assert"

mspmocks "github.com/hyperledger/fabric-sdk-go/pkg/msp/test/mockmsp"
)

func TestCreateChannelCfg(t *testing.T) {
p := newInfraProvider(t)
testChannelID := "test"
p.chCfgCache = newMockChCfgCache(chconfig.NewChannelCfg(testChannelID))
ctx := mocks.NewMockProviderContext()
user := mspmocks.NewMockSigningIdentity("user", "user")
clientCtx := &mockClientContext{
Providers: ctx,
SigningIdentity: user,
}

m, err := p.CreateChannelCfg(clientCtx, "")
assert.Nil(t, err)
assert.NotNil(t, m)

m, err = p.CreateChannelCfg(clientCtx, testChannelID)
assert.Nil(t, err)
assert.NotNil(t, m)

p.Close()
}
47 changes: 39 additions & 8 deletions pkg/fabsdk/provider/fabpvdr/fabprovider_testing_env.go
Expand Up @@ -9,26 +9,57 @@ SPDX-License-Identifier: Apache-2.0
package fabpvdr

import (
"sync"

"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
"github.com/hyperledger/fabric-sdk-go/pkg/fab/chconfig"
"github.com/hyperledger/fabric-sdk-go/pkg/util/concurrent/lazycache"
"github.com/hyperledger/fabric-sdk-go/pkg/util/concurrent/lazyref"
"github.com/pkg/errors"
)

// SetChannelConfig allows setting channel configuration.
// This method is intended to enable tests and should not be called.
func (f *InfraProvider) SetChannelConfig(cfg fab.ChannelCfg) {
f.chCfgCache = newMockCache(cfg)
if _, ok := f.chCfgCache.(*chCfgCache); !ok {
f.chCfgCache = newMockChCfgCache(cfg)
} else {
f.chCfgCache.(*chCfgCache).Put(cfg)
}
}

type chCfgCache struct {
cfgMap sync.Map
}

type mockCache struct {
cfg fab.ChannelCfg
func newMockChCfgCache(cfg fab.ChannelCfg) cache {
c := &chCfgCache{}
c.cfgMap.Store(cfg.ID(), newChCfgRef(cfg))
return c
}

func newMockCache(cfg fab.ChannelCfg) cache {
return &mockCache{cfg: cfg}
func newChCfgRef(cfg fab.ChannelCfg) *chconfig.Ref {
r := &chconfig.Ref{}
r.Reference = lazyref.New(func() (interface{}, error) {
return cfg, nil
})
return r
}

func (m *mockCache) Get(lazycache.Key) (interface{}, error) {
return m.cfg, nil
// Get mock channel config reference
func (m *chCfgCache) Get(k lazycache.Key) (interface{}, error) {
cfg, ok := m.cfgMap.Load(k.(chconfig.CacheKey).ChannelID())
if !ok {
return nil, errors.New("Channel config not found in cache")
}
return cfg, nil
}
func (m *mockCache) Close() {

// Close not implemented
func (m *chCfgCache) Close() {
}

// Put channel config reference into mock cache
func (m *chCfgCache) Put(cfg fab.ChannelCfg) {
m.cfgMap.Store(cfg.ID(), newChCfgRef(cfg))
}

0 comments on commit 2061a93

Please sign in to comment.