[RFC] Add ability to declare unit tests in udf.rs#4922
[RFC] Add ability to declare unit tests in udf.rs#4922Karakatiza666 wants to merge 3 commits intomainfrom
Conversation
8993061 to
9ba6b57
Compare
Signed-off-by: Karakatiza666 <bulakh.96@gmail.com>
9ba6b57 to
5162e0c
Compare
|
You can make the point with a much smaller example. |
|
That's the example I was working on, did not want to spend time to provide a minimal example just for the PR. |
|
Test failures are displayed in the "Errors" tab and allow navigating to the LOC of the test assertion, but do not prevent starting up the pipeline |
|
So the Rust unit tests run every time the pipeline is recompiled? |
|
Yes |
Signed-off-by: Karakatiza666 <bulakh.96@gmail.com>
|
For the sake of an argument I have added a udf_checksum to avoid re-running UDF tests if UDF-related code has not changed |
Signed-off-by: feldera-bot <feldera-bot@feldera.com>
|
@Karakatiza666 Is this ready for review? |
|
I need more feedback on this. I believe @gz had a consideration that the debug symbols would get included into compiled dependencies of a production pipeline? |
mythical-fred
left a comment
There was a problem hiding this comment.
Interesting RFC! The idea of running UDF unit tests after compilation is valuable. A few architectural issues to address before this is ready.
| /// Calculates a checksum only for UDF-related content (udf_rust and udf_toml). | ||
| /// This is used to determine if tests need to be re-run. | ||
| fn calculate_udf_checksum(udf_rust: &str, udf_toml: &str) -> String { | ||
| let mut hasher = sha::Sha256::new(); |
There was a problem hiding this comment.
The UDF checksum only covers udf_rust + udf_toml, but UDF code is compiled against the SQL-generated types. If the SQL program changes (changing generated Rust interfaces), the UDF's behavior against the new types could differ — but tests won't re-run because the UDF checksum is unchanged. Either include a hash of the SQL-generated code here, or tie the test-skip logic to the overall source_checksum (which already covers everything).
| if exit_status.success() { | ||
| // Retrieve previous UDF checksum to determine if tests need to be re-run | ||
| let previous_udf_checksum = if let Some(db) = db.clone() { | ||
| match db |
There was a problem hiding this comment.
The compiler fetching pipeline state from the DB is an awkward inversion of responsibility. call_compiler is a low-level function; it shouldn't be querying pipeline status. The checksum comparison (previous_udf_checksum == current_udf_checksum) belongs at the call site in attempt_end_to_end_rust_compilation, where the previous checksum can be passed in as a parameter. This would also remove the db parameter from call_compiler entirely.
| let mut process = command.spawn().map_err(|e| { | ||
| RustCompilationError::SystemError( | ||
| UtilError::IoError("running 'cargo test'".to_string(), e).to_string(), | ||
| ) |
There was a problem hiding this comment.
The ? here propagates RustCompilationError::SystemError (e.g., cargo binary not found, I/O error) all the way up and would block pipeline startup — contradicting the PR description that says test failures don't prevent starting the pipeline. System errors during test execution should probably be treated as "tests unavailable" rather than a hard failure. Consider catching errors here and returning a RustCompilationInfo with a non-zero exit code and the error message in stderr.
Compilation error in the test module, or the test failures do not prevent starting the pipeline.
You can use the following pipeline to test the feature:
program.sql
udf.rs
udf.toml
Ad-hoc insert statement: