Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
65 changes: 35 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,9 @@ pub(crate) struct Handshaker {
http_client: crate::runtime::HttpClient,
}

#[cfg(test)]
pub(crate) static METADATA: std::sync::OnceLock<ClientMetadata> = std::sync::OnceLock::new();
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 gives me the heebie-jeebies but since it's explicitly test-restricted and a lot less disruptive than trying to propagate the computed metadata back up the ownership/worker hierarchy it seemed the less-bad option.


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

Ok((command, client_first))
Expand Down
144 changes: 112 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,151 @@ 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?;
let metadata = crate::cmap::establish::handshake::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
}