Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

human_to_bytes: Unit tests for isbits arg of human_to_bytes function, adding explanation of isbits to the docstring #58623

Merged
merged 16 commits into from Jul 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
3c12fea
human_to_bytest: add unit tests for isbits
Andersson007 Jul 2, 2019
ef6aeca
human_to_bytest: add unit tests for isbits - fix typos
Andersson007 Jul 2, 2019
8e97b89
human_to_bytest: add unit tests for isbits - fix sanity
Andersson007 Jul 2, 2019
420e2b5
human_to_bytest: add unit tests for isbits - add periods to the end o…
Andersson007 Jul 3, 2019
644fa78
human_to_bytest: add unit tests for isbits - change test license
Andersson007 Jul 3, 2019
a7af5a8
human_to_bytest: add unit tests for isbits - add dict
Andersson007 Jul 4, 2019
43edd1a
human_to_bytest: add unit tests for isbits - continue refactoring
Andersson007 Jul 4, 2019
3dfafb1
human_to_bytest: add unit tests for isbits - refactoring
Andersson007 Jul 4, 2019
291a613
human_to_bytest: add unit tests for isbits - add blank line to docstring
Andersson007 Jul 5, 2019
1bc204a
human_to_bytest: add unit tests for isbits - fix typo
Andersson007 Jul 5, 2019
b420cc2
human_to_bytest: add unit tests for isbits - fix typo
Andersson007 Jul 5, 2019
3fcce9c
human_to_bytest: add unit tests for isbits - change NUM_IN_METRIC val…
Andersson007 Jul 5, 2019
f30aa1d
human_to_bytest: add unit tests for isbits - fix indentation
Andersson007 Jul 5, 2019
482f10c
human_to_bytest: add unit tests for isbits - remove logic from test f…
Andersson007 Jul 5, 2019
13839c6
human_to_bytest: add unit tests for isbits - add -1 as a test case
Andersson007 Jul 5, 2019
ff78422
Update test/units/module_utils/common/text/formatters/test_human_to_b…
Andersson007 Jul 5, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 15 additions & 1 deletion lib/ansible/module_utils/common/text/formatters.py
Expand Up @@ -38,7 +38,21 @@ def lenient_lowercase(lst):

def human_to_bytes(number, default_unit=None, isbits=False):
"""Convert number in string format into bytes (ex: '2K' => 2048) or using unit argument.
Andersson007 marked this conversation as resolved.
Show resolved Hide resolved
example: human_to_bytes('10M') <=> human_to_bytes(10, 'M')

example: human_to_bytes('10M') <=> human_to_bytes(10, 'M').

When isbits is False (default), converts bytes from a human-readable format to integer.
example: human_to_bytes('1MB') returns 1048576 (int).
The function expects 'B' (uppercase) as a byte identifier passed
as a part of 'name' param string or 'unit', e.g. 'MB'/'KB'/etc.
(except when the identifier is single 'b', it is perceived as a byte identifier too).
if 'Mb'/'Kb'/... is passed, the ValueError will be rased.

When isbits is True, converts bits from a human-readable format to integer.
example: human_to_bytes('1Mb', isbits=True) returns 1048576 (int) -
string bits representation was passed and return as a number or bits.
The function expects 'b' (lowercase) as a bit identifier, e.g. 'Mb'/'Kb'/etc.
if 'MB'/'KB'/... is passed, the ValueError will be rased.
"""
m = re.search(r'^\s*(\d*\.?\d*)\s*([A-Za-z]+)?', str(number), flags=re.IGNORECASE)
if m is None:
Expand Down
6 changes: 4 additions & 2 deletions lib/ansible/module_utils/common/validation.py
Expand Up @@ -521,9 +521,11 @@ def check_type_bytes(value):


def check_type_bits(value):
"""Convert a human-readable string value to bits
"""Convert a human-readable string bits value to bits in integer.

Raises TypeError if unable to covert the value
Example: check_type_bits('1Mb') returns integer 1048576.

Raises TypeError if unable to covert the value.
"""
try:
return human_to_bytes(value, isbits=True)
Expand Down
186 changes: 145 additions & 41 deletions test/units/module_utils/common/text/formatters/test_human_to_bytes.py
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
# Copyright 2019, Andrew Klychkov @Andersson007 <aaklychkov@mail.ru>
# Simplified BSD License (see licenses/simplified_bsd.txt or https://opensource.org/licenses/BSD-2-Clause)
# Copyright 2019, Sviatoslav Sydorenko <webknjaz@redhat.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import absolute_import, division, print_function
__metaclass__ = type
Expand All @@ -10,29 +11,41 @@
from ansible.module_utils.common.text.formatters import human_to_bytes


NUM_IN_METRIC = {
'K': 2 ** 10,
'M': 2 ** 20,
'G': 2 ** 30,
'T': 2 ** 40,
'P': 2 ** 50,
'E': 2 ** 60,
'Z': 2 ** 70,
'Y': 2 ** 80,
}


@pytest.mark.parametrize(
'input_data,expected',
[
(0, 0),
(1024, 1024),
(u'1024B', 1024),
(u'0B', 0),
(u'1K', 1024),
(u'1KB', 1024),
(u'1MB', 1048576),
(u'1M', 1048576),
(u'1G', 1073741824),
(u'1GB', 1073741824),
(u'1T', 1099511627776),
(u'1TB', 1099511627776),
(u'1P', 1125899906842624),
(u'1PB', 1125899906842624),
(u'1E', 1152921504606846976),
(u'1EB', 1152921504606846976),
(u'1Z', 1180591620717411303424),
(u'1ZB', 1180591620717411303424),
(u'1Y', 1208925819614629174706176),
(u'1YB', 1208925819614629174706176),
(1024, NUM_IN_METRIC['K']),
(u'1024B', NUM_IN_METRIC['K']),
(u'1K', NUM_IN_METRIC['K']),
(u'1KB', NUM_IN_METRIC['K']),
(u'1M', NUM_IN_METRIC['M']),
(u'1MB', NUM_IN_METRIC['M']),
(u'1G', NUM_IN_METRIC['G']),
(u'1GB', NUM_IN_METRIC['G']),
(u'1T', NUM_IN_METRIC['T']),
(u'1TB', NUM_IN_METRIC['T']),
(u'1P', NUM_IN_METRIC['P']),
(u'1PB', NUM_IN_METRIC['P']),
(u'1E', NUM_IN_METRIC['E']),
(u'1EB', NUM_IN_METRIC['E']),
(u'1Z', NUM_IN_METRIC['Z']),
(u'1ZB', NUM_IN_METRIC['Z']),
(u'1Y', NUM_IN_METRIC['Y']),
(u'1YB', NUM_IN_METRIC['Y']),
]
)
def test_human_to_bytes_number(input_data, expected):
Expand All @@ -41,30 +54,30 @@ def test_human_to_bytes_number(input_data, expected):


@pytest.mark.parametrize(
'input_data,unit,expected',
'input_data,unit',
[
(u'1024', u'B', 1024),
(1, u'K', 1024),
(1, u'KB', 1024),
(u'1', u'M', 1048576),
(u'1', u'MB', 1048576),
(1, u'G', 1073741824),
(1, u'GB', 1073741824),
(1, u'T', 1099511627776),
(1, u'TB', 1099511627776),
(u'1', u'P', 1125899906842624),
(u'1', u'PB', 1125899906842624),
(u'1', u'E', 1152921504606846976),
(u'1', u'EB', 1152921504606846976),
(u'1', u'Z', 1180591620717411303424),
(u'1', u'ZB', 1180591620717411303424),
(u'1', u'Y', 1208925819614629174706176),
(u'1', u'YB', 1208925819614629174706176),
(u'1024', 'B'),
(1, u'K'),
(1, u'KB'),
(u'1', u'M'),
(u'1', u'MB'),
(1, u'G'),
(1, u'GB'),
(1, u'T'),
(1, u'TB'),
(u'1', u'P'),
(u'1', u'PB'),
(u'1', u'E'),
(u'1', u'EB'),
(u'1', u'Z'),
(u'1', u'ZB'),
(u'1', u'Y'),
(u'1', u'YB'),
]
)
def test_human_to_bytes_number_unit(input_data, unit, expected):
def test_human_to_bytes_number_unit(input_data, unit):
"""Test of human_to_bytes function, number and default_unit args are passed."""
assert human_to_bytes(input_data, default_unit=unit) == expected
assert human_to_bytes(input_data, default_unit=unit) == NUM_IN_METRIC.get(unit[0], 1024)


@pytest.mark.parametrize('test_input', [u'1024s', u'1024w', ])
Expand All @@ -74,8 +87,99 @@ def test_human_to_bytes_wrong_unit(test_input):
human_to_bytes(test_input)


@pytest.mark.parametrize('test_input', [u'b1bbb', u'm2mmm', u'', u' ', ])
@pytest.mark.parametrize('test_input', [u'b1bbb', u'm2mmm', u'', u' ', -1])
def test_human_to_bytes_wrong_number(test_input):
"""Test of human_to_bytes function, nubmer param is invalid string / number."""
"""Test of human_to_bytes function, number param is invalid string / number."""
with pytest.raises(ValueError, match="can't interpret"):
human_to_bytes(test_input)


@pytest.mark.parametrize(
'input_data,expected',
[
(0, 0),
(u'0B', 0),
(u'1024b', 1024),
(u'1024B', 1024),
(u'1K', NUM_IN_METRIC['K']),
(u'1Kb', NUM_IN_METRIC['K']),
(u'1M', NUM_IN_METRIC['M']),
(u'1Mb', NUM_IN_METRIC['M']),
(u'1G', NUM_IN_METRIC['G']),
(u'1Gb', NUM_IN_METRIC['G']),
(u'1T', NUM_IN_METRIC['T']),
(u'1Tb', NUM_IN_METRIC['T']),
(u'1P', NUM_IN_METRIC['P']),
(u'1Pb', NUM_IN_METRIC['P']),
(u'1E', NUM_IN_METRIC['E']),
(u'1Eb', NUM_IN_METRIC['E']),
(u'1Z', NUM_IN_METRIC['Z']),
(u'1Zb', NUM_IN_METRIC['Z']),
(u'1Y', NUM_IN_METRIC['Y']),
(u'1Yb', NUM_IN_METRIC['Y']),
]
)
def test_human_to_bytes_isbits(input_data, expected):
"""Test of human_to_bytes function, isbits = True."""
assert human_to_bytes(input_data, isbits=True) == expected


@pytest.mark.parametrize(
'input_data,unit',
[
(1024, 'b'),
(1024, 'B'),
(1, u'K'),
(1, u'Kb'),
(u'1', u'M'),
(u'1', u'Mb'),
(1, u'G'),
(1, u'Gb'),
(1, u'T'),
(1, u'Tb'),
(u'1', u'P'),
(u'1', u'Pb'),
(u'1', u'E'),
(u'1', u'Eb'),
(u'1', u'Z'),
(u'1', u'Zb'),
(u'1', u'Y'),
(u'1', u'Yb'),
]
)
def test_human_to_bytes_isbits_default_unit(input_data, unit):
"""Test of human_to_bytes function, isbits = True and default_unit args are passed."""
assert human_to_bytes(input_data, default_unit=unit, isbits=True) == NUM_IN_METRIC.get(unit[0], 1024)


@pytest.mark.parametrize(
'test_input,isbits',
[
('1024Kb', False),
('10Mb', False),
('1Gb', False),
('10MB', True),
('2KB', True),
('4GB', True),
]
)
def test_human_to_bytes_isbits_wrong_unit(test_input, isbits):
"""Test of human_to_bytes function, unit identifier is in an invalid format for isbits value."""
with pytest.raises(ValueError, match="Value is not a valid string"):
human_to_bytes(test_input, isbits=isbits)


@pytest.mark.parametrize(
'test_input,unit,isbits',
[
(1024, 'Kb', False),
('10', 'Mb', False),
('10', 'MB', True),
(2, 'KB', True),
('4', 'GB', True),
]
)
def test_human_to_bytes_isbits_wrong_default_unit(test_input, unit, isbits):
"""Test of human_to_bytes function, default_unit is in an invalid format for isbits value."""
with pytest.raises(ValueError, match="Value is not a valid string"):
human_to_bytes(test_input, default_unit=unit, isbits=isbits)