@@ -78,19 +78,24 @@ def test_flush(self):
7878
7979 def test_worker (self ):
8080 client = _Client (self .PROJECT )
81- name = 'python_logger'
81+ name = 'python_logger'
8282 batch_size = 30
8383 grace_period = 20.
84+ max_latency = 0.1
8485 transport , worker = self ._make_one (client ,
8586 name ,
8687 grace_period = grace_period ,
87- batch_size = batch_size )
88+ batch_size = batch_size ,
89+ max_latency = max_latency )
8890 worker_grace_period = worker .call_args [1 ]['grace_period' ] # **kwargs.
8991 worker_batch_size = worker .call_args [1 ]['max_batch_size' ]
92+ worker_max_latency = worker .call_args [1 ]['max_latency' ]
9093 self .assertEqual (worker_grace_period ,
9194 grace_period )
9295 self .assertEqual (worker_batch_size ,
9396 batch_size )
97+ self .assertEqual (worker_max_latency ,
98+ max_latency )
9499
95100
96101class Test_Worker (unittest .TestCase ):
@@ -115,13 +120,16 @@ def test_constructor(self):
115120 logger = _Logger (self .NAME )
116121 grace_period = 50
117122 max_batch_size = 50
123+ max_latency = 0.1
118124
119125 worker = self ._make_one (
120- logger , grace_period = grace_period , max_batch_size = max_batch_size )
126+ logger , grace_period = grace_period , max_batch_size = max_batch_size ,
127+ max_latency = max_latency )
121128
122129 self .assertEqual (worker ._cloud_logger , logger )
123130 self .assertEqual (worker ._grace_period , grace_period )
124131 self .assertEqual (worker ._max_batch_size , max_batch_size )
132+ self .assertEqual (worker ._max_latency , max_latency )
125133 self .assertFalse (worker .is_alive )
126134 self .assertIsNone (worker ._thread )
127135
@@ -264,6 +272,74 @@ def test__thread_main_batches(self):
264272 self .assertFalse (worker ._cloud_logger ._batch .commit_called )
265273 self .assertEqual (worker ._queue .qsize (), 0 )
266274
275+ @mock .patch ('time.time' , autospec = True , return_value = 1 )
276+ def test__thread_main_max_latency (self , time ):
277+ # Note: this test is a bit brittle as it assumes the operation of
278+ # _get_many invokes queue.get() followed by queue._get(). It fails
279+ # the "change detector" test in that way. However, this is still a
280+ # useful test to verify the queue timeout is appropriately calculated.
281+ from six .moves import queue
282+ from google .cloud .logging .handlers .transports import background_thread
283+
284+ # Use monotonically increasing time.
285+ time .side_effect = range (1 , 6 )
286+
287+ worker = self ._make_one (
288+ _Logger (self .NAME ), max_latency = 2 , max_batch_size = 10 )
289+ worker ._queue = mock .create_autospec (queue .Queue , instance = True )
290+
291+ worker ._queue .get .side_effect = [
292+ {'info' : {'message' : '1' }}, # Single record.
293+ queue .Empty (), # Emulate a queue.get() timeout.
294+ {'info' : {'message' : '1' }}, # Second record.
295+ background_thread ._WORKER_TERMINATOR , # Stop the thread.
296+ queue .Empty (), # Emulate a queue.get() timeout.
297+ ]
298+
299+ worker ._thread_main ()
300+
301+ self .assertEqual (worker ._cloud_logger ._num_batches , 2 )
302+ self .assertTrue (worker ._cloud_logger ._batch .commit_called )
303+ self .assertEqual (worker ._cloud_logger ._batch .commit_count , 1 )
304+
305+ # Time should have been called five times.
306+ #
307+ # For the first batch, it should have been called:
308+ # * Once to get the start time. (1)
309+ # * Once to get the elapsed time while grabbing the second item.
310+ # (2)
311+ #
312+ # For the second batch, it should have been called:
313+ # * Once to get start time. (3)
314+ # * Once to get the elapsed time while grabbing the second item.
315+ # (3)
316+ # * Once to get the elapsed time while grabbing the final
317+ # item. (4)
318+ # * Once final time to get the elapsed time while receiving
319+ # the empty queue.
320+ #
321+ self .assertEqual (time .call_count , 5 )
322+
323+ # Queue.get should've been called 5 times as well, but with different
324+ # timeouts due to the monotonically increasing time.
325+ #
326+ # For the first batch, it will be called once without a timeout
327+ # (for the first item) and then with timeout=1, as start will be
328+ # 1 and now will be 2.
329+ #
330+ # For the second batch, it will be called once without a timeout
331+ # (for the first item) and then with timeout=1, as start will be
332+ # 3 and now will be 4, and finally with timeout=0 as start will be 3
333+ # and now will be 5.
334+ #
335+ worker ._queue .get .assert_has_calls ([
336+ mock .call (),
337+ mock .call (timeout = 1 ),
338+ mock .call (),
339+ mock .call (timeout = 1 ),
340+ mock .call (timeout = 0 )
341+ ])
342+
267343 def test_flush (self ):
268344 worker = self ._make_one (_Logger (self .NAME ))
269345 worker ._queue = mock .Mock (spec = queue .Queue )
@@ -331,9 +407,11 @@ def __init__(self, name):
331407 self .name = name
332408 self ._batch_cls = _Batch
333409 self ._batch = None
410+ self ._num_batches = 0
334411
335412 def batch (self ):
336413 self ._batch = self ._batch_cls ()
414+ self ._num_batches += 1
337415 return self ._batch
338416
339417
0 commit comments