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
2 changes: 1 addition & 1 deletion src/cmap/establish.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub(super) mod handshake;
pub(crate) mod handshake;

use std::time::Duration;

Expand Down
67 changes: 37 additions & 30 deletions src/cmap/establish/handshake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,43 +26,43 @@ const RUNTIME_NAME: &str = "tokio";
#[cfg(feature = "sync")]
const RUNTIME_NAME: &str = "sync (with tokio)";

#[derive(Clone, Debug)]
struct ClientMetadata {
application: Option<AppMetadata>,
driver: DriverMetadata,
os: OsMetadata,
platform: String,
env: Option<RuntimeEnvironment>,
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct ClientMetadata {
pub(crate) application: Option<AppMetadata>,
pub(crate) driver: DriverMetadata,
pub(crate) os: OsMetadata,
pub(crate) platform: String,
pub(crate) env: Option<RuntimeEnvironment>,
}

#[derive(Clone, Debug)]
struct AppMetadata {
name: String,
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct AppMetadata {
pub(crate) name: String,
}

#[derive(Clone, Debug)]
struct DriverMetadata {
name: String,
version: String,
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct DriverMetadata {
pub(crate) name: String,
pub(crate) version: String,
}

#[derive(Clone, Debug)]
struct OsMetadata {
os_type: String,
name: Option<String>,
architecture: Option<String>,
version: Option<String>,
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct OsMetadata {
pub(crate) os_type: String,
pub(crate) name: Option<String>,
pub(crate) architecture: Option<String>,
pub(crate) version: Option<String>,
}

#[derive(Clone, Debug, PartialEq)]
struct RuntimeEnvironment {
name: Option<FaasEnvironmentName>,
runtime: Option<String>,
timeout_sec: Option<i32>,
memory_mb: Option<i32>,
region: Option<String>,
url: Option<String>,
container: Option<RawDocumentBuf>,
pub(crate) struct RuntimeEnvironment {
pub(crate) name: Option<FaasEnvironmentName>,
pub(crate) runtime: Option<String>,
pub(crate) timeout_sec: Option<i32>,
pub(crate) memory_mb: Option<i32>,
pub(crate) region: Option<String>,
pub(crate) url: Option<String>,
pub(crate) container: Option<RawDocumentBuf>,
}

#[derive(Copy, Clone, Debug, PartialEq)]
Expand Down Expand Up @@ -158,7 +158,7 @@ impl From<&RuntimeEnvironment> for RawBson {
}

impl RuntimeEnvironment {
const UNSET: Self = RuntimeEnvironment {
pub(crate) const UNSET: Self = RuntimeEnvironment {
name: None,
runtime: None,
timeout_sec: None,
Expand Down Expand Up @@ -262,7 +262,7 @@ impl FaasEnvironmentName {
/// Contains the basic handshake information that can be statically determined. This document
/// (potentially with additional fields added) can be cloned and put in the `client` field of
/// the `hello` or legacy hello command.
static BASE_CLIENT_METADATA: Lazy<ClientMetadata> = Lazy::new(|| ClientMetadata {
pub(crate) static BASE_CLIENT_METADATA: Lazy<ClientMetadata> = Lazy::new(|| ClientMetadata {
application: None,
driver: DriverMetadata {
name: "mongo-rust-driver".into(),
Expand Down Expand Up @@ -335,6 +335,10 @@ pub(crate) struct Handshaker {
http_client: crate::runtime::HttpClient,
}

#[cfg(test)]
#[allow(clippy::incompatible_msrv)]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be fine since we only test on the latest release and cfg(test) isn't transitive, so someone using <1.70 (when OnceLock was introduced) can still use the mongodb crate fine, including in their tests.

pub(crate) static TEST_METADATA: std::sync::OnceLock<ClientMetadata> = std::sync::OnceLock::new();

impl Handshaker {
/// Creates a new Handshaker.
pub(crate) fn new(options: HandshakerOptions) -> Self {
Expand Down Expand Up @@ -427,6 +431,9 @@ impl Handshaker {
trunc_fn(&mut metadata);
meta_doc = (&metadata).into();
}
#[cfg(test)]
#[allow(clippy::incompatible_msrv)]
let _ = TEST_METADATA.set(metadata);
body.append("client", meta_doc);

Ok((command, client_first))
Expand Down
147 changes: 115 additions & 32 deletions src/test/spec/faas.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
use std::env;

use crate::Client;
use crate::{
cmap::establish::handshake::{
ClientMetadata,
FaasEnvironmentName,
RuntimeEnvironment,
BASE_CLIENT_METADATA,
},
Client,
};

type Result<T> = anyhow::Result<T>;

Expand Down Expand Up @@ -33,79 +41,154 @@ impl Drop for TempVars {
}
}

async fn check_faas_handshake(vars: &[(&'static str, &str)]) -> Result<()> {
async fn check_faas_handshake(
vars: &[(&'static str, &str)],
expected: &ClientMetadata,
) -> Result<()> {
let _tv = TempVars::set(vars);

let client = Client::for_test().await;
client.list_database_names().await?;
#[allow(clippy::incompatible_msrv)]
let metadata = crate::cmap::establish::handshake::TEST_METADATA
.get()
.unwrap();
assert_eq!(expected, metadata);

Ok(())
}

#[tokio::test]
async fn valid_aws() -> Result<()> {
check_faas_handshake(&[
("AWS_EXECUTION_ENV", "AWS_Lambda_java8"),
("AWS_REGION", "us-east-2"),
("AWS_LAMBDA_FUNCTION_MEMORY_SIZE", "1024"),
])
check_faas_handshake(
&[
("AWS_EXECUTION_ENV", "AWS_Lambda_java8"),
("AWS_REGION", "us-east-2"),
("AWS_LAMBDA_FUNCTION_MEMORY_SIZE", "1024"),
],
&ClientMetadata {
env: Some(RuntimeEnvironment {
name: Some(FaasEnvironmentName::AwsLambda),
runtime: Some("AWS_Lambda_java8".to_string()),
memory_mb: Some(1024),
region: Some("us-east-2".to_string()),
..RuntimeEnvironment::UNSET
}),
..BASE_CLIENT_METADATA.clone()
},
)
.await
}

#[tokio::test]
async fn valid_azure() -> Result<()> {
check_faas_handshake(&[("FUNCTIONS_WORKER_RUNTIME", "node")]).await
check_faas_handshake(
&[("FUNCTIONS_WORKER_RUNTIME", "node")],
&ClientMetadata {
env: Some(RuntimeEnvironment {
name: Some(FaasEnvironmentName::AzureFunc),
runtime: Some("node".to_string()),
..RuntimeEnvironment::UNSET
}),
..BASE_CLIENT_METADATA.clone()
},
)
.await
}

#[tokio::test]
async fn valid_gcp() -> Result<()> {
check_faas_handshake(&[
("K_SERVICE", "servicename"),
("FUNCTION_MEMORY_MB", "1024"),
("FUNCTION_TIMEOUT_SEC", "60"),
("FUNCTION_REGION", "us-central1"),
])
check_faas_handshake(
&[
("K_SERVICE", "servicename"),
("FUNCTION_MEMORY_MB", "1024"),
("FUNCTION_TIMEOUT_SEC", "60"),
("FUNCTION_REGION", "us-central1"),
],
&ClientMetadata {
env: Some(RuntimeEnvironment {
name: Some(FaasEnvironmentName::GcpFunc),
memory_mb: Some(1024),
timeout_sec: Some(60),
region: Some("us-central1".to_string()),
..RuntimeEnvironment::UNSET
}),
..BASE_CLIENT_METADATA.clone()
},
)
.await
}

#[tokio::test]
async fn valid_vercel() -> Result<()> {
check_faas_handshake(&[
("VERCEL", "1"),
("VERCEL_URL", "*.vercel.app"),
("VERCEL_REGION", "cdg1"),
])
check_faas_handshake(
&[
("VERCEL", "1"),
("VERCEL_URL", "*.vercel.app"),
("VERCEL_REGION", "cdg1"),
],
&ClientMetadata {
env: Some(RuntimeEnvironment {
name: Some(FaasEnvironmentName::Vercel),
region: Some("cdg1".to_string()),
..RuntimeEnvironment::UNSET
}),
..BASE_CLIENT_METADATA.clone()
},
)
.await
}

#[tokio::test]
async fn invalid_multiple_providers() -> Result<()> {
check_faas_handshake(&[
("AWS_EXECUTION_ENV", "AWS_Lambda_java8"),
("FUNCTIONS_WORKER_RUNTIME", "node"),
])
check_faas_handshake(
&[
("AWS_EXECUTION_ENV", "AWS_Lambda_java8"),
("FUNCTIONS_WORKER_RUNTIME", "node"),
],
&BASE_CLIENT_METADATA,
)
.await
}

#[tokio::test]
async fn invalid_long_string() -> Result<()> {
check_faas_handshake(&[
("AWS_EXECUTION_ENV", "AWS_Lambda_java8"),
("AWS_REGION", &"a".repeat(512)),
])
check_faas_handshake(
&[
("AWS_EXECUTION_ENV", "AWS_Lambda_java8"),
("AWS_REGION", &"a".repeat(512)),
],
&ClientMetadata {
env: Some(RuntimeEnvironment {
name: Some(FaasEnvironmentName::AwsLambda),
..RuntimeEnvironment::UNSET
}),
..BASE_CLIENT_METADATA.clone()
},
)
.await
}

#[tokio::test]
async fn invalid_wrong_type() -> Result<()> {
check_faas_handshake(&[
("AWS_EXECUTION_ENV", "AWS_Lambda_java8"),
("AWS_LAMBDA_FUNCTION_MEMORY_SIZE", "big"),
])
check_faas_handshake(
&[
("AWS_EXECUTION_ENV", "AWS_Lambda_java8"),
("AWS_LAMBDA_FUNCTION_MEMORY_SIZE", "big"),
],
&ClientMetadata {
env: Some(RuntimeEnvironment {
name: Some(FaasEnvironmentName::AwsLambda),
runtime: Some("AWS_Lambda_java8".to_string()),
..RuntimeEnvironment::UNSET
}),
..BASE_CLIENT_METADATA.clone()
},
)
.await
}

#[tokio::test]
async fn invalid_aws_not_lambda() -> Result<()> {
check_faas_handshake(&[("AWS_EXECUTION_ENV", "EC2")]).await
check_faas_handshake(&[("AWS_EXECUTION_ENV", "EC2")], &BASE_CLIENT_METADATA).await
}