pre-commit/tests/languages/download_test.py

132 lines
3.2 KiB
Python

from __future__ import annotations
import platform
from dataclasses import dataclass
from http.server import BaseHTTPRequestHandler
from http.server import HTTPServer
from threading import Thread
from typing import Collection
from typing import Iterator
import py.path
from pytest import fixture
import pre_commit.constants as C
from pre_commit.languages import download
from pre_commit.languages.download import ChecksumMismatchError
from pre_commit.languages.download import SRI
from pre_commit.languages.download import URI
from pre_commit.prefix import Prefix
@dataclass(frozen=True)
class Script:
content: bytes
integrity: SRI
@fixture
def shell() -> Script:
content = b'#!/bin/sh\necho hello\nexit 123'
integrity = SRI('sha256-oRJkj6Cr8nWIivZ9d3W+rVZt/aSW1l9YtxSVh+GtIHM=')
return Script(content, integrity)
@fixture
def batch() -> Script:
content = b'@echo off\necho hello\nexit 123'
integrity = SRI('sha256-L63Nefq+fKVIm24IKqlcqbJmc1rrJD3dKhIvutFK+IA=')
return Script(content, integrity)
@fixture
def script(shell: Script, batch: Script) -> Script:
if platform.system() == 'Windows':
return batch
else:
return shell
@dataclass(frozen=True)
class Server:
uri: URI
script: Script
@fixture
def server(script: Script) -> Iterator[Server]:
class HTTPRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.end_headers()
self.wfile.write(script.content)
httpd = HTTPServer(('localhost', 5555), HTTPRequestHandler)
thread = Thread(target=httpd.serve_forever, name='HTTP Server')
thread.start()
host, port = httpd.server_address
uri = URI(f'http://{str(host)}:{str(port)}')
try:
yield Server(uri, fixture)
finally:
httpd.shutdown()
httpd.server_close()
thread.join(1)
assert not thread.is_alive()
@dataclass(frozen=True)
class Fixture:
server: Server
dependencies: Collection[str]
@fixture
def healthy(server: Server, shell: Script, batch: Script) -> Fixture:
dependencies = (
f"""linux/amd64
{shell.integrity}
{server.uri}
test.bat""",
f"""windows/amd64
{batch.integrity}
{server.uri}
test.bat""",
)
return Fixture(server, dependencies)
@fixture
def unhealthy(server: Server, shell: Script, batch: Script) -> Fixture:
dependencies = (
f"""linux/amd64
{batch.integrity}
{server.uri}
test.bat""",
f"""windows/amd64
{shell.integrity}
{server.uri}
test.bat""",
)
return Fixture(server, dependencies)
@fixture
def prefix(tmpdir: py.path) -> Iterator[Prefix]:
with tmpdir.as_cwd():
directory = tmpdir.join('prefix').ensure_dir()
prefix = Prefix(str(directory))
yield prefix
def test_download_healthy(prefix: Prefix, healthy: Fixture) -> None:
"""Do a download test with healthy SRI checksum"""
download.install_environment(prefix, C.DEFAULT, healthy.dependencies)
assert download.health_check(prefix, C.DEFAULT) is None
def test_download_unhealthy(prefix: Prefix, unhealthy: Fixture) -> None:
"""Do a download test with unhealthy SRI checksum"""
try:
download.install_environment(prefix, C.DEFAULT, unhealthy.dependencies)
except ChecksumMismatchError:
pass