#!/usr/bin/env python """ This suite is going to realize three tests, simulating three different HTML form to the cgi module. 1st Form:
As the original cgi module cannot handle QUERY_STRING on POST, key1 will never be present on the result of cgi.FieldStorage(). Also, key2 is present in QUERY_STRING and on POST data, so, it should generate a list accessed by form.getlist('key2'). In this case, cgi.FieldStorage() is going to return a list of MiniFieldStorage objects. 2nd Form:
When the form is encoded, cgi.FieldStorage() return a list of FieldStorage objects instead of MiniFieldStorage. The original cgi module completely ignores QUERY_STRING and key1 will never be present, and, again, key2 won't be a list, but a FieldStorage object. With the patch, that result will be a mix of FieldStorage for values on the form and MiniFieldStorage for values on QUERY_STRING, like this: original cgi module produces: FieldStorage(None, None, [ FieldStorage('key2', None, 'value2y'), FieldStorage('key3', None, 'value3'), FieldStorage('key4', None, 'value4') ]) patched cgi module produces: FieldStorage(None, None, [ MiniFieldStorage('key1', 'value1'), MiniFieldStorage('key2', 'value2x'), FieldStorage('key2', None, 'value2y'), FieldStorage('key3', None, 'value3'), FieldStorage('key4', None, 'value4') ]) 3rd Form: This is exactly like the 2nd one, except that it adds a field of type "file", for file upload. original cgi module produces: FieldStorage(None, None, [ FieldStorage('key2', None, 'value2y'), FieldStorage('key3', None, 'value3'), FieldStorage('key4', None, 'value4') FieldStorage('upload', 'fake.txt', 'this is the content of the fake file\n') ]) patched cgi module produces: FieldStorage(None, None, [ MiniFieldStorage('key1', 'value1'), MiniFieldStorage('key2', 'value2x'), FieldStorage('key2', None, 'value2y'), FieldStorage('key3', None, 'value3'), FieldStorage('key4', None, 'value4'), FieldStorage('upload', 'fake.txt', 'this is the content of the fake file\n') ]) """ from StringIO import StringIO import cgi, unittest # test1: regular POST with QS urlencode_data = "key2=value2x&key3=value3&key4=value4" urlencode_environ = { 'CONTENT_LENGTH': str(len(urlencode_data)), 'CONTENT_TYPE': 'application/x-www-form-urlencoded', 'QUERY_STRING': 'key1=value1&key2=value2y', 'REQUEST_METHOD': 'POST', } # test2: encoded POST with QS formdata_data = """ ---123 Content-Disposition: form-data; name="key2" value2y ---123 Content-Disposition: form-data; name="key3" value3 ---123 Content-Disposition: form-data; name="key4" value4 ---123-- """ formdata_environ = { 'CONTENT_LENGTH': str(len(formdata_data)), 'CONTENT_TYPE': 'multipart/form-data; boundary=-123', 'QUERY_STRING': 'key1=value1&key2=value2x', 'REQUEST_METHOD': 'POST', } # test3: encoded POST with file upload and QS formdata_file_data = """ ---123 Content-Disposition: form-data; name="key2" value2y ---123 Content-Disposition: form-data; name="key3" value3 ---123 Content-Disposition: form-data; name="key4" value4 ---123 Content-Disposition: form-data; name="upload"; filename="fake.txt" Content-Type: text/plain this is the content of the fake file ---123-- """ formdata_file_environ = { 'CONTENT_LENGTH': str(len(formdata_file_data)), 'CONTENT_TYPE': 'multipart/form-data; boundary=-123', 'QUERY_STRING': 'key1=value1&key2=value2x', 'REQUEST_METHOD': 'POST', } def gen_result(data, environ): fake_stdin = StringIO(data) fake_stdin.seek(0) form = cgi.FieldStorage(fp=fake_stdin, environ=environ) result = {} for k, v in dict(form).items(): result[k] = type(v) is list and form.getlist(k) or v.value return result class TestCGI(unittest.TestCase): result = { 'key1': 'value1', 'key2': ['value2x', 'value2y'], 'key3': 'value3', 'key4': 'value4' } def testUrlEncode(self): v = gen_result(urlencode_data, urlencode_environ) self.assertEqual(self.result, v) def testFormData(self): v = gen_result(formdata_data, formdata_environ) self.assertEqual(self.result, v) def testFormDataFile(self): result = self.result.copy() result.update({ 'upload': 'this is the content of the fake file\n' }) v = gen_result(formdata_file_data, formdata_file_environ) self.assertEqual(result, v) if __name__ == '__main__': unittest.main()