2024-12-10 18:50:22 -08:00
|
|
|
//! Cache testing framework.
|
|
|
|
|
2025-02-05 17:53:49 +13:00
|
|
|
use kcl_lib::{bust_cache, ExecError, ExecOutcome};
|
2025-03-29 11:43:42 -07:00
|
|
|
use kcmc::{each_cmd as mcmd, ModelingCmd};
|
|
|
|
use kittycad_modeling_cmds as kcmc;
|
2025-05-12 07:07:18 -07:00
|
|
|
use pretty_assertions::assert_eq;
|
2024-12-10 18:50:22 -08:00
|
|
|
|
2025-01-10 22:33:05 -05:00
|
|
|
#[derive(Debug)]
|
2024-12-10 18:50:22 -08:00
|
|
|
struct Variation<'a> {
|
|
|
|
code: &'a str,
|
2025-04-16 11:52:14 -07:00
|
|
|
other_files: Vec<(std::path::PathBuf, std::string::String)>,
|
2024-12-10 18:50:22 -08:00
|
|
|
settings: &'a kcl_lib::ExecutorSettings,
|
|
|
|
}
|
|
|
|
|
2025-01-10 22:33:05 -05:00
|
|
|
async fn cache_test(
|
|
|
|
test_name: &str,
|
|
|
|
variations: Vec<Variation<'_>>,
|
2025-02-25 16:10:06 +13:00
|
|
|
) -> Vec<(String, image::DynamicImage, ExecOutcome)> {
|
2024-12-10 18:50:22 -08:00
|
|
|
let first = variations
|
|
|
|
.first()
|
2025-02-25 16:10:06 +13:00
|
|
|
.ok_or_else(|| anyhow::anyhow!("No variations provided for test '{}'", test_name))
|
|
|
|
.unwrap();
|
2024-12-10 18:50:22 -08:00
|
|
|
|
2025-02-25 16:10:06 +13:00
|
|
|
let mut ctx = kcl_lib::ExecutorContext::new_with_client(first.settings.clone(), None, None)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
2024-12-10 18:50:22 -08:00
|
|
|
|
2025-02-05 17:53:49 +13:00
|
|
|
bust_cache().await;
|
2024-12-10 18:50:22 -08:00
|
|
|
let mut img_results = Vec::new();
|
|
|
|
for (index, variation) in variations.iter().enumerate() {
|
2025-02-25 16:10:06 +13:00
|
|
|
let program = kcl_lib::Program::parse_no_errs(variation.code).unwrap();
|
2024-12-10 18:50:22 -08:00
|
|
|
|
|
|
|
// set the new settings.
|
|
|
|
ctx.settings = variation.settings.clone();
|
|
|
|
|
2025-04-16 11:52:14 -07:00
|
|
|
if !variation.other_files.is_empty() {
|
|
|
|
let tmp_dir = std::env::temp_dir();
|
|
|
|
let tmp_dir = tmp_dir
|
|
|
|
.join(format!("kcl_test_{}", test_name))
|
|
|
|
.join(uuid::Uuid::new_v4().to_string());
|
|
|
|
|
|
|
|
// Create a temporary file for each of the other files.
|
|
|
|
for (variant_path, variant_code) in &variation.other_files {
|
|
|
|
let tmp_file = tmp_dir.join(variant_path);
|
|
|
|
std::fs::create_dir_all(tmp_file.parent().unwrap()).unwrap();
|
|
|
|
std::fs::write(tmp_file, variant_code).unwrap();
|
|
|
|
}
|
|
|
|
|
2025-05-06 20:04:34 -07:00
|
|
|
ctx.settings.project_directory = Some(kcl_lib::TypedPath(tmp_dir.clone()));
|
2025-04-16 11:52:14 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
let outcome = match ctx.run_with_caching(program).await {
|
|
|
|
Ok(outcome) => outcome,
|
|
|
|
Err(error) => {
|
|
|
|
let report = error.clone().into_miette_report_with_outputs(variation.code).unwrap();
|
|
|
|
let report = miette::Report::new(report);
|
|
|
|
panic!("{:?}", report);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2025-02-25 16:10:06 +13:00
|
|
|
let snapshot_png_bytes = ctx.prepare_snapshot().await.unwrap().contents.0;
|
2024-12-10 18:50:22 -08:00
|
|
|
|
|
|
|
// Decode the snapshot, return it.
|
|
|
|
let img = image::ImageReader::new(std::io::Cursor::new(snapshot_png_bytes))
|
|
|
|
.with_guessed_format()
|
|
|
|
.map_err(|e| ExecError::BadPng(e.to_string()))
|
2025-02-25 16:10:06 +13:00
|
|
|
.and_then(|x| x.decode().map_err(|e| ExecError::BadPng(e.to_string())))
|
|
|
|
.unwrap();
|
2024-12-10 18:50:22 -08:00
|
|
|
// Save the snapshot.
|
|
|
|
let path = crate::assert_out(&format!("cache_{}_{}", test_name, index), &img);
|
|
|
|
|
2025-02-05 17:53:49 +13:00
|
|
|
img_results.push((path, img, outcome));
|
2024-12-10 18:50:22 -08:00
|
|
|
}
|
|
|
|
|
2025-01-10 20:05:27 -05:00
|
|
|
ctx.close().await;
|
|
|
|
|
2025-02-25 16:10:06 +13:00
|
|
|
img_results
|
2024-12-10 18:50:22 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
|
|
async fn kcl_test_cache_change_grid_visualizes_grid_off_to_on() {
|
2025-04-30 17:13:11 +12:00
|
|
|
let code = r#"part001 = startSketchOn(XY)
|
2025-04-25 16:01:35 -05:00
|
|
|
|> startProfile(at = [5.5229, 5.25217])
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
|> line(end = [10.50433, -1.19122])
|
|
|
|
|> line(end = [8.01362, -5.48731])
|
|
|
|
|> line(end = [-1.02877, -6.76825])
|
|
|
|
|> line(end = [-11.53311, 2.81559])
|
|
|
|
|> close()
|
|
|
|
|> extrude(length = 4)
|
2024-12-10 18:50:22 -08:00
|
|
|
"#;
|
|
|
|
|
|
|
|
let result = cache_test(
|
|
|
|
"change_grid_visualizes_grid_off_to_on",
|
|
|
|
vec![
|
|
|
|
Variation {
|
|
|
|
code,
|
2025-04-16 11:52:14 -07:00
|
|
|
other_files: vec![],
|
2024-12-10 18:50:22 -08:00
|
|
|
settings: &kcl_lib::ExecutorSettings {
|
|
|
|
show_grid: false,
|
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Variation {
|
|
|
|
code,
|
2025-04-16 11:52:14 -07:00
|
|
|
other_files: vec![],
|
2024-12-10 18:50:22 -08:00
|
|
|
settings: &kcl_lib::ExecutorSettings {
|
|
|
|
show_grid: true,
|
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
|
|
|
)
|
2025-02-25 16:10:06 +13:00
|
|
|
.await;
|
2024-12-10 18:50:22 -08:00
|
|
|
|
|
|
|
let first = result.first().unwrap();
|
|
|
|
let second = result.last().unwrap();
|
|
|
|
|
|
|
|
assert!(first.1 != second.1);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
|
|
async fn kcl_test_cache_change_grid_visualizes_grid_on_to_off() {
|
2025-04-30 13:12:40 +12:00
|
|
|
let code = r#"part001 = startSketchOn(XY)
|
2025-04-25 16:01:35 -05:00
|
|
|
|> startProfile(at = [5.5229, 5.25217])
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
|> line(end = [10.50433, -1.19122])
|
|
|
|
|> line(end = [8.01362, -5.48731])
|
|
|
|
|> line(end = [-1.02877, -6.76825])
|
|
|
|
|> line(end = [-11.53311, 2.81559])
|
|
|
|
|> close()
|
|
|
|
|> extrude(length = 4)
|
2024-12-10 18:50:22 -08:00
|
|
|
"#;
|
|
|
|
|
|
|
|
let result = cache_test(
|
|
|
|
"change_grid_visualizes_grid_on_to_off",
|
|
|
|
vec![
|
|
|
|
Variation {
|
|
|
|
code,
|
2025-04-16 11:52:14 -07:00
|
|
|
other_files: vec![],
|
2024-12-10 18:50:22 -08:00
|
|
|
settings: &kcl_lib::ExecutorSettings {
|
|
|
|
show_grid: true,
|
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Variation {
|
|
|
|
code,
|
2025-04-16 11:52:14 -07:00
|
|
|
other_files: vec![],
|
2024-12-10 18:50:22 -08:00
|
|
|
settings: &kcl_lib::ExecutorSettings {
|
|
|
|
show_grid: false,
|
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
|
|
|
)
|
2025-02-25 16:10:06 +13:00
|
|
|
.await;
|
2024-12-10 18:50:22 -08:00
|
|
|
|
|
|
|
let first = result.first().unwrap();
|
|
|
|
let second = result.last().unwrap();
|
|
|
|
|
|
|
|
assert!(first.1 != second.1);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
|
|
async fn kcl_test_cache_change_highlight_edges_changes_visual() {
|
2025-04-30 13:12:40 +12:00
|
|
|
let code = r#"part001 = startSketchOn(XY)
|
2025-04-25 16:01:35 -05:00
|
|
|
|> startProfile(at = [5.5229, 5.25217])
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
|> line(end = [10.50433, -1.19122])
|
|
|
|
|> line(end = [8.01362, -5.48731])
|
|
|
|
|> line(end = [-1.02877, -6.76825])
|
|
|
|
|> line(end = [-11.53311, 2.81559])
|
|
|
|
|> close()
|
|
|
|
|> extrude(length = 4)
|
2024-12-10 18:50:22 -08:00
|
|
|
"#;
|
|
|
|
|
|
|
|
let result = cache_test(
|
|
|
|
"change_highlight_edges_changes_visual",
|
|
|
|
vec![
|
|
|
|
Variation {
|
|
|
|
code,
|
2025-04-16 11:52:14 -07:00
|
|
|
other_files: vec![],
|
2024-12-10 18:50:22 -08:00
|
|
|
settings: &kcl_lib::ExecutorSettings {
|
|
|
|
highlight_edges: true,
|
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Variation {
|
|
|
|
code,
|
2025-04-16 11:52:14 -07:00
|
|
|
other_files: vec![],
|
2024-12-10 18:50:22 -08:00
|
|
|
settings: &kcl_lib::ExecutorSettings {
|
|
|
|
highlight_edges: false,
|
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
|
|
|
)
|
2025-02-25 16:10:06 +13:00
|
|
|
.await;
|
2024-12-10 18:50:22 -08:00
|
|
|
|
|
|
|
let first = result.first().unwrap();
|
|
|
|
let second = result.last().unwrap();
|
|
|
|
|
|
|
|
assert!(first.1 != second.1);
|
|
|
|
}
|
2025-01-10 22:33:05 -05:00
|
|
|
|
2025-04-16 11:52:14 -07:00
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
|
|
async fn kcl_test_cache_multi_file_same_code_dont_reexecute() {
|
|
|
|
let code = r#"import "toBeImported.kcl" as importedCube
|
|
|
|
|
|
|
|
importedCube
|
|
|
|
|
|
|
|
sketch001 = startSketchOn(XZ)
|
2025-04-25 16:01:35 -05:00
|
|
|
profile001 = startProfile(sketch001, at = [-134.53, -56.17])
|
2025-04-16 11:52:14 -07:00
|
|
|
|> angledLine(angle = 0, length = 79.05, tag = $rectangleSegmentA001)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 76.28)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $seg01)
|
|
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02)
|
|
|
|
|> close()
|
|
|
|
extrude001 = extrude(profile001, length = 100)
|
|
|
|
sketch003 = startSketchOn(extrude001, face = seg02)
|
|
|
|
sketch002 = startSketchOn(extrude001, face = seg01)
|
|
|
|
"#;
|
|
|
|
|
|
|
|
let other_file = (
|
|
|
|
std::path::PathBuf::from("toBeImported.kcl"),
|
|
|
|
r#"sketch001 = startSketchOn(XZ)
|
2025-04-25 16:01:35 -05:00
|
|
|
profile001 = startProfile(sketch001, at = [281.54, 305.81])
|
2025-04-16 11:52:14 -07:00
|
|
|
|> angledLine(angle = 0, length = 123.43, tag = $rectangleSegmentA001)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 85.99)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001))
|
|
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|
|
|> close()
|
|
|
|
extrude(profile001, length = 100)"#
|
|
|
|
.to_string(),
|
|
|
|
);
|
|
|
|
|
|
|
|
let result = cache_test(
|
|
|
|
"multi_file_same_code_dont_reexecute",
|
|
|
|
vec![
|
|
|
|
Variation {
|
|
|
|
code,
|
|
|
|
other_files: vec![other_file.clone()],
|
|
|
|
settings: &Default::default(),
|
|
|
|
},
|
|
|
|
Variation {
|
|
|
|
code,
|
|
|
|
other_files: vec![other_file],
|
|
|
|
settings: &Default::default(),
|
|
|
|
},
|
|
|
|
],
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
|
2025-05-12 07:07:18 -07:00
|
|
|
let first = result.first().unwrap();
|
|
|
|
let last = result.last().unwrap();
|
|
|
|
|
|
|
|
assert!(first.1 == last.1, "The images should be the same");
|
|
|
|
assert_eq!(first.2, last.2, "The outcomes should be the same");
|
2025-04-16 11:52:14 -07:00
|
|
|
}
|
|
|
|
|
2025-04-26 21:21:26 -07:00
|
|
|
#[cfg(feature = "artifact-graph")]
|
2025-01-10 22:33:05 -05:00
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
|
|
async fn kcl_test_cache_add_line_preserves_artifact_commands() {
|
2025-04-30 17:13:11 +12:00
|
|
|
let code = r#"sketch001 = startSketchOn(XY)
|
2025-04-25 16:01:35 -05:00
|
|
|
|> startProfile(at = [5.5229, 5.25217])
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
|> line(end = [10.50433, -1.19122])
|
|
|
|
|> line(end = [8.01362, -5.48731])
|
|
|
|
|> line(end = [-1.02877, -6.76825])
|
|
|
|
|> line(end = [-11.53311, 2.81559])
|
|
|
|
|> close()
|
2025-01-10 22:33:05 -05:00
|
|
|
"#;
|
|
|
|
// Use a new statement; don't extend the prior pipeline. This allows us to
|
|
|
|
// detect a prefix.
|
|
|
|
let code_with_extrude = code.to_owned()
|
|
|
|
+ r#"
|
KCL: Use keyword arguments for line, lineTo, extrude and close (#5249)
Part of #4600.
PR: https://github.com/KittyCAD/modeling-app/pull/4826
# Changes to KCL stdlib
- `line(point, sketch, tag)` and `lineTo(point, sketch, tag)` are combined into `line(@sketch, end?, endAbsolute?, tag?)`
- `close(sketch, tag?)` is now `close(@sketch, tag?)`
- `extrude(length, sketch)` is now `extrude(@sketch, length)`
Note that if a parameter starts with `@` like `@sketch`, it doesn't have any label when called, so you call it like this:
```
sketch = startSketchAt([0, 0])
line(sketch, end = [3, 3], tag = $hi)
```
Note also that if you're using a `|>` pipeline, you can omit the `@` argument and it will be assumed to be the LHS of the `|>`. So the above could be written as
```
sketch = startSketchAt([0, 0])
|> line(end = [3, 3], tag = $hi)
```
Also changes frontend tests to use KittyCAD/kcl-samples#139 instead of its main
The regex find-and-replace I use for migrating code (note these don't work with multi-line expressions) are:
```
line\(([^=]*), %\)
line(end = $1)
line\((.*), %, (.*)\)
line(end = $1, tag = $2)
lineTo\((.*), %\)
line(endAbsolute = $1)
lineTo\((.*), %, (.*)\)
line(endAbsolute = $1, tag = $2)
extrude\((.*), %\)
extrude(length = $1)
extrude\(([^=]*), ([a-zA-Z0-9]+)\)
extrude($2, length = $1)
close\(%, (.*)\)
close(tag = $1)
```
# Selected notes from commits before I squash them all
* Fix test 'yRelative to horizontal distance'
Fixes:
- Make a lineTo helper
- Fix pathToNode to go through the labeled arg .arg property
* Fix test by changing lookups into transformMap
Parts of the code assumed that `line` is always a relative call. But
actually now it might be absolute, if it's got an `endAbsolute` parameter.
So, change whether to look up `line` or `lineTo` and the relevant absolute
or relative line types based on that parameter.
* Stop asserting on exact source ranges
When I changed line to kwargs, all the source ranges we assert on became
slightly different. I find these assertions to be very very low value.
So I'm removing them.
* Fix more tests: getConstraintType calls weren't checking if the
'line' fn was absolute or relative.
* Fixed another queryAst test
There were 2 problems:
- Test was looking for the old style of `line` call to choose an offset
for pathToNode
- Test assumed that the `tag` param was always the third one, but in
a kwarg call, you have to look it up by label
* Fix test: traverse was not handling CallExpressionKw
* Fix another test, addTagKw
addTag helper was not aware of kw args.
* Convert close from positional to kwargs
If the close() call has 0 args, or a single unlabeled arg, the parser
interprets it as a CallExpression (positional) not a CallExpressionKw.
But then if a codemod wants to add a tag to it, it tries adding a kwarg
called 'tag', which fails because the CallExpression doesn't need
kwargs inserted into it.
The fix is: change the node from CallExpression to CallExpressionKw, and
update getNodeFromPath to take a 'replacement' arg, so we can replace
the old node with the new node in the AST.
* Fix the last test
Test was looking for `lineTo` as a substring of the input KCL program.
But there's no more lineTo function, so I changed it to look for
line() with an endAbsolute arg, which is the new equivalent.
Also changed the getConstraintInfo code to look up the lineTo if using
line with endAbsolute.
* Fix many bad regex find-replaces
I wrote a regex find-and-replace which converted `line` calls from
positional to keyword calls. But it was accidentally applied to more
places than it should be, for example, angledLine, xLine and yLine calls.
Fixes this.
* Fixes test 'Basic sketch › code pane closed at start'
Problem was, the getNodeFromPath call might not actually find a callExpressionKw,
it might find a callExpression. So the `giveSketchFnCallTag` thought
it was modifying a kwargs call, but it was actually modifying a positional
call.
This meant it tried to push a labeled argument in, rather than a normal
arg, and a lot of other problems. Fixed by doing runtime typechecking.
* Fix: Optional args given with wrong type were silently ignored
Optional args don't have to be given. But if the user gives them, they
should be the right type.
Bug: if the KCL interpreter found an optional arg, which was given, but
was the wrong type, it would ignore it and pretend the arg was never
given at all. This was confusing for users.
Fix: Now if you give an optional arg, but it's the wrong type, KCL will
emit a type error just like it would for a mandatory argument.
---------
Signed-off-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: Nick Cameron <nrc@ncameron.org>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Kevin Nadro <kevin@zoo.dev>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
2025-02-04 08:31:43 -06:00
|
|
|
extrude(sketch001, length = 4)
|
2025-01-10 22:33:05 -05:00
|
|
|
"#;
|
|
|
|
|
|
|
|
let result = cache_test(
|
|
|
|
"add_line_preserves_artifact_commands",
|
|
|
|
vec![
|
|
|
|
Variation {
|
|
|
|
code,
|
2025-04-16 11:52:14 -07:00
|
|
|
other_files: vec![],
|
2025-01-10 22:33:05 -05:00
|
|
|
settings: &Default::default(),
|
|
|
|
},
|
|
|
|
Variation {
|
|
|
|
code: code_with_extrude.as_str(),
|
2025-04-16 11:52:14 -07:00
|
|
|
other_files: vec![],
|
2025-01-10 22:33:05 -05:00
|
|
|
settings: &Default::default(),
|
|
|
|
},
|
|
|
|
],
|
|
|
|
)
|
2025-02-25 16:10:06 +13:00
|
|
|
.await;
|
2025-01-10 22:33:05 -05:00
|
|
|
|
2025-02-05 17:53:49 +13:00
|
|
|
let first = &result.first().unwrap().2;
|
|
|
|
let second = &result.last().unwrap().2;
|
2025-01-10 22:33:05 -05:00
|
|
|
|
|
|
|
assert!(
|
2025-02-05 17:53:49 +13:00
|
|
|
first.artifact_commands.len() < second.artifact_commands.len(),
|
2025-01-10 22:33:05 -05:00
|
|
|
"Second should have all the artifact commands of the first, plus more. first={:?}, second={:?}",
|
2025-02-05 17:53:49 +13:00
|
|
|
first.artifact_commands.len(),
|
|
|
|
second.artifact_commands.len()
|
2025-01-10 22:33:05 -05:00
|
|
|
);
|
2025-01-17 14:34:36 -05:00
|
|
|
assert!(
|
2025-02-05 17:53:49 +13:00
|
|
|
first.artifact_graph.len() < second.artifact_graph.len(),
|
|
|
|
"Second should have all the artifacts of the first, plus more. first={:?}, second={:?}",
|
|
|
|
first.artifact_graph.len(),
|
|
|
|
second.artifact_graph.len()
|
2025-01-17 14:34:36 -05:00
|
|
|
);
|
2025-01-10 22:33:05 -05:00
|
|
|
}
|
2025-03-29 11:43:42 -07:00
|
|
|
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
|
|
async fn kcl_test_cache_empty_file_pop_cache_empty_file_planes_work() {
|
|
|
|
// Get the current working directory.
|
|
|
|
let code = "";
|
|
|
|
|
2025-03-31 10:56:03 -04:00
|
|
|
let ctx = kcl_lib::ExecutorContext::new_with_default_client().await.unwrap();
|
2025-03-29 11:43:42 -07:00
|
|
|
let program = kcl_lib::Program::parse_no_errs(code).unwrap();
|
|
|
|
let outcome = ctx.run_with_caching(program).await.unwrap();
|
|
|
|
|
|
|
|
// Ensure nothing is left in the batch
|
|
|
|
assert!(ctx.engine.batch().read().await.is_empty());
|
|
|
|
assert!(ctx.engine.batch_end().read().await.is_empty());
|
|
|
|
|
|
|
|
// Ensure the planes work, and we can show or hide them.
|
|
|
|
// Hide/show the grid.
|
|
|
|
let default_planes = ctx.engine.get_default_planes().read().await.clone().unwrap();
|
|
|
|
|
|
|
|
// Assure the outcome is the same.
|
|
|
|
assert_eq!(outcome.default_planes, Some(default_planes.clone()));
|
|
|
|
|
|
|
|
ctx.engine
|
|
|
|
.send_modeling_cmd(
|
|
|
|
uuid::Uuid::new_v4(),
|
|
|
|
Default::default(),
|
|
|
|
&ModelingCmd::from(mcmd::ObjectVisible {
|
|
|
|
hidden: false,
|
|
|
|
object_id: default_planes.xy,
|
|
|
|
}),
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
// Now simulate an engine pause/network disconnect.
|
|
|
|
// Raw dog clear the scene entirely.
|
|
|
|
ctx.engine
|
|
|
|
.send_modeling_cmd(
|
|
|
|
uuid::Uuid::new_v4(),
|
|
|
|
Default::default(),
|
|
|
|
&ModelingCmd::from(mcmd::SceneClearAll {}),
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
// Bust the cache and reset the scene.
|
|
|
|
let outcome = ctx.bust_cache_and_reset_scene().await.unwrap();
|
|
|
|
// Get the default planes.
|
|
|
|
let default_planes = ctx.engine.get_default_planes().read().await.clone().unwrap();
|
|
|
|
|
|
|
|
assert_eq!(outcome.default_planes, Some(default_planes.clone()));
|
|
|
|
|
|
|
|
// Ensure we can show a plane.
|
|
|
|
ctx.engine
|
|
|
|
.send_modeling_cmd(
|
|
|
|
uuid::Uuid::new_v4(),
|
|
|
|
Default::default(),
|
|
|
|
&ModelingCmd::from(mcmd::ObjectVisible {
|
|
|
|
hidden: false,
|
|
|
|
object_id: default_planes.xz,
|
|
|
|
}),
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
ctx.close().await;
|
|
|
|
}
|
2025-04-16 11:52:14 -07:00
|
|
|
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
|
|
async fn kcl_test_cache_multi_file_after_empty_with_export() {
|
|
|
|
let code = r#"import importedCube from "toBeImported.kcl"
|
|
|
|
|
|
|
|
importedCube
|
|
|
|
|
|
|
|
sketch001 = startSketchOn(XZ)
|
2025-04-25 16:01:35 -05:00
|
|
|
profile001 = startProfile(sketch001, at = [-134.53, -56.17])
|
2025-04-16 11:52:14 -07:00
|
|
|
|> angledLine(angle = 0, length = 79.05, tag = $rectangleSegmentA001)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 76.28)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $seg01)
|
|
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02)
|
|
|
|
|> close()
|
|
|
|
extrude001 = extrude(profile001, length = 100)
|
|
|
|
sketch003 = startSketchOn(extrude001, face = seg02)
|
|
|
|
sketch002 = startSketchOn(extrude001, face = seg01)
|
|
|
|
"#;
|
|
|
|
|
|
|
|
let other_file = (
|
|
|
|
std::path::PathBuf::from("toBeImported.kcl"),
|
|
|
|
r#"sketch001 = startSketchOn(XZ)
|
2025-04-25 16:01:35 -05:00
|
|
|
profile001 = startProfile(sketch001, at = [281.54, 305.81])
|
2025-04-16 11:52:14 -07:00
|
|
|
|> angledLine(angle = 0, length = 123.43, tag = $rectangleSegmentA001)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 85.99)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001))
|
|
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|
|
|> close()
|
|
|
|
export importedCube = extrude(profile001, length = 100)
|
|
|
|
"#
|
|
|
|
.to_string(),
|
|
|
|
);
|
|
|
|
|
|
|
|
let result = cache_test(
|
|
|
|
"multi_file_after_empty",
|
|
|
|
vec![
|
|
|
|
Variation {
|
|
|
|
code: "",
|
|
|
|
other_files: vec![],
|
|
|
|
settings: &Default::default(),
|
|
|
|
},
|
|
|
|
Variation {
|
|
|
|
code,
|
|
|
|
other_files: vec![other_file],
|
|
|
|
settings: &Default::default(),
|
|
|
|
},
|
|
|
|
],
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
|
|
|
|
result.first().unwrap();
|
|
|
|
result.last().unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
|
|
async fn kcl_test_cache_multi_file_after_empty_with_woo() {
|
|
|
|
let code = r#"import "toBeImported.kcl" as importedCube
|
|
|
|
|
|
|
|
importedCube
|
|
|
|
|
|
|
|
sketch001 = startSketchOn(XZ)
|
2025-04-25 16:01:35 -05:00
|
|
|
profile001 = startProfile(sketch001, at = [-134.53, -56.17])
|
2025-04-16 11:52:14 -07:00
|
|
|
|> angledLine(angle = 0, length = 79.05, tag = $rectangleSegmentA001)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 76.28)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $seg01)
|
|
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02)
|
|
|
|
|> close()
|
|
|
|
extrude001 = extrude(profile001, length = 100)
|
|
|
|
sketch003 = startSketchOn(extrude001, face = seg02)
|
|
|
|
sketch002 = startSketchOn(extrude001, face = seg01)
|
|
|
|
"#;
|
|
|
|
|
|
|
|
let other_file = (
|
|
|
|
std::path::PathBuf::from("toBeImported.kcl"),
|
|
|
|
r#"sketch001 = startSketchOn(XZ)
|
2025-04-25 16:01:35 -05:00
|
|
|
profile001 = startProfile(sketch001, at = [281.54, 305.81])
|
2025-04-16 11:52:14 -07:00
|
|
|
|> angledLine(angle = 0, length = 123.43, tag = $rectangleSegmentA001)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 85.99)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001))
|
|
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|
|
|> close()
|
|
|
|
extrude(profile001, length = 100)
|
|
|
|
"#
|
|
|
|
.to_string(),
|
|
|
|
);
|
|
|
|
|
|
|
|
let result = cache_test(
|
|
|
|
"multi_file_after_empty",
|
|
|
|
vec![
|
|
|
|
Variation {
|
|
|
|
code: "",
|
|
|
|
other_files: vec![],
|
|
|
|
settings: &Default::default(),
|
|
|
|
},
|
|
|
|
Variation {
|
|
|
|
code,
|
|
|
|
other_files: vec![other_file],
|
|
|
|
settings: &Default::default(),
|
|
|
|
},
|
|
|
|
],
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
|
|
|
|
result.first().unwrap();
|
|
|
|
result.last().unwrap();
|
|
|
|
}
|
2025-05-02 10:41:14 -07:00
|
|
|
|
|
|
|
#[cfg(feature = "artifact-graph")]
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
|
|
async fn kcl_test_cache_multi_file_other_file_only_change() {
|
|
|
|
let code = r#"import "toBeImported.kcl" as importedCube
|
|
|
|
|
|
|
|
importedCube
|
|
|
|
|
|
|
|
sketch001 = startSketchOn(XZ)
|
|
|
|
profile001 = startProfile(sketch001, at = [-134.53, -56.17])
|
|
|
|
|> angledLine(angle = 0, length = 79.05, tag = $rectangleSegmentA001)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 76.28)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $seg01)
|
|
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02)
|
|
|
|
|> close()
|
|
|
|
extrude001 = extrude(profile001, length = 100)
|
|
|
|
sketch003 = startSketchOn(extrude001, face = seg02)
|
|
|
|
sketch002 = startSketchOn(extrude001, face = seg01)
|
|
|
|
"#;
|
|
|
|
|
|
|
|
let other_file = (
|
|
|
|
std::path::PathBuf::from("toBeImported.kcl"),
|
|
|
|
r#"sketch001 = startSketchOn(XZ)
|
|
|
|
profile001 = startProfile(sketch001, at = [281.54, 305.81])
|
|
|
|
|> angledLine(angle = 0, length = 123.43, tag = $rectangleSegmentA001)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 85.99)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001))
|
|
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|
|
|> close()
|
|
|
|
extrude(profile001, length = 100)
|
|
|
|
"#
|
|
|
|
.to_string(),
|
|
|
|
);
|
|
|
|
|
|
|
|
let other_file2 = (
|
|
|
|
std::path::PathBuf::from("toBeImported.kcl"),
|
|
|
|
r#"sketch001 = startSketchOn(XZ)
|
|
|
|
profile001 = startProfile(sketch001, at = [281.54, 305.81])
|
|
|
|
|> angledLine(angle = 0, length = 123.43, tag = $rectangleSegmentA001)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 85.99)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001))
|
|
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|
|
|> close()
|
|
|
|
extrude(profile001, length = 100)
|
|
|
|
|> translate(z = 100)
|
|
|
|
"#
|
|
|
|
.to_string(),
|
|
|
|
);
|
|
|
|
|
|
|
|
let result = cache_test(
|
|
|
|
"multi_file_other_file_only_change",
|
|
|
|
vec![
|
|
|
|
Variation {
|
|
|
|
code,
|
|
|
|
other_files: vec![other_file],
|
|
|
|
settings: &Default::default(),
|
|
|
|
},
|
|
|
|
Variation {
|
|
|
|
code,
|
|
|
|
other_files: vec![other_file2],
|
|
|
|
settings: &Default::default(),
|
|
|
|
},
|
|
|
|
],
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
|
|
|
|
let r1 = result.first().unwrap();
|
|
|
|
let r2 = result.last().unwrap();
|
|
|
|
|
|
|
|
assert!(r1.1 != r2.1, "The images should be different");
|
|
|
|
// Make sure the outcomes are different.
|
|
|
|
assert!(
|
|
|
|
r1.2.artifact_graph != r2.2.artifact_graph,
|
|
|
|
"The outcomes artifact graphs should be different"
|
|
|
|
);
|
|
|
|
}
|
2025-05-12 07:07:18 -07:00
|
|
|
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
|
|
async fn kcl_test_cache_multi_file_same_code_dont_reexecute_settings_only_change() {
|
|
|
|
let code = r#"import "toBeImported.kcl" as importedCube
|
|
|
|
|
|
|
|
importedCube
|
|
|
|
|
|
|
|
sketch001 = startSketchOn(XZ)
|
|
|
|
profile001 = startProfile(sketch001, at = [-134.53, -56.17])
|
|
|
|
|> angledLine(angle = 0, length = 79.05, tag = $rectangleSegmentA001)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 76.28)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $seg01)
|
|
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg02)
|
|
|
|
|> close()
|
|
|
|
extrude001 = extrude(profile001, length = 100)
|
|
|
|
sketch003 = startSketchOn(extrude001, face = seg02)
|
|
|
|
sketch002 = startSketchOn(extrude001, face = seg01)
|
|
|
|
"#;
|
|
|
|
|
|
|
|
let other_file = (
|
|
|
|
std::path::PathBuf::from("toBeImported.kcl"),
|
|
|
|
r#"sketch001 = startSketchOn(XZ)
|
|
|
|
profile001 = startProfile(sketch001, at = [281.54, 305.81])
|
|
|
|
|> angledLine(angle = 0, length = 123.43, tag = $rectangleSegmentA001)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 85.99)
|
|
|
|
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001))
|
|
|
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|
|
|
|> close()
|
|
|
|
extrude(profile001, length = 100)"#
|
|
|
|
.to_string(),
|
|
|
|
);
|
|
|
|
|
|
|
|
let result = cache_test(
|
|
|
|
"multi_file_same_code_dont_reexecute_settings_only_change",
|
|
|
|
vec![
|
|
|
|
Variation {
|
|
|
|
code,
|
|
|
|
other_files: vec![other_file.clone()],
|
|
|
|
settings: &kcl_lib::ExecutorSettings {
|
|
|
|
show_grid: false,
|
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Variation {
|
|
|
|
code,
|
|
|
|
other_files: vec![other_file],
|
|
|
|
settings: &kcl_lib::ExecutorSettings {
|
|
|
|
show_grid: true,
|
|
|
|
..Default::default()
|
|
|
|
},
|
|
|
|
},
|
|
|
|
],
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
|
|
|
|
let first = result.first().unwrap();
|
|
|
|
let last = result.last().unwrap();
|
|
|
|
|
|
|
|
assert!(first.1 != last.1, "The images should be different for the grid");
|
|
|
|
assert_eq!(first.2, last.2, "The outcomes should be the same");
|
|
|
|
}
|