test_cgi.py revision d2717217ae7403dc1cc51aea1fe8a7736612392a
1from test.test_support import verify, verbose 2import cgi 3import os 4import sys 5 6class HackedSysModule: 7 # The regression test will have real values in sys.argv, which 8 # will completely confuse the test of the cgi module 9 argv = [] 10 stdin = sys.stdin 11 12cgi.sys = HackedSysModule() 13 14try: 15 from cStringIO import StringIO 16except ImportError: 17 from StringIO import StringIO 18 19class ComparableException: 20 def __init__(self, err): 21 self.err = err 22 23 def __str__(self): 24 return str(self.err) 25 26 def __cmp__(self, anExc): 27 if not isinstance(anExc, Exception): 28 return -1 29 x = cmp(self.err.__class__, anExc.__class__) 30 if x != 0: 31 return x 32 return cmp(self.err.args, anExc.args) 33 34 def __getattr__(self, attr): 35 return getattr(self.err, attr) 36 37def do_test(buf, method): 38 env = {} 39 if method == "GET": 40 fp = None 41 env['REQUEST_METHOD'] = 'GET' 42 env['QUERY_STRING'] = buf 43 elif method == "POST": 44 fp = StringIO(buf) 45 env['REQUEST_METHOD'] = 'POST' 46 env['CONTENT_TYPE'] = 'application/x-www-form-urlencoded' 47 env['CONTENT_LENGTH'] = str(len(buf)) 48 else: 49 raise ValueError, "unknown method: %s" % method 50 try: 51 return cgi.parse(fp, env, strict_parsing=1) 52 except StandardError, err: 53 return ComparableException(err) 54 55# A list of test cases. Each test case is a a two-tuple that contains 56# a string with the query and a dictionary with the expected result. 57 58parse_qsl_test_cases = [ 59 ("", []), 60 ("&", []), 61 ("&&", []), 62 ("=", [('', '')]), 63 ("=a", [('', 'a')]), 64 ("a", [('a', '')]), 65 ("a=", [('a', '')]), 66 ("a=", [('a', '')]), 67 ("&a=b", [('a', 'b')]), 68 ("a=a+b&b=b+c", [('a', 'a b'), ('b', 'b c')]), 69 ("a=1&a=2", [('a', '1'), ('a', '2')]), 70] 71 72parse_strict_test_cases = [ 73 ("", ValueError("bad query field: ''")), 74 ("&", ValueError("bad query field: ''")), 75 ("&&", ValueError("bad query field: ''")), 76 (";", ValueError("bad query field: ''")), 77 (";&;", ValueError("bad query field: ''")), 78 # Should the next few really be valid? 79 ("=", {}), 80 ("=&=", {}), 81 ("=;=", {}), 82 # This rest seem to make sense 83 ("=a", {'': ['a']}), 84 ("&=a", ValueError("bad query field: ''")), 85 ("=a&", ValueError("bad query field: ''")), 86 ("=&a", ValueError("bad query field: 'a'")), 87 ("b=a", {'b': ['a']}), 88 ("b+=a", {'b ': ['a']}), 89 ("a=b=a", {'a': ['b=a']}), 90 ("a=+b=a", {'a': [' b=a']}), 91 ("&b=a", ValueError("bad query field: ''")), 92 ("b&=a", ValueError("bad query field: 'b'")), 93 ("a=a+b&b=b+c", {'a': ['a b'], 'b': ['b c']}), 94 ("a=a+b&a=b+a", {'a': ['a b', 'b a']}), 95 ("x=1&y=2.0&z=2-3.%2b0", {'x': ['1'], 'y': ['2.0'], 'z': ['2-3.+0']}), 96 ("x=1;y=2.0&z=2-3.%2b0", {'x': ['1'], 'y': ['2.0'], 'z': ['2-3.+0']}), 97 ("x=1;y=2.0;z=2-3.%2b0", {'x': ['1'], 'y': ['2.0'], 'z': ['2-3.+0']}), 98 ("Hbc5161168c542333633315dee1182227:key_store_seqid=400006&cuyer=r&view=bustomer&order_id=0bb2e248638833d48cb7fed300000f1b&expire=964546263&lobale=en-US&kid=130003.300038&ss=env", 99 {'Hbc5161168c542333633315dee1182227:key_store_seqid': ['400006'], 100 'cuyer': ['r'], 101 'expire': ['964546263'], 102 'kid': ['130003.300038'], 103 'lobale': ['en-US'], 104 'order_id': ['0bb2e248638833d48cb7fed300000f1b'], 105 'ss': ['env'], 106 'view': ['bustomer'], 107 }), 108 109 ("group_id=5470&set=custom&_assigned_to=31392&_status=1&_category=100&SUBMIT=Browse", 110 {'SUBMIT': ['Browse'], 111 '_assigned_to': ['31392'], 112 '_category': ['100'], 113 '_status': ['1'], 114 'group_id': ['5470'], 115 'set': ['custom'], 116 }) 117 ] 118 119def norm(list): 120 if type(list) == type([]): 121 list.sort() 122 return list 123 124def first_elts(list): 125 return map(lambda x:x[0], list) 126 127def first_second_elts(list): 128 return map(lambda p:(p[0], p[1][0]), list) 129 130def main(): 131 for orig, expect in parse_qsl_test_cases: 132 result = cgi.parse_qsl(orig, keep_blank_values=True) 133 print repr(orig), '=>', result 134 verify(result == expect, "Error parsing %s" % repr(orig)) 135 136 for orig, expect in parse_strict_test_cases: 137 # Test basic parsing 138 print repr(orig) 139 d = do_test(orig, "GET") 140 verify(d == expect, "Error parsing %s" % repr(orig)) 141 d = do_test(orig, "POST") 142 verify(d == expect, "Error parsing %s" % repr(orig)) 143 144 env = {'QUERY_STRING': orig} 145 fcd = cgi.FormContentDict(env) 146 sd = cgi.SvFormContentDict(env) 147 fs = cgi.FieldStorage(environ=env) 148 if type(expect) == type({}): 149 # test dict interface 150 verify(len(expect) == len(fcd)) 151 verify(norm(expect.keys()) == norm(fcd.keys())) 152 verify(norm(expect.values()) == norm(fcd.values())) 153 verify(norm(expect.items()) == norm(fcd.items())) 154 verify(fcd.get("nonexistent field", "default") == "default") 155 verify(len(sd) == len(fs)) 156 verify(norm(sd.keys()) == norm(fs.keys())) 157 verify(fs.getvalue("nonexistent field", "default") == "default") 158 # test individual fields 159 for key in expect.keys(): 160 expect_val = expect[key] 161 verify(fcd.has_key(key)) 162 verify(norm(fcd[key]) == norm(expect[key])) 163 verify(fcd.get(key, "default") == fcd[key]) 164 verify(fs.has_key(key)) 165 if len(expect_val) > 1: 166 single_value = 0 167 else: 168 single_value = 1 169 try: 170 val = sd[key] 171 except IndexError: 172 verify(not single_value) 173 verify(fs.getvalue(key) == expect_val) 174 else: 175 verify(single_value) 176 verify(val == expect_val[0]) 177 verify(fs.getvalue(key) == expect_val[0]) 178 verify(norm(sd.getlist(key)) == norm(expect_val)) 179 if single_value: 180 verify(norm(sd.values()) == \ 181 first_elts(norm(expect.values()))) 182 verify(norm(sd.items()) == \ 183 first_second_elts(norm(expect.items()))) 184 185 # Test the weird FormContentDict classes 186 env = {'QUERY_STRING': "x=1&y=2.0&z=2-3.%2b0&1=1abc"} 187 expect = {'x': 1, 'y': 2.0, 'z': '2-3.+0', '1': '1abc'} 188 d = cgi.InterpFormContentDict(env) 189 for k, v in expect.items(): 190 verify(d[k] == v) 191 for k, v in d.items(): 192 verify(expect[k] == v) 193 verify(norm(expect.values()) == norm(d.values())) 194 195 print "Testing log" 196 cgi.log("Testing") 197 cgi.logfp = sys.stdout 198 cgi.initlog("%s", "Testing initlog 1") 199 cgi.log("%s", "Testing log 2") 200 if os.path.exists("/dev/null"): 201 cgi.logfp = None 202 cgi.logfile = "/dev/null" 203 cgi.initlog("%s", "Testing log 3") 204 cgi.log("Testing log 4") 205 206main() 207