Skip to content

Commit 590f9d0

Browse files
authored
Move data-driven aggregation logic tests to rust (#346)
* initial test works * fix this * fix json formatting * move files * get rid of c tests * restore * fix build ?? * gr * format
1 parent 4be6122 commit 590f9d0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+110
-109
lines changed

CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,15 +108,16 @@ target_link_libraries( test_net ${PC_DEP} )
108108
# add_executable( test_publish_websocket pctest/test_publish_websocket.cpp )
109109
# target_link_libraries( test_publish_websocket Qt5::Core Qt5::Network Qt5::WebSockets /usr/local/lib/libjcon.so)
110110

111-
add_executable( test_qset pctest/test_qset.cpp )
112-
target_link_libraries( test_qset ${PC_DEP} )
111+
add_executable( test_pd pctest/test_pd.cpp )
112+
target_link_libraries( test_pd ${PC_DEP} )
113113
add_executable( test_twap pctest/test_twap.cpp )
114114
target_link_libraries( test_twap ${PC_DEP} )
115115
add_executable( leader_stats pctest/leader_stats.cpp )
116116
target_link_libraries( leader_stats ${PC_DEP} )
117117

118118
add_test( test_unit test_unit )
119119
add_test( test_net test_net )
120+
add_test( test_pd test_pd )
120121

121122

122123
#

pctest/test_qset.cpp renamed to pctest/test_pd.cpp

Lines changed: 1 addition & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -99,91 +99,10 @@ void test_pd()
9999
PC_TEST_CHECK( pd_gt( n2, n1, dec_fact ) );
100100
}
101101

102-
void test_qs()
102+
int main(int,char**)
103103
{
104104
PC_TEST_START
105105
test_pd();
106106
PC_TEST_END
107-
}
108-
109-
int main( int argc,char** argv )
110-
{
111-
if ( argc < 2 ) {
112-
return usage();
113-
}
114-
// unit test piece first
115-
test_qs();
116-
117-
// construct quotes
118-
mem_map mf;
119-
std::string file = argv[1];
120-
mf.set_file(file );
121-
if ( !mf.init() ) {
122-
std::cerr << "test_qset: failed to read file[" << file << "]"
123-
<< std::endl;
124-
return 1;
125-
}
126-
jtree pt;
127-
pt.parse( mf.data(), mf.size() );
128-
if ( !pt.is_valid() ) {
129-
std::cerr << "test_qset: failed to parse file[" << file << "]"
130-
<< std::endl;
131-
return 1;
132-
}
133-
pc_price_t px[1];
134-
__builtin_memset( px, 0, sizeof( pc_price_t ) );
135-
uint64_t slot = 1000UL;
136-
px->last_slot_ = slot;
137-
px->agg_.pub_slot_ = slot;
138-
px->expo_ = pt.get_int( pt.find_val( 1, "exponent" ) );
139-
px->num_ = 0;
140-
uint32_t qt =pt.find_val( 1, "quotes" );
141-
for( uint32_t it = pt.get_first( qt ); it; it = pt.get_next( it ) ) {
142-
pc_price_comp_t *ptr = &px->comp_[px->num_++];
143-
ptr->latest_.status_ = pt.get_int( pt.find_val( it, "status" ) );
144-
ptr->latest_.price_ = pt.get_int( pt.find_val( it, "price" ) );
145-
int64_t conf = pt.get_int( pt.find_val( it, "conf" ) );
146-
assert( conf >= 0 );
147-
ptr->latest_.conf_ = static_cast< uint64_t >( conf );
148-
int64_t pub_slot = pt.get_int( pt.find_val( it, "slot_diff" ) );
149-
ptr->latest_.pub_slot_ =
150-
static_cast< uint64_t >( static_cast< int64_t >( slot ) + pub_slot );
151-
}
152-
upd_aggregate( px, slot+1, 1234 );
153-
154-
char const* status = "invalid value";
155-
switch ( px->agg_.status_ ) {
156-
case PC_STATUS_UNKNOWN:
157-
status = "unknown";
158-
break;
159-
case PC_STATUS_TRADING:
160-
status = "trading";
161-
break;
162-
case PC_STATUS_HALTED:
163-
status = "halted";
164-
break;
165-
case PC_STATUS_AUCTION:
166-
status = "auction";
167-
break;
168-
}
169-
170-
// generate result
171-
json_wtr jw;
172-
jw.add_val( json_wtr::e_obj );
173-
jw.add_key( "exponent", (int64_t)px->expo_ );
174-
jw.add_key( "price", px->agg_.price_ );
175-
jw.add_key( "conf", px->agg_.conf_ );
176-
jw.add_key( "status", status );
177-
jw.pop();
178-
net_buf *hd, *tl;
179-
jw.detach( hd, tl );
180-
while( hd ) {
181-
net_buf *nxt = hd->next_;
182-
std::cout.write( hd->buf_, hd->size_ );
183-
hd->dealloc();
184-
hd = nxt;
185-
}
186-
std::cout << std::endl;
187-
188107
return 0;
189108
}

program/rust/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ hex = "0.3.1"
2323
quickcheck = "1"
2424
quickcheck_macros = "1"
2525
bincode = "1.3.3"
26+
serde = { version = "1.0", features = ["derive"] }
27+
serde_json = "1.0"
28+
test-generator = "0.3.1"
2629

2730
[features]
2831
debug = []

program/rust/src/tests/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ mod test_add_mapping;
33
mod test_add_price;
44
mod test_add_product;
55
mod test_add_publisher;
6+
mod test_aggregation;
67
mod test_del_price;
78
mod test_del_product;
89
mod test_del_publisher;
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
use {
2+
crate::{
3+
accounts::PriceAccount,
4+
processor::c_upd_aggregate,
5+
},
6+
bytemuck::Zeroable,
7+
serde::{
8+
Deserialize,
9+
Serialize,
10+
},
11+
std::fs::File,
12+
};
13+
extern crate test_generator;
14+
15+
use test_generator::test_resources;
16+
17+
#[test_resources("program/rust/test_data/aggregation/*.json")]
18+
fn test_quote_set(input_path_raw: &str) {
19+
// For some reason these tests have a different working directory than the macro.
20+
let input_path = input_path_raw.replace("program/rust/", "");
21+
let result_path = input_path.replace(".json", ".result");
22+
23+
let file = File::open(input_path).expect("Test file not found");
24+
let quote_set: QuoteSet = serde_json::from_reader(&file).expect("Unable to parse JSON");
25+
26+
let result_file = File::open(result_path).expect("Test file not found");
27+
let expected_result: QuoteSetResult =
28+
serde_json::from_reader(&result_file).expect("Unable to parse JSON");
29+
30+
let current_slot = 1000; // arbitrary
31+
let current_timestamp = 1234; // also arbitrary
32+
let mut price_account: PriceAccount = PriceAccount::zeroed();
33+
34+
price_account.last_slot_ = current_slot;
35+
price_account.agg_.pub_slot_ = current_slot;
36+
price_account.exponent = quote_set.exponent;
37+
price_account.num_ = quote_set.quotes.len() as u32;
38+
for quote_idx in 0..quote_set.quotes.len() {
39+
let mut current_component = &mut price_account.comp_[quote_idx];
40+
let quote = &quote_set.quotes[quote_idx];
41+
current_component.latest_.status_ = quote.status;
42+
current_component.latest_.price_ = quote.price;
43+
current_component.latest_.conf_ = quote.conf;
44+
let slot_diff = quote.slot_diff.unwrap_or(0);
45+
assert!(slot_diff > -(current_slot as i64));
46+
current_component.latest_.pub_slot_ = ((current_slot as i64) + slot_diff) as u64;
47+
}
48+
49+
unsafe {
50+
c_upd_aggregate(
51+
(&mut price_account as *mut PriceAccount) as *mut u8,
52+
current_slot + 1,
53+
current_timestamp,
54+
);
55+
}
56+
57+
// For some idiotic reason the status in the input is a number and the output is a string.
58+
let result_status: String = match price_account.agg_.status_ {
59+
0 => "unknown",
60+
1 => "trading",
61+
2 => "halted",
62+
3 => "auction",
63+
4 => "ignored",
64+
_ => "invalid status",
65+
}
66+
.into();
67+
68+
let actual_result = QuoteSetResult {
69+
exponent: price_account.exponent,
70+
price: price_account.agg_.price_,
71+
conf: price_account.agg_.conf_,
72+
status: result_status,
73+
};
74+
75+
assert_eq!(expected_result, actual_result);
76+
}
77+
78+
#[derive(Serialize, Deserialize, Debug)]
79+
struct Quote {
80+
price: i64,
81+
conf: u64,
82+
status: u32,
83+
slot_diff: Option<i64>,
84+
}
85+
86+
#[derive(Serialize, Deserialize, Debug)]
87+
struct QuoteSet {
88+
exponent: i32,
89+
quotes: Vec<Quote>,
90+
}
91+
92+
#[derive(Serialize, Deserialize, Debug, PartialEq)]
93+
struct QuoteSetResult {
94+
exponent: i32,
95+
price: i64,
96+
conf: u64,
97+
status: String,
98+
}

pyth/tests/qset/1.json renamed to program/rust/test_data/aggregation/1.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@
44
{
55
"price": 10000,
66
"conf": 1000,
7-
"status": 1,
7+
"status": 1
88
},
99
{
1010
"price": 10000,
1111
"conf": 1000,
12-
"status": 1,
12+
"status": 1
1313
},
1414
{
1515
"price": 10000,
1616
"conf": 1000,
17-
"status": 1,
17+
"status": 1
1818
}
1919
]
2020
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

pyth/tests/qset/39.json renamed to program/rust/test_data/aggregation/39.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"comment": "1 good quote, 1 off by factor of 10 - this is the low quote number, tightest outlier limit."
2+
"comment": "1 good quote, 1 off by factor of 10 - this is the low quote number, tightest outlier limit.",
33
"exponent": -8,
44
"quotes": [
55
{
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

pyth/tests/test_qset.py

Lines changed: 0 additions & 21 deletions
This file was deleted.

0 commit comments

Comments
 (0)