diff --git a/statsd/statsd_test.go b/statsd/statsd_test.go index 987e9159..978001b1 100644 --- a/statsd/statsd_test.go +++ b/statsd/statsd_test.go @@ -4,6 +4,7 @@ import ( "fmt" "io" "net" + "sync" "testing" "time" @@ -35,6 +36,62 @@ func TestCustomWriterBufferConfiguration(t *testing.T) { assert.Equal(t, DefaultUDPBufferPoolSize, cap(client.sender.queue)) } +// TestConcurrentSend sends various metric types in separate goroutines to +// trigger any possible data races. It is intended to be run with the data race +// detector enabled. +func TestConcurrentSend(t *testing.T) { + tests := []struct { + description string + clientOptions []Option + }{ + { + description: "Client with default options", + clientOptions: []Option{}, + }, + { + description: "Client with mutex mode enabled", + clientOptions: []Option{WithMutexMode()}, + }, + { + description: "Client with channel mode enabled", + clientOptions: []Option{WithChannelMode()}, + }, + } + + for _, test := range tests { + test := test // Capture range variable. + t.Run(test.description, func(t *testing.T) { + t.Parallel() + + client, err := New("localhost:9876", test.clientOptions...) + require.Nil(t, err, fmt.Sprintf("failed to create client: %s", err)) + + var wg sync.WaitGroup + wg.Add(1) + go func() { + client.Gauge("name", 1, []string{"tag"}, 0.1) + wg.Done() + }() + + wg.Add(1) + go func() { + client.Count("name", 1, []string{"tag"}, 0.1) + wg.Done() + }() + + wg.Add(1) + go func() { + client.Timing("name", 1, []string{"tag"}, 0.1) + wg.Done() + }() + + wg.Wait() + err = client.Close() + require.Nil(t, err, fmt.Sprintf("failed to close client: %s", err)) + }) + } +} + func getTestServer(t *testing.T, addr string) *net.UDPConn { udpAddr, err := net.ResolveUDPAddr("udp", addr) require.Nil(t, err, fmt.Sprintf("could not resolve udp '%s': %s", addr, err))