test_ProxyRotate.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. # Mocks
  2. from requests.models import Response
  3. import requests
  4. import time
  5. import csv
  6. # Test Env
  7. import pytest
  8. from unittest.mock import patch
  9. # Test functions
  10. from baangt.base.ProxyRotate import ProxyRotate, proxy_data
  11. import baangt.base.GlobalConstants as GC
  12. from dataclasses import dataclass, asdict
  13. from http import HTTPStatus
  14. import copy
  15. MIN_PROXIES_FOR_FIRST_RUN = 3
  16. def create_init_proxy_list(length):
  17. proxyList = []
  18. for index in range(length):
  19. proxy = asdict(proxy_data(ip = (str)(index), port = (str)(0)))
  20. for key in proxy:
  21. proxy[key] = str(proxy[key])
  22. proxyList.append(proxy)
  23. return proxyList
  24. def init_ProxyRotate(mock_csv_DictReader, proxyListLength, firstRun = True):
  25. proxyRotate = ProxyRotate()
  26. proxyRotate.proxy_gather_link = "https://www.sslproxies.org/"
  27. proxyRotate.proxies = {}
  28. proxyRotate.all_proxies = {}
  29. proxyRotate._ProxyRotate__temp_proxies = []
  30. proxyRotate.firstRun = firstRun
  31. proxyRotate.MIN_PROXIES_FOR_FIRST_RUN = MIN_PROXIES_FOR_FIRST_RUN
  32. mock_csv_DictReader.return_value = create_init_proxy_list(proxyListLength)
  33. proxyRotate._ProxyRotate__read_proxies()
  34. return proxyRotate
  35. def create_proxy_verification_response(status_code, length, deleteString=None):
  36. ret = []
  37. for index in range(length):
  38. res_youtube = Response()
  39. res_youtube._content = "<!DOCTYPE html><html><head><meta content='Content' property='og:title'/></head><body></body></html>"
  40. res_youtube.status_code = status_code
  41. res_google = copy.copy(res_youtube)
  42. res_google._content = "<!DOCTYPE html><html></head><body><div class='logo'><img src='/img/favicon.png'></img></div></body></html>"
  43. if deleteString is not None:
  44. res_google._content = res_google._content.replace(deleteString, "")
  45. res_youtube._content = res_youtube._content.replace(deleteString, "")
  46. ret.append(res_youtube)
  47. ret.append(res_google)
  48. return ret
  49. def create_request_proxy_list(status_code, length, deleteString=None):
  50. res_proxy = Response()
  51. res_proxy._content = "<!DOCTYPEhtml><html><head></head><body><tbody>"
  52. for index in range(length):
  53. res_proxy._content += f'<tr><td>{index}.000</td><td>40231</td><td>KE</td></tr>'
  54. res_proxy._content += "</tbody></body></html>"
  55. if deleteString is not None:
  56. res_proxy._content = res_proxy._content.replace(deleteString, "")
  57. res_proxy.status_code = status_code
  58. return res_proxy
  59. @patch("requests.get")
  60. @patch('time.sleep', return_value = None)
  61. @patch("csv.DictReader")
  62. @pytest.mark.parametrize("proxyLength", list(range(0,MIN_PROXIES_FOR_FIRST_RUN)))
  63. @pytest.mark.parametrize("additionalProxyRequestLength", [1])
  64. def test_recheckProxies_init_proxy_with_less_min_proxy(mock_csv_DictReader, mock_time_sleep, mock_get, proxyLength, additionalProxyRequestLength):
  65. """
  66. Initialise a valid proxy list <= MIN_PROXIES_FOR_FIRST_RUN
  67. Test Steps:
  68. - Init a valid proxy list (length 0....MIN_PROXIES_FOR_FIRST_RUN), firstRun = True
  69. - Verificate proxy list successful
  70. - Request for more proxy items is provided
  71. If proxy list size <= MIN_PROXIES_FOR_FIRST_RUN, ProxyRotate will request for more proxy servers
  72. """
  73. # Initialize proxy list
  74. proxyRotate = init_ProxyRotate(mock_csv_DictReader, proxyLength)
  75. # Add valid response for proxy verification
  76. responseList = create_proxy_verification_response(HTTPStatus.OK, proxyLength)
  77. # Create successful requests for proxy list and proxy verification because [proxy list size > MIN_PROXIES_FOR_FIRST_RUN]
  78. responseList.append(create_request_proxy_list(HTTPStatus.OK, additionalProxyRequestLength))
  79. responseList.extend(create_proxy_verification_response(HTTPStatus.OK, additionalProxyRequestLength + proxyLength))
  80. mock_get.side_effect = responseList
  81. proxyRotate.recheckProxies(forever= False)
  82. assert len(responseList) == mock_get.call_count
  83. assert len(proxyRotate.proxies) == (additionalProxyRequestLength + proxyLength)
  84. @patch("requests.get")
  85. @patch("csv.DictReader")
  86. @pytest.mark.parametrize("proxyLength", list(range(MIN_PROXIES_FOR_FIRST_RUN,8)))
  87. def test_recheckProxies_init_proxy_list(mock_csv_DictReader, mock_get, proxyLength):
  88. """
  89. Initialise a valid proxy list greater than MIN_PROXIES_FOR_FIRST_RUN
  90. Test Steps:
  91. - Init a valid proxy list (length MIN_PROXIES_FOR_FIRST_RUN...8), firstRun = True
  92. - Verificate proxy list successful
  93. """
  94. # Initialize proxy list
  95. proxyRotate = init_ProxyRotate(mock_csv_DictReader, proxyLength)
  96. # Add valid response for proxy verification (if firstRun == True only MIN_PROXIES_FOR_FIRST_RUN are validated)
  97. responseList = (create_proxy_verification_response(HTTPStatus.OK, MIN_PROXIES_FOR_FIRST_RUN))
  98. mock_get.side_effect = responseList
  99. proxyRotate.recheckProxies(forever= False)
  100. assert len(responseList) == mock_get.call_count
  101. assert len(proxyRotate.proxies) == proxyRotate.MIN_PROXIES_FOR_FIRST_RUN
  102. assert len(proxyRotate.all_proxies) == proxyLength
  103. @patch("requests.get")
  104. @patch('time.sleep', return_value = None)
  105. @patch("csv.DictReader")
  106. @pytest.mark.parametrize("proxyLengthValid", [10])
  107. @pytest.mark.parametrize("proxyLengthInvalid", [1])
  108. @pytest.mark.parametrize("firstRun", [False])
  109. def test_recheckProxies_proxy_verification_failed_html_status_error(mock_csv_DictReader, mock_time_sleep, mock_get,
  110. proxyLengthValid, proxyLengthInvalid, firstRun):
  111. """
  112. Generate a html status error code in proxy verification
  113. Test Steps:
  114. - Init a valid proxy list, firstRun = False
  115. - One unsuccessful proxy validation response with html response status error is generated
  116. """
  117. # Initialize proxy list
  118. proxyRotate = init_ProxyRotate(mock_csv_DictReader, proxyLengthValid + proxyLengthInvalid, firstRun)
  119. # Add valid response for proxy verification
  120. responseList = create_proxy_verification_response(HTTPStatus.OK, proxyLengthValid)
  121. # Add invalid response for proxy verification
  122. responseList.extend(create_proxy_verification_response(HTTPStatus.BAD_REQUEST, proxyLengthInvalid))
  123. # Create response for requesting more proxies
  124. responseList.append(create_request_proxy_list(HTTPStatus.OK, 0))
  125. # Add valid response for proxy verification - proxies are validated again
  126. responseList.extend(create_proxy_verification_response(HTTPStatus.OK, proxyLengthValid))
  127. mock_get.side_effect = responseList
  128. proxyRotate.recheckProxies(forever= False)
  129. assert len(responseList) == mock_get.call_count
  130. assert len(proxyRotate.proxies) == proxyLengthValid
  131. assert len(proxyRotate.all_proxies) == (proxyLengthValid + proxyLengthInvalid)
  132. @patch("requests.get")
  133. @patch('time.sleep', return_value = None)
  134. @patch("csv.DictReader")
  135. @pytest.mark.parametrize("proxyLengthValid", [10])
  136. @pytest.mark.parametrize("proxyLengthInvalid", [1])
  137. @pytest.mark.parametrize("firstRun", [False])
  138. @pytest.mark.parametrize("htmlBodyErrors", ["property","logo", "meta", "div", "content"])
  139. def test_recheckProxies_proxy_verification_failed_html_body(mock_csv_DictReader, mock_time_sleep, mock_get,
  140. proxyLengthValid, proxyLengthInvalid, firstRun, htmlBodyErrors):
  141. """
  142. Generate a html body error in proxy verification
  143. Test Steps:
  144. - Init a valid proxy list, firstRun = False
  145. - One unsuccessful proxy validation response with html body error is generated
  146. """
  147. # Initialize proxy list
  148. proxyRotate= init_ProxyRotate(mock_csv_DictReader, proxyLengthValid + proxyLengthInvalid, firstRun)
  149. # Add valid response for proxy verification
  150. responseList = create_proxy_verification_response(HTTPStatus.OK, proxyLengthValid)
  151. # Add invalid response for proxy verification
  152. responseList.extend(create_proxy_verification_response(HTTPStatus.OK, proxyLengthInvalid, htmlBodyErrors))
  153. # Create response for requesting more proxies
  154. responseList.append(create_request_proxy_list(HTTPStatus.OK, 0))
  155. # Add valid response for proxy verification - proxies are validated again
  156. responseList.extend(create_proxy_verification_response(HTTPStatus.OK, proxyLengthValid))
  157. mock_get.side_effect = responseList
  158. proxyRotate.recheckProxies(forever= False)
  159. assert len(responseList) == mock_get.call_count
  160. assert len(proxyRotate.proxies) == proxyLengthValid
  161. assert len(proxyRotate.all_proxies) == (proxyLengthValid + proxyLengthInvalid)
  162. @patch("requests.get")
  163. @patch('time.sleep', return_value = None)
  164. @patch("csv.DictReader")
  165. @pytest.mark.parametrize("proxyLengthValid", [10])
  166. @pytest.mark.parametrize("proxyLengthInvalid", [1])
  167. @pytest.mark.parametrize("firstRun", [False])
  168. def test_recheckProxies_proxy_list_failed_html_status_error(mock_csv_DictReader, mock_time_sleep, mock_get,
  169. proxyLengthValid, proxyLengthInvalid, firstRun):
  170. """
  171. Generate a html body error in proxy verification
  172. Test Steps:
  173. - Init a valid proxy list, firstRun = False
  174. - One unsuccessful proxy validation response with html response status error is generated
  175. """
  176. # Initialize proxy list
  177. proxyRotate = init_ProxyRotate(mock_csv_DictReader, proxyLengthValid, firstRun)
  178. # Add valid response for proxy verification
  179. responseList = create_proxy_verification_response(HTTPStatus.OK, proxyLengthValid)
  180. # Create response for requesting more proxies
  181. responseList.append(create_request_proxy_list(HTTPStatus.BAD_REQUEST, proxyLengthInvalid))
  182. # Add valid response for proxy verification - proxies are validated again
  183. responseList.extend(create_proxy_verification_response(HTTPStatus.OK, proxyLengthValid))
  184. mock_get.side_effect = responseList
  185. proxyRotate.recheckProxies(forever= False)
  186. assert len(responseList) == mock_get.call_count
  187. assert len(proxyRotate.proxies) == proxyLengthValid
  188. assert len(proxyRotate.all_proxies) == proxyLengthValid
  189. @patch("requests.get")
  190. @patch('time.sleep', return_value = None)
  191. @patch("csv.DictReader")
  192. @pytest.mark.parametrize("proxyLengthValid", [10])
  193. @pytest.mark.parametrize("proxyLengthInvalid", [1])
  194. @pytest.mark.parametrize("firstRun", [False])
  195. @pytest.mark.parametrize("htmlBodyErrors", ["td","tr","tbody"])
  196. def test_recheckProxies_proxy_list_failed_html_body(mock_csv_DictReader, mock_time_sleep, mock_get,
  197. proxyLengthValid, proxyLengthInvalid, firstRun, htmlBodyErrors):
  198. """
  199. Generate a html body error in proxy list request
  200. Test Steps:
  201. - Init a valid proxy list, firstRun = False
  202. - Failure in proxy list html body response is generated
  203. """
  204. # Initialize proxy list
  205. proxyRotate= init_ProxyRotate(mock_csv_DictReader, proxyLengthValid, firstRun)
  206. # Add valid response for proxy verification
  207. responseList = create_proxy_verification_response(HTTPStatus.OK, proxyLengthValid)
  208. # Create response for requesting more proxies
  209. responseList.append(create_request_proxy_list(HTTPStatus.OK, proxyLengthInvalid, htmlBodyErrors))
  210. # Add valid response for proxy verification - proxies are validated again
  211. responseList.extend(create_proxy_verification_response(HTTPStatus.OK, proxyLengthValid))
  212. mock_get.side_effect = responseList
  213. proxyRotate.recheckProxies(forever= False)
  214. assert len(responseList) == mock_get.call_count
  215. assert len(proxyRotate.proxies) == proxyLengthValid
  216. assert len(proxyRotate.all_proxies) == proxyLengthValid
  217. @patch('time.sleep', return_value = None)
  218. @patch("csv.DictReader")
  219. @pytest.mark.parametrize("proxyInitLength", [10, 700])
  220. def test_random_proxy(mock_csv_DictReader, mock_time_sleep, proxyInitLength):
  221. """
  222. Test random proxy return function
  223. When called with "value=0" it will not be able to provide a Proxy-Server as no Proxy servers can be found.
  224. """
  225. # Initialize proxy list
  226. proxyRotate = init_ProxyRotate(mock_csv_DictReader, proxyInitLength)
  227. proxyRotate.proxies = proxyRotate.all_proxies
  228. result = proxyRotate.random_proxy()
  229. assert isinstance(result["ip"], str)
  230. assert isinstance(result["port"], str)
  231. assert isinstance(result["type"], str)
  232. assert proxyRotate.proxies[result["ip"]].called == 1
  233. @patch('time.sleep', return_value = None)
  234. @patch("csv.DictReader")
  235. @pytest.mark.parametrize("proxyInitLength", [0])
  236. def test_random_proxy_no_proxy_found(mock_csv_DictReader, mock_time_sleep, proxyInitLength):
  237. """
  238. Test random proxy return function
  239. When called with "value=0" it will not be able to provide a Proxy-Server as no Proxy servers can be found.
  240. """
  241. # Initialize proxy list
  242. proxyRotate = init_ProxyRotate(mock_csv_DictReader, proxyInitLength)
  243. proxyRotate.proxies = proxyRotate.all_proxies
  244. with pytest.raises(BaseException):
  245. result = proxyRotate.random_proxy()
  246. @patch("csv.DictReader")
  247. @pytest.mark.parametrize("failedCounter", list(range(0,GC.PROXY_FAILCOUNTER)))
  248. @pytest.mark.parametrize("proxyInitLength", [10])
  249. def test_remove_proxy_fail_counter_in_range(mock_csv_DictReader, failedCounter, proxyInitLength):
  250. """
  251. Test increase the fail counter until the fail counter limit.
  252. Proxy should not be removed
  253. """
  254. # Initialize proxy list
  255. proxyRotate = init_ProxyRotate(mock_csv_DictReader, proxyInitLength)
  256. proxyRotate.proxies = proxyRotate.all_proxies
  257. for item in range(0, failedCounter):
  258. proxyRotate.remove_proxy((str)('0'))
  259. assert ('0' in proxyRotate.proxies)
  260. assert len(proxyRotate.proxies) == proxyInitLength
  261. @patch("csv.DictReader")
  262. @pytest.mark.parametrize("failedCounter", list(range(GC.PROXY_FAILCOUNTER, 5)))
  263. #@pytest.mark.parametrize("failedCounter", list(range(5,10)))
  264. @pytest.mark.parametrize("proxyInitLength", [10])
  265. @pytest.mark.parametrize("testProdyId", ["0"])
  266. def test_remove_proxy_fail_counter_out_of_range(mock_csv_DictReader, failedCounter, proxyInitLength, testProdyId):
  267. """
  268. Test increase the fail counter and exceed the fail counter limit.
  269. Proxy should be removed
  270. """
  271. # Initialize proxy list
  272. proxyRotate = init_ProxyRotate(mock_csv_DictReader, proxyInitLength)
  273. proxyRotate.proxies = proxyRotate.all_proxies
  274. for item in range(0, failedCounter):
  275. proxyRotate.remove_proxy((str)(testProdyId))
  276. assert failedCounter >= GC.PROXY_FAILCOUNTER
  277. assert testProdyId not in proxyRotate.proxies
  278. assert len(proxyRotate.proxies) == (proxyInitLength - 1)
  279. @patch("csv.DictReader")
  280. @pytest.mark.parametrize("proxyInitLength", [10])
  281. def test_remove_proxy_invalid_param(mock_csv_DictReader, proxyInitLength):
  282. """
  283. Test remove proxy for invalid parameter
  284. """
  285. # Initialize proxy list
  286. proxyRotate = init_ProxyRotate(mock_csv_DictReader, proxyInitLength)
  287. proxyRotate.proxies = proxyRotate.all_proxies
  288. proxyRotate.remove_proxy(ip = f'{proxyInitLength}')
  289. proxyRotate.remove_proxy(ip = proxyInitLength)
  290. proxyRotate.remove_proxy(ip = 'p')
  291. proxyRotate.remove_proxy(ip = 'z', port = 0)
  292. proxyRotate.remove_proxy(ip = 0, port = 'p')
  293. assert len(proxyRotate.proxies) == proxyInitLength
  294. """
  295. # TODO This test belongs to the integration test
  296. def test_gather_links():
  297. ## Will if links are gathering from website
  298. proxyRotate = ProxyRotate()
  299. proxies = proxyRotate.testGatherProxy()
  300. assert type(proxies)==list and len(proxies)>0
  301. """
  302. """
  303. # TODO This test belongs to the integration test
  304. def test_verify_proxy():
  305. ## Verifies single proxy and will give the result
  306. if os.path.isfile("../proxies.csv"):
  307. with open("../proxies.csv", 'r') as file:
  308. data = file.read()
  309. with open("proxies.csv", 'w') as output_file:
  310. output_file.write(data)
  311. elif os.path.isfile(os.path.join(os.path.expanduser("~"),"baangt/proxies.csv")):
  312. with open(os.path.join(os.path.expanduser("~"),"baangt/proxies.csv"), 'r') as file:
  313. data = file.read()
  314. with open("proxies.csv", 'w') as output_file:
  315. output_file.write(data)
  316. proxyRotate = ProxyRotate()
  317. result = proxyRotate.testVerifyProxy()
  318. print(result)
  319. assert type(result) == str
  320. """
  321. """
  322. # TODO This test belongs to the integration test
  323. def test_proxy_full_run():
  324. proxyRotate = ProxyRotate(reReadProxies=True)
  325. proxyRotate.recheckProxies(forever=False)
  326. assert len(proxyRotate.all_proxies) > len(proxyRotate.proxies)
  327. assert len(proxyRotate.proxies) == proxyRotate.MIN_PROXIES_FOR_FIRST_RUN
  328. result = proxyRotate.random_proxy()
  329. assert isinstance(result["ip"], str)
  330. assert isinstance(result["port"], str)
  331. assert isinstance(result["type"], str)
  332. result = proxyRotate.remove_proxy(ip=proxyRotate.random_proxy()["ip"])
  333. assert 1==1
  334. """