jj/Cargo.toml
Jonas Greitemann e000275ba5 merge-tools builtin: add property-based testing
This adds the proptest crate for property-based testing as well as the
proptest-state-machine crate as direct dev dependencies of jj-cli and as
dependencies of the internal testutils crate. 

Within testutils, a `proptest` module provides a reference state machine
which models a repository workspace as a tree-like data structure whose
leaves represent `File`s. The possible transitions of this state machine
are for now limited to the creation of new files (including replacements
of existing files or directories) and deletions of files (pruning the
tree of empty directory nodes). Additional transitions (moving files,
modifying file contents incrementally, ...) and states (symlinks,
submodules, conflicts, ...) may be added in the future.

The `ReferenceStateMachine` trait implementation provides proptest
with strategies for the generation and shrinking of both the initial
state and the transitions that are replayed on it; by shrinking the
transitions rather than another independent reference state, proptest
can search of a failing test input with a minimal diff. This makes this
approach quite suited to VCS problems.

This reference state machine is then applied to the builtin merge-tool's
test suite:
- The initial state is used to build a corresponding `MergedTree`. Its
  ID is used for the fixed "left" tree and serves as the starting point
  for the right tree.
- As transitions are applied, the right tree is updated accordingly.
- Each step of the way, the same test logic as in the manual
  `test_edit_diff_builtin*` tests is run to check that splitting off
  none or all of the changes results in the left or right tree,
  respectively.

Aside from the bug already captured by `*_replace_directory_with_file`,
the property-based test found an independent problem related to file
mode changes of empty files. Regression test seeds for both of these
issues are also checked in. This ensures that others / CI will reproduce
known edge cases deterministically before randomly exploring additional
onwards.
2025-05-04 16:56:14 +02:00

164 lines
4.8 KiB
TOML

cargo-features = []
[workspace]
resolver = "3"
members = ["cli", "lib", "lib/gen-protos", "lib/proc-macros", "lib/testutils"]
[workspace.package]
version = "0.28.2"
license = "Apache-2.0"
rust-version = "1.84" # NOTE: remember to update CI, contributing.md, changelog.md, and install-and-setup.md
edition = "2021"
readme = "README.md"
homepage = "https://github.com/jj-vcs/jj"
repository = "https://github.com/jj-vcs/jj"
documentation = "https://jj-vcs.github.io/jj/"
categories = ["version-control", "development-tools"]
keywords = ["VCS", "DVCS", "SCM", "Git", "Mercurial"]
[workspace.dependencies]
assert_cmd = "2.0.8"
assert_matches = "1.5.0"
async-trait = "0.1.88"
blake2 = "0.10.6"
bstr = "1.11.3"
clap = { version = "4.5.37", features = [
"derive",
"deprecated",
"wrap_help",
"string",
] }
clap_complete = { version = "4.5.47", features = ["unstable-dynamic"] }
clap_complete_nushell = "4.5.5"
# Update clap-markdown manually since test_generate_md_cli_help snapshot
# will need regenerating.
clap-markdown = "=0.1.5"
clap_mangen = "0.2.25"
chrono = { version = "0.4.40", default-features = false, features = [
"std",
"clock",
] }
clru = "0.6.2"
criterion = "0.5.1"
crossterm = { version = "0.28", default-features = false, features = ["windows"] }
datatest-stable = "0.3.2"
digest = "0.10.7"
dunce = "1.0.5"
etcetera = "0.10.0"
either = "1.15.0"
futures = "0.3.31"
git2 = { version = "0.20.1", features = [
# Do *not* disable this feature even if you'd like dynamic linking. Instead,
# set the environment variable `LIBGIT2_NO_VENDOR=1` if dynamic linking must
# be used (this will override the Cargo feature), and allow static linking
# in other cases. Rationale: If neither the feature nor the environment
# variable are set, `git2` may still decide to vendor `libgit2` if it
# doesn't find a version of `libgit2` to link to dynamically. See also
# https://github.com/rust-lang/git2-rs/commit/3cef4119f
"vendored-libgit2"
] }
gix = { version = "0.71.0", default-features = false, features = [
"attributes",
"blob-diff",
"index",
"max-performance-safe",
"zlib-rs",
] }
glob = "0.3.2"
hashbrown = { version = "0.15.2", default-features = false, features = ["inline-more"] }
hex = "0.4.3"
ignore = "0.4.23"
indexmap = { version = "2.9.0", features = ["serde"] }
indoc = "2.0.6"
insta = { version = "1.43.0", features = ["filters"] }
interim = { version = "0.2.1", features = ["chrono_0_4"] }
itertools = "0.14.0"
libc = { version = "0.2.172" }
maplit = "1.0.2"
num_cpus = "1.16.0"
once_cell = "1.21.3"
os_pipe = "1.2.1"
pest = "2.8.0"
pest_derive = "2.8.0"
pollster = "0.4.0"
pretty_assertions = "1.4.1"
proc-macro2 = "1.0.95"
proptest = "1.6.0"
proptest-state-machine = "0.3.1"
prost = "0.13.5"
prost-build = "0.13.5"
quote = "1.0.40"
rand = "0.8.5"
rand_chacha = "0.3.1"
rayon = "1.10.0"
ref-cast = "1.0.24"
regex = "1.11.1"
rpassword = "7.4.0"
rustix = { version = "1.0.5", features = ["fs"] }
same-file = "1.0.6"
sapling-renderdag = "0.1.0"
sapling-streampager = "0.11.0"
scm-record = "0.8.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.140"
slab = "0.4.9"
smallvec = { version = "1.14.0", features = [
"const_generics",
"const_new",
"union",
] }
strsim = "0.11.1"
syn = "2.0.101"
tempfile = "3.19.1"
test-case = "3.3.1"
textwrap = "0.16.2"
thiserror = "2.0.12"
timeago = { version = "0.4.2", default-features = false }
tokio = { version = "1.44.2" }
toml_edit = { version = "0.22.25", features = ["serde"] }
tracing = "0.1.41"
tracing-chrome = "0.7.2"
tracing-subscriber = { version = "0.3.19", default-features = false, features = [
"std",
"ansi",
"env-filter",
"fmt",
] }
unicode-width = "0.2.0"
version_check = "0.9.5"
watchman_client = { version = "0.9.0" }
whoami = "1.6.0"
winreg = "0.52"
# put all inter-workspace libraries, i.e. those that use 'path = ...' here in
# their own (alphabetically sorted) block
jj-lib = { path = "lib", version = "0.28.2", default-features = false }
jj-lib-proc-macros = { path = "lib/proc-macros", version = "0.28.2" }
testutils = { path = "lib/testutils" }
[workspace.lints.clippy]
explicit_iter_loop = "warn"
flat_map_option = "warn"
implicit_clone = "warn"
needless_for_each = "warn"
semicolon_if_nothing_returned = "warn"
uninlined_format_args = "warn"
unused_trait_names = "warn"
useless_conversion = "warn"
[profile.dev.package]
# Insta suggests compiling these packages in opt mode for faster testing.
# See https://docs.rs/insta/latest/insta/#optional-faster-runs.
insta.opt-level = 3
similar.opt-level = 3
# Proptest suggests compiling itself and its RNG in opt mode as well.
# See https://proptest-rs.github.io/proptest/proptest/tips-and-best-practices.html#setting-opt-level
proptest.opt-level = 3
proptest-state-machine.opt-level = 3
rand_chacha.opt-level = 3
[profile.release]
strip = "debuginfo"
codegen-units = 1