TgWitness tests

Automatic · every commit to main

Every commit, tested in the open.

Each new TgWitness commit runs the whole suite on a clean machine: the signed journal and its verifier, evidence exports and reports, the panel in a real browser, sessions against synthetic Telegram clients. Larger runs drive real test accounts on a test server. Every result is published here, failures included.

2,178tests passed out of 2,255 on commit 3a614fb780cd · Detect secret chats the peer endedFinished 2026-11-14 08:29 UTC
  1. Pick up the commitEach new commit on main, checked out exactly as published
  2. Run the full suite2,255 tests in 137 files, browser checks included
  3. Drive real accountsCapture, export and verify on test accounts and test chats
  4. Publish every resultTotals, each failure with its message, raw JUnit and logs
Tests
2,255
137 files
Passed
2,178
96.6%
New failures
10
turn the run red
Known failures
32
listed with reasons
Skipped
35
not applicable here
Duration
17 min
one machine

COVERAGE

What the suite checks

Tests grouped by the part of TgWitness they exercise; the bar is the share that passed.

Reports and analysis45 files
763 / 778 · 15 known
Journal, signatures and timestamps31 files
469 / 481 · 12 known
Evidence exports18 files
337 / 338 · 1 known
Panel, API and site18 files
239 / 240 · 1 known
Other4 files
145 / 155 · 10 new
Accounts and sessions15 files
132 / 134 · 2 known
Capture add-on6 files
93 / 94 · 1 known

FAILURES

Every failure, in full

New failures turn the run red. Known failures are listed with the reason they are expected until fixed.

tools/test_proxy_source_settings.py10 new
  • test_invalid_settings_prevent_refresh_before_network
    Error message
    Failed: DID NOT RAISE ValueError
  • test_permission_error_never_restores_enabled_defaults
    Error message
    Failed: DID NOT RAISE ValueError
  • test_unreadable_settings_never_restore_enabled_defaults[[]]
    Error message
    Failed: DID NOT RAISE ValueError
  • test_unreadable_settings_never_restore_enabled_defaults[\xff]
    Error message
    Failed: DID NOT RAISE ValueError
  • test_unreadable_settings_never_restore_enabled_defaults[]
    Error message
    Failed: DID NOT RAISE ValueError
  • test_unreadable_settings_never_restore_enabled_defaults[null]
    Error message
    Failed: DID NOT RAISE ValueError
  • test_unreadable_settings_never_restore_enabled_defaults[{"countries":"invalid"}]
    Error message
    Failed: DID NOT RAISE ValueError
  • test_unreadable_settings_never_restore_enabled_defaults[{"github":{"enabled":[]}}]
    Error message
    Failed: DID NOT RAISE ValueError
  • test_unreadable_settings_never_restore_enabled_defaults[{"unknown":true}]
    Error message
    Failed: DID NOT RAISE ValueError
  • test_unreadable_settings_never_restore_enabled_defaults[{]
    Error message
    Failed: DID NOT RAISE ValueError
tools/test_verifier_sources.py9 known
  • test_frozen_verification_decisions_are_unchanged

    The verifier's readable answer was shortened (93976cde9): plain output starts with EVIDENCE instead of ASSURANCE, and frozen JSON decisions differ in note wording. Frozen fixtures need regeneration.

    Error message
    assert False
    [+2 more lines; full report in element text]
  • test_old_and_new_decisions_and_statuses_match[pinned---json]

    The verifier's readable answer was shortened (93976cde9): plain output starts with EVIDENCE instead of ASSURANCE, and frozen JSON decisions differ in note wording. Frozen fixtures need regeneration.

    Error message
    assert False
    [+3 more lines; full report in element text]
  • test_old_and_new_decisions_and_statuses_match[pinned---plain]

    The verifier's readable answer was shortened (93976cde9): plain output starts with EVIDENCE instead of ASSURANCE, and frozen JSON decisions differ in note wording. Frozen fixtures need regeneration.

    Error message
    assert False
    [+5 more lines; full report in element text]
  • test_old_and_new_decisions_and_statuses_match[unmet_tier---json]

    The verifier's readable answer was shortened (93976cde9): plain output starts with EVIDENCE instead of ASSURANCE, and frozen JSON decisions differ in note wording. Frozen fixtures need regeneration.

    Error message
    assert False
    [+3 more lines; full report in element text]
  • test_old_and_new_decisions_and_statuses_match[unmet_tier---plain]

    The verifier's readable answer was shortened (93976cde9): plain output starts with EVIDENCE instead of ASSURANCE, and frozen JSON decisions differ in note wording. Frozen fixtures need regeneration.

    Error message
    assert False
    [+5 more lines; full report in element text]
  • test_old_and_new_decisions_and_statuses_match[unpinned---json]

    The verifier's readable answer was shortened (93976cde9): plain output starts with EVIDENCE instead of ASSURANCE, and frozen JSON decisions differ in note wording. Frozen fixtures need regeneration.

    Error message
    assert False
    [+3 more lines; full report in element text]
  • test_old_and_new_decisions_and_statuses_match[unpinned---plain]

    The verifier's readable answer was shortened (93976cde9): plain output starts with EVIDENCE instead of ASSURANCE, and frozen JSON decisions differ in note wording. Frozen fixtures need regeneration.

    Error message
    assert False
    [+5 more lines; full report in element text]
  • test_old_verifier_accepts_new_archive_with_identical_signed_events

    The verifier's readable answer was shortened (93976cde9): plain output starts with EVIDENCE instead of ASSURANCE, and frozen JSON decisions differ in note wording. Frozen fixtures need regeneration.

    Error message
    assert False
    [+3 more lines; full report in element text]
  • test_review_modules_import_without_application_state

    The verifier's readable answer was shortened (93976cde9): plain output starts with EVIDENCE instead of ASSURANCE, and frozen JSON decisions differ in note wording. Frozen fixtures need regeneration.

    Error message
    AssertionError: assert False
    [+2 more lines; full report in element text]
tools/test_deletion_semantics.py8 known
  • test_deletion_of_subset_keeps_actor_and_whole_history_unknown[10--1000000000555]

    Expects the batch-deletion caveat "does not identify who deleted them, whether deletion applied to all participants…", shortened in 3f5f0fbcb. Pending decision: restore the caveat or update the test.

    Error message
    AssertionError: assert 'does not identify who deleted them' in 'Telegram reported several message IDs as deleted in one update.'
  • test_deletion_of_subset_keeps_actor_and_whole_history_unknown[10-55123]

    Expects the batch-deletion caveat "does not identify who deleted them, whether deletion applied to all participants…", shortened in 3f5f0fbcb. Pending decision: restore the caveat or update the test.

    Error message
    AssertionError: assert 'does not identify who deleted them' in 'Telegram reported several message IDs as deleted in one update.'
  • test_deletion_of_subset_keeps_actor_and_whole_history_unknown[15--1000000000555]

    Expects the batch-deletion caveat "does not identify who deleted them, whether deletion applied to all participants…", shortened in 3f5f0fbcb. Pending decision: restore the caveat or update the test.

    Error message
    AssertionError: assert 'does not identify who deleted them' in 'Telegram reported several message IDs as deleted in one update.'
  • test_deletion_of_subset_keeps_actor_and_whole_history_unknown[15-55123]

    Expects the batch-deletion caveat "does not identify who deleted them, whether deletion applied to all participants…", shortened in 3f5f0fbcb. Pending decision: restore the caveat or update the test.

    Error message
    AssertionError: assert 'does not identify who deleted them' in 'Telegram reported several message IDs as deleted in one update.'
  • test_deletion_of_subset_keeps_actor_and_whole_history_unknown[2--1000000000555]

    Expects the batch-deletion caveat "does not identify who deleted them, whether deletion applied to all participants…", shortened in 3f5f0fbcb. Pending decision: restore the caveat or update the test.

    Error message
    AssertionError: assert 'does not identify who deleted them' in 'Telegram reported several message IDs as deleted in one update.'
  • test_deletion_of_subset_keeps_actor_and_whole_history_unknown[2-55123]

    Expects the batch-deletion caveat "does not identify who deleted them, whether deletion applied to all participants…", shortened in 3f5f0fbcb. Pending decision: restore the caveat or update the test.

    Error message
    AssertionError: assert 'does not identify who deleted them' in 'Telegram reported several message IDs as deleted in one update.'
  • test_deletion_of_subset_keeps_actor_and_whole_history_unknown[9--1000000000555]

    Expects the batch-deletion caveat "does not identify who deleted them, whether deletion applied to all participants…", shortened in 3f5f0fbcb. Pending decision: restore the caveat or update the test.

    Error message
    AssertionError: assert 'does not identify who deleted them' in 'Telegram reported several message IDs as deleted in one update.'
  • test_deletion_of_subset_keeps_actor_and_whole_history_unknown[9-55123]

    Expects the batch-deletion caveat "does not identify who deleted them, whether deletion applied to all participants…", shortened in 3f5f0fbcb. Pending decision: restore the caveat or update the test.

    Error message
    AssertionError: assert 'does not identify who deleted them' in 'Telegram reported several message IDs as deleted in one update.'
tools/test_case_package.py2 known
  • test_package_contains_readable_report_files_and_explanations[ots]

    Expects the heading "Timestamp receipts (not verified)", renamed in the case package.

    Error message
    assert ('Timestamp receipts (not verified)' in '<!doctype html><html lang="en"><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src ...lank"></span></p><p>Date: <span class="blank"></span></p><p>Place: <span class="blank"></span></p></div></body></html>')
  • test_package_contains_readable_report_files_and_explanations[tsr]

    Expects the heading "Timestamp receipts (not verified)", renamed in the case package.

    Error message
    assert ('Timestamp receipts (not verified)' in '<!doctype html><html lang="en"><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src ...lank"></span></p><p>Date: <span class="blank"></span></p><p>Place: <span class="blank"></span></p></div></body></html>')
tools/test_session_import.py2 known
  • test_independent_login_browser[False]

    The sign-in form no longer has the "other sign-in methods" block (.other-sign-in, removed in 3f5f0fbcb); the browser test still follows the old flow.

    Error message
    playwright._impl._errors.TimeoutError: Locator.evaluate: Timeout 30000ms exceeded.
    Call log:
      - waiting for locator(".other-sign-in")
  • test_independent_login_browser[True]

    The sign-in form no longer has the "other sign-in methods" block (.other-sign-in, removed in 3f5f0fbcb); the browser test still follows the old flow.

    Error message
    playwright._impl._errors.TimeoutError: Locator.evaluate: Timeout 30000ms exceeded.
    Call log:
      - waiting for locator(".other-sign-in")
tools/test_verifier_dispatch.py2 known
  • test_direct_check_preserves_policy_and_archive_without_printing[tgwitness.verifier.cli]

    Same frozen verifier decisions as test_verifier_sources.

    Error message
    AssertionError: assert False
    [+2 more lines; full report in element text]
  • test_direct_check_preserves_policy_and_archive_without_printing[tgwitness.verify]

    Same frozen verifier decisions as test_verifier_sources.

    Error message
    AssertionError: assert False
    [+2 more lines; full report in element text]
addons/capture/tests/test_trusted_anchors.py1 known
  • test_cloudflare_queries_are_read_only_scoped_and_token_is_not_exported

    Expects "no proof of continuous presence"; the capture add-on now says "provider state sampled at the polled time".

    Error message
    AssertionError: assert 'no proof of continuous presence' in 'provider state sampled at the polled time'
tools/test_analyzer_graphs.py1 known
  • test_edges_cite_journal_records_across_chosen_chats

    Expects the contact-graph limit "does not mean there was no contact", removed after v0.9.3.

    Error message
    assert False
     +  where False = any(<generator object test_edges_cite_journal_records_across_chosen_chats.<locals>.<genexpr> at 0x7101b5b0b6b0>)
tools/test_analyzer_linking.py1 known
  • test_rotated_account_ranks_first_with_explanation_and_citations

    Expects the account-linking limit "not identification", removed after v0.9.3.

    Error message
    assert False
     +  where False = any(<generator object test_rotated_account_ranks_first_with_explanation_and_citations.<locals>.<genexpr> at 0x7101b638d2f0>)
tools/test_chat_export_integrity.py1 known
  • test_sparse_message_numbers_are_counted_without_expansion

    Missing-number counting now returns (numbers, count) instead of a sized collection; test not yet updated to the new API.

    Error message
    assert 2 == 1999999998
     +  where 2 = len((<tgwitness.message_numbers.MissingNumbers object at 0x7101a37e14c0>, 1))
tools/test_cli.py1 known
  • test_local_commands

    Expects the default workspace name "Main account"; it is now "Main workspace".

    Error message
    AssertionError: assert [{'workspace'...n workspace'}] == [{'workspace'...ain account'}]
      
      At index 0 diff: {'workspace': 'default', 'name': 'Main workspace'} != {'workspace': 'default', 'name': 'Main account'}
      Use -v to get more diff
tools/test_device_attribution.py1 known
  • test_the_dossier_counts_clients_sticker_sets_and_prepared_media

    Expects the wording "Metadata hypothesis about the client that encoded the file"; the dossier now says "Client that encoded the file, read from the file's own metadata".

    Error message
    assert 'Metadata hypothesis about the client that encoded the file' in "Client that encoded the file, read from the file's own metadata. A forwarded or re-uploaded file carries the encoder of whoever made it first."
tools/test_mtproto_forensics.py1 known
  • test_outbox_read_watermark_does_not_identify_a_person

    Expects the caveat that a read watermark does not identify a person, shortened in 3f5f0fbcb.

    Error message
    AssertionError: assert 'does not identify' in 'Observed outgoing read watermark.'
tools/test_verifier_comparison.py1 known
  • test_ots_structure_only_does_not_get_a_positive_indicator[unknown]

    Expects an OTS-structure-only receipt to be labelled unknown; it is now labelled synthetic.

    Error message
    AssertionError: assert 'unknown' in 'synthetic'
tools/test_watchlists.py1 known
  • test_terms_patterns_wallets_usernames_and_domains_are_matched

    Expects the watchlist-hit caveat "nothing about who wrote it", removed after v0.9.3.

    Error message
    assert False
     +  where False = all(<generator object test_terms_patterns_wallets_usernames_and_domains_are_matched.<locals>.<genexpr> at 0x7101b6be35a0>)

LIVE

Real accounts on a test server

Long runs with disposable test accounts and our own test chats: capture, export, independent verification. Account names, chats and message texts are not published. All live runs as JSON.

FinishedScenarioResultWhat was checked
2026-11-14 08:09 UTCOnline status after actionspassedWith hide-online on, the peer saw the account go offline 1.2 s after a panel action and stay offline. With it off (the default), the same action showed the account online for at least 40 s to anyone allowed to see its last seen.
2026-11-14 08:01 UTCSecret chat close, after the fixpassedTelegram does not notify the side that accepted a secret chat when the peer ends it (confirmed with two plain clients). Since 3a614fb78 TgWitness checks accepted chats with an invisible protocol no-op: the close was recorded 61 s after it happened, with the last time the chat was known open. The peer saw no typing, read or message.
2026-11-14 06:46 UTCSecret chat closefailedClosing on either side was not delivered by Telegram within 3 minutes: the peer saw no update. TgWitness records the close when it next tries to send, with the reason 'Telegram reports the chat no longer exists'.
2026-11-14 06:39 UTCGhost behaviourpassedNo read receipt for a direct message or for secret messages; no typing indicator before sending in a group or a secret chat; read-only mode refused a send and nothing reached the peer.
2026-11-14 06:34 UTCSecret chats, both directionspassedProtocol module installed from GitHub with its SHA-256 checked; an incoming request waited for manual accept; texts in both directions recorded exactly; timer, screenshot and deletion notices recorded with the earlier text kept; a PNG saved with the same SHA-256; no decryption failures.
2026-11-14 06:29 UTCOnline status after actionsnot observableThe test account hides last seen from everybody, so the peer only sees 'recently'; whether hide-online-after-actions works could not be observed from outside.
2026-11-14 05:36 UTCJournal export and offline verificationpassedA live test account exported its 67 MB signed journal; the bundled verifier exited 0; HTML and PDF reports were generated, including chats over time.
2026-11-14 04:53 UTCSame text in two test chatspassedAn identical message posted to two of our test chats was listed once under repeated texts, linked to both journal records.

HISTORY

Run after run

One column per tested commit, newest on the right. Select a column or a row for the full run. Archive of all 6 runs.

29741904d · 2026-11-14 06:11 UTC · 1,880 passed, 111 failed23c7cc65e · 2026-11-14 06:24 UTC · 1,912 passed, 79 faileddb86ca0b4 · 2026-11-14 06:35 UTC · 1,912 passed, 79 failed0911462bc · 2026-11-14 06:58 UTC · 1,912 passed, 79 failedc06a2ba5a · 2026-11-14 07:42 UTC · 1,909 passed, 152 failed3a614fb78 · 2026-11-14 08:29 UTC · 2,178 passed, 42 failed
passedknown failuresnew failures
FinishedCommitResultPassedFailed
2026-11-14 08:29 UTC3a614fb78 Detect secret chats the peer endedNew failures2,17842
2026-11-14 07:42 UTCc06a2ba5a Improve jurisdiction guidance and report recovery (#306)Passing, known failures listed1,909152
2026-11-14 06:58 UTC0911462bc Show the chosen chats and the account on the last setup step (#305)Passing, known failures listed1,91279
2026-11-14 06:35 UTCdb86ca0b4 Show a chat's charts and assessment on its first export page only (#304)Passing, known failures listed1,91279
2026-11-14 06:24 UTC23c7cc65e Label service messages in reports and tidy the chat list and account counters (#Passing, known failures listed1,91279
2026-11-14 06:11 UTC29741904d Show chat export progress by messages and translate its states (#301)New failures1,880111

Raw results: tgwitness-tests-3a614fb780cd.tar.gz (all three) · summary.json · junit.xml · pytest.log · archive of all runs