1
+ from contextlib import closing
1
2
import itertools
3
+ import os
4
+ import shutil
2
5
import socket
6
+ import struct
7
+ import tempfile
3
8
from threading import Thread
9
+ import uuid
4
10
5
11
import pytest
6
12
7
13
from datadog .dogstatsd .base import DogStatsd
8
14
9
15
@pytest .mark .parametrize (
10
- "disable_background_sender, disable_buffering, wait_for_pending, socket_timeout, stop" ,
11
- list (itertools .product ([True , False ], [True , False ], [True , False ], [0 , 1 ], [True , False ])),
16
+ "disable_background_sender, disable_buffering, wait_for_pending, socket_timeout, stop, socket_kind " ,
17
+ list (itertools .product ([True , False ], [True , False ], [True , False ], [0 , 1 ], [True , False ], [ socket . SOCK_DGRAM , socket . SOCK_STREAM ] )),
12
18
)
13
- def test_sender_mode (disable_background_sender , disable_buffering , wait_for_pending , socket_timeout , stop ):
19
+ def test_sender_mode (disable_background_sender , disable_buffering , wait_for_pending , socket_timeout , stop , socket_kind ):
14
20
# Test basic sender operation with an assortment of options
15
- foo , bar = socket .socketpair (socket .AF_UNIX , socket . SOCK_DGRAM , 0 )
21
+ foo , bar = socket .socketpair (socket .AF_UNIX , socket_kind , 0 )
16
22
statsd = DogStatsd (
17
23
telemetry_min_flush_interval = 0 ,
18
24
disable_background_sender = disable_background_sender ,
@@ -24,7 +30,11 @@ def test_sender_mode(disable_background_sender, disable_buffering, wait_for_pend
24
30
statsd ._reset_telemetry ()
25
31
26
32
def reader_thread ():
27
- msg = bar .recv (8192 )
33
+ if socket_kind == socket .SOCK_DGRAM :
34
+ msg = bar .recv (8192 )
35
+ else :
36
+ size = struct .unpack ("<I" , bar .recv (4 ))[0 ]
37
+ msg = bar .recv (size )
28
38
assert msg == b"test.metric:1|c\n "
29
39
30
40
t = Thread (target = reader_thread , name = "test_sender_mode/reader_thread" )
@@ -49,6 +59,25 @@ def test_set_socket_timeout():
49
59
statsd .close_socket ()
50
60
assert statsd .get_socket ().gettimeout () == 1
51
61
62
+ def test_stream_cleanup ():
63
+ foo , _ = socket .socketpair (socket .AF_UNIX , socket .SOCK_STREAM , 0 )
64
+
65
+ foo .settimeout (0 )
66
+ statsd = DogStatsd (disable_buffering = True )
67
+ statsd .socket = foo
68
+ statsd .increment ("test" , 1 )
69
+ statsd .increment ("test" , 1 )
70
+ statsd .increment ("test" , 1 )
71
+ assert statsd .socket is not None
72
+
73
+ foo .setsockopt (socket .SOL_SOCKET , socket .SO_SNDBUF , 1 ) # different os's have different mins, e.g. this sets the buffer size to 2304 on certain linux variants
74
+
75
+ with pytest .raises (socket .error ):
76
+ foo .sendall (os .urandom (5000 )) # pre-emptively clog the buffer
77
+
78
+ statsd .increment ("test" , 1 )
79
+
80
+ assert statsd .socket is None
52
81
53
82
@pytest .mark .parametrize (
54
83
"disable_background_sender, disable_buffering" ,
@@ -101,3 +130,41 @@ def test_buffering_with_context():
101
130
bar .settimeout (5 )
102
131
msg = bar .recv (8192 )
103
132
assert msg == b"first:1|c\n "
133
+
134
+ @pytest .fixture ()
135
+ def socket_dir ():
136
+ tempdir = tempfile .mkdtemp ()
137
+ yield tempdir
138
+ shutil .rmtree (tempdir )
139
+
140
+ @pytest .mark .parametrize (
141
+ "socket_prefix, socket_kind, success" ,
142
+ [
143
+ ("" , socket .SOCK_DGRAM , True ),
144
+ ("" , socket .SOCK_STREAM , True ),
145
+ ("unix://" , socket .SOCK_DGRAM , True ),
146
+ ("unix://" , socket .SOCK_STREAM , True ),
147
+ ("unixstream://" , socket .SOCK_DGRAM , False ),
148
+ ("unixstream://" , socket .SOCK_STREAM , True ),
149
+ ("unixgram://" , socket .SOCK_DGRAM , True ),
150
+ ("unixgram://" , socket .SOCK_STREAM , False )
151
+ ]
152
+ )
153
+ def test_socket_connection (socket_dir , socket_prefix , socket_kind , success ):
154
+ socket_path = os .path .join (socket_dir , str (uuid .uuid1 ()) + ".sock" )
155
+ listener_socket = socket .socket (socket .AF_UNIX , socket_kind )
156
+ listener_socket .bind (socket_path )
157
+
158
+ if socket_kind == socket .SOCK_STREAM :
159
+ listener_socket .listen (1 )
160
+
161
+ with closing (listener_socket ):
162
+ statsd = DogStatsd (
163
+ socket_path = socket_prefix + socket_path
164
+ )
165
+
166
+ if success :
167
+ assert statsd .get_socket () is not None
168
+ else :
169
+ with pytest .raises (socket .error ):
170
+ statsd .get_socket ()
0 commit comments