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 }