/ tests / Connection.py
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()