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:
@@ -59,11 +59,19 @@ class BuildInfo:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def to_sql_form_dict(self):
|
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 = asdict(self)
|
||||||
sql_form_dict['partitions'] = ','.join(sql_form_dict['partitions'])
|
sql_form_dict['partitions'] = ','.join(sql_form_dict['partitions'])
|
||||||
return sql_form_dict
|
return sql_form_dict
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
|
"""
|
||||||
|
Return as a normal dict.
|
||||||
|
"""
|
||||||
return asdict(self)
|
return asdict(self)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
2
tools/otagui/test/test_ab_partitions.txt
Normal file
2
tools/otagui/test/test_ab_partitions.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
system
|
||||||
|
vendor
|
||||||
21
tools/otagui/test/test_build.prop
Normal file
21
tools/otagui/test/test_build.prop
Normal 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
|
||||||
18
tools/otagui/test_suite.py
Normal file
18
tools/otagui/test_suite.py
Normal 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)
|
||||||
192
tools/otagui/test_target_lib.py
Normal file
192
tools/otagui/test_target_lib.py
Normal 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()
|
||||||
Reference in New Issue
Block a user