Skip to content

Add unit tests for shape_utility pure functions#3958

Open
tarone-saloni wants to merge 1 commit intoGraphiteEditor:masterfrom
tarone-saloni:add-tests/shape-utility
Open

Add unit tests for shape_utility pure functions#3958
tarone-saloni wants to merge 1 commit intoGraphiteEditor:masterfrom
tarone-saloni:add-tests/shape-utility

Conversation

@tarone-saloni
Copy link
Copy Markdown

@tarone-saloni tarone-saloni commented Mar 27, 2026

What this does

Adds a #[cfg(test)] module to editor/src/messages/tool/common_functionality/shapes/shape_utility.rs, which previously had no test coverage. All tests are pure unit tests — no editor setup or async runtime needed.

Functions covered

wrap_to_tau(angle)

Normalises an angle in radians to [0, 2π). Tests verify:

  • Zero stays zero
  • Angle already in range passes through unchanged
  • Exactly TAU wraps to zero
  • Values beyond TAU reduce to the remainder
  • Negative angles wrap correctly

format_rounded(value, precision)

Formats a float and trims trailing zeros and the decimal point. Tests verify:

  • Trailing zeros and dot are stripped (1.000"1")
  • Partial trailing zeros are stripped (1.50"1.5")
  • Significant digits are preserved (1.23"1.23")
  • Rounding up works (3.14159 with precision 3 → "3.142")
  • Zero precision and zero value

calculate_display_angle(angle)

Converts an angle in degrees to a display-friendly value, normalising full turns. Tests cover all three branches (positive, negative, zero) and the wrap-at-±360° edge cases.

arc_end_points_ignore_layer(radius, start, sweep, viewport)

Calculates arc start/end points in local or viewport space. Tests cover:

  • Zero sweep (both points coincide)
  • Quarter-circle and half-circle sweeps (exact coordinate verification)
  • Radius scaling
  • Identity viewport produces identical results to None

star_vertex_position(viewport, index, n, r1, r2)

Computes a star vertex in viewport space. Tests verify:

  • Even index → outer radius (r1)
  • Odd index → inner radius (r2)
  • Correct angle formula for each vertex

polygon_vertex_position(viewport, index, n, radius)

Computes a regular polygon vertex. Tests verify vertex 0 (top), vertex 1 (right), vertex 2 (bottom) for a square.

inside_polygon(viewport, n, radius, point) and inside_star(viewport, n, r1, r2, point)

Winding-number hit-tests. Tests cover:

  • Centre is inside
  • Far-away point fails the bounding-box early-exit
  • Point just beyond the outermost vertex/tip is outside
  • Point near centre is inside

Closes GraphiteEditor#3954

Tests cover all branches of the following pure functions in shape_utility.rs:

- wrap_to_tau: zero, positive within range, exactly TAU, beyond TAU,
  negative values (wraps correctly into [0, 2π))
- format_rounded: trailing-zero trimming, dot trimming, rounding up,
  zero precision, zero value, all-significant digits retained
- calculate_display_angle: positive within range, positive wrapping past
  360°/720°, exactly 360°, negative small angle, negative beyond -360°,
  positive-zero input
- arc_end_points_ignore_layer: zero sweep, quarter sweep, half-circle
  sweep, radius scaling, identity viewport vs. no viewport
- star_vertex_position: even index (outer radius), odd index (inner radius),
  second outer vertex — verifying angle and radius selection math
- polygon_vertex_position: vertex 0 (up), vertex 1 of square (right),
  vertex 2 of square (down)
- inside_polygon: center inside, far point outside (bbox early exit),
  point beyond vertex outside, point near center inside
- inside_star: center inside, far point outside (bbox early exit), point
  beyond outer tip outside, point near center inside
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 1 file

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a comprehensive suite of unit tests for shape utility functions, covering angle wrapping, coordinate calculations for arcs, stars, and polygons, and hit-testing logic. The feedback identifies opportunities to improve test maintainability and readability by implementing a custom macro for floating-point approximations and utilizing idiomatic vector comparison methods from the glam library.


#[test]
fn wrap_pi_stays_pi() {
assert!((wrap_to_tau(PI) - PI).abs() < 1e-10);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There are many floating-point comparisons in these tests using the pattern (a - b).abs() < 1e-10. To improve readability and provide better failure messages, consider defining a local assert_approx_eq! macro at the top of the tests module.

macro_rules! assert_approx_eq {
    ($a:expr, $b:expr, $eps:expr) => {
        assert!(
            ($a - $b).abs() < $eps,
            "assertion failed: `(left - right).abs() < epsilon`\n  left: `{:?}`\n right: `{:?}`\nepsilon: `{:?}`",
            $a, $b, $eps
        );
    };
    ($a:expr, $b:expr) => {
        assert_approx_eq!($a, $b, 1e-10);
    };
}

This would allow you to write this assertion as assert_approx_eq!(wrap_to_tau(PI), PI); and can be used for all scalar float comparisons in this test module, making them more concise and readable.

Comment on lines +727 to +730
assert!((start.x - 1.).abs() < 1e-10, "start.x expected 1, got {}", start.x);
assert!(start.y.abs() < 1e-10, "start.y expected 0, got {}", start.y);
assert!((end.x - 1.).abs() < 1e-10, "end.x expected 1, got {}", end.x);
assert!(end.y.abs() < 1e-10, "end.y expected 0, got {}", end.y);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

These per-component assertions can be simplified by using glam::DVec2::abs_diff_eq for a more concise and idiomatic vector comparison.

For example, these four lines can be replaced with:

let expected = DVec2::new(1., 0.);
assert!(start.abs_diff_eq(expected, 1e-10), "start point mismatch");
assert!(end.abs_diff_eq(expected, 1e-10), "end point mismatch");

This approach can be applied to other vector comparisons in this file (e.g., in arc_endpoints_with_identity_viewport_matches_no_viewport, star_vertex_*, and polygon_vertex_* tests) to make them cleaner and more readable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant