diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/routes.rs | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/src/routes.rs b/src/routes.rs index 23fcd29..1ab6eff 100644 --- a/src/routes.rs +++ b/src/routes.rs | |||
| @@ -46,3 +46,151 @@ pub fn block_propose(db: Db) -> impl Filter<Extract = impl Reply, Error = Reject | |||
| 46 | .and_then(handlers::propose_block) | 46 | .and_then(handlers::propose_block) |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | #[cfg(test)] | ||
| 50 | mod tests { | ||
| 51 | use super::*; | ||
| 52 | |||
| 53 | use chrono::prelude::*; | ||
| 54 | use parking_lot::RwLock; | ||
| 55 | use std::sync::Arc; | ||
| 56 | use warp::http::StatusCode; | ||
| 57 | |||
| 58 | use crate::schema; | ||
| 59 | use crate::schema::{Block, Transaction}; | ||
| 60 | |||
| 61 | /// Create a mock database to be used in tests | ||
| 62 | fn mocked_db() -> Db { | ||
| 63 | let db = schema::create_database(); | ||
| 64 | |||
| 65 | db.pending_transactions.write().insert( | ||
| 66 | "hash_value".to_owned(), | ||
| 67 | Transaction { | ||
| 68 | source: "source_account".to_owned(), | ||
| 69 | target: "target_account".to_owned(), | ||
| 70 | amount: 20, | ||
| 71 | timestamp: chrono::NaiveDate::from_ymd(2021, 04, 09).and_hms(1, 30, 30), | ||
| 72 | }, | ||
| 73 | ); | ||
| 74 | |||
| 75 | db.blockchain.write().push(Block { | ||
| 76 | transaction_list: vec![ | ||
| 77 | "old_transaction_hash_1".to_owned(), | ||
| 78 | "old_transaction_hash_2".to_owned(), | ||
| 79 | "old_transaction_hash_3".to_owned(), | ||
| 80 | ], | ||
| 81 | nonce: "not_a_thing_yet".to_owned(), | ||
| 82 | timestamp: chrono::NaiveDate::from_ymd(2021, 04, 08).and_hms(12, 30, 30), | ||
| 83 | hash: "not_a_thing_yet".to_owned(), | ||
| 84 | }); | ||
| 85 | |||
| 86 | db | ||
| 87 | } | ||
| 88 | |||
| 89 | /// Create a mock transaction to be used in tests | ||
| 90 | fn mocked_transaction() -> Transaction { | ||
| 91 | Transaction { | ||
| 92 | source: "mock_transaction_source".to_owned(), | ||
| 93 | target: "mock_transaction_target".to_owned(), | ||
| 94 | amount: 25, | ||
| 95 | timestamp: chrono::NaiveDate::from_ymd(2021, 04, 09).and_hms(14, 30, 00), | ||
| 96 | } | ||
| 97 | } | ||
| 98 | |||
| 99 | /// Test simple GET request to /transaction, resource that exists | ||
| 100 | /// https://tools.ietf.org/html/rfc7231#section-6.3.1 | ||
| 101 | /// We should get the only pending transaction available in the database as json | ||
| 102 | #[tokio::test] | ||
| 103 | async fn get_pending_transactions() { | ||
| 104 | let db = mocked_db(); | ||
| 105 | |||
| 106 | let reply = consensus_routes(db); | ||
| 107 | |||
| 108 | let res = warp::test::request() | ||
| 109 | .method("GET") | ||
| 110 | .path("/transaction") | ||
| 111 | .reply(&reply) | ||
| 112 | .await; | ||
| 113 | |||
| 114 | assert_eq!(res.status(), StatusCode::OK); | ||
| 115 | |||
| 116 | let expected_json_body = r#"[{"source":"source_account","target":"target_account","amount":20,"timestamp":"2021-04-09T01:30:30"}]"#; | ||
| 117 | |||
| 118 | assert_eq!(res.body(), expected_json_body); | ||
| 119 | } | ||
| 120 | |||
| 121 | /// Test simple GET request to /block, resource that exists | ||
| 122 | /// https://tools.ietf.org/html/rfc7231#section-6.3.1 | ||
| 123 | /// Should return the single block available in the database as json | ||
| 124 | #[tokio::test] | ||
| 125 | async fn get_blockchain() { | ||
| 126 | let db = mocked_db(); | ||
| 127 | let filter = consensus_routes(db); | ||
| 128 | |||
| 129 | let res = warp::test::request() | ||
| 130 | .method("GET") | ||
| 131 | .path("/block") | ||
| 132 | .reply(&filter) | ||
| 133 | .await; | ||
| 134 | |||
| 135 | assert_eq!(res.status(), StatusCode::OK); | ||
| 136 | |||
| 137 | let expected_json_body = r#"[{"transaction_list":["old_transaction_hash_1","old_transaction_hash_2","old_transaction_hash_3"],"nonce":"not_a_thing_yet","timestamp":"2021-04-08T12:30:30","hash":"not_a_thing_yet"}]"#; | ||
| 138 | assert_eq!(res.body(), expected_json_body); | ||
| 139 | } | ||
| 140 | |||
| 141 | /// Test a simple GET request to a nonexisting path | ||
| 142 | /// https://tools.ietf.org/html/rfc7231#section-6.5.4 | ||
| 143 | /// Should respond with 404 and stop | ||
| 144 | #[tokio::test] | ||
| 145 | async fn get_nonexisting_path_404() { | ||
| 146 | let db = mocked_db(); | ||
| 147 | let filter = consensus_routes(db); | ||
| 148 | |||
| 149 | let res = warp::test::request() | ||
| 150 | .method("GET") | ||
| 151 | .path("/this_path_does_not_exist") | ||
| 152 | .reply(&filter) | ||
| 153 | .await; | ||
| 154 | |||
| 155 | assert_eq!(res.status(), StatusCode::NOT_FOUND); | ||
| 156 | } | ||
| 157 | |||
| 158 | /// Test a POST request to /transaction, a resource that exists | ||
| 159 | /// https://tools.ietf.org/html/rfc7231#section-6.3.2 | ||
| 160 | /// Should accept the json request, create | ||
| 161 | /// the transaction and add it to pending transactions in the db | ||
| 162 | #[tokio::test] | ||
| 163 | async fn post_json_201() { | ||
| 164 | let db = mocked_db(); | ||
| 165 | let filter = consensus_routes(db.clone()); | ||
| 166 | |||
| 167 | let res = warp::test::request() | ||
| 168 | .method("POST") | ||
| 169 | .json(&mocked_transaction()) | ||
| 170 | .path("/transaction") | ||
| 171 | .reply(&filter) | ||
| 172 | .await; | ||
| 173 | |||
| 174 | assert_eq!(res.status(), StatusCode::CREATED); | ||
| 175 | assert_eq!(db.pending_transactions.read().len(), 2); | ||
| 176 | } | ||
| 177 | |||
| 178 | /// Test a POST request to /transaction, a resource that exists with a longer than expected | ||
| 179 | /// payload | ||
| 180 | /// https://tools.ietf.org/html/rfc7231#section-6.5.11 | ||
| 181 | /// Should return 413 to user | ||
| 182 | #[tokio::test] | ||
| 183 | async fn post_too_long_content_413() { | ||
| 184 | let db = mocked_db(); | ||
| 185 | let filter = consensus_routes(db); | ||
| 186 | |||
| 187 | let res = warp::test::request() | ||
| 188 | .method("POST") | ||
| 189 | .header("content-length", 1024 * 36) | ||
| 190 | .path("/transaction") | ||
| 191 | .reply(&filter) | ||
| 192 | .await; | ||
| 193 | |||
| 194 | assert_eq!(res.status(), StatusCode::PAYLOAD_TOO_LARGE); | ||
| 195 | } | ||
| 196 | } | ||
