xref: /aosp_15_r20/external/federated-compute/fcp/demo/media_test.py (revision 14675a029014e728ec732f129a32e299b2da0601)
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