Skip to content

Commit

Permalink
feat: Mock SystemTime::now() for the tests
Browse files Browse the repository at this point in the history
Add a fake `struct SystemTime` for mocking `SystemTime::now()` etc. for test purposes. One still
needs to use `std::time::SystemTime` as a struct representing a system time. I think such a
minimalistic approach is ok -- even if somebody uses the original `SystemTime::elapsed()` or `now()`
instead of mocks by mistake, that could break only tests but not the program itself. The worst thing
that can happen is that tests using `SystemTime::shift()` and checking messages timestamps
f.e. wouldn't catch the corresponding bugs, but now we don't have such tests at all which is much
worse.
  • Loading branch information
iequidoo committed Dec 16, 2023
1 parent d7f8d17 commit 0029cfc
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 17 deletions.
6 changes: 3 additions & 3 deletions src/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::convert::{TryFrom, TryInto};
use std::fmt;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::time::{Duration, SystemTime};
use std::time::Duration;

use anyhow::{anyhow, bail, ensure, Context as _, Result};
use deltachat_derive::{FromSql, ToSql};
Expand Down Expand Up @@ -44,7 +44,7 @@ use crate::sync::{self, Sync::*, SyncData};
use crate::tools::{
buf_compress, create_id, create_outgoing_rfc724_mid, create_smeared_timestamp,
create_smeared_timestamps, get_abs_path, gm2local_offset, improve_single_line_input,
smeared_time, strip_rtlo_characters, time, IsNoneOrEmpty,
smeared_time, strip_rtlo_characters, time, IsNoneOrEmpty, SystemTime,
};
use crate::webxdc::WEBXDC_SUFFIX;

Expand Down Expand Up @@ -3637,7 +3637,7 @@ pub enum MuteDuration {
Forever,

/// Chat is muted for a limited period of time.
Until(SystemTime),
Until(std::time::SystemTime),
}

impl rusqlite::types::ToSql for MuteDuration {
Expand Down
4 changes: 2 additions & 2 deletions src/contact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::convert::{TryFrom, TryInto};
use std::fmt;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::time::{SystemTime, UNIX_EPOCH};
use std::time::UNIX_EPOCH;

use anyhow::{bail, ensure, Context as _, Result};
use async_channel::{self as channel, Receiver, Sender};
Expand Down Expand Up @@ -35,7 +35,7 @@ use crate::sql::{self, params_iter};
use crate::sync::{self, Sync::*, SyncData};
use crate::tools::{
duration_to_str, get_abs_path, improve_single_line_input, strip_rtlo_characters, time,
EmailAddress,
EmailAddress, SystemTime,
};
use crate::{chat, stock_str};

Expand Down
4 changes: 2 additions & 2 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1051,7 +1051,7 @@ pub fn get_version_str() -> &'static str {

#[cfg(test)]
mod tests {
use std::time::{Duration, SystemTime};
use std::time::Duration;

use anyhow::Context as _;
use strum::IntoEnumIterator;
Expand All @@ -1067,7 +1067,7 @@ mod tests {
use crate::message::{Message, Viewtype};
use crate::receive_imf::receive_imf;
use crate::test_utils::TestContext;
use crate::tools::create_outgoing_rfc724_mid;
use crate::tools::{create_outgoing_rfc724_mid, SystemTime};

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_wrong_db() -> Result<()> {
Expand Down
4 changes: 2 additions & 2 deletions src/ephemeral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ use std::collections::BTreeSet;
use std::convert::{TryFrom, TryInto};
use std::num::ParseIntError;
use std::str::FromStr;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use std::time::{Duration, UNIX_EPOCH};

use anyhow::{ensure, Result};
use async_channel::Receiver;
Expand All @@ -85,7 +85,7 @@ use crate::message::{Message, MessageState, MsgId, Viewtype};
use crate::mimeparser::SystemMessage;
use crate::sql::{self, params_iter};
use crate::stock_str;
use crate::tools::{duration_to_str, time};
use crate::tools::{duration_to_str, time, SystemTime};

/// Ephemeral timer value.
#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize)]
Expand Down
6 changes: 3 additions & 3 deletions src/sql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::message::{Message, MsgId, Viewtype};
use crate::param::{Param, Params};
use crate::peerstate::{deduplicate_peerstates, Peerstate};
use crate::stock_str;
use crate::tools::{delete_file, time};
use crate::tools::{delete_file, time, SystemTime};

/// Extension to [`rusqlite::ToSql`] trait
/// which also includes [`Send`] and [`Sync`].
Expand Down Expand Up @@ -857,9 +857,9 @@ pub async fn remove_unused_files(context: &Context) -> Result<()> {
Ok(mut dir_handle) => {
/* avoid deletion of files that are just created to build a message object */
let diff = std::time::Duration::from_secs(60 * 60);
let keep_files_newer_than = std::time::SystemTime::now()
let keep_files_newer_than = SystemTime::now()
.checked_sub(diff)
.unwrap_or(std::time::SystemTime::UNIX_EPOCH);
.unwrap_or(SystemTime::UNIX_EPOCH);

while let Ok(Some(entry)) = dir_handle.next_entry().await {
let name_f = entry.file_name();
Expand Down
3 changes: 2 additions & 1 deletion src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ impl Context {

#[cfg(test)]
mod tests {
use std::time::{Duration, SystemTime};
use std::time::Duration;

use anyhow::bail;

Expand All @@ -329,6 +329,7 @@ mod tests {
use crate::contact::{Contact, Origin};
use crate::test_utils::TestContext;
use crate::token::Namespace;
use crate::tools::SystemTime;

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_config_sync_msgs() -> Result<()> {
Expand Down
6 changes: 3 additions & 3 deletions src/timesmearing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,11 @@ impl SmearedTimestamp {

#[cfg(test)]
mod tests {
use std::time::SystemTime;

use super::*;
use crate::test_utils::TestContext;
use crate::tools::{create_smeared_timestamp, create_smeared_timestamps, smeared_time, time};
use crate::tools::{
create_smeared_timestamp, create_smeared_timestamps, smeared_time, time, SystemTime,
};

#[test]
fn test_smeared_timestamp() {
Expand Down
33 changes: 32 additions & 1 deletion src/tools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ use std::io::{Cursor, Write};
use std::mem;
use std::path::{Path, PathBuf};
use std::str::from_utf8;
#[cfg(test)]
use std::sync::RwLock;
// `std::time::Instant` may use `libc::clock_gettime(CLOCK_MONOTONIC)`, e.g. on Android, and does
// not advance while being in deep sleep mode, so use `SystemTime` for now. When the issue on
// Android will be solved, we can switch to the true `Instant` easily.
pub use std::time::SystemTime as Instant;
use std::time::{Duration, SystemTime};
use std::time::{Duration, SystemTimeError};

use anyhow::{bail, Context as _, Result};
use base64::Engine as _;
Expand Down Expand Up @@ -479,6 +481,35 @@ pub async fn read_dir(path: &Path) -> Result<Vec<fs::DirEntry>> {
Ok(res)
}

#[cfg(test)]
static SYSTEM_TIME_SHIFT: RwLock<Duration> = RwLock::new(Duration::new(0, 0));

/// Fake struct for mocking `SystemTime::now()` etc. for test purposes. You still need to use
/// `std::time::SystemTime` as a struct representing a system time.
pub(crate) struct SystemTime();

impl SystemTime {
pub const UNIX_EPOCH: std::time::SystemTime = std::time::SystemTime::UNIX_EPOCH;

#[allow(unused)]
pub fn elapsed(t: &std::time::SystemTime) -> Result<Duration, SystemTimeError> {
Self::now().duration_since(*t)
}

pub fn now() -> std::time::SystemTime {
#[cfg(not(test))]
return std::time::SystemTime::now();
#[cfg(test)]
return std::time::SystemTime::now() + *SYSTEM_TIME_SHIFT.read().unwrap();
}

/// Simulates a system clock forward adjustment by `duration`.
#[cfg(test)]
pub fn shift(duration: Duration) {
*SYSTEM_TIME_SHIFT.write().unwrap() += duration;
}
}

pub(crate) fn time() -> i64 {
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
Expand Down

0 comments on commit 0029cfc

Please sign in to comment.