Skip to content
Closed
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
17 changes: 17 additions & 0 deletions forensics/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
RAW_TEXT_PREVIEW_CHARS,
audit_bytes_from_request,
client_ip,
group_detail_shell_context,
groups_for_audit_file,
)

Expand Down Expand Up @@ -1821,6 +1822,22 @@ def test_duplicate_heavy_reupload_keeps_group_link_with_zero_stored_events(self)
rows = {row.slug: row for row in group_list_rows()}
self.assertEqual(rows[GROUP_REF].audit_file_count, 2)

# The group-detail shell count must agree with the Files tab listing
# and the group-list table: it counts linked files via the explicit
# AuditFile.groups M2M, so the duplicate-only file (zero stored events
# for GROUP_REF) is included. Before goggles#91 this used
# `events__group`, which excluded the duplicate-only file and made the
# header / Files-tab badge undercount to 1 while the Files tab itself
# listed 2.
shell_context = group_detail_shell_context(group)
self.assertEqual(shell_context["summary"]["file_count"], 2)
self.assertEqual(shell_context["tab_counts"]["files"], 2)
# The shell count must equal the number of files the Files tab lists.
self.assertEqual(
shell_context["summary"]["file_count"],
len(detail_files),
)

def test_corrected_valid_upload_keeps_lines_seen_in_quarantined_upload(self):
raw_token, _token = UploadToken.issue("ios test client")
bad_body = json.dumps(audit_event(0), separators=(",", ":")) + "\n{not-json}\n"
Expand Down
11 changes: 10 additions & 1 deletion forensics/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,16 @@ def group_detail_shell_context(group: AuditGroup) -> dict:
message_count=Count("msg_id", filter=~Q(msg_id=""), distinct=True),
action_count=Count("id", filter=~Q(human_action_action="")),
)
file_count = AuditFile.objects.filter(events__group=group).distinct().count()
# Count linked files from the explicit AuditFile.groups M2M (goggles#37),
# NOT from stored AuditEvent rows. A duplicate-heavy upload whose group
# events were all deduplicated away has zero stored events for the group
# but is still genuinely linked to it via the M2M. Filtering on
# `events__group` (the old behavior) undercounted such files, so the
# header / Files-tab badge disagreed with the Files tab listing, the
# group-list table, and the agent export — all of which count via the M2M
# (audit_files_for_group, annotated_group_list, group_summary). See
# goggles#91.
file_count = AuditFile.objects.filter(groups=group).distinct().count()
invalid_event_count = AuditEvent.objects.filter(
group=group, parse_status=AuditEvent.STATUS_INVALID
).count()
Expand Down
Loading