Skip to content

Commit e91ffb8

Browse files
committed
test: test aggregation toggle
1 parent 847b3f5 commit e91ffb8

File tree

3 files changed

+125
-62
lines changed

3 files changed

+125
-62
lines changed

program/c/src/oracle/upd_aggregate.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ static inline bool upd_aggregate( pc_price_t *ptr, uint64_t slot, int64_t timest
181181
ptr->num_qt_ = numv;
182182
if ( numv == 0 || numv < ptr->min_pub_ ) {
183183
ptr->agg_.status_ = PC_STATUS_UNKNOWN;
184+
__builtin_printf("numv == 0 || numv < min_pub_ %d\n", numv);
184185
return false;
185186
}
186187

@@ -206,6 +207,7 @@ static inline bool upd_aggregate( pc_price_t *ptr, uint64_t slot, int64_t timest
206207
// positive confidences given the current pricing model
207208
if( agg_conf <= (int64_t)0 ) {
208209
ptr->agg_.status_ = PC_STATUS_UNKNOWN;
210+
__builtin_printf("agg_conf <= 0\n");
209211
return false;
210212
}
211213
}
@@ -216,6 +218,7 @@ static inline bool upd_aggregate( pc_price_t *ptr, uint64_t slot, int64_t timest
216218
ptr->agg_.price_ = agg_price;
217219
ptr->agg_.conf_ = (uint64_t)agg_conf;
218220

221+
__builtin_printf("success\n");
219222
return true;
220223
}
221224

program/rust/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![deny(warnings)]
1+
// #![deny(warnings)]
22
// Allow non upper case globals from C
33
#![allow(non_upper_case_globals)]
44

program/rust/src/tests/test_aggregate_v2.rs

Lines changed: 121 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -6,96 +6,156 @@ use {
66
PriceAccountFlags,
77
PythAccount,
88
},
9-
c_oracle_header::PC_VERSION,
10-
deserialize::load_checked,
9+
c_oracle_header::{PC_STATUS_TRADING, PC_VERSION},
10+
deserialize::{load_checked, load_mut},
1111
instruction::{
1212
AddPublisherArgs,
13-
OracleCommand,
13+
OracleCommand, UpdPriceArgs,
1414
},
1515
processor::{
16-
process_instruction,
17-
ENABLE_ACCUMULATOR_V2,
16+
process_instruction, DISABLE_ACCUMULATOR_V2, ENABLE_ACCUMULATOR_V2
1817
},
19-
tests::test_utils::AccountSetup,
20-
},
21-
bytemuck::bytes_of,
22-
solana_program::{
18+
tests::test_utils::{update_clock_slot, AccountSetup},
19+
}, bytemuck::bytes_of, solana_program::{
2320
pubkey::Pubkey,
2421
rent::Rent,
25-
},
22+
}, solana_sdk::account_info::AccountInfo, std::mem::size_of
2623
};
2724

28-
#[test]
29-
fn test_aggregate_v2() {
30-
let program_id = Pubkey::new_unique();
31-
let publisher = Pubkey::new_unique();
32-
33-
let mut cmd = AddPublisherArgs {
34-
header: OracleCommand::AddPublisher.into(),
35-
publisher,
36-
};
37-
let mut instruction_data = bytes_of::<AddPublisherArgs>(&cmd);
38-
39-
let mut funding_setup = AccountSetup::new_funding();
40-
let funding_account = funding_setup.as_account_info();
25+
struct Accounts {
26+
program_id: Pubkey,
27+
publisher_account: AccountSetup,
28+
funding_account: AccountSetup,
29+
price_account: AccountSetup,
30+
permissions_account: AccountSetup,
31+
clock_account: AccountSetup,
32+
}
4133

42-
let mut price_setup = AccountSetup::new::<PriceAccount>(&program_id);
43-
let price_account = price_setup.as_account_info();
44-
PriceAccount::initialize(&price_account, PC_VERSION).unwrap();
34+
impl Accounts {
35+
fn new() -> Self {
36+
let program_id = Pubkey::new_unique();
37+
let publisher_account = AccountSetup::new_funding();
38+
let clock_account = AccountSetup::new_clock();
39+
let mut funding_account = AccountSetup::new_funding();
40+
let mut permissions_account = AccountSetup::new_permission(&program_id);
41+
let mut price_account = AccountSetup::new::<PriceAccount>(&program_id);
4542

46-
**price_account.try_borrow_mut_lamports().unwrap() = 100;
43+
PriceAccount::initialize(&price_account.as_account_info(), PC_VERSION).unwrap();
4744

48-
let mut permissions_setup = AccountSetup::new_permission(&program_id);
49-
let permissions_account = permissions_setup.as_account_info();
45+
{
46+
let permissions_account_info = permissions_account.as_account_info();
47+
let mut permissions_account_data =
48+
PermissionAccount::initialize(&permissions_account_info, PC_VERSION).unwrap();
49+
permissions_account_data.master_authority = *funding_account.as_account_info().key;
50+
permissions_account_data.data_curation_authority = *funding_account.as_account_info().key;
51+
permissions_account_data.security_authority = *funding_account.as_account_info().key;
52+
}
5053

51-
{
52-
let mut permissions_account_data =
53-
PermissionAccount::initialize(&permissions_account, PC_VERSION).unwrap();
54-
permissions_account_data.master_authority = *funding_account.key;
55-
permissions_account_data.data_curation_authority = *funding_account.key;
56-
permissions_account_data.security_authority = *funding_account.key;
54+
Self {
55+
program_id,
56+
publisher_account,
57+
funding_account,
58+
price_account,
59+
permissions_account,
60+
clock_account,
61+
}
5762
}
63+
}
5864

59-
// Give the price account enough lamports to be rent exempt
60-
**price_account.try_borrow_mut_lamports().unwrap() =
61-
Rent::minimum_balance(&Rent::default(), PriceAccount::MINIMUM_SIZE);
65+
fn add_publisher(accounts: &mut Accounts, publisher: Option<Pubkey>) {
66+
let args = AddPublisherArgs {
67+
header: OracleCommand::AddPublisher.into(),
68+
publisher: publisher.unwrap_or(*accounts.publisher_account.as_account_info().key),
69+
};
6270

6371
assert!(process_instruction(
64-
&program_id,
72+
&accounts.program_id,
6573
&[
66-
funding_account.clone(),
67-
price_account.clone(),
68-
permissions_account.clone(),
74+
accounts.funding_account.as_account_info(),
75+
accounts.price_account.as_account_info(),
76+
accounts.permissions_account.as_account_info(),
6977
],
70-
instruction_data
78+
bytes_of::<AddPublisherArgs>(&args)
7179
)
7280
.is_ok());
81+
}
7382

74-
{
75-
let price_data = load_checked::<PriceAccount>(&price_account, PC_VERSION).unwrap();
76-
assert_eq!(price_data.num_, 1);
77-
assert_eq!(price_data.header.size, PriceAccount::INITIAL_SIZE);
78-
assert!(price_data.comp_[0].pub_ == publisher);
79-
// Make sure that v2 aggregation is disabled
80-
assert!(!price_data.flags.contains(PriceAccountFlags::ACCUMULATOR_V2));
81-
}
83+
fn update_price(accounts: &mut Accounts, price: i64, conf: u64, slot: u64) {
84+
let instruction_data = &mut [0u8; size_of::<UpdPriceArgs>()];
85+
let mut cmd = load_mut::<UpdPriceArgs>(instruction_data).unwrap();
86+
cmd.header = OracleCommand::UpdPrice.into();
87+
cmd.status = PC_STATUS_TRADING;
88+
cmd.price = price;
89+
cmd.confidence = conf;
90+
cmd.publishing_slot = slot;
91+
cmd.unused_ = 0;
8292

83-
cmd.publisher = ENABLE_ACCUMULATOR_V2.into();
84-
instruction_data = bytes_of::<AddPublisherArgs>(&cmd);
85-
assert!(process_instruction(
86-
&program_id,
93+
let mut clock = accounts.clock_account.as_account_info();
94+
clock.is_signer = false;
95+
clock.is_writable = false;
96+
97+
process_instruction(
98+
&accounts.program_id,
8799
&[
88-
funding_account.clone(),
89-
price_account.clone(),
90-
permissions_account.clone(),
100+
accounts.publisher_account.as_account_info(),
101+
accounts.price_account.as_account_info(),
102+
clock,
91103
],
92104
instruction_data
93105
)
94-
.is_ok());
106+
.unwrap();
107+
}
108+
109+
#[test]
110+
fn test_aggregate_v2_toggle() {
111+
let accounts = &mut Accounts::new();
112+
113+
// Add an initial Publisher to test with.
114+
add_publisher(accounts, None);
115+
116+
// Update the price, no aggregation will happen on the first slot.
117+
{
118+
update_clock_slot(&mut accounts.clock_account.as_account_info(), 1);
119+
update_price(accounts, 42, 2, 1);
120+
let info = accounts.price_account.as_account_info();
121+
let price_data = load_checked::<PriceAccount>(&info, PC_VERSION).unwrap();
122+
assert_eq!(price_data.last_slot_, 0);
123+
assert!(!price_data.flags.contains(PriceAccountFlags::ACCUMULATOR_V2));
124+
}
125+
126+
// Update again, component is now TRADING so aggregation should trigger.
127+
{
128+
update_clock_slot(&mut accounts.clock_account.as_account_info(), 2);
129+
update_price(accounts, 42, 2, 2);
130+
let info = accounts.price_account.as_account_info();
131+
let price_data = load_checked::<PriceAccount>(&info, PC_VERSION).unwrap();
132+
assert_eq!(price_data.last_slot_, 2);
133+
assert!(!price_data.flags.contains(PriceAccountFlags::ACCUMULATOR_V2));
134+
}
95135

96-
// Make sure that v2 aggregation is enabled
136+
// Enable v2 Aggregation
137+
add_publisher(accounts, Some(ENABLE_ACCUMULATOR_V2.into()));
138+
139+
// Update again, with accumulator bit set, aggregation should not have
140+
// happened, as its now the validators job.
97141
{
98-
let price_data = load_checked::<PriceAccount>(&price_account, PC_VERSION).unwrap();
142+
update_clock_slot(&mut accounts.clock_account.as_account_info(), 3);
143+
update_price(accounts, 42, 2, 3);
144+
let info = accounts.price_account.as_account_info();
145+
let price_data = load_checked::<PriceAccount>(&info, PC_VERSION).unwrap();
146+
assert_eq!(price_data.last_slot_, 2);
99147
assert!(price_data.flags.contains(PriceAccountFlags::ACCUMULATOR_V2));
100148
}
149+
150+
add_publisher(accounts, Some(DISABLE_ACCUMULATOR_V2.into()));
151+
152+
// Confirm disabling v2 Aggregation re-enables the aggregation flow.
153+
{
154+
update_clock_slot(&mut accounts.clock_account.as_account_info(), 4);
155+
update_price(accounts, 42, 2, 4);
156+
let info = accounts.price_account.as_account_info();
157+
let price_data = load_checked::<PriceAccount>(&info, PC_VERSION).unwrap();
158+
assert_eq!(price_data.last_slot_, 4);
159+
assert!(!price_data.flags.contains(PriceAccountFlags::ACCUMULATOR_V2));
160+
}
101161
}

0 commit comments

Comments
 (0)