From def33e4811983665bdccc06a06fdab4a646e576f Mon Sep 17 00:00:00 2001 From: Cathy Ouyang Date: Fri, 23 Feb 2024 16:53:53 -0800 Subject: [PATCH 1/2] test: add mutation test case --- gcs/upload.py | 4 +++ tests/test_upload.py | 64 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/gcs/upload.py b/gcs/upload.py index 82a423ca..50764ea4 100644 --- a/gcs/upload.py +++ b/gcs/upload.py @@ -210,6 +210,7 @@ def init_write_object_grpc(cls, db, request_iterator, context): else: print("WARNING unexpected data field %s\n" % data) continue + content = checksummed_data.content crc32c_hash = ( checksummed_data.crc32c if checksummed_data.HasField("crc32c") else None @@ -330,6 +331,9 @@ def process_bidi_write_object_grpc(cls, db, request_iterator, context): # Handles final message with no data to insert. upload.complete = True continue + else: + print("WARNING unexpected data field %s\n" % data) + continue content = checksummed_data.content crc32c_hash = ( diff --git a/tests/test_upload.py b/tests/test_upload.py index ed241482..c1ad3b7e 100644 --- a/tests/test_upload.py +++ b/tests/test_upload.py @@ -694,6 +694,40 @@ def test_init_object_write_grpc_final_message_empty_data(self): self.assertEqual(upload.metadata.name, "object") self.assertEqual(upload.metadata.bucket, "projects/_/buckets/bucket-name") + def test_init_object_write_grpc_message_empty_data(self): + request = testbench.common.FakeRequest( + args={}, data=json.dumps({"name": "bucket-name"}) + ) + bucket, _ = gcs.bucket.Bucket.init(request, None) + request = storage_pb2.StartResumableWriteRequest( + write_object_spec=storage_pb2.WriteObjectSpec( + resource={"name": "object", "bucket": "projects/_/buckets/bucket-name"} + ) + ) + context = self.mock_context() + upload = gcs.upload.Upload.init_resumable_grpc( + request, bucket.metadata, context + ) + + r1 = storage_pb2.WriteObjectRequest( + upload_id=upload.upload_id, + write_offset=0, + finish_write=False, + ) + + context = self.mock_context() + db = unittest.mock.Mock() + db.get_bucket = unittest.mock.MagicMock(return_value=bucket) + db.get_upload = unittest.mock.MagicMock(return_value=upload) + upload, is_resumable = gcs.upload.Upload.init_write_object_grpc( + db, [r1], context + ) + self.assertIsNotNone(upload) + self.assertFalse(upload.complete) + self.assertTrue(is_resumable) + self.assertEqual(upload.metadata.name, "object") + self.assertEqual(upload.metadata.bucket, "projects/_/buckets/bucket-name") + def test_process_bidi_write_grpc_resumable(self): request = testbench.common.FakeRequest( args={}, data=json.dumps({"name": "bucket-name"}) @@ -989,6 +1023,36 @@ def test_process_bidi_write_grpc_final_message_empty_data(self): blob = responses[0].resource self.assertEqual(blob.name, "object") self.assertEqual(blob.bucket, "projects/_/buckets/bucket-name") + self.assertTrue(upload.complete) + + def test_process_bidi_write_grpc_message_empty_data(self): + request = testbench.common.FakeRequest( + args={}, data=json.dumps({"name": "bucket-name"}) + ) + bucket, _ = gcs.bucket.Bucket.init(request, None) + request = storage_pb2.StartResumableWriteRequest( + write_object_spec=storage_pb2.WriteObjectSpec( + resource={"name": "object", "bucket": "projects/_/buckets/bucket-name"} + ) + ) + context = self.mock_context() + upload = gcs.upload.Upload.init_resumable_grpc( + request, bucket.metadata, context + ) + + r1 = storage_pb2.BidiWriteObjectRequest( + upload_id=upload.upload_id, + write_offset=0, + finish_write=False, + ) + context = self.mock_context() + db = unittest.mock.Mock() + db.get_bucket = unittest.mock.MagicMock(return_value=bucket) + db.get_upload = unittest.mock.MagicMock(return_value=upload) + responses = list( + gcs.upload.Upload.process_bidi_write_object_grpc(db, [r1], context) + ) + self.assertFalse(upload.complete) if __name__ == "__main__": From cd5d13bfb053c467d03fe20825270495beefa626 Mon Sep 17 00:00:00 2001 From: Cathy Ouyang Date: Mon, 26 Feb 2024 15:48:14 -0800 Subject: [PATCH 2/2] return error for invalid data fields --- gcs/upload.py | 7 +++---- tests/test_upload.py | 20 +++++++++----------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/gcs/upload.py b/gcs/upload.py index 50764ea4..01650f23 100644 --- a/gcs/upload.py +++ b/gcs/upload.py @@ -208,8 +208,8 @@ def init_write_object_grpc(cls, db, request_iterator, context): upload.complete = True continue else: - print("WARNING unexpected data field %s\n" % data) - continue + testbench.error.invalid("Invalid data field in upload", context) + return None, False content = checksummed_data.content crc32c_hash = ( @@ -332,8 +332,7 @@ def process_bidi_write_object_grpc(cls, db, request_iterator, context): upload.complete = True continue else: - print("WARNING unexpected data field %s\n" % data) - continue + return testbench.error.invalid("Invalid data field in upload", context) content = checksummed_data.content crc32c_hash = ( diff --git a/tests/test_upload.py b/tests/test_upload.py index c1ad3b7e..429d62ea 100644 --- a/tests/test_upload.py +++ b/tests/test_upload.py @@ -694,7 +694,7 @@ def test_init_object_write_grpc_final_message_empty_data(self): self.assertEqual(upload.metadata.name, "object") self.assertEqual(upload.metadata.bucket, "projects/_/buckets/bucket-name") - def test_init_object_write_grpc_message_empty_data(self): + def test_init_object_write_grpc_message_invalid_data(self): request = testbench.common.FakeRequest( args={}, data=json.dumps({"name": "bucket-name"}) ) @@ -719,14 +719,11 @@ def test_init_object_write_grpc_message_empty_data(self): db = unittest.mock.Mock() db.get_bucket = unittest.mock.MagicMock(return_value=bucket) db.get_upload = unittest.mock.MagicMock(return_value=upload) - upload, is_resumable = gcs.upload.Upload.init_write_object_grpc( - db, [r1], context + upload, _ = gcs.upload.Upload.init_write_object_grpc(db, [r1], context) + self.assertIsNone(upload) + context.abort.assert_called_once_with( + grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY ) - self.assertIsNotNone(upload) - self.assertFalse(upload.complete) - self.assertTrue(is_resumable) - self.assertEqual(upload.metadata.name, "object") - self.assertEqual(upload.metadata.bucket, "projects/_/buckets/bucket-name") def test_process_bidi_write_grpc_resumable(self): request = testbench.common.FakeRequest( @@ -1025,7 +1022,7 @@ def test_process_bidi_write_grpc_final_message_empty_data(self): self.assertEqual(blob.bucket, "projects/_/buckets/bucket-name") self.assertTrue(upload.complete) - def test_process_bidi_write_grpc_message_empty_data(self): + def test_process_bidi_write_grpc_message_invalid_data(self): request = testbench.common.FakeRequest( args={}, data=json.dumps({"name": "bucket-name"}) ) @@ -1049,8 +1046,9 @@ def test_process_bidi_write_grpc_message_empty_data(self): db = unittest.mock.Mock() db.get_bucket = unittest.mock.MagicMock(return_value=bucket) db.get_upload = unittest.mock.MagicMock(return_value=upload) - responses = list( - gcs.upload.Upload.process_bidi_write_object_grpc(db, [r1], context) + list(gcs.upload.Upload.process_bidi_write_object_grpc(db, [r1], context)) + context.abort.assert_called_once_with( + grpc.StatusCode.INVALID_ARGUMENT, unittest.mock.ANY ) self.assertFalse(upload.complete)