Skip to content

Commit 91acc9e

Browse files
committed
Test: add layout test check Accounts with [repr(packed)]
Due to the changes in Rust 1.80.0, where the fields in struct marked with [repr(packed)] might be reordered. There is necessary to add tests to confirm whether this change will impact the layout of these accounts. More details about the Rust changes at: rust-lang/rust#125360.
1 parent e5783e8 commit 91acc9e

File tree

8 files changed

+706
-15
lines changed

8 files changed

+706
-15
lines changed

Cargo.lock

Lines changed: 26 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
[workspace]
2-
members = [
3-
"programs/*",
4-
"client",
5-
]
2+
resolver = "2"
3+
members = ["programs/*", "client"]
64

75
[profile.test]
86
opt-level = 0

programs/amm/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ paramset = []
2424

2525
[dependencies]
2626
anchor-lang = { version = "0.29.0", features = ["init-if-needed"] }
27-
anchor-spl = {version = "0.29.0", features = ["metadata"]}
27+
anchor-spl = { version = "0.29.0", features = ["metadata"] }
2828
solana-program = "<1.17.0"
2929
spl-memo = "4.0.0"
3030
uint = { git = "https://github.com/raydium-io/parity-common", package = "uint" }
3131
mpl-token-metadata = { version = "^1.11.0", features = ["no-entrypoint"] }
32-
bytemuck = { version = "1.4.0", features = ["derive", "min_const_generics"] }
32+
bytemuck = { version = "1.19.0", features = ["derive", "min_const_generics"] }
3333
arrayref = { version = "0.3.6" }
3434
solana-security-txt = "1.1.1"
3535

@@ -46,4 +46,4 @@ overflow-checks = true
4646
[profile.release.build-override]
4747
opt-level = 3
4848
incremental = false
49-
codegen-units = 1
49+
codegen-units = 1

programs/amm/src/states/operation_account.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,4 +212,55 @@ mod test {
212212
operation_state.remove_operation_owner(keys.clone());
213213
println!("{:?}", operation_state.operation_owners);
214214
}
215+
216+
#[test]
217+
fn operation_layout_test() {
218+
use anchor_lang::Discriminator;
219+
220+
let bump: u8 = 0x12;
221+
let operation_owners: [Pubkey; OPERATION_SIZE_USIZE] =
222+
std::array::from_fn(|_| Pubkey::new_unique());
223+
let whitelist_mints: [Pubkey; WHITE_MINT_SIZE_USIZE] =
224+
std::array::from_fn(|_| Pubkey::new_unique());
225+
226+
// serialize original data
227+
let mut operation_data =
228+
[0u8; 8 + 1 + 32 * OPERATION_SIZE_USIZE + 32 * WHITE_MINT_SIZE_USIZE];
229+
let mut offset = 0;
230+
operation_data[offset..offset + 8].copy_from_slice(&OperationState::discriminator());
231+
offset += 8;
232+
operation_data[offset..offset + 1].copy_from_slice(&bump.to_le_bytes());
233+
offset += 1;
234+
for i in 0..OPERATION_SIZE_USIZE {
235+
operation_data[offset..offset + 32].copy_from_slice(&operation_owners[i].to_bytes());
236+
offset += 32;
237+
}
238+
for i in 0..WHITE_MINT_SIZE_USIZE {
239+
operation_data[offset..offset + 32].copy_from_slice(&whitelist_mints[i].to_bytes());
240+
offset += 32;
241+
}
242+
243+
// len check
244+
assert_eq!(offset, operation_data.len());
245+
assert_eq!(
246+
operation_data.len(),
247+
core::mem::size_of::<OperationState>() + 8
248+
);
249+
250+
// deserialize original data
251+
let unpack_data: &OperationState =
252+
bytemuck::from_bytes(&operation_data[8..core::mem::size_of::<OperationState>() + 8]);
253+
254+
// data check
255+
let unpack_bump = unpack_data.bump;
256+
assert_eq!(unpack_bump, bump);
257+
for i in 0..OPERATION_SIZE_USIZE {
258+
let unpack_operation_owners = unpack_data.operation_owners[i];
259+
assert_eq!(unpack_operation_owners, operation_owners[i]);
260+
}
261+
for i in 0..WHITE_MINT_SIZE_USIZE {
262+
let unpack_whitelist_mints = unpack_data.whitelist_mints[i];
263+
assert_eq!(unpack_whitelist_mints, whitelist_mints[i]);
264+
}
265+
}
215266
}

programs/amm/src/states/oracle.rs

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,117 @@ pub fn block_timestamp_mock() -> u64 {
121121
.unwrap()
122122
.as_secs()
123123
}
124+
125+
#[cfg(test)]
126+
pub mod oracle_layout_test {
127+
use super::*;
128+
use anchor_lang::Discriminator;
129+
#[test]
130+
fn test_observation_layout() {
131+
let initialized = true;
132+
let recent_epoch: u64 = 0x123456789abcdef0;
133+
let observation_index: u16 = 0x1122;
134+
let pool_id: Pubkey = Pubkey::new_unique();
135+
let padding: [u64; 4] = [
136+
0x123456789abcde0f,
137+
0x123456789abcd0ef,
138+
0x123456789abc0def,
139+
0x123456789ab0cdef,
140+
];
141+
142+
let mut observation_datas = [0u8; Observation::LEN * OBSERVATION_NUM];
143+
let mut observations = [Observation::default(); OBSERVATION_NUM];
144+
let mut offset = 0;
145+
for i in 0..OBSERVATION_NUM {
146+
let index = i + 1;
147+
let block_timestamp: u32 = u32::MAX - 3 * index as u32;
148+
let tick_cumulative: i64 = i64::MAX - 3 * index as i64;
149+
let padding: [u64; 4] = [
150+
u64::MAX - index as u64,
151+
u64::MAX - 2 * index as u64,
152+
u64::MAX - 3 * index as u64,
153+
u64::MAX - 4 * index as u64,
154+
];
155+
observations[i].block_timestamp = block_timestamp;
156+
observations[i].tick_cumulative = tick_cumulative;
157+
observations[i].padding = padding;
158+
observation_datas[offset..offset + 4].copy_from_slice(&block_timestamp.to_le_bytes());
159+
offset += 4;
160+
observation_datas[offset..offset + 8].copy_from_slice(&tick_cumulative.to_le_bytes());
161+
offset += 8;
162+
observation_datas[offset..offset + 8].copy_from_slice(&padding[0].to_le_bytes());
163+
offset += 8;
164+
observation_datas[offset..offset + 8].copy_from_slice(&padding[1].to_le_bytes());
165+
offset += 8;
166+
observation_datas[offset..offset + 8].copy_from_slice(&padding[2].to_le_bytes());
167+
offset += 8;
168+
observation_datas[offset..offset + 8].copy_from_slice(&padding[3].to_le_bytes());
169+
offset += 8;
170+
}
171+
172+
// serialize original data
173+
let mut observation_state_data = [0u8; ObservationState::LEN];
174+
let mut offset = 0;
175+
observation_state_data[offset..offset + 8]
176+
.copy_from_slice(&ObservationState::discriminator());
177+
offset += 8;
178+
observation_state_data[offset..offset + 1]
179+
.copy_from_slice(&(initialized as u8).to_le_bytes());
180+
offset += 1;
181+
observation_state_data[offset..offset + 8].copy_from_slice(&recent_epoch.to_le_bytes());
182+
offset += 8;
183+
observation_state_data[offset..offset + 2]
184+
.copy_from_slice(&observation_index.to_le_bytes());
185+
offset += 2;
186+
observation_state_data[offset..offset + 32].copy_from_slice(&pool_id.to_bytes());
187+
offset += 32;
188+
observation_state_data[offset..offset + Observation::LEN * OBSERVATION_NUM]
189+
.copy_from_slice(&observation_datas);
190+
offset += Observation::LEN * OBSERVATION_NUM;
191+
observation_state_data[offset..offset + 8].copy_from_slice(&padding[0].to_le_bytes());
192+
offset += 8;
193+
observation_state_data[offset..offset + 8].copy_from_slice(&padding[1].to_le_bytes());
194+
offset += 8;
195+
observation_state_data[offset..offset + 8].copy_from_slice(&padding[2].to_le_bytes());
196+
offset += 8;
197+
observation_state_data[offset..offset + 8].copy_from_slice(&padding[3].to_le_bytes());
198+
offset += 8;
199+
// len check
200+
assert_eq!(offset, observation_state_data.len());
201+
assert_eq!(
202+
observation_state_data.len(),
203+
core::mem::size_of::<ObservationState>() + 8
204+
);
205+
206+
// deserialize original data
207+
let unpack_data: &ObservationState = bytemuck::from_bytes(
208+
&observation_state_data[8..core::mem::size_of::<ObservationState>() + 8],
209+
);
210+
211+
// data check
212+
let unpack_initialized = unpack_data.initialized;
213+
assert_eq!(unpack_initialized, initialized);
214+
let unpack_recent_epoch = unpack_data.recent_epoch;
215+
assert_eq!(unpack_recent_epoch, recent_epoch);
216+
let unpack_observation_index = unpack_data.observation_index;
217+
assert_eq!(unpack_observation_index, observation_index);
218+
let unpack_pool_id = unpack_data.pool_id;
219+
assert_eq!(unpack_pool_id, pool_id);
220+
let unpack_padding = unpack_data.padding;
221+
assert_eq!(unpack_padding, padding);
222+
for (observation, unpack_observation) in
223+
observations.iter().zip(unpack_data.observations.iter())
224+
{
225+
let block_timestamp = observation.block_timestamp;
226+
let tick_cumulative = observation.tick_cumulative;
227+
let padding = observation.padding;
228+
229+
let unpack_block_timestamp = unpack_observation.block_timestamp;
230+
let unpack_tick_cumulative = unpack_observation.tick_cumulative;
231+
let unpack_padding = unpack_observation.padding;
232+
assert_eq!(block_timestamp, unpack_block_timestamp);
233+
assert_eq!(tick_cumulative, unpack_tick_cumulative);
234+
assert_eq!(padding, unpack_padding);
235+
}
236+
}
237+
}

0 commit comments

Comments
 (0)