use super::*; #[tokio::test] async fn test_resize_buffer() { let mut context = MessageBufferTestContext::initialize_with_default_test_buffer( false, MessageBufferTestContext::DEFAULT_TARGET_SIZE, ) .await .unwrap(); let (msg_buffer_pda, _) = MessageBufferTestContext::default_msg_buffer(); // increase buffer size let mut target_size = MessageBufferTestContext::DEFAULT_TARGET_SIZE + 10240; let target_sizes = vec![target_size]; context .resize_msg_buffer( MessageBufferTestContext::DEFAULT_TEST_PRICE_ID, target_sizes, ) .await .unwrap(); let msg_buffer_account_data = context .fetch_msg_buffer_account_data(&msg_buffer_pda) .await .unwrap(); assert_eq!(msg_buffer_account_data.len(), target_size as usize); // decrease buffer size to less than original target_size -= 10340; let target_sizes = vec![target_size]; context .resize_msg_buffer( MessageBufferTestContext::DEFAULT_TEST_PRICE_ID, target_sizes, ) .await .unwrap(); let msg_buffer_account_data = context .fetch_msg_buffer_account_data(&msg_buffer_pda) .await .unwrap(); assert_eq!(msg_buffer_account_data.len(), target_size as usize); } #[tokio::test] async fn test_multiple_resize_buffer_ixs_in_same_txn() { let mut context = MessageBufferTestContext::initialize_with_default_test_buffer( false, MessageBufferTestContext::DEFAULT_TARGET_SIZE, ) .await .unwrap(); let (msg_buffer_pda, _) = MessageBufferTestContext::default_msg_buffer(); // increase buffer size let mut target_size = MessageBufferTestContext::DEFAULT_TARGET_SIZE + 10240; let mut target_sizes = vec![]; target_sizes.push(target_size); target_size += 10240; target_sizes.push(target_size); context .resize_msg_buffer( MessageBufferTestContext::DEFAULT_TEST_PRICE_ID, target_sizes, ) .await .unwrap(); let msg_buffer_account_data = context .fetch_msg_buffer_account_data(&msg_buffer_pda) .await .unwrap(); assert_eq!(msg_buffer_account_data.len(), target_size as usize); } #[tokio::test] #[should_panic] async fn fail_resize_buffer_invalid_increase() { let mut context = MessageBufferTestContext::initialize_with_default_test_buffer( false, MessageBufferTestContext::DEFAULT_TARGET_SIZE, ) .await .unwrap(); let whitelist = context.whitelist(); let admin = context.admin(); let cpi_caller_auth = MessageBufferTestContext::get_mock_cpi_auth(); let pyth_price_acct = MessageBufferTestContext::default_pyth_price_account(); let (msg_buffer_pda, msg_buffer_bump) = MessageBufferTestContext::default_msg_buffer(); // increase buffer size beyond maximum allowed let target_size = MessageBufferTestContext::DEFAULT_TARGET_SIZE + 10240 + 100; let resize_ix = resize_msg_buffer_ix( cpi_caller_auth, pyth_price_acct, target_size, whitelist, admin.pubkey(), context.payer.pubkey(), msg_buffer_pda, ); let res = context.process_ixs(&[resize_ix], vec![&admin]).await; assert!(res.is_err()); let err: ProgramError = res.unwrap_err().into(); assert_eq!( err, ProgramError::Custom(anchor_lang::error::ErrorCode::AccountReallocExceedsLimit.into()) ); let msg_buffer_account_data = context .fetch_msg_buffer_account_data(&msg_buffer_pda) .await .unwrap(); assert_eq!( msg_buffer_account_data.len(), MessageBufferTestContext::DEFAULT_TARGET_SIZE as usize ); let (bump, _version, _header_len, end_offsets) = deserialize_msg_buffer_header(&msg_buffer_account_data); assert_eq!(bump, msg_buffer_bump); assert_eq!(end_offsets, [0u16; 255]); // shrink buffer size to less than MessageBuffer::HEADER_LEN let target_size = 15; let resize_ix = resize_msg_buffer_ix( cpi_caller_auth, pyth_price_acct, target_size, whitelist, admin.pubkey(), context.payer.pubkey(), msg_buffer_pda, ); // a target_size less than the MessageBuffer::HEADER_LEN // will result in a `ProgramFailedToComplete` (or AccountDiscriminatorNotFound // if target_size < 8) since after the realloc, // the AccountLoadder.load/load_mut() calls will fail context .process_ixs(&[resize_ix], vec![&admin]) .await .unwrap(); } #[tokio::test] async fn test_resize_initialized_buffer() { let mut context = MessageBufferTestContext::initialize_with_default_test_buffer( false, MessageBufferTestContext::DEFAULT_TARGET_SIZE, ) .await .unwrap(); let payer = context.payer.pubkey(); let whitelist = context.whitelist(); let cpi_caller_auth = MessageBufferTestContext::get_mock_cpi_auth(); let (msg_buffer_pda, msg_buffer_bump) = MessageBufferTestContext::default_msg_buffer(); let add_price_params = MessageBufferTestContext::DEFAULT_ADD_PRICE_PARAMS; context .add_price(add_price_params, payer, whitelist, cpi_caller_auth) .await .unwrap(); let (id, price, price_expo, ema, ema_expo) = add_price_params; let msg_buffer_account_data = context .fetch_msg_buffer_account_data(&msg_buffer_pda) .await .unwrap(); let (bump, _version, header_len, end_offsets) = deserialize_msg_buffer_header(&msg_buffer_account_data); assert_eq!(bump, msg_buffer_bump); // size_of(price::MessageHeader) + FullPriceMessage::SIZE let msg_size_0 = 7 + 40; assert_eq!(&end_offsets[0], &msg_size_0); // size_of(price::MessageHeader) + CompactPriceMessage::SIZE let msg_size_1 = 7 + 24; assert_eq!(&end_offsets[1], &(msg_size_0 + msg_size_1)); assert_eq!(&end_offsets[2..], &[0u16; 253]); let msgs = extract_msg_buffer_messages(header_len, end_offsets, &msg_buffer_account_data); validate_price_msgs(id, price, price_expo, ema, ema_expo, &msgs).unwrap(); // increase buffer size should not edit the original data let target_size = MessageBufferTestContext::DEFAULT_TARGET_SIZE + 10240; let target_sizes = vec![target_size]; context .resize_msg_buffer( MessageBufferTestContext::DEFAULT_TEST_PRICE_ID, target_sizes, ) .await .unwrap(); let msg_buffer_account_data = context .fetch_msg_buffer_account_data(&msg_buffer_pda) .await .unwrap(); let (bump, _version, header_len, end_offsets) = deserialize_msg_buffer_header(&msg_buffer_account_data); assert_eq!(bump, msg_buffer_bump); // size_of(price::MessageHeader) + FullPriceMessage::SIZE let msg_size_0 = 7 + 40; assert_eq!(&end_offsets[0], &msg_size_0); // size_of(price::MessageHeader) + CompactPriceMessage::SIZE let msg_size_1 = 7 + 24; assert_eq!(&end_offsets[1], &(msg_size_0 + msg_size_1)); assert_eq!(&end_offsets[2..], &[0u16; 253]); let msgs = extract_msg_buffer_messages(header_len, end_offsets, &msg_buffer_account_data); validate_price_msgs(id, price, price_expo, ema, ema_expo, &msgs).unwrap(); } #[tokio::test] async fn fail_resize_initialized_buffer() { let mut context = MessageBufferTestContext::initialize_with_default_test_buffer( false, MessageBufferTestContext::DEFAULT_TARGET_SIZE, ) .await .unwrap(); let payer = context.payer.pubkey(); let admin = context.admin(); let pyth_price_acct = MessageBufferTestContext::default_pyth_price_account(); let whitelist = context.whitelist(); let cpi_caller_auth = MessageBufferTestContext::get_mock_cpi_auth(); let (msg_buffer_pda, _msg_buffer_bump) = MessageBufferTestContext::default_msg_buffer(); let add_price_params = MessageBufferTestContext::DEFAULT_ADD_PRICE_PARAMS; context .add_price(add_price_params, payer, whitelist, cpi_caller_auth) .await .unwrap(); let msg_buffer_account_data = context .fetch_msg_buffer_account_data(&msg_buffer_pda) .await .unwrap(); let (_, _version, header_len, end_offsets) = deserialize_msg_buffer_header(&msg_buffer_account_data); let max_end_offset = end_offsets.iter().max().unwrap(); let min_size = header_len + max_end_offset; // decrease buffer size to less than something that can fit the current messages let target_size = (min_size as u32) - 1; let resize_ix = resize_msg_buffer_ix( cpi_caller_auth, pyth_price_acct, target_size, whitelist, admin.pubkey(), context.payer.pubkey(), msg_buffer_pda, ); let res = context.process_ixs(&[resize_ix], vec![&admin]).await; assert!(res.is_err()); let err: ProgramError = res.unwrap_err().into(); assert_eq!( err, ProgramError::Custom(MessageBufferError::MessageBufferTooSmall.into()) ); let target_size = (min_size as u32) + 1; let resize_ix = resize_msg_buffer_ix( cpi_caller_auth, pyth_price_acct, target_size, whitelist, admin.pubkey(), context.payer.pubkey(), msg_buffer_pda, ); let res = context.process_ixs(&[resize_ix], vec![&admin]).await; assert!(res.is_ok()); let msg_buffer_account_data = context .fetch_msg_buffer_account_data(&msg_buffer_pda) .await .unwrap(); assert_eq!(msg_buffer_account_data.len(), target_size as usize); } #[tokio::test] async fn fail_resize_buffer_exceed_max_size() { let mut context = MessageBufferTestContext::initialize_with_default_test_buffer( false, MessageBufferTestContext::DEFAULT_TARGET_SIZE, ) .await .unwrap(); let whitelist = context.whitelist(); let admin = context.admin(); let cpi_caller_auth = MessageBufferTestContext::get_mock_cpi_auth(); let pyth_price_acct = MessageBufferTestContext::default_pyth_price_account(); let (msg_buffer_pda, _msg_buffer_bump) = MessageBufferTestContext::default_msg_buffer(); // increase buffer size beyond maximum allowed let mut target_size = MessageBufferTestContext::DEFAULT_TARGET_SIZE + 10240; while target_size < u32::from(u16::MAX) { let resize_ix = resize_msg_buffer_ix( cpi_caller_auth, pyth_price_acct, target_size, whitelist, admin.pubkey(), context.payer.pubkey(), msg_buffer_pda, ); let res = context.process_ixs(&[resize_ix], vec![&admin]).await; assert!(res.is_ok()); target_size += 10240; } let resize_ix = resize_msg_buffer_ix( cpi_caller_auth, pyth_price_acct, target_size, whitelist, admin.pubkey(), context.payer.pubkey(), msg_buffer_pda, ); let res = context.process_ixs(&[resize_ix], vec![&admin]).await; assert!(res.is_err()); let err: ProgramError = res.unwrap_err().into(); assert_eq!( err, ProgramError::Custom(MessageBufferError::TargetSizeExceedsMaxLen.into()) ); }