Connection.py
1 ############################ Copyrights and license ############################ 2 # # 3 # Copyright 2019 Adam Baratz <adam.baratz@gmail.com> # 4 # # 5 # This file is part of PyGithub. # 6 # http://pygithub.readthedocs.io/ # 7 # # 8 # PyGithub is free software: you can redistribute it and/or modify it under # 9 # the terms of the GNU Lesser General Public License as published by the Free # 10 # Software Foundation, either version 3 of the License, or (at your option) # 11 # any later version. # 12 # # 13 # PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # 14 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # 15 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # 16 # details. # 17 # # 18 # You should have received a copy of the GNU Lesser General Public License # 19 # along with PyGithub. If not, see <http://www.gnu.org/licenses/>. # 20 # # 21 ################################################################################ 22 23 24 import itertools 25 from io import StringIO 26 from unittest.mock import Mock 27 28 import httpretty # type: ignore 29 import pytest # type: ignore 30 31 from . import Framework 32 33 PARAMETERS = itertools.product( 34 [ 35 (Framework.ReplayingHttpConnection, "http"), 36 (Framework.ReplayingHttpsConnection, "https"), 37 ], 38 [ 39 ( 40 '{"body":"BODY TEXT"}', 41 "\nGET\napi.github.com\nNone\n/user\n{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}\nNone\n200\n[]\n{\"body\":\"BODY TEXT\"}\n\n", 42 ), 43 ( 44 '{"body":"BODY\xa0TEXT"}', 45 "\nGET\napi.github.com\nNone\n/user\n{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}\nNone\n200\n[]\n{\"body\":\"BODY\xa0TEXT\"}\n\n", 46 ), 47 ( 48 "BODY TEXT", 49 "\nGET\napi.github.com\nNone\n/user\n{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}\nNone\n200\n[]\nBODY TEXT\n\n", 50 ), 51 ( 52 "BODY\xa0TEXT", 53 "\nGET\napi.github.com\nNone\n/user\n{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}\nNone\n200\n[]\nBODY\xa0TEXT\n\n", 54 ), 55 ], 56 ) 57 58 59 class RecordingMockConnection(Framework.RecordingConnection): 60 def __init__(self, file, protocol, host, port, realConnection): 61 self._realConnection = realConnection 62 super().__init__(file, protocol, host, port) 63 64 65 @pytest.mark.parametrize( 66 ("replaying_connection_class", "protocol", "response_body", "expected_recording"), 67 list(tuple(itertools.chain(*p)) for p in PARAMETERS), 68 ) 69 def testRecordAndReplay(replaying_connection_class, protocol, response_body, expected_recording): 70 file = StringIO() 71 host = "api.github.com" 72 verb = "GET" 73 url = "/user" 74 headers = {"Authorization": "Basic p4ssw0rd", "User-Agent": "PyGithub/Python"} 75 76 response = Mock() 77 response.status = 200 78 response.getheaders.return_value = {} 79 response.read.return_value = response_body 80 81 connection = Mock() 82 connection.getresponse.return_value = response 83 84 # write mock response to buffer 85 recording_connection = RecordingMockConnection(file, protocol, host, None, lambda *args, **kwds: connection) 86 recording_connection.request(verb, url, None, headers) 87 recording_connection.getresponse() 88 recording_connection.close() 89 90 # validate contents of buffer 91 file_value_lines = file.getvalue().split("\n") 92 expected_recording_lines = (protocol + expected_recording).split("\n") 93 assert file_value_lines[:5] == expected_recording_lines[:5] 94 assert eval(file_value_lines[5]) == eval(expected_recording_lines[5]) 95 # dict literal, so keys not in guaranteed order 96 assert file_value_lines[6:] == expected_recording_lines[6:] 97 98 # required for replay to work as expected 99 httpretty.enable(allow_net_connect=False) 100 101 # rewind buffer and attempt to replay response from it 102 file.seek(0) 103 replaying_connection = replaying_connection_class(file, host=host, port=None) 104 replaying_connection.request(verb, url, None, headers) 105 replaying_connection.getresponse() 106 107 # not necessarily required for subsequent tests 108 httpretty.disable() 109 httpretty.reset()