go.opentelemetry.io/contrib/instrumentation/github.com/Shopify/sarama/otelsarama@v0.43.0/producer_test.go (about)

     1  // Copyright The OpenTelemetry Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package otelsarama
    16  
    17  import (
    18  	"testing"
    19  	"time"
    20  
    21  	"github.com/Shopify/sarama"
    22  	"github.com/Shopify/sarama/mocks"
    23  	"github.com/stretchr/testify/assert"
    24  
    25  	oteltrace "go.opentelemetry.io/otel/trace"
    26  )
    27  
    28  func TestAsyncProducer_ConcurrencyEdgeCases(t *testing.T) {
    29  	cfg := newSaramaConfig()
    30  	testCases := []struct {
    31  		name             string
    32  		newAsyncProducer func(t *testing.T) sarama.AsyncProducer
    33  	}{
    34  		{
    35  			name: "original",
    36  			newAsyncProducer: func(t *testing.T) sarama.AsyncProducer {
    37  				return mocks.NewAsyncProducer(t, cfg)
    38  			},
    39  		},
    40  		{
    41  			name: "wrapped",
    42  			newAsyncProducer: func(t *testing.T) sarama.AsyncProducer {
    43  				var ap sarama.AsyncProducer = mocks.NewAsyncProducer(t, cfg)
    44  				ap = WrapAsyncProducer(cfg, ap)
    45  				return ap
    46  			},
    47  		},
    48  	}
    49  
    50  	for _, tc := range testCases {
    51  		t.Run(tc.name, func(t *testing.T) {
    52  			t.Run("closes Successes and Error after Close", func(t *testing.T) {
    53  				timeout := time.NewTimer(time.Minute)
    54  				defer timeout.Stop()
    55  				p := tc.newAsyncProducer(t)
    56  
    57  				p.Close()
    58  
    59  				select {
    60  				case <-timeout.C:
    61  					t.Error("timeout - Successes channel was not closed")
    62  				case _, ok := <-p.Successes():
    63  					if ok {
    64  						t.Error("message was send to Successes channel instead of being closed")
    65  					}
    66  				}
    67  
    68  				select {
    69  				case <-timeout.C:
    70  					t.Error("timeout - Errors channel was not closed")
    71  				case _, ok := <-p.Errors():
    72  					if ok {
    73  						t.Error("message was send to Errors channel instead of being closed")
    74  					}
    75  				}
    76  			})
    77  
    78  			t.Run("closes Successes and Error after AsyncClose", func(t *testing.T) {
    79  				timeout := time.NewTimer(time.Minute)
    80  				defer timeout.Stop()
    81  				p := tc.newAsyncProducer(t)
    82  
    83  				p.AsyncClose()
    84  
    85  				select {
    86  				case <-timeout.C:
    87  					t.Error("timeout - Successes channel was not closed")
    88  				case _, ok := <-p.Successes():
    89  					if ok {
    90  						t.Error("message was send to Successes channel instead of being closed")
    91  					}
    92  				}
    93  
    94  				select {
    95  				case <-timeout.C:
    96  					t.Error("timeout - Errors channel was not closed")
    97  				case _, ok := <-p.Errors():
    98  					if ok {
    99  						t.Error("message was send to Errors channel instead of being closed")
   100  					}
   101  				}
   102  			})
   103  
   104  			t.Run("panic when sending to Input after Close", func(t *testing.T) {
   105  				p := tc.newAsyncProducer(t)
   106  				p.Close()
   107  				assert.Panics(t, func() {
   108  					p.Input() <- &sarama.ProducerMessage{Key: sarama.StringEncoder("foo")}
   109  				})
   110  			})
   111  
   112  			t.Run("panic when sending to Input after AsyncClose", func(t *testing.T) {
   113  				p := tc.newAsyncProducer(t)
   114  				p.AsyncClose()
   115  				assert.Panics(t, func() {
   116  					p.Input() <- &sarama.ProducerMessage{Key: sarama.StringEncoder("foo")}
   117  				})
   118  			})
   119  
   120  			t.Run("panic when calling Close after AsyncClose", func(t *testing.T) {
   121  				p := tc.newAsyncProducer(t)
   122  				p.AsyncClose()
   123  				assert.Panics(t, func() {
   124  					p.Close()
   125  				})
   126  			})
   127  
   128  			t.Run("panic when calling AsyncClose after Close", func(t *testing.T) {
   129  				p := tc.newAsyncProducer(t)
   130  				p.Close()
   131  				assert.Panics(t, func() {
   132  					p.AsyncClose()
   133  				})
   134  			})
   135  		})
   136  	}
   137  }
   138  
   139  func newSaramaConfig() *sarama.Config {
   140  	cfg := sarama.NewConfig()
   141  	cfg.Version = sarama.V0_11_0_0
   142  	return cfg
   143  }
   144  
   145  func BenchmarkWrapSyncProducer(b *testing.B) {
   146  	// Mock provider
   147  	provider := oteltrace.NewNoopTracerProvider()
   148  
   149  	cfg := newSaramaConfig()
   150  	// Mock sync producer
   151  	mockSyncProducer := mocks.NewSyncProducer(b, cfg)
   152  
   153  	// Wrap sync producer
   154  	syncProducer := WrapSyncProducer(cfg, mockSyncProducer, WithTracerProvider(provider))
   155  	message := sarama.ProducerMessage{Key: sarama.StringEncoder("foo")}
   156  
   157  	b.ReportAllocs()
   158  	b.ResetTimer()
   159  
   160  	for i := 0; i < b.N; i++ {
   161  		mockSyncProducer.ExpectSendMessageAndSucceed()
   162  		_, _, err := syncProducer.SendMessage(&message)
   163  		assert.NoError(b, err)
   164  	}
   165  }
   166  
   167  func BenchmarkMockSyncProducer(b *testing.B) {
   168  	cfg := newSaramaConfig()
   169  	// Mock sync producer
   170  	mockSyncProducer := mocks.NewSyncProducer(b, cfg)
   171  
   172  	// Wrap sync producer
   173  	syncProducer := mockSyncProducer
   174  	message := sarama.ProducerMessage{Key: sarama.StringEncoder("foo")}
   175  
   176  	b.ReportAllocs()
   177  	b.ResetTimer()
   178  
   179  	for i := 0; i < b.N; i++ {
   180  		mockSyncProducer.ExpectSendMessageAndSucceed()
   181  		_, _, err := syncProducer.SendMessage(&message)
   182  		assert.NoError(b, err)
   183  	}
   184  }
   185  
   186  func BenchmarkWrapAsyncProducer(b *testing.B) {
   187  	// Mock provider
   188  	provider := oteltrace.NewNoopTracerProvider()
   189  
   190  	cfg := newSaramaConfig()
   191  	cfg.Producer.Return.Successes = true
   192  	mockAsyncProducer := mocks.NewAsyncProducer(b, cfg)
   193  
   194  	// Wrap sync producer
   195  	asyncProducer := WrapAsyncProducer(cfg, mockAsyncProducer, WithTracerProvider(provider))
   196  	message := sarama.ProducerMessage{Key: sarama.StringEncoder("foo")}
   197  
   198  	b.ReportAllocs()
   199  	b.ResetTimer()
   200  
   201  	for i := 0; i < b.N; i++ {
   202  		mockAsyncProducer.ExpectInputAndSucceed()
   203  		asyncProducer.Input() <- &message
   204  		<-asyncProducer.Successes()
   205  	}
   206  }
   207  
   208  func BenchmarkMockAsyncProducer(b *testing.B) {
   209  	cfg := newSaramaConfig()
   210  	cfg.Producer.Return.Successes = true
   211  	mockAsyncProducer := mocks.NewAsyncProducer(b, cfg)
   212  
   213  	// Wrap sync producer
   214  	asyncProducer := mockAsyncProducer
   215  	message := sarama.ProducerMessage{Key: sarama.StringEncoder("foo")}
   216  
   217  	b.ReportAllocs()
   218  	b.ResetTimer()
   219  
   220  	for i := 0; i < b.N; i++ {
   221  		mockAsyncProducer.ExpectInputAndSucceed()
   222  		mockAsyncProducer.Input() <- &message
   223  		<-asyncProducer.Successes()
   224  	}
   225  }