mongodb 1.1.1

The official MongoDB driver for Rust
Documentation
use std::collections::HashMap;

use futures::stream::TryStreamExt;
use semver::VersionReq;
use serde::Deserialize;

use crate::{
    bson::{doc, Document},
    options::{ClientOptions, FindOptions},
    test::{util::EventClient, AnyTestOperation, TestEvent},
};

#[derive(Debug, Deserialize)]
pub struct TestFile {
    #[serde(rename = "runOn")]
    pub run_on: Option<Vec<RunOn>>,
    pub database_name: Option<String>,
    pub collection_name: Option<String>,
    pub bucket_name: Option<String>,
    pub data: Option<TestData>,
    pub tests: Vec<TestCase>,
}

#[derive(Debug, Deserialize)]
#[serde(untagged)]
pub enum TestData {
    Single(Vec<Document>),
    Many(HashMap<String, Vec<Document>>),
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RunOn {
    pub min_server_version: Option<String>,
    pub max_server_version: Option<String>,
    pub topology: Option<Vec<String>>,
}

impl RunOn {
    pub fn can_run_on(&self, client: &EventClient) -> bool {
        if let Some(ref min_version) = self.min_server_version {
            let req = VersionReq::parse(&format!(">= {}", &min_version)).unwrap();
            if !req.matches(&client.server_version) {
                return false;
            }
        }
        if let Some(ref max_version) = self.max_server_version {
            let req = VersionReq::parse(&format!("<= {}", &max_version)).unwrap();
            if !req.matches(&client.server_version) {
                return false;
            }
        }
        if let Some(ref topology) = self.topology {
            if !topology.contains(&client.topology()) {
                return false;
            }
        }
        true
    }
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TestCase {
    pub description: String,
    pub client_options: Option<ClientOptions>,
    pub use_multiple_mongoses: Option<bool>,
    pub skip_reason: Option<String>,
    pub fail_point: Option<Document>,
    pub operations: Vec<AnyTestOperation>,
    pub outcome: Option<Outcome>,
    pub expectations: Option<Vec<TestEvent>>,
}

#[derive(Debug, Deserialize)]
pub struct Outcome {
    pub collection: CollectionOutcome,
}

impl Outcome {
    pub async fn matches_actual(
        self,
        db_name: String,
        coll_name: String,
        client: &EventClient,
    ) -> bool {
        let coll_name = match self.collection.name {
            Some(name) => name,
            None => coll_name,
        };
        let coll = client.database(&db_name).collection(&coll_name);
        let options = FindOptions::builder().sort(doc! { "_id": 1 }).build();
        let actual_data: Vec<Document> = coll
            .find(None, options)
            .await
            .unwrap()
            .try_collect()
            .await
            .unwrap();
        actual_data == self.collection.data
    }
}

#[derive(Debug, Deserialize)]
pub struct CollectionOutcome {
    pub name: Option<String>,
    pub data: Vec<Document>,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum OperationObject {
    Database,
    Collection,
    Client,
    GridfsBucket,
}