1use crate::{
16 config::{
17 Backend,
18 Node,
19 },
20 ir,
21};
22use derive_more::From;
23use proc_macro2::TokenStream as TokenStream2;
24use quote::quote;
25
26#[derive(From)]
28pub struct InkE2ETest {
29 test: ir::InkE2ETest,
31}
32
33impl InkE2ETest {
34 pub fn generate_code(&self) -> TokenStream2 {
36 #[cfg(clippy)]
37 if true {
38 return quote! {};
39 }
40
41 let item_fn = &self.test.item_fn.item_fn;
42 let fn_name = &item_fn.sig.ident;
43 let block = &item_fn.block;
44 let fn_return_type = &item_fn.sig.output;
45 let vis = &item_fn.vis;
46 let attrs = &item_fn.attrs;
47 let ret = match fn_return_type {
48 syn::ReturnType::Default => quote! {},
49 syn::ReturnType::Type(rarrow, ret_type) => quote! { #rarrow #ret_type },
50 };
51
52 let environment = self
53 .test
54 .config
55 .environment()
56 .unwrap_or_else(|| syn::parse_quote! { ::ink::env::DefaultEnvironment });
57
58 let exec_build_contracts = quote! {
59 ::ink_e2e::build_root_and_contract_dependencies()
60 };
61
62 let client_building = match self.test.config.backend() {
63 Backend::Node(node_config) => {
64 build_full_client(&environment, exec_build_contracts, node_config)
65 }
66 #[cfg(any(test, feature = "sandbox"))]
67 Backend::RuntimeOnly(runtime) => {
68 build_runtime_client(exec_build_contracts, runtime.into())
69 }
70 };
71
72 quote! {
73 #( #attrs )*
74 #[test]
75 #vis fn #fn_name () #ret {
76 use ::ink_e2e::log_info;
77 ::ink_e2e::LOG_PREFIX.with(|log_prefix| {
78 let str = format!("test: {}", stringify!(#fn_name));
79 *log_prefix.borrow_mut() = String::from(str);
80 });
81 log_info("setting up e2e test");
82
83 ::ink_e2e::INIT.call_once(|| {
84 ::ink_e2e::tracing_subscriber::fmt::init();
85 });
86
87 log_info("creating new client");
88
89 let run = async {
90 #client_building
91
92 let __ret = {
93 #block
94 };
95 __ret
96 };
97
98 {
99 return ::ink_e2e::tokio::runtime::Builder::new_current_thread()
100 .enable_all()
101 .build()
102 .unwrap_or_else(|err| panic!("Failed building the Runtime: {err}"))
103 .block_on(run);
104 }
105 }
106 }
107 }
108}
109
110fn build_full_client(
111 environment: &syn::Path,
112 contracts: TokenStream2,
113 node_config: Node,
114) -> TokenStream2 {
115 match node_config.url() {
116 Some(url) => {
117 quote! {
118 let contracts = #contracts;
119 let rpc = ::ink_e2e::RpcClient::from_url(#url)
120 .await
121 .unwrap_or_else(|err|
122 ::core::panic!("Error connecting to node at {}: {err:?}", #url)
123 );
124 let mut client = ::ink_e2e::Client::<
125 ::ink_e2e::PolkadotConfig,
126 #environment
127 >::new(rpc, contracts, #url.to_string()).await?;
128 }
129 }
130 None => {
131 quote! {
132 let contracts = #contracts;
133 let node_rpc = ::ink_e2e::TestNodeProcess::<::ink_e2e::PolkadotConfig>
134 ::build_with_env_or_default()
135 .spawn()
136 .await
137 .unwrap_or_else(|err|
138 ::core::panic!("Error spawning ink-node: {err:?}")
139 );
140 let mut client = ::ink_e2e::Client::<
141 ::ink_e2e::PolkadotConfig,
142 #environment
143 >::new(node_rpc.rpc(), contracts, node_rpc.url().to_string()).await?;
144 }
145 }
146 }
147}
148
149#[cfg(any(test, feature = "sandbox"))]
150fn build_runtime_client(contracts: TokenStream2, runtime: syn::Path) -> TokenStream2 {
151 quote! {
152 let contracts = #contracts;
153 let mut client = ::ink_e2e::SandboxClient::<_, #runtime>::new(contracts);
154 }
155}