1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
|
######################################################################
#
# File: test/unit/v0/test_utils.py
#
# Copyright 2019 Backblaze Inc. All Rights Reserved.
#
# License https://www.backblaze.com/using_b2_code.html
#
######################################################################
from __future__ import annotations
from ..test_base import TestBase
from .deps import (
b2_url_decode,
b2_url_encode,
choose_part_ranges,
format_and_scale_fraction,
format_and_scale_number,
)
# These are from the B2 Docs (https://www.backblaze.com/b2/docs/string_encoding.html)
ENCODING_TEST_CASES = [
{'fullyEncoded': '%20', 'minimallyEncoded': '+', 'string': ' '},
{'fullyEncoded': '%21', 'minimallyEncoded': '!', 'string': '!'},
{'fullyEncoded': '%22', 'minimallyEncoded': '%22', 'string': '"'},
{'fullyEncoded': '%23', 'minimallyEncoded': '%23', 'string': '#'},
{'fullyEncoded': '%24', 'minimallyEncoded': '$', 'string': '$'},
{'fullyEncoded': '%25', 'minimallyEncoded': '%25', 'string': '%'},
{'fullyEncoded': '%26', 'minimallyEncoded': '%26', 'string': '&'},
{'fullyEncoded': '%27', 'minimallyEncoded': "'", 'string': "'"},
{'fullyEncoded': '%28', 'minimallyEncoded': '(', 'string': '('},
{'fullyEncoded': '%29', 'minimallyEncoded': ')', 'string': ')'},
{'fullyEncoded': '%2A', 'minimallyEncoded': '*', 'string': '*'},
{'fullyEncoded': '%2B', 'minimallyEncoded': '%2B', 'string': '+'},
{'fullyEncoded': '%2C', 'minimallyEncoded': '%2C', 'string': ','},
{'fullyEncoded': '%2D', 'minimallyEncoded': '-', 'string': '-'},
{'fullyEncoded': '%2E', 'minimallyEncoded': '.', 'string': '.'},
{'fullyEncoded': '/', 'minimallyEncoded': '/', 'string': '/'},
{'fullyEncoded': '%30', 'minimallyEncoded': '0', 'string': '0'},
{'fullyEncoded': '%39', 'minimallyEncoded': '9', 'string': '9'},
{'fullyEncoded': '%3A', 'minimallyEncoded': ':', 'string': ':'},
{'fullyEncoded': '%3B', 'minimallyEncoded': ';', 'string': ';'},
{'fullyEncoded': '%3C', 'minimallyEncoded': '%3C', 'string': '<'},
{'fullyEncoded': '%3D', 'minimallyEncoded': '=', 'string': '='},
{'fullyEncoded': '%3E', 'minimallyEncoded': '%3E', 'string': '>'},
{'fullyEncoded': '%3F', 'minimallyEncoded': '%3F', 'string': '?'},
{'fullyEncoded': '%40', 'minimallyEncoded': '@', 'string': '@'},
{'fullyEncoded': '%41', 'minimallyEncoded': 'A', 'string': 'A'},
{'fullyEncoded': '%5A', 'minimallyEncoded': 'Z', 'string': 'Z'},
{'fullyEncoded': '%5B', 'minimallyEncoded': '%5B', 'string': '['},
{'fullyEncoded': '%5C', 'minimallyEncoded': '%5C', 'string': '\\'},
{'fullyEncoded': '%5D', 'minimallyEncoded': '%5D', 'string': ']'},
{'fullyEncoded': '%5E', 'minimallyEncoded': '%5E', 'string': '^'},
{'fullyEncoded': '%5F', 'minimallyEncoded': '_', 'string': '_'},
{'fullyEncoded': '%60', 'minimallyEncoded': '%60', 'string': '`'},
{'fullyEncoded': '%61', 'minimallyEncoded': 'a', 'string': 'a'},
{'fullyEncoded': '%7A', 'minimallyEncoded': 'z', 'string': 'z'},
{'fullyEncoded': '%7B', 'minimallyEncoded': '%7B', 'string': '{'},
{'fullyEncoded': '%7C', 'minimallyEncoded': '%7C', 'string': '|'},
{'fullyEncoded': '%7D', 'minimallyEncoded': '%7D', 'string': '}'},
{'fullyEncoded': '%7E', 'minimallyEncoded': '~', 'string': '~'},
{'fullyEncoded': '%7F', 'minimallyEncoded': '%7F', 'string': '\u007f'},
{
'fullyEncoded': '%E8%87%AA%E7%94%B1',
'minimallyEncoded': '%E8%87%AA%E7%94%B1',
'string': '\u81ea\u7531',
},
{'fullyEncoded': '%F0%90%90%80', 'minimallyEncoded': '%F0%90%90%80', 'string': '\U00010400'},
]
class TestUrlEncoding(TestBase):
def test_it(self):
for test_case in ENCODING_TEST_CASES:
string = test_case['string']
fully_encoded = test_case['fullyEncoded']
minimally_encoded = test_case['minimallyEncoded']
encoded = b2_url_encode(string)
expected_encoded = (minimally_encoded, fully_encoded)
if encoded not in expected_encoded:
print(f'string: {repr(string)} encoded: {encoded} expected: {expected_encoded}')
self.assertTrue(encoded in expected_encoded)
self.assertEqual(string, b2_url_decode(fully_encoded))
self.assertEqual(string, b2_url_decode(minimally_encoded))
class TestChooseParts(TestBase):
def test_it(self):
self._check_one([(0, 100), (100, 100)], 200, 100)
self._check_one([(0, 149), (149, 150)], 299, 100)
self._check_one([(0, 100), (100, 100), (200, 100)], 300, 100)
ten_TB = 10 * 1000 * 1000 * 1000 * 1000
one_GB = 1000 * 1000 * 1000
expected = [(i * one_GB, one_GB) for i in range(10000)]
actual = choose_part_ranges(ten_TB, 100 * 1000 * 1000)
self.assertEqual(expected, actual)
def _check_one(self, expected, content_length, min_part_size):
self.assertEqual(expected, choose_part_ranges(content_length, min_part_size))
class TestFormatAndScaleNumber(TestBase):
def test_it(self):
self._check_one('1 B', 1)
self._check_one('999 B', 999)
self._check_one('1.00 kB', 1000)
self._check_one('999 kB', 999000)
def _check_one(self, expected, x):
self.assertEqual(expected, format_and_scale_number(x, 'B'))
class TestFormatAndScaleFraction(TestBase):
def test_it(self):
self._check_one('0 / 100 B', 0, 100)
self._check_one('0.0 / 10.0 kB', 0, 10000)
self._check_one('9.4 / 10.0 kB', 9400, 10000)
def _check_one(self, expected, numerator, denominator):
self.assertEqual(expected, format_and_scale_fraction(numerator, denominator, 'B'))
|