ansible/test/units/module_utils/urls/test_prepare_multipart.py
Matt Martz b748edea45
Add multipart/form-data functionality (#69376)
* Add multipart/form-data functionality

* Fix some linting issues

* Fix error message

* Allow filename to be provided with content

* Add integration test

* Update examples

* General improvements to multipart handling

* Use prepare_multipart for galaxy collection publish

* Properly account for py2 vs py3, ensuring no max header length

* Address test assumptions

* Add unit tests

* Add changelog

* Ensure to use CRLF instead of NL

* Ignore line-endings in fixture

* Consolidate code, add comment

* Bump fallaxy container version

* ci_complete
2020-05-20 15:44:01 -05:00

102 lines
3 KiB
Python

# -*- coding: utf-8 -*-
# (c) 2020 Matt Martz <matt@sivel.net>
# 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
import os
from io import StringIO
from email.message import Message
import pytest
from ansible.module_utils.urls import prepare_multipart
def test_prepare_multipart():
fixture_boundary = b'===============3996062709511591449=='
here = os.path.dirname(__file__)
multipart = os.path.join(here, 'fixtures/multipart.txt')
client_cert = os.path.join(here, 'fixtures/client.pem')
client_key = os.path.join(here, 'fixtures/client.key')
client_txt = os.path.join(here, 'fixtures/client.txt')
fields = {
'form_field_1': 'form_value_1',
'form_field_2': {
'content': 'form_value_2',
},
'form_field_3': {
'content': '<html></html>',
'mime_type': 'text/html',
},
'form_field_4': {
'content': '{"foo": "bar"}',
'mime_type': 'application/json',
},
'file1': {
'content': 'file_content_1',
'filename': 'fake_file1.txt',
},
'file2': {
'content': '<html></html>',
'mime_type': 'text/html',
'filename': 'fake_file2.html',
},
'file3': {
'content': '{"foo": "bar"}',
'mime_type': 'application/json',
'filename': 'fake_file3.json',
},
'file4': {
'filename': client_cert,
'mime_type': 'text/plain',
},
'file5': {
'filename': client_key,
},
'file6': {
'filename': client_txt,
},
}
content_type, b_data = prepare_multipart(fields)
headers = Message()
headers['Content-Type'] = content_type
assert headers.get_content_type() == 'multipart/form-data'
boundary = headers.get_boundary()
assert boundary is not None
with open(multipart, 'rb') as f:
b_expected = f.read().replace(fixture_boundary, boundary.encode())
# Depending on Python version, there may or may not be a trailing newline
assert b_data.rstrip(b'\r\n') == b_expected.rstrip(b'\r\n')
def test_wrong_type():
pytest.raises(TypeError, prepare_multipart, 'foo')
pytest.raises(TypeError, prepare_multipart, {'foo': None})
def test_empty():
pytest.raises(ValueError, prepare_multipart, {'foo': {}})
def test_unknown_mime(mocker):
fields = {'foo': {'filename': 'foo.boom', 'content': 'foo'}}
mocker.patch('mimetypes.guess_type', return_value=(None, None))
content_type, b_data = prepare_multipart(fields)
assert b'Content-Type: application/octet-stream' in b_data
def test_bad_mime(mocker):
fields = {'foo': {'filename': 'foo.boom', 'content': 'foo'}}
mocker.patch('mimetypes.guess_type', side_effect=TypeError)
content_type, b_data = prepare_multipart(fields)
assert b'Content-Type: application/octet-stream' in b_data