From 4ef6ebc8aa4fd794126267708646c4a6b0ef51e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Panadero=20Guarde=C3=B1o?= Date: Sun, 24 May 2020 10:47:39 +0200 Subject: [PATCH 1/4] Fix #9 error marking @trusted .equals, .bigger/smallerThan, .length, etc Methods calling opEquals or opCmp of a class must be @trusted, as these methods are @system --- source/pijamas.d | 14 +++++++------- tests/pijamas_spec.d | 36 +++++++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/source/pijamas.d b/source/pijamas.d index 62415e3..63e76e2 100644 --- a/source/pijamas.d +++ b/source/pijamas.d @@ -97,7 +97,7 @@ class Assertion(T) * 255.should.equal(10); // Throws an Exception "expected 255 to equal 10" * ``` */ - T equal(U)(U other, string file = __FILE__, size_t line = __LINE__) @safe + T equal(U)(U other, string file = __FILE__, size_t line = __LINE__) @trusted { this.ok(context == other, this.message(other), file, line); return context; @@ -157,7 +157,7 @@ class Assertion(T) * 10.should.be.biggerThan(1); * ``` */ - bool biggerThan(U)(U other, string file = __FILE__, size_t line = __LINE__) @safe + bool biggerThan(U)(U other, string file = __FILE__, size_t line = __LINE__) @trusted { operator = "be bigger than"; return this.ok(context > other, this.message(other), file, line); @@ -172,7 +172,7 @@ class Assertion(T) * false.should.be.smallerThan(true); * ``` */ - bool smallerThan(U)(U other, string file = __FILE__, size_t line = __LINE__) @safe + bool smallerThan(U)(U other, string file = __FILE__, size_t line = __LINE__) @trusted { operator = "be smaller than"; return this.ok(context < other, this.message(other), file, line); @@ -189,7 +189,7 @@ class Assertion(T) * [1, 2, 0, 4].should.not.be.sorted; * ``` */ - bool sorted(string file = __FILE__, size_t line = __LINE__) @safe + bool sorted(string file = __FILE__, size_t line = __LINE__) @trusted { operator = "be sorted"; return this.ok(context.isSorted, this.message, file, line); @@ -206,7 +206,7 @@ class Assertion(T) * ["something": 10].should.have.key("something"); * ``` */ - void key(U)(U other, string file = __FILE__, size_t line = __LINE__) @safe + void key(U)(U other, string file = __FILE__, size_t line = __LINE__) @trusted { operator = "have key"; this.ok(!(other !in context), this.message(other), file, line); @@ -256,7 +256,7 @@ class Assertion(T) * // ^^ - Throws an Exception "expected 'abcdefg' to have length of 0" * ``` */ - U length(U)(U len, string file = __FILE__, size_t line = __LINE__) @safe + U length(U)(U len, string file = __FILE__, size_t line = __LINE__) @trusted { operator = "have length of"; this.ok(context.length == len, this.message(len), file, line); @@ -272,7 +272,7 @@ class Assertion(T) * "".should.be.empty; * ``` */ - bool empty(string file = __FILE__, size_t line = __LINE__) @safe + bool empty(string file = __FILE__, size_t line = __LINE__) @trusted { operator = "is empty"; return this.ok(context.length == 0, this.message(), file, line); diff --git a/tests/pijamas_spec.d b/tests/pijamas_spec.d index 8eddbfb..080109a 100644 --- a/tests/pijamas_spec.d +++ b/tests/pijamas_spec.d @@ -150,16 +150,42 @@ import pijamas; // it("works for structs", { - struct Example + struct ExampleS { bool a = false; string f = "something"; } - auto e = Example(true, "here"); - e.should.be.equal(Example(true, "here")); - e.should.be.not.equal(Example(true, "asdf")); - assertThrown!Exception(e.should.be.equal(Example(true, "asdf"))); + auto e = ExampleS(true, "here"); + e.should.be.equal(ExampleS(true, "here")); + e.should.be.not.equal(ExampleS(true, "asdf")); + assertThrown!Exception(e.should.be.equal(ExampleS(true, "asdf"))); + } + + // it("works for classes", + { + class ExampleC + { + int x; + this (int x) + { + this.x = x; + } + + override bool opEquals(Object o) const// @trusted + { + if (ExampleC rhs = cast(ExampleC)o) { + return this.x == rhs.x; + } + return false; + } + } + + auto e = new ExampleC(33); + e.should.be.equal(new ExampleC(33)); + e.should.be.not.equal(new ExampleC(1)); + assertThrown!Exception(e.should.be.equal(new ExampleC(1))); + } } From 62919792498f4f1e957234214bcba476e14f51f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Panadero=20Guarde=C3=B1o?= Date: Sun, 24 May 2020 12:39:01 +0200 Subject: [PATCH 2/4] Implements .approxEqual #7 --- source/pijamas.d | 21 +++++++++++++++++++++ tests/pijamas_spec.d | 45 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/source/pijamas.d b/source/pijamas.d index 63e76e2..e2b3b21 100644 --- a/source/pijamas.d +++ b/source/pijamas.d @@ -103,6 +103,27 @@ class Assertion(T) return context; } + /** + * Asserts that a float type is aproximated equal. Returns the valued wrapped around the assertion + * + * Examples: + * ``` + * double d = 0.1; + * double d2 = d + 1e-05; + * d.should.not.be.equal(d2); + * d.should.be.approxEqual(d2); + * ``` + */ + T approxEqual(U = double)(U other, U maxRelDiff = 1e-2, U maxAbsDiff = 1e-05, + string file = __FILE__, size_t line = __LINE__) @trusted + if (is(T : real) && __traits(isFloating, T) && is(U : real) && __traits(isFloating, U)) + { + import std.math : approxEqual; + operator = "be approximated equal than"; + this.ok(approxEqual(context, other, maxRelDiff, maxAbsDiff), this.message(other), file, line); + return context; + } + /** * Asserts whether a value exists - currently simply compares it with null, if it is a pointer, a class or a string. * Returns the value wrapped around the assertion. diff --git a/tests/pijamas_spec.d b/tests/pijamas_spec.d index 080109a..9eac302 100644 --- a/tests/pijamas_spec.d +++ b/tests/pijamas_spec.d @@ -189,6 +189,51 @@ import pijamas; } } +@("Should Assertion.approxEqual") +@safe unittest +{ + // it("asserts that the identical value are identical") + { + float f = 0.01; + f.should.be.approxEqual(f); + + double d = 0.01; + d.should.be.approxEqual(d); + + real r = 0.01; + r.should.be.approxEqual(r); + } + + // it("handles comparing diferent float types") + { + float f = 0.01; + double d = 0.01; + real r = 0.01; + f.should.be.approxEqual(d); + f.should.be.approxEqual(r); + + d.should.be.approxEqual(f); + d.should.be.approxEqual(r); + + r.should.be.approxEqual(f); + r.should.be.approxEqual(d); + } + + // it("asserts that two nearly identical float values are approximated equal") + { + double d = 0.1; + double d2 = d + 1e-05; + d.should.not.be.equal(d2); + d.should.be.approxEqual(d2); + + // and("when increase the difference, it must not be approximated equals") + d2 += 1e-2; + d.should.not.be.equal(d2); + d.should.not.be.approxEqual(d2); + assertThrown!Exception(d.should.be.approxEqual(d2)); + } +} + @("Should Assertion.match") @safe unittest { From 9a921f5bb6c57598e973a215e82edc4daa9ad461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Panadero=20Guarde=C3=B1o?= Date: Sun, 24 May 2020 13:05:38 +0200 Subject: [PATCH 3/4] Update documentation --- CHANGELOG.md | 5 ++++ README.md | 9 +++++++ docs/pijamas.html | 66 ++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 73 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bcf7eec..7c3779a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# v0.3.2 + +* .equals and others, must be @trusted to allow to call @system opEquals +* .approxEquals to do approximated equality of float types + # v0.3.1 * Make Pijamas @safe diff --git a/README.md b/README.md index 3b362a5..8c709d5 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,15 @@ assertion. 255.should.equal(10); // Throws an Exception "expected 255 to equal 10" ``` +#### `T approxEqual(U)(U other, U maxRelDiff = 1e-2, U maxAbsDiff = 1e-05, string file = __FILE__, size_t line = __LINE__);` + +Asserts for aproximated equality of float types. Returns the value wrapped around the +assertion. +```d +(1.0f).should.be.approxEqual(1.00000001); +(1.0f).should.no.be.approxEqual(1.001); +``` + #### `T exist(string file = __FILE__, size_t line = __LINE__);` Asserts whether a value exists - currently simply compares it with `null`, if it diff --git a/docs/pijamas.html b/docs/pijamas.html index 7976b4a..4226ee2 100644 --- a/docs/pijamas.html +++ b/docs/pijamas.html @@ -705,7 +705,7 @@

Declaration

- @safe T equal(U)(U other, string file = __FILE__, size_t line = __LINE__); + @trusted T equal(U)(U other, string file = __FILE__, size_t line = __LINE__);

@@ -743,6 +743,58 @@

Examples

+
  • +
    + +
    +
    +
    +

    Declaration

    +
    +

    + + @trusted T approxEqual(U = double)(U other, U maxRelDiff = 0.01, U maxAbsDiff = 1e-05, string file = __FILE__, size_t line = __LINE__) if (is(T : real) && __traits(isFloating, T) && is(U : real) && __traits(isFloating, U)); + + +

    +
    +
    +
    +
    +
    +
    +
    +

    + Asserts that a float type is aproximated equal. Returns the valued wrapped around the assertion + +

    +
    +
    +

    Examples

    +

    + +

    +
    +
    +
      +
    1. double d = 0.1; +double d2 = d + 1e-05; +d.should.not.be.equal(d2); +d.should.be.approxEqual(d2); +
    2. +
    +
    +
    +
    + +

    +
    +
    + +
    +
  • @@ -810,7 +862,7 @@

    Declaration

    - @safe bool biggerThan(U)(U other, string file = __FILE__, size_t line = __LINE__); + @trusted bool biggerThan(U)(U other, string file = __FILE__, size_t line = __LINE__);

    @@ -860,7 +912,7 @@

    Declaration

    - @safe bool smallerThan(U)(U other, string file = __FILE__, size_t line = __LINE__); + @trusted bool smallerThan(U)(U other, string file = __FILE__, size_t line = __LINE__);

    @@ -910,7 +962,7 @@

    Declaration

    - @safe bool sorted(string file = __FILE__, size_t line = __LINE__); + @trusted bool sorted(string file = __FILE__, size_t line = __LINE__);

    @@ -960,7 +1012,7 @@

    Declaration

    - @safe void key(U)(U other, string file = __FILE__, size_t line = __LINE__); + @trusted void key(U)(U other, string file = __FILE__, size_t line = __LINE__);

    @@ -1064,7 +1116,7 @@

    Declaration

    - @safe U length(U)(U len, string file = __FILE__, size_t line = __LINE__); + @trusted U length(U)(U len, string file = __FILE__, size_t line = __LINE__);

    @@ -1115,7 +1167,7 @@

    Declaration

    - @safe bool empty(string file = __FILE__, size_t line = __LINE__); + @trusted bool empty(string file = __FILE__, size_t line = __LINE__);

    From f501054e196abb30d20a102b4f59513a80808801 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Panadero=20Guarde=C3=B1o?= Date: Sun, 24 May 2020 13:07:10 +0200 Subject: [PATCH 4/4] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8c709d5..464bfc6 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ Asserts for aproximated equality of float types. Returns the value wrapped aroun assertion. ```d (1.0f).should.be.approxEqual(1.00000001); -(1.0f).should.no.be.approxEqual(1.001); +(1.0f).should.not.be.approxEqual(1.001); ``` #### `T exist(string file = __FILE__, size_t line = __LINE__);`