1from paste.httpheaders import *
2import time
3
4def _test_generic(collection):
5    assert 'bing' == VIA(collection)
6    REFERER.update(collection,'internal:/some/path')
7    assert 'internal:/some/path' == REFERER(collection)
8    CACHE_CONTROL.update(collection,max_age=1234)
9    CONTENT_DISPOSITION.update(collection,filename="bingles.txt")
10    PRAGMA.update(collection,"test","multi",'valued="items"')
11    assert 'public, max-age=1234' == CACHE_CONTROL(collection)
12    assert 'attachment; filename="bingles.txt"' == \
13            CONTENT_DISPOSITION(collection)
14    assert 'test, multi, valued="items"' == PRAGMA(collection)
15    VIA.delete(collection)
16
17
18def test_environ():
19    collection = {'HTTP_VIA':'bing', 'wsgi.version': '1.0' }
20    _test_generic(collection)
21    assert collection == {'wsgi.version': '1.0',
22      'HTTP_PRAGMA': 'test, multi, valued="items"',
23      'HTTP_REFERER': 'internal:/some/path',
24      'HTTP_CONTENT_DISPOSITION': 'attachment; filename="bingles.txt"',
25      'HTTP_CACHE_CONTROL': 'public, max-age=1234'
26    }
27
28def test_environ_cgi():
29    environ = {'CONTENT_TYPE': 'text/plain', 'wsgi.version': '1.0',
30               'HTTP_CONTENT_TYPE': 'ignored/invalid',
31               'CONTENT_LENGTH': '200'}
32    assert 'text/plain' == CONTENT_TYPE(environ)
33    assert '200' == CONTENT_LENGTH(environ)
34    CONTENT_TYPE.update(environ,'new/type')
35    assert 'new/type' == CONTENT_TYPE(environ)
36    CONTENT_TYPE.delete(environ)
37    assert '' == CONTENT_TYPE(environ)
38    assert 'ignored/invalid' == environ['HTTP_CONTENT_TYPE']
39
40def test_response_headers():
41    collection = [('via', 'bing')]
42    _test_generic(collection)
43    normalize_headers(collection)
44    assert collection == [
45        ('Cache-Control', 'public, max-age=1234'),
46        ('Pragma', 'test, multi, valued="items"'),
47        ('Referer', 'internal:/some/path'),
48        ('Content-Disposition', 'attachment; filename="bingles.txt"')
49    ]
50
51def test_cache_control():
52    assert 'public' == CACHE_CONTROL()
53    assert 'public' == CACHE_CONTROL(public=True)
54    assert 'private' == CACHE_CONTROL(private=True)
55    assert 'no-cache' == CACHE_CONTROL(no_cache=True)
56    assert 'private, no-store' == CACHE_CONTROL(private=True, no_store=True)
57    assert 'public, max-age=60' == CACHE_CONTROL(max_age=60)
58    assert 'public, max-age=86400' == \
59            CACHE_CONTROL(max_age=CACHE_CONTROL.ONE_DAY)
60    CACHE_CONTROL.extensions['community'] = str
61    assert 'public, community="bingles"' == \
62            CACHE_CONTROL(community="bingles")
63    headers = []
64    CACHE_CONTROL.apply(headers,max_age=60)
65    assert 'public, max-age=60' == CACHE_CONTROL(headers)
66    assert EXPIRES.parse(headers) > time.time()
67    assert EXPIRES.parse(headers) < time.time() + 60
68
69def test_content_disposition():
70    assert 'attachment' == CONTENT_DISPOSITION()
71    assert 'attachment' == CONTENT_DISPOSITION(attachment=True)
72    assert 'inline' == CONTENT_DISPOSITION(inline=True)
73    assert 'inline; filename="test.txt"' == \
74            CONTENT_DISPOSITION(inline=True, filename="test.txt")
75    assert 'attachment; filename="test.txt"' == \
76            CONTENT_DISPOSITION(filename="/some/path/test.txt")
77    headers = []
78    CONTENT_DISPOSITION.apply(headers,filename="test.txt")
79    assert 'text/plain' == CONTENT_TYPE(headers)
80    CONTENT_DISPOSITION.apply(headers,filename="test")
81    assert 'text/plain' == CONTENT_TYPE(headers)
82    CONTENT_DISPOSITION.apply(headers,filename="test.html")
83    assert 'text/plain' == CONTENT_TYPE(headers)
84    headers = [('Content-Type', 'application/octet-stream')]
85    CONTENT_DISPOSITION.apply(headers,filename="test.txt")
86    assert 'text/plain' == CONTENT_TYPE(headers)
87    assert headers == [
88      ('Content-Type', 'text/plain'),
89      ('Content-Disposition', 'attachment; filename="test.txt"')
90    ]
91
92def test_range():
93    assert ('bytes',[(0,300)]) == RANGE.parse("bytes=0-300")
94    assert ('bytes',[(0,300)]) == RANGE.parse("bytes   =  -300")
95    assert ('bytes',[(0,None)]) == RANGE.parse("bytes=  -")
96    assert ('bytes',[(0,None)]) == RANGE.parse("bytes=0   -   ")
97    assert ('bytes',[(300,None)]) == RANGE.parse("   BYTES=300-")
98    assert ('bytes',[(4,5),(6,7)]) == RANGE.parse(" Bytes = 4 - 5,6 - 07  ")
99    assert ('bytes',[(0,5),(7,None)]) == RANGE.parse(" bytes=-5,7-")
100    assert ('bytes',[(0,5),(7,None)]) == RANGE.parse(" bytes=-5,7-")
101    assert ('bytes',[(0,5),(7,None)]) == RANGE.parse(" bytes=-5,7-")
102    assert None == RANGE.parse("")
103    assert None == RANGE.parse("bytes=0,300")
104    assert None == RANGE.parse("bytes=-7,5-")
105
106def test_copy():
107    environ = {'HTTP_VIA':'bing', 'wsgi.version': '1.0' }
108    response_headers = []
109    VIA.update(response_headers,environ)
110    assert response_headers == [('Via', 'bing')]
111
112def test_sorting():
113    # verify the HTTP_HEADERS are set with their canonical form
114    sample = [WWW_AUTHENTICATE, VIA, ACCEPT, DATE,
115    ACCEPT_CHARSET, AGE, ALLOW, CACHE_CONTROL,
116    CONTENT_ENCODING, ETAG, CONTENT_TYPE, FROM,
117    EXPIRES, RANGE, UPGRADE, VARY, ALLOW]
118    sample.sort()
119    sample = [str(x) for x in sample]
120    assert sample == [
121     # general headers first
122     'Cache-Control', 'Date', 'Upgrade', 'Via',
123     # request headers next
124     'Accept', 'Accept-Charset', 'From', 'Range',
125     # response headers following
126     'Age', 'ETag', 'Vary', 'WWW-Authenticate',
127     # entity headers (/w expected duplicate)
128     'Allow', 'Allow', 'Content-Encoding', 'Content-Type', 'Expires'
129    ]
130
131def test_normalize():
132    response_headers = [
133       ('www-authenticate','Response AuthMessage'),
134       ('unknown-header','Unknown Sorted Last'),
135       ('Via','General Bingles'),
136       ('aLLoW','Entity Allow Something'),
137       ('ETAG','Response 34234'),
138       ('expires','Entity An-Expiration-Date'),
139       ('date','General A-Date')]
140    normalize_headers(response_headers, strict=False)
141    assert response_headers == [
142     ('Date', 'General A-Date'),
143     ('Via', 'General Bingles'),
144     ('ETag', 'Response 34234'),
145     ('WWW-Authenticate', 'Response AuthMessage'),
146     ('Allow', 'Entity Allow Something'),
147     ('Expires', 'Entity An-Expiration-Date'),
148     ('Unknown-Header', 'Unknown Sorted Last')]
149
150def test_if_modified_since():
151    from paste.httpexceptions import HTTPBadRequest
152    date = 'Thu, 34 Jul 3119 29:34:18 GMT'
153    try:
154        x = IF_MODIFIED_SINCE.parse({'HTTP_IF_MODIFIED_SINCE': date,
155                                     'wsgi.version': (1, 0)})
156    except HTTPBadRequest:
157        pass
158    else:
159        assert 0
160