1*14675a02SAndroid Build Coastguard Worker# Copyright 2022 Google LLC 2*14675a02SAndroid Build Coastguard Worker# 3*14675a02SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*14675a02SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*14675a02SAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*14675a02SAndroid Build Coastguard Worker# 7*14675a02SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*14675a02SAndroid Build Coastguard Worker# 9*14675a02SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*14675a02SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*14675a02SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*14675a02SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*14675a02SAndroid Build Coastguard Worker# limitations under the License. 14*14675a02SAndroid Build Coastguard Worker"""Tests for media.""" 15*14675a02SAndroid Build Coastguard Worker 16*14675a02SAndroid Build Coastguard Workerimport http 17*14675a02SAndroid Build Coastguard Workerfrom unittest import mock 18*14675a02SAndroid Build Coastguard Workerimport uuid 19*14675a02SAndroid Build Coastguard Worker 20*14675a02SAndroid Build Coastguard Workerfrom absl.testing import absltest 21*14675a02SAndroid Build Coastguard Worker 22*14675a02SAndroid Build Coastguard Workerfrom fcp.demo import http_actions 23*14675a02SAndroid Build Coastguard Workerfrom fcp.demo import media 24*14675a02SAndroid Build Coastguard Workerfrom fcp.protos.federatedcompute import common_pb2 25*14675a02SAndroid Build Coastguard Worker 26*14675a02SAndroid Build Coastguard Worker 27*14675a02SAndroid Build Coastguard Workerclass MediaTest(absltest.TestCase): 28*14675a02SAndroid Build Coastguard Worker 29*14675a02SAndroid Build Coastguard Worker @mock.patch.object(uuid, 'uuid4', return_value=uuid.uuid4(), autospec=True) 30*14675a02SAndroid Build Coastguard Worker def test_create_download_group(self, mock_uuid): 31*14675a02SAndroid Build Coastguard Worker forwarding_info = common_pb2.ForwardingInfo( 32*14675a02SAndroid Build Coastguard Worker target_uri_prefix='https://media.example/') 33*14675a02SAndroid Build Coastguard Worker service = media.Service(lambda: forwarding_info) 34*14675a02SAndroid Build Coastguard Worker with service.create_download_group() as group: 35*14675a02SAndroid Build Coastguard Worker self.assertEqual(group.prefix, 36*14675a02SAndroid Build Coastguard Worker f'https://media.example/data/{mock_uuid.return_value}/') 37*14675a02SAndroid Build Coastguard Worker name = 'file-name' 38*14675a02SAndroid Build Coastguard Worker self.assertEqual(group.add(name, b'data'), group.prefix + name) 39*14675a02SAndroid Build Coastguard Worker 40*14675a02SAndroid Build Coastguard Worker def test_download(self): 41*14675a02SAndroid Build Coastguard Worker service = media.Service(common_pb2.ForwardingInfo) 42*14675a02SAndroid Build Coastguard Worker with service.create_download_group() as group: 43*14675a02SAndroid Build Coastguard Worker data = b'data' 44*14675a02SAndroid Build Coastguard Worker url = group.add('name', data) 45*14675a02SAndroid Build Coastguard Worker self.assertEqual( 46*14675a02SAndroid Build Coastguard Worker service.download(b'', 47*14675a02SAndroid Build Coastguard Worker *url.split('/')[-2:]), 48*14675a02SAndroid Build Coastguard Worker http_actions.HttpResponse( 49*14675a02SAndroid Build Coastguard Worker body=data, 50*14675a02SAndroid Build Coastguard Worker headers={ 51*14675a02SAndroid Build Coastguard Worker 'Content-Length': len(data), 52*14675a02SAndroid Build Coastguard Worker 'Content-Type': 'application/octet-stream', 53*14675a02SAndroid Build Coastguard Worker })) 54*14675a02SAndroid Build Coastguard Worker 55*14675a02SAndroid Build Coastguard Worker def test_download_with_content_type(self): 56*14675a02SAndroid Build Coastguard Worker service = media.Service(common_pb2.ForwardingInfo) 57*14675a02SAndroid Build Coastguard Worker with service.create_download_group() as group: 58*14675a02SAndroid Build Coastguard Worker data = b'data' 59*14675a02SAndroid Build Coastguard Worker content_type = 'application/x-test' 60*14675a02SAndroid Build Coastguard Worker url = group.add('name', data, content_type=content_type) 61*14675a02SAndroid Build Coastguard Worker self.assertEqual( 62*14675a02SAndroid Build Coastguard Worker service.download(b'', 63*14675a02SAndroid Build Coastguard Worker *url.split('/')[-2:]), 64*14675a02SAndroid Build Coastguard Worker http_actions.HttpResponse( 65*14675a02SAndroid Build Coastguard Worker body=data, 66*14675a02SAndroid Build Coastguard Worker headers={ 67*14675a02SAndroid Build Coastguard Worker 'Content-Length': len(data), 68*14675a02SAndroid Build Coastguard Worker 'Content-Type': content_type, 69*14675a02SAndroid Build Coastguard Worker })) 70*14675a02SAndroid Build Coastguard Worker 71*14675a02SAndroid Build Coastguard Worker def test_download_multiple_files(self): 72*14675a02SAndroid Build Coastguard Worker service = media.Service(common_pb2.ForwardingInfo) 73*14675a02SAndroid Build Coastguard Worker with service.create_download_group() as group: 74*14675a02SAndroid Build Coastguard Worker data1 = b'data1' 75*14675a02SAndroid Build Coastguard Worker data2 = b'data2' 76*14675a02SAndroid Build Coastguard Worker url1 = group.add('file1', data1) 77*14675a02SAndroid Build Coastguard Worker url2 = group.add('file2', data2) 78*14675a02SAndroid Build Coastguard Worker self.assertEqual(service.download(b'', *url1.split('/')[-2:]).body, data1) 79*14675a02SAndroid Build Coastguard Worker self.assertEqual(service.download(b'', *url2.split('/')[-2:]).body, data2) 80*14675a02SAndroid Build Coastguard Worker 81*14675a02SAndroid Build Coastguard Worker def test_download_multiple_groups(self): 82*14675a02SAndroid Build Coastguard Worker service = media.Service(common_pb2.ForwardingInfo) 83*14675a02SAndroid Build Coastguard Worker with service.create_download_group() as group1, ( 84*14675a02SAndroid Build Coastguard Worker service.create_download_group()) as group2: 85*14675a02SAndroid Build Coastguard Worker self.assertNotEqual(group1.prefix, group2.prefix) 86*14675a02SAndroid Build Coastguard Worker data1 = b'data1' 87*14675a02SAndroid Build Coastguard Worker data2 = b'data2' 88*14675a02SAndroid Build Coastguard Worker url1 = group1.add('name', data1) 89*14675a02SAndroid Build Coastguard Worker url2 = group2.add('name', data2) 90*14675a02SAndroid Build Coastguard Worker self.assertEqual(service.download(b'', *url1.split('/')[-2:]).body, data1) 91*14675a02SAndroid Build Coastguard Worker self.assertEqual(service.download(b'', *url2.split('/')[-2:]).body, data2) 92*14675a02SAndroid Build Coastguard Worker 93*14675a02SAndroid Build Coastguard Worker def test_download_unregistered_group(self): 94*14675a02SAndroid Build Coastguard Worker service = media.Service(common_pb2.ForwardingInfo) 95*14675a02SAndroid Build Coastguard Worker with self.assertRaises(http_actions.HttpError) as cm: 96*14675a02SAndroid Build Coastguard Worker service.download(b'', 'does-not-exist', 'does-not-exist') 97*14675a02SAndroid Build Coastguard Worker self.assertEqual(cm.exception.code, http.HTTPStatus.NOT_FOUND) 98*14675a02SAndroid Build Coastguard Worker 99*14675a02SAndroid Build Coastguard Worker def test_download_unregistered_file(self): 100*14675a02SAndroid Build Coastguard Worker service = media.Service(common_pb2.ForwardingInfo) 101*14675a02SAndroid Build Coastguard Worker with service.create_download_group() as group: 102*14675a02SAndroid Build Coastguard Worker url = group.add('name', b'data') 103*14675a02SAndroid Build Coastguard Worker with self.assertRaises(http_actions.HttpError) as cm: 104*14675a02SAndroid Build Coastguard Worker service.download(b'', url.split('/')[-2], 'does-not-exist') 105*14675a02SAndroid Build Coastguard Worker self.assertEqual(cm.exception.code, http.HTTPStatus.NOT_FOUND) 106*14675a02SAndroid Build Coastguard Worker 107*14675a02SAndroid Build Coastguard Worker def test_download_no_longer_registered(self): 108*14675a02SAndroid Build Coastguard Worker service = media.Service(common_pb2.ForwardingInfo) 109*14675a02SAndroid Build Coastguard Worker with service.create_download_group() as group: 110*14675a02SAndroid Build Coastguard Worker url = group.add('name', b'data') 111*14675a02SAndroid Build Coastguard Worker with self.assertRaises(http_actions.HttpError) as cm: 112*14675a02SAndroid Build Coastguard Worker service.download(b'', *url.split('/')[-2:]) 113*14675a02SAndroid Build Coastguard Worker self.assertEqual(cm.exception.code, http.HTTPStatus.NOT_FOUND) 114*14675a02SAndroid Build Coastguard Worker 115*14675a02SAndroid Build Coastguard Worker def test_register_duplicate_download(self): 116*14675a02SAndroid Build Coastguard Worker service = media.Service(common_pb2.ForwardingInfo) 117*14675a02SAndroid Build Coastguard Worker with service.create_download_group() as group: 118*14675a02SAndroid Build Coastguard Worker data1 = b'data' 119*14675a02SAndroid Build Coastguard Worker url = group.add('name', data1) 120*14675a02SAndroid Build Coastguard Worker with self.assertRaises(KeyError): 121*14675a02SAndroid Build Coastguard Worker group.add('name', b'data2') 122*14675a02SAndroid Build Coastguard Worker 123*14675a02SAndroid Build Coastguard Worker # The original file should still be downloadable. 124*14675a02SAndroid Build Coastguard Worker self.assertEqual(service.download(b'', *url.split('/')[-2:]).body, data1) 125*14675a02SAndroid Build Coastguard Worker 126*14675a02SAndroid Build Coastguard Worker def test_upload(self): 127*14675a02SAndroid Build Coastguard Worker service = media.Service(common_pb2.ForwardingInfo) 128*14675a02SAndroid Build Coastguard Worker name = service.register_upload() 129*14675a02SAndroid Build Coastguard Worker data = b'data' 130*14675a02SAndroid Build Coastguard Worker self.assertEqual( 131*14675a02SAndroid Build Coastguard Worker service.upload(data, name), http_actions.HttpResponse(body=b'')) 132*14675a02SAndroid Build Coastguard Worker self.assertEqual(service.finalize_upload(name), data) 133*14675a02SAndroid Build Coastguard Worker 134*14675a02SAndroid Build Coastguard Worker def test_upload_without_data(self): 135*14675a02SAndroid Build Coastguard Worker service = media.Service(common_pb2.ForwardingInfo) 136*14675a02SAndroid Build Coastguard Worker name = service.register_upload() 137*14675a02SAndroid Build Coastguard Worker self.assertIsNone(service.finalize_upload(name)) 138*14675a02SAndroid Build Coastguard Worker 139*14675a02SAndroid Build Coastguard Worker def test_upload_multiple_times(self): 140*14675a02SAndroid Build Coastguard Worker service = media.Service(common_pb2.ForwardingInfo) 141*14675a02SAndroid Build Coastguard Worker name = service.register_upload() 142*14675a02SAndroid Build Coastguard Worker 143*14675a02SAndroid Build Coastguard Worker data = b'data1' 144*14675a02SAndroid Build Coastguard Worker self.assertEqual( 145*14675a02SAndroid Build Coastguard Worker service.upload(data, name), http_actions.HttpResponse(body=b'')) 146*14675a02SAndroid Build Coastguard Worker 147*14675a02SAndroid Build Coastguard Worker with self.assertRaises(http_actions.HttpError) as cm: 148*14675a02SAndroid Build Coastguard Worker service.upload(b'data2', name) 149*14675a02SAndroid Build Coastguard Worker self.assertEqual(cm.exception.code, http.HTTPStatus.UNAUTHORIZED) 150*14675a02SAndroid Build Coastguard Worker 151*14675a02SAndroid Build Coastguard Worker self.assertEqual(service.finalize_upload(name), data) 152*14675a02SAndroid Build Coastguard Worker 153*14675a02SAndroid Build Coastguard Worker def test_upload_multiple(self): 154*14675a02SAndroid Build Coastguard Worker service = media.Service(common_pb2.ForwardingInfo) 155*14675a02SAndroid Build Coastguard Worker name1 = service.register_upload() 156*14675a02SAndroid Build Coastguard Worker name2 = service.register_upload() 157*14675a02SAndroid Build Coastguard Worker 158*14675a02SAndroid Build Coastguard Worker # Order shouldn't matter. 159*14675a02SAndroid Build Coastguard Worker service.upload(b'data2', name2) 160*14675a02SAndroid Build Coastguard Worker service.upload(b'data1', name1) 161*14675a02SAndroid Build Coastguard Worker 162*14675a02SAndroid Build Coastguard Worker self.assertEqual(service.finalize_upload(name1), b'data1') 163*14675a02SAndroid Build Coastguard Worker self.assertEqual(service.finalize_upload(name2), b'data2') 164*14675a02SAndroid Build Coastguard Worker 165*14675a02SAndroid Build Coastguard Worker def test_upload_unregistered(self): 166*14675a02SAndroid Build Coastguard Worker service = media.Service(common_pb2.ForwardingInfo) 167*14675a02SAndroid Build Coastguard Worker with self.assertRaises(http_actions.HttpError) as cm: 168*14675a02SAndroid Build Coastguard Worker service.upload(b'data', 'does-not-exist') 169*14675a02SAndroid Build Coastguard Worker self.assertEqual(cm.exception.code, http.HTTPStatus.UNAUTHORIZED) 170*14675a02SAndroid Build Coastguard Worker 171*14675a02SAndroid Build Coastguard Worker with self.assertRaises(KeyError): 172*14675a02SAndroid Build Coastguard Worker service.finalize_upload('does-not-exist') 173*14675a02SAndroid Build Coastguard Worker 174*14675a02SAndroid Build Coastguard Worker def test_upload_no_longer_registered(self): 175*14675a02SAndroid Build Coastguard Worker service = media.Service(common_pb2.ForwardingInfo) 176*14675a02SAndroid Build Coastguard Worker name = service.register_upload() 177*14675a02SAndroid Build Coastguard Worker self.assertIsNone(service.finalize_upload(name)) 178*14675a02SAndroid Build Coastguard Worker 179*14675a02SAndroid Build Coastguard Worker with self.assertRaises(http_actions.HttpError) as cm: 180*14675a02SAndroid Build Coastguard Worker service.upload(b'data', name) 181*14675a02SAndroid Build Coastguard Worker self.assertEqual(cm.exception.code, http.HTTPStatus.UNAUTHORIZED) 182*14675a02SAndroid Build Coastguard Worker 183*14675a02SAndroid Build Coastguard Worker with self.assertRaises(KeyError): 184*14675a02SAndroid Build Coastguard Worker service.finalize_upload(name) 185*14675a02SAndroid Build Coastguard Worker 186*14675a02SAndroid Build Coastguard Worker 187*14675a02SAndroid Build Coastguard Workerif __name__ == '__main__': 188*14675a02SAndroid Build Coastguard Worker absltest.main() 189