test(sdk): Test that OAuth::server_metadata uses the refresh lock

Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
This commit is contained in:
Kévin Commaille
2026-04-28 14:57:41 +02:00
committed by Ivan Enderlin
parent adc0caa7d3
commit df5f5a8e2b

View File

@@ -11,6 +11,7 @@ use ruma::{
};
use tokio::sync::broadcast::error::TryRecvError;
use url::Url;
use wiremock::ResponseTemplate;
use super::{
AuthorizationCode, AuthorizationError, AuthorizationResponse, OAuth, OAuthAuthorizationData,
@@ -23,6 +24,8 @@ use crate::{
error::{AuthorizationCodeErrorResponseType, OAuthClientRegistrationError},
},
client::caches::CachedValue,
config::RequestConfig,
executor::spawn,
test_utils::{
client::{
MockClientBuilder, mock_prev_session_tokens_with_refresh,
@@ -713,6 +716,49 @@ async fn test_server_metadata_cache() {
assert_matches!(client.inner.caches.server_metadata.value(), CachedValue::Cached(value) if !value.has_expired());
}
#[async_test]
async fn test_server_metadata_cache_refresh_lock() {
let server = MatrixMockServer::new().await;
let oauth_server = server.oauth();
// Make the first request to the endpoint fail after a second.
oauth_server
.mock_server_metadata()
.respond_with(ResponseTemplate::new(500).set_delay(Duration::from_secs(1)))
.mock_once()
.mount()
.await;
// The following request will succeed.
oauth_server.mock_server_metadata().ok().expect(1).mount().await;
let client = server
.client_builder()
.logged_in_with_oauth()
// Disable retries so the first request succeeds or fails without waiting.
.on_builder(|builder| builder.request_config(RequestConfig::new().disable_retry()))
.build()
.await;
let oauth = client.oauth();
// Spawn the first request that will fail after one second.
let oauth_clone = oauth.clone();
let first_request = spawn(async move { oauth_clone.server_metadata().await });
// Wait to make sure that the first request started.
sleep(Duration::from_millis(200)).await;
// Spawn the second and third requests. The first that acquires a lock will
// retry the request and succeed, and the second one will read the value from
// the cache.
let oauth_clone = oauth.clone();
let second_request = spawn(async move { oauth_clone.server_metadata().await });
let third_request = spawn(async move { oauth.server_metadata().await });
first_request.await.expect("task was not cancelled").unwrap_err();
second_request.await.expect("task was not cancelled").unwrap();
third_request.await.expect("task was not cancelled").unwrap();
}
#[async_test]
async fn test_server_metadata() {
let server = MatrixMockServer::new().await;