From b3fe74cc97305908d67f9deb5f5a16b28667423d Mon Sep 17 00:00:00 2001 From: Ivan Carvalho <8753214+IvanIsCoding@users.noreply.github.com> Date: Wed, 10 Jul 2024 10:02:35 -0400 Subject: [PATCH] Add support for shared test-only modules (#2734) Currently, `rust_test_suite` is not capable of supporting integration tests with shared modules. A very basic example is: ``` [crate]/ src/ lib.rs tests/ integration_test_a.rs integration_test_b.rs util/ mod.rs ``` With `integration_test_a.rs` and `integration_test_b.rs` importing code from `util`. This PR adds a `shared_srcs` argument to `rust_test_suite`. That way, we can finally compile and run those tests with: ```python rust_test_suite( name = "integrated_tests_suite", srcs = glob(["tests/**"]), shared_srcs = ["tests/util/mod.rs"], deps = [":example_dep"], ) ``` --- docs/defs.md | 6 +++++- docs/flatten.md | 6 +++++- rust/private/rust.bzl | 12 ++++++++++-- test/rust_test_suite_shared/BUILD.bazel | 15 +++++++++++++++ test/rust_test_suite_shared/src/lib.rs | 8 ++++++++ test/rust_test_suite_shared/tests/helpers/mod.rs | 12 ++++++++++++ .../tests/integrated_test_a.rs | 11 +++++++++++ .../tests/integrated_test_b.rs | 11 +++++++++++ 8 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 test/rust_test_suite_shared/BUILD.bazel create mode 100644 test/rust_test_suite_shared/src/lib.rs create mode 100644 test/rust_test_suite_shared/tests/helpers/mod.rs create mode 100644 test/rust_test_suite_shared/tests/integrated_test_a.rs create mode 100644 test/rust_test_suite_shared/tests/integrated_test_b.rs diff --git a/docs/defs.md b/docs/defs.md index 6cadad94bf..d1f6bd3c7b 100644 --- a/docs/defs.md +++ b/docs/defs.md @@ -650,7 +650,7 @@ Run the test with `bazel test //hello_lib:greeting_test`. ## rust_test_suite
-rust_test_suite(name, srcs, kwargs) +rust_test_suite(name, srcs, shared_srcs, kwargs)A rule for creating a test suite for a set of `rust_test` targets. @@ -670,6 +670,8 @@ directory structure: integrated_test_c.rs patterns/ fibonacci_test.rs + helpers/ + mod.rs ``` The rule can be used to generate [rust_test](#rust_test) targets for each source file under `tests` @@ -691,6 +693,7 @@ rust_binary( rust_test_suite( name = "integrated_tests_suite", srcs = glob(["tests/**"]), + shared_srcs=glob(["tests/helpers/**"]), deps = [":math_lib"], ) ``` @@ -706,6 +709,7 @@ rust_test_suite( | :------------- | :------------- | :------------- | | name | The name of the `test_suite`. | none | | srcs | All test sources, typically `glob(["tests/**/*.rs"])`. | none | +| shared_srcs | Optional argument for sources shared among tests, typically helper functions. | `[]` | | kwargs | Additional keyword arguments for the underyling [rust_test](#rust_test) targets. The `tags` argument is also passed to the generated `test_suite` target. | none | diff --git a/docs/flatten.md b/docs/flatten.md index e9a222cc82..f3d33865af 100644 --- a/docs/flatten.md +++ b/docs/flatten.md @@ -1934,7 +1934,7 @@ Assembles a remote repository for the given toolchain params, produces a proxy r ## rust_test_suite
-rust_test_suite(name, srcs, kwargs) +rust_test_suite(name, srcs, shared_srcs, kwargs)A rule for creating a test suite for a set of `rust_test` targets. @@ -1954,6 +1954,8 @@ directory structure: integrated_test_c.rs patterns/ fibonacci_test.rs + helpers/ + mod.rs ``` The rule can be used to generate [rust_test](#rust_test) targets for each source file under `tests` @@ -1975,6 +1977,7 @@ rust_binary( rust_test_suite( name = "integrated_tests_suite", srcs = glob(["tests/**"]), + shared_srcs=glob(["tests/helpers/**"]), deps = [":math_lib"], ) ``` @@ -1990,6 +1993,7 @@ rust_test_suite( | :------------- | :------------- | :------------- | | name | The name of the `test_suite`. | none | | srcs | All test sources, typically `glob(["tests/**/*.rs"])`. | none | +| shared_srcs | Optional argument for sources shared among tests, typically helper functions. | `[]` | | kwargs | Additional keyword arguments for the underyling [rust_test](#rust_test) targets. The `tags` argument is also passed to the generated `test_suite` target. | none | diff --git a/rust/private/rust.bzl b/rust/private/rust.bzl index afe1f129d3..d4dff1b529 100644 --- a/rust/private/rust.bzl +++ b/rust/private/rust.bzl @@ -1393,7 +1393,7 @@ rust_test = rule( """), ) -def rust_test_suite(name, srcs, **kwargs): +def rust_test_suite(name, srcs, shared_srcs = [], **kwargs): """A rule for creating a test suite for a set of `rust_test` targets. This rule can be used for setting up typical rust [integration tests][it]. Given the following @@ -1411,6 +1411,8 @@ def rust_test_suite(name, srcs, **kwargs): integrated_test_c.rs patterns/ fibonacci_test.rs + helpers/ + mod.rs ``` The rule can be used to generate [rust_test](#rust_test) targets for each source file under `tests` @@ -1432,6 +1434,7 @@ def rust_test_suite(name, srcs, **kwargs): rust_test_suite( name = "integrated_tests_suite", srcs = glob(["tests/**"]), + shared_srcs=glob(["tests/helpers/**"]), deps = [":math_lib"], ) ``` @@ -1442,6 +1445,7 @@ def rust_test_suite(name, srcs, **kwargs): Args: name (str): The name of the `test_suite`. srcs (list): All test sources, typically `glob(["tests/**/*.rs"])`. + shared_srcs (list): Optional argument for sources shared among tests, typically helper functions. **kwargs (dict): Additional keyword arguments for the underyling [rust_test](#rust_test) targets. The `tags` argument is also passed to the generated `test_suite` target. """ @@ -1451,12 +1455,16 @@ def rust_test_suite(name, srcs, **kwargs): if not src.endswith(".rs"): fail("srcs should have `.rs` extensions") + if src in shared_srcs: + continue + # Prefixed with `name` to allow parameterization with macros # The test name should not end with `.rs` test_name = name + "_" + src[:-3] rust_test( name = test_name, - srcs = [src], + crate_root = src, + srcs = [src] + shared_srcs, **kwargs ) tests.append(test_name) diff --git a/test/rust_test_suite_shared/BUILD.bazel b/test/rust_test_suite_shared/BUILD.bazel new file mode 100644 index 0000000000..b3848d6458 --- /dev/null +++ b/test/rust_test_suite_shared/BUILD.bazel @@ -0,0 +1,15 @@ +load("//rust:defs.bzl", "rust_library", "rust_test_suite") + +rust_library( + name = "math_lib", + srcs = ["src/lib.rs"], + edition = "2018", +) + +rust_test_suite( + name = "tests_suite", + srcs = glob(["tests/**"]), + edition = "2018", + shared_srcs = glob(["tests/helpers/**"]), + deps = [":math_lib"], +) diff --git a/test/rust_test_suite_shared/src/lib.rs b/test/rust_test_suite_shared/src/lib.rs new file mode 100644 index 0000000000..8236afbdf3 --- /dev/null +++ b/test/rust_test_suite_shared/src/lib.rs @@ -0,0 +1,8 @@ +/// Calculate the n'th fibonacci number +pub fn fibonacci(n: i32) -> i32 { + match n { + 0 => 1, + 1 => 1, + _ => fibonacci(n - 1) + fibonacci(n - 2), + } +} diff --git a/test/rust_test_suite_shared/tests/helpers/mod.rs b/test/rust_test_suite_shared/tests/helpers/mod.rs new file mode 100644 index 0000000000..cf54111b0a --- /dev/null +++ b/test/rust_test_suite_shared/tests/helpers/mod.rs @@ -0,0 +1,12 @@ +// Binet's formula for checking Fibonacci numbers +pub fn is_fibonacci(x: i32) -> bool { + is_perfect_square(5 * x * x + 4) || is_perfect_square(5 * x * x - 4) +} + +fn is_perfect_square(x: i32) -> bool { + if x < 0 { + return false; + } + let y = (x as f64).sqrt() as i32; + y * y == x +} diff --git a/test/rust_test_suite_shared/tests/integrated_test_a.rs b/test/rust_test_suite_shared/tests/integrated_test_a.rs new file mode 100644 index 0000000000..47adea50f5 --- /dev/null +++ b/test/rust_test_suite_shared/tests/integrated_test_a.rs @@ -0,0 +1,11 @@ +mod helpers; + +use helpers::is_fibonacci; +use math_lib::fibonacci; + +#[test] +fn fibonacci_test() { + let fib6 = fibonacci(6); + assert_eq!(fib6, fibonacci(5) + fibonacci(4)); + assert!(is_fibonacci(fib6)); +} diff --git a/test/rust_test_suite_shared/tests/integrated_test_b.rs b/test/rust_test_suite_shared/tests/integrated_test_b.rs new file mode 100644 index 0000000000..4908ecbb48 --- /dev/null +++ b/test/rust_test_suite_shared/tests/integrated_test_b.rs @@ -0,0 +1,11 @@ +mod helpers; + +use helpers::is_fibonacci; +use math_lib::fibonacci; + +#[test] +fn fibonacci_test() { + let fib7 = fibonacci(7); + assert_eq!(fib7, fibonacci(6) + fibonacci(5)); + assert!(is_fibonacci(fib7)); +}