summaryrefslogtreecommitdiffstats
path: root/src/routes.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/routes.rs')
-rw-r--r--src/routes.rs148
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)]
50mod 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}