mirror of
https://gitlab.com/fdroid/fdroidserver.git
synced 2024-11-09 00:40:11 +01:00
Merge branch 'normalize-type-list-int' into 'master'
metadata: refactor parsing normalization See merge request fdroid/fdroidserver!1359
This commit is contained in:
commit
65a1698ba3
@ -57,6 +57,7 @@ metadata_v0:
|
|||||||
- cd fdroiddata
|
- cd fdroiddata
|
||||||
- ../tests/dump_internal_metadata_format.py
|
- ../tests/dump_internal_metadata_format.py
|
||||||
- sed -i
|
- sed -i
|
||||||
|
-e '/RequiresRoot:/d'
|
||||||
-e "/buildozer/d"
|
-e "/buildozer/d"
|
||||||
-e '/^comments\W /d'
|
-e '/^comments\W /d'
|
||||||
-e 's,maven\(\W\) false,maven\1 null,'
|
-e 's,maven\(\W\) false,maven\1 null,'
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
import git
|
import git
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import math
|
||||||
import platform
|
import platform
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
@ -883,6 +884,21 @@ def parse_localized_antifeatures(app):
|
|||||||
app['AntiFeatures'][f.stem][locale] = f.read_text()
|
app['AntiFeatures'][f.stem][locale] = f.read_text()
|
||||||
|
|
||||||
|
|
||||||
|
def _normalize_type_int(k, v):
|
||||||
|
"""Normalize anything that can be reliably converted to an integer."""
|
||||||
|
if isinstance(v, int) and not isinstance(v, bool):
|
||||||
|
return v
|
||||||
|
if v is None:
|
||||||
|
return None
|
||||||
|
if isinstance(v, str):
|
||||||
|
try:
|
||||||
|
return int(v)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
msg = _('{build_flag} must be an integer, found: {value}')
|
||||||
|
_warn_or_exception(msg.format(build_flag=k, value=v))
|
||||||
|
|
||||||
|
|
||||||
def _normalize_type_string(v):
|
def _normalize_type_string(v):
|
||||||
"""Normalize any data to TYPE_STRING.
|
"""Normalize any data to TYPE_STRING.
|
||||||
|
|
||||||
@ -892,11 +908,27 @@ def _normalize_type_string(v):
|
|||||||
numbers. Like "versionName: 1.0" would be a YAML float, but
|
numbers. Like "versionName: 1.0" would be a YAML float, but
|
||||||
should be a string.
|
should be a string.
|
||||||
|
|
||||||
|
SHA-256 values are string values, but YAML 1.2 can interpret some
|
||||||
|
unquoted values as decimal ints. This converts those to a string
|
||||||
|
if they are over 50 digits. In the wild, the longest 0 padding on
|
||||||
|
a SHA-256 key fingerprint I found was 8 zeros.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if isinstance(v, bool):
|
if isinstance(v, bool):
|
||||||
if v:
|
if v:
|
||||||
return 'true'
|
return 'true'
|
||||||
return 'false'
|
return 'false'
|
||||||
|
if isinstance(v, float):
|
||||||
|
# YAML 1.2 values for NaN, Inf, and -Inf
|
||||||
|
if math.isnan(v):
|
||||||
|
return '.nan'
|
||||||
|
if math.isinf(v):
|
||||||
|
if v > 0:
|
||||||
|
return '.inf'
|
||||||
|
return '-.inf'
|
||||||
|
if v and isinstance(v, int):
|
||||||
|
if math.log10(v) > 50: # only if the int has this many digits
|
||||||
|
return '%064d' % v
|
||||||
return str(v)
|
return str(v)
|
||||||
|
|
||||||
|
|
||||||
@ -955,30 +987,47 @@ def _normalize_type_stringmap(k, v):
|
|||||||
return retdict
|
return retdict
|
||||||
|
|
||||||
|
|
||||||
|
def _normalize_type_list(k, v):
|
||||||
|
"""Normalize any data to TYPE_LIST, which is always a list of strings."""
|
||||||
|
if isinstance(v, dict):
|
||||||
|
msg = _('{build_flag} must be list or string, found: {value}')
|
||||||
|
_warn_or_exception(msg.format(build_flag=k, value=v))
|
||||||
|
elif type(v) not in (list, tuple, set):
|
||||||
|
v = [v]
|
||||||
|
return [_normalize_type_string(i) for i in v]
|
||||||
|
|
||||||
|
|
||||||
def post_parse_yaml_metadata(yamldata):
|
def post_parse_yaml_metadata(yamldata):
|
||||||
"""Convert human-readable metadata data structures into consistent data structures.
|
"""Convert human-readable metadata data structures into consistent data structures.
|
||||||
|
|
||||||
|
"Be conservative in what is written out, be liberal in what is parsed."
|
||||||
|
https://en.wikipedia.org/wiki/Robustness_principle
|
||||||
|
|
||||||
This also handles conversions that make metadata YAML behave
|
This also handles conversions that make metadata YAML behave
|
||||||
something like StrictYAML. Specifically, a field should have a
|
something like StrictYAML. Specifically, a field should have a
|
||||||
fixed value type, regardless of YAML 1.2's type auto-detection.
|
fixed value type, regardless of YAML 1.2's type auto-detection.
|
||||||
|
|
||||||
|
TODO: None values should probably be treated as the string 'null',
|
||||||
|
since YAML 1.2 uses that for nulls
|
||||||
|
|
||||||
"""
|
"""
|
||||||
for k, v in yamldata.items():
|
for k, v in yamldata.items():
|
||||||
_fieldtype = fieldtype(k)
|
_fieldtype = fieldtype(k)
|
||||||
if _fieldtype == TYPE_LIST:
|
if _fieldtype == TYPE_LIST:
|
||||||
if isinstance(v, str):
|
if v or v == 0:
|
||||||
yamldata[k] = [v]
|
yamldata[k] = _normalize_type_list(k, v)
|
||||||
elif v:
|
|
||||||
yamldata[k] = [str(i) for i in v]
|
|
||||||
elif _fieldtype == TYPE_INT:
|
elif _fieldtype == TYPE_INT:
|
||||||
if v:
|
v = _normalize_type_int(k, v)
|
||||||
yamldata[k] = int(v)
|
if v or v == 0:
|
||||||
|
yamldata[k] = v
|
||||||
elif _fieldtype == TYPE_STRING:
|
elif _fieldtype == TYPE_STRING:
|
||||||
if v or v == 0:
|
if v or v == 0:
|
||||||
yamldata[k] = _normalize_type_string(v)
|
yamldata[k] = _normalize_type_string(v)
|
||||||
elif _fieldtype == TYPE_STRINGMAP:
|
elif _fieldtype == TYPE_STRINGMAP:
|
||||||
if v or v == 0: # TODO probably want just `if v:`
|
if v or v == 0: # TODO probably want just `if v:`
|
||||||
yamldata[k] = _normalize_type_stringmap(k, v)
|
yamldata[k] = _normalize_type_stringmap(k, v)
|
||||||
|
elif _fieldtype == TYPE_BOOL:
|
||||||
|
yamldata[k] = bool(v)
|
||||||
else:
|
else:
|
||||||
if type(v) in (float, int):
|
if type(v) in (float, int):
|
||||||
yamldata[k] = str(v)
|
yamldata[k] = str(v)
|
||||||
@ -994,29 +1043,17 @@ def post_parse_yaml_metadata(yamldata):
|
|||||||
if v or v == 0:
|
if v or v == 0:
|
||||||
build[k] = _normalize_type_string(v)
|
build[k] = _normalize_type_string(v)
|
||||||
elif _flagtype == TYPE_INT:
|
elif _flagtype == TYPE_INT:
|
||||||
|
v = _normalize_type_int(k, v)
|
||||||
|
if v or v == 0:
|
||||||
build[k] = v
|
build[k] = v
|
||||||
# versionCode must be int
|
|
||||||
if not isinstance(v, int):
|
|
||||||
_warn_or_exception(
|
|
||||||
_('{build_flag} must be an integer, found: {value}').format(
|
|
||||||
build_flag=k, value=v
|
|
||||||
)
|
|
||||||
)
|
|
||||||
elif _flagtype in (TYPE_LIST, TYPE_SCRIPT):
|
elif _flagtype in (TYPE_LIST, TYPE_SCRIPT):
|
||||||
if isinstance(v, str) or isinstance(v, int):
|
if v or v == 0:
|
||||||
build[k] = [_normalize_type_string(v)]
|
build[k] = _normalize_type_list(k, v)
|
||||||
else:
|
|
||||||
build[k] = v
|
|
||||||
# float and dict are here only to keep things compatible
|
|
||||||
if type(build[k]) not in (list, tuple, set, float, dict):
|
|
||||||
_warn_or_exception(
|
|
||||||
_('{build_flag} must be list or string, found: {value}').format(
|
|
||||||
build_flag=k, value=v
|
|
||||||
)
|
|
||||||
)
|
|
||||||
elif _flagtype == TYPE_STRINGMAP:
|
elif _flagtype == TYPE_STRINGMAP:
|
||||||
if v or v == 0:
|
if v or v == 0:
|
||||||
build[k] = _normalize_type_stringmap(k, v)
|
build[k] = _normalize_type_stringmap(k, v)
|
||||||
|
elif _flagtype == TYPE_BOOL:
|
||||||
|
build[k] = bool(v)
|
||||||
|
|
||||||
builds.append(build)
|
builds.append(build)
|
||||||
|
|
||||||
|
@ -343,6 +343,13 @@ class MetadataTest(unittest.TestCase):
|
|||||||
self.assertEqual('false', metadata._normalize_type_string(False))
|
self.assertEqual('false', metadata._normalize_type_string(False))
|
||||||
self.assertEqual('true', metadata._normalize_type_string(True))
|
self.assertEqual('true', metadata._normalize_type_string(True))
|
||||||
|
|
||||||
|
def test_normalize_type_string_sha256(self):
|
||||||
|
"""SHA-256 values are TYPE_STRING, which YAML can parse as decimal ints."""
|
||||||
|
yaml = ruamel.yaml.YAML(typ='safe')
|
||||||
|
for v in range(1, 1000):
|
||||||
|
s = '%064d' % (v * (10**51))
|
||||||
|
self.assertEqual(s, metadata._normalize_type_string(yaml.load(s)))
|
||||||
|
|
||||||
def test_normalize_type_stringmap_none(self):
|
def test_normalize_type_stringmap_none(self):
|
||||||
self.assertEqual(dict(), metadata._normalize_type_stringmap('key', None))
|
self.assertEqual(dict(), metadata._normalize_type_stringmap('key', None))
|
||||||
|
|
||||||
@ -355,6 +362,57 @@ class MetadataTest(unittest.TestCase):
|
|||||||
metadata._normalize_type_stringmap('AntiFeatures', ['Ads', 'Tracking']),
|
metadata._normalize_type_stringmap('AntiFeatures', ['Ads', 'Tracking']),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_normalize_type_int(self):
|
||||||
|
"""TYPE_INT should be an int whenever possible."""
|
||||||
|
self.assertEqual(0, metadata._normalize_type_int('key', 0))
|
||||||
|
self.assertEqual(1, metadata._normalize_type_int('key', 1))
|
||||||
|
self.assertEqual(-5, metadata._normalize_type_int('key', -5))
|
||||||
|
self.assertEqual(0, metadata._normalize_type_int('key', '0'))
|
||||||
|
self.assertEqual(1, metadata._normalize_type_int('key', '1'))
|
||||||
|
self.assertEqual(-5, metadata._normalize_type_int('key', '-5'))
|
||||||
|
self.assertEqual(
|
||||||
|
12345678901234567890,
|
||||||
|
metadata._normalize_type_int('key', 12345678901234567890),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_normalize_type_int_fails(self):
|
||||||
|
with self.assertRaises(MetaDataException):
|
||||||
|
metadata._normalize_type_int('key', '1a')
|
||||||
|
with self.assertRaises(MetaDataException):
|
||||||
|
metadata._normalize_type_int('key', 1.1)
|
||||||
|
with self.assertRaises(MetaDataException):
|
||||||
|
metadata._normalize_type_int('key', True)
|
||||||
|
|
||||||
|
def test_normalize_type_list(self):
|
||||||
|
"""TYPE_LIST is always a list of strings, no matter what YAML thinks."""
|
||||||
|
k = 'placeholder'
|
||||||
|
yaml = ruamel.yaml.YAML(typ='safe')
|
||||||
|
self.assertEqual(['1.0'], metadata._normalize_type_list(k, 1.0))
|
||||||
|
self.assertEqual(['1234567890'], metadata._normalize_type_list(k, 1234567890))
|
||||||
|
self.assertEqual(['false'], metadata._normalize_type_list(k, False))
|
||||||
|
self.assertEqual(['true'], metadata._normalize_type_list(k, True))
|
||||||
|
self.assertEqual(['foo'], metadata._normalize_type_list(k, 'foo'))
|
||||||
|
self.assertEqual([], metadata._normalize_type_list(k, list()))
|
||||||
|
self.assertEqual([], metadata._normalize_type_list(k, tuple()))
|
||||||
|
self.assertEqual([], metadata._normalize_type_list(k, set()))
|
||||||
|
self.assertEqual(['0', '1', '2'], metadata._normalize_type_list(k, {0, 1, 2}))
|
||||||
|
self.assertEqual(
|
||||||
|
['a', 'b', 'c', '0', '0.0'],
|
||||||
|
metadata._normalize_type_list(k, yaml.load('[a, b, c, 0, 0.0]')),
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
['1', '1.0', 's', 'true', '{}'],
|
||||||
|
metadata._normalize_type_list(k, yaml.load('[1, 1.0, s, true, {}]')),
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
['1', '1.0', 's', 'true', '{}'],
|
||||||
|
metadata._normalize_type_list(k, (1, 1.0, 's', True, dict())),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_normalize_type_list_fails(self):
|
||||||
|
with self.assertRaises(MetaDataException):
|
||||||
|
metadata._normalize_type_list('placeholder', dict())
|
||||||
|
|
||||||
def test_post_parse_yaml_metadata(self):
|
def test_post_parse_yaml_metadata(self):
|
||||||
yamldata = dict()
|
yamldata = dict()
|
||||||
metadata.post_parse_yaml_metadata(yamldata)
|
metadata.post_parse_yaml_metadata(yamldata)
|
||||||
@ -365,10 +423,18 @@ class MetadataTest(unittest.TestCase):
|
|||||||
metadata.post_parse_yaml_metadata(yamldata)
|
metadata.post_parse_yaml_metadata(yamldata)
|
||||||
|
|
||||||
def test_post_parse_yaml_metadata_fails(self):
|
def test_post_parse_yaml_metadata_fails(self):
|
||||||
yamldata = {'AllowedAPKSigningKeys': True}
|
yamldata = {'AllowedAPKSigningKeys': {'bad': 'dict-placement'}}
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(MetaDataException):
|
||||||
metadata.post_parse_yaml_metadata(yamldata)
|
metadata.post_parse_yaml_metadata(yamldata)
|
||||||
|
|
||||||
|
def test_post_parse_yaml_metadata_0padding_sha256(self):
|
||||||
|
"""SHA-256 values are strings, but YAML 1.2 will read some as decimal ints."""
|
||||||
|
v = '0027293472934293872934729834729834729834729834792837487293847926'
|
||||||
|
yaml = ruamel.yaml.YAML(typ='safe')
|
||||||
|
yamldata = yaml.load('AllowedAPKSigningKeys: ' + v)
|
||||||
|
metadata.post_parse_yaml_metadata(yamldata)
|
||||||
|
self.assertEqual(yamldata['AllowedAPKSigningKeys'], [v])
|
||||||
|
|
||||||
def test_post_parse_yaml_metadata_builds(self):
|
def test_post_parse_yaml_metadata_builds(self):
|
||||||
yamldata = OrderedDict()
|
yamldata = OrderedDict()
|
||||||
builds = []
|
builds = []
|
||||||
@ -383,7 +449,7 @@ class MetadataTest(unittest.TestCase):
|
|||||||
yamldata,
|
yamldata,
|
||||||
)
|
)
|
||||||
|
|
||||||
build['versionCode'] = '1'
|
build['versionCode'] = '1a'
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
fdroidserver.exception.MetaDataException,
|
fdroidserver.exception.MetaDataException,
|
||||||
fdroidserver.metadata.post_parse_yaml_metadata,
|
fdroidserver.metadata.post_parse_yaml_metadata,
|
||||||
@ -475,14 +541,14 @@ class MetadataTest(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_parse_yaml_metadata_app_type_list_fails(self):
|
def test_parse_yaml_metadata_app_type_list_fails(self):
|
||||||
mf = _get_mock_mf('AllowedAPKSigningKeys: true')
|
mf = _get_mock_mf('AllowedAPKSigningKeys: {t: f}')
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(MetaDataException):
|
||||||
metadata.parse_yaml_metadata(mf)
|
|
||||||
mf = _get_mock_mf('AllowedAPKSigningKeys: 1')
|
|
||||||
with self.assertRaises(TypeError):
|
|
||||||
metadata.parse_yaml_metadata(mf)
|
metadata.parse_yaml_metadata(mf)
|
||||||
|
|
||||||
self.assertEqual(fdroidserver.metadata.parse_yaml_metadata(mf), dict())
|
def test_parse_yaml_metadata_build_type_list_fails(self):
|
||||||
|
mf = _get_mock_mf('Builds: [{versionCode: 1, rm: {bad: dict-placement}}]')
|
||||||
|
with self.assertRaises(MetaDataException):
|
||||||
|
metadata.parse_yaml_metadata(mf)
|
||||||
|
|
||||||
def test_parse_yaml_metadata_unknown_app_field(self):
|
def test_parse_yaml_metadata_unknown_app_field(self):
|
||||||
mf = io.StringIO(
|
mf = io.StringIO(
|
||||||
@ -965,6 +1031,24 @@ class MetadataTest(unittest.TestCase):
|
|||||||
{'AntiFeatures': {'true': {}}},
|
{'AntiFeatures': {'true': {}}},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_parse_yaml_app_antifeatures_float_nan(self):
|
||||||
|
self.assertEqual(
|
||||||
|
metadata.parse_yaml_metadata(io.StringIO('AntiFeatures: .nan')),
|
||||||
|
{'AntiFeatures': {'.nan': {}}},
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_parse_yaml_app_antifeatures_float_inf(self):
|
||||||
|
self.assertEqual(
|
||||||
|
metadata.parse_yaml_metadata(io.StringIO('AntiFeatures: .inf')),
|
||||||
|
{'AntiFeatures': {'.inf': {}}},
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_parse_yaml_app_antifeatures_float_negative_inf(self):
|
||||||
|
self.assertEqual(
|
||||||
|
metadata.parse_yaml_metadata(io.StringIO('AntiFeatures: -.inf')),
|
||||||
|
{'AntiFeatures': {'-.inf': {}}},
|
||||||
|
)
|
||||||
|
|
||||||
def test_parse_yaml_app_antifeatures_int(self):
|
def test_parse_yaml_app_antifeatures_int(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
metadata.parse_yaml_metadata(io.StringIO('AntiFeatures: 1')),
|
metadata.parse_yaml_metadata(io.StringIO('AntiFeatures: 1')),
|
||||||
@ -1106,6 +1190,34 @@ class MetadataTest(unittest.TestCase):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_parse_yaml_build_type_int_fail(self):
|
||||||
|
mf = io.StringIO('Builds: [{versionCode: 1a}]')
|
||||||
|
with self.assertRaises(MetaDataException):
|
||||||
|
fdroidserver.metadata.parse_yaml_metadata(mf)
|
||||||
|
|
||||||
|
def test_parse_yaml_int_strict_typing_fails(self):
|
||||||
|
"""Things that cannot be preserved when parsing as YAML."""
|
||||||
|
mf = io.StringIO('Builds: [{versionCode: 1, rm: 0xf}]')
|
||||||
|
self.assertEqual(
|
||||||
|
{'Builds': [{'rm': ['15'], 'versionCode': 1}]}, # 15 != 0xf
|
||||||
|
fdroidserver.metadata.parse_yaml_metadata(mf),
|
||||||
|
)
|
||||||
|
mf = io.StringIO('Builds: [{versionCode: 1, rm: 0x010}]')
|
||||||
|
self.assertEqual(
|
||||||
|
{'Builds': [{'rm': ['16'], 'versionCode': 1}]}, # 16 != 0x010
|
||||||
|
fdroidserver.metadata.parse_yaml_metadata(mf),
|
||||||
|
)
|
||||||
|
mf = io.StringIO('Builds: [{versionCode: 1, rm: 0o015}]')
|
||||||
|
self.assertEqual(
|
||||||
|
{'Builds': [{'rm': ['13'], 'versionCode': 1}]}, # 13 != 0o015
|
||||||
|
fdroidserver.metadata.parse_yaml_metadata(mf),
|
||||||
|
)
|
||||||
|
mf = io.StringIO('Builds: [{versionCode: 1, rm: 10_000}]')
|
||||||
|
self.assertEqual(
|
||||||
|
{'Builds': [{'rm': ['10000'], 'versionCode': 1}]}, # 10000 != 10_000
|
||||||
|
fdroidserver.metadata.parse_yaml_metadata(mf),
|
||||||
|
)
|
||||||
|
|
||||||
def test_write_yaml_1_line_scripts_as_string(self):
|
def test_write_yaml_1_line_scripts_as_string(self):
|
||||||
mf = io.StringIO()
|
mf = io.StringIO()
|
||||||
app = fdroidserver.metadata.App()
|
app = fdroidserver.metadata.App()
|
||||||
@ -1999,22 +2111,49 @@ class PostMetadataParseTest(unittest.TestCase):
|
|||||||
app['Builds'][0][tested_key] = expected
|
app['Builds'][0][tested_key] = expected
|
||||||
return app, post
|
return app, post
|
||||||
|
|
||||||
|
def test_post_metadata_parse_none(self):
|
||||||
|
"""Run None aka YAML null or blank through the various field and flag types."""
|
||||||
|
self.assertEqual(*self._post_metadata_parse_app_list(None, None))
|
||||||
|
self.assertEqual(*self._post_metadata_parse_app_string(None, None))
|
||||||
|
self.assertEqual(*self._post_metadata_parse_build_bool(None, None))
|
||||||
|
self.assertEqual(*self._post_metadata_parse_build_int(None, None))
|
||||||
|
self.assertEqual(*self._post_metadata_parse_build_list(None, None))
|
||||||
|
self.assertEqual(*self._post_metadata_parse_build_script(None, None))
|
||||||
|
self.assertEqual(*self._post_metadata_parse_build_string(None, None))
|
||||||
|
|
||||||
def test_post_metadata_parse_int(self):
|
def test_post_metadata_parse_int(self):
|
||||||
"""Run the int 123456 through the various field and flag types."""
|
"""Run the int 123456 through the various field and flag types."""
|
||||||
with self.assertRaises(TypeError):
|
self.assertEqual(*self._post_metadata_parse_app_list(123456, ['123456']))
|
||||||
self._post_metadata_parse_app_list(123456, TypeError)
|
|
||||||
self.assertEqual(*self._post_metadata_parse_app_string(123456, '123456'))
|
self.assertEqual(*self._post_metadata_parse_app_string(123456, '123456'))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_bool(123456, 123456))
|
self.assertEqual(*self._post_metadata_parse_build_bool(123456, True))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_int(123456, 123456))
|
self.assertEqual(*self._post_metadata_parse_build_int(123456, 123456))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_list(123456, ['123456']))
|
self.assertEqual(*self._post_metadata_parse_build_list(123456, ['123456']))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_script(123456, ['123456']))
|
self.assertEqual(*self._post_metadata_parse_build_script(123456, ['123456']))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_string(123456, '123456'))
|
self.assertEqual(*self._post_metadata_parse_build_string(123456, '123456'))
|
||||||
|
|
||||||
|
def test_post_metadata_parse_sha256(self):
|
||||||
|
"""Run a SHA-256 that YAML calls an int through the various types.
|
||||||
|
|
||||||
|
The current f-droid.org signer set has SHA-256 values with a
|
||||||
|
maximum of two leading zeros, but this will handle more.
|
||||||
|
|
||||||
|
"""
|
||||||
|
yaml = ruamel.yaml.YAML(typ='safe', pure=True)
|
||||||
|
str_sha256 = '0000000000000498456908409534729834729834729834792837487293847926'
|
||||||
|
sha256 = yaml.load('a: ' + str_sha256)['a']
|
||||||
|
self.assertEqual(*self._post_metadata_parse_app_list(sha256, [str_sha256]))
|
||||||
|
self.assertEqual(*self._post_metadata_parse_app_string(sha256, str_sha256))
|
||||||
|
self.assertEqual(*self._post_metadata_parse_build_bool(sha256, True))
|
||||||
|
self.assertEqual(*self._post_metadata_parse_build_int(sha256, sha256))
|
||||||
|
self.assertEqual(*self._post_metadata_parse_build_list(sha256, [str_sha256]))
|
||||||
|
self.assertEqual(*self._post_metadata_parse_build_script(sha256, [str_sha256]))
|
||||||
|
self.assertEqual(*self._post_metadata_parse_build_string(sha256, str_sha256))
|
||||||
|
|
||||||
def test_post_metadata_parse_int_0(self):
|
def test_post_metadata_parse_int_0(self):
|
||||||
"""Run the int 0 through the various field and flag types."""
|
"""Run the int 0 through the various field and flag types."""
|
||||||
self.assertEqual(*self._post_metadata_parse_app_list(0, 0))
|
self.assertEqual(*self._post_metadata_parse_app_list(0, ['0']))
|
||||||
self.assertEqual(*self._post_metadata_parse_app_string(0, '0'))
|
self.assertEqual(*self._post_metadata_parse_app_string(0, '0'))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_bool(0, 0))
|
self.assertEqual(*self._post_metadata_parse_build_bool(0, False))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_int(0, 0))
|
self.assertEqual(*self._post_metadata_parse_build_int(0, 0))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_list(0, ['0']))
|
self.assertEqual(*self._post_metadata_parse_build_list(0, ['0']))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_script(0, ['0']))
|
self.assertEqual(*self._post_metadata_parse_build_script(0, ['0']))
|
||||||
@ -2022,43 +2161,41 @@ class PostMetadataParseTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_post_metadata_parse_float_0_0(self):
|
def test_post_metadata_parse_float_0_0(self):
|
||||||
"""Run the float 0.0 through the various field and flag types."""
|
"""Run the float 0.0 through the various field and flag types."""
|
||||||
self.assertEqual(*self._post_metadata_parse_app_list(0.0, 0.0))
|
self.assertEqual(*self._post_metadata_parse_app_list(0.0, ['0.0']))
|
||||||
self.assertEqual(*self._post_metadata_parse_app_string(0.0, '0.0'))
|
self.assertEqual(*self._post_metadata_parse_app_string(0.0, '0.0'))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_bool(0.0, 0.0))
|
self.assertEqual(*self._post_metadata_parse_build_bool(0.0, False))
|
||||||
with self.assertRaises(MetaDataException):
|
with self.assertRaises(MetaDataException):
|
||||||
self._post_metadata_parse_build_int(0.0, MetaDataException)
|
self._post_metadata_parse_build_int(0.0, MetaDataException)
|
||||||
self.assertEqual(*self._post_metadata_parse_build_list(0.0, 0.0))
|
self.assertEqual(*self._post_metadata_parse_build_list(0.0, ['0.0']))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_script(0.0, 0.0))
|
self.assertEqual(*self._post_metadata_parse_build_script(0.0, ['0.0']))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_string(0.0, '0.0'))
|
self.assertEqual(*self._post_metadata_parse_build_string(0.0, '0.0'))
|
||||||
|
|
||||||
def test_post_metadata_parse_float_0_1(self):
|
def test_post_metadata_parse_float_0_1(self):
|
||||||
"""Run the float 0.1 through the various field and flag types."""
|
"""Run the float 0.1 through the various field and flag types."""
|
||||||
with self.assertRaises(TypeError):
|
self.assertEqual(*self._post_metadata_parse_app_list(0.1, ['0.1']))
|
||||||
self._post_metadata_parse_app_list(0.1, TypeError)
|
|
||||||
self.assertEqual(*self._post_metadata_parse_app_string(0.1, '0.1'))
|
self.assertEqual(*self._post_metadata_parse_app_string(0.1, '0.1'))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_bool(0.1, 0.1))
|
self.assertEqual(*self._post_metadata_parse_build_bool(0.1, True))
|
||||||
with self.assertRaises(MetaDataException):
|
with self.assertRaises(MetaDataException):
|
||||||
self._post_metadata_parse_build_int(0.1, MetaDataException)
|
self._post_metadata_parse_build_int(0.1, MetaDataException)
|
||||||
self.assertEqual(*self._post_metadata_parse_build_list(0.1, 0.1))
|
self.assertEqual(*self._post_metadata_parse_build_list(0.1, ['0.1']))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_script(0.1, 0.1))
|
self.assertEqual(*self._post_metadata_parse_build_script(0.1, ['0.1']))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_string(0.1, '0.1'))
|
self.assertEqual(*self._post_metadata_parse_build_string(0.1, '0.1'))
|
||||||
|
|
||||||
def test_post_metadata_parse_float_1_0(self):
|
def test_post_metadata_parse_float_1_0(self):
|
||||||
"""Run the float 1.0 through the various field and flag types."""
|
"""Run the float 1.0 through the various field and flag types."""
|
||||||
with self.assertRaises(TypeError):
|
self.assertEqual(*self._post_metadata_parse_app_list(1.0, ['1.0']))
|
||||||
self._post_metadata_parse_app_list(1.0, TypeError)
|
|
||||||
self.assertEqual(*self._post_metadata_parse_app_string(1.0, '1.0'))
|
self.assertEqual(*self._post_metadata_parse_app_string(1.0, '1.0'))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_bool(1.0, 1.0))
|
self.assertEqual(*self._post_metadata_parse_build_bool(1.0, True))
|
||||||
with self.assertRaises(MetaDataException):
|
with self.assertRaises(MetaDataException):
|
||||||
self._post_metadata_parse_build_int(1.0, MetaDataException)
|
self._post_metadata_parse_build_int(1.0, MetaDataException)
|
||||||
self.assertEqual(*self._post_metadata_parse_build_list(1.0, 1.0))
|
self.assertEqual(*self._post_metadata_parse_build_list(1.0, ['1.0']))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_script(1.0, 1.0))
|
self.assertEqual(*self._post_metadata_parse_build_script(1.0, ['1.0']))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_string(1.0, '1.0'))
|
self.assertEqual(*self._post_metadata_parse_build_string(1.0, '1.0'))
|
||||||
|
|
||||||
def test_post_metadata_parse_empty_list(self):
|
def test_post_metadata_parse_empty_list(self):
|
||||||
self.assertEqual(*self._post_metadata_parse_app_list(list(), list()))
|
self.assertEqual(*self._post_metadata_parse_app_list(list(), list()))
|
||||||
self.assertEqual(*self._post_metadata_parse_app_string(list(), list()))
|
self.assertEqual(*self._post_metadata_parse_app_string(list(), list()))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_bool(list(), list()))
|
self.assertEqual(*self._post_metadata_parse_build_bool(list(), False))
|
||||||
with self.assertRaises(MetaDataException):
|
with self.assertRaises(MetaDataException):
|
||||||
self._post_metadata_parse_build_int(list(), MetaDataException)
|
self._post_metadata_parse_build_int(list(), MetaDataException)
|
||||||
self.assertEqual(*self._post_metadata_parse_build_list(list(), list()))
|
self.assertEqual(*self._post_metadata_parse_build_list(list(), list()))
|
||||||
@ -2068,17 +2205,17 @@ class PostMetadataParseTest(unittest.TestCase):
|
|||||||
def test_post_metadata_parse_set_of_1(self):
|
def test_post_metadata_parse_set_of_1(self):
|
||||||
self.assertEqual(*self._post_metadata_parse_app_list({1}, ['1']))
|
self.assertEqual(*self._post_metadata_parse_app_list({1}, ['1']))
|
||||||
self.assertEqual(*self._post_metadata_parse_app_string({1}, '{1}'))
|
self.assertEqual(*self._post_metadata_parse_app_string({1}, '{1}'))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_bool({1}, {1}))
|
self.assertEqual(*self._post_metadata_parse_build_bool({1}, True))
|
||||||
with self.assertRaises(MetaDataException):
|
with self.assertRaises(MetaDataException):
|
||||||
self._post_metadata_parse_build_int({1}, MetaDataException)
|
self._post_metadata_parse_build_int({1}, MetaDataException)
|
||||||
self.assertEqual(*self._post_metadata_parse_build_list({1}, {1}))
|
self.assertEqual(*self._post_metadata_parse_build_list({1}, ['1']))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_script({1}, {1}))
|
self.assertEqual(*self._post_metadata_parse_build_script({1}, ['1']))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_string({1}, '{1}'))
|
self.assertEqual(*self._post_metadata_parse_build_string({1}, '{1}'))
|
||||||
|
|
||||||
def test_post_metadata_parse_empty_dict(self):
|
def test_post_metadata_parse_empty_dict(self):
|
||||||
self.assertEqual(*self._post_metadata_parse_app_list(dict(), dict()))
|
self.assertEqual(*self._post_metadata_parse_app_list(dict(), dict()))
|
||||||
self.assertEqual(*self._post_metadata_parse_app_string(dict(), dict()))
|
self.assertEqual(*self._post_metadata_parse_app_string(dict(), dict()))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_bool(dict(), dict()))
|
self.assertEqual(*self._post_metadata_parse_build_bool(dict(), False))
|
||||||
with self.assertRaises(MetaDataException):
|
with self.assertRaises(MetaDataException):
|
||||||
self._post_metadata_parse_build_int(dict(), MetaDataException)
|
self._post_metadata_parse_build_int(dict(), MetaDataException)
|
||||||
self.assertEqual(*self._post_metadata_parse_build_list(dict(), dict()))
|
self.assertEqual(*self._post_metadata_parse_build_list(dict(), dict()))
|
||||||
@ -2088,38 +2225,42 @@ class PostMetadataParseTest(unittest.TestCase):
|
|||||||
def test_post_metadata_parse_list_int_string(self):
|
def test_post_metadata_parse_list_int_string(self):
|
||||||
self.assertEqual(*self._post_metadata_parse_app_list([1, 'a'], ['1', 'a']))
|
self.assertEqual(*self._post_metadata_parse_app_list([1, 'a'], ['1', 'a']))
|
||||||
self.assertEqual(*self._post_metadata_parse_app_string([1, 'a'], "[1, 'a']"))
|
self.assertEqual(*self._post_metadata_parse_app_string([1, 'a'], "[1, 'a']"))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_bool([1, 'a'], [1, 'a']))
|
self.assertEqual(*self._post_metadata_parse_build_bool([1, 'a'], True))
|
||||||
with self.assertRaises(MetaDataException):
|
with self.assertRaises(MetaDataException):
|
||||||
self._post_metadata_parse_build_int([1, 'a'], MetaDataException)
|
self._post_metadata_parse_build_int([1, 'a'], MetaDataException)
|
||||||
self.assertEqual(*self._post_metadata_parse_build_list([1, 'a'], [1, 'a']))
|
self.assertEqual(*self._post_metadata_parse_build_list([1, 'a'], ['1', 'a']))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_script([1, 'a'], [1, 'a']))
|
self.assertEqual(*self._post_metadata_parse_build_script([1, 'a'], ['1', 'a']))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_string([1, 'a'], "[1, 'a']"))
|
self.assertEqual(*self._post_metadata_parse_build_string([1, 'a'], "[1, 'a']"))
|
||||||
|
|
||||||
def test_post_metadata_parse_dict_int_string(self):
|
def test_post_metadata_parse_dict_int_string(self):
|
||||||
self.assertEqual(*self._post_metadata_parse_app_list({'k': 1}, ['k']))
|
with self.assertRaises(MetaDataException):
|
||||||
|
self._post_metadata_parse_app_list({'k': 1}, MetaDataException)
|
||||||
self.assertEqual(*self._post_metadata_parse_app_string({'k': 1}, "{'k': 1}"))
|
self.assertEqual(*self._post_metadata_parse_app_string({'k': 1}, "{'k': 1}"))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_bool({'k': 1}, {'k': 1}))
|
self.assertEqual(*self._post_metadata_parse_build_bool({'k': 1}, True))
|
||||||
with self.assertRaises(MetaDataException):
|
with self.assertRaises(MetaDataException):
|
||||||
self._post_metadata_parse_build_int({'k': 1}, MetaDataException)
|
self._post_metadata_parse_build_int({'k': 1}, MetaDataException)
|
||||||
self.assertEqual(*self._post_metadata_parse_build_list({'k': 1}, {'k': 1}))
|
with self.assertRaises(MetaDataException):
|
||||||
self.assertEqual(*self._post_metadata_parse_build_script({'k': 1}, {'k': 1}))
|
self._post_metadata_parse_build_list({'k': 1}, MetaDataException)
|
||||||
|
with self.assertRaises(MetaDataException):
|
||||||
|
self._post_metadata_parse_build_script({'k': 1}, MetaDataException)
|
||||||
self.assertEqual(*self._post_metadata_parse_build_string({'k': 1}, "{'k': 1}"))
|
self.assertEqual(*self._post_metadata_parse_build_string({'k': 1}, "{'k': 1}"))
|
||||||
|
|
||||||
def test_post_metadata_parse_false(self):
|
def test_post_metadata_parse_false(self):
|
||||||
self.assertEqual(*self._post_metadata_parse_app_list(False, False))
|
self.assertEqual(*self._post_metadata_parse_app_list(False, ['false']))
|
||||||
self.assertEqual(*self._post_metadata_parse_app_string(False, 'false'))
|
self.assertEqual(*self._post_metadata_parse_app_string(False, 'false'))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_bool(False, False))
|
self.assertEqual(*self._post_metadata_parse_build_bool(False, False))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_int(False, False))
|
with self.assertRaises(MetaDataException):
|
||||||
|
self._post_metadata_parse_build_int(False, MetaDataException)
|
||||||
self.assertEqual(*self._post_metadata_parse_build_list(False, ['false']))
|
self.assertEqual(*self._post_metadata_parse_build_list(False, ['false']))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_script(False, ['false']))
|
self.assertEqual(*self._post_metadata_parse_build_script(False, ['false']))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_string(False, 'false'))
|
self.assertEqual(*self._post_metadata_parse_build_string(False, 'false'))
|
||||||
|
|
||||||
def test_post_metadata_parse_true(self):
|
def test_post_metadata_parse_true(self):
|
||||||
with self.assertRaises(TypeError):
|
self.assertEqual(*self._post_metadata_parse_app_list(True, ['true']))
|
||||||
self._post_metadata_parse_app_list(True, TypeError)
|
|
||||||
self.assertEqual(*self._post_metadata_parse_app_string(True, 'true'))
|
self.assertEqual(*self._post_metadata_parse_app_string(True, 'true'))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_bool(True, True))
|
self.assertEqual(*self._post_metadata_parse_build_bool(True, True))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_int(True, True))
|
with self.assertRaises(MetaDataException):
|
||||||
|
self._post_metadata_parse_build_int(True, MetaDataException)
|
||||||
self.assertEqual(*self._post_metadata_parse_build_list(True, ['true']))
|
self.assertEqual(*self._post_metadata_parse_build_list(True, ['true']))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_script(True, ['true']))
|
self.assertEqual(*self._post_metadata_parse_build_script(True, ['true']))
|
||||||
self.assertEqual(*self._post_metadata_parse_build_string(True, 'true'))
|
self.assertEqual(*self._post_metadata_parse_build_string(True, 'true'))
|
||||||
|
Loading…
Reference in New Issue
Block a user