summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorTiago Natel de Moura <t.nateldemoura@f5.com>2020-02-05 13:13:04 +0000
committerTiago Natel de Moura <t.nateldemoura@f5.com>2020-02-05 13:13:04 +0000
commitd3e218a8c379baf1af4759097d3c9c2fedb01432 (patch)
tree27c5b2c227535b7ff21ef41a16db3cb76f3f6033
parent29d8b34244e24095f23f5e483f8452035fbb77aa (diff)
downloadunit-d3e218a8c379baf1af4759097d3c9c2fedb01432.tar.gz
unit-d3e218a8c379baf1af4759097d3c9c2fedb01432.tar.bz2
Tests: add helper for form-data and multipart.
-rw-r--r--test/test_java_application.py39
-rw-r--r--test/unit/http.py73
2 files changed, 90 insertions, 22 deletions
diff --git a/test/test_java_application.py b/test/test_java_application.py
index d2b97f88..9d873d6b 100644
--- a/test/test_java_application.py
+++ b/test/test_java_application.py
@@ -1,3 +1,4 @@
+import io
import os
import time
import unittest
@@ -1223,31 +1224,25 @@ class TestJavaApplication(TestApplicationJava):
os.mkdir(fulldst)
self.public_dir(fulldst)
- body = (
- """Preamble. Should be ignored.\r
-\r
---12345\r
-Content-Disposition: form-data; name="file"; filename="sample.txt"\r
-Content-Type: text/plain\r
-\r
-Data from sample file\r
---12345\r
-Content-Disposition: form-data; name="destination"\r
-\r
-%s\r
---12345\r
-Content-Disposition: form-data; name="upload"\r
-\r
-Upload\r
---12345--\r
-\r
-Epilogue. Should be ignored."""
- % fulldst
- )
+ fields = {
+ 'file': {
+ 'filename': 'sample.txt',
+ 'type': 'text/plain',
+ 'data': io.StringIO('Data from sample file'),
+ },
+ 'destination': fulldst,
+ 'upload': 'Upload',
+ }
+
+ encoded, content_type = self.multipart_encode(fields)
+
+ preamble = 'Preamble. Should be ignored.'
+ epilogue = 'Epilogue. Should be ignored.'
+ body = "%s\r\n%s\r\n%s" % (preamble, encoded.decode(), epilogue)
resp = self.post(
headers={
- 'Content-Type': 'multipart/form-data; boundary=12345',
+ 'Content-Type': content_type,
'Host': 'localhost',
'Connection': 'close',
},
diff --git a/test/unit/http.py b/test/unit/http.py
index 839e91a2..c71e8f7e 100644
--- a/test/unit/http.py
+++ b/test/unit/http.py
@@ -1,3 +1,6 @@
+import binascii
+import io
+import os
import re
import time
import json
@@ -68,6 +71,10 @@ class TestHTTP(TestUnit):
if body != b'':
if isinstance(body, str):
body = body.encode()
+ elif isinstance(body, dict):
+ body, content_type = self.form_encode(body)
+
+ headers['Content-Type'] = content_type
if 'Content-Length' not in headers:
headers['Content-Length'] = len(body)
@@ -266,3 +273,69 @@ class TestHTTP(TestUnit):
sock.close()
self.assertTrue(ret, 'socket connected')
+
+ def form_encode(self, fields):
+ is_multipart = False
+
+ for _, value in fields.items():
+ if isinstance(value, dict):
+ is_multipart = True
+ break
+
+ if is_multipart:
+ body, content_type = self.multipart_encode(fields)
+
+ else:
+ body, content_type = self.form_url_encode(fields)
+
+ return body, content_type
+
+ def form_url_encode(self, fields):
+ data = "&".join("%s=%s" % (name, value)
+ for name, value in fields.items()).encode()
+ return data, 'application/x-www-form-urlencoded'
+
+ def multipart_encode(self, fields):
+ boundary = binascii.hexlify(os.urandom(16)).decode('ascii')
+
+ body = ''
+
+ for field, value in fields.items():
+ filename = ''
+ datatype = ''
+
+ if isinstance(value, dict):
+ datatype = 'text/plain'
+ filename = value['filename']
+
+ if value.get('type'):
+ datatype = value['type']
+
+ if not isinstance(value['data'], io.IOBase):
+ self.fail('multipart encoding of file requires a stream.')
+
+ data = value['data'].read()
+
+ elif isinstance(value, str):
+ data = value
+
+ else:
+ self.fail('multipart requires a string or stream data')
+
+ body += (
+ "--%s\r\nContent-Disposition: form-data; name=\"%s\""
+ ) % (boundary, field)
+
+ if filename != '':
+ body += "; filename=\"%s\"" % filename
+
+ body += "\r\n"
+
+ if datatype != '':
+ body += "Content-Type: %s\r\n" % datatype
+
+ body += "\r\n%s\r\n" % data
+
+ body += "--%s--\r\n" % boundary
+
+ return body.encode(), "multipart/form-data; boundary=%s" % boundary