Skip to content
Merged
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
9 changes: 6 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,12 @@ jobs:
run: cargo clippy --all-targets --all-features -- -D warnings

# Integration tests against a live MISP instance
# Mirrors the MISP project's own CI setup from .github/workflows/main.yml
# Mirrors the MISP project's own CI setup from .github/workflows/main.yml.
# MISP core pairs each PHP version with the distro that ships its mod_php:
# 8.1 on jammy, 8.3 on noble. We install libapache2-mod-php8.3, so the
# runner must be 24.04 -- jammy has no php8.3 mod_php in its default repos.
integration-tests:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04

services:
mariadb:
Expand Down Expand Up @@ -134,7 +137,7 @@ jobs:

- name: Install system deps
run: |
sudo apt-get -y update
sudo apt-get -y update --allow-releaseinfo-change
sudo apt-get -y install curl python3 python3-pip python3-virtualenv \
apache2 libapache2-mod-php8.3

Expand Down
24 changes: 24 additions & 0 deletions tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,24 @@ fn unique(label: &str) -> String {
format!("RustMISP Test - {} - {}", label, uuid::Uuid::new_v4())
}

/// Wait until an event actually reports `published`.
///
/// CI runs MISP with SimpleBackgroundJobs and supervisor workers enabled, so
/// `EventsController::publish()` hands the work to `publishRouter()` and returns
/// "Job queued" immediately -- the `published` flag is set later by a worker.
/// Searching straight after `publish()` therefore races that worker.
async fn wait_until_published(client: &MispClient, event_id: i64) {
for _ in 0..60 {
if let Ok(ev) = client.get_event(event_id).await {
if ev.published {
return;
}
}
tokio::time::sleep(std::time::Duration::from_millis(500)).await;
}
panic!("event {event_id} was not published within 30s (background worker stuck?)");
}

/// Random octet for generating unique IPs in tests.
fn rand_octet() -> u8 {
(now_ts() as u8).wrapping_add(uuid::Uuid::new_v4().as_bytes()[0])
Expand Down Expand Up @@ -207,6 +225,11 @@ async fn test_event_crud_lifecycle() {

// --- PUBLISH / UNPUBLISH ---
client.publish(event_id, false).await.expect("publish");
// publish() only queues the job, so read back through the same wait the
// search test uses. This also settles the worker before the unpublish
// below: without it the worker can set `published` back to true after
// unpublish() has run, which would fail the next assertion instead.
wait_until_published(&client, event_id).await;
let pub_ev = client.get_event(event_id).await.unwrap();
assert!(pub_ev.published);

Expand Down Expand Up @@ -899,6 +922,7 @@ async fn test_search_publish_and_metadata() {

// Publish ev1, then search published only
client.publish(ev1_id, false).await.expect("publish");
wait_until_published(&client, ev1_id).await;
let params = SearchParameters {
timestamp: Some(Value::from(ts)),
published: Some(true),
Expand Down
Loading