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

feat: add log type info collection for test entries to enable log decoding at forc-test #5678

Closed
wants to merge 11 commits into from
133 changes: 131 additions & 2 deletions forc-pkg/src/pkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ use std::{
str::FromStr,
sync::{atomic::AtomicBool, Arc},
};
use sway_core::language::ty::{TyAstNodeContent, TyExpressionVariant};
pub use sway_core::Programs;
use sway_core::TypeInfo;
use sway_core::{
abi_generation::{
evm_abi,
Expand All @@ -51,7 +53,7 @@ use sway_core::{
};
use sway_error::{error::CompileError, handler::Handler, warning::CompileWarning};
use sway_types::constants::{CORE, PRELUDE, STD};
use sway_types::{Ident, Span, Spanned};
use sway_types::{Ident, SourceId, Span, Spanned};
use sway_utils::{constants, time_expr, PerformanceData, PerformanceMetric};
use tracing::{debug, info};

Expand Down Expand Up @@ -162,6 +164,7 @@ pub struct PkgTestEntry {
pub pass_condition: TestPassCondition,
pub span: Span,
pub file_path: Arc<PathBuf>,
pub log_params: Vec<(SourceId, Arc<TypeInfo>)>,
}

/// The result of successfully compiling a workspace.
Expand Down Expand Up @@ -2011,16 +2014,43 @@ impl PkgTestEntry {
bail!("Invalid test argument(s) for test: {test_name}.")
}?;

let mut log_params = Vec::new();
for ast_node in test_function_decl.body.contents.iter() {
if let TyAstNodeContent::Expression(expr) = &ast_node.content {
if let TyExpressionVariant::FunctionApplication {
call_path,
arguments,
..
} = &expr.expression
{
let suffix = call_path.suffix.to_string();
if suffix == "log" {
let arg_type = arguments
.iter()
.map(|(_, arg_expr)| arg_expr.return_type)
.map(|type_id| engines.te().get(type_id))
.next();
if let (Some(source_id), Some(arg_type)) = (expr.span.source_id(), arg_type)
{
log_params.push((*source_id, arg_type));
}
}
}
}
}

let file_path = Arc::new(
engines.se().get_path(
span.source_id()
.ok_or_else(|| anyhow::anyhow!("Missing span for test function"))?,
),
);

Ok(Self {
pass_condition,
span,
file_path,
log_params,
})
}
}
Expand Down Expand Up @@ -2775,7 +2805,7 @@ mod test {
let manifest_dir = PathBuf::from(current_dir)
.parent()
.unwrap()
.join("test/src/e2e_vm_tests/test_programs/should_pass/forc/workspace_building/");
.join("test/src/e2e_vm_tests/test_programs/should_pass/forc/workspace_building");
let manifest_file = ManifestFile::from_dir(manifest_dir).unwrap();
let member_manifests = manifest_file.member_manifests().unwrap();
let lock_path = manifest_file.lock_path().unwrap();
Expand All @@ -2789,6 +2819,105 @@ mod test {
.unwrap()
}

fn get_test_entry_logs(entry_name: &str) -> Vec<Arc<TypeInfo>> {
let current_dir = env!("CARGO_MANIFEST_DIR");
let manifest_dir = format!("{current_dir}/tests/test_pkg_entry");
let build_opts = BuildOpts {
pkg: PkgOpts {
path: Some(manifest_dir),
..Default::default()
},
build_target: BuildTarget::Fuel,
tests: true,
experimental: ExperimentalFlags { new_encoding: true },
..Default::default()
};
let built_pkgs = build_with_options(build_opts).unwrap();
let built_pkg = built_pkgs.expect_pkg().unwrap();
let pkg_entry = built_pkg
.bytecode
.entries
.iter()
.filter(|pkg_entry| pkg_entry.finalized.fn_name == entry_name)
.find_map(|entry| {
if let PkgEntryKind::Test(test_entry) = &entry.kind {
Some(test_entry)
} else {
None
}
})
.unwrap();

pkg_entry
.log_params
.iter()
.map(|(_, type_info)| type_info)
.cloned()
.collect()
}

#[test]
fn collect_test_entry_log_unsigned_int() {
let log_types = get_test_entry_logs("log_unsigned_int");
assert_eq!(log_types.len(), 1);
assert!(matches!(*log_types[0], TypeInfo::Numeric,))
}

#[test]
fn collect_test_entry_log_bool() {
let log_types = get_test_entry_logs("log_bool");
assert_eq!(log_types.len(), 1);
assert!(matches!(*log_types[0], TypeInfo::Boolean))
}

#[test]
fn collect_test_entry_log_string_slice() {
let log_types = get_test_entry_logs("log_string_slice");
assert_eq!(log_types.len(), 1);
assert!(matches!(*log_types[0], TypeInfo::StringSlice))
}

#[test]
fn collect_test_entry_log_array() {
let log_types = get_test_entry_logs("log_array");
assert_eq!(log_types.len(), 1);
assert!(matches!(*log_types[0], TypeInfo::Array(_, _)))
}

#[test]
fn collect_test_entry_log_tuple() {
let log_types = get_test_entry_logs("log_tuple");
assert_eq!(log_types.len(), 1);
assert!(matches!(*log_types[0], TypeInfo::Tuple(_)))
}

#[test]
fn collect_test_entry_log_struct() {
let log_types = get_test_entry_logs("log_struct");
assert_eq!(log_types.len(), 1);
assert!(matches!(*log_types[0], TypeInfo::Struct(_)))
}

#[test]
fn collect_test_entry_log_enum() {
let log_types = get_test_entry_logs("log_enum");
assert_eq!(log_types.len(), 1);
assert!(matches!(*log_types[0], TypeInfo::Enum(_)))
}

#[test]
fn collect_test_entry_multiple_log() {
let log_types = get_test_entry_logs("log_multiple");
assert_eq!(log_types.len(), 7);
assert!(matches!(*log_types[0], TypeInfo::Numeric));
assert!(matches!(*log_types[1], TypeInfo::Boolean));
assert!(matches!(*log_types[2], TypeInfo::StringSlice));
assert!(matches!(*log_types[3], TypeInfo::Array(_, _)));
assert!(matches!(*log_types[4], TypeInfo::Tuple(_)));
assert!(matches!(*log_types[5], TypeInfo::Struct(_)));
assert!(matches!(*log_types[6], TypeInfo::Enum(_)));
}

#[test]
fn test_root_pkg_order() {
let build_plan = setup_build_plan();
Expand Down
2 changes: 2 additions & 0 deletions forc-pkg/tests/test_pkg_entry/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
out
target
13 changes: 13 additions & 0 deletions forc-pkg/tests/test_pkg_entry/Forc.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[[package]]
name = "core"
source = "path+from-root-9F43309F1982F720"

[[package]]
name = "std"
source = "path+from-root-9F43309F1982F720"
dependencies = ["core"]

[[package]]
name = "test_pkg_entry"
source = "member"
dependencies = ["std"]
8 changes: 8 additions & 0 deletions forc-pkg/tests/test_pkg_entry/Forc.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[project]
authors = ["Fuel Labs <[email protected]>"]
entry = "lib.sw"
license = "Apache-2.0"
name = "test_pkg_entry"

[dependencies]
std = { path = "../../../sway-lib-std/" }
81 changes: 81 additions & 0 deletions forc-pkg/tests/test_pkg_entry/src/lib.sw
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
library;

#[test]
fn log_unsigned_int() {
let a = 10;
log(a);
}

#[test]
fn log_bool() {
let a = true;
log(a);
}

#[test]
fn log_string_slice() {
let a = "test";
log(a);
}

#[test]
fn log_array() {
let a: [u8; 5] = [1, 2, 3, 4, 5];
log(a);
let b: [u8; 5] = [1, 2, 3, 4, 5];
}

#[test]
fn log_tuple() {
let a = (1,2);
log(a);
let b = (1,2);
}

struct Foo {
f1: u32,
}

#[test]
fn log_struct() {
let a = Foo {
f1: 1,
};

log(a);
let b = Foo {
f1: 1,
};
}


enum Bar {
Foo: (),
}

#[test]
fn log_enum() {
let a: Bar = Bar::Foo;
log(a);
}


#[test]
fn log_multiple() {
let a = 10;
log(a);
let a = true;
log(a);
let a = "test";
log(a);
let a: [u8; 5] = [1, 2, 3, 4, 5];
log(a);
let a = (1,2);
log(a);
let a = Foo {
f1: 1,
};
log(a);
let a: Bar = Bar::Foo;
log(a);
}