Merge "Add test to target_lib.py." am: f73c0f6138

Original change: https://android-review.googlesource.com/c/platform/development/+/1795808

Change-Id: Icf82fa2068901a89d43daabaefd4091c757a7d06
This commit is contained in:
Treehugger Robot
2021-08-17 17:37:00 +00:00
committed by Automerger Merge Worker
5 changed files with 241 additions and 0 deletions

View File

@@ -59,11 +59,19 @@ class BuildInfo:
pass
def to_sql_form_dict(self):
"""
Because sqlite can only store text but self.partitions is a list
Turn the list into a string joined by ',', for example:
['system', 'vendor'] => 'system,vendor'
"""
sql_form_dict = asdict(self)
sql_form_dict['partitions'] = ','.join(sql_form_dict['partitions'])
return sql_form_dict
def to_dict(self):
"""
Return as a normal dict.
"""
return asdict(self)

View File

@@ -0,0 +1,2 @@
system
vendor

View File

@@ -0,0 +1,21 @@
ro.build.id=AOSP.MASTER
ro.build.display.id=aosp_cf_x86_64_phone-userdebug S AOSP.MASTER 7392671 test-keys
ro.build.version.incremental=7392671
ro.build.version.sdk=30
ro.build.version.preview_sdk=1
ro.build.version.preview_sdk_fingerprint=5f1ee022916302ff92d66186575d0b95
ro.build.version.codename=S
ro.build.version.all_codenames=S
ro.build.version.release=11
ro.build.version.release_or_codename=S
ro.build.version.security_patch=2021-05-05
ro.build.version.base_os=
ro.build.version.min_supported_target_sdk=23
ro.build.date=Mon May 24 08:56:05 UTC 2021
ro.build.date.utc=1621846565
ro.build.type=userdebug
ro.build.user=android-build
ro.build.host=abfarm069
ro.build.tags=test-keys
ro.build.flavor=aosp_cf_x86_64_phone-userdebug
ro.build.system_root_image=false

View File

@@ -0,0 +1,18 @@
import os, unittest
class Tests():
def suite(self):
modules_to_test = []
test_dir = os.listdir('.')
for test in test_dir:
if test.startswith('test') and test.endswith('.py'):
modules_to_test.append(test.rstrip('.py'))
alltests = unittest.TestSuite()
for module in map(__import__, modules_to_test):
alltests.addTest(unittest.findTestCases(module))
return alltests
if __name__ == '__main__':
MyTests = Tests()
unittest.main(defaultTest='MyTests.suite', verbosity=2)

View File

@@ -0,0 +1,192 @@
import unittest
from unittest.mock import patch, mock_open, Mock, MagicMock
from target_lib import BuildInfo, TargetLib
import zipfile
import os
import sqlite3
from tempfile import NamedTemporaryFile
class CreateTestBuild():
def __init__(self, include_build_prop=True, include_ab_partitions=True):
self.file = NamedTemporaryFile(dir='test/')
self.test_path = self.file.name
with zipfile.ZipFile(self.file, mode='w') as package:
if include_build_prop:
package.write('test/test_build.prop', 'SYSTEM/build.prop')
if include_ab_partitions:
package.write('test/test_ab_partitions.txt',
'META/ab_partitions.txt')
self.test_info = {
'file_name': self.test_path.split('/')[-1],
'path': self.test_path,
'time': 1628698830,
'build_id': 'AOSP.MASTER',
'build_version': '7392671',
'build_flavor': 'aosp_cf_x86_64_phone-userdebug',
'partitions': ['system', 'vendor'],
}
if not include_build_prop:
self.test_info['build_id'] = ''
self.test_info['build_version'] = ''
self.test_info['build_flavor'] = ''
if not include_ab_partitions:
self.test_info['partitions'] = []
def clean(self):
self.file.close()
class TestBuildInfo(unittest.TestCase):
def setUp(self):
"""
Create a virtual Android build, which only have build.prop
and ab_partitions.txt
"""
self.test_build = CreateTestBuild()
self.build_info = BuildInfo(
self.test_build.test_info['file_name'],
self.test_build.test_info['path'],
self.test_build.test_info['time']
)
self.build_info.analyse_buildprop()
def tearDown(self):
self.test_build.clean()
def test_analyse_buildprop(self):
# Test if the build.prop and ab_partitions are not empty
for key, value in self.test_build.test_info.items():
self.assertEqual(value, self.build_info.__dict__[key],
'The ' + key + ' is not parsed correctly.'
)
# Test if the ab_partitions is empty
test_build_no_partitions = CreateTestBuild(include_ab_partitions=False)
build_info = BuildInfo(
test_build_no_partitions.test_info['file_name'],
test_build_no_partitions.test_info['path'],
test_build_no_partitions.test_info['time']
)
build_info.analyse_buildprop()
self.assertEqual(build_info.partitions,
test_build_no_partitions.test_info['partitions'],
'The partition list is not empty if ab_partitions is not provided.'
)
test_build_no_partitions.clean()
def test_to_sql_form_dict(self):
sql_dict = self.build_info.to_sql_form_dict()
for key, value in self.test_build.test_info.items():
if key != 'partitions':
self.assertEqual(value, sql_dict[key],
'The ' + key + ' is not parsed correctly.'
)
else:
self.assertEqual(','.join(value), sql_dict[key],
'The partition list is not coverted to sql form properly.'
)
def test_to_dict(self):
ordinary_dict = self.build_info.to_dict()
for key, value in self.test_build.test_info.items():
self.assertEqual(value, ordinary_dict[key],
'The ' + key + ' is not parsed correctly.'
)
class TestTargetLib(unittest.TestCase):
def setUp(self):
self.test_path = 'test/test_target_lib.db'
self.tearDown()
self.target_build = TargetLib(path=self.test_path)
def tearDown(self):
if os.path.isfile(self.test_path):
os.remove(self.test_path)
def test_init(self):
# Test the database is created successfully
self.assertTrue(os.path.isfile(self.test_path))
test_columns = [
{'name': 'FileName','type':'TEXT'},
{'name': 'Path','type':'TEXT'},
{'name': 'BuildID','type':'TEXT'},
{'name': 'BuildVersion','type':'TEXT'},
{'name': 'BuildFlavor','type':'TEXT'},
{'name': 'Partitions','type':'TEXT'},
{'name': 'UploadTime','type':'INTEGER'},
]
connect = sqlite3.connect(self.test_path)
cursor = connect.cursor()
cursor.execute("PRAGMA table_info(Builds)")
columns = cursor.fetchall()
for column in test_columns:
column_found = list(filter(lambda x: x[1]==column['name'], columns))
self.assertEqual(len(column_found), 1,
'The column ' + column['name'] + ' is not found in database'
)
self.assertEqual(column_found[0][2], column['type'],
'The column ' + column['name'] + ' has a wrong type'
)
def test_new_build(self):
test_build = CreateTestBuild()
self.target_build.new_build(
filename=test_build.test_info['file_name'],
path=test_build.test_path
)
connect = sqlite3.connect(self.test_path)
cursor = connect.cursor()
cursor.execute("SELECT * FROM BUILDS")
entries = cursor.fetchall()
self.assertEqual(len(entries), 1,
'The test build cannot be added into the database.'
)
test_build.clean()
def test_get_builds(self):
test_build = CreateTestBuild()
# time.time() has to be mocked, otherwise it will be the current time
mock_time = Mock(return_value=test_build.test_info['time'])
with patch('time.time', mock_time):
self.target_build.new_build(
filename=test_build.test_info['file_name'],
path=test_build.test_path
)
# build_list is read and parsed from the database
# build_info is directly parsed from the package
# Test if the read/write database process changes the data entry
build_list = self.target_build.get_builds()
build_info = BuildInfo(
test_build.test_info['file_name'],
test_build.test_info['path'],
test_build.test_info['time']
)
build_info.analyse_buildprop()
self.assertEqual(build_list[0], build_info,
'The list of build info cannot be extracted from database.'
)
test_build.clean()
def test_get_build_by_path(self):
test_build = CreateTestBuild()
# time.time() has to be mocked, otherwise it will be the current time
mock_time = Mock(return_value=test_build.test_info['time'])
with patch('time.time', mock_time):
self.target_build.new_build(
filename=test_build.test_info['file_name'],
path=test_build.test_path
)
build = self.target_build.get_build_by_path(test_build.test_info['path'])
build_info = BuildInfo(
test_build.test_info['file_name'],
test_build.test_info['path'],
test_build.test_info['time']
)
build_info.analyse_buildprop()
self.assertEqual(build, build_info,
'Build info cannot be extracted by path.'
)
test_build.clean()
if __name__ == '__main__':
unittest.main()