55
66import pytest
77from redis import Redis
8+ from shared .reports .resources import Report , ReportFile
89from shared .reports .types import ReportLine
910from shared .yaml import UserYaml
1011from sqlalchemy .orm import Session
1112
13+ from database .models .core import Commit , CompareCommit , Repository
1214from database .tests .factories import CommitFactory , RepositoryFactory
15+ from database .tests .factories .core import PullFactory
1316from rollouts import PARALLEL_UPLOAD_PROCESSING_BY_REPO
1417from services .archive import ArchiveService
1518from services .redis import get_redis_connection
@@ -37,6 +40,78 @@ def lines(lines: Iterable[tuple[int, ReportLine]]) -> list[tuple[int, int]]:
3740 return list (((lineno , line .coverage ) for lineno , line in lines ))
3841
3942
43+ def get_base_report ():
44+ file_a = ReportFile ("a.rs" )
45+ file_a .append (1 , ReportLine .create (coverage = 1 , sessions = [[0 , 1 ]]))
46+ file_a .append (1 , ReportLine .create (coverage = 2 , sessions = [[1 , 2 ]]))
47+
48+ file_b = ReportFile ("b.rs" )
49+ file_b .append (1 , ReportLine .create (coverage = 3 , sessions = [[0 , 3 ]]))
50+ file_b .append (2 , ReportLine .create (coverage = 5 , sessions = [[1 , 5 ]]))
51+ report = Report ()
52+ report .append (file_a )
53+ report .append (file_b )
54+ return report
55+
56+
57+ def setup_base_commit (repository : Repository , dbsession : Session ) -> Commit :
58+ base_report = get_base_report ()
59+ commit = CommitFactory (repository = repository )
60+ dbsession .add (commit )
61+ dbsession .flush ()
62+ report_service = ReportService ({})
63+ report_service .save_full_report (commit , base_report )
64+ return commit
65+
66+
67+ def setup_mock_get_compare (
68+ base_commit : Commit , head_commit : Commit , mock_repo_provider
69+ ):
70+ get_compare = {
71+ "diff" : {
72+ "files" : {
73+ "a.rs" : {
74+ "type" : "modified" ,
75+ "before" : None ,
76+ "segments" : [
77+ {
78+ "header" : ["1" , "3" , "1" , "4" ],
79+ "lines" : [
80+ " fn main() {" ,
81+ '- println!("Salve!");' ,
82+ '+ println!("Hello World!");' ,
83+ '+ println!(":wink:");' ,
84+ " }" ,
85+ ],
86+ }
87+ ],
88+ }
89+ }
90+ },
91+ "commits" : [
92+ {
93+ "commitid" : base_commit .commitid ,
94+ "message" : "BASE commit" ,
95+ "timestamp" : base_commit .timestamp ,
96+ "author" : {
97+ "id" : base_commit .author .service_id ,
98+ "username" : base_commit .author .username ,
99+ },
100+ },
101+ {
102+ "commitid" : head_commit .commitid ,
103+ "message" : "HEAD commit" ,
104+ "timestamp" : head_commit .timestamp ,
105+ "author" : {
106+ "id" : head_commit .author .service_id ,
107+ "username" : head_commit .author .username ,
108+ },
109+ },
110+ ],
111+ }
112+ mock_repo_provider .get_compare .return_value = get_compare
113+
114+
40115@pytest .mark .integration
41116@pytest .mark .django_db ()
42117@pytest .mark .parametrize ("do_parallel_processing" , [False , True ])
@@ -81,12 +156,25 @@ def test_full_upload(
81156 dbsession .add (repository )
82157 dbsession .flush ()
83158
159+ # setup a base commit (with a report) to compare against the current one
160+ base_commit = setup_base_commit (repository , dbsession )
161+
84162 repoid = repository .repoid
85163 commitid = uuid4 ().hex
86- commit = CommitFactory .create (repository = repository , commitid = commitid )
164+ commit = CommitFactory .create (repository = repository , commitid = commitid , pullid = 12 )
87165 dbsession .add (commit )
88166 dbsession .flush ()
89167
168+ # BASE and HEAD are connected in a PR
169+ pull = PullFactory (
170+ pullid = 12 ,
171+ repository = repository ,
172+ compared_to = base_commit .commitid ,
173+ )
174+ dbsession .add (pull )
175+ dbsession .flush ()
176+ setup_mock_get_compare (base_commit , commit , mock_repo_provider )
177+
90178 archive_service = ArchiveService (repository )
91179 do_upload = partial (
92180 write_raw_upload ,
@@ -96,38 +184,47 @@ def test_full_upload(
96184 commitid ,
97185 )
98186
99- do_upload (b"""
187+ do_upload (
188+ b"""
100189a.rs
101190<<<<<< network
102191# path=coverage.lcov
103192SF:a.rs
104193DA:1,1
105194end_of_record
106- """ )
107- do_upload (b"""
195+ """
196+ )
197+ do_upload (
198+ b"""
108199a.rs
109200<<<<<< network
110201# path=coverage.lcov
111202SF:a.rs
112203DA:2,2
204+ DA:3,1
113205end_of_record
114- """ )
115- do_upload (b"""
206+ """
207+ )
208+ do_upload (
209+ b"""
116210b.rs
117211<<<<<< network
118212# path=coverage.lcov
119213SF:b.rs
120214DA:1,3
121215end_of_record
122- """ )
123- do_upload (b"""
216+ """
217+ )
218+ do_upload (
219+ b"""
124220b.rs
125221<<<<<< network
126222# path=coverage.lcov
127223SF:b.rs
128224DA:2,5
129225end_of_record
130- """ )
226+ """
227+ )
131228
132229 with run_tasks ():
133230 upload_task .apply_async (
@@ -148,6 +245,7 @@ def test_full_upload(
148245 assert lines (a .lines ) == [
149246 (1 , 1 ),
150247 (2 , 2 ),
248+ (3 , 1 ),
151249 ]
152250
153251 b = report .get ("b.rs" )
@@ -156,14 +254,16 @@ def test_full_upload(
156254
157255 # Adding one more upload
158256
159- do_upload (b"""
257+ do_upload (
258+ b"""
160259c.rs
161260<<<<<< network
162261# path=coverage.lcov
163262SF:c.rs
164263DA:2,4
165264end_of_record
166- """ )
265+ """
266+ )
167267
168268 with run_tasks ():
169269 upload_task .apply_async (
@@ -188,3 +288,21 @@ def test_full_upload(
188288 assert raw_chunks_path in archive
189289 raw_files_sessions_path = f"v4/repos/{ repo_hash } /commits/{ commitid } /json_data/commits/report_json/{ commitid } .json"
190290 assert raw_files_sessions_path in archive
291+
292+ comparison : CompareCommit = (
293+ dbsession .query (CompareCommit )
294+ .filter (
295+ CompareCommit .base_commit_id == base_commit .id ,
296+ CompareCommit .compare_commit_id == commit .id ,
297+ )
298+ .first ()
299+ )
300+ assert comparison is not None
301+ assert comparison .error is None
302+ assert comparison .state == "processed"
303+ assert comparison .patch_totals == {
304+ "hits" : 2 ,
305+ "misses" : 0 ,
306+ "coverage" : 1 ,
307+ "partials" : 0 ,
308+ }
0 commit comments