Skip to content
This repository has been archived by the owner on Oct 25, 2024. It is now read-only.

Commit

Permalink
chore: add sway app abi tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Rashad Alston authored and Rashad Alston committed Sep 27, 2023
1 parent 093c553 commit f82538b
Show file tree
Hide file tree
Showing 38 changed files with 9,107 additions and 109 deletions.
4 changes: 4 additions & 0 deletions packages/fuel-indexer-lib/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,12 @@ lazy_static! {
/// Generic Sway ABI types.
pub static ref IGNORED_GENERIC_METADATA: HashSet<&'static str> = HashSet::from([
"generic T",
"generic E",
"raw untyped ptr",
"struct RawVec",
"struct RawBytes",
"struct Bytes",
"enum Result"
]);

pub static ref GENERIC_STRUCTS: HashSet<&'static str> = HashSet::from([
Expand Down
7 changes: 7 additions & 0 deletions packages/fuel-indexer-macros/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ pub fn is_non_decodable_type(typ: &TypeDeclaration) -> bool {
is_tuple_type(typ)
|| is_unit_type(typ)
|| IGNORED_GENERIC_METADATA.contains(typ.type_field.as_str())
|| is_array_type(typ)
}

/// Derive Ident for decoded type
Expand Down Expand Up @@ -1116,6 +1117,12 @@ pub fn typed_path_components(
(name, tokens)
}

fn is_array_type(typ: &TypeDeclaration) -> bool {
typ.type_field.starts_with('[')
&& typ.type_field.ends_with(']')
&& typ.type_field.contains(';')
}

/// Determine whether or not the given type name is an unsupported type.
///
/// Since we allow unsupported types in the ABI JSON, this check is only
Expand Down
15 changes: 15 additions & 0 deletions packages/fuel-indexer-macros/src/indexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ use std::collections::{HashMap, HashSet};
use std::path::{Path, PathBuf};
use syn::{parse_macro_input, FnArg, Item, ItemMod, PatType, Type};

fn additional_declarations() -> proc_macro2::TokenStream {
quote! {
// Miscellaneous types that can be included in ABI JSON
type b256 = [u8; 32];
type Bytes = Vec<u8>;
type B512 = [u8; 64];
}
}

fn process_fn_items(
manifest: &Manifest,
abi_path: Option<String>,
Expand Down Expand Up @@ -930,6 +939,8 @@ pub fn process_indexer_module(attrs: TokenStream, item: TokenStream) -> TokenStr
manifest.execution_source(),
);

let decl_tokens = additional_declarations();

let output = match manifest.execution_source() {
ExecutionSource::Native => {
let (handler_block, fn_items) =
Expand All @@ -939,6 +950,8 @@ pub fn process_indexer_module(attrs: TokenStream, item: TokenStream) -> TokenStr

quote! {

#decl_tokens

#abi_tokens

#graphql_tokens
Expand All @@ -956,6 +969,8 @@ pub fn process_indexer_module(attrs: TokenStream, item: TokenStream) -> TokenStr
let handler_block = handler_block_wasm(handler_block);
quote! {

#decl_tokens

#abi_tokens

#graphql_tokens
Expand Down
10 changes: 4 additions & 6 deletions packages/fuel-indexer-macros/src/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ pub fn handler_block_native(
/// indexer module, not within the scope of the entire lib module.
fn native_prelude() -> proc_macro2::TokenStream {
quote! {
type B256 = [u8; 32];

static mut db: Option<Arc<Mutex<Database>>> = None;

use fuel_indexer_utils::plugin::types::*;
Expand All @@ -60,10 +58,10 @@ pub fn native_main() -> proc_macro2::TokenStream {


let config = args
.config
.as_ref()
.map(IndexerConfig::from_file)
.unwrap_or(Ok(IndexerConfig::from(args)))?;
.config
.as_ref()
.map(IndexerConfig::from_file)
.unwrap_or(Ok(IndexerConfig::from(args)))?;

init_logging(&config).await?;

Expand Down
2 changes: 0 additions & 2 deletions packages/fuel-indexer-macros/src/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ fn wasm_prelude() -> proc_macro2::TokenStream {
use alloc::{format, vec, vec::Vec};
use std::str::FromStr;

type B256 = [u8; 32];

use fuel_indexer_utils::plugin::types::*;
use fuel_indexer_utils::plugin::wasm::*;
use fuel_indexer_utils::plugin::{serde_json, serialize, deserialize, bincode};
Expand Down
60 changes: 60 additions & 0 deletions packages/fuel-indexer-tests/scripts/copy-swap-app-abi.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/bin/bash

# This script copies the JSON ABI for each Sway application into the indexer's
# trybuild tests.
#
# This helps ensure that the indexers can be built with Sway projects that more
# closely resemble "real-world" contracts, as oppposed to just indexer test
# contracts.
#
# This script should be run from the repository root, and might have to be updated
# to account for the addition/removal of Sway applications.

usage() {
echo "Usage: $0 [options] <directory_root_path>"
echo "Options:"
echo " -h, --help Show this help message and exit."
echo
echo "Arguments:"
echo " <directory_root_path> The root path of the sway-application repository."
echo
}

swayapps_root=$1

if [[ "$1" == "-h" || "$1" == "--help" ]]; then
usage
exit 0
fi

if [[ -z "$1" || ! -d "$1" ]]; then
echo "Error: Invalid or missing directory root path."
usage
exit 1
fi

testdir=$(realpath $(dirname $(dirname $0)))
abidir=$testdir/trybuild/abi
echo $abidir

paths=(
"AMM/project/contracts/AMM-contract"
"AMM/project/contracts/exchange-contract"
"DAO/project/contracts/DAO-contract"
"OTC-swap-predicate/project/predicates/swap-predicate"
"airdrop/project/contracts/asset-contract"
"airdrop/project/contracts/distributor-contract"
"multisig-wallet/project/contracts/multisig-contract"
"escrow/project/contracts/escrow-contract"
"timelock/project/contracts/timelock-contract"
"auctions/english-auction/project/contracts/auction-contract"
"name-registry/project/contracts/registry-contract"
"oracle/project/contracts/oracle-contract"
)

for path in "${paths[@]}"; do
cd $swayapps_root/$path
forc build
cp -fv $path/out/debug/*-abi.json $abidir/
done

117 changes: 101 additions & 16 deletions packages/fuel-indexer-tests/tests/trybuild.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,29 @@ enum TestKind {
Fail,
}

fn manifest_with_contract_abi(contract_name: &str) -> String {
let manifest_dir = env!("CARGO_MANIFEST_DIR");
let project_root =
std::fs::canonicalize(std::path::Path::new(manifest_dir).join("..").join(".."))
.unwrap();
let project_root_str = project_root.to_str().unwrap();
let tests_root = project_root.join("packages").join("fuel-indexer-tests");
let tests_root_str = tests_root.to_str().unwrap();
let trybuild_root = tests_root.join("trybuild");
let abi_root = trybuild_root.join("abi");
let abi_root_str = abi_root.to_str().unwrap();
format!(
r#"
namespace: test_namespace
identifier: simple_wasm_executor
abi: {abi_root_str}/{contract_name}
graphql_schema: {tests_root_str}/indexers/simple-wasm/schema/simple_wasm.graphql
contract_id: ~
module:
wasm: {project_root_str}/target/wasm32-unknown-unknown/release/simple_wasm.wasm"#
)
}

#[test]
fn test_success_and_failure_macros() {
let t = trybuild::TestCases::new();
Expand All @@ -21,6 +44,8 @@ fn test_success_and_failure_macros() {
let tests_root = project_root.join("packages").join("fuel-indexer-tests");
let tests_root_str = tests_root.to_str().unwrap();
let trybuild_root = tests_root.join("trybuild");
let abi_root = trybuild_root.join("abi");
let abi_root_str = abi_root.to_str().unwrap();

let manifest_content = format!(
r#"
Expand All @@ -34,12 +59,16 @@ module:
"#
);

// IMPORTANT: Even though in theory we should be able to just re-use the same filename
// since we're writing and reading to each file for each test individually, in practice,
// these tests will error out if we use the same filename for each test.
//
// So, we simply change the manifest name according to each test to avoid these flaky errors.
let tests = vec![
(
"fail_if_attribute_manifest_schema_arg_is_invalid.rs",
"invalid_schema_simple_wasm.yaml",
TestKind::Fail,
// Using a custom manifest here
format!(
r#"
namespace: test_namespace
Expand Down Expand Up @@ -84,38 +113,27 @@ module:
),
(
"pass_if_indexer_is_valid_single_type.rs",
"simple_wasm.yaml",
"simple_wasm_single.yaml",
TestKind::Pass,
manifest_content.clone(),
),
(
"pass_if_indexer_is_valid_multi_type.rs",
"simple_wasm.yaml",
"simple_wasm_multi.yaml",
TestKind::Pass,
manifest_content.clone(),
),
(
"pass_if_unsupported_types_are_used.rs",
"simple_wasm.yaml",
"simple_wasm_unsupported.yaml",
TestKind::Pass,
// Using a custom manifest here
manifest_content.clone(),
),
(
"fail_if_abi_contains_reserved_fuel_type.rs",
"invalid_abi_type_simple_wasm.yaml",
TestKind::Fail,
// Using a custom manifest here
format!(
r#"
namespace: test_namespace
identifier: simple_wasm_executor
abi: {tests_root_str}/contracts/simple-wasm/out/debug/contracts-abi-reserved-name.json
graphql_schema: {tests_root_str}/indexers/simple-wasm/schema/simple_wasm.graphql
contract_id: ~
module:
wasm: {project_root_str}/target/wasm32-unknown-unknown/release/simple_wasm.wasm"#
),
manifest_with_contract_abi("contracts-abi-reserved-name.json"),
),
(
"fail_if_ident_not_defined_in_abi.rs",
Expand All @@ -135,6 +153,73 @@ module:
TestKind::Fail,
manifest_content.clone(),
),
(
"pass_if_using_sway_amm_abi.rs",
"sway_amm.yaml",
TestKind::Pass,
manifest_with_contract_abi("AMM-contract-abi.json"),
),
(
"pass_if_using_sway_dao_abi.rs",
"sway_dao.yaml",
TestKind::Pass,
manifest_with_contract_abi("DAO-contract-abi.json"),
),
(
"pass_if_using_sway_asset_contract_abi.rs",
"asset_contract.yaml",
TestKind::Pass,
manifest_with_contract_abi("asset-contract-abi.json"),
),
(
"pass_if_using_sway_distributor_contract_abi.rs",
"distributor_contract.yaml",
TestKind::Pass,
manifest_with_contract_abi("distributor-contract-abi.json"),
),
(
"pass_if_using_sway_escrow_contract_abi.rs",
"escrow_contract.yaml",
TestKind::Pass,
manifest_with_contract_abi("escrow-contract-abi.json"),
),
(
"pass_is_using_sway_exchange_contract_abi.rs",
"exchange_contract.yaml",
TestKind::Pass,
manifest_with_contract_abi("exchange-contract-abi.json"),
),
// NOTE: I don't think the ABI tokens are being properly generated from this contract JSON
// (
// "pass_if_using_sway_multisig_contract_abi.rs",
// "multisig_contract.yaml",
// TestKind::Pass,
// manifest_with_contract_abi("multisig-contract-abi.json"),
// ),
(
"pass_if_using_sway_oracle_contract_abi.rs",
"oracle_contract.yaml",
TestKind::Pass,
manifest_with_contract_abi("oracle-contract-abi.json"),
),
(
"pass_if_using_sway_registry_contract_abi.rs",
"registry_contract.yaml",
TestKind::Pass,
manifest_with_contract_abi("registry-contract-abi.json"),
),
(
"pass_if_using_swap_predicate_abi.rs",
"predicate_abi.yaml",
TestKind::Pass,
manifest_with_contract_abi("swap-predicate-abi.json"),
),
(
"pass_if_using_timelock_contract_abi.rs",
"timelock_contract.yaml",
TestKind::Pass,
manifest_with_contract_abi("timelock-contract-abi.json"),
),
];

for (name, manifest_name, kind, manifest_content) in tests {
Expand Down
Loading

0 comments on commit f82538b

Please sign in to comment.