1212# See the License for the specific language governing permissions and
1313# limitations under the License.
1414
15+ from copy import deepcopy
16+ from datetime import datetime
17+ from datetime import timedelta
18+ from datetime import timezone
19+
1520import unittest
1621
1722import mock
@@ -33,6 +38,7 @@ class TestClient(unittest.TestCase):
3338 METRIC_NAME = "metric_name"
3439 FILTER = "logName:syslog AND severity>=ERROR"
3540 DESCRIPTION = "DESCRIPTION"
41+ TIME_FORMAT = '"%Y-%m-%dT%H:%M:%S.%f%z"'
3642
3743 @staticmethod
3844 def _get_target_class ():
@@ -279,15 +285,27 @@ def test_list_entries_defaults(self):
279285 self .assertEqual (logger .project , self .PROJECT )
280286 self .assertEqual (token , TOKEN )
281287
282- called_with = client ._connection ._called_with
288+ # check call payload
289+ call_payload_no_filter = deepcopy (client ._connection ._called_with )
290+ call_payload_no_filter ["data" ]["filter" ] = "removed"
283291 self .assertEqual (
284- called_with ,
292+ call_payload_no_filter ,
285293 {
286294 "path" : "/entries:list" ,
287295 "method" : "POST" ,
288- "data" : {"projectIds" : [self .PROJECT ]},
296+ "data" : {
297+ "filter" : "removed" ,
298+ "projectIds" : [self .PROJECT ],
299+ },
289300 },
290301 )
302+ # verify that default filter is 24 hours
303+ timestamp = datetime .strptime (
304+ client ._connection ._called_with ["data" ]["filter" ],
305+ "timestamp>=" + self .TIME_FORMAT ,
306+ )
307+ yesterday = datetime .now (timezone .utc ) - timedelta (days = 1 )
308+ self .assertLess (yesterday - timestamp , timedelta (minutes = 1 ))
291309
292310 def test_list_entries_explicit (self ):
293311 from google .cloud .logging import DESCENDING
@@ -297,7 +315,7 @@ def test_list_entries_explicit(self):
297315
298316 PROJECT1 = "PROJECT1"
299317 PROJECT2 = "PROJECT2"
300- FILTER = "logName:LOGNAME"
318+ INPUT_FILTER = "logName:LOGNAME"
301319 IID1 = "IID1"
302320 IID2 = "IID2"
303321 PAYLOAD = {"message" : "MESSAGE" , "weather" : "partly cloudy" }
@@ -327,7 +345,7 @@ def test_list_entries_explicit(self):
327345
328346 iterator = client .list_entries (
329347 projects = [PROJECT1 , PROJECT2 ],
330- filter_ = FILTER ,
348+ filter_ = INPUT_FILTER ,
331349 order_by = DESCENDING ,
332350 page_size = PAGE_SIZE ,
333351 page_token = TOKEN ,
@@ -360,14 +378,111 @@ def test_list_entries_explicit(self):
360378
361379 self .assertIs (entries [0 ].logger , entries [1 ].logger )
362380
363- called_with = client ._connection ._called_with
381+ # check call payload
382+ call_payload_no_filter = deepcopy (client ._connection ._called_with )
383+ call_payload_no_filter ["data" ]["filter" ] = "removed"
364384 self .assertEqual (
365- called_with ,
385+ call_payload_no_filter ,
386+ {
387+ "path" : "/entries:list" ,
388+ "method" : "POST" ,
389+ "data" : {
390+ "filter" : "removed" ,
391+ "orderBy" : DESCENDING ,
392+ "pageSize" : PAGE_SIZE ,
393+ "pageToken" : TOKEN ,
394+ "projectIds" : [PROJECT1 , PROJECT2 ],
395+ },
396+ },
397+ )
398+ # verify that default timestamp filter is added
399+ timestamp = datetime .strptime (
400+ client ._connection ._called_with ["data" ]["filter" ],
401+ INPUT_FILTER + " AND timestamp>=" + self .TIME_FORMAT ,
402+ )
403+ yesterday = datetime .now (timezone .utc ) - timedelta (days = 1 )
404+ self .assertLess (yesterday - timestamp , timedelta (minutes = 1 ))
405+
406+ def test_list_entries_explicit_timestamp (self ):
407+ from google .cloud .logging import DESCENDING
408+ from google .cloud .logging .entries import ProtobufEntry
409+ from google .cloud .logging .entries import StructEntry
410+ from google .cloud .logging .logger import Logger
411+
412+ PROJECT1 = "PROJECT1"
413+ PROJECT2 = "PROJECT2"
414+ INPUT_FILTER = 'logName:LOGNAME AND timestamp="2020-10-13T21"'
415+ IID1 = "IID1"
416+ IID2 = "IID2"
417+ PAYLOAD = {"message" : "MESSAGE" , "weather" : "partly cloudy" }
418+ PROTO_PAYLOAD = PAYLOAD .copy ()
419+ PROTO_PAYLOAD ["@type" ] = "type.googleapis.com/testing.example"
420+ TOKEN = "TOKEN"
421+ PAGE_SIZE = 42
422+ ENTRIES = [
423+ {
424+ "jsonPayload" : PAYLOAD ,
425+ "insertId" : IID1 ,
426+ "resource" : {"type" : "global" },
427+ "logName" : "projects/%s/logs/%s" % (self .PROJECT , self .LOGGER_NAME ),
428+ },
429+ {
430+ "protoPayload" : PROTO_PAYLOAD ,
431+ "insertId" : IID2 ,
432+ "resource" : {"type" : "global" },
433+ "logName" : "projects/%s/logs/%s" % (self .PROJECT , self .LOGGER_NAME ),
434+ },
435+ ]
436+ client = self ._make_one (
437+ self .PROJECT , credentials = _make_credentials (), _use_grpc = False
438+ )
439+ returned = {"entries" : ENTRIES }
440+ client ._connection = _Connection (returned )
441+
442+ iterator = client .list_entries (
443+ projects = [PROJECT1 , PROJECT2 ],
444+ filter_ = INPUT_FILTER ,
445+ order_by = DESCENDING ,
446+ page_size = PAGE_SIZE ,
447+ page_token = TOKEN ,
448+ )
449+ entries = list (iterator )
450+ token = iterator .next_page_token
451+
452+ # First, check the token.
453+ self .assertIsNone (token )
454+ # Then check the entries.
455+ self .assertEqual (len (entries ), 2 )
456+ entry = entries [0 ]
457+ self .assertIsInstance (entry , StructEntry )
458+ self .assertEqual (entry .insert_id , IID1 )
459+ self .assertEqual (entry .payload , PAYLOAD )
460+ logger = entry .logger
461+ self .assertIsInstance (logger , Logger )
462+ self .assertEqual (logger .name , self .LOGGER_NAME )
463+ self .assertIs (logger .client , client )
464+ self .assertEqual (logger .project , self .PROJECT )
465+
466+ entry = entries [1 ]
467+ self .assertIsInstance (entry , ProtobufEntry )
468+ self .assertEqual (entry .insert_id , IID2 )
469+ self .assertEqual (entry .payload , PROTO_PAYLOAD )
470+ logger = entry .logger
471+ self .assertEqual (logger .name , self .LOGGER_NAME )
472+ self .assertIs (logger .client , client )
473+ self .assertEqual (logger .project , self .PROJECT )
474+
475+ self .assertIs (entries [0 ].logger , entries [1 ].logger )
476+
477+ # check call payload
478+ # filter should not be changed
479+ self .assertEqual (
480+ client ._connection ._called_with ,
366481 {
367482 "path" : "/entries:list" ,
368483 "method" : "POST" ,
369484 "data" : {
370- "filter" : FILTER ,
485+ "filter" : INPUT_FILTER ,
371486 "orderBy" : DESCENDING ,
372487 "pageSize" : PAGE_SIZE ,
373488 "pageToken" : TOKEN ,
0 commit comments