Skip to content

Commit 840b68f

Browse files
authored
Test init mapping (#222)
* First test * Mapping * Delete c version of init_mapping
1 parent 3686a5a commit 840b68f

File tree

5 files changed

+188
-107
lines changed

5 files changed

+188
-107
lines changed

program/c/src/oracle/oracle.c

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -59,33 +59,6 @@ static bool valid_writable_account( SolParameters *prm,
5959
is_rent_exempt( *ka->lamports, ka->data_len );
6060
}
6161

62-
static uint64_t init_mapping( SolParameters *prm, SolAccountInfo *ka )
63-
{
64-
// Verify that the new account is signed and writable, with correct
65-
// ownership and size
66-
if ( prm->ka_num != 2 ||
67-
!valid_funding_account( &ka[0] ) ||
68-
!valid_signable_account( prm, &ka[1], sizeof( pc_map_table_t ) ) ) {
69-
return ERROR_INVALID_ARGUMENT;
70-
}
71-
72-
// Check that the account has not already been initialized
73-
pc_map_table_t *tptr = (pc_map_table_t*)ka[1].data;
74-
if ( tptr->magic_ != 0 || tptr->ver_ != 0 ) {
75-
return ERROR_INVALID_ARGUMENT;
76-
}
77-
78-
// Initialize by setting to zero again (just in case) and setting
79-
// the version number
80-
cmd_hdr_t *hdr = (cmd_hdr_t*)prm->data;
81-
sol_memset( tptr, 0, sizeof( pc_map_table_t ) );
82-
tptr->magic_ = PC_MAGIC;
83-
tptr->ver_ = hdr->ver_;
84-
tptr->type_ = PC_ACCTYPE_MAPPING;
85-
tptr->size_ = sizeof( pc_map_table_t ) - sizeof( tptr->prod_ );
86-
return SUCCESS;
87-
}
88-
8962
static uint64_t add_mapping( SolParameters *prm, SolAccountInfo *ka )
9063
{
9164
// Account (1) is the tail or last mapping account in the chain
@@ -539,7 +512,7 @@ static uint64_t dispatch( SolParameters *prm, SolAccountInfo *ka )
539512
case e_cmd_agg_price: return upd_price( prm, ka );
540513
case e_cmd_upd_price_no_fail_on_error: return upd_price_no_fail_on_error( prm, ka );
541514
// init_mapping is overridden in Rust, but still implemented here to make the C unit tests pass.
542-
case e_cmd_init_mapping: return init_mapping( prm, ka );
515+
case e_cmd_init_mapping: return ERROR_INVALID_ARGUMENT;
543516
case e_cmd_add_mapping: return add_mapping( prm, ka );
544517
case e_cmd_add_product: return add_product( prm, ka );
545518
case e_cmd_upd_product: return upd_product( prm, ka );

program/c/src/oracle/test_oracle.c

Lines changed: 0 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -7,81 +7,6 @@ uint64_t MAPPING_ACCOUNT_LAMPORTS = 143821440;
77
uint64_t PRODUCT_ACCOUNT_LAMPORTS = 4454400;
88
uint64_t PRICE_ACCOUNT_LAMPORTS = 23942400;
99

10-
Test(oracle, init_mapping) {
11-
12-
// start with perfect inputs
13-
cmd_hdr_t idata = {
14-
.ver_ = PC_VERSION,
15-
.cmd_ = e_cmd_init_mapping
16-
};
17-
SolPubkey p_id = {.x = { 0xff, }};
18-
SolPubkey p_id2 = {.x = { 0xfe, }};
19-
SolPubkey pkey = {.x = { 1, }};
20-
SolPubkey mkey = {.x = { 2, }};
21-
uint64_t pqty = 100;
22-
pc_map_table_t mptr[1];
23-
sol_memset( mptr, 0, sizeof( pc_map_table_t ) );
24-
SolAccountInfo acc[] = {{
25-
.key = &pkey,
26-
.lamports = &pqty,
27-
.data_len = 0,
28-
.data = NULL,
29-
.owner = NULL,
30-
.rent_epoch = 0,
31-
.is_signer = true,
32-
.is_writable = true,
33-
.executable = false
34-
},{
35-
.key = &mkey,
36-
.lamports = &MAPPING_ACCOUNT_LAMPORTS,
37-
.data_len = sizeof( pc_map_table_t ),
38-
.data = (uint8_t*)mptr,
39-
.owner = &p_id,
40-
.rent_epoch = 0,
41-
.is_signer = true,
42-
.is_writable = true,
43-
.executable = false
44-
}};
45-
SolParameters prm = {
46-
.ka = acc,
47-
.ka_num = 2,
48-
.data = (const uint8_t*)&idata,
49-
.data_len = sizeof( idata ),
50-
.program_id = &p_id
51-
};
52-
cr_assert( SUCCESS == dispatch( &prm, acc ) );
53-
cr_assert( mptr->ver_ == PC_VERSION );
54-
cr_assert( mptr->type_ == PC_ACCTYPE_MAPPING );
55-
56-
// cant reinitialize because version has been set
57-
cr_assert( ERROR_INVALID_ARGUMENT == dispatch( &prm, acc ) );
58-
sol_memset( mptr, 0, sizeof( pc_map_table_t ) );
59-
60-
// check other params
61-
prm.ka_num = 1;
62-
cr_assert( ERROR_INVALID_ARGUMENT == dispatch( &prm, acc ) );
63-
prm.ka_num = 2;
64-
acc[0].is_signer = false;
65-
cr_assert( ERROR_INVALID_ARGUMENT == dispatch( &prm, acc ) );
66-
acc[0].is_signer = true;
67-
acc[1].is_signer = false;
68-
cr_assert( ERROR_INVALID_ARGUMENT == dispatch( &prm, acc ) );
69-
acc[1].is_signer = true;
70-
acc[0].is_writable = false;
71-
cr_assert( ERROR_INVALID_ARGUMENT == dispatch( &prm, acc ) );
72-
acc[0].is_writable = true;
73-
acc[1].is_writable = false;
74-
cr_assert( ERROR_INVALID_ARGUMENT == dispatch( &prm, acc ) );
75-
acc[1].is_writable = true;
76-
acc[1].owner = &p_id2;
77-
cr_assert( ERROR_INVALID_ARGUMENT == dispatch( &prm, acc ) );
78-
acc[1].owner = &p_id;
79-
acc[1].data_len = 0;
80-
cr_assert( ERROR_INVALID_ARGUMENT == dispatch( &prm, acc ) );
81-
acc[1].data_len = sizeof( pc_map_table_t );
82-
cr_assert( SUCCESS == dispatch( &prm, acc ) );
83-
}
84-
8510
Test(oracle, add_mapping ) {
8611
// start with perfect inputs
8712
cmd_hdr_t idata = {

program/rust/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ mod error;
1010
mod log;
1111
mod processor;
1212
mod rust_oracle;
13+
mod test_oracle;
1314
mod time_machine_types;
1415
mod utils;
1516

program/rust/src/rust_oracle.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ use bytemuck::{
1313
try_from_bytes_mut,
1414
Pod,
1515
};
16+
use solana_program::account_info::AccountInfo;
1617
use solana_program::entrypoint::SUCCESS;
1718
use solana_program::program_error::ProgramError;
1819
use solana_program::program_memory::sol_memset;
1920
use solana_program::pubkey::Pubkey;
2021
use solana_program::rent::Rent;
21-
use solana_program::sysvar::slot_history::AccountInfo;
2222

2323
use crate::c_oracle_header::{
2424
cmd_hdr_t,
@@ -143,7 +143,7 @@ fn valid_fresh_account(account: &AccountInfo) -> bool {
143143
}
144144

145145
/// Sets the data of account to all-zero
146-
fn clear_account(account: &AccountInfo) -> Result<(), ProgramError> {
146+
pub fn clear_account(account: &AccountInfo) -> Result<(), ProgramError> {
147147
let mut data = account
148148
.try_borrow_mut_data()
149149
.map_err(|_| ProgramError::InvalidArgument)?;
@@ -164,7 +164,7 @@ fn load_mut<T: Pod>(data: &mut [u8]) -> Result<&mut T, ProgramError> {
164164
}
165165

166166
/// Get the data stored in `account` as a value of type `T`
167-
fn load_account_as<'a, T: Pod>(account: &'a AccountInfo) -> Result<Ref<'a, T>, ProgramError> {
167+
pub fn load_account_as<'a, T: Pod>(account: &'a AccountInfo) -> Result<Ref<'a, T>, ProgramError> {
168168
let data = account.try_borrow_data()?;
169169

170170
Ok(Ref::map(data, |data| {
@@ -174,7 +174,7 @@ fn load_account_as<'a, T: Pod>(account: &'a AccountInfo) -> Result<Ref<'a, T>, P
174174

175175
/// Mutably borrow the data in `account` as a value of type `T`.
176176
/// Any mutations to the returned value will be reflected in the account data.
177-
fn load_account_as_mut<'a, T: Pod>(
177+
pub fn load_account_as_mut<'a, T: Pod>(
178178
account: &'a AccountInfo,
179179
) -> Result<RefMut<'a, T>, ProgramError> {
180180
let data = account.try_borrow_mut_data()?;

program/rust/src/test_oracle.rs

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
#[cfg(test)]
2+
mod test {
3+
use crate::c_oracle_header::{
4+
cmd_hdr_t,
5+
command_t_e_cmd_init_mapping,
6+
pc_map_table_t,
7+
PC_ACCTYPE_MAPPING,
8+
PC_MAGIC,
9+
PC_VERSION,
10+
};
11+
use crate::rust_oracle::{
12+
clear_account,
13+
init_mapping,
14+
load_account_as,
15+
};
16+
use bytemuck::bytes_of;
17+
use solana_program::account_info::AccountInfo;
18+
use solana_program::clock::Epoch;
19+
use solana_program::native_token::LAMPORTS_PER_SOL;
20+
use solana_program::program_error::ProgramError;
21+
use solana_program::pubkey::Pubkey;
22+
use solana_program::rent::Rent;
23+
use solana_program::system_program;
24+
use std::cell::RefCell;
25+
use std::mem::size_of;
26+
use std::rc::Rc;
27+
28+
#[test]
29+
fn test_init_mapping() {
30+
let hdr: cmd_hdr_t = cmd_hdr_t {
31+
ver_: PC_VERSION,
32+
cmd_: command_t_e_cmd_init_mapping as i32,
33+
};
34+
let instruction_data = bytes_of::<cmd_hdr_t>(&hdr);
35+
36+
let program_id = Pubkey::new_unique();
37+
let program_id_2 = Pubkey::new_unique();
38+
let funding_key = Pubkey::new_unique();
39+
let mapping_key = Pubkey::new_unique();
40+
let system_program = system_program::id();
41+
42+
let mut funding_balance = LAMPORTS_PER_SOL.clone();
43+
let mut funding_account = AccountInfo::new(
44+
&funding_key,
45+
true,
46+
true,
47+
&mut funding_balance,
48+
&mut [],
49+
&system_program,
50+
false,
51+
Epoch::default(),
52+
);
53+
54+
let mut mapping_balance =
55+
Rent::minimum_balance(&Rent::default(), size_of::<pc_map_table_t>());
56+
let mut mapping_raw_data = [0u8; size_of::<pc_map_table_t>()];
57+
58+
let mut mapping_account = AccountInfo::new(
59+
&mapping_key,
60+
true,
61+
true,
62+
&mut mapping_balance,
63+
&mut mapping_raw_data,
64+
&program_id,
65+
false,
66+
Epoch::default(),
67+
);
68+
69+
assert!(init_mapping(
70+
&program_id,
71+
&[funding_account.clone(), mapping_account.clone()],
72+
instruction_data
73+
)
74+
.is_ok());
75+
76+
{
77+
let mapping_data = load_account_as::<pc_map_table_t>(&mapping_account).unwrap();
78+
79+
assert_eq!(mapping_data.ver_, PC_VERSION);
80+
assert_eq!(mapping_data.magic_, PC_MAGIC);
81+
assert_eq!(mapping_data.type_, PC_ACCTYPE_MAPPING);
82+
assert_eq!(mapping_data.size_, 56);
83+
}
84+
85+
assert_eq!(
86+
init_mapping(
87+
&program_id,
88+
&[funding_account.clone(), mapping_account.clone()],
89+
instruction_data
90+
),
91+
Err(ProgramError::InvalidArgument)
92+
);
93+
94+
clear_account(&mapping_account).unwrap();
95+
96+
assert_eq!(
97+
init_mapping(&program_id, &[funding_account.clone()], instruction_data),
98+
Err(ProgramError::InvalidArgument)
99+
);
100+
101+
funding_account.is_signer = false;
102+
103+
assert_eq!(
104+
init_mapping(
105+
&program_id,
106+
&[funding_account.clone(), mapping_account.clone()],
107+
instruction_data
108+
),
109+
Err(ProgramError::InvalidArgument)
110+
);
111+
112+
funding_account.is_signer = true;
113+
mapping_account.is_signer = false;
114+
115+
assert_eq!(
116+
init_mapping(
117+
&program_id,
118+
&[funding_account.clone(), mapping_account.clone()],
119+
instruction_data
120+
),
121+
Err(ProgramError::InvalidArgument)
122+
);
123+
124+
mapping_account.is_signer = true;
125+
funding_account.is_writable = false;
126+
127+
assert_eq!(
128+
init_mapping(
129+
&program_id,
130+
&[funding_account.clone(), mapping_account.clone()],
131+
instruction_data
132+
),
133+
Err(ProgramError::InvalidArgument)
134+
);
135+
136+
funding_account.is_writable = true;
137+
mapping_account.is_writable = false;
138+
139+
assert_eq!(
140+
init_mapping(
141+
&program_id,
142+
&[funding_account.clone(), mapping_account.clone()],
143+
instruction_data
144+
),
145+
Err(ProgramError::InvalidArgument)
146+
);
147+
148+
mapping_account.is_writable = true;
149+
mapping_account.owner = &program_id_2;
150+
151+
assert_eq!(
152+
init_mapping(
153+
&program_id,
154+
&[funding_account.clone(), mapping_account.clone()],
155+
instruction_data
156+
),
157+
Err(ProgramError::InvalidArgument)
158+
);
159+
160+
mapping_account.owner = &program_id;
161+
let prev_data = mapping_account.data;
162+
mapping_account.data = Rc::new(RefCell::new(&mut []));
163+
164+
assert_eq!(
165+
init_mapping(
166+
&program_id,
167+
&[funding_account.clone(), mapping_account.clone()],
168+
instruction_data
169+
),
170+
Err(ProgramError::InvalidArgument)
171+
);
172+
173+
mapping_account.data = prev_data;
174+
175+
assert!(init_mapping(
176+
&program_id,
177+
&[funding_account.clone(), mapping_account.clone()],
178+
instruction_data
179+
)
180+
.is_ok());
181+
}
182+
}

0 commit comments

Comments
 (0)