1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
//! Mock request dispatcher and credentials for unit testing services

extern crate chrono;
extern crate futures;
extern crate http;
extern crate rusoto_core;

use std::fs::File;
use std::io::Read;
use std::collections::HashMap;
use std::time::Duration;

use rusoto_core::{DispatchSignedRequest, HttpDispatchError};
use rusoto_core::credential::{ProvideAwsCredentials, CredentialsError, AwsCredentials};
use rusoto_core::request::{Headers, HttpResponse};
use rusoto_core::signature::SignedRequest;
use futures::future::{FutureResult, ok};
use futures::stream::once;
use http::{HttpTryFrom, StatusCode};

pub struct MockCredentialsProvider;

impl ProvideAwsCredentials for MockCredentialsProvider {
    type Future = FutureResult<AwsCredentials, CredentialsError>;

    fn credentials(&self) -> Self::Future {
        ok(AwsCredentials::new("mock_key",
                               "mock_secret",
                               None,
                               None))
    }
}

pub struct MockRequestDispatcher {
    status: StatusCode,
    body: Vec<u8>,
    headers: HashMap<String, String>,
    request_checker: Option<Box<Fn(&SignedRequest) + Send + Sync>>,
}

impl MockRequestDispatcher {
    pub fn with_status(status: u16) -> MockRequestDispatcher {
        MockRequestDispatcher {
            status: StatusCode::try_from(status).unwrap(),
            body: b"".to_vec(),
            headers: HashMap::new(),
            request_checker: None,
        }
    }

    pub fn with_body(mut self, body: &str) -> MockRequestDispatcher {
        self.body = body.as_bytes().to_vec();
        self
    }

    pub fn with_request_checker<F>(mut self, checker: F) -> MockRequestDispatcher
        where F: Fn(&SignedRequest) + Send + Sync + 'static {
        self.request_checker = Some(Box::new(checker));
        self
    }

    pub fn with_header(mut self, key: &str, value: &str) -> MockRequestDispatcher {
        self.headers.insert(key.into(), value.into());
        self
    }
}

impl DispatchSignedRequest for MockRequestDispatcher {
    type Future = FutureResult<HttpResponse, HttpDispatchError>;

    fn dispatch(&self, request: SignedRequest, _timeout: Option<Duration>) -> Self::Future {
        if self.request_checker.is_some() {
            self.request_checker.as_ref().unwrap()(&request);
        }
        ok(HttpResponse {
            status: self.status,
            body: Box::new(once(Ok(self.body.clone()))),
            headers: Headers::new(self.headers.iter().map(|(k, v)| (k.as_ref(), v.to_owned()))),
        })
    }
}

pub trait ReadMockResponse {
    fn read_response(dir_name: &str, file_name: &str) -> String;
}

pub struct MockResponseReader;

impl ReadMockResponse for MockResponseReader {
    fn read_response(dir_name: &str, response_name: &str) -> String {
        let file_name = format!("{}/{}", dir_name, response_name);

        let mut input_file = File::open(&file_name).expect("couldn't find file");

        let mut mock_response = String::new();

        input_file.read_to_string(&mut mock_response).expect(&format!(
	        "Failed to read {:?}",
	        file_name,
	    ));

        mock_response
    }
}