2023-09-17 21:57:43 -07:00
|
|
|
use anyhow::Result;
|
|
|
|
use kcl_lib::{
|
2024-11-20 15:19:25 +13:00
|
|
|
exec::{KclValue, PlaneType},
|
|
|
|
modify_ast_for_sketch, ExecState, ExecutorContext, ModuleId, Program, SourceRange,
|
2023-09-17 21:57:43 -07:00
|
|
|
};
|
2024-09-19 14:06:29 -07:00
|
|
|
use kittycad_modeling_cmds::{each_cmd as mcmd, length_unit::LengthUnit, shared::Point3d, ModelingCmd};
|
2023-09-17 21:57:43 -07:00
|
|
|
use pretty_assertions::assert_eq;
|
|
|
|
|
|
|
|
/// Setup the engine and parse code for an ast.
|
2024-11-20 15:19:25 +13:00
|
|
|
async fn setup(code: &str, name: &str) -> Result<(ExecutorContext, Program, ModuleId, uuid::Uuid)> {
|
|
|
|
let program = Program::parse(code)?;
|
|
|
|
let ctx = kcl_lib::ExecutorContext::new_with_default_client(Default::default()).await?;
|
|
|
|
let mut exec_state = ExecState::default();
|
|
|
|
ctx.run(&program, &mut exec_state).await?;
|
2023-09-17 21:57:43 -07:00
|
|
|
|
|
|
|
// We need to get the sketch ID.
|
2024-09-27 15:44:44 -07:00
|
|
|
// Get the sketch ID from memory.
|
2024-11-14 17:27:19 -06:00
|
|
|
let KclValue::Sketch { value: sketch } = exec_state.memory.get(name, SourceRange::default()).unwrap() else {
|
2024-09-16 15:10:33 -04:00
|
|
|
anyhow::bail!("part001 not found in memory: {:?}", exec_state.memory);
|
2023-09-17 21:57:43 -07:00
|
|
|
};
|
2024-09-27 15:44:44 -07:00
|
|
|
let sketch_id = sketch.id;
|
2023-09-17 21:57:43 -07:00
|
|
|
|
|
|
|
let plane_id = uuid::Uuid::new_v4();
|
2023-10-05 14:27:48 -07:00
|
|
|
ctx.engine
|
2023-09-20 18:27:08 -07:00
|
|
|
.send_modeling_cmd(
|
|
|
|
plane_id,
|
|
|
|
SourceRange::default(),
|
2024-09-18 17:04:04 -05:00
|
|
|
ModelingCmd::from(mcmd::MakePlane {
|
2023-09-20 18:27:08 -07:00
|
|
|
clobber: false,
|
2024-09-18 17:04:04 -05:00
|
|
|
origin: Point3d::default(),
|
|
|
|
size: LengthUnit(60.0),
|
|
|
|
x_axis: Point3d { x: 1.0, y: 0.0, z: 0.0 },
|
|
|
|
y_axis: Point3d { x: 0.0, y: 1.0, z: 0.0 },
|
2023-10-05 19:54:31 -07:00
|
|
|
hide: Some(true),
|
2024-09-18 17:04:04 -05:00
|
|
|
}),
|
2023-09-20 18:27:08 -07:00
|
|
|
)
|
|
|
|
.await?;
|
2023-09-17 21:57:43 -07:00
|
|
|
|
|
|
|
// Enter sketch mode.
|
|
|
|
// We can't get control points without being in sketch mode.
|
|
|
|
// You can however get path info without sketch mode.
|
2023-10-05 14:27:48 -07:00
|
|
|
ctx.engine
|
2023-09-20 18:27:08 -07:00
|
|
|
.send_modeling_cmd(
|
|
|
|
uuid::Uuid::new_v4(),
|
|
|
|
SourceRange::default(),
|
2024-09-18 17:04:04 -05:00
|
|
|
ModelingCmd::from(mcmd::EnableSketchMode {
|
2023-09-20 18:27:08 -07:00
|
|
|
animated: false,
|
|
|
|
ortho: true,
|
2024-05-03 14:45:39 -07:00
|
|
|
entity_id: plane_id,
|
2024-09-18 17:04:04 -05:00
|
|
|
planar_normal: Some(Point3d { x: 0.0, y: 0.0, z: 1.0 }),
|
2024-05-03 14:45:39 -07:00
|
|
|
adjust_camera: false,
|
2024-09-18 17:04:04 -05:00
|
|
|
}),
|
2023-09-20 18:27:08 -07:00
|
|
|
)
|
|
|
|
.await?;
|
2023-09-17 21:57:43 -07:00
|
|
|
|
2024-11-20 15:19:25 +13:00
|
|
|
Ok((ctx, program, ModuleId::default(), sketch_id))
|
2023-09-17 21:57:43 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
2024-08-12 13:06:30 -07:00
|
|
|
async fn kcl_test_modify_sketch_part001() {
|
2023-09-17 21:57:43 -07:00
|
|
|
let name = "part001";
|
|
|
|
let code = format!(
|
2024-10-02 14:19:40 -05:00
|
|
|
r#"{} = startSketchOn("XY")
|
2023-10-05 14:27:48 -07:00
|
|
|
|> startProfileAt([8.41, 5.78], %)
|
2023-09-17 21:57:43 -07:00
|
|
|
|> line([7.37, -11.0], %)
|
|
|
|
|> line([-8.69, -3.75], %)
|
|
|
|
|> line([-5.0, 4.25], %)
|
|
|
|
"#,
|
|
|
|
name
|
|
|
|
);
|
|
|
|
|
2024-11-07 11:23:41 -05:00
|
|
|
let (ctx, program, module_id, sketch_id) = setup(&code, name).await.unwrap();
|
2023-09-17 21:57:43 -07:00
|
|
|
let mut new_program = program.clone();
|
2024-11-07 11:23:41 -05:00
|
|
|
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, module_id, name, PlaneType::XY, sketch_id)
|
2023-09-17 21:57:43 -07:00
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
// Make sure the code is the same.
|
|
|
|
assert_eq!(code, new_code);
|
|
|
|
// Make sure the program is the same.
|
|
|
|
assert_eq!(new_program, program);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
2024-08-12 13:06:30 -07:00
|
|
|
async fn kcl_test_modify_sketch_part002() {
|
2023-09-17 21:57:43 -07:00
|
|
|
let name = "part002";
|
|
|
|
let code = format!(
|
2024-10-02 14:19:40 -05:00
|
|
|
r#"{} = startSketchOn("XY")
|
2023-10-05 14:27:48 -07:00
|
|
|
|> startProfileAt([8.41, 5.78], %)
|
2023-09-17 21:57:43 -07:00
|
|
|
|> line([7.42, -8.62], %)
|
|
|
|
|> line([-6.38, -3.51], %)
|
|
|
|
|> line([-3.77, 3.56], %)
|
|
|
|
"#,
|
|
|
|
name
|
|
|
|
);
|
|
|
|
|
2024-11-07 11:23:41 -05:00
|
|
|
let (ctx, program, module_id, sketch_id) = setup(&code, name).await.unwrap();
|
2023-09-17 21:57:43 -07:00
|
|
|
let mut new_program = program.clone();
|
2024-11-07 11:23:41 -05:00
|
|
|
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, module_id, name, PlaneType::XY, sketch_id)
|
2023-09-17 21:57:43 -07:00
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
// Make sure the code is the same.
|
|
|
|
assert_eq!(code, new_code);
|
|
|
|
// Make sure the program is the same.
|
|
|
|
assert_eq!(new_program, program);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
|
|
#[ignore] // until KittyCAD/engine#1434 is fixed.
|
2024-08-12 13:06:30 -07:00
|
|
|
async fn kcl_test_modify_close_sketch() {
|
2023-09-17 21:57:43 -07:00
|
|
|
let name = "part002";
|
|
|
|
let code = format!(
|
2024-10-02 14:19:40 -05:00
|
|
|
r#"{} = startSketchOn("XY")
|
2023-10-05 14:27:48 -07:00
|
|
|
|> startProfileAt([7.91, 3.89], %)
|
2023-09-17 21:57:43 -07:00
|
|
|
|> line([7.42, -8.62], %)
|
|
|
|
|> line([-6.38, -3.51], %)
|
|
|
|
|> line([-3.77, 3.56], %)
|
|
|
|
|> close(%)
|
|
|
|
"#,
|
|
|
|
name
|
|
|
|
);
|
|
|
|
|
2024-11-07 11:23:41 -05:00
|
|
|
let (ctx, program, module_id, sketch_id) = setup(&code, name).await.unwrap();
|
2023-09-17 21:57:43 -07:00
|
|
|
let mut new_program = program.clone();
|
2024-11-07 11:23:41 -05:00
|
|
|
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, module_id, name, PlaneType::XY, sketch_id)
|
2023-09-17 21:57:43 -07:00
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
// Make sure the code is the same.
|
|
|
|
assert_eq!(code, new_code);
|
|
|
|
// Make sure the program is the same.
|
|
|
|
assert_eq!(new_program, program);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
2024-08-12 13:06:30 -07:00
|
|
|
async fn kcl_test_modify_line_to_close_sketch() {
|
2023-09-17 21:57:43 -07:00
|
|
|
let name = "part002";
|
|
|
|
let code = format!(
|
2023-10-05 14:27:48 -07:00
|
|
|
r#"const {} = startSketchOn("XY")
|
|
|
|
|> startProfileAt([7.91, 3.89], %)
|
2023-09-17 21:57:43 -07:00
|
|
|
|> line([7.42, -8.62], %)
|
|
|
|
|> line([-6.38, -3.51], %)
|
|
|
|
|> line([-3.77, 3.56], %)
|
|
|
|
|> lineTo([7.91, 3.89], %)
|
|
|
|
"#,
|
|
|
|
name
|
|
|
|
);
|
|
|
|
|
2024-11-07 11:23:41 -05:00
|
|
|
let (ctx, program, module_id, sketch_id) = setup(&code, name).await.unwrap();
|
2023-09-17 21:57:43 -07:00
|
|
|
let mut new_program = program.clone();
|
2024-11-07 11:23:41 -05:00
|
|
|
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, module_id, name, PlaneType::XY, sketch_id)
|
2023-09-17 21:57:43 -07:00
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
// Make sure the code is the same.
|
|
|
|
assert_eq!(
|
|
|
|
new_code,
|
|
|
|
format!(
|
2024-10-02 14:19:40 -05:00
|
|
|
r#"{} = startSketchOn("XY")
|
2023-10-05 14:27:48 -07:00
|
|
|
|> startProfileAt([7.91, 3.89], %)
|
2023-09-17 21:57:43 -07:00
|
|
|
|> line([7.42, -8.62], %)
|
|
|
|
|> line([-6.38, -3.51], %)
|
|
|
|
|> line([-3.77, 3.56], %)
|
|
|
|
|> close(%)
|
|
|
|
"#,
|
|
|
|
name
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
2024-08-12 13:06:30 -07:00
|
|
|
async fn kcl_test_modify_with_constraint() {
|
2023-09-17 21:57:43 -07:00
|
|
|
let name = "part002";
|
|
|
|
let code = format!(
|
|
|
|
r#"const thing = 12
|
2023-10-05 14:27:48 -07:00
|
|
|
const {} = startSketchOn("XY")
|
|
|
|
|> startProfileAt([7.91, 3.89], %)
|
2023-09-17 21:57:43 -07:00
|
|
|
|> line([7.42, -8.62], %)
|
|
|
|
|> line([-6.38, -3.51], %)
|
|
|
|
|> line([-3.77, 3.56], %)
|
|
|
|
|> lineTo([thing, 3.89], %)
|
|
|
|
"#,
|
|
|
|
name
|
|
|
|
);
|
|
|
|
|
2024-11-07 11:23:41 -05:00
|
|
|
let (ctx, program, module_id, sketch_id) = setup(&code, name).await.unwrap();
|
2023-09-17 21:57:43 -07:00
|
|
|
let mut new_program = program.clone();
|
2024-11-07 11:23:41 -05:00
|
|
|
let result = modify_ast_for_sketch(&ctx.engine, &mut new_program, module_id, name, PlaneType::XY, sketch_id).await;
|
2023-09-17 21:57:43 -07:00
|
|
|
|
|
|
|
assert!(result.is_err());
|
|
|
|
assert_eq!(
|
|
|
|
result.unwrap_err().to_string(),
|
2024-11-07 11:23:41 -05:00
|
|
|
r#"engine: KclErrorDetails { source_ranges: [SourceRange([188, 193, 0])], message: "Sketch part002 is constrained `partial` and cannot be modified" }"#
|
2023-09-17 21:57:43 -07:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
2024-08-12 13:06:30 -07:00
|
|
|
async fn kcl_test_modify_line_should_close_sketch() {
|
2023-09-17 21:57:43 -07:00
|
|
|
let name = "part003";
|
|
|
|
let code = format!(
|
2023-10-05 14:27:48 -07:00
|
|
|
r#"const {} = startSketchOn("XY")
|
|
|
|
|> startProfileAt([13.69, 3.8], %)
|
2023-09-17 21:57:43 -07:00
|
|
|
|> line([4.23, -11.79], %)
|
|
|
|
|> line([-10.7, -1.16], %)
|
|
|
|
|> line([-3.72, 8.69], %)
|
|
|
|
|> line([10.19, 4.26], %)
|
|
|
|
"#,
|
|
|
|
name
|
|
|
|
);
|
|
|
|
|
2024-11-07 11:23:41 -05:00
|
|
|
let (ctx, program, module_id, sketch_id) = setup(&code, name).await.unwrap();
|
2023-09-17 21:57:43 -07:00
|
|
|
let mut new_program = program.clone();
|
2024-11-07 11:23:41 -05:00
|
|
|
let new_code = modify_ast_for_sketch(&ctx.engine, &mut new_program, module_id, name, PlaneType::XY, sketch_id)
|
2023-09-17 21:57:43 -07:00
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
// Make sure the code is the same.
|
|
|
|
assert_eq!(
|
|
|
|
new_code,
|
|
|
|
format!(
|
2024-10-02 14:19:40 -05:00
|
|
|
r#"{} = startSketchOn("XY")
|
2023-10-05 14:27:48 -07:00
|
|
|
|> startProfileAt([13.69, 3.8], %)
|
2023-09-17 21:57:43 -07:00
|
|
|
|> line([4.23, -11.79], %)
|
|
|
|
|> line([-10.7, -1.16], %)
|
|
|
|
|> line([-3.72, 8.69], %)
|
|
|
|
|> close(%)
|
|
|
|
"#,
|
|
|
|
name
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|