Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: logging with multiple(external) logs #751

Merged
merged 9 commits into from
Dec 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 9 additions & 13 deletions packages/fuels-contract/src/logs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,13 @@ impl LogDecoder {
});

ids_with_data
.map(|((c_id, log_id), data)| {
let param_type = self
.logs_map
.filter_map(|((c_id, log_id), data)| {
self.logs_map
.get(&(c_id, log_id))
.ok_or_else(|| Error::InvalidData("Failed to find log id".into()))?;

param_type.decode_log(&data)
.map(|param_type| (param_type, data))
})
.collect::<Result<Vec<String>, Error>>()
.map(|(param_type, data)| param_type.decode_log(&data))
.collect()
}

/// Get decoded logs with specific type from the given receipts.
Expand All @@ -59,7 +57,7 @@ impl LogDecoder {
})
.collect();

let decoded_logs: Vec<T> = receipts
receipts
.iter()
.filter_map(|r| match r {
Receipt::LogData { id, rb, data, .. }
Expand All @@ -75,9 +73,7 @@ impl LogDecoder {
_ => None,
})
.map(|data| try_from_bytes(&data))
.collect::<Result<Vec<_>, _>>()?;

Ok(decoded_logs)
.collect()
}

pub fn merge(&mut self, log_decoder: &LogDecoder) {
Expand All @@ -90,8 +86,8 @@ impl LogDecoder {
pub fn decode_revert_error(err: Error, log_decoder: &LogDecoder) -> Error {
if let Error::RevertTransactionError(_, receipts) = &err {
if let Ok(logs) = log_decoder.get_logs(receipts) {
if let Some(log) = logs.into_iter().next() {
return Error::RevertTransactionError(log, receipts.to_owned());
if let Some(log) = logs.last() {
return Error::RevertTransactionError(log.to_string(), receipts.to_owned());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@ license = "Apache-2.0"
name = "foo_caller_contract"

[dependencies]

foo = { path = "../foo_contract_abi/", package = "foo_contract_abi" }
1 change: 0 additions & 1 deletion packages/fuels/tests/contracts/foo_contract/Forc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@ license = "Apache-2.0"
name = "foo_contract"

[dependencies]

foo = { path = "../foo_contract_abi/", package = "foo_contract_abi" }
9 changes: 9 additions & 0 deletions packages/fuels/tests/contracts/require/src/main.sw
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
contract;

use std::logging::log;

enum EnumWithGeneric<D> {
VariantOne: D,
VariantTwo: (),
Expand All @@ -19,6 +21,7 @@ abi TestContract {
fn require_primitive();
fn require_string();
fn require_custom_generic();
fn require_with_additional_logs();
}

impl TestContract for Contract {
Expand All @@ -45,4 +48,10 @@ impl TestContract for Contract {

require(false, test_deeply_nested_generic);
}

fn require_with_additional_logs() {
log(42);
log("fuel");
require(false, 64);
}
}
88 changes: 88 additions & 0 deletions packages/fuels/tests/logs.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use fuels::core::tx::Bytes32;
use fuels::prelude::*;
use fuels::tx::{Input, Output, Receipt, TxPointer, UtxoId};

#[tokio::test]
async fn test_parse_logged_varibles() -> Result<(), Error> {
Expand Down Expand Up @@ -334,6 +336,15 @@ async fn test_require_log() -> Result<(), Error> {

assert_is_revert_containing_msg("StructDeeplyNestedGeneric", error);
}
{
let error = contract_methods
.require_with_additional_logs()
.call()
.await
.expect_err("Should return a revert error");

assert_is_revert_containing_msg("64", error);
}

Ok(())
}
Expand Down Expand Up @@ -511,6 +522,73 @@ async fn test_script_get_logs() -> Result<(), Error> {
Ok(())
}

#[tokio::test]
async fn test_script_logs_with_contract_logs() -> Result<(), Error> {
let wallet = launch_provider_and_get_wallet().await;

let contract_id: ContractId = Contract::deploy(
"../../packages/fuels/tests/logs/contract_logs/out/debug/contract_logs.bin",
&wallet,
TxParameters::default(),
StorageConfiguration::default(),
)
.await?
.into();

script_abigen!(
log_script,
"packages/fuels/tests/logs/script_with_contract_logs/out/debug/script_with_contract_logs-abi.json"
);

let bin_path =
"../fuels/tests/logs/script_with_contract_logs/out/debug/script_with_contract_logs.bin";
let instance = log_script::new(wallet.clone(), bin_path);

let expected_num_contract_logs = 4;

let expected_script_logs: Vec<String> = vec![
format!("{:?}", true),
format!("{:?}", 42),
format!("{:?}", SizedAsciiString::<4>::new("Fuel".to_string())?),
format!("{:?}", [1, 2, 3]),
];

let response = instance
.main(contract_id)
.with_inputs(vec![Input::contract(
UtxoId::new(Bytes32::zeroed(), 0),
Bytes32::zeroed(),
Bytes32::zeroed(),
TxPointer::default(),
contract_id,
)])
.with_outputs(vec![Output::contract(
0,
Bytes32::zeroed(),
Bytes32::zeroed(),
)])
.call()
.await?;

{
let num_contract_logs = response
.receipts
.iter()
.filter(|receipt| matches!(receipt, Receipt::LogData { id, .. } | Receipt::Log { id, .. } if *id == contract_id))
.count();

assert_eq!(num_contract_logs, expected_num_contract_logs);
}
{
// Assert that the logs that we can decode are the ones generated by the script
let logs = response.get_logs()?;

assert_eq!(logs, expected_script_logs);
}

Ok(())
}

#[tokio::test]
async fn test_script_get_logs_with_type() -> Result<(), Error> {
script_abigen!(
Expand Down Expand Up @@ -623,6 +701,16 @@ async fn test_script_require_log() -> Result<(), Error> {

assert_is_revert_containing_msg("StructDeeplyNestedGeneric", error);
}
{
let instance = log_script::new(wallet.clone(), bin_path);
let error = instance
.main(MatchEnum::RequireWithAdditionalLogs())
.call()
.await
.expect_err("Should return a revert error");

assert_is_revert_containing_msg("64", error);
}

Ok(())
}
1 change: 1 addition & 0 deletions packages/fuels/tests/logs/contract_logs/Forc.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ license = "Apache-2.0"
name = "contract_logs"

[dependencies]
library = { path = "../contract_logs_abi/", package = "contract_logs_abi" }
15 changes: 4 additions & 11 deletions packages/fuels/tests/logs/contract_logs/src/main.sw
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
contract;

use std::logging::log;
use library::ContractLogs;

struct TestStruct {
field_1: bool,
Expand Down Expand Up @@ -33,17 +34,9 @@ struct StructDeeplyNestedGeneric<D> {
field_2: u64,
}

abi TestContract {
fn produce_logs_values() -> ();
fn produce_logs_variables() -> ();
fn produce_logs_custom_types() -> ();
fn produce_logs_generic_types() -> ();
fn produce_multiple_logs() -> ();
}

impl TestContract for Contract {
fn produce_logs_values() {
log(64);
impl ContractLogs for Contract {
fn produce_logs_values() -> () {
log(64u64);
log(32u32);
log(16u16);
log(8u8);
Expand Down
7 changes: 7 additions & 0 deletions packages/fuels/tests/logs/contract_logs_abi/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[project]
authors = ["Fuel Labs <contact@fuel.sh>"]
entry = "main.sw"
license = "Apache-2.0"
name = "contract_logs_abi"

[dependencies]
11 changes: 11 additions & 0 deletions packages/fuels/tests/logs/contract_logs_abi/src/main.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
library contract_logs_abi;

use std::logging::log;

abi ContractLogs {
fn produce_logs_values() -> ();
fn produce_logs_variables() -> ();
fn produce_logs_custom_types() -> ();
fn produce_logs_generic_types() -> ();
fn produce_multiple_logs() -> ();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <contact@fuel.sh>"]
entry = "main.sw"
license = "Apache-2.0"
name = "script_with_contract_logs"

[dependencies]
library = { path = "../contract_logs_abi/", package = "contract_logs_abi" }
19 changes: 19 additions & 0 deletions packages/fuels/tests/logs/script_with_contract_logs/src/main.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
script;

use std::logging::log;
use library::ContractLogs;

fn main(contract_id: ContractId) {
// Call contract with `contract_id` and make some logs
let contract_instance = abi(ContractLogs, contract_id.into());
contract_instance.produce_logs_values();

let f: bool = true;
let u: u64 = 42;
let e: str[4] = "Fuel";
let l: [u8; 3] = [1u8, 2u8, 3u8];
log(f);
log(u);
log(e);
log(l);
}
7 changes: 7 additions & 0 deletions packages/fuels/tests/scripts/script_require/src/main.sw
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
script;

use std::logging::log;

enum EnumWithGeneric<D> {
VariantOne: D,
VariantTwo: (),
Expand All @@ -19,6 +21,7 @@ enum MatchEnum {
RequirePrimitive: (),
RequireString: (),
RequireCustomGeneric: (),
RequireWithAdditionalLogs: (),
}

fn main(match_enum: MatchEnum) {
Expand All @@ -40,5 +43,9 @@ fn main(match_enum: MatchEnum) {
};

require(false, test_deeply_nested_generic);
} else if let MatchEnum::RequireWithAdditionalLogs = match_enum {
log(42);
log("fuel");
require(false, 64);
}
}