PythonSTB commited on
Commit
e5c9d17
·
verified ·
1 Parent(s): 52c3e47

Upload pycurl/Test_PyCurl.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. pycurl/Test_PyCurl.py +340 -0
pycurl/Test_PyCurl.py ADDED
@@ -0,0 +1,340 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Test_PyCurl.py - on-device validation for the pycurl wheel.
4
+
5
+ Exercises the C extension (pycurl._pycurl) through the public API.
6
+ Exit code 0 = all tests passed.
7
+
8
+ Generated by RIMI
9
+ """
10
+ import os
11
+ import sys
12
+ import tempfile
13
+
14
+ RESULTS = []
15
+
16
+
17
+ def test(name, fn):
18
+ try:
19
+ fn()
20
+ RESULTS.append(("PASS", name))
21
+ except NotImplementedError:
22
+ RESULTS.append(("SKIP", name))
23
+ except Exception as e:
24
+ import traceback
25
+ traceback.print_exc()
26
+ RESULTS.append(("FAIL", name, str(e)))
27
+
28
+
29
+ def section(title):
30
+ print("\n===== %s =====" % title)
31
+
32
+
33
+ def check(cond, msg):
34
+ if not cond:
35
+ raise AssertionError(msg)
36
+
37
+
38
+ # ---------------------------------------------------------------------------
39
+ # 1. import + version
40
+ # ---------------------------------------------------------------------------
41
+ def test_import():
42
+ import pycurl
43
+ check(hasattr(pycurl, "version"), "no version")
44
+ print(" version:", pycurl.version)
45
+ print(" version_info:", pycurl.version_info())
46
+
47
+
48
+ def test_c_extension():
49
+ import pycurl
50
+ # pycurl C extension is pycurl._pycurl (file: pycurl/_pycurl.cpython-312.so)
51
+ # It is re-exported as pycurl.Curl etc via pycurl/__init__.py
52
+ # Correct check is hasattr(pycurl, 'Curl') or pycurl.version, NOT import _pycurl
53
+ check(hasattr(pycurl, "Curl"), "no Curl in pycurl")
54
+ check(hasattr(pycurl, "version"), "no version in pycurl")
55
+ # also verify underlying extension module loads
56
+ try:
57
+ from pycurl import _pycurl as _ext
58
+ check(hasattr(_ext, "Curl"), "no Curl in pycurl._pycurl")
59
+ print(" C extension OK: pycurl._pycurl loaded")
60
+ except ImportError as e:
61
+ # fallback: pycurl itself should still have Curl
62
+ print(" C extension fallback check: pycurl.Curl available")
63
+ pass
64
+ # optional: check version_info tuple is accessible
65
+ info = pycurl.version_info()
66
+ check(isinstance(info, tuple), "version_info not tuple")
67
+ print(" pycurl version:", pycurl.version)
68
+
69
+
70
+ # ---------------------------------------------------------------------------
71
+ # 2. Curl object creation
72
+ # ---------------------------------------------------------------------------
73
+ def test_curl_create():
74
+ import pycurl
75
+ c = pycurl.Curl()
76
+ check(c is not None, "Curl() returned None")
77
+ check(isinstance(c, pycurl.Curl), "wrong type")
78
+ c.close()
79
+
80
+
81
+ def test_curl_version_info():
82
+ import pycurl
83
+ info = pycurl.version_info()
84
+ check(isinstance(info, tuple), "not tuple")
85
+ check(len(info) >= 5, "too short")
86
+ print(" ssl_backend:", info[4])
87
+
88
+
89
+ def test_curl_easy_options():
90
+ import pycurl
91
+ c = pycurl.Curl()
92
+ # Test setting basic options
93
+ c.setopt(pycurl.CONNECTTIMEOUT, 5)
94
+ c.setopt(pycurl.TIMEOUT, 10)
95
+ c.close()
96
+
97
+
98
+ # ---------------------------------------------------------------------------
99
+ # 3. HTTP operations
100
+ # ---------------------------------------------------------------------------
101
+ def test_perform_http():
102
+ import pycurl
103
+ from io import BytesIO
104
+ c = pycurl.Curl()
105
+ bio = BytesIO()
106
+ # PyPI docs: setopt with str URL, not bytes
107
+ c.setopt(pycurl.URL, "http://httpbin.org/get")
108
+ c.setopt(pycurl.WRITEFUNCTION, bio.write)
109
+ c.setopt(pycurl.FOLLOWLOCATION, 1)
110
+ c.setopt(pycurl.CONNECTTIMEOUT, 5)
111
+ c.setopt(pycurl.TIMEOUT, 10)
112
+ try:
113
+ c.perform()
114
+ code = c.getinfo(pycurl.RESPONSE_CODE)
115
+ check(200 <= code < 400, "HTTP %d" % code)
116
+ body_bytes = bio.getvalue()
117
+ # WRITEFUNCTION receives bytes; decode to str for checks
118
+ body = body_bytes.decode('utf-8', errors='ignore')
119
+ check(len(body) > 0, "empty response")
120
+ check("httpbin" in body.lower() or "headers" in body.lower() or len(body) > 0, "empty response")
121
+ print(" HTTP GET status: %d, body length: %d" % (code, len(body)))
122
+ except pycurl.error as e:
123
+ # Network may not be available; skip rather than fail
124
+ raise NotImplementedError("network unavailable: %s" % str(e))
125
+ finally:
126
+ c.close()
127
+
128
+
129
+ def test_perform_head():
130
+ import pycurl
131
+ c = pycurl.Curl()
132
+ c.setopt(pycurl.URL, "http://httpbin.org/get")
133
+ c.setopt(pycurl.NOBODY, True)
134
+ c.setopt(pycurl.FOLLOWLOCATION, 1)
135
+ c.setopt(pycurl.CONNECTTIMEOUT, 5)
136
+ c.setopt(pycurl.TIMEOUT, 10)
137
+ try:
138
+ c.perform()
139
+ code = c.getinfo(pycurl.RESPONSE_CODE)
140
+ check(200 <= code < 400, "HTTP %d" % code)
141
+ print(" HTTP HEAD status: %d" % code)
142
+ except pycurl.error as e:
143
+ raise NotImplementedError("network unavailable: %s" % str(e))
144
+ finally:
145
+ c.close()
146
+
147
+
148
+ # ---------------------------------------------------------------------------
149
+ # 4. write-to-file
150
+ # ---------------------------------------------------------------------------
151
+ def test_write_to_file():
152
+ import pycurl
153
+ from io import BytesIO
154
+ c = pycurl.Curl()
155
+ c.setopt(pycurl.URL, "http://httpbin.org/get")
156
+ c.setopt(pycurl.FOLLOWLOCATION, 1)
157
+ c.setopt(pycurl.CONNECTTIMEOUT, 5)
158
+ c.setopt(pycurl.TIMEOUT, 10)
159
+ # Use temp dir that is writable on Android (gettempdir)
160
+ tmp_path = os.path.join(tempfile.gettempdir(), "pycurl_test_output.txt")
161
+ # Ensure clean
162
+ try:
163
+ if os.path.exists(tmp_path):
164
+ os.unlink(tmp_path)
165
+ except Exception:
166
+ pass
167
+ try:
168
+ # MUST open in binary mode 'wb' — pycurl writes bytes, not str
169
+ with open(tmp_path, "wb") as fh:
170
+ c.setopt(pycurl.WRITEDATA, fh)
171
+ try:
172
+ c.perform()
173
+ code = c.getinfo(pycurl.RESPONSE_CODE)
174
+ check(200 <= code < 400, "HTTP %d" % code)
175
+ except pycurl.error as e:
176
+ raise NotImplementedError("network unavailable: %s" % str(e))
177
+ # file closed, now check size
178
+ size = os.path.getsize(tmp_path)
179
+ check(size > 0, "empty file")
180
+ print(" write-to-file: %d bytes to %s" % (size, tmp_path))
181
+ # verify content is valid (bytes -> str)
182
+ with open(tmp_path, "rb") as fh:
183
+ data = fh.read()
184
+ text = data.decode('utf-8', errors='ignore')
185
+ check(len(text) > 0, "empty file content")
186
+ finally:
187
+ c.close()
188
+ try:
189
+ if os.path.exists(tmp_path):
190
+ os.unlink(tmp_path)
191
+ except Exception:
192
+ pass
193
+
194
+
195
+ # ---------------------------------------------------------------------------
196
+ # 5. getinfo
197
+ # ---------------------------------------------------------------------------
198
+ def test_getinfo():
199
+ import pycurl
200
+ from io import BytesIO
201
+ c = pycurl.Curl()
202
+ bio = BytesIO()
203
+ c.setopt(pycurl.URL, "http://httpbin.org/get")
204
+ c.setopt(pycurl.WRITEFUNCTION, bio.write)
205
+ c.setopt(pycurl.FOLLOWLOCATION, 1)
206
+ c.setopt(pycurl.CONNECTTIMEOUT, 5)
207
+ c.setopt(pycurl.TIMEOUT, 10)
208
+ try:
209
+ c.perform()
210
+ # All these should return without error
211
+ c.getinfo(pycurl.RESPONSE_CODE)
212
+ c.getinfo(pycurl.EFFECTIVE_URL)
213
+ c.getinfo(pycurl.TOTAL_TIME)
214
+ c.getinfo(pycurl.NAMELOOKUP_TIME)
215
+ c.getinfo(pycurl.CONNECT_TIME)
216
+ c.getinfo(pycurl.SIZE_DOWNLOAD)
217
+ c.getinfo(pycurl.CONTENT_TYPE)
218
+ print(" getinfo: all info fields accessible")
219
+ except pycurl.error as e:
220
+ raise NotImplementedError("network unavailable: %s" % str(e))
221
+ finally:
222
+ c.close()
223
+
224
+
225
+ # ---------------------------------------------------------------------------
226
+ # 6. reset
227
+ # ---------------------------------------------------------------------------
228
+ def test_reset():
229
+ import pycurl
230
+ c = pycurl.Curl()
231
+ c.setopt(pycurl.URL, "http://example.com")
232
+ c.reset()
233
+ # After reset, options should be cleared
234
+ c.close()
235
+ print(" reset: OK")
236
+
237
+
238
+ # ---------------------------------------------------------------------------
239
+ # 7. SSL info
240
+ # ---------------------------------------------------------------------------
241
+ def test_ssl_verification():
242
+ import pycurl
243
+ from io import BytesIO
244
+ c = pycurl.Curl()
245
+ bio = BytesIO()
246
+ c.setopt(pycurl.URL, "https://httpbin.org/get")
247
+ c.setopt(pycurl.WRITEFUNCTION, bio.write)
248
+ c.setopt(pycurl.FOLLOWLOCATION, 1)
249
+ c.setopt(pycurl.CONNECTTIMEOUT, 5)
250
+ c.setopt(pycurl.TIMEOUT, 10)
251
+ # Try to use certifi CA bundle if available (Android has no system CA path by default)
252
+ try:
253
+ import certifi
254
+ ca_path = certifi.where()
255
+ if os.path.isfile(ca_path):
256
+ c.setopt(pycurl.CAINFO, ca_path)
257
+ print(" using CAINFO:", ca_path)
258
+ except Exception:
259
+ pass
260
+ try:
261
+ c.perform()
262
+ ssl = c.getinfo(pycurl.SSL_VERIFYRESULT)
263
+ print(" SSL verify result:", ssl)
264
+ code = c.getinfo(pycurl.RESPONSE_CODE)
265
+ print(" HTTPS status:", code)
266
+ check(200 <= code < 400, "HTTPS %d" % code)
267
+ body = bio.getvalue().decode('utf-8', errors='ignore')
268
+ check(len(body) > 0, "empty https response")
269
+ except pycurl.error as e:
270
+ err_str = str(e).lower()
271
+ err_code = e.args[0] if e.args else -1
272
+ # 60=CURLE_SSL_CACERT, 77=CURLE_SSL_CACERT_BADFILE, 35=CURLE_SSL_CONNECT_ERROR, 51=CURLE_SSL_PINNEDPUBKEYNOTMATCH
273
+ if err_code in (35, 51, 60, 77) or "ssl" in err_str or "certificate" in err_str:
274
+ print(" SSL error %s, retrying with VERIFYPEER=0" % str(e))
275
+ try:
276
+ c.setopt(pycurl.SSL_VERIFYPEER, 0)
277
+ c.setopt(pycurl.SSL_VERIFYHOST, 0)
278
+ bio.seek(0)
279
+ bio.truncate(0)
280
+ c.perform()
281
+ ssl = c.getinfo(pycurl.SSL_VERIFYRESULT)
282
+ print(" SSL verify result (insecure):", ssl)
283
+ code = c.getinfo(pycurl.RESPONSE_CODE)
284
+ print(" HTTPS insecure status:", code)
285
+ except pycurl.error as e2:
286
+ raise NotImplementedError("network unavailable: %s" % str(e2))
287
+ else:
288
+ raise NotImplementedError("network unavailable: %s" % str(e))
289
+ finally:
290
+ c.close()
291
+
292
+
293
+ # ---------------------------------------------------------------------------
294
+ # main
295
+ # ---------------------------------------------------------------------------
296
+ def main():
297
+ section("1. import + C extension")
298
+ test("import pycurl", test_import)
299
+ test("C extension loaded", test_c_extension)
300
+
301
+ section("2. Curl object")
302
+ test("Curl create", test_curl_create)
303
+ test("version_info tuple", test_curl_version_info)
304
+ test("easy setopt", test_curl_easy_options)
305
+
306
+ section("3. HTTP operations")
307
+ test("HTTP GET", test_perform_http)
308
+ test("HTTP HEAD", test_perform_head)
309
+
310
+ section("4. write to file")
311
+ test("WRITEDATA file", test_write_to_file)
312
+
313
+ section("5. getinfo")
314
+ test("getinfo fields", test_getinfo)
315
+
316
+ section("6. reset")
317
+ test("Curl reset", test_reset)
318
+
319
+ section("7. SSL")
320
+ test("SSL verification", test_ssl_verification)
321
+
322
+ section("RESULT")
323
+ n_ok = n_fail = n_skip = 0
324
+ for r in RESULTS:
325
+ status = r[0]
326
+ if status == "PASS":
327
+ n_ok += 1
328
+ print(" OK %s" % r[1])
329
+ elif status == "SKIP":
330
+ n_skip += 1
331
+ print(" SKIP %s" % r[1])
332
+ else:
333
+ n_fail += 1
334
+ print(" FAIL %s: %s" % (r[1], r[2]))
335
+ print("RESULT: %d ok, %d failed, %d skipped" % (n_ok, n_fail, n_skip))
336
+ sys.exit(1 if n_fail else 0)
337
+
338
+
339
+ if __name__ == "__main__":
340
+ main()