diff --git a/deltachat-ffi/deltachat.h b/deltachat-ffi/deltachat.h index 3898b5586..8fc483a72 100644 --- a/deltachat-ffi/deltachat.h +++ b/deltachat-ffi/deltachat.h @@ -405,9 +405,14 @@ char* dc_get_config (dc_context_t* context, const char* /** * Get information about the context. + * * The information is returned by a multi-line string * and contains information about the current configuration. * + * If the context is not open or configured only a subset of the information + * will be available. There is no guarantee about which information will be + * included when however. + * * @memberof dc_context_t * @param context The context as created by dc_context_new(). * @return String which must be free()'d after usage. Never returns NULL. diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 878222b7e..511fdbc94 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -347,9 +347,12 @@ pub unsafe extern "C" fn dc_get_info(context: *mut dc_context_t) -> *mut libc::c return dc_strdup(ptr::null()); } let ffi_context = &*context; - ffi_context - .with_inner(|ctx| render_info(ctx.get_info()).unwrap_or_default().strdup()) - .unwrap_or_else(|_| "".strdup()) + let guard = ffi_context.inner.read().unwrap(); + let info = match guard.as_ref() { + Some(ref ctx) => ctx.get_info(), + None => context::get_info(), + }; + render_info(info).unwrap_or_default().strdup() } fn render_info( diff --git a/python/tests/test_lowlevel.py b/python/tests/test_lowlevel.py index 08e30fbf2..09b696962 100644 --- a/python/tests/test_lowlevel.py +++ b/python/tests/test_lowlevel.py @@ -108,3 +108,25 @@ def test_provider_info(): def test_provider_info_none(): assert lib.dc_provider_new_from_email(cutil.as_dc_charpointer("email@unexistent.no")) == ffi.NULL + + +def test_get_info_closed(): + ctx = ffi.gc( + lib.dc_context_new(lib.py_dc_callback, ffi.NULL, ffi.NULL), + lib.dc_context_unref, + ) + info = cutil.from_dc_charpointer(lib.dc_get_info(ctx)) + assert 'deltachat_core_version' in info + assert 'database_dir' not in info + + +def test_get_info_open(tmpdir): + ctx = ffi.gc( + lib.dc_context_new(lib.py_dc_callback, ffi.NULL, ffi.NULL), + lib.dc_context_unref, + ) + db_fname = tmpdir.join("test.db") + lib.dc_open(ctx, db_fname.strpath.encode("ascii"), ffi.NULL) + info = cutil.from_dc_charpointer(lib.dc_get_info(ctx)) + assert 'deltachat_core_version' in info + assert 'database_dir' in info diff --git a/src/context.rs b/src/context.rs index 2b8da2174..de0bfdc0d 100644 --- a/src/context.rs +++ b/src/context.rs @@ -66,6 +66,30 @@ pub struct RunningState { pub shall_stop_ongoing: bool, } +/// Return some info about deltachat-core +/// +/// This contains information mostly about the library itself, the +/// actual keys and their values which will be present are not +/// guaranteed. Calling [Context::get_info] also includes information +/// about the context on top of the information here. +pub fn get_info() -> HashMap<&'static str, String> { + let mut res = HashMap::new(); + res.insert("deltachat_core_version", format!("v{}", &*DC_VERSION_STR)); + res.insert("sqlite_version", rusqlite::version().to_string()); + res.insert( + "sqlite_thread_safe", + unsafe { rusqlite::ffi::sqlite3_threadsafe() }.to_string(), + ); + res.insert( + "arch", + (::std::mem::size_of::<*mut libc::c_void>()) + .wrapping_mul(8) + .to_string(), + ); + res.insert("level", "awesome".into()); + res +} + impl Context { pub fn new(cb: Box, os_name: String, dbfile: PathBuf) -> Result { let mut blob_fname = OsString::new(); @@ -209,19 +233,7 @@ impl Context { .get_config(self, "configured_mvbox_folder") .unwrap_or_else(|| "".to_string()); - let mut res = HashMap::new(); - res.insert("deltachat_core_version", format!("v{}", &*DC_VERSION_STR)); - res.insert("sqlite_version", rusqlite::version().to_string()); - res.insert( - "sqlite_thread_safe", - unsafe { rusqlite::ffi::sqlite3_threadsafe() }.to_string(), - ); - res.insert( - "arch", - (::std::mem::size_of::<*mut libc::c_void>()) - .wrapping_mul(8) - .to_string(), - ); + let mut res = get_info(); res.insert("number_of_chats", chats.to_string()); res.insert("number_of_chat_messages", real_msgs.to_string()); res.insert("messages_in_contact_requests", deaddrop_msgs.to_string()); @@ -251,7 +263,6 @@ impl Context { pub_key_cnt.unwrap_or_default().to_string(), ); res.insert("fingerprint", fingerprint_str); - res.insert("level", "awesome".into()); res } @@ -504,6 +515,14 @@ mod tests { let t = dummy_context(); let info = t.ctx.get_info(); + assert!(info.get("database_dir").is_some()); + } + + #[test] + fn test_get_info_no_context() { + let info = get_info(); + assert!(info.get("deltachat_core_version").is_some()); + assert!(info.get("database_dir").is_none()); assert_eq!(info.get("level").unwrap(), "awesome"); } }