func TestSilentConfigModification(t *testing.T) {
	cm, err := NewManagerImpl(
		makeEnvelopeConfig(
			defaultChain,
			makeConfigPair("foo", "foo", 0, []byte("foo")),
			makeConfigPair("bar", "bar", 0, []byte("bar")),
		),
		defaultInitializer(), nil)
	if err != nil {
		t.Fatalf("Error constructing config manager: %s", err)
	}
	newConfig := makeConfigUpdateEnvelope(
		defaultChain,
		makeConfigSet(),
		makeConfigSet(
			makeConfigPair("foo", "foo", 0, []byte("different")),
			makeConfigPair("bar", "bar", 1, []byte("bar")),
		),
	)
	_, err = cm.ProposeConfigUpdate(newConfig)
	if err == nil {
		t.Error("Should have errored proposing config because foo was silently modified (despite modification allowed by policy)")
	}
}
TestSilentConfigModification tests to make sure that even if a validly signed new config for an existing sequence number
is substituted into an otherwise valid new config, that the new config is rejected for attempting a modification without
increasing the config item's LastModified
package configtx
import (
	"fmt"
	"testing"
	"github.com/inklabsfoundation/inkchain/common/configtx/api"
	mockconfigtx "github.com/inklabsfoundation/inkchain/common/mocks/configtx"
	mockpolicies "github.com/inklabsfoundation/inkchain/common/mocks/policies"
	"github.com/inklabsfoundation/inkchain/common/policies"
	cb "github.com/inklabsfoundation/inkchain/protos/common"
	"github.com/inklabsfoundation/inkchain/protos/utils"
	"github.com/stretchr/testify/assert"
)
var defaultChain = "default.chain.id"
func defaultInitializer() *mockconfigtx.Initializer {
	return &mockconfigtx.Initializer{
		Resources: mockconfigtx.Resources{
			PolicyManagerVal: &mockpolicies.Manager{
				Policy: &mockpolicies.Policy{},
			},
		},
		PolicyProposerVal: &mockconfigtx.PolicyProposer{
			Transactional: mockconfigtx.Transactional{},
		},
		ValueProposerVal: &mockconfigtx.ValueProposer{
			Transactional: mockconfigtx.Transactional{},
		},
	}
}
type configPair struct {
	key   string
	value *cb.ConfigValue
}
func makeConfigPair(id, modificationPolicy string, lastModified uint64, data []byte) *configPair {
	return &configPair{
		key: id,
		value: &cb.ConfigValue{
			ModPolicy: modificationPolicy,
			Version:   lastModified,
			Value:     data,
		},
	}
}
func makeEnvelopeConfig(channelID string, configPairs ...*configPair) *cb.Envelope {
	channelGroup := cb.NewConfigGroup()
	for _, pair := range configPairs {
		channelGroup.Values[pair.key] = pair.value
	}
	return &cb.Envelope{
		Payload: utils.MarshalOrPanic(&cb.Payload{
			Header: &cb.Header{
				ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
					Type:      int32(cb.HeaderType_CONFIG),
					ChannelId: channelID,
				}),
			},
			Data: utils.MarshalOrPanic(&cb.ConfigEnvelope{
				Config: &cb.Config{
					ChannelGroup: channelGroup,
				},
			}),
		}),
	}
}
func makeConfigSet(configPairs ...*configPair) *cb.ConfigGroup {
	result := cb.NewConfigGroup()
	for _, pair := range configPairs {
		result.Values[pair.key] = pair.value
	}
	return result
}
func makeConfigUpdateEnvelope(chainID string, readSet, writeSet *cb.ConfigGroup) *cb.Envelope {
	return &cb.Envelope{
		Payload: utils.MarshalOrPanic(&cb.Payload{
			Header: &cb.Header{
				ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
					Type: int32(cb.HeaderType_CONFIG_UPDATE),
				}),
			},
			Data: utils.MarshalOrPanic(&cb.ConfigUpdateEnvelope{
				ConfigUpdate: utils.MarshalOrPanic(&cb.ConfigUpdate{
					ChannelId: chainID,
					ReadSet:   readSet,
					WriteSet:  writeSet,
				}),
			}),
		}),
	}
}
func TestCallback(t *testing.T) {
	var calledBack api.Manager
	callback := func(m api.Manager) {
		calledBack = m
	}
	cm, err := NewManagerImpl(
		makeEnvelopeConfig(defaultChain, makeConfigPair("foo", "foo", 0, []byte("foo"))),
		defaultInitializer(), []func(api.Manager){callback})
	if err != nil {
		t.Fatalf("Error constructing config manager: %s", err)
	}
	if calledBack != cm {
		t.Fatalf("Should have called back with the correct manager")
	}
}
func TestEmptyChannel(t *testing.T) {
	_, err := NewManagerImpl(&cb.Envelope{
		Payload: utils.MarshalOrPanic(&cb.Payload{
			Header: &cb.Header{
				ChannelHeader: utils.MarshalOrPanic(&cb.ChannelHeader{
					Type:      int32(cb.HeaderType_CONFIG),
					ChannelId: "foo",
				}),
			},
			Data: utils.MarshalOrPanic(&cb.ConfigEnvelope{
				Config: &cb.Config{},
			}),
		}),
	}, defaultInitializer(), nil)
	assert.Error(t, err)
}
func TestDifferentChainID(t *testing.T) {
	cm, err := NewManagerImpl(
		makeEnvelopeConfig(defaultChain, makeConfigPair("foo", "foo", 0, []byte("foo"))),
		defaultInitializer(), nil)
	if err != nil {
		t.Fatalf("Error constructing config manager: %s", err)
	}
	newConfig := makeConfigUpdateEnvelope("wrongChain", makeConfigSet(), makeConfigSet(makeConfigPair("foo", "foo", 1, []byte("foo"))))
	_, err = cm.ProposeConfigUpdate(newConfig)
	if err == nil {
		t.Error("Should have errored when proposing a new config set the wrong chain ID")
	}
}
func TestOldConfigReplay(t *testing.T) {
	cm, err := NewManagerImpl(
		makeEnvelopeConfig(defaultChain, makeConfigPair("foo", "foo", 0, []byte("foo"))),
		defaultInitializer(), nil)
	if err != nil {
		t.Fatalf("Error constructing config manager: %s", err)
	}
	newConfig := makeConfigUpdateEnvelope(defaultChain, makeConfigSet(), makeConfigSet(makeConfigPair("foo", "foo", 0, []byte("foo"))))
	_, err = cm.ProposeConfigUpdate(newConfig)
	if err == nil {
		t.Error("Should have errored when proposing a config that is not a newer sequence number")
	}
}
func TestValidConfigChange(t *testing.T) {
	cm, err := NewManagerImpl(
		makeEnvelopeConfig(defaultChain, makeConfigPair("foo", "foo", 0, []byte("foo"))),
		defaultInitializer(), nil)
	if err != nil {
		t.Fatalf("Error constructing config manager: %s", err)
	}
	newConfig := makeConfigUpdateEnvelope(defaultChain, makeConfigSet(), makeConfigSet(makeConfigPair("foo", "foo", 1, []byte("foo"))))
	configEnv, err := cm.ProposeConfigUpdate(newConfig)
	if err != nil {
		t.Errorf("Should not have errored proposing config: %s", err)
	}
	err = cm.Validate(configEnv)
	if err != nil {
		t.Errorf("Should not have errored validating config: %s", err)
	}
	err = cm.Apply(configEnv)
	if err != nil {
		t.Errorf("Should not have errored applying config: %s", err)
	}
}
func TestConfigChangeRegressedSequence(t *testing.T) {
	cm, err := NewManagerImpl(
		makeEnvelopeConfig(defaultChain, makeConfigPair("foo", "foo", 1, []byte("foo"))),
		defaultInitializer(), nil)
	if err != nil {
		t.Fatalf("Error constructing config manager: %s", err)
	}
	newConfig := makeConfigUpdateEnvelope(
		defaultChain,
		makeConfigSet(makeConfigPair("foo", "foo", 0, []byte("foo"))),
		makeConfigSet(makeConfigPair("bar", "bar", 2, []byte("bar"))),
	)
	_, err = cm.ProposeConfigUpdate(newConfig)
	if err == nil {
		t.Error("Should have errored proposing config because foo's sequence number regressed")
	}
}
func TestConfigChangeOldSequence(t *testing.T) {
	cm, err := NewManagerImpl(
		makeEnvelopeConfig(defaultChain, makeConfigPair("foo", "foo", 1, []byte("foo"))),
		defaultInitializer(), nil)
	if err != nil {
		t.Fatalf("Error constructing config manager: %s", err)
	}
	newConfig := makeConfigUpdateEnvelope(
		defaultChain,
		makeConfigSet(),
		makeConfigSet(
			makeConfigPair("foo", "foo", 2, []byte("foo")),
			makeConfigPair("bar", "bar", 1, []byte("bar")),
		),
	)
	_, err = cm.ProposeConfigUpdate(newConfig)
	if err == nil {
		t.Error("Should have errored proposing config because bar was new but its sequence number was old")
	}
}
func TestConfigPartialUpdate(t *testing.T) {
	cm, err := NewManagerImpl(
		makeEnvelopeConfig(
			defaultChain,
			makeConfigPair("foo", "foo", 0, []byte("foo")),
			makeConfigPair("bar", "bar", 0, []byte("bar")),
		),
		defaultInitializer(), nil)
	if err != nil {
		t.Fatalf("Error constructing config manager: %s", err)
	}
	newConfig := makeConfigUpdateEnvelope(
		defaultChain,
		makeConfigSet(),
		makeConfigSet(makeConfigPair("bar", "bar", 1, []byte("bar"))),
	)
	_, err = cm.ProposeConfigUpdate(newConfig)
	assert.NoError(t, err, "Should have allowed partial update")
}
func TestEmptyConfigUpdate(t *testing.T) {
	cm, err := NewManagerImpl(
		makeEnvelopeConfig(defaultChain, makeConfigPair("foo", "foo", 0, []byte("foo"))),
		defaultInitializer(), nil)
	if err != nil {
		t.Fatalf("Error constructing config manager: %s", err)
	}
	newConfig := &cb.Envelope{}
	_, err = cm.ProposeConfigUpdate(newConfig)
	if err == nil {
		t.Error("Should not errored proposing config because new config is empty")
	}
}