Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dabb15b8e4 | |||
| 4b9e04ff75 | |||
| 80707a055d | |||
| 050b022ab1 | |||
| a8bc5d2038 | |||
| c224933459 | |||
| e769c61892 | |||
| e1cb61800d | |||
| 365a120eba | |||
| a7166af45b | |||
| 226b8b3786 | |||
| 1972c6dcf2 | |||
| a4c727de85 | |||
| 8ac53966e4 | |||
| a5f882a462 | |||
| 16eabc6d23 |
@@ -0,0 +1,23 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "docker"
|
||||||
|
directory: "/ci/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
labels:
|
||||||
|
- "dependencies"
|
||||||
|
- "docker"
|
||||||
|
- package-ecosystem: "cargo"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
labels:
|
||||||
|
- "dependencies"
|
||||||
|
- "rust"
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
labels:
|
||||||
|
- "dependencies"
|
||||||
|
- "github-actions"
|
||||||
@@ -1,11 +1,8 @@
|
|||||||
name: OCCT FFI Unit Tests
|
name: OCCT FFI Unit Tests
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
packages: write
|
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [master, dev-occt**, dev-ffi**]
|
branches: [master, dev**]
|
||||||
paths:
|
paths:
|
||||||
- "src/occt/**"
|
- "src/occt/**"
|
||||||
- "src/ffi/**"
|
- "src/ffi/**"
|
||||||
@@ -15,7 +12,7 @@ on:
|
|||||||
- "ci/scripts/occt.sh"
|
- "ci/scripts/occt.sh"
|
||||||
- "ci/ffi.Dockerfile"
|
- "ci/ffi.Dockerfile"
|
||||||
- "ci/scripts/ffi.sh"
|
- "ci/scripts/ffi.sh"
|
||||||
- ".github/**"
|
- ".github/workflows/occt-ffi-unit-test.yml"
|
||||||
- "./CMakeLists.txt"
|
- "./CMakeLists.txt"
|
||||||
- "Cargo.toml"
|
- "Cargo.toml"
|
||||||
- "Cargo.lock"
|
- "Cargo.lock"
|
||||||
@@ -31,7 +28,7 @@ on:
|
|||||||
- "ci/scripts/occt.sh"
|
- "ci/scripts/occt.sh"
|
||||||
- "ci/ffi.Dockerfile"
|
- "ci/ffi.Dockerfile"
|
||||||
- "ci/scripts/ffi.sh"
|
- "ci/scripts/ffi.sh"
|
||||||
- ".github/**"
|
- ".github/workflows/occt-ffi-unit-test.yml"
|
||||||
- "./CMakeLists.txt"
|
- "./CMakeLists.txt"
|
||||||
- "Cargo.toml"
|
- "Cargo.toml"
|
||||||
- "Cargo.lock"
|
- "Cargo.lock"
|
||||||
@@ -44,7 +41,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
@@ -76,7 +73,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time.
|
||||||
|
#
|
||||||
|
# You can adjust the behavior by modifying this file.
|
||||||
|
# For more information, see:
|
||||||
|
# https://github.com/actions/stale
|
||||||
|
name: Mark stale issues and pull requests
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '25 23 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v10
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
stale-issue-message: 'Stale issue message'
|
||||||
|
stale-pr-message: 'Stale pull request message'
|
||||||
|
stale-issue-label: 'no-issue-activity'
|
||||||
|
stale-pr-label: 'no-pr-activity'
|
||||||
+5
-47
@@ -86,66 +86,24 @@ mod ffi_point {
|
|||||||
|
|
||||||
pub use ffi_point::Point;
|
pub use ffi_point::Point;
|
||||||
|
|
||||||
// Basic tests
|
// FFI API tests
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use std::os::raw::c_double;
|
use std::os::raw::c_double;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn point_debug_precision() {
|
fn types_compatibility() {
|
||||||
let p = Point::new(1.123456789, 2.987654321, -3.555555555).expect("Failed to create point");
|
|
||||||
let debug_str = format!("{:?}", p);
|
|
||||||
|
|
||||||
let coords = p.coordinates();
|
|
||||||
assert!(debug_str.contains(&coords.0.to_string()));
|
|
||||||
assert!(debug_str.contains(&coords.1.to_string()));
|
|
||||||
assert!(debug_str.contains(&coords.2.to_string()));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn point_null_pointer_safety() {
|
|
||||||
let result = Point::new(1.0, 2.0, 3.0);
|
|
||||||
assert!(result.is_ok());
|
|
||||||
|
|
||||||
let p = result.unwrap();
|
|
||||||
let coords = p.coordinates();
|
|
||||||
|
|
||||||
assert_eq!(coords, (1.0, 2.0, 3.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn point_drop_impl_safety() {
|
|
||||||
{
|
|
||||||
let p = Point::new(1.0, 2.0, 3.0).expect("Failed to create point");
|
|
||||||
// p goes out of scope here and should be dropped
|
|
||||||
}
|
|
||||||
let p2 = Point::new(4.0, 5.0, 6.0).expect("Failed to create point after drop");
|
|
||||||
assert_eq!(p2.coordinates(), (4.0, 5.0, 6.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn point_ffi_repr_c() {
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
// PointShape should be repr(C) and zero-sized in Rust
|
|
||||||
assert_eq!(mem::size_of::<ffi_point::PointShape>(), 0);
|
assert_eq!(mem::size_of::<ffi_point::PointShape>(), 0);
|
||||||
|
|
||||||
// c_double should match f64
|
|
||||||
assert_eq!(mem::size_of::<c_double>(), mem::size_of::<f64>());
|
assert_eq!(mem::size_of::<c_double>(), mem::size_of::<f64>());
|
||||||
assert_eq!(mem::align_of::<c_double>(), mem::align_of::<f64>());
|
assert_eq!(mem::align_of::<c_double>(), mem::align_of::<f64>());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn point_coordinates_after_multiple_uses() {
|
fn basic_lifecycle() {
|
||||||
let p = Point::new(1.1, 2.2, 3.3).expect("Failed to create point");
|
let p = Point::new(1.0, 2.0, 3.0).expect("FFI creation failed");
|
||||||
|
assert_eq!(p.coordinates(), (1.0, 2.0, 3.0));
|
||||||
let _coords1 = p.coordinates();
|
|
||||||
let _debug1 = format!("{:?}", p);
|
|
||||||
let _coords2 = p.coordinates();
|
|
||||||
let _debug2 = format!("{:?}", p);
|
|
||||||
let final_coords = p.coordinates();
|
|
||||||
|
|
||||||
assert_eq!(final_coords, (1.1, 2.2, 3.3));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-116
@@ -4,11 +4,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <catch2/catch_test_macros.hpp>
|
#include <catch2/catch_test_macros.hpp>
|
||||||
#include <catch2/benchmark/catch_benchmark.hpp>
|
|
||||||
#include <catch2/catch_approx.hpp>
|
#include <catch2/catch_approx.hpp>
|
||||||
#include "point.hpp"
|
#include "point.hpp"
|
||||||
|
|
||||||
TEST_CASE("Test point creation, query and deletion behaviour", "[point]") {
|
TEST_CASE("Point lifecycle and coordinate operations", "[point]") {
|
||||||
auto check_coords = [](const point_shape_t* p, const double expected[3]) {
|
auto check_coords = [](const point_shape_t* p, const double expected[3]) {
|
||||||
double x, y, z;
|
double x, y, z;
|
||||||
coord_point(p, &x, &y, &z);
|
coord_point(p, &x, &y, &z);
|
||||||
@@ -17,65 +16,34 @@ TEST_CASE("Test point creation, query and deletion behaviour", "[point]") {
|
|||||||
REQUIRE(z == Catch::Approx(expected[2]));
|
REQUIRE(z == Catch::Approx(expected[2]));
|
||||||
};
|
};
|
||||||
|
|
||||||
SECTION("Accept integer coordinates") {
|
SECTION("Basic creation and coordinate retrieval") {
|
||||||
double coords[3] = {3, -7, 2};
|
|
||||||
point_shape_t* p = make_point(coords[0], coords[1], coords[2]);
|
|
||||||
check_coords(p, coords);
|
|
||||||
delete_point(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Accept float coordinates") {
|
|
||||||
double coords[3] = {3.2352, 7.124662, -2.5};
|
double coords[3] = {3.2352, 7.124662, -2.5};
|
||||||
point_shape_t* p = make_point(coords[0], coords[1], coords[2]);
|
point_shape_t* p = make_point(coords[0], coords[1], coords[2]);
|
||||||
check_coords(p, coords);
|
check_coords(p, coords);
|
||||||
delete_point(p);
|
delete_point(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("XYZ Origin") {
|
SECTION("Extreme double values") {
|
||||||
double coords[3] = {0, 0, 0};
|
double coords[3] = {
|
||||||
point_shape_t* p = make_point(coords[0], coords[1], coords[2]);
|
std::numeric_limits<double>::max(),
|
||||||
check_coords(p, coords);
|
|
||||||
delete_point(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Large magnitude values") {
|
|
||||||
double coords[3] = {6.5186415e7, 9.48156654e8, -6.516515e6};
|
|
||||||
point_shape_t* p = make_point(coords[0], coords[1], coords[2]);
|
|
||||||
check_coords(p, coords);
|
|
||||||
delete_point(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Multiple points") {
|
|
||||||
const double points[5][3] = {
|
|
||||||
{3, 7, 2},
|
|
||||||
{3, 7, 2},
|
|
||||||
{-5, 3.7, 8},
|
|
||||||
{-3, -7, -2},
|
|
||||||
{0, 0, 1}
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const auto& c : points) {
|
|
||||||
point_shape_t* p = make_point(c[0], c[1], c[2]);
|
|
||||||
check_coords(p, c);
|
|
||||||
delete_point(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Extreme double limits") {
|
|
||||||
double coords[3] = {std::numeric_limits<double>::max(),
|
|
||||||
std::numeric_limits<double>::lowest(),
|
std::numeric_limits<double>::lowest(),
|
||||||
std::numeric_limits<double>::min()};
|
std::numeric_limits<double>::min()
|
||||||
|
};
|
||||||
point_shape_t* p = make_point(coords[0], coords[1], coords[2]);
|
point_shape_t* p = make_point(coords[0], coords[1], coords[2]);
|
||||||
check_coords(p, coords);
|
check_coords(p, coords);
|
||||||
delete_point(p);
|
delete_point(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("NaN and Infinity") {
|
SECTION("Special floating-point values") {
|
||||||
double coords[3] = {std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::infinity(), -std::numeric_limits<double>::infinity()};
|
double coords[3] = {
|
||||||
|
std::numeric_limits<double>::quiet_NaN(),
|
||||||
|
std::numeric_limits<double>::infinity(),
|
||||||
|
-std::numeric_limits<double>::infinity()
|
||||||
|
};
|
||||||
point_shape_t* p = make_point(coords[0], coords[1], coords[2]);
|
point_shape_t* p = make_point(coords[0], coords[1], coords[2]);
|
||||||
|
|
||||||
double x, y, z;
|
double x, y, z;
|
||||||
coord_point(p, &x, &y, &z);
|
coord_point(p, &x, &y, &z);
|
||||||
|
|
||||||
REQUIRE(std::isnan(x));
|
REQUIRE(std::isnan(x));
|
||||||
REQUIRE(std::isinf(y));
|
REQUIRE(std::isinf(y));
|
||||||
REQUIRE(std::isinf(z));
|
REQUIRE(std::isinf(z));
|
||||||
@@ -85,87 +53,35 @@ TEST_CASE("Test point creation, query and deletion behaviour", "[point]") {
|
|||||||
delete_point(p);
|
delete_point(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Denormal values") {
|
SECTION("Multiple independent instances") {
|
||||||
double coords[3] = {std::numeric_limits<double>::denorm_min(),
|
const double points[3][3] = {
|
||||||
-std::numeric_limits<double>::denorm_min(),
|
{3, 7, 2},
|
||||||
0.0};
|
{-5, 3.7, 8},
|
||||||
|
{-3, -7, -2}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto& coords : points) {
|
||||||
point_shape_t* p = make_point(coords[0], coords[1], coords[2]);
|
point_shape_t* p = make_point(coords[0], coords[1], coords[2]);
|
||||||
check_coords(p, coords);
|
check_coords(p, coords);
|
||||||
delete_point(p);
|
delete_point(p);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("Clear single point") {
|
SECTION("Null pointer safety") {
|
||||||
point_shape_t* p = make_point(1.0, 2.0, 3.0);
|
point_shape_t* null_p = nullptr;
|
||||||
|
delete_point(null_p);
|
||||||
|
|
||||||
double x, y, z;
|
double x, y, z;
|
||||||
coord_point(p, &x, &y, &z);
|
coord_point(null_p, &x, &y, &z);
|
||||||
REQUIRE(x == Catch::Approx(1.0));
|
|
||||||
REQUIRE(y == Catch::Approx(2.0));
|
|
||||||
REQUIRE(z == Catch::Approx(3.0));
|
|
||||||
|
|
||||||
delete_point(p);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("Clear multiple points") {
|
TEST_CASE("Point memory management", "[point]") {
|
||||||
const int num_points = 5;
|
SECTION("Rapid allocation/deallocation cycle") {
|
||||||
point_shape_t* p[num_points];
|
for (int i = 0; i < 50; ++i) {
|
||||||
|
|
||||||
for (int i = 0; i < num_points; ++i) {
|
|
||||||
p[i] = make_point(i * 1.0, i * 2.0, i * 3.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < num_points; ++i) {
|
|
||||||
delete_point(p[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Clear already null shape") {
|
|
||||||
point_shape_t* null_p = nullptr;
|
|
||||||
REQUIRE(null_p == nullptr);
|
|
||||||
delete_point(null_p);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Memory efficiency - multiple clear calls") {
|
|
||||||
for (int i = 0; i < 100; ++i) {
|
|
||||||
point_shape_t* tmp_p = make_point(1.0, 1.0, 1.0);
|
|
||||||
delete_point(tmp_p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("Pointer validity after operations") {
|
|
||||||
point_shape_t* p = make_point(1.0, 2.0, 3.0);
|
point_shape_t* p = make_point(1.0, 2.0, 3.0);
|
||||||
REQUIRE(p != nullptr);
|
REQUIRE(p != nullptr);
|
||||||
|
|
||||||
double x, y, z;
|
|
||||||
coord_point(p, &x, &y, &z);
|
|
||||||
|
|
||||||
delete_point(p);
|
delete_point(p);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("Benchmark point operations") {
|
|
||||||
SECTION("make_point performance") {
|
|
||||||
point_shape_t* p = nullptr;
|
|
||||||
BENCHMARK("Create point") {
|
|
||||||
return p = make_point(1.0, 2.0, 3.0);
|
|
||||||
};
|
|
||||||
delete_point(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("coord_point performance") {
|
|
||||||
point_shape_t* p = make_point(1.0, 2.0, 3.0);
|
|
||||||
double x, y, z;
|
|
||||||
|
|
||||||
BENCHMARK("Extract coordinates") {
|
|
||||||
coord_point(p, &x, &y, &z);
|
|
||||||
};
|
|
||||||
delete_point(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("delete_point performance") {
|
|
||||||
BENCHMARK("Delete point") {
|
|
||||||
point_shape_t* p = make_point(1.0, 2.0, 3.0);
|
|
||||||
delete_point(p);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-70
@@ -5,108 +5,59 @@
|
|||||||
|
|
||||||
use arc_core::ffi::point::Point;
|
use arc_core::ffi::point::Point;
|
||||||
|
|
||||||
|
// Safe wrapper tests
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn point_creation() {
|
fn creation_and_query() {
|
||||||
let p = Point::new(1.0, 2.0, -3.0).expect("Failed to create point");
|
let p = Point::new(1.0, 2.0, -3.0).expect("Safe creation failed");
|
||||||
let coords = p.coordinates();
|
assert_eq!(p.coordinates(), (1.0, 2.0, -3.0));
|
||||||
assert_eq!(coords, (1.0, 2.0, -3.0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn point_query() {
|
fn manual_deletion() {
|
||||||
let p = Point::new(5.5, 3.15, -0.001).expect("Failed to create point");
|
let p = Point::new(1.0, 2.0, 3.0).expect("Creation failed");
|
||||||
let coords = p.coordinates();
|
p.delete().expect("Manual deletion failed");
|
||||||
assert_eq!(coords, (5.5, 3.15, -0.001));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn point_deletion() {
|
fn automatic_cleanup() {
|
||||||
let p = Point::new(1.0, 2.0, 3.0).expect("Failed to create point");
|
|
||||||
let result = p.delete();
|
|
||||||
assert!(result.is_ok(), "Deletion should succeed for valid point");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn point_creation_extreme_values() {
|
|
||||||
let cases = [
|
|
||||||
(f64::MAX, f64::MIN, 0.0),
|
|
||||||
(0.0, 0.0, 0.0),
|
|
||||||
(-f64::MAX, -f64::MIN, f64::EPSILON),
|
|
||||||
];
|
|
||||||
|
|
||||||
for (x, y, z) in cases {
|
|
||||||
let p = Point::new(x, y, z).expect("Failed to create point with extreme values");
|
|
||||||
let coords = p.coordinates();
|
|
||||||
assert_eq!(coords, (x, y, z));
|
|
||||||
p.delete().expect("Failed to delete point");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn point_coordinates_immutability() {
|
|
||||||
let p = Point::new(1.5, 2.5, 3.5).expect("Failed to create point");
|
|
||||||
|
|
||||||
let coords1 = p.coordinates();
|
|
||||||
let coords2 = p.coordinates();
|
|
||||||
let coords3 = p.coordinates();
|
|
||||||
|
|
||||||
assert_eq!(coords1, coords2);
|
|
||||||
assert_eq!(coords2, coords3);
|
|
||||||
assert_eq!(coords1, (1.5, 2.5, 3.5));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn point_automatic_cleanup_on_drop() {
|
|
||||||
let coords = {
|
let coords = {
|
||||||
let p = Point::new(7.0, 8.0, 9.0).expect("Failed to create point");
|
let p = Point::new(7.0, 8.0, 9.0).expect("Creation failed");
|
||||||
p.coordinates()
|
p.coordinates()
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(coords, (7.0, 8.0, 9.0));
|
assert_eq!(coords, (7.0, 8.0, 9.0));
|
||||||
|
|
||||||
// Verify we can still create points after automatic cleanup
|
|
||||||
let p2 = Point::new(10.0, 11.0, 12.0).expect("Failed to create point after drop");
|
|
||||||
assert_eq!(p2.coordinates(), (10.0, 11.0, 12.0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn point_multiple_instances_independent() {
|
fn multiple_instances() {
|
||||||
let p1 = Point::new(1.0, 1.0, 1.0).expect("Failed to create point 1");
|
let p1 = Point::new(1.0, 1.0, 1.0).expect("Creation failed");
|
||||||
let p2 = Point::new(2.0, 2.0, 2.0).expect("Failed to create point 2");
|
let p2 = Point::new(2.0, 2.0, 2.0).expect("Creation failed");
|
||||||
let p3 = Point::new(3.0, 3.0, 3.0).expect("Failed to create point 3");
|
|
||||||
|
|
||||||
assert_eq!(p1.coordinates(), (1.0, 1.0, 1.0));
|
assert_eq!(p1.coordinates(), (1.0, 1.0, 1.0));
|
||||||
assert_eq!(p2.coordinates(), (2.0, 2.0, 2.0));
|
assert_eq!(p2.coordinates(), (2.0, 2.0, 2.0));
|
||||||
assert_eq!(p3.coordinates(), (3.0, 3.0, 3.0));
|
|
||||||
|
|
||||||
p2.delete().expect("Failed to delete p2");
|
|
||||||
p1.delete().expect("Failed to delete p1");
|
|
||||||
p3.delete().expect("Failed to delete p3");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn point_debug_format() {
|
fn debug_format() {
|
||||||
let p = Point::new(1.1, 2.2, 3.3).expect("Failed to create point");
|
let p = Point::new(1.1, 2.2, 3.3).expect("Creation failed");
|
||||||
let debug_output = format!("{:?}", p);
|
let debug_output = format!("{:?}", p);
|
||||||
|
|
||||||
assert!(debug_output.contains("Point"));
|
assert!(debug_output.starts_with("Point("));
|
||||||
assert!(debug_output.contains("1.1"));
|
assert!(debug_output.contains("1.1"));
|
||||||
assert!(debug_output.contains("2.2"));
|
assert!(debug_output.contains("2.2"));
|
||||||
assert!(debug_output.contains("3.3"));
|
assert!(debug_output.contains("3.3"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn point_rapid_creation_deletion_cycle_stress_test() {
|
fn boundary_values() {
|
||||||
for i in 0..100 {
|
let cases = [(0.0, 0.0, 0.0), (f64::MAX, f64::MIN, 0.0)];
|
||||||
let p = Point::new(i as f64, i as f64, i as f64)
|
|
||||||
.expect(&format!("Failed to create point in iteration {}", i));
|
for (x, y, z) in cases {
|
||||||
assert_eq!(p.coordinates(), (i as f64, i as f64, i as f64));
|
let p = Point::new(x, y, z).expect("Creation with boundary values failed");
|
||||||
p.delete()
|
assert_eq!(p.coordinates(), (x, y, z));
|
||||||
.expect(&format!("Failed to delete point in iteration {}", i));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user