From ac8fa81ec48faf9dddfadb7d314bf5da7a45d42f Mon Sep 17 00:00:00 2001 From: link2xt Date: Wed, 16 Sep 2026 16:16:51 +0000 Subject: [PATCH] test: add pseudo transport explicitly rather than by setting ConfiguredAddr ConfiguredAddr is going to be removed, but we need to be able to add fake transports, also for existing offline Python tests. --- deltachat-ffi/deltachat.h | 15 ++++++++ deltachat-ffi/src/lib.rs | 16 +++++++++ python/src/deltachat/testplugin.py | 5 +++ src/config.rs | 57 ++++++++++++------------------ src/configure.rs | 2 +- src/key.rs | 4 +++ src/lib.rs | 2 +- src/pgp/pgp_tests.rs | 4 +++ src/test_utils.rs | 3 ++ src/transport.rs | 2 +- 10 files changed, 73 insertions(+), 37 deletions(-) diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 602e2597c7..005905e74d 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -693,6 +693,21 @@ char* dc_get_connectivity_html (dc_context_t* context); void dc_configure (dc_context_t* context); +/** + * Add fake transport that cannot be used to connect. + * + * Used for offline tests only. + * + * To add a transport, use JSON-RPC calls `add_or_update_transport` + * and `add_transport_from_qr` instead. + * + * @memberof dc_context_t + * @param context The context object. + * @param addr The email address of the new transport. + */ +void dc_add_pseudo_transport (dc_context_t* context, const char *addr); + + /** * Check if the context is already configured. * diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index a96e4e0cb0..d133359775 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -31,6 +31,7 @@ use deltachat::key::preconfigure_keypair; use deltachat::message::MsgId; use deltachat::qr_code_generator::{create_qr_svg, generate_backup_qr, get_securejoin_qr_svg}; use deltachat::stock_str::StockMessage; +use deltachat::transport::add_pseudo_transport; use deltachat::webxdc::StatusUpdateSerial; use deltachat::*; use deltachat::{accounts::Accounts, log::LogExt}; @@ -414,6 +415,21 @@ pub unsafe extern "C" fn dc_configure(context: *mut dc_context_t) { spawn_configure(ctx.clone()); } +#[unsafe(no_mangle)] +pub unsafe extern "C" fn dc_add_pseudo_transport( + context: *mut dc_context_t, + addr: *const libc::c_char, +) { + if context.is_null() { + eprintln!("ignoring careless call to dc_add_pseudo_transport()"); + return; + } + + let ctx = unsafe { &*context }; + let addr = to_string_lossy(addr); + block_on(add_pseudo_transport(ctx, &addr)).log_err(ctx).ok(); +} + #[unsafe(no_mangle)] pub unsafe extern "C" fn dc_is_configured(context: *mut dc_context_t) -> libc::c_int { if context.is_null() { diff --git a/python/src/deltachat/testplugin.py b/python/src/deltachat/testplugin.py index 943d055010..7dab54298e 100644 --- a/python/src/deltachat/testplugin.py +++ b/python/src/deltachat/testplugin.py @@ -11,6 +11,9 @@ from queue import Queue from typing import Callable, Dict, List, Optional +from .capi import lib +from .cutil import as_dc_charpointer + import pytest from _pytest._code import Source @@ -366,6 +369,7 @@ def get_pseudo_configured_account(self, passphrase: Optional[str] = None) -> Acc ac.open(passphrase) acname = ac._logid addr = f"{acname}@offline.org" + lib.dc_add_pseudo_transport(ac._dc_context, as_dc_charpointer(addr)) ac.update_config( { "configured_addr": addr, @@ -374,6 +378,7 @@ def get_pseudo_configured_account(self, passphrase: Optional[str] = None) -> Acc ) self._preconfigure_key(ac) self._acsetup.init_logging(ac) + assert ac.is_configured(), "Pseudo configured account should look like if it is configured" return ac def new_online_configuring_account(self, cloned_from=None, **kwargs) -> Account: diff --git a/src/config.rs b/src/config.rs index 966484f7b0..12ab9f45ae 100644 --- a/src/config.rs +++ b/src/config.rs @@ -19,7 +19,7 @@ use crate::log::LogExt; use crate::mimefactory::RECOMMENDED_FILE_SIZE; use crate::sync::{self, Sync::*, SyncData}; use crate::tools::get_abs_path; -use crate::transport::{add_pseudo_transport, transport_addrs}; +use crate::transport::transport_addrs; use crate::{constants, stats}; /// The available configuration keys. @@ -753,39 +753,28 @@ impl Context { bail!("Cannot unset configured_addr"); }; - if !self.is_configured().await? { - info!( - self, - "Creating a pseudo configured account which will not be able to send or receive messages. Only meant for tests!" - ); - add_pseudo_transport(self, addr).await?; - self.sql - .set_raw_config(Config::ConfiguredAddr.as_ref(), Some(addr)) - .await?; - } else { - self.sql - .transaction(|transaction| { - if transaction.query_row( - "SELECT COUNT(*) FROM transports WHERE addr=?", - (addr,), - |row| { - let res: i64 = row.get(0)?; - Ok(res) - }, - )? == 0 - { - bail!("Address does not belong to any transport."); - } - transaction.execute( - "UPDATE config SET value=? WHERE keyname='configured_addr'", - (addr,), - )?; - - Ok(()) - }) - .await?; - self.sql.uncache_raw_config("configured_addr").await; - } + self.sql + .transaction(|transaction| { + if transaction.query_row( + "SELECT COUNT(*) FROM transports WHERE addr=?", + (addr,), + |row| { + let res: i64 = row.get(0)?; + Ok(res) + }, + )? == 0 + { + bail!("Address does not belong to any transport."); + } + transaction.execute( + "INSERT OR REPLACE INTO config (keyname, value) VALUES ('configured_addr', ?)", + (addr,), + )?; + + Ok(()) + }) + .await?; + self.sql.uncache_raw_config("configured_addr").await; } _ => { self.sql.set_raw_config(key.as_ref(), value).await?; diff --git a/src/configure.rs b/src/configure.rs index d9a83d7a8e..bb436b3cf3 100644 --- a/src/configure.rs +++ b/src/configure.rs @@ -715,7 +715,7 @@ mod tests { let mut tcm = TestContextManager::new(); let t = &tcm.unconfigured().await; - // Setting ConfiguredAddr on an unconfigured account creates a pseudo transport + add_pseudo_transport(t, "primary@example.org").await?; t.set_config(Config::ConfiguredAddr, Some("primary@example.org")) .await?; assert_eq!(t.count_transports().await?, 1); diff --git a/src/key.rs b/src/key.rs index 997fb9e6d8..e7d69eb5fe 100644 --- a/src/key.rs +++ b/src/key.rs @@ -662,6 +662,7 @@ mod tests { use crate::config::Config; use crate::test_utils::{TestContext, TestContextManager, alice_keypair}; use crate::tools::SystemTime; + use crate::transport::add_pseudo_transport; static KEYPAIR: LazyLock = LazyLock::new(alice_keypair); @@ -811,6 +812,7 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_load_self_generate_public() { let t = TestContext::new().await; + add_pseudo_transport(&t, "alice@example.org").await.unwrap(); t.set_config(Config::ConfiguredAddr, Some("alice@example.org")) .await .unwrap(); @@ -821,6 +823,7 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_load_self_generate_secret() { let t = TestContext::new().await; + add_pseudo_transport(&t, "alice@example.org").await.unwrap(); t.set_config(Config::ConfiguredAddr, Some("alice@example.org")) .await .unwrap(); @@ -833,6 +836,7 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD use std::thread; let t = TestContext::new().await; + add_pseudo_transport(&t, "alice@example.org").await.unwrap(); t.set_config(Config::ConfiguredAddr, Some("alice@example.org")) .await .unwrap(); diff --git a/src/lib.rs b/src/lib.rs index d430487f76..c4ec71e8aa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -97,7 +97,7 @@ pub mod stock_str; pub mod storage_usage; mod sync; mod token; -mod transport; +pub mod transport; mod update_helper; pub mod webxdc; #[macro_use] diff --git a/src/pgp/pgp_tests.rs b/src/pgp/pgp_tests.rs index bd2b617671..3649bc6323 100644 --- a/src/pgp/pgp_tests.rs +++ b/src/pgp/pgp_tests.rs @@ -2,6 +2,7 @@ use std::sync::LazyLock; use tokio::sync::OnceCell; use super::*; +use crate::transport::add_pseudo_transport; use crate::{ config::Config, decrypt, @@ -19,6 +20,9 @@ async fn decrypt_bytes( auth_tokens_for_decryption: &[String], ) -> Result> { let t = &TestContext::new().await; + add_pseudo_transport(t, "alice@example.org") + .await + .expect("Failed to add pseudo transport"); t.set_config(Config::ConfiguredAddr, Some("alice@example.org")) .await .expect("Failed to configure address"); diff --git a/src/test_utils.rs b/src/test_utils.rs index d31cc83218..52e7c29fbd 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -557,6 +557,9 @@ impl TestContext { /// The context will be configured but the key will not be pre-generated so if a key is /// used the fingerprint will be different every time. pub async fn configure_addr(&self, addr: &str) { + add_pseudo_transport(&self.ctx, addr) + .await + .expect("Failed to add pseudo transport"); self.ctx .set_config(Config::ConfiguredAddr, Some(addr)) .await diff --git a/src/transport.rs b/src/transport.rs index 9d07675c85..b16151f09c 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -765,7 +765,7 @@ pub(crate) fn maybe_update_sending_transport( } /// Adds transport entry to the `transports` table with empty configuration. -pub(crate) async fn add_pseudo_transport(context: &Context, addr: &str) -> Result<()> { +pub async fn add_pseudo_transport(context: &Context, addr: &str) -> Result<()> { context.sql .execute( "INSERT OR IGNORE INTO transports (addr, entered_param, configured_param) VALUES (?, ?, ?)",