1package statsd
2
3import (
4	"fmt"
5	"io"
6	"net"
7	"testing"
8	"time"
9
10	"github.com/stretchr/testify/assert"
11	"github.com/stretchr/testify/require"
12)
13
14type statsdWriterWrapper struct{}
15
16func (statsdWriterWrapper) SetWriteTimeout(time.Duration) error {
17	return nil
18}
19
20func (statsdWriterWrapper) Close() error {
21	return nil
22}
23
24func (statsdWriterWrapper) Write(p []byte) (n int, err error) {
25	return 0, nil
26}
27
28func TestCustomWriterBufferConfiguration(t *testing.T) {
29	client, err := NewWithWriter(statsdWriterWrapper{})
30	require.Nil(t, err)
31	defer client.Close()
32
33	assert.Equal(t, OptimalUDPPayloadSize, client.sender.pool.bufferMaxSize)
34	assert.Equal(t, DefaultUDPBufferPoolSize, cap(client.sender.pool.pool))
35	assert.Equal(t, DefaultUDPBufferPoolSize, cap(client.sender.queue))
36}
37
38func getTestServer(t *testing.T, addr string) *net.UDPConn {
39	udpAddr, err := net.ResolveUDPAddr("udp", addr)
40	require.Nil(t, err, fmt.Sprintf("could not resolve udp '%s': %s", addr, err))
41
42	server, err := net.ListenUDP("udp", udpAddr)
43	require.Nil(t, err, fmt.Sprintf("Could not listen to UDP addr: %s", err))
44	return server
45}
46
47func testStatsdPipeline(t *testing.T, client *Client, addr string) {
48	server := getTestServer(t, addr)
49	defer server.Close()
50
51	client.Count("name", 1, []string{"tag"}, 1)
52
53	err := client.Close()
54	require.Nil(t, err, fmt.Sprintf("failed to close client: %s", err))
55
56	readDone := make(chan struct{})
57	buffer := make([]byte, 4096)
58	n := 0
59	go func() {
60		n, _ = io.ReadAtLeast(server, buffer, 1)
61		close(readDone)
62	}()
63
64	select {
65	case <-readDone:
66	case <-time.After(2 * time.Second):
67		require.Fail(t, "No data was flush on Close")
68	}
69
70	result := string(buffer[:n])
71	assert.Equal(t, "name:1|c|#tag", result)
72}
73
74func TestChannelMode(t *testing.T) {
75	addr := "localhost:1201"
76
77	client, err := New(addr, WithChannelMode())
78	require.Nil(t, err, fmt.Sprintf("failed to create client: %s", err))
79	assert.False(t, client.telemetry.devMode)
80
81	testStatsdPipeline(t, client, addr)
82}
83
84func TestMutexMode(t *testing.T) {
85	addr := "localhost:1201"
86
87	client, err := New(addr)
88	require.Nil(t, err, fmt.Sprintf("failed to create client: %s", err))
89	assert.False(t, client.telemetry.devMode)
90
91	testStatsdPipeline(t, client, addr)
92}
93
94func TestDevMode(t *testing.T) {
95	addr := "localhost:1201"
96
97	client, err := New(addr, WithDevMode())
98	require.Nil(t, err, fmt.Sprintf("failed to create client: %s", err))
99	assert.True(t, client.telemetry.devMode)
100
101	testStatsdPipeline(t, client, addr)
102}
103
104func TestCloneWithExtraOptions(t *testing.T) {
105	addr := "localhost:1201"
106
107	client, err := New(addr, WithTags([]string{"tag1", "tag2"}))
108	require.Nil(t, err, fmt.Sprintf("failed to create client: %s", err))
109
110	assert.Equal(t, client.Tags, []string{"tag1", "tag2"})
111	assert.Equal(t, client.Namespace, "")
112	assert.Equal(t, client.receiveMode, MutexMode)
113	assert.Equal(t, client.addrOption, addr)
114	assert.Len(t, client.options, 1)
115
116	cloneClient, err := CloneWithExtraOptions(client, WithNamespace("test"), WithChannelMode())
117	require.Nil(t, err, fmt.Sprintf("failed to clone client: %s", err))
118
119	assert.Equal(t, cloneClient.Tags, []string{"tag1", "tag2"})
120	assert.Equal(t, cloneClient.Namespace, "test.")
121	assert.Equal(t, cloneClient.receiveMode, ChannelMode)
122	assert.Equal(t, cloneClient.addrOption, addr)
123	assert.Len(t, cloneClient.options, 3)
124}
125