Add lsystem.kcl to tests (#4146)
* Add lsystem.kcl to tests * Reduce iterations * Fix the user settings flake shit (NOTE TO ALL FUTURE PEOPLE MODELING-APP DOES NOT WAIT FOR I/O IN SOME CASES BEFORE ROUTER NAVIGATION)
This commit is contained in:
@ -1497,6 +1497,7 @@ test(
|
|||||||
'i_shape.kcl',
|
'i_shape.kcl',
|
||||||
'kittycad_svg.kcl',
|
'kittycad_svg.kcl',
|
||||||
'lego.kcl',
|
'lego.kcl',
|
||||||
|
'lsystem.kcl',
|
||||||
'math.kcl',
|
'math.kcl',
|
||||||
'member_expression_sketch.kcl',
|
'member_expression_sketch.kcl',
|
||||||
'mike_stress_test.kcl',
|
'mike_stress_test.kcl',
|
||||||
|
@ -286,11 +286,12 @@ test.describe('Testing settings', () => {
|
|||||||
await page.setViewportSize({ width: 1200, height: 500 })
|
await page.setViewportSize({ width: 1200, height: 500 })
|
||||||
|
|
||||||
// Selectors and constants
|
// Selectors and constants
|
||||||
const tempSettingsFilePath = join(
|
const tempProjectSettingsFilePath = join(
|
||||||
projectDirName,
|
projectDirName,
|
||||||
projectName,
|
projectName,
|
||||||
PROJECT_SETTINGS_FILE_NAME
|
PROJECT_SETTINGS_FILE_NAME
|
||||||
)
|
)
|
||||||
|
const tempUserSettingsFilePath = join(projectDirName, SETTINGS_FILE_NAME)
|
||||||
const userThemeColor = '120'
|
const userThemeColor = '120'
|
||||||
const projectThemeColor = '50'
|
const projectThemeColor = '50'
|
||||||
const settingsOpenButton = page.getByRole('link', {
|
const settingsOpenButton = page.getByRole('link', {
|
||||||
@ -311,6 +312,12 @@ test.describe('Testing settings', () => {
|
|||||||
await themeColorSetting.fill(userThemeColor)
|
await themeColorSetting.fill(userThemeColor)
|
||||||
await expect(logoLink).toHaveCSS('--primary-hue', userThemeColor)
|
await expect(logoLink).toHaveCSS('--primary-hue', userThemeColor)
|
||||||
await settingsCloseButton.click()
|
await settingsCloseButton.click()
|
||||||
|
await expect
|
||||||
|
.poll(async () => fsp.readFile(tempUserSettingsFilePath, 'utf-8'), {
|
||||||
|
message: 'Setting should now be written to the file',
|
||||||
|
timeout: 5_000,
|
||||||
|
})
|
||||||
|
.toContain(`themeColor = "${userThemeColor}"`)
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Set project theme color', async () => {
|
await test.step('Set project theme color', async () => {
|
||||||
@ -324,10 +331,13 @@ test.describe('Testing settings', () => {
|
|||||||
await settingsCloseButton.click()
|
await settingsCloseButton.click()
|
||||||
// Make sure that the project settings file has been written to before continuing
|
// Make sure that the project settings file has been written to before continuing
|
||||||
await expect
|
await expect
|
||||||
.poll(async () => fsp.readFile(tempSettingsFilePath, 'utf-8'), {
|
.poll(
|
||||||
message: 'Setting should now be written to the file',
|
async () => fsp.readFile(tempProjectSettingsFilePath, 'utf-8'),
|
||||||
timeout: 5_000,
|
{
|
||||||
})
|
message: 'Setting should now be written to the file',
|
||||||
|
timeout: 5_000,
|
||||||
|
}
|
||||||
|
)
|
||||||
.toContain(`themeColor = "${projectThemeColor}"`)
|
.toContain(`themeColor = "${projectThemeColor}"`)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -341,6 +351,7 @@ test.describe('Testing settings', () => {
|
|||||||
|
|
||||||
await test.step(`Navigate back to the home view and see user setting applied`, async () => {
|
await test.step(`Navigate back to the home view and see user setting applied`, async () => {
|
||||||
await logoLink.click()
|
await logoLink.click()
|
||||||
|
await page.screenshot({ path: 'out.png' })
|
||||||
await expect(logoLink).toHaveCSS('--primary-hue', userThemeColor)
|
await expect(logoLink).toHaveCSS('--primary-hue', userThemeColor)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ pub fn bench_parse(c: &mut Criterion) {
|
|||||||
("cube", CUBE_PROGRAM),
|
("cube", CUBE_PROGRAM),
|
||||||
("math", MATH_PROGRAM),
|
("math", MATH_PROGRAM),
|
||||||
("mike_stress_test", MIKE_STRESS_TEST_PROGRAM),
|
("mike_stress_test", MIKE_STRESS_TEST_PROGRAM),
|
||||||
|
("koch snowflake", LSYSTEM_KOCH_SNOWFLAKE_PROGRAM),
|
||||||
] {
|
] {
|
||||||
let tokens = kcl_lib::token::lexer(file).unwrap();
|
let tokens = kcl_lib::token::lexer(file).unwrap();
|
||||||
c.bench_function(&format!("parse_{name}"), move |b| {
|
c.bench_function(&format!("parse_{name}"), move |b| {
|
||||||
@ -37,3 +38,4 @@ const PIPES_PROGRAM: &str = include_str!("../../tests/executor/inputs/pipes_on_p
|
|||||||
const CUBE_PROGRAM: &str = include_str!("../../tests/executor/inputs/cube.kcl");
|
const CUBE_PROGRAM: &str = include_str!("../../tests/executor/inputs/cube.kcl");
|
||||||
const MATH_PROGRAM: &str = include_str!("../../tests/executor/inputs/math.kcl");
|
const MATH_PROGRAM: &str = include_str!("../../tests/executor/inputs/math.kcl");
|
||||||
const MIKE_STRESS_TEST_PROGRAM: &str = include_str!("../../tests/executor/inputs/mike_stress_test.kcl");
|
const MIKE_STRESS_TEST_PROGRAM: &str = include_str!("../../tests/executor/inputs/mike_stress_test.kcl");
|
||||||
|
const LSYSTEM_KOCH_SNOWFLAKE_PROGRAM: &str = include_str!("../../tests/executor/inputs/lsystem.kcl");
|
||||||
|
@ -19,6 +19,9 @@ fn lex_cube() {
|
|||||||
fn lex_math() {
|
fn lex_math() {
|
||||||
black_box(kcl_lib::token::lexer(MATH_PROGRAM).unwrap());
|
black_box(kcl_lib::token::lexer(MATH_PROGRAM).unwrap());
|
||||||
}
|
}
|
||||||
|
fn lex_lsystem() {
|
||||||
|
black_box(kcl_lib::token::lexer(LSYSTEM_PROGRAM).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_kitt() {
|
fn parse_kitt() {
|
||||||
parse(KITT_PROGRAM)
|
parse(KITT_PROGRAM)
|
||||||
@ -32,19 +35,25 @@ fn parse_cube() {
|
|||||||
fn parse_math() {
|
fn parse_math() {
|
||||||
parse(MATH_PROGRAM)
|
parse(MATH_PROGRAM)
|
||||||
}
|
}
|
||||||
|
fn parse_lsystem() {
|
||||||
|
parse(LSYSTEM_PROGRAM)
|
||||||
|
}
|
||||||
|
|
||||||
iai::main! {
|
iai::main! {
|
||||||
lex_kitt,
|
lex_kitt,
|
||||||
lex_pipes,
|
lex_pipes,
|
||||||
lex_cube,
|
lex_cube,
|
||||||
lex_math,
|
lex_math,
|
||||||
|
lex_lsystem,
|
||||||
parse_kitt,
|
parse_kitt,
|
||||||
parse_pipes,
|
parse_pipes,
|
||||||
parse_cube,
|
parse_cube,
|
||||||
parse_math,
|
parse_math,
|
||||||
|
parse_lsystem,
|
||||||
}
|
}
|
||||||
|
|
||||||
const KITT_PROGRAM: &str = include_str!("../../tests/executor/inputs/kittycad_svg.kcl");
|
const KITT_PROGRAM: &str = include_str!("../../tests/executor/inputs/kittycad_svg.kcl");
|
||||||
const PIPES_PROGRAM: &str = include_str!("../../tests/executor/inputs/pipes_on_pipes.kcl");
|
const PIPES_PROGRAM: &str = include_str!("../../tests/executor/inputs/pipes_on_pipes.kcl");
|
||||||
const CUBE_PROGRAM: &str = include_str!("../../tests/executor/inputs/cube.kcl");
|
const CUBE_PROGRAM: &str = include_str!("../../tests/executor/inputs/cube.kcl");
|
||||||
const MATH_PROGRAM: &str = include_str!("../../tests/executor/inputs/math.kcl");
|
const MATH_PROGRAM: &str = include_str!("../../tests/executor/inputs/math.kcl");
|
||||||
|
const LSYSTEM_PROGRAM: &str = include_str!("../../tests/executor/inputs/lsystem.kcl");
|
||||||
|
@ -7,6 +7,7 @@ pub fn bench_digest(c: &mut Criterion) {
|
|||||||
("cube", CUBE_PROGRAM),
|
("cube", CUBE_PROGRAM),
|
||||||
("math", MATH_PROGRAM),
|
("math", MATH_PROGRAM),
|
||||||
("mike_stress_test", MIKE_STRESS_TEST_PROGRAM),
|
("mike_stress_test", MIKE_STRESS_TEST_PROGRAM),
|
||||||
|
("lsystem", LSYSTEM_PROGRAM),
|
||||||
] {
|
] {
|
||||||
let tokens = kcl_lib::token::lexer(file).unwrap();
|
let tokens = kcl_lib::token::lexer(file).unwrap();
|
||||||
let prog = kcl_lib::parser::Parser::new(tokens).ast().unwrap();
|
let prog = kcl_lib::parser::Parser::new(tokens).ast().unwrap();
|
||||||
@ -29,3 +30,4 @@ const PIPES_PROGRAM: &str = include_str!("../../tests/executor/inputs/pipes_on_p
|
|||||||
const CUBE_PROGRAM: &str = include_str!("../../tests/executor/inputs/cube.kcl");
|
const CUBE_PROGRAM: &str = include_str!("../../tests/executor/inputs/cube.kcl");
|
||||||
const MATH_PROGRAM: &str = include_str!("../../tests/executor/inputs/math.kcl");
|
const MATH_PROGRAM: &str = include_str!("../../tests/executor/inputs/math.kcl");
|
||||||
const MIKE_STRESS_TEST_PROGRAM: &str = include_str!("../../tests/executor/inputs/mike_stress_test.kcl");
|
const MIKE_STRESS_TEST_PROGRAM: &str = include_str!("../../tests/executor/inputs/mike_stress_test.kcl");
|
||||||
|
const LSYSTEM_PROGRAM: &str = include_str!("../../tests/executor/inputs/lsystem.kcl");
|
||||||
|
@ -8,6 +8,7 @@ pub fn bench_execute(c: &mut Criterion) {
|
|||||||
("cube", CUBE_PROGRAM),
|
("cube", CUBE_PROGRAM),
|
||||||
("server_rack_lite", SERVER_RACK_LITE_PROGRAM),
|
("server_rack_lite", SERVER_RACK_LITE_PROGRAM),
|
||||||
("server_rack_heavy", SERVER_RACK_HEAVY_PROGRAM),
|
("server_rack_heavy", SERVER_RACK_HEAVY_PROGRAM),
|
||||||
|
("lsystem", LSYSTEM_PROGRAM),
|
||||||
] {
|
] {
|
||||||
let mut group = c.benchmark_group("executor");
|
let mut group = c.benchmark_group("executor");
|
||||||
// Configure Criterion.rs to detect smaller differences and increase sample size to improve
|
// Configure Criterion.rs to detect smaller differences and increase sample size to improve
|
||||||
@ -52,3 +53,4 @@ const CUBE_PROGRAM: &str = include_str!("../../tests/executor/inputs/cube.kcl");
|
|||||||
const SERVER_RACK_HEAVY_PROGRAM: &str = include_str!("../../tests/executor/inputs/server-rack-heavy.kcl");
|
const SERVER_RACK_HEAVY_PROGRAM: &str = include_str!("../../tests/executor/inputs/server-rack-heavy.kcl");
|
||||||
const SERVER_RACK_LITE_PROGRAM: &str = include_str!("../../tests/executor/inputs/server-rack-lite.kcl");
|
const SERVER_RACK_LITE_PROGRAM: &str = include_str!("../../tests/executor/inputs/server-rack-lite.kcl");
|
||||||
const LEGO_PROGRAM: &str = include_str!("../../tests/executor/inputs/slow_lego.kcl.tmpl");
|
const LEGO_PROGRAM: &str = include_str!("../../tests/executor/inputs/slow_lego.kcl.tmpl");
|
||||||
|
const LSYSTEM_PROGRAM: &str = include_str!("../../tests/executor/inputs/lsystem.kcl");
|
||||||
|
@ -42,6 +42,7 @@ fn bench_kcl_lsp_semantic_tokens(c: &mut Criterion) {
|
|||||||
("math", MATH_PROGRAM),
|
("math", MATH_PROGRAM),
|
||||||
("mike_stress_test", MIKE_STRESS_TEST_PROGRAM),
|
("mike_stress_test", MIKE_STRESS_TEST_PROGRAM),
|
||||||
("global_tags", GLOBAL_TAGS_FILE),
|
("global_tags", GLOBAL_TAGS_FILE),
|
||||||
|
("lsystem", LSYSTEM_PROGRAM),
|
||||||
] {
|
] {
|
||||||
c.bench_with_input(BenchmarkId::new("semantic_tokens_", name), &code, |b, &s| {
|
c.bench_with_input(BenchmarkId::new("semantic_tokens_", name), &code, |b, &s| {
|
||||||
let rt = Runtime::new().unwrap();
|
let rt = Runtime::new().unwrap();
|
||||||
@ -63,3 +64,4 @@ const CUBE_PROGRAM: &str = include_str!("../../tests/executor/inputs/cube.kcl");
|
|||||||
const MATH_PROGRAM: &str = include_str!("../../tests/executor/inputs/math.kcl");
|
const MATH_PROGRAM: &str = include_str!("../../tests/executor/inputs/math.kcl");
|
||||||
const MIKE_STRESS_TEST_PROGRAM: &str = include_str!("../../tests/executor/inputs/mike_stress_test.kcl");
|
const MIKE_STRESS_TEST_PROGRAM: &str = include_str!("../../tests/executor/inputs/mike_stress_test.kcl");
|
||||||
const GLOBAL_TAGS_FILE: &str = include_str!("../../tests/executor/inputs/global-tags.kcl");
|
const GLOBAL_TAGS_FILE: &str = include_str!("../../tests/executor/inputs/global-tags.kcl");
|
||||||
|
const LSYSTEM_PROGRAM: &str = include_str!("../../tests/executor/inputs/lsystem.kcl");
|
||||||
|
121
src/wasm-lib/tests/executor/inputs/lsystem.kcl
Normal file
121
src/wasm-lib/tests/executor/inputs/lsystem.kcl
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
// L-System KCL
|
||||||
|
// Zoo Corporation ⓒ 2024
|
||||||
|
|
||||||
|
// Comparators
|
||||||
|
|
||||||
|
fn cond = (bools) => {
|
||||||
|
return (a, b) => {
|
||||||
|
x = int(min(max(-1, a-b), 1) + 1)
|
||||||
|
return bools[x]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Not = (b) => { return if b { false } else { true } }
|
||||||
|
fn And = (a, b) => { return if a { if b { true } else { false } } else { false }}
|
||||||
|
fn Or = (a, b) => { return if a { true } else { if b { true } else { false }}}
|
||||||
|
|
||||||
|
Eq = cond([false, true, false])
|
||||||
|
Lt = cond([true, false, false])
|
||||||
|
Gt = cond([false, false, true])
|
||||||
|
|
||||||
|
fn Lte = (a, b) => { return Not(Gt(a, b)) }
|
||||||
|
fn Gte = (a, b) => { return Not(Lt(a, b)) }
|
||||||
|
|
||||||
|
// L-system
|
||||||
|
// Note: it was most concise to encode productions directly in axioms.
|
||||||
|
// Change them as you need.
|
||||||
|
|
||||||
|
deg = pi()*2 / 360
|
||||||
|
|
||||||
|
fn setSketch = (state, _) => {
|
||||||
|
return {
|
||||||
|
depthMax: state.depthMax,
|
||||||
|
depth: state.depth + 1,
|
||||||
|
currentLength: state.currentLength,
|
||||||
|
factor: state.factor,
|
||||||
|
currentAngle: state.currentAngle,
|
||||||
|
angle: state.angle,
|
||||||
|
_: _
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setDepth = (state, _) => {
|
||||||
|
return {
|
||||||
|
depthMax: state.depthMax,
|
||||||
|
depth: _,
|
||||||
|
currentLength: state.currentLength,
|
||||||
|
factor: state.factor,
|
||||||
|
currentAngle: state.currentAngle,
|
||||||
|
angle: state.angle,
|
||||||
|
_: state._
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setAngle = (state, _) => {
|
||||||
|
return {
|
||||||
|
depthMax: state.depthMax,
|
||||||
|
depth: state.depth,
|
||||||
|
currentLength: state.currentLength,
|
||||||
|
factor: state.factor,
|
||||||
|
currentAngle: _,
|
||||||
|
angle: state.angle,
|
||||||
|
_: state._
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setLength = (state, _) => {
|
||||||
|
return {
|
||||||
|
depthMax: state.depthMax,
|
||||||
|
depth: state.depth,
|
||||||
|
currentLength: _,
|
||||||
|
factor: state.factor,
|
||||||
|
currentAngle: state.currentAngle,
|
||||||
|
angle: state.angle,
|
||||||
|
_: state._
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn Gt2 = (state) => { return setLength(state, state.currentLength * state.factor) }
|
||||||
|
fn Lt2 = (state) => { return setLength(state, state.currentLength / state.factor) }
|
||||||
|
fn Add = (state) => { return setAngle(state, rem(int(state.currentAngle - state.angle), 360)) }
|
||||||
|
fn Sub = (state) => { return setAngle(state, rem(int(state.currentAngle + state.angle), 360)) }
|
||||||
|
|
||||||
|
// Only necessary to get around recursion limitations...
|
||||||
|
fn F = (state, F) => {
|
||||||
|
return if Lt(state.depth, state.depthMax) {
|
||||||
|
stateNext = state |> setDepth(%, state.depth + 1)
|
||||||
|
|
||||||
|
// Produce
|
||||||
|
// Note:if you need [ and ], just save state to a variable.
|
||||||
|
stateNext
|
||||||
|
|> F(%, F) |> Sub(%) |> F(%, F)
|
||||||
|
|> Add(%) |> Add(%)
|
||||||
|
|> F(%, F) |> Sub(%) |> F(%, F)
|
||||||
|
|> setDepth(%, stateNext.depth - 1)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Pass onto the next instruction
|
||||||
|
state |> setSketch(%, angledLine({ angle: state.currentAngle, length: state.currentLength }, state._))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn LSystem = (args, axioms) => {
|
||||||
|
return axioms({
|
||||||
|
depthMax: args.iterations,
|
||||||
|
depth: 0,
|
||||||
|
currentLength: 1.0,
|
||||||
|
factor: args.factor,
|
||||||
|
currentAngle: 0,
|
||||||
|
angle: args.angle,
|
||||||
|
_: startSketchAt([0, 0]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
LSystem({
|
||||||
|
iterations: 1,
|
||||||
|
factor: 1.36,
|
||||||
|
angle: 60,
|
||||||
|
}, (_) => {
|
||||||
|
result = _ |> F(%, F) |> Add(%) |> Add(%) |> F(%, F) |> Add(%) |> Add(%) |> F(%, F)
|
||||||
|
return result._
|
||||||
|
})
|
@ -121,6 +121,14 @@ async fn kcl_test_execute_kittycad_svg() {
|
|||||||
assert_out("kittycad_svg", &result);
|
assert_out("kittycad_svg", &result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
|
async fn kcl_test_execute_lsystem() {
|
||||||
|
let code = kcl_input!("lsystem");
|
||||||
|
|
||||||
|
let result = execute_and_snapshot(code, UnitLength::Mm).await.unwrap();
|
||||||
|
assert_out("lsystem", &result);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test(flavor = "multi_thread")]
|
||||||
async fn kcl_test_member_expression_sketch() {
|
async fn kcl_test_member_expression_sketch() {
|
||||||
let code = kcl_input!("member_expression_sketch");
|
let code = kcl_input!("member_expression_sketch");
|
||||||
|
Reference in New Issue
Block a user