Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions tests/test_current_site_persistent_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from pathlib import Path
import sys
import unittest
from unittest.mock import patch

ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / 'tools'))
Expand Down Expand Up @@ -95,5 +96,61 @@ def test_complete_descriptors_do_not_admit_changed_source_text_or_role(self):
with self.subTest(change=before), self.assertRaisesRegex(ValueError, 'exact observation'):
history._restore_v2_live_pages(self.data, self.meta, descriptors)

def test_legacy50_restoration_qualifies_acquisitions_once(self):
expected = self.old['legacy_live_descriptors']
with patch.object(history, 'project_current_acquisitions',
wraps=history.project_current_acquisitions) as project:
restored = history._restore_v2_live_pages(self.data, self.meta, expected)
self.assertEqual([history.descriptor(k, v) for k, v in sorted(restored.items())], expected)
self.assertEqual(len(restored), 50)
self.assertEqual(project.call_count, 1, 'presentation retries share the same acquisition input')

def test_all_24_presentations_restore_exactly_with_task_table_sensitive_input(self):
data = copy.deepcopy(self.data)
data['graph']['data']['nodes']['math.lifetime-remainder'] = data['graph']['data']['nodes'].pop('node-0')
for task_records in (history.RESUME_TASK_RECORDS, history._RESUME_TASK_RECORDS_V1):
for annotations, style_first, resume in history.LIVE_PRESENTATIONS:
for readable in (True, False):
pages = history.render_live_current_v2(
data, self.meta, annotations=annotations, style_first=style_first,
resume=resume, task_records=task_records, readable_status=readable)
expected = [history.descriptor(k, v) for k, v in sorted(pages.items())]
with self.subTest(current_tasks=task_records is history.RESUME_TASK_RECORDS,
annotations=annotations, style_first=style_first,
resume=resume, readable=readable):
self.assertEqual(history._restore_v2_live_pages(data, self.meta, expected), pages)

def test_restore_still_requires_complete_ordered_descriptor_membership(self):
pages = history.render_live_current_v2(self.data, self.meta)
expected = [history.descriptor(k, v) for k, v in sorted(pages.items())]
wrong_path = copy.deepcopy(expected); wrong_path[0]['path'] = 'nodes/other.html'
wrong_size = copy.deepcopy(expected); wrong_size[0]['bytes'] += 1
mixed = copy.deepcopy(expected); mixed[0] = copy.deepcopy(self.old['legacy_live_descriptors'][0])
controls = {'missing': expected[:-1], 'duplicate': expected + [expected[0]],
'reordered': list(reversed(expected)), 'wrong_path': wrong_path,
'wrong_size': wrong_size, 'mixed': mixed}
for label, descriptors in controls.items():
with self.subTest(control=label), self.assertRaisesRegex(ValueError, 'exact observation'):
history._restore_v2_live_pages(self.data, self.meta, descriptors)

def test_each_restoration_qualifies_changed_input_without_mutation(self):
first = copy.deepcopy(self.data)
second = copy.deepcopy(self.data)
second['sources'].append(copy.deepcopy(second['sources'][0]))
self.assertNotEqual(history.project_current_acquisitions(first)['reasons'],
history.project_current_acquisitions(second)['reasons'])
before = copy.deepcopy(second)
cases = []
for data in (first, second):
pages = history.render_live_current_v2(data, self.meta, readable_status=False)
expected = [history.descriptor(k, v) for k, v in sorted(pages.items())]
cases.append((data, pages, expected))
with patch.object(history, 'project_current_acquisitions',
wraps=history.project_current_acquisitions) as project:
for data, pages, expected in cases:
self.assertEqual(history._restore_v2_live_pages(data, self.meta, expected), pages)
self.assertEqual(project.call_count, 2, 'each restoration must qualify its own input')
self.assertEqual(second, before)


if __name__ == '__main__': unittest.main()
7 changes: 6 additions & 1 deletion tools/current_site_history.py
Original file line number Diff line number Diff line change
Expand Up @@ -1162,12 +1162,17 @@ def _restore_v2_live_pages(data, meta, expected):
available for already-published observations; current builds use the current
table. Neither an observation date nor a partial match selects old bytes.
"""
# Reuse this pure projection only within this call's immutable input.
acquisition = None
for task_records in (RESUME_TASK_RECORDS, _RESUME_TASK_RECORDS_V1):
for annotations, style_first, resume in LIVE_PRESENTATIONS:
if annotations and acquisition is None:
acquisition = project_current_acquisitions(data)
for readable_status in (True, False):
pages = render_live_current_v2(
data, meta, annotations=annotations, style_first=style_first,
resume=resume, task_records=task_records, readable_status=readable_status)
resume=resume, task_records=task_records, readable_status=readable_status,
acquisition=acquisition)
if [descriptor(k, v) for k, v in sorted(pages.items())] == expected:
return pages
raise ValueError("live static reading does not match the exact observation")
Expand Down
Loading