diff --git a/justfile b/justfile index 5322360bd72..e66a1ad300a 100644 --- a/justfile +++ b/justfile @@ -19,6 +19,10 @@ update-fuel-dependencies: update-contract-ids: bash ./test/update-contract-ids.sh +[group('automation')] +bisect-forc path command: + bash ./scripts/bisect-forc/bisect-forc.sh "{{path}}" "{{command}}" + [group('benchmark')] benchmark: bash ./benchmark.sh @@ -31,6 +35,33 @@ benchmark-tests: collect-gas-usage: cargo r -p test --release -- --verbose --forc-test-only | ./scripts/compare-gas-usage/extract-gas-usage.sh +# This recipe should be used on snapshot tests that contains gas usage from `forc test`, +# because it will extract gas usage from all versions of the file and generate an html interactive report. +# path: path to file to extract gas usage +# open: "-o" will open the default browser showing the report +[linux] +[group('benchmark')] +collect-historic-gas-usage path open: + #! /bin/bash + mkdir -p target + rm target/a.csv + rm target/a.html + echo "test,gas,commit" > target/a.csv + for HASH in `git log --format='%H' -- {{path}}`; do + TIMESTAMP=$(git show -s --format='%as-%ct-%H' "$HASH") + git --no-pager show "$HASH:{{path}}" | bash -c "scripts/compare-gas-usage/extract-gas-usage.sh $TIMESTAMP" >> target/a.csv + done + ./scripts/csv2html/csv2html.sh target/a.csv >> target/a.html + if [ -n "{{open}}" ]; then + if which xdg-open &>> /dev/null + then + xdg-open target/a.html + elif which gnome-open &>> /dev/null + then + gnome-open target/a.html + fi + fi + [group('build')] build-prism: cd ./scripts/prism && ./build.sh diff --git a/scripts/bisect-forc/bisect-forc.sh b/scripts/bisect-forc/bisect-forc.sh index 53bed8b70e1..3f883ade03c 100755 --- a/scripts/bisect-forc/bisect-forc.sh +++ b/scripts/bisect-forc/bisect-forc.sh @@ -48,7 +48,7 @@ echo -n "Running: " CACHENAME="$(git show -s --format='%as-%ct-%H' HEAD)" compile_and_cp_to_cache "$CACHENAME" -INITIAL_COMPILATION_STATUS=$(run_cargo) +INITIAL_COMPILATION_STATUS=$(run_cargo "$1" "$2") if [ "$INITIAL_COMPILATION_STATUS" = "0" ]; then echo -e " ${BOLD_GREEN}Ok${NC}" @@ -69,7 +69,7 @@ for HASH in `git log --format="%H" --tags --no-walk`; do CACHENAME="$(git show -s --format='%as-%ct-%H' HEAD)" compile_and_cp_to_cache "$CACHENAME" - LAST_STATUS=$(run_cargo) + LAST_STATUS=$(run_cargo "$1" "$2") if [ "$INITIAL_COMPILATION_STATUS" != "$LAST_STATUS" ]; then echo -e "^^^^^^^^^ ${BOLD_WHITE}This version result is different!${NC}" break @@ -93,14 +93,14 @@ do #git --no-pager bisect visualize --oneline git bisect next | grep "is the first new commit" &>> /dev/null - if [ "$LAST_STATUS" = "0" ]; then + if [ "$?" = "0" ]; then FIRST_COMMIT="$(git bisect next 2>&1 | head -n 1 | cut -f1 -d" ")" git checkout "$FIRST_COMMIT" &>> /dev/null break fi - + git bisect next | grep "Bisecting" - if [ "$LAST_STATUS" != "0" ]; then + if [ "$?" != "0" ]; then break fi @@ -108,7 +108,7 @@ do CACHENAME="$(git show -s --format='%as-%ct-%H' HEAD)" compile_and_cp_to_cache "$CACHENAME" - LAST_STATUS=$(run_cargo) + LAST_STATUS=$(run_cargo "$1" "$2") if [ "$LAST_STATUS" = "$INITIAL_COMPILATION_STATUS" ]; then git bisect new &>> /dev/null else @@ -127,7 +127,7 @@ echo -n "checking the found commit has the same behaviour as the initial commit. CACHENAME="$(git show -s --format='%as-%ct-%H' HEAD)" compile_and_cp_to_cache "$CACHENAME" -LAST_STATUS=$(run_cargo) +LAST_STATUS=$(run_cargo "$1" "$2") if [ "$INITIAL_COMPILATION_STATUS" != "$LAST_STATUS" ]; then echo -e " ${BOLD_RED}Unexpected exit code${NC}" @@ -143,7 +143,7 @@ git checkout HEAD~1 &>> /dev/null PREVIOUS_COMMIT="$(git show -s --format='%H' HEAD)" CACHENAME="$(git show -s --format='%as-%ct-%H' HEAD)" compile_and_cp_to_cache "$CACHENAME" -LAST_STATUS=$(run_cargo) +LAST_STATUS=$(run_cargo "$1" "$2") if [ "$INITIAL_COMPILATION_STATUS" = "$LAST_STATUS" ]; then echo -e " ${BOLD_RED}Unexpected exit code${NC}" diff --git a/scripts/compare-gas-usage/extract-gas-usage.sh b/scripts/compare-gas-usage/extract-gas-usage.sh index 8894804fae7..7bcc9107177 100755 --- a/scripts/compare-gas-usage/extract-gas-usage.sh +++ b/scripts/compare-gas-usage/extract-gas-usage.sh @@ -2,6 +2,7 @@ # This script extracts full test names and test gas usage from a `forc test` output. # Usage: `forc test | test_gas_usage.sh`. +# if $1 is not empty it will be appended as a new column to the csv current_suite="" results=() @@ -19,7 +20,12 @@ while IFS= read -r line; do # printf 'Test: %s\n' "$test_name" gas="${BASH_REMATCH[2]}" # printf 'Gas: %s\n' "$gas" - results+=("${current_suite}::${test_name},${gas}") + + if [ "$1" = "" ]; then + results+=("${current_suite}::${test_name},${gas}") + else + results+=("${current_suite}::${test_name},${gas},$1") + fi fi done diff --git a/scripts/csv2html/csv2html.sh b/scripts/csv2html/csv2html.sh new file mode 100755 index 00000000000..05a90c1e879 --- /dev/null +++ b/scripts/csv2html/csv2html.sh @@ -0,0 +1,60 @@ +#!/bin/bash +echo ' + + + Pivot Demo + + + + + + + + + + + + + + + + + + + + +
+
+ + ' +head -n 1 "$1" | sed -e 's/^/ + ' +tail -n +2 "$1" | sed -e 's/^/ +
/' -e 's/,/<\/th>/g' -e 's/$/<\/th><\/tr>/' +echo '
/' -e 's/,/<\/td>/g' -e 's/$/<\/td><\/tr>/' +echo "
+ +" \ No newline at end of file diff --git a/sway-core/src/decl_engine/id.rs b/sway-core/src/decl_engine/id.rs index 099f99f7ab2..7a849f8a779 100644 --- a/sway-core/src/decl_engine/id.rs +++ b/sway-core/src/decl_engine/id.rs @@ -240,12 +240,23 @@ impl SubstTypes for DeclId { } } +// This implementation deviates from all other DeclId<...> implementations. +// For more, see https://github.com/FuelLabs/sway/pull/7440#discussion_r2428833840. +// A better solution will be implemented in the future. +// +// TL;DR: +// When a constant is declared inside a function, its value is shared by every +// “version” of that function—that is, by all monomorphizations. If we “replace” the +// constant, as other implementations do, we would change its value in *every* version, +// which is incorrect. impl SubstTypes for DeclId { fn subst_inner(&mut self, ctx: &SubstTypesContext) -> HasChanges { let decl_engine = ctx.engines.de(); let mut decl = (*decl_engine.get(self)).clone(); if decl.subst(ctx).has_changes() { - decl_engine.replace(*self, decl); + *self = *decl_engine + .insert(decl, decl_engine.get_parsed_decl_id(self).as_ref()) + .id(); HasChanges::Yes } else { HasChanges::No diff --git a/sway-core/src/type_system/ast_elements/type_argument.rs b/sway-core/src/type_system/ast_elements/type_argument.rs index eb0b12223a2..1f91055fca1 100644 --- a/sway-core/src/type_system/ast_elements/type_argument.rs +++ b/sway-core/src/type_system/ast_elements/type_argument.rs @@ -225,7 +225,12 @@ impl DebugWithEngines for GenericArgument { fn fmt(&self, f: &mut fmt::Formatter<'_>, engines: &Engines) -> fmt::Result { match self { GenericArgument::Type(a) => { - write!(f, "{:?}", engines.help_out(&*engines.te().get(a.type_id))) + write!( + f, + "{:?} -> {:?}", + engines.help_out(&*engines.te().get(a.initial_type_id)), + engines.help_out(&*engines.te().get(a.type_id)) + ) } GenericArgument::Const(a) => match &a.expr { ConstGenericExpr::Literal { val, .. } => { diff --git a/sway-lib-std/src/codec.sw b/sway-lib-std/src/codec.sw index d348528c129..2d273a7d772 100644 --- a/sway-lib-std/src/codec.sw +++ b/sway-lib-std/src/codec.sw @@ -2789,6 +2789,13 @@ impl AbiDecode for str[N] { } } +#[cfg(experimental_const_generics = false)] +impl AbiDecode for str[0] { + fn abi_decode(ref mut _buffer: BufferReader) -> str[0] { + __to_str_array("") + } +} + // BEGIN STRARRAY_DECODE #[cfg(experimental_const_generics = false)] impl AbiDecode for str[1] { @@ -3390,6 +3397,16 @@ where } } +#[cfg(experimental_const_generics = false)] +impl AbiDecode for [T; 0] +where + T: AbiDecode, +{ + fn abi_decode(ref mut _buffer: BufferReader) -> [T; 0] { + [] + } +} + // BEGIN ARRAY_DECODE #[cfg(experimental_const_generics = false)] impl AbiDecode for [T; 1] diff --git a/test/README.md b/test/README.md new file mode 100644 index 00000000000..e7fde7a7f35 --- /dev/null +++ b/test/README.md @@ -0,0 +1,144 @@ +# Snapshot tests + +There are two ways to run snapshot tests: + +``` +> cargo r -p test --release +> cargo r -p test --release -- -k snapshot +``` + +When the snapshot flag is enabled (the default) the test harness will search for `snapshot.toml` files. For every `toml` file found a new snapshot test will run. If the `toml` file is empty, it will be interpreted as simply being: + +```toml +# this is how the test harness understands an empty `snapshot.toml +cmds = [ + \"forc build --path {root}\" +] +``` + +When the test harness runs a snapshot test, it will iterate the `cmds` array of each file, run each command, and append everything into the snapshot. + +So the snapshot of the above file would be something like: + +``` +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [1.88 KB] in ??? +``` + +To make snapshot "environment free", the test harness changes `forc` output a little bit. + +1 - First it does not show complete file paths. All paths are relative to the Sway repo root. +2 - Test harness also removes all printing of times. +3 - It also removes all ANSI codes for coloring and others. + +## Commands + +To make snapshot tests more versatile there are a lot of options of what one can use inside `cmds`: + +1 - `forc`; Any native forc command is available; +2 - Forc plugins; Currently only `forc doc` is available; +3 - `echo`; One can use echo to write a message. Usage is: + +```toml +cmds = [ + "echo Explain something here.", + "forc build --path {root}", +] +``` + +4 - `sub`; Sub will iterate all lines of the previous command and filter in only those that contain its argument. + +```toml +cmds = [ + "forc build --path {root} --asm final | sub ecal" +] +``` + +The example above will only show asm lines that contain the `ecal` instruction. + +5 - `regex`; Regex is very similar to `sub`, but allows a regex to be written. + +```toml +cmds = [ + "forc build --path {root} --ir initial | regex ' (v0 = call call|v0 = const|v1 = const|revert)'" +] +``` + +6 - `filter-fn`. This command only shows IR, ASM for a specific function. It needs that previous command return a complete IR of a program. + +```toml +cmds = [ + "forc build --path {root} --ir final --asm final | filter-fn {name} transmute_by_reference_7", +] +``` + +In the example above, the snapshot will only contain IR and asm from the function "transmute_by_reference_7" + +Some commands manipulate files. These commands have an "undo" list that will restore the file original content when they are finished. +So it is guaranteed that if the test harness finishes gracefully, manipulated files will have their original values. + +For security reasons, these commands can ONLY manipulate files under its project folder. + +1 - `replace`. Replace a simple string for another. + +```toml +cmds = [ + "replace src/main.sw \"fn cost_of_in\" \"fn isolated_cost_of_in\"", +] +``` + +## Variables + +1 - `root`. Is the folder of the project being compiled. +2 - `name`. Is the name of the specific project being compiled. + +## Blocks + +Blocks are blocks of code that live inside two comments of the form below: + +```sway +/* START BOOL */ +#[test] +fn cost_of_in_bool() { + let _ = abi(MyContract, CONTRACT_ID).in_bool(false); +} +/* END BOOL */ +``` + +These blocks can be manipulated from inside the `snapshot.toml` and allowing multiples tests to use the same project. +To manipulate these blocks one can: + +1 - Use the `repeat-for-each-block`. + +```toml +cmds = [ + { repeat = "for-each-block", cmds = [ + "forc test --path {root} --release --experimental const_generics" + ] } +] +``` + +In the example above, the test harness will collect all "blocks" in the project being compiled, and will run the `cmds` inside the inner table for each block, removing all others. So for example: + +```rust +/* START BOOL */ +#[test] +fn cost_of_in_bool() { + let _ = abi(MyContract, CONTRACT_ID).in_bool(false); +} +/* END BOOL */ + +/* START U8 */ +#[test] +fn cost_of_in_u8() { + let _ = abi(MyContract, CONTRACT_ID).in_u8(0); +} +/* END U8 */ +``` + +In the example above, the `repeat = "for-each-block"` means that its `cmds` list will be run twice. First removing the block `U8`; and after, it will restore the original file contents and remove "BOOL". diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/array/array_repeat/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_pass/language/array/array_repeat/stdout.snap index cb93439587d..bfa7ed0631d 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/array/array_repeat/stdout.snap +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/array/array_repeat/stdout.snap @@ -1167,27 +1167,27 @@ script { !234 = span !184 71080 71101 !235 = fn_call_path_span !184 71080 71093 !236 = (!234 !235) -!237 = span !184 89587 89627 +!237 = span !184 89756 89796 !238 = (!234 !235 !237) -!239 = span !184 89607 89627 +!239 = span !184 89776 89796 !240 = (!234 !235 !237) -!241 = span !184 89653 89666 +!241 = span !184 89822 89835 !242 = (!234 !235 !241) -!243 = span !184 89637 89667 +!243 = span !184 89806 89836 !244 = (!234 !235 !243) -!245 = span !184 89752 89757 +!245 = span !184 89921 89926 !246 = (!234 !235 !245) -!247 = span !184 89676 89759 +!247 = span !184 89845 89928 !248 = (!234 !235 !247) !249 = (!234 !235 !247) -!250 = span !184 89769 89783 +!250 = span !184 89938 89952 !251 = (!234 !235 !250) -!252 = span !184 89781 89782 +!252 = span !184 89950 89951 !253 = (!234 !235 !250) -!254 = span !184 89799 89800 +!254 = span !184 89968 89969 !255 = (!234 !235 !254) -!256 = span !184 89799 89804 -!257 = fn_call_path_span !184 89801 89802 +!256 = span !184 89968 89973 +!257 = fn_call_path_span !184 89970 89971 !258 = (!234 !235 !256 !257) !259 = (!234 !235 !256 !257) !260 = (!234 !235 !256 !257) @@ -1198,17 +1198,17 @@ script { !265 = (!234 !235 !256 !257 !264) !266 = (!234 !235 !256 !257) !267 = (!234 !235 !256 !257) -!268 = span !184 89848 89853 +!268 = span !184 90017 90022 !269 = (!234 !235 !268) -!270 = span !184 89855 89856 +!270 = span !184 90024 90025 !271 = (!234 !235 !270) -!272 = span !184 89819 89858 +!272 = span !184 89988 90027 !273 = (!234 !235 !272) !274 = (!234 !235 !272) -!275 = span !184 89879 89885 +!275 = span !184 90048 90054 !276 = (!234 !235 !275) -!277 = span !184 89879 89899 -!278 = fn_call_path_span !184 89886 89892 +!277 = span !184 90048 90068 +!278 = fn_call_path_span !184 90055 90061 !279 = (!234 !235 !277 !278) !280 = span !184 3973 3977 !281 = (!234 !235 !277 !278 !280) @@ -1333,17 +1333,17 @@ script { !400 = (!234 !235 !277 !278 !282 !283 !287 !288 !371 !372) !401 = (!234 !235 !277 !278 !282 !283 !287 !288) !402 = (!234 !235 !277 !278 !282 !283 !287 !288) -!403 = span !184 89872 89876 +!403 = span !184 90041 90045 !404 = (!234 !235 !403) -!405 = span !184 89871 89899 +!405 = span !184 90040 90068 !406 = (!234 !235 !405) -!407 = span !184 89913 89914 +!407 = span !184 90082 90083 !408 = (!234 !235 !407) -!409 = span !184 89913 89919 -!410 = fn_call_path_span !184 89915 89917 +!409 = span !184 90082 90088 +!410 = fn_call_path_span !184 90084 90086 !411 = (!234 !235 !409 !410) !412 = (!234 !235 !409 !410) -!413 = span !184 89918 89919 +!413 = span !184 90087 90088 !414 = (!234 !235 !409 !410) !415 = span !28 1322 1326 !416 = (!234 !235 !409 !410 !415) @@ -1354,7 +1354,7 @@ script { !421 = (!234 !235 !409 !410) !422 = (!234 !235 !409) !423 = (!234 !235 !409) -!424 = span !184 89941 89946 +!424 = span !184 90110 90115 !425 = (!234 !235 !424) !426 = "test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-assert/src/logging.sw" !427 = span !426 591 596 diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_dedup_decode/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_dedup_decode/stdout.snap index c126cf51508..5526fc5bfb3 100644 --- a/test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_dedup_decode/stdout.snap +++ b/test/src/e2e_vm_tests/test_programs/should_pass/language/configurable_dedup_decode/stdout.snap @@ -226,8 +226,8 @@ script { !18 = span !3 71305 71311 !19 = span !3 71291 71312 !20 = fn_call_path_span !3 71291 71304 -!21 = span !3 114976 114997 -!22 = fn_call_path_span !3 114976 114989 +!21 = span !3 115325 115346 +!22 = fn_call_path_span !3 115325 115338 !23 = span !3 71904 71932 !24 = fn_call_path_span !3 71911 71923 !25 = span !3 625 637 @@ -241,7 +241,7 @@ script { !33 = (!19 !20 !21 !22 !23 !24) !34 = span !3 2857 2896 !35 = (!19 !20 !21 !22 !23 !24 !34) -!36 = span !3 114975 115000 +!36 = span !3 115324 115349 !37 = (!19 !20 !36) !38 = (!19 !20 !36) !39 = (!19 !20 !36) diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call/Forc.lock b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call/Forc.lock new file mode 100644 index 00000000000..59a03d8c81a --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call/Forc.lock @@ -0,0 +1,8 @@ +[[package]] +name = "const_of_contract_call" +source = "member" +dependencies = ["std"] + +[[package]] +name = "std" +source = "path+from-root-819F923052268091" diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call/Forc.toml b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call/Forc.toml new file mode 100644 index 00000000000..8080c612d8a --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call/Forc.toml @@ -0,0 +1,9 @@ +[project] +authors = ["Fuel Labs "] +entry = "main.sw" +license = "Apache-2.0" +name = "const_of_contract_call" + +[dependencies] + +std = { path = "../../../../reduced_std_libs/sway-lib-std-core/" } diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call/snapshot.toml b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call/snapshot.toml new file mode 100644 index 00000000000..e29e5ff922e --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call/snapshot.toml @@ -0,0 +1,7 @@ +cmds = [ + "forc test --path {root} --release --experimental const_generics", + { repeat = "for-each-block", cmds = [ + "replace-file src/main.sw \"fn cost_of_in\" \"fn isolated_cost_of_in\"", + "forc test --path {root} --release --experimental const_generics" + ] } +] \ No newline at end of file diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call/src/main.sw b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call/src/main.sw new file mode 100644 index 00000000000..a6d6a709f24 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call/src/main.sw @@ -0,0 +1,463 @@ +contract; + +struct S1 { + #[allow(dead_code)] + a: A +} +struct S2 { + #[allow(dead_code)] + a: A, + #[allow(dead_code)] + b: B +} +struct S3 { + #[allow(dead_code)] + a: A, + #[allow(dead_code)] + b: B, + #[allow(dead_code)] + c: C +} + +enum E1 { A: A } +enum E2 { A: A, B: B } +enum E3 { A: A, B: B, C: C } + +abi MyContract { + /* START BOOL */ + fn in_bool(v: bool) -> bool; + /* END BOOL */ + + /* START U8 */ + fn in_u8(v: u8) -> u8; + /* END U8 */ + + /* START U16 */ + fn in_u16(v: u16) -> u16; + /* END U16 */ + + /* START U32 */ + fn in_u32(v: u32) -> u32; + /* END U32 */ + + /* START U64 */ + fn in_u64(v: u64) -> u64; + /* END U64 */ + + /* START U256 */ + fn in_u256(v: u256) -> u256; + /* END U256 */ + + /* START B256 */ + fn in_b256(v: b256) -> b256; + /* END B256 */ + + /* START STR0 */ + fn in_str_0(v: str[0]) -> str[0]; + /* END STR0 */ + + /* START STR1 */ + fn in_str_1(v: str[1]) -> str[1]; + /* END STR1 */ + + /* START STR8 */ + fn in_str_8(v: str[8]) -> str[8]; + /* END STR8 */ + + /* START STR16 */ + fn in_str_16(v: str[16]) -> str[16]; + /* END STR16 */ + + /* START STR32 */ + fn in_str_32(v: str[32]) -> str[32]; + /* END STR32 */ + + /* START ARRAY0 */ + fn in_array_0(v: [u64; 0]) -> [u64; 0]; + /* END ARRAY0 */ + + /* START ARRAY1 */ + fn in_array_1(v: [u64; 1]) -> [u64; 1]; + /* END ARRAY1 */ + + /* START ARRAY8 */ + fn in_array_8(v: [u64; 8]) -> [u64; 8]; + /* END ARRAY8 */ + + /* START ARRAY16 */ + fn in_array_16(v: [u64; 16]) -> [u64; 16]; + /* END ARRAY16 */ + + /* START ARRAY32 */ + fn in_array_32(v: [u64; 32]) -> [u64; 32]; + /* END ARRAY32 */ + + /* START ARRAY64 */ + fn in_array_64(v: [u64; 64]) -> [u64; 64]; + /* END ARRAY64 */ + + /* START TUPLE0 */ + fn in_tuple_0(v: ()) -> (); + /* END TUPLE0 */ + + /* START TUPLE1 */ + fn in_tuple_1(v: (u64,)) -> (u64,); + /* END TUPLE1 */ + + /* START TUPLE2 */ + fn in_tuple_2(v: (u64, u64)) -> (u64, u64); + /* END TUPLE2 */ + + /* START TUPLE3 */ + fn in_tuple_3(v: (u64, u64, u64)) -> (u64, u64, u64); + /* END TUPLE3 */ + + /* START TUPLE4 */ + fn in_tuple_4(v: (u64, u64, u64, u64)) -> (u64, u64, u64, u64); + /* END TUPLE4 */ + + /* START STRUCT_U64 */ + fn in_struct_u64(v: S1) -> S1; + /* END STRUCT_U64 */ + + /* START STRUCT_U64_U64 */ + fn in_struct_u64_u64(v: S2) -> S2; + /* END STRUCT_U64_U64 */ + + /* START STRUCT_U64_U64_U64 */ + fn in_struct_u64_u64_u64(v: S3) -> S3; + /* END STRUCT_U64_U64_U64 */ + + /* START ENUM_U64 */ + fn in_enum_u64(v: E1) -> E1; + /* END ENUM_U64 */ + + /* START ENUM_U64_U64 */ + fn in_enum_u64_u64(v: E2) -> E2; + /* END ENUM_U64_U64 */ + + /* START ENUM_U64_U64_U64 */ + fn in_enum_u64_u64_u64(v: E3) -> E3; + /* END ENUM_U64_U64_U64 */ +} + +impl MyContract for Contract { + /* START BOOL */ + fn in_bool(v: bool) -> bool { v } + /* END BOOL */ + + /* START U8 */ + fn in_u8(v: u8) -> u8 { v } + /* END U8 */ + + /* START U16 */ + fn in_u16(v: u16) -> u16 { v } + /* END U16 */ + + /* START U32 */ + fn in_u32(v: u32) -> u32 { v } + /* END U32 */ + + /* START U64 */ + fn in_u64(v: u64) -> u64 { v } + /* END U64 */ + + /* START U256 */ + fn in_u256(v: u256) -> u256 { v } + /* END U256 */ + + /* START B256 */ + fn in_b256(v: b256) -> b256 { v } + /* END B256 */ + + /* START STR0 */ + fn in_str_0(v: str[0]) -> str[0] { v } + /* END STR0 */ + + /* START STR1 */ + fn in_str_1(v: str[1]) -> str[1] { v } + /* END STR1 */ + + /* START STR8 */ + fn in_str_8(v: str[8]) -> str[8] { v } + /* END STR8 */ + + /* START STR16 */ + fn in_str_16(v: str[16]) -> str[16] { v } + /* END STR16 */ + + /* START STR32 */ + fn in_str_32(v: str[32]) -> str[32] { v } + /* END STR32 */ + + /* START ARRAY0 */ + fn in_array_0(v: [u64; 0]) -> [u64; 0] { v } + /* END ARRAY0 */ + + /* START ARRAY1 */ + fn in_array_1(v: [u64; 1]) -> [u64; 1] { v } + /* END ARRAY1 */ + + /* START ARRAY8 */ + fn in_array_8(v: [u64; 8]) -> [u64; 8] { __log(v); v } + /* END ARRAY8 */ + + /* START ARRAY16 */ + fn in_array_16(v: [u64; 16]) -> [u64; 16] { v } + /* END ARRAY16 */ + + /* START ARRAY32 */ + fn in_array_32(v: [u64; 32]) -> [u64; 32] { v } + /* END ARRAY32 */ + + /* START ARRAY64 */ + fn in_array_64(v: [u64; 64]) -> [u64; 64] { v } + /* END ARRAY64 */ + + /* START TUPLE0 */ + fn in_tuple_0(v: ()) -> () { v } + /* END TUPLE0 */ + + /* START TUPLE1 */ + fn in_tuple_1(v: (u64,)) -> (u64,) { v } + /* END TUPLE1 */ + + /* START TUPLE2 */ + fn in_tuple_2(v: (u64, u64)) -> (u64, u64) { v } + /* END TUPLE2 */ + + /* START TUPLE3 */ + fn in_tuple_3(v: (u64, u64, u64)) -> (u64, u64, u64) { v } + /* END TUPLE3 */ + + /* START TUPLE4 */ + fn in_tuple_4(v: (u64, u64, u64, u64)) -> (u64, u64, u64, u64) { v } + /* END TUPLE4 */ + + /* START STRUCT_U64 */ + fn in_struct_u64(v: S1) -> S1 { v } + /* END STRUCT_U64 */ + + /* START STRUCT_U64_U64 */ + fn in_struct_u64_u64(v: S2) -> S2 { v } + /* END STRUCT_U64_U64 */ + + /* START STRUCT_U64_U64_U64 */ + fn in_struct_u64_u64_u64(v: S3) -> S3 { v } + /* END STRUCT_U64_U64_U64 */ + + /* START ENUM_U64 */ + fn in_enum_u64(v: E1) -> E1 { v } + /* END ENUM_U64 */ + + /* START ENUM_U64_U64 */ + fn in_enum_u64_u64(v: E2) -> E2 { v } + /* END ENUM_U64_U64 */ + + /* START ENUM_U64_U64_U64 */ + fn in_enum_u64_u64_u64(v: E3) -> E3 { v } + /* END ENUM_U64_U64_U64 */ +} + +/* START BOOL */ +#[test] +fn cost_of_in_bool() { + let _ = abi(MyContract, CONTRACT_ID).in_bool(false); +} +/* END BOOL */ + +/* START U8 */ +#[test] +fn cost_of_in_u8() { + let _ = abi(MyContract, CONTRACT_ID).in_u8(0); +} +/* END U8 */ + +/* START U16 */ +#[test] +fn cost_of_in_u16() { + let _ = abi(MyContract, CONTRACT_ID).in_u16(0); +} +/* END U16 */ + +/* START U32 */ +#[test] +fn cost_of_in_u32() { + let _ = abi(MyContract, CONTRACT_ID).in_u32(0); +} +/* END U32 */ + +/* START U64 */ +#[test] +fn cost_of_in_u64() { + let _ = abi(MyContract, CONTRACT_ID).in_u64(0); +} +/* END U64 */ + +/* START U256 */ +#[test] +fn cost_of_in_u256() { + let _ = abi(MyContract, CONTRACT_ID).in_u256(0x0000000000000000000000000000000000000000000000000000000000000000u256); +} +/* END U256 */ + +/* START B256 */ +#[test] +fn cost_of_in_b256() { + let _ = abi(MyContract, CONTRACT_ID).in_b256(0x0000000000000000000000000000000000000000000000000000000000000000); +} +/* END B256 */ + +/* START STR0 */ +#[test] +fn cost_of_in_str_0() { + let _ = abi(MyContract, CONTRACT_ID).in_str_0(__to_str_array("")); +} +/* END STR0 */ + +/* START STR1 */ +#[test] +fn cost_of_in_str_1() { + let _ = abi(MyContract, CONTRACT_ID).in_str_1(__to_str_array("1")); +} +/* END STR1 */ + +/* START STR8 */ +#[test] +fn cost_of_in_str_8() { + let _ = abi(MyContract, CONTRACT_ID).in_str_8(__to_str_array("12345678")); +} +/* END STR8 */ + +/* START STR16 */ +#[test] +fn cost_of_in_str_16() { + let _ = abi(MyContract, CONTRACT_ID).in_str_16(__to_str_array("1234567890123456")); +} +/* END STR16 */ + +/* START STR32 */ +#[test] +fn cost_of_in_str_32() { + let _ = abi(MyContract, CONTRACT_ID).in_str_32(__to_str_array("12345678901234567890123456789012")); +} +/* END STR32 */ + +/* START ARRAY0 */ +#[test] +fn cost_of_in_array_0() { + let _ = abi(MyContract, CONTRACT_ID).in_array_0([]); +} +/* END ARRAY0 */ + +/* START ARRAY1 */ +#[test] +fn cost_of_in_array_1() { + let _ = abi(MyContract, CONTRACT_ID).in_array_1([0]); +} +/* END ARRAY1 */ + +/* START ARRAY8 */ +#[test] +fn cost_of_in_array_8() { + let _ = abi(MyContract, CONTRACT_ID).in_array_8([0, 0, 0, 0, 0, 0, 0, 0]); +} +/* END ARRAY8 */ + +/* START ARRAY16 */ +#[test] +fn cost_of_in_array_16() { + let _ = abi(MyContract, CONTRACT_ID).in_array_16([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); +} +/* END ARRAY16 */ + +/* START ARRAY32 */ +#[test] +fn cost_of_in_array_32() { + let _ = abi(MyContract, CONTRACT_ID).in_array_32([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); +} +/* END ARRAY32 */ + +/* START ARRAY64 */ +#[test] +fn cost_of_in_array_64() { + let _ = abi(MyContract, CONTRACT_ID).in_array_64([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); +} +/* END ARRAY64 */ + +/* START TUPLE0 */ +#[test] +fn cost_of_in_tuple_0() { + let _ = abi(MyContract, CONTRACT_ID).in_tuple_0(()); +} +/* END TUPLE0 */ + +/* START TUPLE1 */ +#[test] +fn cost_of_in_tuple_1() { + let _ = abi(MyContract, CONTRACT_ID).in_tuple_1((0,)); +} +/* END TUPLE1 */ + +/* START TUPLE2 */ +#[test] +fn cost_of_in_tuple_2() { + let _ = abi(MyContract, CONTRACT_ID).in_tuple_2((0,0)); +} +/* END TUPLE2 */ + +/* START TUPLE3 */ +#[test] +fn cost_of_in_tuple_3() { + let _ = abi(MyContract, CONTRACT_ID).in_tuple_3((0,0,0)); +} +/* END TUPLE3 */ + +/* START TUPLE4 */ +#[test] +fn cost_of_in_tuple_4() { + let _ = abi(MyContract, CONTRACT_ID).in_tuple_4((0,0,0,0)); +} +/* END TUPLE4 */ + +/* START STRUCT_U64 */ +#[test] +fn in_struct_u64() { + let _ = abi(MyContract, CONTRACT_ID).in_struct_u64(S1 { a: 0 }); +} +/* END STRUCT_U64 */ + +/* START STRUCT_U64_U64 */ +#[test] +fn in_struct_u64_u64() { + let _ = abi(MyContract, CONTRACT_ID).in_struct_u64_u64(S2 { a: 0, b: 0 }); +} +/* END STRUCT_U64_U64 */ + +/* START STRUCT_U64_U64_U64 */ +#[test] +fn in_struct_u64_u64_u64() { + let _ = abi(MyContract, CONTRACT_ID).in_struct_u64_u64_u64(S3 { a: 0, b: 0, c: 0 }); +} +/* END STRUCT_U64_U64_U64 */ + +/* START ENUM_U64 */ +#[test] +fn in_enum_u64() { + let _ = abi(MyContract, CONTRACT_ID).in_enum_u64(E1::A(0)); +} +/* END ENUM_U64 */ + +/* START ENUM_U64_U64 */ +#[test] +fn in_enum_u64_u64() { + let _ = abi(MyContract, CONTRACT_ID).in_enum_u64_u64(E2::A(0)); +} +/* END ENUM_U64_U64 */ + +/* START ENUM_U64_U64_U64 */ +#[test] +fn in_enum_u64_u64_u64() { + let _ = abi(MyContract, CONTRACT_ID).in_enum_u64_u64_u64(E3::A(0)); +} +/* END ENUM_U64_U64_U64 */ diff --git a/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call/stdout.snap b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call/stdout.snap new file mode 100644 index 00000000000..01aab205782 --- /dev/null +++ b/test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call/stdout.snap @@ -0,0 +1,641 @@ +--- +source: test/src/snapshot/mod.rs +--- +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 101 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [38.76 KB] in ??? + Running 29 tests, filtered 0 tests + +tested -- const_of_contract_call + + test cost_of_in_bool ... ok (???, 2627 gas) + test cost_of_in_u8 ... ok (???, 4874 gas) + test cost_of_in_u16 ... ok (???, 4493 gas) + test cost_of_in_u32 ... ok (???, 4926 gas) + test cost_of_in_u64 ... ok (???, 4934 gas) + test cost_of_in_u256 ... ok (???, 4777 gas) + test cost_of_in_b256 ... ok (???, 2491 gas) + test cost_of_in_str_0 ... ok (???, 3043 gas) + test cost_of_in_str_1 ... ok (???, 3345 gas) + test cost_of_in_str_8 ... ok (???, 3768 gas) + test cost_of_in_str_16 ... ok (???, 3374 gas) + test cost_of_in_str_32 ... ok (???, 3572 gas) + test cost_of_in_array_0 ... FAILED (???, 1632 gas) + test cost_of_in_array_1 ... ok (???, 2125 gas) + test cost_of_in_array_8 ... ok (???, 4724 gas) + test cost_of_in_array_16 ... ok (???, 5096 gas) + test cost_of_in_array_32 ... ok (???, 8421 gas) + test cost_of_in_array_64 ... ok (???, 14895 gas) + test cost_of_in_tuple_0 ... ok (???, 3822 gas) + test cost_of_in_tuple_1 ... ok (???, 4392 gas) + test cost_of_in_tuple_2 ... ok (???, 4761 gas) + test cost_of_in_tuple_3 ... ok (???, 5104 gas) + test cost_of_in_tuple_4 ... ok (???, 5468 gas) + test in_struct_u64 ... ok (???, 3635 gas) + test in_struct_u64_u64 ... ok (???, 3897 gas) + test in_struct_u64_u64_u64 ... ok (???, 4156 gas) + test in_enum_u64 ... ok (???, 3186 gas) + test in_enum_u64_u64 ... ok (???, 3061 gas) + test in_enum_u64_u64_u64 ... ok (???, 3173 gas) + + failures: + test cost_of_in_array_0, "test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call/src/main.sw":347 + revert code: 0 + + + +test result: FAILED. 28 passed; 1 failed; finished in ??? + + Finished in ??? +error: Some tests failed. + +> Block: ARRAY0 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 101 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.448 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_array_0 ... FAILED (???, 1262 gas) + + failures: + test isolated_cost_of_in_array_0, "test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call/src/main.sw":175 + revert code: 0 + + + +test result: FAILED. 0 passed; 1 failed; finished in ??? + + Finished in ??? +error: Some tests failed. + +> Block: ARRAY1 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.624 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_array_1 ... ok (???, 1515 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: ARRAY16 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.648 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_array_16 ... ok (???, 3955 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: ARRAY32 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.648 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_array_32 ... ok (???, 6544 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: ARRAY64 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.848 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_array_64 ... ok (???, 11787 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: ARRAY8 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.784 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_array_8 ... ok (???, 3225 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: B256 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.504 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_b256 ... ok (???, 1462 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: BOOL +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.504 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_bool ... ok (???, 1358 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: ENUM_U64 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.632 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test in_enum_u64 ... ok (???, 1644 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: ENUM_U64_U64 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.784 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test in_enum_u64_u64 ... ok (???, 1658 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: ENUM_U64_U64_U64 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.96 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test in_enum_u64_u64_u64 ... ok (???, 1661 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: STR0 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.536 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_str_0 ... ok (???, 1451 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: STR1 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.736 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_str_1 ... ok (???, 1547 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: STR16 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.776 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_str_16 ... ok (???, 1552 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: STR32 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.792 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_str_32 ... ok (???, 1553 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: STR8 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.752 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_str_8 ... ok (???, 1551 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: STRUCT_U64 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.496 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test in_struct_u64 ... ok (???, 1435 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: STRUCT_U64_U64 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.576 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test in_struct_u64_u64 ... ok (???, 1615 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: STRUCT_U64_U64_U64 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.648 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test in_struct_u64_u64_u64 ... ok (???, 1766 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: TUPLE0 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.024 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_tuple_0 ... ok (???, 1131 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: TUPLE1 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.44 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_tuple_1 ... ok (???, 1412 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: TUPLE2 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.568 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_tuple_2 ... ok (???, 1615 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: TUPLE3 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.64 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_tuple_3 ... ok (???, 1766 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: TUPLE4 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.704 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_tuple_4 ... ok (???, 1916 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: U16 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.528 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_u16 ... ok (???, 1428 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: U256 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.616 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_u256 ... ok (???, 1431 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: U32 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.64 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_u32 ... ok (???, 1554 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: U64 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.256 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_u64 ... ok (???, 1336 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? + +> Block: U8 +> replace-file src/main.sw "fn cost_of_in" "fn isolated_cost_of_in" + +> forc test --path test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call --release --experimental const_generics +exit status: 0 +output: + Building test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call + Compiling library std (test/src/e2e_vm_tests/reduced_std_libs/sway-lib-std-core) + Compiling contract const_of_contract_call (test/src/e2e_vm_tests/test_programs/should_pass/test_contracts/const_of_contract_call) + Finished release [optimized + fuel] target(s) [2.472 KB] in ??? + Running 1 test, filtered 0 tests + +tested -- const_of_contract_call + + test isolated_cost_of_in_u8 ... ok (???, 1352 gas) + +test result: OK. 1 passed; 0 failed; finished in ??? + + Finished in ??? diff --git a/test/src/snapshot/mod.rs b/test/src/snapshot/mod.rs index 1fe54dadc1a..3e112a0e0cb 100644 --- a/test/src/snapshot/mod.rs +++ b/test/src/snapshot/mod.rs @@ -1,9 +1,9 @@ use anyhow::Result; use libtest_mimic::{Arguments, Trial}; use normalize_path::NormalizePath; -use regex::Regex; +use regex::{Captures, Regex}; use std::{ - collections::{BTreeSet, VecDeque}, + collections::{BTreeSet, HashMap, VecDeque}, path::{Path, PathBuf}, str::FromStr, sync::Once, @@ -16,7 +16,7 @@ static FORC_COMPILATION: Once = Once::new(); static FORC_DOC_COMPILATION: Once = Once::new(); fn compile_forc() { - let args = vec!["b", /*"--release",*/ "-p", "forc"]; + let args = vec!["b", "--release", "-p", "forc"]; let o = std::process::Command::new("cargo") .args(args) .output() @@ -25,7 +25,7 @@ fn compile_forc() { } fn compile_forc_doc() { - let args = vec!["b", /*"--release",*/ "-p", "forc-doc"]; + let args = vec!["b", "--release", "-p", "forc-doc"]; let o = std::process::Command::new("cargo") .args(args) .output() @@ -33,6 +33,20 @@ fn compile_forc_doc() { assert!(o.status.success()); } +#[derive(Default)] +struct UndoFiles { + contents: HashMap>, +} + +impl Drop for UndoFiles { + fn drop(&mut self) { + #[allow(clippy::iter_over_hash_type)] + for (path, contents) in self.contents.drain() { + let _ = std::fs::write(path, contents); + } + } +} + pub(super) async fn run(filter_regex: Option<®ex::Regex>) -> Result<()> { let repo_root = PathBuf::from_str(&std::env::var("CARGO_MANIFEST_DIR")?)? .parent() @@ -60,220 +74,334 @@ pub(super) async fn run(filter_regex: Option<®ex::Regex>) -> Result<()> { Trial::test(name.clone(), move || { let snapshot_toml = std::fs::read_to_string(format!("{}/snapshot.toml", dir.display()))?; - let snapshot_toml = toml::from_str::(&snapshot_toml)?; - let cmds = if let Some(cmds) = snapshot_toml.get("cmds") { - cmds.as_array() - .unwrap() - .iter() - .map(|v| v.as_str().unwrap()) - .collect::>() + let snapshot_toml = if snapshot_toml.trim().is_empty() { + "cmds = [ \"forc build --path {root}\" ]".to_string() } else { - vec!["forc build --path {root}"] + snapshot_toml }; + let snapshot_toml = toml::from_str::(&snapshot_toml)?; let root = dir.strip_prefix(&repo_root).unwrap().display().to_string(); - use std::fmt::Write; + let cmds = snapshot_toml.get("cmds").unwrap().as_array().unwrap(); + let mut snapshot = String::new(); - let name = PathBuf::from_str(&name).unwrap(); - let name = name.file_stem().unwrap(); - for cmd in cmds { - let cmd = cmd.replace("{root}", &root).replace("{name}", name.to_str().unwrap()); - - let _ = writeln!(&mut snapshot, "> {cmd}"); - - let mut last_output: Option = None; - - // We intentionally split the command by " | " to allow for - // `regex` command to support `|` operator, although without - // surrounding spaces. - for cmd in cmd.split(" | ") { - let cmd = cmd.trim(); - - let cmd = if let Some(cmd) = cmd.strip_prefix("forc doc ") { - FORC_DOC_COMPILATION.call_once(|| { - compile_forc_doc(); - }); - format!("target/debug/forc-doc {cmd} 1>&2") - } else if let Some(cmd) = cmd.strip_prefix("forc ") { - FORC_COMPILATION.call_once(|| { - compile_forc(); - }); - format!("target/debug/forc {cmd} 1>&2") - } else if let Some(cmd) = cmd.strip_prefix("sub ") { - let arg = cmd.trim(); - if let Some(l) = last_output.take() { - let mut new_output = String::new(); - for line in l.lines() { - if line.contains(arg) { - new_output.push_str(line); - new_output.push('\n'); - } + let _ = run_cmds(&name, &repo_root, &root, cmds, &mut snapshot); + + fn stdout(root: &str, snapshot: &str) { + let root = PathBuf::from_str(root).unwrap(); + let root = root.normalize(); + + let mut insta = insta::Settings::new(); + insta.set_snapshot_path(root); + insta.set_prepend_module_to_snapshot(false); + insta.set_omit_expression(true); + let scope = insta.bind_to_scope(); + insta::assert_snapshot!("stdout", snapshot); + drop(scope); + } + stdout(&format!("{}/{root}", repo_root.display()), &snapshot); + + Ok(()) + }) + }) + .collect(); + + libtest_mimic::run(&args, tests).exit(); +} + +fn run_cmds( + test_name: &String, + repo_root: &PathBuf, + root: &String, + cmds: &Vec, + snapshot: &mut String, +) -> std::result::Result<(), libtest_mimic::Failed> { + use std::fmt::Write; + + let name = PathBuf::from_str(test_name).unwrap(); + let name = name.file_stem().unwrap(); + + let find_blocks_regex = Regex::new(r#"START ([0-9a-zA-Z_]*)"#).unwrap(); + + for cmd in cmds { + match cmd { + toml::Value::String(cmd) => { + let cmd = cmd + .replace("{root}", root) + .replace("{name}", name.to_str().unwrap()); + + let _ = writeln!(snapshot, "> {cmd}"); + + let mut last_output: Option = None; + + // We intentionally split the command by " | " to allow for + // `regex` command to support `|` operator, although without + // surrounding spaces. + for cmd in cmd.split(" | ") { + let cmd = cmd.trim(); + + let cmd = if let Some(cmd) = cmd.strip_prefix("forc doc ") { + FORC_DOC_COMPILATION.call_once(|| { + compile_forc_doc(); + }); + format!("target/release/forc-doc {cmd} 1>&2") + } else if let Some(cmd) = cmd.strip_prefix("forc ") { + FORC_COMPILATION.call_once(|| { + compile_forc(); + }); + format!("target/release/forc {cmd} 1>&2") + } else if let Some(cmd) = cmd.strip_prefix("sub ") { + let arg = cmd.trim(); + if let Some(l) = last_output.take() { + let mut new_output = String::new(); + for line in l.lines() { + if line.contains(arg) { + new_output.push_str(line); + new_output.push('\n'); } - last_output = Some(new_output); } - continue; - } else if let Some(cmd) = cmd.strip_prefix("regex ") { - let arg = cmd.trim(); - let arg = arg.trim_matches('\''); - let regex = Regex::new(arg).expect("regex provided to the snapshot `regex` filter is not a valid Rust regex"); - if let Some(l) = last_output.take() { - let mut new_output = String::new(); - for line in l.lines() { - if regex.is_match(line) { - new_output.push_str(line); - new_output.push('\n'); - } + last_output = Some(new_output); + } + continue; + } else if let Some(cmd) = cmd.strip_prefix("regex ") { + let arg = cmd.trim(); + let arg = arg.trim_matches('\''); + let regex = Regex::new(arg).expect("regex provided to the snapshot `regex` filter is not a valid Rust regex"); + if let Some(l) = last_output.take() { + let mut new_output = String::new(); + for line in l.lines() { + if regex.is_match(line) { + new_output.push_str(line); + new_output.push('\n'); } - last_output = Some(new_output); } - continue; - } else if let Some(args) = cmd.strip_prefix("filter-fn") { - if let Some(output) = last_output.take() { - let (name, fns) = args.trim().split_once(" ").unwrap(); - - let fns = fns.split(",") - .map(|x| x.trim().to_string()) - .collect::>(); - - let mut captured = String::new(); - - let mut inside_ir = false; - let mut inside_asm = false; - let mut last_asm_lines = VecDeque::new(); - let mut capture_line = false; - - let compiling_project_line = format!("Compiling script {name}"); - for line in output.lines() { - if line.contains(&compiling_project_line) { - inside_ir = true; - } + last_output = Some(new_output); + } + continue; + } else if let Some(args) = cmd.strip_prefix("replace-file ") { + let Some((path, args)) = args.trim().split_once(" ") else { + panic!("replace needs three arguments: file from to"); + }; + let Some(from) = args.trim().strip_prefix("\"") else { + panic!("replace arguments must be quoted"); + }; + let Some((from, args)) = from.split_once("\"") else { + panic!("replace arguments must be quoted"); + }; - if line.contains(";; ASM: Final program") { - inside_asm = true; - } + let Some(to) = args.trim().strip_prefix("\"") else { + panic!("replace arguments must be quoted"); + }; + let Some((to, _)) = to.split_once("\"") else { + panic!("replace arguments must be quoted"); + }; - if inside_ir { - if line.starts_with("// IR:") { - capture_line = true; - } + let proj_root = repo_root.join(root); + let path = proj_root.join(path); + let path = path.canonicalize().unwrap(); + + if !path + .display() + .to_string() + .starts_with(&proj_root.display().to_string()) + { + panic!("not allowed to edit files outside project folder"); + } + + let contents = std::fs::read_to_string(&path).unwrap(); + let contents = contents.replace(from, to); + std::fs::write(path, contents).unwrap(); + + continue; + } else if let Some(args) = cmd.strip_prefix("filter-fn ") { + if let Some(output) = last_output.take() { + let (name, fns) = args.trim().split_once(" ").unwrap(); + + let fns = fns + .split(",") + .map(|x| x.trim().to_string()) + .collect::>(); + + let mut captured = String::new(); + + let mut inside_ir = false; + let mut inside_asm = false; + let mut last_asm_lines = VecDeque::new(); + let mut capture_line = false; + + let compiling_project_line = format!("Compiling script {name}"); + for line in output.lines() { + if line.contains(&compiling_project_line) { + inside_ir = true; + } - if line.starts_with("!0 =") { - let engines = Engines::default(); - let ir = sway_ir::parse(&captured, engines.se(), ExperimentalFeatures::default(), Backtrace::default()).unwrap(); - - for m in ir.module_iter() { - for f in m.function_iter(&ir) { - if fns.contains(f.get_name(&ir)) { - snapshot.push('\n'); - function_print(&mut snapshot, &ir, f, false).unwrap(); - snapshot.push('\n'); - } - } - } + if line.contains(";; ASM: Final program") { + inside_asm = true; + } - capture_line = false; - inside_ir = false; - captured.clear(); - } + if inside_ir { + if line.starts_with("// IR:") { + capture_line = true; } - if inside_asm { - if line.contains("save locals base register for function") { - for f in fns.iter() { - if line.contains(f.as_str()) { - capture_line = true; - + if line.starts_with("!0 =") { + let engines = Engines::default(); + let ir = sway_ir::parse( + &captured, + engines.se(), + ExperimentalFeatures::default(), + Backtrace::None, + ) + .unwrap(); + + for m in ir.module_iter() { + for f in m.function_iter(&ir) { + if fns.contains(f.get_name(&ir)) { + snapshot.push('\n'); + function_print(snapshot, &ir, f, false) + .unwrap(); snapshot.push('\n'); - - for l in last_asm_lines.drain(..) { - snapshot.push_str(l); - snapshot.push('\n'); - } } } } - // keep the last two lines - if last_asm_lines.len() >= 2 { - last_asm_lines.pop_front(); - } - last_asm_lines.push_back(line); + capture_line = false; + inside_ir = false; + captured.clear(); + } + } - if line.is_empty() { - inside_asm = false; - } + if inside_asm { + if line.contains("save locals base register for function") { + for f in fns.iter() { + if line.contains(f.as_str()) { + capture_line = true; - if line.contains("; return from call") { - if capture_line { - captured.push_str(line); - captured.push('\n'); + snapshot.push('\n'); - write!(&mut snapshot, "{captured}").unwrap(); - captured.clear(); + for l in last_asm_lines.drain(..) { + snapshot.push_str(l); + snapshot.push('\n'); + } } - - capture_line = false; } } - if capture_line { - captured.push_str(line); - captured.push('\n'); + // keep the last two lines + if last_asm_lines.len() >= 2 { + last_asm_lines.pop_front(); } - } + last_asm_lines.push_back(line); - last_output = Some(String::new()); - } - continue; - } else { - panic!("`{cmd}` is not a supported snapshot command.\nPossible tool commands: forc doc, forc\nPossible filtering commands: sub, regex, filter-fn"); - }; + if line.is_empty() { + inside_asm = false; + } - let o = duct::cmd!("bash", "-c", cmd.clone()) - .dir(repo_root.clone()) - .stderr_to_stdout() - .stdout_capture(); + if line.contains("; return from call") { + if capture_line { + captured.push_str(line); + captured.push('\n'); - let o = if let Some(last_output) = last_output.as_ref() { - o.stdin_bytes(last_output.as_bytes()) - } else { - o - }; + write!(snapshot, "{captured}").unwrap(); + captured.clear(); + } - let o = o.env("COLUMNS", "10").unchecked().start().unwrap(); - let o = o.wait().unwrap(); - last_output = Some(clean_output(&format!( - "exit status: {}\noutput:\n{}", - o.status.code().unwrap(), - std::str::from_utf8(&o.stdout).unwrap(), - ))); - } + capture_line = false; + } + } + + if capture_line { + captured.push_str(line); + captured.push('\n'); + } + } - let _ = writeln!(&mut snapshot, "{}", last_output.unwrap_or_default()); + last_output = Some(String::new()); + } + continue; + } else { + panic!("`{cmd}` is not a supported snapshot command.\nPossible tool commands: forc doc, forc\nPossible filtering commands: sub, regex, filter-fn"); + }; + + let o = duct::cmd!("bash", "-c", cmd.clone()) + .dir(repo_root.clone()) + .stderr_to_stdout() + .stdout_capture(); + + let o = if let Some(last_output) = last_output.as_ref() { + o.stdin_bytes(last_output.as_bytes()) + } else { + o + }; + + let o = o.env("COLUMNS", "10").unchecked().start().unwrap(); + let o = o.wait().unwrap(); + last_output = Some(clean_output(&format!( + "exit status: {}\noutput:\n{}", + o.status.code().unwrap(), + std::str::from_utf8(&o.stdout).unwrap(), + ))); } - fn stdout(root: &str, snapshot: &str) { - let root = PathBuf::from_str(root).unwrap(); - let root = root.normalize(); + let _ = writeln!(snapshot, "{}", last_output.unwrap_or_default()); + } + toml::Value::Table(map) => { + let repeat_type = map["repeat"].as_str().unwrap(); + let cmds = map["cmds"].as_array().unwrap(); + + match repeat_type { + "for-each-block" => { + fn remove_block_from_file(contents: &str, block_name: &str) -> String { + let block_regex = Regex::new(&format!("\\/\\* START {block_name} \\*\\/[.\\s\\S]+?END {block_name} \\*\\/")).unwrap(); + block_regex + .replace_all(contents, |_: &Captures| -> String { String::new() }) + .to_string() + } + + let path = PathBuf::from_str(root).unwrap().join("src/main.sw"); + let byte_contents = std::fs::read(&path).unwrap(); + let contents = String::from_utf8(byte_contents.clone()).unwrap(); + + let mut blocks = BTreeSet::new(); + + for capture in find_blocks_regex.captures_iter(&contents) { + let name = capture.get(1).unwrap().as_str().to_string(); + blocks.insert(name); + } + + for block in blocks.iter() { + let _ = writeln!(snapshot, "> Block: {block}"); + + let mut undo = UndoFiles::default(); + undo.contents.insert(path.clone(), byte_contents.clone()); + + let mut new_contents = contents.clone(); + for remove_block in blocks.iter() { + if remove_block != block { + new_contents = + remove_block_from_file(&new_contents, remove_block) + .to_string(); + } + } - let mut insta = insta::Settings::new(); - insta.set_snapshot_path(root); - insta.set_prepend_module_to_snapshot(false); - insta.set_omit_expression(true); - let scope = insta.bind_to_scope(); - insta::assert_snapshot!("stdout", snapshot); - drop(scope); + let _ = std::fs::write(&path, new_contents); + let _ = run_cmds(test_name, repo_root, root, cmds, snapshot); + } + } + _ => { + panic!("`{cmd}` is not a supported repeat type.\nPossible types are: for-each-block."); + } } - stdout(&format!("{}/{root}", repo_root.display()), &snapshot); - - Ok(()) - }) - }) - .collect(); + } + _ => { + panic!("`cmds` items can only be strings or inline tables."); + } + } + } - libtest_mimic::run(&args, tests).exit(); + Ok(()) } pub fn discover_tests(test_root: &Path) -> Vec {