{"id":15457678,"url":"https://github.com/neysofu/reltester","last_synced_at":"2025-05-05T21:14:39.901Z","repository":{"id":129873612,"uuid":"611470547","full_name":"neysofu/reltester","owner":"neysofu","description":"Automatically verify traits invariants for [Partial]Eq, [Partial]Ord, Hash, [DoubleEnded|Fused]iterator","archived":false,"fork":false,"pushed_at":"2023-08-27T15:20:07.000Z","size":24,"stargazers_count":20,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-05T21:14:25.901Z","etag":null,"topics":["math","property-based-testing","rust"],"latest_commit_sha":null,"homepage":"https://docs.rs/reltester/latest/reltester/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/neysofu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-03-08T22:24:30.000Z","updated_at":"2024-08-01T01:25:31.000Z","dependencies_parsed_at":null,"dependency_job_id":"17a285b0-117c-405f-aed6-7120aef7a2bf","html_url":"https://github.com/neysofu/reltester","commit_stats":{"total_commits":16,"total_committers":2,"mean_commits":8.0,"dds":0.125,"last_synced_commit":"d6209abff72929f5ba41614f5cea3e4a748428c3"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neysofu%2Freltester","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neysofu%2Freltester/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neysofu%2Freltester/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neysofu%2Freltester/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/neysofu","download_url":"https://codeload.github.com/neysofu/reltester/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252577026,"owners_count":21770721,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["math","property-based-testing","rust"],"created_at":"2024-10-01T22:49:36.055Z","updated_at":"2025-05-05T21:14:39.877Z","avatar_url":"https://github.com/neysofu.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Reltester\n\n[![Crates.io](https://img.shields.io/crates/l/reltester)](https://github.com/neysofu/reltester/blob/main/LICENSE.txt) [![docs.rs](https://img.shields.io/docsrs/reltester)](https://docs.rs/reltester/latest/reltester/) [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/neysofu/reltester/ci.yml)](https://github.com/neysofu/reltester/actions) [![Crates.io](https://img.shields.io/crates/v/reltester)](https://crates.io/crates/reltester) [![min-rustc](https://img.shields.io/badge/min--rustc-1.56-blue)](https://github.com/neysofu/reltester/blob/main/rust-toolchain.toml)\n\n**Rel**ation **tester** is a small testing utility for automatically checking the correctness of `[Partial]Eq`, `[Partial]Ord`, `Hash`, and `[DoubleEnded|Fused]Iterator` trait implementations. It's most useful when used in conjuction with [`quickcheck`](https://github.com/BurntSushi/quickcheck) or some other property-based testing framework.\n\n\n*Go to the [docs](https://docs.rs/reltester/latest/reltester/)!*\n\n## Rationale\n\nImagine a scenario where you have a type `Foo` with a custom implementation of either `PartialEq`, `Eq`, `PartialOrd`, or `Ord`. By \"custom\" we mean hand-written as opposed to derived. The Rust compiler alone cannot verify the correctness of these implementations and thus it is up to you, the programmer, to uphold certain invariants about the specific [binary relation](https://en.wikipedia.org/wiki/Binary_relation) that you're implementing. For example, if you implement `PartialEq` for `Foo`, you must guarantee that `foo1 == foo2` implies `foo2 == foo1` (*symmetry*).\n\nOther traits such as `Hash` and `Iterator` mandate several invariants as well – some of which are very intuitive, and [others](https://doc.rust-lang.org/std/hash/trait.Hash.html#prefix-collisions) which are not. It's especially common for less-than-perfect implementations of the `std::iter` family of traits to introduce off-by-one bugs[^1][^2][^3][^4] among others.\n\nThe idea is, instead of keeping these invariants in your head whenever you go about manually implementing one of these traits in your codebase, you can add a Reltester check to your test suite and have a higher degree of confidence that your implementation is correct.\n\n\n## How to use\n\n1. Write some tests that generate random values of the type you wish to test. You can do this by hand or using crates such as [`quickcheck`](https://github.com/BurntSushi/quickcheck) and [`proptest`](https://github.com/proptest-rs/proptest). Calling the checkers on static, non-randomized values is possible but is less effective in catching bugs.\n2. Based on the traits that your type implements, call the appropriate checker(s):\n\n   - `reltester::eq` for `Eq`;\n   - `reltester::ord` for `Ord`;\n   - `reltester::partial_eq` for `PartialEq`;\n   - `reltester::partial_ord` for `PartialOrd`;\n   - `reltester::hash` for `Hash`;\n   - `reltester::iterator` for `Iterator`;\n   - `reltester::fused_iterator` for `FusedIterator`;\n   - `reltester::double_ended_iterator` for `DoubleEndedIterator`;\n\n   Some of these functions take multiple (two or three) values of the same type. This is because it takes up to three values to test some invariants.\n\nPlease refer to the documentation for more information. The `reltester::invariants` module is available for more granular checks if you can't satisfy the type bounds of the main functions.\n\n## Examples\n\n### `f32` (`PartialEq`, `PartialOrd`)\n\n```rust\nuse reltester;\nuse quickcheck_macros::quickcheck;\n\n#[quickcheck]\nfn test_f32(a: f32, b: f32, c: f32) -\u003e bool {\n    // Let's check if `f32` implements `PartialEq` and `PartialOrd` correctly\n    // (spoiler: it does).\n    reltester::partial_eq(\u0026a, \u0026b, \u0026c).is_ok()\n        \u0026\u0026 reltester::partial_ord(\u0026a, \u0026b, \u0026c).is_ok()\n}\n```\n\n### `u32` (`Hash`)\n\n```rust\nuse reltester;\nuse quickcheck_macros::quickcheck;\n\n#[quickcheck]\nfn test_u32(a: u32, b: u32) -\u003e bool {\n    // Unlike `f32`, `u32` implements both `Eq` and `Hash`, which allows us to\n    // test `Hash` invariants.\n    reltester::hash(\u0026a, \u0026b).is_ok()\n}\n```\n\n### `Vec\u003cu32\u003e` (`DoubleEndedIterator`, `FusedIterator`, `Iterator`)\n\n```rust\nuse reltester;\nuse quickcheck_macros::quickcheck;\n\n#[quickcheck]\nfn test_vec_u32(nums: Vec\u003cu32\u003e) -\u003e bool {\n    // `Iterator` is implied and checked by both `DoubleEndedIterator` and\n    // `FusedIterator`.\n    reltester::double_ended_iterator(nums.iter()).is_ok()\n        \u0026\u0026 reltester::fused_iterator(nums.iter()).is_ok()\n}\n```\n\n## Legal\n\nReltester is available under the terms of the MIT license.\n\n## External references and footnotes\n\n[^1]: https://github.com/rust-lang/rust/issues/41964\n[^2]: https://github.com/bevyengine/bevy/pull/7469\n[^3]: https://github.com/bluejekyll/trust-dns/issues/1638\n[^4]: https://github.com/sparsemat/sprs/issues/261\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneysofu%2Freltester","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fneysofu%2Freltester","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneysofu%2Freltester/lists"}