|
2 | 2 |
|
3 | 3 | use super::tools::get_transaction;
|
4 | 4 | use crate::operation_pool::tests::POOL_SETTINGS;
|
| 5 | +use crate::tests::tools::create_executesc; |
5 | 6 | use crate::tests::tools::{self, get_transaction_with_addresses, pool_test};
|
6 | 7 | use crate::PoolSettings;
|
7 | 8 | use massa_models::Address;
|
@@ -183,6 +184,172 @@ async fn test_pool() {
|
183 | 184 | )
|
184 | 185 | .await;
|
185 | 186 | }
|
| 187 | + |
| 188 | +#[tokio::test] |
| 189 | +#[serial] |
| 190 | +async fn test_pool_with_execute_sc() { |
| 191 | + let (cfg, thread_count, operation_validity_periods, max_pool_size_per_thread): &( |
| 192 | + PoolSettings, |
| 193 | + u8, |
| 194 | + u64, |
| 195 | + u64, |
| 196 | + ) = &POOL_SETTINGS; |
| 197 | + |
| 198 | + pool_test( |
| 199 | + cfg, |
| 200 | + *thread_count, |
| 201 | + *operation_validity_periods, |
| 202 | + async move |mut protocol_controller, mut pool_command_sender, pool_manager| { |
| 203 | + let op_filter = |cmd| match cmd { |
| 204 | + cmd @ ProtocolCommand::PropagateOperations(_) => Some(cmd), |
| 205 | + _ => None, |
| 206 | + }; |
| 207 | + // generate transactions |
| 208 | + let mut thread_tx_lists = vec![Vec::new(); *thread_count as usize]; |
| 209 | + for i in 0..18 { |
| 210 | + let fee = 40 + i; |
| 211 | + let expire_period: u64 = 40 + i; |
| 212 | + let start_period = expire_period.saturating_sub(*operation_validity_periods); |
| 213 | + let (op, thread) = create_executesc(expire_period, fee, 100, 1); // Only the fee determines the rentability |
| 214 | + let id = op.verify_integrity().unwrap(); |
| 215 | + |
| 216 | + let mut ops = OperationHashMap::default(); |
| 217 | + ops.insert(id, op.clone()); |
| 218 | + |
| 219 | + pool_command_sender |
| 220 | + .add_operations(ops.clone()) |
| 221 | + .await |
| 222 | + .unwrap(); |
| 223 | + |
| 224 | + let newly_added = match protocol_controller |
| 225 | + .wait_command(250.into(), op_filter) |
| 226 | + .await |
| 227 | + { |
| 228 | + Some(ProtocolCommand::PropagateOperations(ops)) => ops, |
| 229 | + Some(_) => panic!("unexpected protocol command"), |
| 230 | + None => panic!("unexpected timeout reached"), |
| 231 | + }; |
| 232 | + assert_eq!( |
| 233 | + newly_added.keys().copied().collect::<Vec<_>>(), |
| 234 | + ops.keys().copied().collect::<Vec<_>>() |
| 235 | + ); |
| 236 | + |
| 237 | + // duplicate |
| 238 | + pool_command_sender |
| 239 | + .add_operations(ops.clone()) |
| 240 | + .await |
| 241 | + .unwrap(); |
| 242 | + |
| 243 | + if let Some(cmd) = protocol_controller |
| 244 | + .wait_command(250.into(), op_filter) |
| 245 | + .await |
| 246 | + { |
| 247 | + panic!("unexpected protocol command {:?}", cmd) |
| 248 | + }; |
| 249 | + |
| 250 | + thread_tx_lists[thread as usize].push((id, op, start_period..=expire_period)); |
| 251 | + } |
| 252 | + // sort from bigger fee to smaller and truncate |
| 253 | + for lst in thread_tx_lists.iter_mut() { |
| 254 | + lst.reverse(); |
| 255 | + lst.truncate(*max_pool_size_per_thread as usize); |
| 256 | + } |
| 257 | + |
| 258 | + // checks ops for thread 0 and 1 and various periods |
| 259 | + for thread in 0u8..=1 { |
| 260 | + for period in 0u64..70 { |
| 261 | + let target_slot = Slot::new(period, thread); |
| 262 | + let max_count = 3; |
| 263 | + let res = pool_command_sender |
| 264 | + .get_operation_batch( |
| 265 | + target_slot, |
| 266 | + OperationHashSet::default(), |
| 267 | + max_count, |
| 268 | + 10000, |
| 269 | + ) |
| 270 | + .await |
| 271 | + .unwrap(); |
| 272 | + assert!(res |
| 273 | + .iter() |
| 274 | + .map(|(id, op, _)| (id, op.to_bytes_compact().unwrap())) |
| 275 | + .eq(thread_tx_lists[target_slot.thread as usize] |
| 276 | + .iter() |
| 277 | + .filter(|(_, _, r)| r.contains(&target_slot.period)) |
| 278 | + .take(max_count) |
| 279 | + .map(|(id, op, _)| (id, op.to_bytes_compact().unwrap())))); |
| 280 | + } |
| 281 | + } |
| 282 | + // op ending before or at period 45 should be discarded |
| 283 | + let final_period = 45u64; |
| 284 | + pool_command_sender |
| 285 | + .update_latest_final_periods(vec![final_period; *thread_count as usize]) |
| 286 | + .await |
| 287 | + .unwrap(); |
| 288 | + for lst in thread_tx_lists.iter_mut() { |
| 289 | + lst.retain(|(_, op, _)| op.content.expire_period > final_period); |
| 290 | + } |
| 291 | + // checks ops for thread 0 and 1 and various periods |
| 292 | + for thread in 0u8..=1 { |
| 293 | + for period in 0u64..70 { |
| 294 | + let target_slot = Slot::new(period, thread); |
| 295 | + let max_count = 4; |
| 296 | + let res = pool_command_sender |
| 297 | + .get_operation_batch( |
| 298 | + target_slot, |
| 299 | + OperationHashSet::default(), |
| 300 | + max_count, |
| 301 | + 10000, |
| 302 | + ) |
| 303 | + .await |
| 304 | + .unwrap(); |
| 305 | + assert!(res |
| 306 | + .iter() |
| 307 | + .map(|(id, op, _)| (id, op.to_bytes_compact().unwrap())) |
| 308 | + .eq(thread_tx_lists[target_slot.thread as usize] |
| 309 | + .iter() |
| 310 | + .filter(|(_, _, r)| r.contains(&target_slot.period)) |
| 311 | + .take(max_count) |
| 312 | + .map(|(id, op, _)| (id, op.to_bytes_compact().unwrap())))); |
| 313 | + } |
| 314 | + } |
| 315 | + // add transactions from protocol with a high fee but too much in the future: should be ignored |
| 316 | + { |
| 317 | + pool_command_sender |
| 318 | + .update_current_slot(Slot::new(10, 0)) |
| 319 | + .await |
| 320 | + .unwrap(); |
| 321 | + let fee = 1000; |
| 322 | + let expire_period: u64 = 300; |
| 323 | + let (op, thread) = get_transaction(expire_period, fee); |
| 324 | + let id = op.verify_integrity().unwrap(); |
| 325 | + let mut ops = OperationHashMap::default(); |
| 326 | + ops.insert(id, op); |
| 327 | + |
| 328 | + pool_command_sender.add_operations(ops).await.unwrap(); |
| 329 | + |
| 330 | + if let Some(cmd) = protocol_controller |
| 331 | + .wait_command(250.into(), op_filter) |
| 332 | + .await |
| 333 | + { |
| 334 | + panic!("unexpected protocol command {:?}", cmd) |
| 335 | + }; |
| 336 | + let res = pool_command_sender |
| 337 | + .get_operation_batch( |
| 338 | + Slot::new(expire_period - 1, thread), |
| 339 | + OperationHashSet::default(), |
| 340 | + 10, |
| 341 | + 10000, |
| 342 | + ) |
| 343 | + .await |
| 344 | + .unwrap(); |
| 345 | + assert!(res.is_empty()); |
| 346 | + } |
| 347 | + (protocol_controller, pool_command_sender, pool_manager) |
| 348 | + }, |
| 349 | + ) |
| 350 | + .await; |
| 351 | +} |
| 352 | + |
186 | 353 | #[tokio::test]
|
187 | 354 | #[serial]
|
188 | 355 | async fn test_pool_with_protocol_events() {
|
|
0 commit comments