github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/orderer/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  	"log"
    12  	"os"
    13  	"strings"
    14  	"testing"
    15  	"time"
    16  
    17  	"github.com/Shopify/sarama"
    18  	"github.com/golang/protobuf/proto"
    19  	"github.com/hyperledger/fabric/common/flogging"
    20  	mockconfig "github.com/hyperledger/fabric/common/mocks/config"
    21  	localconfig "github.com/hyperledger/fabric/orderer/localconfig"
    22  	mockblockcutter "github.com/hyperledger/fabric/orderer/mocks/blockcutter"
    23  	mockmultichain "github.com/hyperledger/fabric/orderer/mocks/multichain"
    24  	"github.com/hyperledger/fabric/orderer/multichain"
    25  	cb "github.com/hyperledger/fabric/protos/common"
    26  	ab "github.com/hyperledger/fabric/protos/orderer"
    27  	"github.com/hyperledger/fabric/protos/utils"
    28  	"github.com/stretchr/testify/assert"
    29  )
    30  
    31  var mockRetryOptions = localconfig.Retry{
    32  	ShortInterval: 50 * time.Millisecond,
    33  	ShortTotal:    100 * time.Millisecond,
    34  	LongInterval:  60 * time.Millisecond,
    35  	LongTotal:     120 * time.Millisecond,
    36  	NetworkTimeouts: localconfig.NetworkTimeouts{
    37  		DialTimeout:  40 * time.Millisecond,
    38  		ReadTimeout:  40 * time.Millisecond,
    39  		WriteTimeout: 40 * time.Millisecond,
    40  	},
    41  	Metadata: localconfig.Metadata{
    42  		RetryMax:     2,
    43  		RetryBackoff: 40 * time.Millisecond,
    44  	},
    45  	Producer: localconfig.Producer{
    46  		RetryMax:     2,
    47  		RetryBackoff: 40 * time.Millisecond,
    48  	},
    49  	Consumer: localconfig.Consumer{
    50  		RetryBackoff: 40 * time.Millisecond,
    51  	},
    52  }
    53  
    54  func init() {
    55  	mockLocalConfig = newMockLocalConfig(false, mockRetryOptions, false)
    56  	mockBrokerConfig = newMockBrokerConfig(mockLocalConfig.General.TLS, mockLocalConfig.Kafka.Retry, mockLocalConfig.Kafka.Version, defaultPartition)
    57  	mockConsenter = newMockConsenter(mockBrokerConfig, mockLocalConfig.General.TLS, mockLocalConfig.Kafka.Retry, mockLocalConfig.Kafka.Version)
    58  	setupTestLogging("ERROR", mockLocalConfig.Kafka.Verbose)
    59  }
    60  
    61  func TestNew(t *testing.T) {
    62  	_ = multichain.Consenter(New(mockLocalConfig.General.TLS, mockLocalConfig.Kafka.Retry, mockLocalConfig.Kafka.Version))
    63  }
    64  
    65  func TestHandleChain(t *testing.T) {
    66  	consenter := multichain.Consenter(New(mockLocalConfig.General.TLS, mockLocalConfig.Kafka.Retry, mockLocalConfig.Kafka.Version))
    67  
    68  	oldestOffset := int64(0)
    69  	newestOffset := int64(5)
    70  	message := sarama.StringEncoder("messageFoo")
    71  
    72  	mockChannel := newChannel(channelNameForTest(t), defaultPartition)
    73  
    74  	mockBroker := sarama.NewMockBroker(t, 0)
    75  	mockBroker.SetHandlerByMap(map[string]sarama.MockResponse{
    76  		"MetadataRequest": sarama.NewMockMetadataResponse(t).
    77  			SetBroker(mockBroker.Addr(), mockBroker.BrokerID()).
    78  			SetLeader(mockChannel.topic(), mockChannel.partition(), mockBroker.BrokerID()),
    79  		"ProduceRequest": sarama.NewMockProduceResponse(t).
    80  			SetError(mockChannel.topic(), mockChannel.partition(), sarama.ErrNoError),
    81  		"OffsetRequest": sarama.NewMockOffsetResponse(t).
    82  			SetOffset(mockChannel.topic(), mockChannel.partition(), sarama.OffsetOldest, oldestOffset).
    83  			SetOffset(mockChannel.topic(), mockChannel.partition(), sarama.OffsetNewest, newestOffset),
    84  		"FetchRequest": sarama.NewMockFetchResponse(t, 1).
    85  			SetMessage(mockChannel.topic(), mockChannel.partition(), newestOffset, message),
    86  	})
    87  
    88  	mockSupport := &mockmultichain.ConsenterSupport{
    89  		ChainIDVal: mockChannel.topic(),
    90  		SharedConfigVal: &mockconfig.Orderer{
    91  			KafkaBrokersVal: []string{mockBroker.Addr()},
    92  		},
    93  	}
    94  
    95  	mockMetadata := &cb.Metadata{Value: utils.MarshalOrPanic(&ab.KafkaMetadata{LastOffsetPersisted: newestOffset - 1})}
    96  
    97  	_, err := consenter.HandleChain(mockSupport, mockMetadata)
    98  	assert.NoError(t, err, "Expected the HandleChain call to return without errors")
    99  }
   100  
   101  // Test helper functions and mock objects defined here
   102  
   103  var mockConsenter commonConsenter
   104  var mockLocalConfig *localconfig.TopLevel
   105  var mockBrokerConfig *sarama.Config
   106  
   107  func extractEncodedOffset(marshalledOrdererMetadata []byte) int64 {
   108  	omd := &cb.Metadata{}
   109  	_ = proto.Unmarshal(marshalledOrdererMetadata, omd)
   110  	kmd := &ab.KafkaMetadata{}
   111  	_ = proto.Unmarshal(omd.GetValue(), kmd)
   112  	return kmd.LastOffsetPersisted
   113  }
   114  
   115  func newMockBrokerConfig(tlsConfig localconfig.TLS, retryOptions localconfig.Retry, kafkaVersion sarama.KafkaVersion, chosenStaticPartition int32) *sarama.Config {
   116  	brokerConfig := newBrokerConfig(tlsConfig, retryOptions, kafkaVersion, chosenStaticPartition)
   117  	brokerConfig.ClientID = "test"
   118  	return brokerConfig
   119  }
   120  
   121  func newMockConsenter(brokerConfig *sarama.Config, tlsConfig localconfig.TLS, retryOptions localconfig.Retry, kafkaVersion sarama.KafkaVersion) *consenterImpl {
   122  	return &consenterImpl{
   123  		brokerConfigVal: brokerConfig,
   124  		tlsConfigVal:    tlsConfig,
   125  		retryOptionsVal: retryOptions,
   126  		kafkaVersionVal: kafkaVersion,
   127  	}
   128  }
   129  
   130  func newMockConsumerMessage(wrappedMessage *ab.KafkaMessage) *sarama.ConsumerMessage {
   131  	return &sarama.ConsumerMessage{
   132  		Value: sarama.ByteEncoder(utils.MarshalOrPanic(wrappedMessage)),
   133  	}
   134  }
   135  
   136  func newMockEnvelope(content string) *cb.Envelope {
   137  	return &cb.Envelope{Payload: []byte(content)}
   138  }
   139  
   140  func newMockLocalConfig(enableTLS bool, retryOptions localconfig.Retry, verboseLog bool) *localconfig.TopLevel {
   141  	return &localconfig.TopLevel{
   142  		General: localconfig.General{
   143  			TLS: localconfig.TLS{
   144  				Enabled: enableTLS,
   145  			},
   146  		},
   147  		Kafka: localconfig.Kafka{
   148  			Retry:   retryOptions,
   149  			Verbose: verboseLog,
   150  			Version: sarama.V0_9_0_1,
   151  		},
   152  	}
   153  }
   154  
   155  func setupTestLogging(logLevel string, verbose bool) {
   156  	// This call allows us to (a) get the logging backend initialization that
   157  	// takes place in the `flogging` package, and (b) adjust the verbosity of
   158  	// the logs when running tests on this package.
   159  	flogging.SetModuleLevel(pkgLogID, logLevel)
   160  
   161  	if verbose {
   162  		sarama.Logger = log.New(os.Stdout, "[sarama] ", log.Ldate|log.Lmicroseconds|log.Lshortfile)
   163  	}
   164  }
   165  
   166  // Taken from orderer/solo/consensus_test.go
   167  func syncQueueMessage(message *cb.Envelope, chain *chainImpl, mockBlockcutter *mockblockcutter.Receiver) {
   168  	chain.Enqueue(message)
   169  	mockBlockcutter.Block <- struct{}{} // We'll move past this line (and the function will return) only when the mock blockcutter is about to return
   170  }
   171  
   172  func tamperBytes(original []byte) []byte {
   173  	byteCount := len(original)
   174  	return original[:byteCount-1]
   175  }
   176  
   177  func channelNameForTest(t *testing.T) string {
   178  	name := strings.Split(fmt.Sprint(t), " ")[18] // w/golang 1.8, use t.Name()
   179  	return fmt.Sprintf("%s.channel", strings.Replace(strings.ToLower(name), "/", ".", -1))
   180  }