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