241 lines
6.7 KiB
Python
241 lines
6.7 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Tests for check_updates.py
|
|
"""
|
|
|
|
import json
|
|
import sys
|
|
import tempfile
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
import responses
|
|
|
|
# Import the module
|
|
sys.path.insert(0, str(Path(__file__).parent.parent / 'scripts'))
|
|
|
|
from check_updates import GitHubAPI, check_entry
|
|
|
|
|
|
@pytest.fixture
|
|
def github_api():
|
|
"""Create a GitHubAPI instance for testing."""
|
|
return GitHubAPI(token='test-token')
|
|
|
|
|
|
@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': 'pinned-sha-123',
|
|
'pinned_raw_url': 'https://raw.githubusercontent.com/owner/repo/pinned-sha-123/path/to/file.stl',
|
|
'local_path': 'vendor/owner-repo/path/to/file.stl',
|
|
'checksum_sha256': 'abc123',
|
|
'last_checked': '2024-01-01T00:00:00Z',
|
|
'upstream_latest_sha': None,
|
|
'status': 'unknown',
|
|
'license': None
|
|
}
|
|
|
|
|
|
@responses.activate
|
|
def test_check_entry_up_to_date(github_api, sample_manifest_entry):
|
|
"""Test checking an entry that is up-to-date."""
|
|
owner = 'owner'
|
|
repo = 'repo'
|
|
path = 'path/to/file.stl'
|
|
ref = 'main'
|
|
pinned_sha = 'pinned-sha-123'
|
|
|
|
# Mock commits API - return same SHA as pinned
|
|
responses.add(
|
|
responses.GET,
|
|
f'https://api.github.com/repos/{owner}/{repo}/commits',
|
|
json=[{'sha': pinned_sha}],
|
|
match=[responses.matchers.query_param_matcher({
|
|
'path': path,
|
|
'sha': ref,
|
|
'per_page': 1
|
|
})]
|
|
)
|
|
|
|
updated_entry = check_entry(sample_manifest_entry, github_api)
|
|
|
|
assert updated_entry['status'] == 'up-to-date'
|
|
assert updated_entry['upstream_latest_sha'] == pinned_sha
|
|
assert updated_entry['last_checked'] is not None
|
|
|
|
|
|
@responses.activate
|
|
def test_check_entry_out_of_date(github_api, sample_manifest_entry):
|
|
"""Test checking an entry that is out-of-date."""
|
|
owner = 'owner'
|
|
repo = 'repo'
|
|
path = 'path/to/file.stl'
|
|
ref = 'main'
|
|
pinned_sha = 'pinned-sha-123'
|
|
latest_sha = 'latest-sha-456'
|
|
|
|
# Mock commits API - return different SHA
|
|
responses.add(
|
|
responses.GET,
|
|
f'https://api.github.com/repos/{owner}/{repo}/commits',
|
|
json=[{'sha': latest_sha}],
|
|
match=[responses.matchers.query_param_matcher({
|
|
'path': path,
|
|
'sha': ref,
|
|
'per_page': 1
|
|
})]
|
|
)
|
|
|
|
updated_entry = check_entry(sample_manifest_entry, github_api)
|
|
|
|
assert updated_entry['status'] == 'out-of-date'
|
|
assert updated_entry['upstream_latest_sha'] == latest_sha
|
|
assert updated_entry['pinned_sha'] == pinned_sha # Pinned SHA unchanged
|
|
assert updated_entry['last_checked'] is not None
|
|
|
|
|
|
@responses.activate
|
|
def test_check_entry_no_pinned_sha(github_api):
|
|
"""Test checking an entry with no pinned SHA."""
|
|
entry = {
|
|
'id': 'test-entry',
|
|
'source_repo': 'owner/repo',
|
|
'source_path': 'path/to/file.stl',
|
|
'source_ref': 'main',
|
|
'pinned_sha': None,
|
|
'status': 'unknown'
|
|
}
|
|
|
|
owner = 'owner'
|
|
repo = 'repo'
|
|
path = 'path/to/file.stl'
|
|
ref = 'main'
|
|
latest_sha = 'latest-sha-456'
|
|
|
|
responses.add(
|
|
responses.GET,
|
|
f'https://api.github.com/repos/{owner}/{repo}/commits',
|
|
json=[{'sha': latest_sha}],
|
|
match=[responses.matchers.query_param_matcher({
|
|
'path': path,
|
|
'sha': ref,
|
|
'per_page': 1
|
|
})]
|
|
)
|
|
|
|
updated_entry = check_entry(entry, github_api)
|
|
|
|
assert updated_entry['status'] == 'unknown'
|
|
assert updated_entry['upstream_latest_sha'] == latest_sha
|
|
|
|
|
|
@responses.activate
|
|
def test_check_entry_api_error(github_api, sample_manifest_entry):
|
|
"""Test handling of API errors."""
|
|
owner = 'owner'
|
|
repo = 'repo'
|
|
path = 'path/to/file.stl'
|
|
ref = 'main'
|
|
|
|
# Mock API error
|
|
responses.add(
|
|
responses.GET,
|
|
f'https://api.github.com/repos/{owner}/{repo}/commits',
|
|
status=500
|
|
)
|
|
|
|
updated_entry = check_entry(sample_manifest_entry, github_api)
|
|
|
|
assert updated_entry['status'] == 'unknown'
|
|
assert updated_entry['upstream_latest_sha'] is None
|
|
|
|
|
|
@responses.activate
|
|
def test_check_entry_file_not_found(github_api, sample_manifest_entry):
|
|
"""Test handling when file doesn't exist at ref."""
|
|
owner = 'owner'
|
|
repo = 'repo'
|
|
path = 'path/to/file.stl'
|
|
ref = 'main'
|
|
|
|
# Mock empty commits response (file doesn't exist)
|
|
responses.add(
|
|
responses.GET,
|
|
f'https://api.github.com/repos/{owner}/{repo}/commits',
|
|
json=[],
|
|
match=[responses.matchers.query_param_matcher({
|
|
'path': path,
|
|
'sha': ref,
|
|
'per_page': 1
|
|
})]
|
|
)
|
|
|
|
updated_entry = check_entry(sample_manifest_entry, github_api)
|
|
|
|
# Should still update last_checked but status might be unknown
|
|
assert updated_entry['last_checked'] is not None
|
|
|
|
|
|
def test_github_api_get_latest_commit_sha(github_api):
|
|
"""Test getting latest commit SHA."""
|
|
owner = 'owner'
|
|
repo = 'repo'
|
|
path = 'file.stl'
|
|
ref = 'main'
|
|
expected_sha = 'commit-sha-789'
|
|
|
|
with responses.RequestsMock() as rsps:
|
|
rsps.add(
|
|
responses.GET,
|
|
f'https://api.github.com/repos/{owner}/{repo}/commits',
|
|
json=[{'sha': expected_sha}],
|
|
match=[responses.matchers.query_param_matcher({
|
|
'path': path,
|
|
'sha': ref,
|
|
'per_page': 1
|
|
})]
|
|
)
|
|
|
|
sha = github_api.get_latest_commit_sha(owner, repo, path, ref)
|
|
|
|
assert sha == expected_sha
|
|
|
|
|
|
def test_github_api_get_latest_commit_sha_ref_is_sha(github_api):
|
|
"""Test when ref is already a SHA."""
|
|
owner = 'owner'
|
|
repo = 'repo'
|
|
path = 'file.stl'
|
|
ref = 'a' * 40 # Valid SHA format
|
|
|
|
# Should return the ref as-is if it's already a SHA
|
|
sha = github_api.get_latest_commit_sha(owner, repo, path, ref)
|
|
|
|
# Actually, the function tries to get commits first, so it will make an API call
|
|
# But if ref is a SHA, it should work
|
|
with responses.RequestsMock() as rsps:
|
|
rsps.add(
|
|
responses.GET,
|
|
f'https://api.github.com/repos/{owner}/{repo}/commits',
|
|
json=[{'sha': ref}],
|
|
match=[responses.matchers.query_param_matcher({
|
|
'path': path,
|
|
'sha': ref,
|
|
'per_page': 1
|
|
})]
|
|
)
|
|
|
|
sha = github_api.get_latest_commit_sha(owner, repo, path, ref)
|
|
assert sha == ref
|
|
|
|
|
|
if __name__ == '__main__':
|
|
pytest.main([__file__, '-v'])
|