1"""Tests for acloud.internal.lib.gstorage_client."""
2
3import io
4import time
5
6import apiclient
7import mock
8
9import unittest
10from acloud.internal.lib import driver_test_lib
11from acloud.internal.lib import gstorage_client
12from acloud.public import errors
13
14
15class StorageClientTest(driver_test_lib.BaseDriverTest):
16    """Test StorageClient."""
17
18    LOCAL_SRC = "/fake/local/path"
19    BUCKET = "fake_bucket"
20    OBJECT = "fake_obj"
21    MIME_TYPE = "fake_mimetype"
22
23    def setUp(self):
24        """Set up test."""
25        super(StorageClientTest, self).setUp()
26        self.Patch(gstorage_client.StorageClient, "InitResourceHandle")
27        self.client = gstorage_client.StorageClient(mock.MagicMock())
28        self.client._service = mock.MagicMock()
29
30    def testGet(self):
31        """Test Get."""
32        mock_api = mock.MagicMock()
33        resource_mock = mock.MagicMock()
34        self.client._service.objects = mock.MagicMock(
35            return_value=resource_mock)
36        resource_mock.get = mock.MagicMock(return_value=mock_api)
37        self.client.Get(self.BUCKET, self.OBJECT)
38        resource_mock.get.assert_called_with(
39            bucket=self.BUCKET, object=self.OBJECT)
40        self.assertTrue(mock_api.execute.called)
41
42    def testList(self):
43        """Test List."""
44        mock_items = ["fake/return"]
45        self.Patch(
46            gstorage_client.StorageClient,
47            "ListWithMultiPages",
48            return_value=mock_items)
49        resource_mock = mock.MagicMock()
50        self.client._service.objects = mock.MagicMock(
51            return_value=resource_mock)
52        items = self.client.List(self.BUCKET, self.OBJECT)
53        self.client.ListWithMultiPages.assert_called_once_with(
54            api_resource=resource_mock.list,
55            bucket=self.BUCKET,
56            prefix=self.OBJECT)
57        self.assertEqual(mock_items, items)
58
59    def testUpload(self):
60        """Test Upload."""
61        # Create mocks
62        mock_file = mock.MagicMock()
63        mock_file_io = mock.MagicMock()
64        mock_file_io.__enter__.return_value = mock_file
65        mock_media = mock.MagicMock()
66        mock_api = mock.MagicMock()
67        mock_response = mock.MagicMock()
68
69        self.Patch(io, "FileIO", return_value=mock_file_io)
70        self.Patch(
71            apiclient.http, "MediaIoBaseUpload", return_value=mock_media)
72        resource_mock = mock.MagicMock()
73        self.client._service.objects = mock.MagicMock(
74            return_value=resource_mock)
75        resource_mock.insert = mock.MagicMock(return_value=mock_api)
76        mock_api.execute = mock.MagicMock(return_value=mock_response)
77
78        # Make the call to the api
79        response = self.client.Upload(self.LOCAL_SRC, self.BUCKET, self.OBJECT,
80                                      self.MIME_TYPE)
81
82        # Verify
83        self.assertEqual(response, mock_response)
84        io.FileIO.assert_called_with(self.LOCAL_SRC, mode="rb")
85        apiclient.http.MediaIoBaseUpload.assert_called_with(mock_file,
86                                                            self.MIME_TYPE)
87        resource_mock.insert.assert_called_with(
88            bucket=self.BUCKET, name=self.OBJECT, media_body=mock_media)
89
90    def testUploadOSError(self):
91        """Test Upload when OSError is raised."""
92        self.Patch(io, "FileIO", side_effect=OSError("fake OSError"))
93        self.assertRaises(errors.DriverError, self.client.Upload,
94                          self.LOCAL_SRC, self.BUCKET, self.OBJECT,
95                          self.MIME_TYPE)
96
97    def testDelete(self):
98        """Test Delete."""
99        mock_api = mock.MagicMock()
100        resource_mock = mock.MagicMock()
101        self.client._service.objects = mock.MagicMock(
102            return_value=resource_mock)
103        resource_mock.delete = mock.MagicMock(return_value=mock_api)
104        self.client.Delete(self.BUCKET, self.OBJECT)
105        resource_mock.delete.assert_called_with(
106            bucket=self.BUCKET, object=self.OBJECT)
107        self.assertTrue(mock_api.execute.called)
108
109    def testDeleteMultipleFiles(self):
110        """Test Delete multiple files."""
111        fake_objs = ["fake_obj1", "fake_obj2"]
112        mock_api = mock.MagicMock()
113        resource_mock = mock.MagicMock()
114        self.client._service.objects = mock.MagicMock(
115            return_value=resource_mock)
116        resource_mock.delete = mock.MagicMock(return_value=mock_api)
117        deleted, failed, error_msgs = self.client.DeleteFiles(self.BUCKET,
118                                                              fake_objs)
119        self.assertEqual(deleted, fake_objs)
120        self.assertEqual(failed, [])
121        self.assertEqual(error_msgs, [])
122        calls = [mock.call(
123            bucket=self.BUCKET, object="fake_obj1"), mock.call(
124                bucket=self.BUCKET, object="fake_obj2")]
125        resource_mock.delete.assert_has_calls(calls)
126        self.assertEqual(mock_api.execute.call_count, 2)
127
128    def testGetUrl(self):
129        """Test GetUrl."""
130        fake_item = {"name": "fake-item-1", "selfLink": "link1"}
131        self.Patch(
132            gstorage_client.StorageClient, "Get", return_value=fake_item)
133        self.assertEqual(
134            self.client.GetUrl("fake_bucket", "fake-item-1"), "link1")
135
136    def testGetUrlNotFound(self):
137        """Test GetUrl when object is not found."""
138        self.Patch(
139            gstorage_client.StorageClient,
140            "Get",
141            side_effect=errors.ResourceNotFoundError(404, "expected error"))
142        self.Patch(time, "sleep")
143        self.assertRaises(errors.ResourceNotFoundError, self.client.GetUrl,
144                          "fake_bucket", "fake-item-1")
145
146
147if __name__ == "__main__":
148    unittest.main()
149