blob: 0985d0b87e70f4e61be31e379af52c8daa472471 [file] [log] [blame]
#
# Copyright (C) 2015 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""Unittests for classes in device.py"""
import unittest
from bsp import device
from bsp import operating_system_stub
from bsp import package
from bsp import package_stub
from bsp import status
from core import util_stub
from test import stubs
class DeviceTest(unittest.TestCase):
_OS_VERSION = '98.76.54'
_OS_PATH = '/path/to/os'
def setUp(self):
self.dev_json = {
'device_name': 'Test Device 1',
'vendor': 'test_vendor',
'arch': 'test_arch',
'packages': {
'package_1': {
'subpackage_1': 'path/to/link'
}
}
}
self.package1 = package_stub.StubPackage(
'package_1',
subpackages={'subpackage_1': status.INSTALLED,
'subpackage_2': status.INSTALLED},
licenses=['license1', 'license2'])
self.package2 = package_stub.StubPackage(
'package_2', subpackages={'subpackage_2': status.INSTALLED})
self.packages = {'package_1': self.package1, 'package_2': self.package2}
self.stub_os = stubs.StubOs()
self.stub_open = stubs.StubOpen(self.stub_os)
self.stub_hashlib = stubs.StubHashlib()
self.stub_tar_package = package_stub.StubTarPackage('tarball_version')
self.stub_util = util_stub.StubUtil()
device.os = self.stub_os
device.open = self.stub_open.open
device.hashlib = self.stub_hashlib
device.util = self.stub_util
device.package = package_stub.StubPackageModule(self.stub_tar_package)
self.dev = device.Device(
'test_device', 'Test Device', 'test_vendor', 'test_arch',
{self.package1: {'subpackage_1': 'path1', 'subpackage_2': 'path2'},
self.package2: {'subpackage_2': 'path3'}})
self.os_ = operating_system_stub.StubOperatingSystem(
root=self._OS_PATH, version=self._OS_VERSION)
def test_init(self):
# Check all public attributes.
self.assertEqual(self.dev.name, 'test_device')
self.assertEqual(self.dev.full_name, 'Test Device')
self.assertEqual(self.dev.vendor, 'test_vendor')
self.assertEqual(self.dev.arch, 'test_arch')
self.assertEqual(self.dev.version, '0.0.0')
def test_from_dict(self):
dev = device.Device.from_dict(self.dev_json, 'a_name', self.packages)
self.assertIsInstance(dev, device.Device)
# pylint: disable=protected-access
self.assertTrue(self.package1 in dev._package_map)
self.assertEqual(dev._package_map[self.package1]['subpackage_1'],
'path/to/link')
self.assertEqual(dev.name, 'a_name')
self.assertEqual(dev.full_name, 'Test Device 1')
self.assertEqual(dev.vendor, 'test_vendor')
self.assertEqual(dev.arch, 'test_arch')
self.assertEqual(dev.version, '0.0.0')
def test_from_dict_bad_package(self):
self.dev_json['packages']['nonexistent'] = {}
with self.assertRaisesRegexp(ValueError,
'Package.*nonexistent.*does not exist'):
device.Device.from_dict(self.dev_json, 'a_name', self.packages)
def test_from_dict_bad_subpackage(self):
self.dev_json['packages']['package_1']['nonexistent'] = {}
with self.assertRaisesRegexp(ValueError,
'Sub.*nonexistent.*does not exist'):
device.Device.from_dict(self.dev_json, 'a_name', self.packages)
def test_from_dict_missing_keys(self):
del self.dev_json['arch']
with self.assertRaisesRegexp(KeyError, 'arch'):
device.Device.from_dict(self.dev_json, 'a_name', self.packages)
self.dev_json['arch'] = 'test_arch'
del self.dev_json['vendor']
with self.assertRaisesRegexp(KeyError, 'vendor'):
device.Device.from_dict(self.dev_json, 'a_name', self.packages)
self.dev_json['vendor'] = 'test_vendor'
del self.dev_json['packages']
with self.assertRaisesRegexp(KeyError, 'packages'):
device.Device.from_dict(self.dev_json, 'a_name', self.packages)
def test_status_installed(self):
self.assertEqual(self.dev.status(self.os_)[0], status.INSTALLED)
self.assertEqual(self.dev.status()[0], status.INSTALLED)
def test_status_linked(self):
self.package1.subpackages['subpackage_1'] = status.LINKED
self.assertEqual(self.dev.status(self.os_)[0], status.LINKED)
self.assertEqual(self.dev.status()[0], status.INSTALLED)
def test_status_unrecognized(self):
self.package1.subpackages['subpackage_1'] = status.LINKED
self.package1.subpackages['subpackage_2'] = status.UNRECOGNIZED
# Also test that this beats out linked.
self.assertEqual(self.dev.status(self.os_)[0],
status.UNRECOGNIZED)
# In certain situations, this could also be missing, but that's more
# complex to code into stubs.
self.assertEqual(self.dev.status()[0], status.INSTALLED)
def test_status_missing(self):
self.package1.subpackages['subpackage_1'] = status.LINKED
self.package1.subpackages['subpackage_2'] = status.UNRECOGNIZED
self.package2.subpackages['subpackage_2'] = status.MISSING
# Also test that this beats out linked and unrecognized.
self.assertEqual(self.dev.status()[0], status.MISSING)
self.assertEqual(self.dev.status(self.os_)[0], status.MISSING)
def test_status_not_installed(self):
self.package1.subpackages['subpackage_1'] = status.NOT_INSTALLED
self.package1.subpackages['subpackage_2'] = status.UNRECOGNIZED
self.package2.subpackages['subpackage_2'] = status.MISSING
# Also test that this beats out missing and unrecognized
# (and transitively linked).
self.assertEqual(self.dev.status()[0], status.NOT_INSTALLED)
self.assertEqual(self.dev.status(self.os_)[0],
status.NOT_INSTALLED)
def test_is_available(self):
self.assertTrue(self.dev.is_available())
self.package2.subpackages['subpackage_2'] = status.UNRECOGNIZED
self.assertTrue(self.dev.is_available())
self.package2.subpackages['subpackage_2'] = status.LINKED
self.assertTrue(self.dev.is_available())
self.package2.subpackages['subpackage_2'] = status.MISSING
self.assertFalse(self.dev.is_available())
self.package2.subpackages['subpackage_2'] = status.NOT_INSTALLED
self.assertFalse(self.dev.is_available())
def test_link(self):
link1 = self.os_.path('path1')
link2 = self.os_.path('path2')
link3 = self.os_.path('path3')
self.package1.should_link['subpackage_1'] = link1
self.package1.should_link['subpackage_2'] = link2
self.package2.should_link['subpackage_2'] = link3
self.dev.link(self.os_)
self.assertEqual(self.package1.subpackage_status(
'subpackage_1', link1)[0], status.LINKED)
self.assertEqual(self.package1.subpackage_status(
'subpackage_2', link2)[0], status.LINKED)
self.assertEqual(self.package2.subpackage_status(
'subpackage_2', link3)[0], status.LINKED)
def test_link_fail(self):
link1 = self.os_.path('path1')
link2 = self.os_.path('path2')
link3 = self.os_.path('path3')
self.package1.should_link['subpackage_1'] = link1
# Gonna be problems with package1.subpackage_2
self.package2.should_link['subpackage_2'] = link3
with self.assertRaises(device.PackageLinkError):
self.dev.link(self.os_)
# Should still link what it can.
self.assertEqual(self.package1.subpackage_status(
'subpackage_1', link1)[0], status.LINKED)
self.assertNotEqual(self.package1.subpackage_status(
'subpackage_2', link2)[0], status.LINKED)
self.assertEqual(self.package2.subpackage_status(
'subpackage_2', link3)[0], status.LINKED)
def test_link_not_downloaded(self):
link1 = self.os_.path('path1')
link2 = self.os_.path('path2')
link3 = self.os_.path('path3')
self.package1.should_link['subpackage_1'] = link1
self.package1.should_link['subpackage_2'] = link2
self.package2.should_link['subpackage_2'] = link3
self.package2.downloaded = False
with self.assertRaises(device.PackageLinkError):
self.dev.link(self.os_)
# Should still link what it can.
self.assertEqual(self.package1.subpackage_status(
'subpackage_1', link1)[0], status.LINKED)
self.assertEqual(self.package1.subpackage_status(
'subpackage_2', link2)[0], status.LINKED)
self.assertNotEqual(self.package2.subpackage_status(
'subpackage_2', link3)[0], status.LINKED)
def test_link_overwrite(self):
link1 = self.os_.path('path1')
link2 = self.os_.path('path2')
link3 = self.os_.path('path3')
self.package1.should_link['subpackage_1'] = link1
self.stub_os.path.should_exist = [link2]
self.package2.should_link['subpackage_2'] = link3
# Shouldn't raise, but shouldn't link package1.subpackage_2.
self.dev.link(self.os_)
self.assertEqual(self.package1.subpackage_status(
'subpackage_1', link1)[0], status.LINKED)
self.assertNotEqual(self.package1.subpackage_status(
'subpackage_2', link2)[0], status.LINKED)
self.assertEqual(self.package2.subpackage_status(
'subpackage_2', link3)[0], status.LINKED)
def test_unlink(self):
link1 = self.os_.path('path1')
link2 = self.os_.path('path2')
link3 = self.os_.path('path3')
self.package1.subpackages['subpackage_1'] = status.LINKED
self.package1.subpackages['subpackage_2'] = status.LINKED
self.package2.subpackages['subpackage_2'] = status.LINKED
self.package1.should_unlink['subpackage_1'] = link1
self.package1.should_unlink['subpackage_2'] = link2
self.package2.should_unlink['subpackage_2'] = link3
self.dev.unlink(self.os_)
self.assertEqual(self.package1.subpackage_status(
'subpackage_1', link1)[0], status.INSTALLED)
self.assertEqual(self.package1.subpackage_status(
'subpackage_2', link2)[0], status.INSTALLED)
self.assertEqual(self.package2.subpackage_status(
'subpackage_2', link3)[0], status.INSTALLED)
def test_partial_unlink(self):
link1 = self.os_.path('path1')
link2 = self.os_.path('path2')
link3 = self.os_.path('path3')
self.package1.subpackages['subpackage_1'] = status.MISSING
self.package1.subpackages['subpackage_2'] = status.INSTALLED
self.package2.subpackages['subpackage_2'] = status.LINKED
self.package1.should_unlink['subpackage_1'] = link1
self.package1.should_unlink['subpackage_2'] = link2
self.package2.should_unlink['subpackage_2'] = link3
# Should only actually unlink package2.subpackage_2.
self.dev.unlink(self.os_)
self.assertEqual(self.package1.subpackage_status(
'subpackage_1', link1)[0], status.MISSING)
self.assertEqual(self.package1.subpackage_status(
'subpackage_2', link2)[0], status.INSTALLED)
self.assertEqual(self.package2.subpackage_status(
'subpackage_2', link3)[0], status.INSTALLED)
def test_failed_unlink(self):
link1 = self.os_.path('path1')
link2 = self.os_.path('path2')
link3 = self.os_.path('path3')
self.package2.subpackages['subpackage_2'] = status.LINKED
# Should fail to unlink package2.subpackage_2.
with self.assertRaises(device.PackageUnlinkError):
self.dev.unlink(self.os_)
self.assertEqual(self.package1.subpackage_status(
'subpackage_1', link1)[0], status.INSTALLED)
self.assertEqual(self.package1.subpackage_status(
'subpackage_2', link2)[0], status.INSTALLED)
self.assertEqual(self.package2.subpackage_status(
'subpackage_2', link3)[0], status.LINKED)
def test_unrecognized_paths(self):
self.package1.subpackages['subpackage_1'] = status.NOT_INSTALLED
self.package1.subpackages['subpackage_2'] = status.UNRECOGNIZED
self.package2.subpackages['subpackage_2'] = status.UNRECOGNIZED
result = self.dev.unrecognized_paths(self.os_)
self.assertIn(self.os_.path('path2'), result)
self.assertIn(self.os_.path('path3'), result)
self.assertNotIn(self.os_.path('path1'), result)
def test_match_tarball(self):
matching = package.TarPackage('match', None,
self.stub_tar_package.tarball_version,
None)
non_matching_tar = package_stub.StubPackage(
'non_match', None, '<wrong_version>', None)
# While unlikely git and tar hashes would match, it is in theory
# possible. Luckily the branch:hash formulation for git versions
# should prevent this issue.
non_matching_git = package_stub.StubPackage(
'git', None, '<branch>:' + self.stub_tar_package.tarball_version,
None)
dev = device.Device('name', 'full_name', 'vend', 'arch', {
non_matching_tar: {}, matching: {}, non_matching_git: {}})
self.assertEqual(dev.match_tarball('file1'), 'match')
def test_non_matching_tarball(self):
non_matching_tar = package.TarPackage(
'non_match', None, '<wrong_version>', None)
# While unlikely git and tar hashes would match, it is in theory
# possible. Luckily the branch:hash formulation for git versions
# should prevent this issue.
non_matching_git = package.GitPackage(
'git', None, '<branch>:<correct_version>', None)
self.stub_open.files = {'file1': stubs.StubFile('file1')}
self.stub_os.path.should_exist = ['file1']
self.stub_hashlib.should_return = '<correct_version>'
dev = device.Device('name', 'full_name', 'vend', 'arch',
{non_matching_tar: {}, non_matching_git: {}})
self.assertEqual(dev.match_tarball('file1'), None)
def test_install(self):
self.package1.downloaded = False
self.package2.downloaded = False
self.package1.should_download = True
self.package2.should_download = True
self.assertFalse(self.dev.is_available())
self.dev.install(auto_accept=True)
self.assertTrue(self.dev.is_available())
def test_partial_install_with_link(self):
self.package1.downloaded = True
self.package2.downloaded = False
link1 = self.os_.path('path1')
link2 = self.os_.path('path2')
link3 = self.os_.path('path3')
self.package1.should_link['subpackage_1'] = link1
self.package1.should_link['subpackage_2'] = link2
self.package2.should_link['subpackage_2'] = link3
# Package 1 is already downloaded. But it will still link.
self.package1.should_download = False
self.package2.should_download = True
self.assertFalse(self.dev.is_available())
self.dev.install(auto_accept=True, link_os=self.os_)
self.assertTrue(self.dev.is_available())
self.assertEqual(self.package1.subpackage_status(
'subpackage_1', link1)[0], status.LINKED)
self.assertEqual(self.package1.subpackage_status(
'subpackage_2', link2)[0], status.LINKED)
self.assertEqual(self.package2.subpackage_status(
'subpackage_2', link3)[0], status.LINKED)
def test_failed_install(self):
self.package1.downloaded = False
self.package2.downloaded = False
self.package1.should_download = True
self.package2.should_download = False
# Since it will have downloaded successfully, it should be cleaned up.
self.package1.should_uninstall = True
self.assertFalse(self.dev.is_available())
with self.assertRaises(device.PackageDownloadError):
self.dev.install(auto_accept=True)
self.assertFalse(self.dev.is_available())
self.assertFalse(self.package1.is_downloaded())
self.assertFalse(self.package2.is_downloaded())
def test_failed_partial_install(self):
self.package1.downloaded = True
self.package2.downloaded = False
self.package1.should_download = False
self.package2.should_download = False
self.assertFalse(self.dev.is_available())
with self.assertRaises(device.PackageDownloadError):
self.dev.install(auto_accept=True)
self.assertFalse(self.dev.is_available())
# Package1 was already available; it shouldn't go away just because
# Package2 failed.
self.assertTrue(self.package1.is_downloaded())
self.assertFalse(self.package2.is_downloaded())
def test_void_install(self):
self.package1.downloaded = True
self.package2.downloaded = True
self.package1.should_download = False
self.package2.should_download = False
self.package1.licenses = []
self.assertTrue(self.dev.is_available())
self.dev.install(auto_accept=False)
self.assertTrue(self.dev.is_available())
self.assertTrue(self.package1.is_downloaded())
self.assertTrue(self.package2.is_downloaded())
def test_install_failed_link(self):
self.package1.downloaded = False
self.package2.downloaded = False
self.package1.should_download = True
self.package2.should_download = True
self.assertFalse(self.dev.is_available())
with self.assertRaises(device.PackageLinkError):
self.dev.install(auto_accept=True, link_os=self.os_)
# Should still install, just won't be linked.
self.assertTrue(self.dev.is_available())
self.assertNotEqual(self.package1.subpackage_status('subpackage_1')[0],
status.LINKED)
self.assertNotEqual(self.package1.subpackage_status('subpackage_2')[0],
status.LINKED)
self.assertNotEqual(self.package2.subpackage_status('subpackage_2')[0],
status.LINKED)
def test_uninstall(self):
self.package1.downloaded = True
self.package2.downloaded = True
self.package1.should_uninstall = True
self.package2.should_uninstall = True
self.assertTrue(self.dev.is_available())
self.dev.uninstall()
self.assertFalse(self.dev.is_available())
self.assertFalse(self.package1.is_downloaded())
self.assertFalse(self.package2.is_downloaded())
def test_uninstall_unnecessary(self):
self.package1.downloaded = False
self.package2.downloaded = True
# Still ok to try uninstalling package1.
self.package1.should_uninstall = True
self.package2.should_uninstall = True
self.assertFalse(self.dev.is_available())
self.dev.uninstall()
self.assertFalse(self.dev.is_available())
self.assertFalse(self.package1.is_downloaded())
self.assertFalse(self.package2.is_downloaded())