Skip to content

test(stackable-versioned): Add snapshot testing #881

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

Merged
merged 15 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.stderr linguist-generated
*.snap linguist-generated
90 changes: 90 additions & 0 deletions Cargo.lock

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

15 changes: 11 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ either = "1.13.0"
futures = "0.3.30"
futures-util = "0.3.30"
indexmap = "2.5"
insta = { version= "1.40", features = ["glob"] }
hyper = { version = "1.4.1", features = ["full"] }
hyper-util = "0.1.8"
itertools = "0.13.0"
Expand All @@ -41,6 +42,7 @@ opentelemetry-otlp = "0.16.0"
opentelemetry-semantic-conventions = "0.15.0"
p256 = { version = "0.13.2", features = ["ecdsa"] }
pin-project = "1.1.5"
prettyplease = "0.2.22"
proc-macro2 = "1.0.86"
quote = "1.0.37"
rand = "0.8.5"
Expand Down Expand Up @@ -77,7 +79,12 @@ x509-cert = { version = "0.2.5", features = ["builder"] }
zeroize = "1.8.1"

# Use O3 in tests to improve the RSA key generation speed in the stackable-certs crate
[profile.test.package.stackable-certs]
opt-level = 3
[profile.test.package."rsa"]
opt-level = 3
[profile.test.package]
stackable-certs.opt-level = 3
rsa.opt-level = 3

# Run snapshot testing faster even as a dev dependecy.
# See https://insta.rs/docs/quickstart/#optional-faster-runs
[profile.dev.package]
insta.opt-level = 3
similar.opt-level = 3
4 changes: 4 additions & 0 deletions crates/stackable-versioned-macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,13 @@ syn.workspace = true
quote.workspace = true

[dev-dependencies]
insta.workspace = true
prettyplease.workspace = true
regex.workspace = true
rstest.workspace = true
schemars.workspace = true
serde.workspace = true
serde_json.workspace = true
serde_yaml.workspace = true
snafu.workspace = true
trybuild.workspace = true
60 changes: 60 additions & 0 deletions crates/stackable-versioned-macros/fixtures/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Snapshot Testing

> [!NOTE]
> Also see the compile-fail tests, described [here](../tests/README.md).

This folder contains fixtures for snapshot testing the `#[versioned()]` macro. Snapshot testing is
done using the [insta] crate. It provides a [CLI tool][insta-cli] called `cargo-insta` and a
[VS Code extension][insta-ext].

Test inputs and snapshots of the expected output are located in the `fixtures` folder. There are two
inputs to the `#[versioned()]` macro because it is an attribute macro:

> The first TokenStream is the delimited token tree following the attribute’s name, not including
> the outer delimiters. If the attribute is written as a bare attribute name, the attribute
> TokenStream is empty. The second TokenStream is the rest of the item including other attributes on
> the item.
>
> _(Taken from the [Rust reference][rust-ref])_

Because of that, a special delimiter is used in the input files which separates the two inputs while
still enabling developers to write valid Rust code. The delimiter is `// ---\n`. Most of the inner
workings are located in [this file](../src/test_utils.rs).

```rust
#[versioned(
version(name = "v1alpha1"),
version(name = "v1beta1"),
version(name = "v1")
)]
// --- <- See here!
pub(crate) struct Foo {
#[versioned(
changed(since = "v1beta1", from_name = "jjj", from_type = "u8"),
changed(since = "v1", from_type = "u16"),
)]
bar: usize,
baz: bool,
}
```

## Recommended Workflow

First, add new input files (which automatically get picked up by `insta`) to the `fixtures/inputs`
folder. Make sure the delimiter is placed correctly between the attribute and the container
definition. Doc comments on the container have to be placed after the delimiter. Next, generate the
snapshot files (initially not accepted) by running

```shell
cargo insta test -p stackable-versioned-macros
```

This command will place the new snapshot files (with a `.new` extension) in the `fixtures/snapshots`
folder. These new snapshot files must not appear on `main`, but can be shared on branches for
collaboration. To review them, run the `cargo insta review` command, then accept or fix the
snapshots. Once all are accepted (ie: no `.new` files remaining), check in the files.

[rust-ref]: https://doc.rust-lang.org/reference/procedural-macros.html#attribute-macros
[insta-ext]: https://insta.rs/docs/vscode/
[insta-cli]: https://insta.rs/docs/cli/
[insta]: https://insta.rs/
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#[versioned(
version(name = "v1alpha1"),
version(
name = "v1beta1",
doc = r#"
Additional docs for this version which are purposefully long to
show how manual line wrapping works. \
Multi-line docs are also supported, as per regular doc-comments.
"#
),
version(name = "v1beta2"),
version(name = "v1"),
version(name = "v2"),
options(skip(from))
)]
// ---
#[derive(Default)]
enum Foo {
/// This variant is available in every version (so far).
#[default]
Foo,

/// Keep the main field docs the same, even after the field is
/// deprecated.
#[versioned(deprecated(since = "v1beta1", note = "gone"))]
DeprecatedBar,

/// This is for baz
#[versioned(added(since = "v1beta1"))]
// Just to check stackable-versioned deprecation warning appears.
// #[deprecated]
Baz,

/// This is will keep changing over time.
#[versioned(changed(since = "v1beta1", from_name = "Qoox"))]
#[versioned(changed(since = "v1", from_name = "Qaax"))]
Quux,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#[versioned(
version(name = "v1alpha1"),
version(
name = "v1beta1",
doc = r#"
Additional docs for this version which are purposefully long to
show how manual line wrapping works. \
Multi-line docs are also supported, as per regular doc-comments.
"#
),
version(name = "v1beta2"),
version(name = "v1"),
version(name = "v2"),
options(skip(from))
)]
// ---
/// Test
#[derive(Default)]
struct Foo {
/// This field is available in every version (so far).
foo: String,

/// Keep the main field docs the same, even after the field is deprecated.
#[versioned(deprecated(since = "v1beta1", note = "gone"))]
deprecated_bar: String,

/// This is for baz
#[versioned(added(since = "v1beta1"))]
baz: String,

/// This is will keep changing over time.
#[versioned(changed(since = "v1beta1", from_name = "qoox"))]
#[versioned(changed(since = "v1", from_name = "qaax"))]
quux: String,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#[versioned(
version(name = "v1alpha1", deprecated),
version(name = "v1beta1"),
version(name = "v1"),
version(name = "v2"),
version(name = "v3")
)]
// ---
pub(crate) struct Foo {
#[versioned(
changed(since = "v1beta1", from_name = "jjj", from_type = "u8"),
changed(since = "v1", from_type = "u16"),
deprecated(since = "v2", note = "not empty")
)]
/// Test
deprecated_bar: usize,
baz: bool,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#[versioned(
version(name = "v1alpha1"),
version(name = "v1beta1"),
version(name = "v1"),
version(name = "v2"),
version(name = "v3")
)]
// ---
enum Foo {
#[versioned(deprecated(since = "v1"))]
DeprecatedBar,
Baz,
}
Loading
Loading