Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions deltachat-jsonrpc/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,13 @@ impl CommandApi {
tokio::time::sleep(std::time::Duration::from_secs_f64(delay)).await
}

/// Emit the test checkpoint event, used for tests.
/// Returns a unique id of the emitted `TestCheckpointEvent`.
async fn trigger_checkpoint_event(&self, account_id: u32) -> Result<usize> {
let ctx = self.get_context(account_id).await?;
Ok(ctx.emit_test_checkpoint_event().await)
}

// ---------------------------------------------
// Misc top level functions
// ---------------------------------------------
Expand Down
8 changes: 8 additions & 0 deletions deltachat-jsonrpc/src/api/types/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,13 @@ pub enum EventType {
/// If `chat_id` is set to None, then all currently visible chats need to be rerendered, and all not-visible items need to be cleared from cache if the UI has a cache.
#[serde(rename_all = "camelCase")]
ChatlistItemChanged { chat_id: Option<u32> },

/// Tests can trigger this event and then wait for it, to make sure all events before it were consumed.
/// Useful for tests that test whether a specific event is emitted,
TestCheckpointEvent {
/// unique id to recognize the event
id: usize,
},
}

impl From<CoreEventType> for EventType {
Expand Down Expand Up @@ -370,6 +377,7 @@ impl From<CoreEventType> for EventType {
chat_id: chat_id.map(|id| id.to_u32()),
},
CoreEventType::ChatlistChanged => ChatlistChanged,
CoreEventType::TestCheckpointEvent { id } => TestCheckpointEvent { id },
}
}
}
1 change: 1 addition & 0 deletions deltachat-rpc-client/src/deltachat_rpc_client/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class EventType(str, Enum):
WEBXDC_INSTANCE_DELETED = "WebxdcInstanceDeleted"
CHATLIST_CHANGED = "ChatlistChanged"
CHATLIST_ITEM_CHANGED = "ChatlistItemChanged"
TEST_CHECKPOINT_EVENT = "TestCheckpointEvent"


class ChatId(IntEnum):
Expand Down
15 changes: 8 additions & 7 deletions deltachat-rpc-client/src/deltachat_rpc_client/rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
import os
import subprocess
import sys
from queue import Empty, Queue
from queue import Queue
from threading import Event, Thread
from typing import Any, Iterator, Optional

from .const import EventType


class JsonRpcError(Exception):
pass
Expand Down Expand Up @@ -190,12 +192,11 @@ def wait_for_event(self, account_id: int) -> Optional[dict]:

def clear_all_events(self, account_id: int):
"""Removes all queued-up events for a given account. Useful for tests."""
queue = self.get_queue(account_id)
try:
while True:
queue.get_nowait()
except Empty:
pass
id = self.trigger_checkpoint_event(account_id)
while True:
event = self.wait_for_event(account_id)
if event.kind == EventType.TEST_CHECKPOINT_EVENT and event.id == id:
break

def __getattr__(self, attr: str):
return RpcMethod(self, attr)
13 changes: 13 additions & 0 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,9 @@ pub struct InnerContext {

/// True if account has subscribed to push notifications via IMAP.
pub(crate) push_subscribed: AtomicBool,

/// Counter for the id for the test checkpoint event that is used by tests.
pub(crate) test_event_checkpoint_counter: Mutex<usize>,
}

/// The state of ongoing process.
Expand Down Expand Up @@ -445,6 +448,7 @@ impl Context {
debug_logging: std::sync::RwLock::new(None),
push_subscriber,
push_subscribed: AtomicBool::new(false),
test_event_checkpoint_counter: Mutex::new(0),
};

let ctx = Context {
Expand Down Expand Up @@ -1362,6 +1366,15 @@ impl Context {
wal_fname.push("-wal");
dbfile.with_file_name(wal_fname)
}

/// Emit the test checkpoint event, used for tests.
/// Returns a unique id of the emitted `TestCheckpointEvent`.
pub async fn emit_test_checkpoint_event(&self) -> usize {
let mut counter = self.inner.test_event_checkpoint_counter.lock().await;
*counter = counter.wrapping_add(1);
self.emit_event(EventType::TestCheckpointEvent { id: *counter });
*counter
}
}

/// Returns core version as a string.
Expand Down
7 changes: 7 additions & 0 deletions src/events/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,4 +302,11 @@ pub enum EventType {
/// ID of the changed chat
chat_id: Option<ChatId>,
},

/// Tests can trigger this event and then wait for it, to make sure all events before it were consumed.
/// Useful for tests that test whether a specific event is emitted,
TestCheckpointEvent {
/// unique id to recognize the event
id: usize,
},
}
11 changes: 11 additions & 0 deletions src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,17 @@ impl TestContext {

chat_id
}

/// Clears event queue.
/// Works by emitting a `TestCheckpointEvent` and consuming all events until.
/// times out after 10 seconds.
pub async fn clear_events(&self) {
let event_id = self.emit_test_checkpoint_event().await;
self.evtracker.get_matching(|ev| match ev {
EventType::TestCheckpointEvent { id } => event_id == *id,
_ => false
}).await;
}
}

impl Deref for TestContext {
Expand Down