Files
ossm-configurator/tests/test_vendor_update.py

318 lines
8.6 KiB
Python

#!/usr/bin/env python3
"""
Tests for vendor_update.py
"""
import hashlib
import json
import tempfile
from pathlib import Path
from unittest.mock import Mock, patch, mock_open
import pytest
import responses
# Import the module (adjust path as needed)
import sys
sys.path.insert(0, str(Path(__file__).parent.parent / 'scripts'))
from vendor_update import GitHubAPI, compute_sha256, download_file, update_manifest_entry
@pytest.fixture
def temp_dir():
"""Create a temporary directory for tests."""
with tempfile.TemporaryDirectory() as tmpdir:
yield Path(tmpdir)
@pytest.fixture
def sample_manifest_entry():
"""Sample manifest entry for testing."""
return {
'id': 'test-entry',
'source_repo': 'owner/repo',
'source_path': 'path/to/file.stl',
'source_ref': 'main',
'pinned_sha': None,
'pinned_raw_url': None,
'local_path': 'vendor/owner-repo/path/to/file.stl',
'checksum_sha256': None,
'last_checked': None,
'upstream_latest_sha': None,
'status': 'unknown',
'license': None
}
@pytest.fixture
def github_api():
"""Create a GitHubAPI instance for testing."""
return GitHubAPI(token='test-token')
def test_compute_sha256(temp_dir):
"""Test SHA256 computation."""
test_file = temp_dir / 'test.txt'
test_file.write_text('test content')
checksum = compute_sha256(test_file)
# Verify it's a valid SHA256 hex string
assert len(checksum) == 64
assert all(c in '0123456789abcdef' for c in checksum.lower())
# Verify it matches expected hash
expected = hashlib.sha256(b'test content').hexdigest()
assert checksum == expected
@responses.activate
def test_download_file_success(temp_dir):
"""Test successful file download."""
test_url = 'https://example.com/file.stl'
test_content = b'STL file content'
dest_path = temp_dir / 'downloaded.stl'
responses.add(
responses.GET,
test_url,
body=test_content,
status=200
)
result = download_file(test_url, dest_path)
assert result is True
assert dest_path.exists()
assert dest_path.read_bytes() == test_content
@responses.activate
def test_download_file_failure():
"""Test file download failure."""
test_url = 'https://example.com/missing.stl'
dest_path = Path('/tmp/test.stl')
responses.add(
responses.GET,
test_url,
status=404
)
result = download_file(test_url, dest_path)
assert result is False
@responses.activate
def test_github_api_get_file_sha(github_api):
"""Test getting file SHA from GitHub API."""
owner = 'test-owner'
repo = 'test-repo'
path = 'file.stl'
ref = 'main'
# Mock Contents API response
responses.add(
responses.GET,
f'https://api.github.com/repos/{owner}/{repo}/contents/{path}',
json={'sha': 'blob-sha-123'},
match=[responses.matchers.query_param_matcher({'ref': ref})]
)
# Mock Commits API response
responses.add(
responses.GET,
f'https://api.github.com/repos/{owner}/{repo}/commits',
json=[{'sha': 'commit-sha-456'}],
match=[responses.matchers.query_param_matcher({
'path': path,
'sha': ref,
'per_page': 1
})]
)
sha = github_api.get_file_sha(owner, repo, path, ref)
assert sha == 'commit-sha-456'
@responses.activate
def test_github_api_get_license(github_api):
"""Test getting license information."""
owner = 'test-owner'
repo = 'test-repo'
sha = 'abc123'
# Mock LICENSE file found
responses.add(
responses.GET,
f'https://api.github.com/repos/{owner}/{repo}/contents/LICENSE',
json={'type': 'file'},
match=[responses.matchers.query_param_matcher({'ref': sha})]
)
license_url = github_api.get_license(owner, repo, sha)
assert license_url == f'https://raw.githubusercontent.com/{owner}/{repo}/{sha}/LICENSE'
@responses.activate
def test_update_manifest_entry_dry_run(temp_dir, sample_manifest_entry):
"""Test updating manifest entry in dry-run mode."""
owner = 'owner'
repo = 'repo'
path = 'path/to/file.stl'
ref = 'main'
# Mock API responses
responses.add(
responses.GET,
f'https://api.github.com/repos/{owner}/{repo}/contents/{path}',
json={'sha': 'blob-sha'},
match=[responses.matchers.query_param_matcher({'ref': ref})]
)
responses.add(
responses.GET,
f'https://api.github.com/repos/{owner}/{repo}/commits',
json=[{'sha': 'commit-sha-123'}],
match=[responses.matchers.query_param_matcher({
'path': path,
'sha': ref,
'per_page': 1
})]
)
api = GitHubAPI(token='test-token')
updated_entry = update_manifest_entry(
sample_manifest_entry,
api,
temp_dir,
dry_run=True
)
assert updated_entry['pinned_sha'] == 'commit-sha-123'
assert updated_entry['pinned_raw_url'] == f'https://raw.githubusercontent.com/{owner}/{repo}/commit-sha-123/{path}'
assert updated_entry['status'] == 'up-to-date'
assert updated_entry['last_checked'] is not None
assert updated_entry['upstream_latest_sha'] == 'commit-sha-123'
# In dry-run, file should not be downloaded
local_path = temp_dir / updated_entry['local_path']
assert not local_path.exists()
@responses.activate
def test_update_manifest_entry_with_download(temp_dir, sample_manifest_entry):
"""Test updating manifest entry with actual download."""
owner = 'owner'
repo = 'repo'
path = 'path/to/file.stl'
ref = 'main'
commit_sha = 'commit-sha-123'
file_content = b'STL file content here'
# Mock API responses
responses.add(
responses.GET,
f'https://api.github.com/repos/{owner}/{repo}/contents/{path}',
json={'sha': 'blob-sha'},
match=[responses.matchers.query_param_matcher({'ref': ref})]
)
responses.add(
responses.GET,
f'https://api.github.com/repos/{owner}/{repo}/commits',
json=[{'sha': commit_sha}],
match=[responses.matchers.query_param_matcher({
'path': path,
'sha': ref,
'per_page': 1
})]
)
# Mock file download
pinned_url = f'https://raw.githubusercontent.com/{owner}/{repo}/{commit_sha}/{path}'
responses.add(
responses.GET,
pinned_url,
body=file_content,
status=200
)
api = GitHubAPI(token='test-token')
updated_entry = update_manifest_entry(
sample_manifest_entry,
api,
temp_dir,
dry_run=False
)
assert updated_entry['pinned_sha'] == commit_sha
assert updated_entry['checksum_sha256'] is not None
assert updated_entry['status'] == 'up-to-date'
# Verify file was downloaded
local_path = temp_dir / updated_entry['local_path']
assert local_path.exists()
assert local_path.read_bytes() == file_content
# Verify checksum
expected_checksum = hashlib.sha256(file_content).hexdigest()
assert updated_entry['checksum_sha256'] == expected_checksum
@responses.activate
def test_update_manifest_entry_download_failure(temp_dir, sample_manifest_entry):
"""Test handling of download failure."""
owner = 'owner'
repo = 'repo'
path = 'path/to/file.stl'
ref = 'main'
commit_sha = 'commit-sha-123'
# Mock API responses
responses.add(
responses.GET,
f'https://api.github.com/repos/{owner}/{repo}/contents/{path}',
json={'sha': 'blob-sha'},
match=[responses.matchers.query_param_matcher({'ref': ref})]
)
responses.add(
responses.GET,
f'https://api.github.com/repos/{owner}/{repo}/commits',
json=[{'sha': commit_sha}],
match=[responses.matchers.query_param_matcher({
'path': path,
'sha': ref,
'per_page': 1
})]
)
# Mock file download failure
pinned_url = f'https://raw.githubusercontent.com/{owner}/{repo}/{commit_sha}/{path}'
responses.add(
responses.GET,
pinned_url,
status=404
)
api = GitHubAPI(token='test-token')
updated_entry = update_manifest_entry(
sample_manifest_entry,
api,
temp_dir,
dry_run=False
)
assert updated_entry['status'] == 'error'
assert updated_entry['pinned_sha'] == commit_sha # SHA was resolved
assert updated_entry['checksum_sha256'] is None # File not downloaded
if __name__ == '__main__':
pytest.main([__file__, '-v'])