Skip to content

Commit

Permalink
test(ticker): covers proxy_price_provider
Browse files Browse the repository at this point in the history
  • Loading branch information
jurajpiar committed Oct 10, 2023
1 parent 3edecff commit 8bc9ac4
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 43 deletions.
208 changes: 168 additions & 40 deletions core/bin/zksync_api/src/bin/providers/proxy_price_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ async fn fetch_coins_list(_: web::Data<AppState>, _: web::Path<(bool,)>) -> Http
async fn fetch_market_chart(reqest: HttpRequest) -> HttpResponse {
let data: &web::Data<AppState> = reqest.app_data().unwrap();
let query = reqest.query_string();
let path = reqest.path().to_string();
let path: String = reqest.path().to_string();
let forward_url = match query.is_empty() {
true => reqest.uri().to_string(),
false => format!("{}{}/{}?{}", API_URL, API_PATH, path, query),
Expand Down Expand Up @@ -69,42 +69,170 @@ pub(crate) fn create_price_service() -> Scope {
)
}

// TODO: finish test
// #[cfg(test)]
// test that the fetch_market_chart forwards any path arguments after question mark to the proxy_request
// mod fetch_market_chart_tests {
// use super::*;
// use actix_web::{test, App};

// #[actix_web::test]
// async fn forwards_path_arguments() {
// let proxied_app = test::init_service(
// App::new()
// .app_data(ProxyState {
// cache: std::sync::Arc::new(Mutex::new(HashMap::new())),
// })
// .route(
// "/coins/{coin_id}/market_chart",
// web::get().to(|| async move { HttpResponse::Ok().body("proxied") }),
// ),
// );

// let test_app = test::init_service(
// App::new()
// .app_data(ProxyState {
// cache: std::sync::Arc::new(Mutex::new(HashMap::new())),
// })
// .route(
// "/coins/{coin_id}/market_chart",
// web::get().to(fetch_market_chart),
// ),
// )
// .await;

// let req = test::TestRequest::get()
// .uri("/coins/rif-token/market_chart?vs_currency=usd&days=1")
// .to_request();
// let resp = test::call_service(&test_app, req).await;
// assert!(resp.status().is_success());
// }
// }
#[cfg(test)]
mod fetch_market_chart_tests {
use crate::providers::test_utils::{FakeBody, FakeHttpClient};

use super::*;
use actix_web::{test, App};

#[actix_web::test]
async fn changes_url() {
let test_app = test::init_service(
#[allow(deprecated)]
// Allowed deprecated .data function as .app_data is not working inside the test service
App::new()
.data(AppState {
proxy_state: ProxyState {
cache: std::sync::Arc::new(Mutex::new(HashMap::new())),
},
proxy_client: Box::<FakeHttpClient>::default(),
})
.route(
"/coins/{coin_id}/market_chart",
web::get().to(fetch_market_chart),
),
)
.await;
let req = test::TestRequest::get()
.uri("/coins/rif-token/market_chart?vs_currency=usd&days=1")
.to_request();
let response = test::call_service(&test_app, req).await;
assert!(response.status().is_success());

let body_bytes = match response.response().body() {
actix_web::body::Body::Bytes(b) => b.clone(),
_ => actix_web::web::Bytes::default(),
};
let body: FakeBody = serde_json::from_slice(&body_bytes).unwrap();

assert!(body
.called_url
.starts_with(&(API_URL.to_owned() + API_PATH)));
}

#[actix_web::test]
async fn forwards_no_path_arguments() {
let test_app = test::init_service(
#[allow(deprecated)]
// Allowed deprecated .data function as .app_data is not working inside the test service
App::new()
.data(AppState {
proxy_state: ProxyState {
cache: std::sync::Arc::new(Mutex::new(HashMap::new())),
},
proxy_client: Box::<FakeHttpClient>::default(),
})
.route(
"/coins/{coin_id}/market_chart",
web::get().to(fetch_market_chart),
),
)
.await;
let req = test::TestRequest::get()
.uri("/coins/rif-token/market_chart")
.to_request();
let response = test::call_service(&test_app, req).await;
assert!(response.status().is_success());

let body_bytes = match response.response().body() {
actix_web::body::Body::Bytes(b) => b.clone(),
_ => actix_web::web::Bytes::default(),
};
let body: FakeBody = serde_json::from_slice(&body_bytes).unwrap();

assert!(body.called_url.ends_with("/coins/rif-token/market_chart"));
}

#[actix_web::test]
async fn forwards_path_arguments() {
let test_app = test::init_service(
#[allow(deprecated)]
// Allowed deprecated .data function as .app_data is not working inside the test service
App::new()
.data(AppState {
proxy_state: ProxyState {
cache: std::sync::Arc::new(Mutex::new(HashMap::new())),
},
proxy_client: Box::<FakeHttpClient>::default(),
})
.route(
"/coins/{coin_id}/market_chart",
web::get().to(fetch_market_chart),
),
)
.await;
let expected_arguments = "?vs_currency=usd&days=1";
let req = test::TestRequest::get()
.uri(&("/coins/rif-token/market_chart".to_owned() + expected_arguments))
.to_request();
let response = test::call_service(&test_app, req).await;
assert!(response.status().is_success());

let body_bytes = match response.response().body() {
actix_web::body::Body::Bytes(b) => b.clone(),
_ => actix_web::web::Bytes::default(),
};
let body: FakeBody = serde_json::from_slice(&body_bytes).unwrap();

assert!(body.called_url.ends_with(expected_arguments));
}
}

#[cfg(test)]
mod fetch_coins_list_tests {
use crate::providers::test_utils::FakeHttpClient;

use super::*;

#[actix_web::test]
async fn returns_hardcoded_tokens() {
let response: HttpResponse = fetch_coins_list(
web::Data::new(AppState {
proxy_state: ProxyState {
cache: std::sync::Arc::new(Mutex::new(HashMap::new())),
},
proxy_client: Box::<FakeHttpClient>::default(),
}),
web::Path::from((true,)),
)
.await;
assert!(response.status().is_success());

let body_bytes = match response.body() {
actix_web::body::Body::Bytes(b) => b.clone(),
_ => actix_web::web::Bytes::default(),
};
let body: Vec<CoinsListItem> = serde_json::from_slice(&body_bytes).unwrap();

let rif_token = body.iter().find(|coin| coin.id == "rif-token").unwrap();
let rbtc = body.iter().find(|coin| coin.id == "rootstock").unwrap();

assert_eq!(body.len(), 2);
assert_eq!(rif_token.name, "RIF Token");
assert_eq!(rif_token.symbol, "TRIF");
assert_eq!(
rif_token
.platforms
.as_ref()
.unwrap()
.get("rootstock")
.unwrap()
.as_ref()
.unwrap(),
RIF_TOKEN_TESTNET_ADDRESS
);
assert_eq!(rbtc.name, "Rootstock RSK");
assert_eq!(rbtc.symbol, "TRBTC");
assert_eq!(
rbtc.platforms
.as_ref()
.unwrap()
.get("rootstock")
.unwrap()
.as_ref()
.unwrap(),
RIF_TOKEN_TESTNET_ADDRESS
);
}
}
2 changes: 1 addition & 1 deletion core/bin/zksync_api/src/bin/providers/proxy_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ pub(crate) async fn cache_proxy_request<C: HttpClient + ?Sized>(
}

// Fetch data if not in cache or stale
match client.get(url.clone()).await {
match client.get(url).await {
Ok(response) => match response.json::<Value>().await {
Ok(data) => {
// Cache the fetched data
Expand Down
2 changes: 1 addition & 1 deletion core/bin/zksync_api/src/bin/providers/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl Default for FakeHttpClient {
Self {
called: Default::default(),
response_generator: Box::new(|url| {
let body = json!({ "called_url": url}).to_string();
let body = json!({ "called_url": url }).to_string();

Ok(Response::from(hyper::Response::new(hyper::Body::from(
body,
Expand Down
1 change: 1 addition & 0 deletions core/bin/zksync_api/src/fee_ticker/ticker_api/coingecko.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ impl TokenPriceAPI for CoinGeckoAPI {
("vs_currency", "usd"),
("days", "1"),
// Removed ("interval", "hourly"), parameter as hourly charts are only available to coingecko enterprice plan customers
// The default interval is daily
])
.send()
.await
Expand Down
2 changes: 1 addition & 1 deletion etc/env/base/dev_ticker.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
blacklisted_tokens="0x0000000000000000000000000000000000000001"
default_volume=500
regime="whitelist"
proxy_cache_timout=5
proxy_cache_timout=5

0 comments on commit 8bc9ac4

Please sign in to comment.