Skip to content

Commit

Permalink
[DVX-487] sui-move tests based on shell scripts (#20885)
Browse files Browse the repository at this point in the history
## Description 

This introduces a test runner for `sui-move` that just runs shell
scripts and snapshots the output. It also adds a handful of tests for
`sui-move new`.


## Test plan 

It is tests. I did temporarily change some things locally to ensure that
the tests were actually catching some errors

---

## Release notes

Check each box that your changes affect. If none of the boxes relate to
your changes, release notes aren't required.

For each box you select, include information after the relevant heading
that describes the impact of your changes that a user might notice and
any actions they must take to implement updates.

- [ ] Protocol: 
- [ ] Nodes (Validators and Full nodes): 
- [ ] gRPC:
- [ ] JSON-RPC: 
- [ ] GraphQL: 
- [ ] CLI: 
- [ ] Rust SDK:
  • Loading branch information
mdgeorge4153 authored Jan 23, 2025
1 parent c63ead2 commit 791ce91
Show file tree
Hide file tree
Showing 23 changed files with 326 additions and 9 deletions.
20 changes: 17 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ indexmap = { version = "2.1.0", features = ["serde"] }
indicatif = "0.17.2"
inquire = "0.6.0"
insta = { version = "1.21.1", features = ["redactions", "yaml", "json"] }
insta-cmd = "0.6.0"
integer-encoding = "3.0.1"
ipnetwork = "0.20.0"
itertools = "0.13.0"
Expand Down Expand Up @@ -536,6 +537,7 @@ unescape = "0.1.0"
ureq = "2.9.1"
url = "2.3.1"
uuid = { version = "1.1.2", features = ["v4", "fast-rng"] }
walkdir = "2.5.0"
webpki = { version = "0.102", package = "rustls-webpki", features = [
"alloc",
"std",
Expand Down
11 changes: 11 additions & 0 deletions crates/sui-move/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ serde_yaml.workspace = true
tracing.workspace = true
prometheus.workspace = true
bin-version.workspace = true
datatest-stable.workspace = true

move-binary-format.workspace = true
move-cli.workspace = true
Expand Down Expand Up @@ -45,6 +46,9 @@ futures.workspace = true
jsonrpsee.workspace = true
rand.workspace = true
tempfile.workspace = true
walkdir.workspace = true
insta-cmd.workspace = true
insta.workspace = true

move-package.workspace = true

Expand All @@ -56,3 +60,10 @@ sui-simulator.workspace = true

[package.metadata.cargo-udeps.ignore]
normal = ["jemalloc-ctl"]

[[test]]
name = "cli_tests"
harness = false

[lints]
workspace = true
3 changes: 2 additions & 1 deletion crates/sui-move/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use clap::Parser;
use move_cli::base::test::UnitTestResult;
use move_package::BuildConfig;
use std::path::Path;
use sui_move_build::set_sui_flavor;
use sui_move_build::{set_sui_flavor, SuiPackageHooks};

pub mod build;
pub mod coverage;
Expand Down Expand Up @@ -41,6 +41,7 @@ pub fn execute_move_command(
if let Some(err_msg) = set_sui_flavor(&mut build_config) {
anyhow::bail!(err_msg);
}
move_package::package_hooks::register_package_hooks(Box::new(SuiPackageHooks));
match command {
Command::Build(c) => c.execute(package_path, build_config),
Command::Coverage(c) => c.execute(package_path, build_config),
Expand Down
79 changes: 79 additions & 0 deletions crates/sui-move/tests/cli_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use insta_cmd::get_cargo_bin;
use std::fs;
use std::path::Path;
use std::process::Command;
use walkdir::WalkDir;

// [test_shell_snapshot] is run on every file matching [TEST_PATTERN] in [TEST_DIR]; this runs the
// files as shell scripts and compares their output to the snapshots; use `cargo insta test
// --review` to update the snapshots.

const TEST_DIR: &str = "tests/tests";
const TEST_PATTERN: &str = r"^test.*\.sh$";

/// run the bash script at [path], comparing its output to the insta snapshot of the same name.
/// The script is run in a temporary working directory that contains a copy of the parent directory
/// of [path], with the `sui-move` binary on the path.
fn test_shell_snapshot(path: &Path) -> datatest_stable::Result<()> {
// copy files into temporary directory
let srcdir = path.parent().unwrap();
let tmpdir = tempfile::tempdir()?;
let sandbox = tmpdir.path().join("sandbox");

for entry in WalkDir::new(srcdir) {
let entry = entry.unwrap();
let srcfile = entry.path();
let dstfile = sandbox.join(srcfile.strip_prefix(srcdir)?);
if srcfile.is_dir() {
fs::create_dir_all(dstfile)?;
} else {
fs::copy(srcfile, dstfile)?;
}
}

// set up command
let mut shell = Command::new("bash");
shell
.env("PATH", format!("/bin:/usr/bin:{}", get_sui_move_path()))
.current_dir(sandbox)
.arg(path.file_name().unwrap());

// run it; snapshot test output
let output = shell.output()?;
let result = format!(
"success: {:?}\nexit_code: {}\n----- stdout -----\n{}\n----- stderr -----\n{}",
output.status.success(),
output.status.code().unwrap_or(!0),
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);

let snapshot_name: String = path
.strip_prefix("tests/tests")?
.to_string_lossy()
.to_string();

insta::with_settings!({description => path.to_string_lossy(), omit_expression => true}, {
insta::assert_snapshot!(snapshot_name, result);
});

Ok(())
}

fn get_sui_move_path() -> String {
get_cargo_bin("sui-move")
.parent()
.unwrap()
.to_str()
.expect("directory name is valid UTF-8")
.to_owned()
}

#[cfg(not(msim))]
datatest_stable::harness!(test_shell_snapshot, TEST_DIR, TEST_PATTERN);

#[cfg(msim)]
fn main() {}
11 changes: 11 additions & 0 deletions crates/sui-move/tests/snapshots/cli_tests__dummy__dummy.sh.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
source: crates/sui-move/tests/cli_tests.rs
description: tests/tests/dummy/dummy.sh
---
success: true
exit_code: 0
----- stdout -----
dummy test
some dummy data

----- stderr -----
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
source: crates/sui-move/tests/cli_tests.rs
description: tests/tests/new_tests/gitignore_exists.sh
---
success: true
exit_code: 0
----- stdout -----
existing_ignore
build/*
----- stderr -----
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
source: crates/sui-move/tests/cli_tests.rs
description: tests/tests/new_tests/gitignore_has_build.sh
---
success: true
exit_code: 0
----- stdout -----
ignore1
build/*
ignore2
==== files in example/ ====
.gitignore
Move.toml
sources
tests
----- stderr -----
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
source: crates/sui-move/tests/cli_tests.rs
description: tests/tests/new_tests/manifest_template.sh
---
success: true
exit_code: 0
----- stdout -----
[package]
name = "example"
edition = "2024.beta" # edition = "legacy" to use legacy (pre-2024) Move
# license = "" # e.g., "MIT", "GPL", "Apache 2.0"
# authors = ["..."] # e.g., ["Joe Smith ([email protected])", "John Snow ([email protected])"]

[dependencies]
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "framework/testnet" }

# For remote import, use the `{ git = "...", subdir = "...", rev = "..." }`.
# Revision can be a branch, a tag, and a commit hash.
# MyRemotePackage = { git = "https://some.remote/host.git", subdir = "remote/path", rev = "main" }

# For local dependencies use `local = path`. Path is relative to the package root
# Local = { local = "../path/to" }

# To resolve a version conflict and force a specific version for dependency
# override use `override = true`
# Override = { local = "../conflicting/version", override = true }

[addresses]
example = "0x0"

# Named addresses will be accessible in Move as `@name`. They're also exported:
# for example, `std = "0x1"` is exported by the Standard Library.
# alice = "0xA11CE"

[dev-dependencies]
# The dev-dependencies section allows overriding dependencies for `--test` and
# `--dev` modes. You can introduce test-only dependencies here.
# Local = { local = "../path/to/dev-build" }

[dev-addresses]
# The dev-addresses section allows overwriting named addresses for the `--test`
# and `--dev` modes.
# alice = "0xB0B"


----- stderr -----
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
source: crates/sui-move/tests/cli_tests.rs
description: tests/tests/new_tests/new_files.sh
---
success: true
exit_code: 0
----- stdout -----
==== files in project ====
.gitignore
Move.toml
sources
tests
==== files in sources ====
example.move
==== files in tests =====
example_tests.move

----- stderr -----
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
source: crates/sui-move/tests/cli_tests.rs
description: tests/tests/new_tests/new_then_build.sh
---
success: true
exit_code: 0
----- stdout -----

----- stderr -----
INCLUDING DEPENDENCY Sui
INCLUDING DEPENDENCY MoveStdlib
BUILDING example
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
source: crates/sui-move/tests/cli_tests.rs
description: tests/tests/new_tests/new_then_test.sh
---
success: true
exit_code: 0
----- stdout -----
INCLUDING DEPENDENCY Sui
INCLUDING DEPENDENCY MoveStdlib
BUILDING example
Running Move unit tests
Test result: OK. Total tests: 0; passed: 0; failed: 0

----- stderr -----
1 change: 1 addition & 0 deletions crates/sui-move/tests/tests/dummy/data/data.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
some dummy data
7 changes: 7 additions & 0 deletions crates/sui-move/tests/tests/dummy/dummy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Copyright (c) Mysten Labs, Inc.
# SPDX-License-Identifier: Apache-2.0

# simple test just to make sure the test runner works
echo "dummy test"
cat data/data.txt
sui-move new dummy
8 changes: 8 additions & 0 deletions crates/sui-move/tests/tests/new_tests/gitignore_exists.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Copyright (c) Mysten Labs, Inc.
# SPDX-License-Identifier: Apache-2.0

# check that sui-move new correctly updates existing .gitignore
mkdir example
echo "existing_ignore" > example/.gitignore
sui-move new example
cat example/.gitignore
13 changes: 13 additions & 0 deletions crates/sui-move/tests/tests/new_tests/gitignore_has_build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright (c) Mysten Labs, Inc.
# SPDX-License-Identifier: Apache-2.0

# sui-move new example when `example/.gitignore` already contains build/*; it should be unchanged
mkdir example
echo "ignore1" >> example/.gitignore
echo "build/*" >> example/.gitignore
echo "ignore2" >> example/.gitignore
sui-move new example
cat example/.gitignore
echo
echo ==== files in example/ ====
ls -A example
5 changes: 5 additions & 0 deletions crates/sui-move/tests/tests/new_tests/manifest_template.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright (c) Mysten Labs, Inc.
# SPDX-License-Identifier: Apache-2.0

sui-move new example
cat example/Move.toml
11 changes: 11 additions & 0 deletions crates/sui-move/tests/tests/new_tests/new_files.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Copyright (c) Mysten Labs, Inc.
# SPDX-License-Identifier: Apache-2.0

# basic test that sui-move new outputs correct files
sui-move new example
echo ==== files in project ====
ls -A example
echo ==== files in sources ====
ls -A example/sources
echo ==== files in tests =====
ls -A example/tests
18 changes: 18 additions & 0 deletions crates/sui-move/tests/tests/new_tests/new_then_build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright (c) Mysten Labs, Inc.
# SPDX-License-Identifier: Apache-2.0

# tests that sui-move new followed by sui-move build succeeds

sui-move new example

# we mangle the generated toml file to replace the framework dependency with a local dependency
FRAMEWORK_DIR=$(echo $CARGO_MANIFEST_DIR | sed 's#/crates/sui-move##g')
cat example/Move.toml \
| sed 's#\(Sui = .*\)git = "[^"]*", \(.*\)#\1\2#' \
| sed 's#\(Sui = .*\), rev = "[^"]*"\(.*\)#\1\2#' \
| sed 's#\(Sui = .*\)subdir = "\([^"]*\)"\(.*\)#\1local = "FRAMEWORK/\2"\3#' \
| sed "s#\(Sui = .*\)FRAMEWORK\(.*\)#\1$FRAMEWORK_DIR\2#" \
> Move.toml
mv Move.toml example/Move.toml

cd example && sui-move build
Loading

0 comments on commit 791ce91

Please sign in to comment.