# Copyright 2020 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import json
import os
import shutil
import tempfile
import unittest
from unittest import mock
from core.perfetto_binary_roller import binary_deps_manager
class BinaryDepsManagerTests(unittest.TestCase):
def setUp(self):
self.temp_dir = tempfile.mkdtemp()
self.config_path = os.path.join(self.temp_dir, 'config.json')
self.original_config_path = binary_deps_manager.CONFIG_PATH
binary_deps_manager.CONFIG_PATH = self.config_path
def tearDown(self):
binary_deps_manager.CONFIG_PATH = self.original_config_path
shutil.rmtree(self.temp_dir)
def writeConfig(self, config):
with open(self.config_path, 'w') as f:
json.dump(config, f)
def readConfig(self):
with open(self.config_path) as f:
return json.load(f)
def testUploadHostBinaryChromium(self):
with mock.patch('py_utils.cloud_storage.Exists') as exists_patch:
with mock.patch('py_utils.cloud_storage.Insert') as insert_patch:
with mock.patch(
'core.perfetto_binary_roller.binary_deps_manager._GetHostOsName'
) as get_os_patch:
exists_patch.return_value = False
get_os_patch.return_value = 'testos'
binary_deps_manager.UploadHostBinaryChromium('dep', '/path/to/bin',
'abc123')
insert_patch.assert_has_calls([
mock.call(
'chromium-telemetry',
'perfetto_binaries/dep/testos/abc123/bin',
'/path/to/bin',
publicly_readable=True),
mock.call(
'chromium-telemetry',
'perfetto_binaries/dep/testos/latest',
mock.ANY,
publicly_readable=True),
])
def testUploadHostBinaryChromiumExists(self):
with mock.patch('py_utils.cloud_storage.Exists') as exists_patch:
with mock.patch('py_utils.cloud_storage.Insert') as insert_patch:
with mock.patch(
'core.perfetto_binary_roller.binary_deps_manager._GetHostOsName'
) as get_os_patch:
exists_patch.return_value = True
get_os_patch.return_value = 'testos'
binary_deps_manager.UploadHostBinaryChromium('dep', '/path/to/bin',
'abc123')
insert_patch.assert_called_once_with(
'chromium-telemetry',
'perfetto_binaries/dep/testos/latest',
mock.ANY,
publicly_readable=True,
)
def testSwitchBinaryToNewFullPath(self):
self.writeConfig(
{'dep': {
'testos': {
'full_remote_path': 'bucket/old/path/to/bin'
}
}})
latest_path = 'bucket/new/path/to/bin'
def write_latest_path(bucket, remote_path, local_path):
del bucket, remote_path # unused
with open(local_path, 'w') as f:
f.write(latest_path)
with mock.patch('py_utils.cloud_storage.Get') as get_patch:
with mock.patch('py_utils.cloud_storage.CalculateHash') as hash_patch:
get_patch.side_effect = write_latest_path
hash_patch.return_value = '123'
binary_deps_manager.SwitchBinaryToNewFullPath('dep', 'testos',
latest_path)
self.assertEqual(
self.readConfig(),
{'dep': {
'testos': {
'full_remote_path': latest_path,
'hash': '123',
}
}})
def testFetchHostBinary(self):
bucket = 'bucket'
remote_path = 'remote/path/to/bin'
full_remote_path = '/'.join([bucket, remote_path])
self.writeConfig({
'dep': {
'testos': {
'full_remote_path': full_remote_path,
'hash': '123',
}
}
})
with mock.patch('py_utils.cloud_storage.Get') as get_patch:
with mock.patch(
'core.perfetto_binary_roller.binary_deps_manager._GetHostOsName'
) as get_os_patch:
with mock.patch('py_utils.cloud_storage.CalculateHash') as hash_patch:
with mock.patch('os.stat'):
with mock.patch('os.chmod'):
hash_patch.return_value = '123'
get_os_patch.return_value = 'testos'
local_path = binary_deps_manager.FetchHostBinary('dep')
self.assertEqual(os.path.basename(local_path), 'bin')
get_patch.assert_called_once_with(bucket, remote_path, local_path)
def testFetchHostBinaryWrongHash(self):
bucket = 'bucket'
remote_path = 'remote/path/to/bin'
full_remote_path = '/'.join([bucket, remote_path])
self.writeConfig({
'dep': {
'testos': {
'full_remote_path': full_remote_path,
'hash': '123',
}
}
})
with mock.patch('py_utils.cloud_storage.Get'):
with mock.patch(
'core.perfetto_binary_roller.binary_deps_manager._GetHostOsName'
) as get_os_patch:
with mock.patch('py_utils.cloud_storage.CalculateHash') as hash_patch:
hash_patch.return_value = '234'
get_os_patch.return_value = 'testos'
with self.assertRaises(RuntimeError):
binary_deps_manager.FetchHostBinary('dep')
def testUploadAndSwitchDataFile(self):
self.writeConfig(
{'data_dep': {
'full_remote_path': 'chrome-telemetry/old/path/to/data'
}})
new_path = 'new/path/to/data'
with mock.patch('py_utils.cloud_storage.Exists') as exists_patch:
with mock.patch('py_utils.cloud_storage.Insert') as insert_patch:
with mock.patch('py_utils.cloud_storage.CalculateHash') as hash_patch:
exists_patch.return_value = False
hash_patch.return_value = '123'
binary_deps_manager.UploadAndSwitchDataFile('data_dep', new_path,
'abc123')
insert_patch.assert_called_once_with(
'chrome-telemetry',
'perfetto_data/data_dep/abc123/data',
'new/path/to/data',
publicly_readable=False,
)
self.assertEqual(
self.readConfig(), {
'data_dep': {
'full_remote_path':
'chrome-telemetry/perfetto_data/data_dep/abc123/data',
'hash': '123',
}
})
def testFetchDataFile(self):
bucket = 'bucket'
remote_path = 'remote/path/to/data'
full_remote_path = '/'.join([bucket, remote_path])
self.writeConfig(
{'data_dep': {
'full_remote_path': full_remote_path,
'hash': '123',
}})
with mock.patch('py_utils.cloud_storage.Get') as get_patch:
with mock.patch('py_utils.cloud_storage.CalculateHash') as hash_patch:
hash_patch.return_value = '123'
local_path = binary_deps_manager.FetchDataFile('data_dep')
self.assertEqual(os.path.basename(local_path), 'data')
get_patch.assert_called_once_with(bucket, remote_path, local_path)