mirror of
https://github.com/openai/codex.git
synced 2026-11-02 19:43:24 +00:00
Filter plugin-install test analytics by event type (#45515)
## Why The analytics test helper returned the first analytics request, which could contain unrelated events. Plugin-install assertions need to select the expected event even when it arrives in a later request or shares a batch with other events. ## What changed Update `wait_for_plugin_analytics_payload` to accept an event type, scan requests until matching events appear, and return the payload with only those events. Update callers to request `codex_plugin_installed` or `codex_plugin_install_failed` as appropriate. ## Testing Add a regression test that sends an unrelated analytics request followed by a mixed batch and verifies that the helper returns only the expected plugin-install failure event. GitOrigin-RevId: 41290c63ea1c2a3da1efa78b81222b8da76bcbff
This commit is contained in:
@@ -587,7 +587,7 @@ async fn plugin_install_tracks_analytics_when_remote_detail_fetch_fails() -> Res
|
||||
assert_eq!(err.error.code, -32600);
|
||||
assert!(err.error.message.contains("failed with status 404"));
|
||||
|
||||
let payload = wait_for_plugin_analytics_payload(&server).await?;
|
||||
let payload = wait_for_plugin_analytics_payload(&server, "codex_plugin_install_failed").await?;
|
||||
let event_params = &payload["events"][0]["event_params"];
|
||||
assert_eq!(
|
||||
payload["events"][0]["event_type"],
|
||||
@@ -659,7 +659,7 @@ async fn plugin_install_tracks_analytics_when_remote_install_is_rate_limited() -
|
||||
/*expected_count*/ 1,
|
||||
)
|
||||
.await?;
|
||||
let payload = wait_for_plugin_analytics_payload(&server).await?;
|
||||
let payload = wait_for_plugin_analytics_payload(&server, "codex_plugin_install_failed").await?;
|
||||
let event_params = &payload["events"][0]["event_params"];
|
||||
assert_eq!(
|
||||
payload["events"][0]["event_type"],
|
||||
@@ -734,7 +734,7 @@ async fn plugin_install_rejects_remote_plugin_disabled_by_admin_before_download(
|
||||
.join("plugins/cache/openai-curated-remote/linear")
|
||||
.exists()
|
||||
);
|
||||
let payload = wait_for_plugin_analytics_payload(&server).await?;
|
||||
let payload = wait_for_plugin_analytics_payload(&server, "codex_plugin_install_failed").await?;
|
||||
let event_params = &payload["events"][0]["event_params"];
|
||||
assert_eq!(
|
||||
payload["events"][0]["event_type"],
|
||||
@@ -783,7 +783,7 @@ async fn plugin_install_rejects_remote_plugin_not_available() -> Result<()> {
|
||||
/*expected_count*/ 0,
|
||||
)
|
||||
.await?;
|
||||
let payload = wait_for_plugin_analytics_payload(&server).await?;
|
||||
let payload = wait_for_plugin_analytics_payload(&server, "codex_plugin_install_failed").await?;
|
||||
let event_params = &payload["events"][0]["event_params"];
|
||||
assert_eq!(
|
||||
payload["events"][0]["event_type"],
|
||||
@@ -872,7 +872,8 @@ async fn plugin_install_tracks_analytics_when_marketplace_file_cannot_be_read()
|
||||
.contains("failed to read marketplace file")
|
||||
);
|
||||
|
||||
let payload = wait_for_plugin_analytics_payload(&analytics_server).await?;
|
||||
let payload =
|
||||
wait_for_plugin_analytics_payload(&analytics_server, "codex_plugin_install_failed").await?;
|
||||
let event_params = &payload["events"][0]["event_params"];
|
||||
assert_eq!(
|
||||
payload["events"][0]["event_type"],
|
||||
@@ -1026,7 +1027,8 @@ async fn plugin_install_tracks_analytics_event() -> Result<()> {
|
||||
timeout(DEFAULT_TIMEOUT, mcp.read_response(request_id)).await??;
|
||||
assert_eq!(response.apps_needing_auth, Vec::<AppSummary>::new());
|
||||
|
||||
let payload = wait_for_plugin_analytics_payload(&analytics_server).await?;
|
||||
let payload =
|
||||
wait_for_plugin_analytics_payload(&analytics_server, "codex_plugin_installed").await?;
|
||||
assert_eq!(
|
||||
payload,
|
||||
json!({
|
||||
@@ -1094,7 +1096,8 @@ async fn plugin_install_failure_tracks_analytics_event() -> Result<()> {
|
||||
.await??;
|
||||
assert_eq!(err.error.code, -32600);
|
||||
|
||||
let payload = wait_for_plugin_analytics_payload(&analytics_server).await?;
|
||||
let payload =
|
||||
wait_for_plugin_analytics_payload(&analytics_server, "codex_plugin_install_failed").await?;
|
||||
let event_params = &payload["events"][0]["event_params"];
|
||||
assert_eq!(
|
||||
payload["events"][0]["event_type"],
|
||||
@@ -1151,7 +1154,7 @@ async fn plugin_install_tracks_remote_plugin_analytics_event() -> Result<()> {
|
||||
json!({"install_attempt_id": INSTALL_ATTEMPT_ID})
|
||||
);
|
||||
|
||||
let payload = wait_for_plugin_analytics_payload(&server).await?;
|
||||
let payload = wait_for_plugin_analytics_payload(&server, "codex_plugin_installed").await?;
|
||||
assert_eq!(
|
||||
payload,
|
||||
json!({
|
||||
@@ -1229,7 +1232,7 @@ async fn plugin_install_preserves_status_when_remote_bundle_error_body_is_too_la
|
||||
/*expected_count*/ 0,
|
||||
)
|
||||
.await?;
|
||||
let payload = wait_for_plugin_analytics_payload(&server).await?;
|
||||
let payload = wait_for_plugin_analytics_payload(&server, "codex_plugin_install_failed").await?;
|
||||
let event_params = &payload["events"][0]["event_params"];
|
||||
assert_eq!(
|
||||
payload["events"][0]["event_type"],
|
||||
@@ -2762,22 +2765,32 @@ async fn mount_backend_analytics_events(server: &MockServer) {
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn wait_for_plugin_analytics_payload(server: &MockServer) -> Result<serde_json::Value> {
|
||||
async fn wait_for_plugin_analytics_payload(
|
||||
server: &MockServer,
|
||||
event_type: &str,
|
||||
) -> Result<serde_json::Value> {
|
||||
timeout(DEFAULT_TIMEOUT, async {
|
||||
loop {
|
||||
let Some(requests) = server.received_requests().await else {
|
||||
tokio::time::sleep(Duration::from_millis(25)).await;
|
||||
continue;
|
||||
};
|
||||
if let Some(request) = requests.iter().find(|request| {
|
||||
for request in requests.iter().filter(|request| {
|
||||
request.method == "POST"
|
||||
&& request
|
||||
.url
|
||||
.path()
|
||||
.ends_with("/codex/analytics-events/events")
|
||||
}) {
|
||||
return serde_json::from_slice(&request.body)
|
||||
.map_err(|err| anyhow::anyhow!("invalid analytics payload: {err}"));
|
||||
let mut payload: serde_json::Value = serde_json::from_slice(&request.body)
|
||||
.map_err(|err| anyhow::anyhow!("invalid analytics payload: {err}"))?;
|
||||
let events = payload["events"]
|
||||
.as_array_mut()
|
||||
.ok_or_else(|| anyhow::anyhow!("analytics payload missing events array"))?;
|
||||
events.retain(|event| event["event_type"] == event_type);
|
||||
if !events.is_empty() {
|
||||
return Ok(payload);
|
||||
}
|
||||
}
|
||||
tokio::time::sleep(Duration::from_millis(25)).await;
|
||||
}
|
||||
@@ -2785,6 +2798,36 @@ async fn wait_for_plugin_analytics_payload(server: &MockServer) -> Result<serde_
|
||||
.await?
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn plugin_analytics_wait_ignores_unrelated_requests_and_batched_events() -> Result<()> {
|
||||
let server = MockServer::start().await;
|
||||
mount_backend_analytics_events(&server).await;
|
||||
let client = HttpClientBuilder::new().build_direct()?;
|
||||
let expected = json!({
|
||||
"event_type": "codex_plugin_install_failed",
|
||||
"event_params": {"plugin_id": "sample-plugin@debug"}
|
||||
});
|
||||
for events in [
|
||||
json!([{"event_type": "codex_turn_event"}]),
|
||||
json!([{"event_type": "codex_thread_initialized"}, expected.clone()]),
|
||||
] {
|
||||
client
|
||||
.post(format!(
|
||||
"{}/backend-api/codex/analytics-events/events",
|
||||
server.uri()
|
||||
))
|
||||
.json(&json!({"events": events}))
|
||||
.send()
|
||||
.await?
|
||||
.error_for_status()?;
|
||||
}
|
||||
assert_eq!(
|
||||
wait_for_plugin_analytics_payload(&server, "codex_plugin_install_failed").await?,
|
||||
json!({"events": [expected]})
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn oauth_discovery_request_count(server: &MockServer) -> usize {
|
||||
server
|
||||
.received_requests()
|
||||
|
||||
Reference in New Issue
Block a user