github.com/kaituanwang/hyperledger@v2.0.1+incompatible/orderer/consensus/kafka/consenter_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package kafka
     8  
     9  import (
    10  	"fmt"
    11  	"strings"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/Shopify/sarama"
    16  	"github.com/golang/protobuf/proto"
    17  	cb "github.com/hyperledger/fabric-protos-go/common"
    18  	ab "github.com/hyperledger/fabric-protos-go/orderer"
    19  	"github.com/hyperledger/fabric/common/channelconfig"
    20  	"github.com/hyperledger/fabric/common/flogging"
    21  	"github.com/hyperledger/fabric/common/metrics/disabled"
    22  	"github.com/hyperledger/fabric/orderer/common/localconfig"
    23  	"github.com/hyperledger/fabric/orderer/consensus"
    24  	"github.com/hyperledger/fabric/orderer/consensus/kafka/mock"
    25  	mockmultichannel "github.com/hyperledger/fabric/orderer/mocks/common/multichannel"
    26  	"github.com/hyperledger/fabric/protoutil"
    27  	"github.com/stretchr/testify/assert"
    28  )
    29  
    30  //go:generate counterfeiter -o mock/orderer_config.go --fake-name OrdererConfig . ordererConfig
    31  
    32  type ordererConfig interface {
    33  	channelconfig.Orderer
    34  }
    35  
    36  var mockRetryOptions = localconfig.Retry{
    37  	ShortInterval: 50 * time.Millisecond,
    38  	ShortTotal:    100 * time.Millisecond,
    39  	LongInterval:  60 * time.Millisecond,
    40  	LongTotal:     120 * time.Millisecond,
    41  	NetworkTimeouts: localconfig.NetworkTimeouts{
    42  		DialTimeout:  40 * time.Millisecond,
    43  		ReadTimeout:  40 * time.Millisecond,
    44  		WriteTimeout: 40 * time.Millisecond,
    45  	},
    46  	Metadata: localconfig.Metadata{
    47  		RetryMax:     2,
    48  		RetryBackoff: 40 * time.Millisecond,
    49  	},
    50  	Producer: localconfig.Producer{
    51  		RetryMax:     2,
    52  		RetryBackoff: 40 * time.Millisecond,
    53  	},
    54  	Consumer: localconfig.Consumer{
    55  		RetryBackoff: 40 * time.Millisecond,
    56  	},
    57  }
    58  
    59  func init() {
    60  	mockLocalConfig = newMockLocalConfig(
    61  		false,
    62  		localconfig.SASLPlain{Enabled: false},
    63  		mockRetryOptions,
    64  		false)
    65  	mockBrokerConfig = newMockBrokerConfig(
    66  		mockLocalConfig.General.TLS,
    67  		mockLocalConfig.Kafka.SASLPlain,
    68  		mockLocalConfig.Kafka.Retry,
    69  		mockLocalConfig.Kafka.Version,
    70  		defaultPartition)
    71  	mockConsenter = newMockConsenter(
    72  		mockBrokerConfig,
    73  		mockLocalConfig.General.TLS,
    74  		mockLocalConfig.Kafka.Retry,
    75  		mockLocalConfig.Kafka.Version)
    76  	setupTestLogging("ERROR")
    77  }
    78  
    79  func TestNew(t *testing.T) {
    80  	c, _ := New(mockLocalConfig.Kafka, &mock.MetricsProvider{}, &mock.HealthChecker{}, nil, func(string) {})
    81  	_ = consensus.Consenter(c)
    82  }
    83  
    84  func TestHandleChain(t *testing.T) {
    85  	consenter, _ := New(mockLocalConfig.Kafka, &disabled.Provider{}, &mock.HealthChecker{}, nil, func(string) {})
    86  
    87  	oldestOffset := int64(0)
    88  	newestOffset := int64(5)
    89  	message := sarama.StringEncoder("messageFoo")
    90  
    91  	mockChannel := newChannel(channelNameForTest(t), defaultPartition)
    92  
    93  	mockBroker := sarama.NewMockBroker(t, 0)
    94  	mockBroker.SetHandlerByMap(map[string]sarama.MockResponse{
    95  		"MetadataRequest": sarama.NewMockMetadataResponse(t).
    96  			SetBroker(mockBroker.Addr(), mockBroker.BrokerID()).
    97  			SetLeader(mockChannel.topic(), mockChannel.partition(), mockBroker.BrokerID()),
    98  		"ProduceRequest": sarama.NewMockProduceResponse(t).
    99  			SetError(mockChannel.topic(), mockChannel.partition(), sarama.ErrNoError),
   100  		"OffsetRequest": sarama.NewMockOffsetResponse(t).
   101  			SetOffset(mockChannel.topic(), mockChannel.partition(), sarama.OffsetOldest, oldestOffset).
   102  			SetOffset(mockChannel.topic(), mockChannel.partition(), sarama.OffsetNewest, newestOffset),
   103  		"FetchRequest": sarama.NewMockFetchResponse(t, 1).
   104  			SetMessage(mockChannel.topic(), mockChannel.partition(), newestOffset, message),
   105  	})
   106  
   107  	mockOrderer := &mock.OrdererConfig{}
   108  	mockOrderer.KafkaBrokersReturns([]string{mockBroker.Addr()})
   109  	mockSupport := &mockmultichannel.ConsenterSupport{
   110  		ChannelIDVal:    mockChannel.topic(),
   111  		SharedConfigVal: mockOrderer,
   112  	}
   113  
   114  	mockMetadata := &cb.Metadata{Value: protoutil.MarshalOrPanic(&ab.KafkaMetadata{LastOffsetPersisted: newestOffset - 1})}
   115  	_, err := consenter.HandleChain(mockSupport, mockMetadata)
   116  	assert.NoError(t, err, "Expected the HandleChain call to return without errors")
   117  }
   118  
   119  // Test helper functions and mock objects defined here
   120  
   121  var mockConsenter commonConsenter
   122  var mockLocalConfig *localconfig.TopLevel
   123  var mockBrokerConfig *sarama.Config
   124  
   125  func extractEncodedOffset(marshalledOrdererMetadata []byte) int64 {
   126  	omd := &cb.Metadata{}
   127  	_ = proto.Unmarshal(marshalledOrdererMetadata, omd)
   128  	kmd := &ab.KafkaMetadata{}
   129  	_ = proto.Unmarshal(omd.GetValue(), kmd)
   130  	return kmd.LastOffsetPersisted
   131  }
   132  
   133  func newMockBrokerConfig(
   134  	tlsConfig localconfig.TLS,
   135  	saslPlain localconfig.SASLPlain,
   136  	retryOptions localconfig.Retry,
   137  	kafkaVersion sarama.KafkaVersion,
   138  	chosenStaticPartition int32) *sarama.Config {
   139  
   140  	brokerConfig := newBrokerConfig(
   141  		tlsConfig,
   142  		saslPlain,
   143  		retryOptions,
   144  		kafkaVersion,
   145  		chosenStaticPartition)
   146  	brokerConfig.ClientID = "test"
   147  	return brokerConfig
   148  }
   149  
   150  func newMockConsenter(brokerConfig *sarama.Config, tlsConfig localconfig.TLS, retryOptions localconfig.Retry, kafkaVersion sarama.KafkaVersion) *consenterImpl {
   151  	return &consenterImpl{
   152  		brokerConfigVal: brokerConfig,
   153  		tlsConfigVal:    tlsConfig,
   154  		retryOptionsVal: retryOptions,
   155  		kafkaVersionVal: kafkaVersion,
   156  		metrics:         NewMetrics(&disabled.Provider{}, nil),
   157  	}
   158  }
   159  
   160  func newMockConsumerMessage(wrappedMessage *ab.KafkaMessage) *sarama.ConsumerMessage {
   161  	return &sarama.ConsumerMessage{
   162  		Value: sarama.ByteEncoder(protoutil.MarshalOrPanic(wrappedMessage)),
   163  	}
   164  }
   165  
   166  func newMockEnvelope(content string) *cb.Envelope {
   167  	return &cb.Envelope{Payload: protoutil.MarshalOrPanic(&cb.Payload{
   168  		Header: &cb.Header{ChannelHeader: protoutil.MarshalOrPanic(&cb.ChannelHeader{ChannelId: "foo"})},
   169  		Data:   []byte(content),
   170  	})}
   171  }
   172  
   173  func newMockLocalConfig(
   174  	enableTLS bool,
   175  	saslPlain localconfig.SASLPlain,
   176  	retryOptions localconfig.Retry,
   177  	verboseLog bool) *localconfig.TopLevel {
   178  
   179  	return &localconfig.TopLevel{
   180  		General: localconfig.General{
   181  			TLS: localconfig.TLS{
   182  				Enabled: enableTLS,
   183  			},
   184  		},
   185  		Kafka: localconfig.Kafka{
   186  			TLS: localconfig.TLS{
   187  				Enabled: enableTLS,
   188  			},
   189  			SASLPlain: saslPlain,
   190  			Retry:     retryOptions,
   191  			Verbose:   verboseLog,
   192  			Version:   sarama.V0_9_0_1, // sarama.MockBroker only produces messages compatible with version < 0.10
   193  		},
   194  	}
   195  }
   196  
   197  func setupTestLogging(logLevel string) {
   198  	// This call allows us to (a) get the logging backend initialization that
   199  	// takes place in the `flogging` package, and (b) adjust the verbosity of
   200  	// the logs when running tests on this package.
   201  	spec := fmt.Sprintf("orderer.consensus.kafka=%s", logLevel)
   202  	flogging.ActivateSpec(spec)
   203  }
   204  
   205  func tamperBytes(original []byte) []byte {
   206  	byteCount := len(original)
   207  	return original[:byteCount-1]
   208  }
   209  
   210  func channelNameForTest(t *testing.T) string {
   211  	return fmt.Sprintf("%s.channel", strings.Replace(strings.ToLower(t.Name()), "/", ".", -1))
   212  }