"""
Tests for http2 functionality in http_client.
We are really just unit testing the replay function here, but real test
scripts were used to generate these, which are:
  test/data/http2.01.py
  test/data/http2.02.py
"""
import asyncio
import json
import unittest

from preseem.http_client import ReplayHttpClient

class TestHttp2(unittest.TestCase):
    """Tests for HTTP2 client replay."""
    def setUp(self):
        self.loop = asyncio.new_event_loop() # needed to initialize asyncio
        asyncio.set_event_loop(self.loop)

    async def _make_client(self, url, file):
        return ReplayHttpClient(url, file)

    def make_client(self, url, file):
        return self._await(self._make_client(url, file))

    def tearDown(self):
        self.loop.close()

    def _await(self, co):
        return self.loop.run_until_complete(co)

    async def _get_stream_content(self, r):
        content = b''
        async for chunk in r.aiter_bytes():
            content += chunk
        return content

    def test_request(self):
        """Test replay of a http2 request"""
        client = self.make_client('https://ipinfo.io', 'test/data/http2.01.http2')
        r = self._await(client.http2_request('/', headers={'accept': 'application/json'}))
        self.assertEqual(r.headers, {
            'access-control-allow-origin': '*',
            'alt-svc': 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000',
            'content-encoding': 'gzip',
            'content-type': 'application/json; charset=utf-8',
            'date': 'Tue, 20 Sep 2022 01:35:34 GMT',
            'referrer-policy': 'strict-origin-when-cross-origin',
            'strict-transport-security': 'max-age=2592000; includeSubDomains',
            'vary': 'Accept-Encoding',
            'via': '1.1 google',
            'x-content-type-options': 'nosniff',
            'x-envoy-upstream-service-time': '3',
            'x-frame-options': 'SAMEORIGIN',
            'x-xss-protection': '1; mode=block',
        })
        self.assertEqual(json.loads(r.content.decode('utf-8')), 
        {
            "ip": "216.58.123.77",
            "hostname": "216-58-123-77.cpe.distributel.net",
            "city": "Kitchener",
            "region": "Ontario",
            "country": "CA",
            "loc": "43.4260,-80.5438",
            "org": "AS11814 Distributel Communications Limited",
            "postal": "N2N",
            "timezone": "America/Toronto",
            "readme": "https://ipinfo.io/missingauth",
        })
        self._await(client.close())

    def test_stream(self):
        """Test replay of a http2 stream"""
        client = self.make_client('https://ipinfo.io', 'test/data/http2.02.http2')
        r = self._await(client.http2_stream('/', headers={'accept': 'application/json'}))
        content = self._await(self._get_stream_content(r))
        self.assertEqual(r.headers, {
            'access-control-allow-origin': '*',
            'alt-svc': 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000',
            'content-encoding': 'gzip',
            'content-type': 'application/json; charset=utf-8',
            'date': 'Tue, 20 Sep 2022 01:42:41 GMT',
            'referrer-policy': 'strict-origin-when-cross-origin',
            'strict-transport-security': 'max-age=2592000; includeSubDomains',
            'vary': 'Accept-Encoding',
            'via': '1.1 google',
            'x-content-type-options': 'nosniff',
            'x-envoy-upstream-service-time': '4',
            'x-frame-options': 'SAMEORIGIN',
            'x-xss-protection': '1; mode=block',
        })
        self.assertEqual(json.loads(content.decode('utf-8')), 
        {
            "ip": "216.58.123.77",
            "hostname": "216-58-123-77.cpe.distributel.net",
            "city": "Kitchener",
            "region": "Ontario",
            "country": "CA",
            "loc": "43.4260,-80.5438",
            "org": "AS11814 Distributel Communications Limited",
            "postal": "N2N",
            "timezone": "America/Toronto",
            "readme": "https://ipinfo.io/missingauth",
        })
        self._await(client.close())
