# Prosody 13.0.6 Test Run Report ## Summary | Run | Passed | Skipped | Failed | |-----|--------|---------|--------| | Compose harness (`run-compose-tests.sh`) | 80 | 6 | 0 | | External deployment (`run-all-tests.sh`) | 50 | 36 | 0 | | **Combined unique coverage** | **81** | **5** | **0** | **Zero failures in both runs.** The compose log predates the carbons test enhancement (the test was still skipping); the external log is post-fix (carbons test passed). The external run had 11 extra skips because the SSH tunnel to PostgreSQL was stale (port open but connection dead), and 5 extra skips because `MOCK_URL` is not set on the external deployment. **Environment:** Prosody 13.0.6, Lua 5.4.8, Alpine 3.23.4, PostgreSQL 15. --- ## All Passed Tests (81 unique) ### test_01_core — Core XMPP (12 passed) | Test | Verifies | |------|----------| | `test_connect_and_auth` | Client connects and authenticates via c2s with TLS | | `test_disco_info_server` | Server domain advertises `disco#info` and `disco#items` features | | `test_disco_info_account` | Account disco advertises MAM (`urn:xmpp:mam:2`) and stanza-id (`urn:xmpp:sid:0`) | | `test_mam_available` | MAM preferences query succeeds (XEP-0313) | | `test_carbons_enable` | Carbons enable IQ succeeds (XEP-0280) | | `test_bosh_url_reachable` | BOSH HTTP endpoint responds | | `test_websocket_url_reachable` | WebSocket HTTP endpoint responds | | `test_rest_accepts_xml` | `POST /rest` with valid XML returns 201/422 | | `test_rest_rejects_non_xml` | `POST /rest` with non-XML body returns 415/422 | | `test_rest_message_archived_in_sender_mam` | REST-injected message appears in sender's MAM archive (mod_mam `vnc-rest-message` hook + `store_user` inversion patch) | | `test_rest_message_to_non_roster_contact_is_archived` | REST message to a non-roster contact is archived (`shall_store` always returns `true`) | | `test_rest_message_carbon_copied_to_second_resource` | REST-injected message is carbon-copied to a second resource of the same bare JID (mod_carbons `vnc-rest-message` hook) — **external only** | ### test_02_muc — MUC / Group Chat (9 passed) | Test | Verifies | |------|----------| | `test_muc_component_disco` | MUC component advertises `muc` and `mam:2` features | | `test_room_hidden_by_default` | Newly created rooms don't appear in `disco#items`; room advertises `muc_hidden` not `muc_public` (hidden.lib patch) | | `test_muc_mam_query_returns_groupchat_only` | MUC MAM query returns only `groupchat` messages, no presence | | `test_muc_broadcast_strips_spoofed_stanza_id` | A spoofed `` in a groupchat message is stripped before broadcast | | `test_muc_automember_with_distinct_account` | Room owner can set affiliation for a non-present user (mod_vnc_muc_automember) | | `test_muc_unregister_iq_removes_affiliation` | `iq-set` with `xmpp:vnctalk:unregister` removes affiliation and fires `vnc-muc-kick` (register.lib + mod_muc patches) | | `test_muc_mam_presence_not_archived` | MUC MAM does not archive presence stanzas (only messages with bodies) | | `test_muc_vdata_disco` | MUC room advertises `xmpp:vnctalk:vdata` in disco#info | | `test_muc_vcard_get_set` | MUC vCard get/set round-trip works (mod_vcard_muc) | ### test_03_vnctalk — VNCtalk Extensions (9 passed) | Test | Verifies | |------|----------| | `test_vcard_avatar_upload_trigger` | Setting a vCard with PHOTO triggers an HTTP PUT to `avatar_upload_url` (mod_vnc_vcard_avatar) | | `test_timestamp_added` | Outgoing messages get a `` element (mod_vnc_timestamp) | | `test_receipts_archive` | Messages with receipt requests are archived in the `receipts` store (mod_vnc_receipts) | | `test_broadcast_component` | `broadcast@domain` component responds to disco#info (mod_vnc_broadcast) | | `test_http_upload_external_disco` | HTTP upload external slot handshake works (mod_http_upload_external) | | `test_open_host_store_smoke` | MUC component can open stores on the main virtual host via `storagemanager.open()` (mod_vnc_muc_fcm) | | `test_muc_e2e_config_field` | MUC room config form includes the `xmpp:vnctalk:e2e` field | | `test_muc_data_broadcast_on_config_change` | Room config changes broadcast an `xmpp:vnctalk:update` message with affiliations and data (mod_vnc_muc_data) | | `test_muc_hook_notifies_nonjoined_affiliate` | A non-joined affiliated member receives MUC notifications (mod_vnc_muc_hook) | ### test_04_infra — Infrastructure (6 passed) | Test | Verifies | |------|----------| | `test_telnet_port_open` | Admin telnet port 5582 accepts TCP connections | | `test_telnet_banner` | Telnet sends a Prosody banner | | `test_healthcheck_script_exists` | `healthcheck.sh` exists in the image | | `test_healthcheck_exits_two_on_cert_mismatch` | Healthcheck source contains the exit-2-on-cert-mismatch logic | | `test_c2s_port_open` | c2s port 5222 accepts TCP connections | | `test_http_port_open` | HTTP port 5280 accepts TCP connections | ### test_05_patches — Patch Verification (5 passed) | Test | Verifies | |------|----------| | `test_unique_iq_to_bare_jid_returns_item_not_found` | `iq-get` muc#unique to a bare JID returns `item-not-found` (mod_muc_unique patch) | | `test_non_admin_cannot_make_room_public` | Non-admin cannot make a room public when `restrict_public` is active (hidden.lib patch) | | `test_large_stanza_not_truncated` | A stanza > 4096 bytes is delivered without truncation (portmanager `network_default_read_size` = 8192) | | `test_offline_affiliate_receives_message` | Offline remote affiliated members receive MUC messages (muc.lib broadcast patch) | | `test_self_unavailable_not_routed_on_leave` | Unavailable self-presence is not routed to the leaving occupant (muc.lib `publicise_occupant_status` patch) | ### test_06_postgres — PostgreSQL Storage (11 passed, compose only) | Test | Verifies | |------|----------| | `test_connection` | PostgreSQL connection succeeds | | `test_prosody_tables_exist` | `prosody` key-value table exists | | `test_archive_table_exists` | `prosodyarchive` table exists | | `test_muc_log_store_exists` | MUC log data is stored under the `conference.` host | | `test_archive_has_required_columns` | `prosodyarchive` has all required columns (host, user, store, key, when, with, type, value) | | `test_muc_log_stored_under_conference_host` | MUC MAM entries have `host = conference.example.com` | | `test_vcard_store_exists` | vCard store exists in the `prosody` table | | `test_rest_message_archived_under_sender` | REST-injected message is archived under the sender's user row, not the recipient's (mod_mam `vnc_rest` store-user inversion) | | `test_kick_store_exists` | Kick store exists in `prosodyarchive` with `store = 'kick'` | | `test_kick_writes_fresh_row` | MUC unregister IQ writes a kick row to the archive (mod_vnc_track_kicks + register.lib patch + `default_storage = "sql"` for the kick store) | | `test_activity_store_exists` | Activity store exists in the `prosody` table | ### test_07_module_load — Module Load Detection (5 passed) | Test | Verifies | |------|----------| | `test_mod_vnc_lastactivity_loaded` | `mod_vnc_lastactivity` is loaded and hooks `iq-get` for last activity | | `test_mod_vnc_delfile_message_hook_present` | `mod_vnc_delfile` hooks `message` for file deletion | | `test_mod_vnc_remotemucstore_message_hook_present` | `mod_vnc_remotemucstore` hooks `message` for remote MUC archiving | | `test_mod_vnc_remotemucinvite_event_handler_present` | `mod_vnc_remotemucinvite` handles MUC invite events | | `test_mod_vnc_track_kicks_event_handler_present` | `mod_vnc_track_kicks` hooks `vnc-muc-kick` event | ### test_08_image_patches — Image Patch Application (9 passed, compose only) | Test | Verifies | |------|----------| | `mod_mam_has_vnc_rest_message` | `vnc-rest-message` hook present in mod_mam.lua | | `vnc_muc_fcm_uses_storagemanager` | `storagemanager.open` call present in mod_vnc_muc_fcm.lua (replaces dropped moduleapi patch) | | `register_lib_has_vnc_muc_kick` | `vnc-muc-kick` event present in register.lib.lua | | `config_has_console_interfaces` | `console_interfaces` in rendered config (replaces dropped mod_admin_telnet patch) | | `config_has_http_interfaces` | `http_interfaces` in rendered config (replaces dropped portmanager patch) | | `portmanager_uses_network_default_read_size` | `network_default_read_size` recognized by portmanager.lua | | `mod_carbons_has_vnc_rest_hook` | `vnc-rest-message` hook present in mod_carbons.lua | | `hidden_lib_present` | `muc_room_allow_public` config option present in hidden.lib.lua | | `mod_muc_unique_has_handle_iq_tobare` | `handle_iq_tobare` function present in mod_muc_unique.lua | ### test_09_http_sideeffects — HTTP Side-Effects (5 passed, compose only) | Test | Verifies | |------|----------| | `test_fcm_push_on_chat_to_registered_recipient` | Chat message to an offline user triggers an FCM push POST (mod_vnc_fcm) | | `test_muc_fcm_push_to_offline_member` | Groupchat message triggers FCM push to non-joined affiliated members (mod_vnc_muc_fcm) | | `test_delfile_http_post_on_replace` | Message correction (``) triggers a DELETE request to `del_api_url` (mod_vnc_delfile) | | `test_avatar_upload_on_vcard_photo` | vCard set with PHOTO triggers an HTTP PUT to `avatar_upload_url` (mod_vnc_vcard_avatar) | | `test_receipt_archived_in_receipts_store` | Messages with receipt requests are archived in the `receipts` store (mod_vnc_receipts) | ### test_10_smacks — Stream Management (2 passed) | Test | Verifies | |------|----------| | `test_smacks_enable_and_ack` | SMACKS enable + / ack round-trip works (XEP-0198) | | `test_smacks_resume_replays_queue` | SMACKS resume with a short disconnect replays unacked stanzas | ### test_11_smokes — Smoke Tests (4 passed in compose, 2 in external) | Test | Verifies | |------|----------| | `test_chatstate_dropped_when_inactive` | Chat states (``) are dropped when recipient is inactive (mod_filter_chatstates) | | `test_idle_injected_into_last_activity_presence` | Idle timestamp is injected into last-activity presence (mod_idlecompat) | | `test_host_meta_json_advertises_alt_connections` | `/.well-known/host-meta.json` advertises WebSocket alt-connections (mod_http_altconnect) — **compose only** | | `test_presence_endpoint_returns_image` | `/status/` returns an image (mod_webpresence) — **compose only** | ### test_12_image_runtime — Image Runtime (4 passed, compose only) | Test | Verifies | |------|----------| | `test_http_upload_slot_handshake` | HTTP upload external slot handshake works inside the running container | | `test_healthcheck_exit2_on_cert_mismatch` | `healthcheck.sh` exits 2 when a new TLS cert is present but not yet loaded | | `test_healthcheck_not_exit2_after_restore` | `healthcheck.sh` does not exit 2 after cert is restored | | `test_config_rendering_no_residual_placeholders` | Rendered config has no unsubstituted `${...}` placeholders | --- ## Skips (5 remaining after combining both runs) | Test | Reason | |------|--------| | `test_02_muc::test_hidden_lib_rejects_public_override` | Requires an admin JID; test user is not a server admin | | `test_03_vnctalk::test_vcard_fallback` | `mod_vnc_vcard_fallback` not enabled in config template | | `test_10_smacks::test_smacks_hibernation_expiry` | `smacks_hibernation_time` > 30s threshold (production default 300s; compose uses 10s but the test still skips) | | `test_10_smacks::test_smacks_offline_queue_after_expiry` | Same hibernation time threshold | | `test_11_smokes::test_telnet_reachable_on_non_loopback` | `ADMIN_TELNET_HOST` is loopback; can't prove wildcard bind from the same host | ### External-only skips (infrastructure prerequisites, not test gaps) | Category | Count | Reason | |----------|-------|--------| | `test_06_postgres` (all 11) | 11 | SSH tunnel to PostgreSQL was stale (port open but connection dead) | | `test_08_image_patches` (all 9) | 9 | Needs `docker compose exec` — external deployment is not a compose stack | | `test_09_http_sideeffects` (all 5) | 5 | Needs `MOCK_URL` — external deployment has real backends, not a capture mock | | `test_11_smokes` (2) | 2 | BOSH/WS URLs use default HTTPS port 443 without explicit `:port`; `_http_base()` requires an explicit port | | `test_12_image_runtime` (all 4) | 4 | Needs `docker compose exec` for healthcheck/config inspection | | `test_10_smacks` (2) | 2 | Hibernation time too large (>30s) | --- ## Conclusion All 81 tests that can run against either environment passed. Zero failures. The 5 remaining skips are: 2 require admin/module config changes, 2 require a low smacks hibernation time, and 1 requires a non-loopback telnet connection. None are regressions from the 0.11.6 → 13.0.6 upgrade.