Section II - module

couchdb.rs

To create the module, create a new file named couchdb.rs in the /src directory.

Now is a good time to rerun the cargo test command to ensure all your tests still pass.

Add the use declarations at the top of the file.

use std::str;
use base64::{encode, decode};
use roadrunner::RestClient;
use roadrunner::RestClientMethods;
use hyper::{StatusCode};
use serde_json::value::{Value};
use super::daas::{DaaSDoc};

Tests

NOTE: These tests require preexisting documents in CouchDB in the test database. You will need to create the test database and then create the following documents in the test database: 1. doc-12345 2. doc-upsert_existing_doc

First create the tests for this module as a nested module at the bottom of the file.

#[cfg(test)]
mod tests {
    use super::*;
    use std::time::{SystemTime, UNIX_EPOCH};
    use rand::Rng;

    #[test]
    fn test_couchdb_new() {
        let couch = CouchDB::new("foo".to_string(), "bar".to_string());
        assert_eq!(couch.get_auth(), "Zm9vOmJhcg==");
        assert_eq!(couch.get_host(), "localhost");
        assert_eq!(couch.get_port(), 5984);
        assert_eq!(couch.get_protocol(), "http");
        assert_eq!(couch.get_base_url(), "http://localhost:5984".to_string())
    }

    #[test]
    fn test_cluster_setup() {
        let couch = CouchDB::new("admin".to_string(), "password".to_string());
        assert_eq!(couch.cluster_setup().unwrap(), StatusCode::Created);
    }    

    #[ignore]
    #[test]
    fn test_create_db_201() {
        let couch = CouchDB::new("admin".to_string(), "password".to_string());

        match couch.create_db("test".to_string()).unwrap() {
            StatusCode::Created => assert!(true),
            StatusCode::PreconditionFailed => assert!(true),
            _ => assert!(false)
        }
    }

    #[test]
    fn test_create_db_401() {
        let couch = CouchDB::new("foo".to_string(), "bar".to_string());
        assert_eq!(couch.create_db("test2".to_string()).unwrap(), StatusCode::Unauthorized);
    }

    #[test]
    fn test_create_doc_200() {
        let couch = CouchDB::new("admin".to_string(), "password".to_string());
        let src = "iStore".to_string();
        let mut rng = rand::thread_rng();
        let uid: usize = rng.gen_range(0, 1000000);
        let cat = "order".to_string();
        let sub = "clothing".to_string();
        let auth = "istore_app".to_string();
        let data = json!({
            "status": "new"
        });
        let doc = DaaSDoc::new(src, uid, cat, sub, auth, data);
        let rslt = couch.create_doc("test".to_string(),doc);

        match rslt {
            Ok(_v) => {
                assert!(true);
            },
            Err(e) => {
                println!("Failed: {}",e);
                assert!(false);
            }
        }
    }    

    #[test]
    fn test_get_doc_by_id_200() {
        let couch = CouchDB::new("admin".to_string(), "password".to_string());

        match couch.get_doc_by_id("test".to_string(),"12345".to_string()) {
            Ok(doc) => {
                println!("DOC ID: {}", doc._id);
                assert_eq!(doc._id, "12345".to_string())
            },
            Err(_e) => assert!(false)
        }
    }

    #[test]
    fn test_get_doc_by_id_404() {
        let couch = CouchDB::new("admin".to_string(), "password".to_string());

        match couch.get_doc_by_id("test".to_string(),"bad-id".to_string()) {
            Ok(_v) => assert!(false),
            Err(_e) => assert!(true)
        }
    }    

    #[test]
    fn test_get_password() {
        let couch = CouchDB::new("foo".to_string(), "bar".to_string());
        assert_eq!(couch.get_password(), "bar".to_string());
    }

    #[test]
    fn test_get_username() {
        let couch = CouchDB::new("foo".to_string(), "bar".to_string());
        assert_eq!(couch.get_username(), "foo".to_string());
    }    

    #[test]
    fn test_set_host() {
        let mut couch = CouchDB::new("foo".to_string(), "bar".to_string());
        assert!(couch.set_host("127.0.0.1".to_string()));
        assert_eq!(couch.get_host(), "127.0.0.1".to_string());
    }

    #[test]
    fn test_set_port() {
        let mut couch = CouchDB::new("foo".to_string(), "bar".to_string());
        assert!(couch.set_port(8080));
        assert_eq!(couch.get_port(), 8080);
    }

    #[test]
    fn test_set_protocol() {
        let mut couch = CouchDB::new("foo".to_string(), "bar".to_string());
        assert!(couch.set_protocol("https".to_string()));
        assert_eq!(couch.get_protocol(), "https".to_string());
    }

    #[test]
    fn test_update_doc_200() {
        let couch = CouchDB::new("admin".to_string(), "password".to_string());
        let mut before = couch.get_doc_by_id("test".to_string(),"12345".to_string()).unwrap();
        let old_uid = before.source_uid.clone();
        let _rev = before._rev.clone().unwrap();
        let new_src_uid: usize = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as usize;
        before.source_uid = new_src_uid;

        match couch.update_doc("test".to_string(), before) {
            Ok(_doc) => {
                match couch.get_doc_by_id("test".to_string(),"12345".to_string()) {
                    Ok(after) => assert_ne!(old_uid, after.source_uid),
                    _ => assert!(false)
                }
            },
            Err(_e) => assert!(false)
        }
    }   

    #[test]
    fn test_upsert_new_doc_200() {
        // create a new document
        let couch = CouchDB::new("admin".to_string(), "password".to_string());
        let src = "iStore".to_string();
        let mut rng = rand::thread_rng();
        let uid: usize = rng.gen_range(0, 1000000);
        let cat = "order".to_string();
        let sub = "clothing".to_string();
        let auth = "istore_app".to_string();
        let data = json!({
            "status": "new"
        });
        let doc = DaaSDoc::new(src, uid, cat, sub, auth, data);
        let rslt = couch.upsert_doc("test".to_string(),doc);

        match rslt {
            Ok(_v) => {
                assert!(true);
            },
            Err(e) => {
                println!("Failed: {}",e);
                assert!(false);
            }
        }
    }    

    #[test]
    fn test_upsert_existing_doc_200() {
        let couch = CouchDB::new("admin".to_string(), "password".to_string());
        let mut before = couch.get_doc_by_id("test".to_string(),"upsert_existing_doc".to_string()).unwrap();
        let old_uid = before.source_uid.clone();
        let new_src_uid: usize = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as usize;
        before.source_uid = new_src_uid;

        match couch.upsert_doc("test".to_string(), before) {
            Ok(_doc) => {
                match couch.get_doc_by_id("test".to_string(),"upsert_existing_doc".to_string()) {
                    Ok(after) => assert_ne!(old_uid, after.source_uid),
                    _ => assert!(false)
                }
            },
            Err(_e) => assert!(false)
        }
    }      

    #[test]
    fn test_upsert_existing_doc_without_rev_200() {
        // create a new document
        let couch = CouchDB::new("admin".to_string(), "password".to_string());
        let db = "test".to_string();
        let src = "iStore".to_string();
        let mut rng = rand::thread_rng();
        let uid: usize = rng.gen_range(0, 1000000);
        let cat = "order".to_string();
        let sub = "clothing".to_string();
        let auth = "istore_app".to_string();
        let data = json!({
            "status": "new"
        });
        let doc = DaaSDoc::new(src.clone(), uid.clone(), cat.clone(), sub.clone(), auth.clone(), data.clone());

        match couch.create_doc(db.clone(), doc) {
            Ok(_rslt) => {
                let updt_doc = DaaSDoc::new(src, 6000, cat, sub, auth, data);
                let doc_id = updt_doc._id.clone();

                match couch.upsert_doc(db.clone(), updt_doc) {
                    Ok(_v) => {
                        let after = couch.get_doc_by_id(db.clone(), doc_id).unwrap();
                        assert_eq!(6000, after.source_uid);
                    },
                    Err(e) => {
                        println!("Failed: {}",e);
                        assert!(false);
                    }
                }
            },
            Err(e) => {
                println!("Failed: {}",e);
                assert!(false);
            }
        }
    }             
}

Code

Just like in the daas module, we will follow an OOD and first create a structure for the CouchDB object.

And then use impl to provide the CouchDB object with funcitonality. Notice the new() constructor function.

Last updated

Was this helpful?