def test_parse_parts_with_head_boundary(): bndry = '---boundary---' part_bndry = bytes('--' + bndry + '\r\n', 'ascii') file_bndry = bytes('--' + bndry + '--\r\n', 'ascii') # head boundary - announce part assert mhtml.parse_parts(b'\r\n' + part_bndry + b'CH: CV\r\n\r\n' b'content\r\n', bndry, 2) \ == ([(mhtml.ResourceHeader([('CH', 'CV')]), 20, 30, 39)], -1) # TODO: work with monkeypatching? # TODO: should recognize empty part? # something like first part, then another follows but is somewhat vague ... assert mhtml.parse_parts(b'\r\n' + part_bndry + b'CH: CV\r\n\r\n' b'content\r\n' + part_bndry, bndry, 2) \ == ([(mhtml.ResourceHeader([('CH', 'CV')]), 20, 30, 39), (mhtml.ResourceHeader(), 57, -1, 57)], -1) # single part (use-case: last-part before file boundary) assert mhtml.parse_parts(b'\r\n' + part_bndry + b'CH: CV\r\n\r\n' b'content\r\n' + file_bndry, bndry, 0) \ == ([(mhtml.ResourceHeader([('CH', 'CV')]), 20, 30, 39)], -1)
def test_MHTMLArchive_properties(mocker): # noqa: N802 mhtarc = mhtml.MHTMLArchive(b'content', mhtml.ResourceHeader(), 0, '---boundary---') assert mhtarc.headers == mhtml.ResourceHeader() mhtarc = mhtml.MHTMLArchive(b'content', None, 0, '---boundary---') assert mhtarc.headers == mhtml.ResourceHeader() mock_headers = mocker.Mock(content_type='content-abc', location='location-abc') mhtarc._headers = mock_headers assert mhtarc.headers == mock_headers assert mhtarc.content_type == 'content-abc' assert mhtarc.location == 'location-abc' assert mhtarc.boundary == '---boundary---' assert mhtarc.content == b'content' # WIP no boundary? - may need to create one mock_method = mocker.patch('mhtml.get_boundary', return_value=None) mock_headers = mocker.Mock(spec=mhtml.ResourceHeader) mhtarc = mhtml.MHTMLArchive(b'content', mock_headers, 0, None) assert mhtarc.boundary is None mock_method.assert_called_once_with(mock_headers) # check if in headers mocker.patch('mhtml.get_boundary', return_value=mocker.sentinel.bndry) mhtarc = mhtml.MHTMLArchive(b'content', mhtml.ResourceHeader(), 0, None) assert mhtarc.boundary == mocker.sentinel.bndry
def test_get_boundary(): # no headers with pytest.raises(AttributeError): mhtml.get_boundary(None) # no content-type assert mhtml.get_boundary(mhtml.ResourceHeader()) is None # missing boundary declaration assert mhtml.get_boundary( mhtml.ResourceHeader([('conTent-TyPe', 'text/html')])) is None assert mhtml.get_boundary( mhtml.ResourceHeader( [('conTent-TyPe', 'text/html;\r\n\tabc\r\n\tboundary="' '---test-boundary---' '"')])) is None # has to be multipart assert mhtml.get_boundary( mhtml.ResourceHeader( [('Content-Type', 'multipart/related;\r\n\tabc\r\n' '\tnothing-here')])) is None # has to be multipart and contain a boundary declaration assert mhtml.get_boundary( mhtml.ResourceHeader([('Content-Type', 'multipart/related;\r\n\tabc\r\n\tboundary="' '---test-boundary---' '"')])) == '---test-boundary---'
def test_get_content_type(): # more verbose construction mock_headers = mhtml.ResourceHeader() mock_headers['Content-Type'] = 'text/html' assert mhtml.get_content_type(mock_headers) == 'text/html' # case insensitive assert mhtml.get_content_type( mhtml.ResourceHeader([('conTent-TyPe', 'text/html')])) == 'text/html' # multipart/related assert mhtml.get_content_type( mhtml.ResourceHeader([('conTent-TyPe', 'multipart/related;\r\n\t...') ])) == 'multipart/related' # empty headers -> None assert mhtml.get_content_type(mhtml.ResourceHeader()) is None # no headers with pytest.raises(AttributeError): mhtml.get_content_type(None) # even standard dicts, but case sensitive assert mhtml.get_content_type({'Content-Type': 'text/abc'}) == 'text/abc' assert mhtml.get_content_type({'conTent-TyPe': 'text/abc'}) is None
def test_parse_header(): assert mhtml.parse_header(b'', 0) == (mhtml.ResourceHeader(), -1) # needs two linebreaks (a single empty line) after the header fields with pytest.raises(AssertionError): assert mhtml.parse_header(b'CH: CV\r\n', 0) == \ (mhtml.ResourceHeader([('CH', 'CV')]), -1) # really short header assert mhtml.parse_header(b'CH: CV\r\n\r\n', 0) == \ (mhtml.ResourceHeader([('CH', 'CV')]), -1) assert mhtml.parse_header(b'CH: CV\r\nCH2: CV2\r\nCH3: CV3\r\n\r\n', 0) \ == (mhtml.ResourceHeader([('CH', 'CV'), ('CH2', 'CV2'), ('CH3', 'CV3')]), -1) # TODO: how to handle multiple spaces -> trim()? assert mhtml.parse_header(b'CH: CV\r\n\r\n', 0) == \ (mhtml.ResourceHeader([('CH', ' CV')]), -1) # needs at least a single space assert mhtml.parse_header(b'CH:CV\r\n\r\n', 0) == \ (mhtml.ResourceHeader([]), -1) assert mhtml.parse_header(b'CH: CV\r\n\r\n\r\n-----boundary---', 0) == \ (mhtml.ResourceHeader([('CH', 'CV')]), 10) # value with linebreaks assert mhtml.parse_header(b'CH: CV;\r\n\tCV2\r\n\r\n', 0) == \ (mhtml.ResourceHeader([('CH', 'CV;\r\n\tCV2')]), -1) assert mhtml.parse_header(b'CH: CV;\r\n\tCV2\r\nCH2: CV3\r\n\r\n', 0) == \ (mhtml.ResourceHeader([('CH', 'CV;\r\n\tCV2'), ('CH2', 'CV3')]), -1)
def test_ResourceHeader_magic(): # noqa: N802 # eq / ne rh1 = mhtml.ResourceHeader([('a', 'b')]) rh2 = mhtml.ResourceHeader([('A', 'b')]) rh3 = mhtml.ResourceHeader([('A', 'b')]) rh4 = mhtml.ResourceHeader([('c', 'b')]) assert not rh1 == rh2 # pylint: disable=unneeded-not assert rh2 == rh3 assert rh1 != rh2 assert not rh2 != rh3 # pylint: disable=unneeded-not assert rh2 != rh4 assert not rh1 == rh4 # pylint: disable=unneeded-not assert (not rh1.__eq__(rh2)) == rh1.__ne__(rh2) assert rh3.__eq__(rh2) == (not rh3.__ne__(rh2)) # checks type, not only content assert rh1 != rh1._headers # str / repr assert str(rh2) == str(rh2._headers) assert repr(rh2) == 'ResourceHeader: ' + repr(rh2._headers) # as_list rh = mhtml.ResourceHeader([('a', 'b'), ('A', 'c'), ('D', 'e')]) assert rh.as_list() == [('a', 'b'), ('A', 'c'), ('D', 'e')] hl = rh.as_list() hl.append(('t', 't')) assert rh.as_list() != hl # as_dict rh = mhtml.ResourceHeader([('a', 'b'), ('A', 'c'), ('D', 'e')]) assert rh.as_dict() == {'a': 'b', 'A': 'c', 'D': 'e'} # TODO: items() modification ? # iter rh = mhtml.ResourceHeader([('a', 'b'), ('A', 'c'), ('D', 'e')]) assert iter(rh) assert list(rh) == ['a', 'A', 'D'] # del rh = mhtml.ResourceHeader([('a', 'b'), ('A', 'c'), ('D', 'e')]) del rh['a'] assert rh.items() == [('D', 'e')] del rh[None] assert len(rh) == 1 # TODO: get/del/set empty strings? rh = mhtml.ResourceHeader() rh[''] = 'h' assert len(rh) == 1 assert rh[''] == 'h' del rh[''] assert len(rh) == 0
def test_make_filename(): # no headers given assert mhtml.make_filename(None, default='abc') == 'abc' # empty header assert mhtml.make_filename(mhtml.ResourceHeader(), default='abd') == 'abd' assert mhtml.make_filename(mhtml.ResourceHeader([('CH', 'CV')]), default='abd') == 'abd' # assume we have extensions mock_headers = mhtml.ResourceHeader() mock_headers['Content-Location'] = 'proto://path/to/file.ext' assert mhtml.make_filename(mock_headers, guess_extension=False) == 'file.ext' assert mhtml.make_filename(mock_headers, folder='abc', guess_extension=False) == 'abc/file.ext' assert mhtml.make_filename(mock_headers, guess_extension=True) == 'file.ext' assert mhtml.make_filename(mock_headers) == 'file.ext' # test guessing extensions del mock_headers['Content-Location'] mock_headers['Content-Location'] = 'proto://path/to/file' assert mhtml.make_filename(mock_headers, default='abc.hhh') == 'file.hhh' # if not extension, then .bin ? assert mhtml.make_filename(mock_headers, default=None) == 'file.bin' assert mhtml.make_filename(mock_headers, default='ooo') == 'file.bin' assert mhtml.make_filename(mock_headers, default='lolo.olo', ext_from_default=True) == 'file.olo' # add content-type mock_headers['Content-Type'] = 'myster/lexi' assert mhtml.make_filename(mock_headers, default='ooo.hhh') == 'file.lexi' assert mhtml.make_filename(mock_headers, folder='ddd/bbb/', default='ooo.hhh') == 'ddd/bbb/file.lexi' del mock_headers['Content-Type'] mock_headers['Content-Type'] = 'mystery' assert mhtml.make_filename(mock_headers) == 'file.mystery' # force use of default extension del mock_headers['Content-Location'] mock_headers['Content-Location'] = 'proto://path/to/file' assert mhtml.make_filename(mock_headers, default='lolo.olo', ext_from_default=True) == 'file.olo'
def test_ResourceHeader_methods_get(): # noqa: N802 rh = mhtml.ResourceHeader() rh['a'] = 'b' assert rh.get(None, None) is None assert rh.get(None, 'y') == 'y' assert rh.get('A') == 'b' assert rh.get('a') == 'b' assert rh.get('a', None) == 'b' assert rh.get('c', 'x') == 'x' assert rh.get_all('a') == ['b'] assert rh.get_all('c') == [] # return default list on invalid key/name assert rh.get_all(None) == [] assert rh.get_all(None, default=1) == 1 rh['A'] = 'F' assert rh.get_all('a') == ['b', 'F'] # getter assert rh['a'] == 'b' rh['C'] = 1 rh['c'] = 2 assert rh['c'] == 1
def test_MHTMLArchive_properties_resources(mocker): # noqa: N802 mhtarc = mhtml.MHTMLArchive(b'content', mhtml.ResourceHeader(), 0, '---boundary---') assert mhtarc.resources == [] assert mhtarc.get_resource(0) is None assert mhtarc.get_resource(-1) is None assert mhtarc.get_resource(10) is None # setting resources mhtarc._set_resources(None) assert isinstance(mhtarc.resources, list) mhtarc._set_resources('a') assert isinstance(mhtarc.resources, list) mhtarc._set_resources([]) assert isinstance(mhtarc.resources, list) # TODO: checking resources from type Resource? mhtarc._set_resources([1]) assert mhtarc.resources == [1] assert mhtarc.get_resource(0) == 1 assert mhtarc.get_resource(1) is None assert mhtarc.remove_resource(-1) is False # wrong resource type should raise an error with pytest.raises(AttributeError, match="""'int' object has no attribute 'get_resource_range'"""): # noqa: E501 pylint: disable=line-too-long mhtarc.remove_resource(0)
def test_MHTMLArchive_update_offsets(mocker): # noqa: N802 mhtarc = mhtml.MHTMLArchive(b'content', mhtml.ResourceHeader(), 0, '---boundary---') mock_resource = mocker.Mock() mock_resource2 = mocker.Mock() mhtarc._set_resources([mock_resource, mock_resource2]) # abort if not valid mhtarc._update_offsets(-5, None) mock_resource._update_offsets.assert_not_called() mock_resource2._update_offsets.assert_not_called() mhtarc._update_offsets(-5, 1) mock_resource._update_offsets.assert_not_called() mock_resource2._update_offsets.assert_called_once_with(-5) mhtarc._update_offsets(2, 0) mock_resource._update_offsets.assert_called_once_with(2) mock_resource2._update_offsets.assert_any_call(2) mock_method = mocker.Mock(return_value=False) mhtarc._is_valid_resource_index = mock_method mhtarc._update_offsets(2, 0) mock_method.assert_called_once_with(0)
def test_Resource_properties(mocker): # noqa: N802 with pytest.raises(AssertionError, match='mhtml_file should be a MHTMLArchive'): mhtml.Resource(None, None, 0, 0, 0) mhtarc = mhtml.MHTMLArchive(b'', None, 0, '---boundary---') # default resource headers res = mhtml.Resource(mhtarc, None, 0, 0, 0) assert res.headers == mhtml.ResourceHeader() assert res.headers == res._headers assert mhtml.Resource(mhtarc, None, 0, 0, 0).headers == \ mhtml.ResourceHeader() assert mhtml.Resource(mhtarc, [], 0, 0, 0).headers == \ mhtml.ResourceHeader() assert mhtml.Resource(mhtarc, {}, 0, 0, 0).headers == \ mhtml.ResourceHeader() # properties mock_headers = mocker.Mock(content_type='content-abc', location='location-abc', encoding='encoding-123') res._headers = mock_headers assert res.content_type == 'content-abc' assert res.location == 'location-abc' assert res.encoding == 'encoding-123' # filename mock_method = mocker.patch('mhtml.make_filename') mock_method.return_value = 'name' assert res.get_short_filename(default='foo') == 'name' mock_method.assert_called_once_with(res._headers, default='foo') # content mock_prop = mocker.Mock(return_value=b'123') res.get_content = mock_prop assert res.content == b'123' mock_prop.assert_called_once_with() # content set mock_prop_set = mocker.Mock() res.set_content = mock_prop_set res.content = b'abc123' mock_prop_set.assert_called_once_with(b'abc123')
def test_ResourceHeader_headers(): # noqa: N802 # single header as list or dict rh = mhtml.ResourceHeader([('a', 'b')]) assert rh._headers == [('a', 'b')] rh = mhtml.ResourceHeader({'aA': 'BbC'}) assert rh._headers == [('aA', 'BbC')] # empty header + add some rh = mhtml.ResourceHeader() assert rh._headers == [] assert len(rh) == 0 # pylint: disable=len-as-condition rh['C'] = 'BbBb' rh['AAaA'] = 'BbBb' rh['AAaA'] = 'BbBb' rh['aaaa'] = 'bbbb' assert rh._headers == [('C', 'BbBb'), ('AAaA', 'BbBb'), ('AAaA', 'BbBb'), ('aaaa', 'bbbb')] assert rh.items() == [('C', 'BbBb'), ('AAaA', 'BbBb'), ('AAaA', 'BbBb'), ('aaaa', 'bbbb')] assert len(rh) == 4 # none as key is ignored rh[None] = 1 assert len(rh) == 4 rh[''] = 1 assert len(rh) == 5 # set converts name to string rh[1] = 2 assert len(rh) == 6 assert rh._headers[5] == ('1', 2) # check contains, case insensitive assert '1' in rh assert 'c' in rh assert 'aaaa' in rh assert 'AAAA' in rh assert 'xxxxx' not in rh assert not 'xxxxx' in rh # noqa: E713 pylint: disable=unneeded-not rh[None] = 1 assert None not in rh
def test_MHTMLArchive_move_resource(mocker): # noqa: N802 bndry = '---boundary---' content = b'content' mhtarc = mhtml.MHTMLArchive(content, mhtml.ResourceHeader(), 0, bndry) mock_resource = mocker.Mock(spec=mhtml.Resource) mock_resource2 = mocker.Mock(spec=mhtml.Resource) mock_resource2.headers = mhtml.ResourceHeader({'H2': 'V33'}) mhtarc._set_resources([mock_resource, mock_resource2]) # _get_resource_and_nr fails mock_method_getresnr1 = mocker.Mock(return_value=(None, None, False)) mhtarc._get_resource_and_nr = mock_method_getresnr1 assert mhtarc.move_resource(mocker.sentinel.nr_or_res, mocker.sentinel.nr) is False mock_method_getresnr1.assert_called_once_with(mocker.sentinel.nr_or_res) # _get_resource_and_nr ok, same position pos = 1234 mock_method_getresnr2 = mocker.Mock(return_value=(pos, mocker.sentinel.res, True)) mhtarc._get_resource_and_nr = mock_method_getresnr2 assert mhtarc.move_resource(mocker.sentinel.nr_or_res, pos) is True mock_method_getresnr2.assert_called_once_with(mocker.sentinel.nr_or_res) # _get_resource_and_nr ok, different position, insert fails pos2 = 4321 mock_method_insert1 = mocker.Mock(return_value=False) mhtarc.insert_resource = mock_method_insert1 assert mhtarc.move_resource(mocker.sentinel.nr_or_res, pos2) is False mock_method_insert1.assert_called_once_with(pos2, mocker.sentinel.res) # ret ok, different nrs, insert ok, remove mock_method_insert2 = mocker.Mock(return_value=True) mock_method_remove = mocker.Mock(return_value=mocker.sentinel.remove_ret) mhtarc.insert_resource = mock_method_insert2 mhtarc.remove_resource = mock_method_remove assert mhtarc.move_resource(mocker.sentinel.nr_or_res, pos2) \ is mocker.sentinel.remove_ret mock_method_insert2.assert_called_once_with(pos2, mocker.sentinel.res) mock_method_remove.assert_called_once_with(mocker.sentinel.res)
def test_parse_part(): # boundary is string (because from header) with pytest.raises(TypeError): mhtml.parse_part(b'', b'', 0) bndry = '---boundary---' part_bndry = bytes('--' + bndry + '\r\n', 'ascii') file_bndry = bytes('--' + bndry + '--\r\n', 'ascii') # this case should not happen, because there will always be a part when # the function is called? assert mhtml.parse_part(b'', bndry, 0) == \ ((mhtml.ResourceHeader(), 0, -1, 0), -1) # simulate last part (end-of-parts boundary) (see the extra dashes) assert mhtml.parse_part(b'CH: CV\r\n\r\ncontent\r\n' + file_bndry, bndry, 0) == \ ((mhtml.ResourceHeader([('CH', 'CV')]), 0, 10, 19), -1) # simulate more parts (end-of-part boundary) assert mhtml.parse_part(b'CH: CV\r\n\r\ncontent\r\n' + part_bndry, bndry, 0) == \ ((mhtml.ResourceHeader([('CH', 'CV')]), 0, 10, 19), 37)
def test_MHTMLArchive_change_resource_content(mocker): # noqa: N802 bndry = '---boundary---' bndry_part = bytes('--' + bndry + '\r\n', 'ascii') header = b'H: V\r\n\r\n\r\n' content1 = b'H1: V2\r\n\r\ncontent\r\n' content2_header = b'H2: V33\r\n\r\n' content2_content = b'123\r\n' content2_content_new = b'new_content_abc' content2 = content2_header + content2_content content = header \ + bndry_part \ + content1 \ + bndry_part \ + content2 \ + bytes('--' + bndry + '--\r\n', 'ascii') mhtarc = mhtml.MHTMLArchive(content, mhtml.ResourceHeader(), len(header), bndry) assert mhtarc.replace_content(0, content2_content_new) is False assert mhtarc.replace_content(None, content2_content_new) is False mock_resource = mocker.Mock(spec=mhtml.Resource) # resource to change mock_resource2 = mocker.Mock(spec=mhtml.Resource) offset = len(header) + len(bndry_part) + len(content1) + len(bndry_part) mock_resource2._offset_start = offset mock_resource2._offset_content = offset + len(content2_header) mock_resource2._offset_end = offset + len(content2) mhtarc._set_resources([mock_resource, mock_resource2]) mock_method_get = mocker.Mock(return_value=(1, mock_resource2, True)) mhtarc._get_resource_and_nr = mock_method_get mock_method_update = mocker.Mock() mhtarc._update_offsets = mock_method_update assert mhtarc.replace_content(mock_resource2, content2_content_new) is True mock_method_get.assert_called_once_with(mock_resource2) # difference between content, nr nach resource mock_method_update.assert_called_once_with( len(content2_content_new) - len(content2_content), 2) assert mock_resource2._offset_end == mock_resource2._offset_content \ + len(content2_content_new) assert mhtarc.content == header \ + bndry_part \ + content1 \ + bndry_part \ + content2_header + content2_content_new \ + bytes('--' + bndry + '--\r\n', 'ascii')
def test_MHTMLArchive_remove_resource(mocker): # noqa: N802 mhtarc = mhtml.MHTMLArchive(b'content', mhtml.ResourceHeader(), 0, '---boundary---') mock_resource = mocker.Mock(spec=mhtml.Resource) mock_resource.get_resource_range.return_value = (2, 5) mock_method = mocker.Mock() mhtarc._update_offsets = mock_method mhtarc._set_resources([mock_resource]) assert mhtarc.remove_resource(0) is True assert mhtarc.remove_resource(0) is False assert mhtarc.content == b'cont' assert mhtarc.resources == [] mock_resource.get_resource_range.assert_called_once_with(18) mock_method.assert_called_once_with(-3, 0)
def test_MHTMLArchive_helpers(mocker): # noqa: N802 mhtarc = mhtml.MHTMLArchive(b'content', mhtml.ResourceHeader(), 0, '---boundary---') # valid resource index assert mhtarc._is_valid_resource_index(None) is False assert mhtarc._is_valid_resource_index(3.4) is False assert mhtarc._is_valid_resource_index(-1) is False assert mhtarc._is_valid_resource_index(0) is False assert mhtarc._is_valid_resource_index(1) is False mock_resource = mocker.Mock(spec=mhtml.Resource) mock_resource2 = mocker.Mock(spec=mhtml.Resource) mhtarc._set_resources([mock_resource, mock_resource2]) assert mhtarc._is_valid_resource_index(-1) is False assert mhtarc._is_valid_resource_index(0) is True assert mhtarc._is_valid_resource_index(1) is True assert mhtarc._is_valid_resource_index(2) is False assert mhtarc._is_valid_resource_index('1') is False # get resource nr mhtarc._set_resources([]) assert mhtarc._resource_to_nr(mock_resource) is None mhtarc._set_resources([mock_resource, mock_resource2]) assert mhtarc._resource_to_nr(mock_resource) == 0 assert mhtarc._resource_to_nr(mock_resource2) == 1 assert mhtarc._resource_to_nr(None) is None assert mhtarc._resource_to_nr(0) is None # get resource + nr mhtarc._set_resources([]) assert mhtarc._get_resource_and_nr(None) == (None, None, False) assert mhtarc._get_resource_and_nr(mock_resource)[2] is False assert mhtarc._get_resource_and_nr(0)[2] is False mhtarc._set_resources([mock_resource]) assert mhtarc._get_resource_and_nr(mock_resource) == \ (0, mock_resource, True) assert mhtarc._get_resource_and_nr(mock_resource2)[2] is False assert mhtarc._get_resource_and_nr(1)[2] is False assert mhtarc._get_resource_and_nr(-1)[2] is False mhtarc._set_resources([mock_resource, mock_resource2]) assert mhtarc._get_resource_and_nr(mock_resource2) == \ (1, mock_resource2, True) assert mhtarc._get_resource_and_nr('1') == (None, None, False)
def test_ResourceHeader_properties(mocker): # noqa: N802 rh = mhtml.ResourceHeader() rh['C'] = 'BbBb' # content type mock_method = mocker.patch('mhtml.get_content_type') mock_method.return_value = 'ab' assert rh.content_type == 'ab' mock_method.assert_called_once_with(rh) # encoding mock_get = mocker.Mock() mock_get.return_value = 1 rh.get = mock_get assert rh.encoding == 1 mock_get.assert_called_once_with('Content-Transfer-Encoding') # location mock_get = mocker.Mock() mock_get.return_value = None rh.get = mock_get assert rh.location is None assert mock_get.call_args_list == [ mocker.call('Snapshot-Content-Location'), mocker.call('Content-Location')] def mock_get_sideeffect(name): if name == 'Snapshot-Content-Location': return 5 return None # pragma: no cover mock_get = mocker.Mock(side_effect=mock_get_sideeffect) rh.get = mock_get assert rh.location == 5 def mock_get_sideeffect2(name): if name == 'Content-Location': return 6 return None mock_get = mocker.Mock(side_effect=mock_get_sideeffect2) rh.get = mock_get assert rh.location == 6
def test_MHTMLArchive_insert_resource_reslist_empty(mocker): # noqa: N802 bndry = '---boundary---' bndry_part = bytes('--' + bndry + '\r\n', 'ascii') header = b'H: V\r\n\r\n\r\n' content1 = b'H1: V2\r\n\r\ncontent\r\n' content2_header = b'H2: V33\r\n\r\n' content2_content = b'123\r\n' content2 = content2_header + content2_content content = header \ + bndry_part \ + content1 \ + bytes('--' + bndry + '--\r\n', 'ascii') mhtarc = mhtml.MHTMLArchive(content, mhtml.ResourceHeader(), len(header), bndry) # existing resource in archive mock_resource = mocker.Mock(spec=mhtml.Resource) mock_resource.get_resource_range.return_value = (len(header), len(header) + len(bndry_part) + len(content1)) mock_resource._offset_start = len(header) + len(bndry_part) mock_resource._offset_content = len(header) + len(bndry) + 10 # resource to insert mock_resource2 = mocker.Mock(spec=mhtml.Resource) mock_resource2.headers = mhtml.ResourceHeader({'H2': 'V33'}) mock_resource2.content_with_headers = content2 mock_resource2._offset_start = 0 mock_resource2._offset_content = len(content2_header) mhtarc._set_resources([mock_resource]) # insert when empty content = header \ + bytes('--' + bndry + '--\r\n', 'ascii') mhtarc._content = bytearray(content) mhtarc._set_resources([]) assert mhtarc.insert_resource(9001, mock_resource2) is True assert mhtarc.content == header \ + bndry_part \ + content2 \ + bytes('--' + bndry + '--\r\n', 'ascii') assert len(mhtarc.resources) == 1 assert mhtarc.resources[0]._offset_start == \ len(header) + len(bndry_part) assert mhtarc.resources[0]._offset_content == \ len(header) + len(bndry_part) + len(content2_header) assert mhtarc.resources[0]._offset_end == \ len(header) + len(bndry_part) + len(content2) assert mhtarc.resources[0].headers == mock_resource2.headers content = header \ + bytes('--' + bndry + '--\r\n', 'ascii') mhtarc._content = bytearray(content) mhtarc._set_resources([]) assert mhtarc.insert_resource(0, mock_resource2) is True assert mhtarc.content == header \ + bndry_part \ + content2 \ + bytes('--' + bndry + '--\r\n', 'ascii') assert len(mhtarc.resources) == 1 assert mhtarc.resources[0]._offset_start == \ len(header) + len(bndry_part) assert mhtarc.resources[0]._offset_content == \ len(header) + len(bndry_part) + len(content2_header) assert mhtarc.resources[0]._offset_end == \ len(header) + len(bndry_part) + len(content2) # check that not called (not neccessary) mock_method = mocker.Mock() mhtarc._content = bytearray(content) mhtarc._set_resources([]) mhtarc._update_offsets = mock_method assert mhtarc.insert_resource(0, mock_resource2) is True mock_method.assert_not_called()
def test_MHTMLArchive_insert_resource_update_calls(mocker): # noqa: N802 bndry = '---boundary---' bndry_part = bytes('--' + bndry + '\r\n', 'ascii') header = b'H: V\r\n\r\n\r\n' content1 = b'H1: V2\r\n\r\ncontent\r\n' content2_header = b'H2: V33\r\n\r\n' content2_content = b'123\r\n' content2 = content2_header + content2_content content = header \ + bndry_part \ + content1 \ + bytes('--' + bndry + '--\r\n', 'ascii') mhtarc = mhtml.MHTMLArchive(content, mhtml.ResourceHeader(), len(header), bndry) # existing resource in archive mock_resource = mocker.Mock(spec=mhtml.Resource) mock_resource.get_resource_range.return_value = (len(header), len(header) + len(bndry_part) + len(content1)) mock_resource._offset_start = len(header) + len(bndry_part) mock_resource._offset_content = len(header) + len(bndry) + 10 # resource to insert mock_resource2 = mocker.Mock(spec=mhtml.Resource) mock_resource2.headers = mhtml.ResourceHeader({'H2': 'V33'}) mock_resource2.content_with_headers = content2 mock_resource2._offset_start = 0 mock_resource2._offset_content = len(content2_header) mhtarc._set_resources([mock_resource]) # check that not called (not neccessary) mock_method1 = mocker.Mock() content = header \ + bytes('--' + bndry + '--\r\n', 'ascii') mhtarc._content = bytearray(content) mhtarc._set_resources([]) mhtarc._update_offsets = mock_method1 assert mhtarc.insert_resource(0, mock_resource2) is True mock_method1.assert_not_called() # check offset updates mock_method2 = mocker.Mock() content = header \ + bndry_part \ + content1 \ + bytes('--' + bndry + '--\r\n', 'ascii') mhtarc._content = bytearray(content) mhtarc._set_resources([mock_resource]) mhtarc._update_offsets = mock_method2 assert mhtarc.insert_resource(9001, mock_resource2) is True mock_method2.assert_not_called() mock_method3 = mocker.Mock() content = header \ + bndry_part \ + content1 \ + bytes('--' + bndry + '--\r\n', 'ascii') mhtarc._content = bytearray(content) mhtarc._set_resources([mock_resource]) mhtarc._update_offsets = mock_method3 assert mhtarc.insert_resource(0, mock_resource2) is True mock_method3.assert_called_once_with(len(bndry_part) + len(content2), 1) # simply test that the resource parameter is given to the next method mock_method4 = mocker.Mock(return_value=4) mhtarc._set_resources([1, 2, 3]) mhtarc.insert_resource = mock_method4 assert mhtarc.append_resource('abc') == 4 mock_method4.assert_called_once_with(3, 'abc')