Skip to content

Commit

Permalink
Fix lazy Assessment of Iterates, fixes #110
Browse files Browse the repository at this point in the history
Also makes Anything generic.
  • Loading branch information
dmfs committed Oct 2, 2023
1 parent 5d25096 commit 06a8283
Show file tree
Hide file tree
Showing 17 changed files with 204 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@
import org.dmfs.srcless.annotations.composable.Composable;


/**
* The assessment of an object in regard to a specific {@link Quality}.
* <p>
* Note, {@link Assessment}s must be immutable. If a {@link Quality} returns an {@link Assessment} of a mutable object
* the {@link Assessment} instance MUST return the same result when the object is mutated.
*/
@Composable(packageName = "org.saynotobugs.confidence.assessment")
public interface Assessment
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.dmfs.jems2.iterable.Seq;
import org.dmfs.jems2.optional.Zipped;
import org.dmfs.jems2.single.Backed;
import org.dmfs.jems2.single.Collected;
import org.dmfs.srcless.annotations.staticfactory.StaticFactories;
import org.saynotobugs.confidence.Assessment;
import org.saynotobugs.confidence.Description;
Expand All @@ -36,6 +37,8 @@
import org.saynotobugs.confidence.description.Value;
import org.saynotobugs.confidence.quality.object.EqualTo;

import java.util.ArrayList;

import static org.saynotobugs.confidence.description.LiteralDescription.COMMA_NEW_LINE;


Expand Down Expand Up @@ -70,14 +73,18 @@ public Assessment assessmentOf(Iterable<T> candidate)
{
return new AllPassed(new Text("iterated [ "), COMMA_NEW_LINE, new Text(" ]"),
new Numbered(
new OuterZipped<>(
mDelegates,
candidate,
(left, right) -> new Backed<>(new Zipped<>(left, right, Quality::assessmentOf),
() -> new Fail(left.isPresent()
? new Spaced(new Text("missing"), left.value().description())
: new Spaced(new Text("additional"), new Value(right.value())))).value()
)));
// eagerly collect the Assessments, otherwise the result might be wrong when the tested candidate is
// mutable and mutated afterward
new Collected<>(ArrayList::new,
new OuterZipped<>(
mDelegates,
candidate,
(left, right) -> new Backed<>(new Zipped<>(left, right, Quality::assessmentOf),
() -> new Fail(left.isPresent()
? new Spaced(new Text("missing"), left.value().description())
: new Spaced(new Text("additional"), new Value(right.value())))).value()
)
).value()));
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public ContainsEntry(K key)

public ContainsEntry(Quality<? super K> key)
{
this(key, new Anything());
this(key, new Anything<>());
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public final class EntryOf<K, V> extends QualityComposition<Map.Entry<K, V>>
{
public EntryOf(K key)
{
this(new EqualTo<>(key), new Anything());
this(new EqualTo<>(key), new Anything<>());
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public final class Present<T> extends QualityComposition<Optional<T>>
*/
public Present()
{
this(new Anything());
this(new Anything<>());
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@


@StaticFactories(value = "Core", packageName = "org.saynotobugs.confidence.quality")
public final class Anything extends QualityComposition<Object>
public final class Anything<T> extends QualityComposition<T>
{
public Anything()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ class AllOfTest
void testMatch()
{
assertThat(new AllOf<>(), new Passes<>(123, "abc"));
assertThat(new AllOf<>(new Anything()), new Passes<>(123, "abc"));
assertThat(new AllOf<>(new Anything(), new Anything()), new Passes<>(123, "abc"));
assertThat(new AllOf<>(new Anything<>()), new Passes<>(123, "abc"));
assertThat(new AllOf<>(new Anything<>(), new Anything<>()), new Passes<>(123, "abc"));
}


@Test
void testMismatch()
{
assertThat(new AllOf<>(new Nothing()), new Fails<>(123, "{ <123> }"));
assertThat(new AllOf<>(new Anything(), new Nothing()), new Fails<>(123, "{ ...\n <123> }"));
assertThat(new AllOf<>(new Nothing(), new Anything(), new Anything()), new Fails<>(123, "{ <123>\n ... }"));
assertThat(new AllOf<>(new Anything<>(), new Nothing()), new Fails<>(123, "{ ...\n <123> }"));
assertThat(new AllOf<>(new Nothing(), new Anything<>(), new Anything<>()), new Fails<>(123, "{ <123>\n ... }"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ void test()
new Fails<>("123", "\"123\" ( \"123\" )"),
new HasDescription("not ( \"123\" )")));

assertThat(new Not<>(new Anything()),
assertThat(new Not<>(new Anything<>()),
new AllOf<>(
new Fails<>("123", "\"123\" ( <anything> )"),
new HasDescription("not ( <anything> )")));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ void testValue()
@Test
void testMatch()
{
assertThat(new Is<>(new Anything()),
assertThat(new Is<>(new Anything<>()),
new AllOf<>(
new Passes<>("12", 1, new Object()),
new HasDescription("is <anything>")));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void testValue()
@Test
void testMatch()
{
assertThat(new To<>(new Anything()),
assertThat(new To<>(new Anything<>()),
new AllOf<>(
new Passes<>("12", 1, new Object()),
new HasDescription("to <anything>")));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,19 @@
import org.dmfs.jems2.iterable.EmptyIterable;
import org.dmfs.jems2.iterable.Seq;
import org.junit.jupiter.api.Test;
import org.saynotobugs.confidence.description.Text;
import org.saynotobugs.confidence.quality.comparable.GreaterThan;
import org.saynotobugs.confidence.quality.comparable.LessThan;
import org.saynotobugs.confidence.quality.composite.AllOf;
import org.saynotobugs.confidence.test.quality.Fails;
import org.saynotobugs.confidence.test.quality.HasDescription;
import org.saynotobugs.confidence.test.quality.Passes;
import org.saynotobugs.confidence.test.quality.PassesPostMutation;

import java.util.ArrayList;
import java.util.List;

import static java.util.Collections.singletonList;
import static org.saynotobugs.confidence.Assertion.assertThat;


Expand Down Expand Up @@ -80,4 +86,14 @@ void testMultipleMatchers()
new HasDescription("iterates [ 0: less than <1>,\n 1: greater than <2>,\n 2: less than <3> ]")
));
}


@Test
void testOneValueWithPostMutation()
{
assertThat(new Iterates<>(1),
new PassesPostMutation<>(() -> new ArrayList<>(singletonList(1)), new Text("clear list"), List::clear));
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class ThrowingTest
@Test
void test()
{
assertThat(new Throwing(new Anything()),
assertThat(new Throwing(new Anything<>()),
new AllOf<>(
new Passes<>((Throwing.Breakable) () -> {throw new NoSuchElementException();}),
new Fails<>(() -> {}, "not throwing <anything>"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class AnythingTest
void test()
{
assertThat(
new Anything(),
new Anything<>(),
new AllOf<>(
new Passes<>(123),
new Passes<Object>("abc"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public IsAlive()
orig -> orig,
orig -> new Text("alive"),
new NoneOf<>(
new Has<>("error", RxTestAdapter::errors, new Contains<>(new Anything())),
new Has<>("error", RxTestAdapter::errors, new Contains<>(new Anything<>())),
new IsComplete(),
new IsCancelled<>()
)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public final class Fails<T> implements Quality<Quality<? super T>>

public Fails(T mismatchingValue)
{
this(mismatchingValue, new Anything());
this(mismatchingValue, new Anything<>());
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright 2022 dmfs GmbH
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.saynotobugs.confidence.test.quality;

import org.dmfs.jems2.Generator;
import org.dmfs.jems2.Procedure;
import org.dmfs.srcless.annotations.staticfactory.StaticFactories;
import org.saynotobugs.confidence.Assessment;
import org.saynotobugs.confidence.Description;
import org.saynotobugs.confidence.Quality;
import org.saynotobugs.confidence.assessment.FailUpdated;
import org.saynotobugs.confidence.description.DescriptionDescription;
import org.saynotobugs.confidence.description.Spaced;
import org.saynotobugs.confidence.description.Text;
import org.saynotobugs.confidence.description.Value;

import static org.saynotobugs.confidence.description.LiteralDescription.NEW_LINE;


@StaticFactories("Test")
public final class PassesPostMutation<T> implements Quality<Quality<? super T>>
{
private final Generator<T> mMatchingValue;
private final Description mMutationDescription;
private final Procedure<? super T> mMutation;


public PassesPostMutation(Generator<T> matchingValue, Description mutationDescription, Procedure<? super T> mutation)
{
mMatchingValue = matchingValue;
mMutationDescription = mutationDescription;
mMutation = mutation;
}


@Override
public Assessment assessmentOf(Quality<? super T> candidate)
{
T value = mMatchingValue.next();
Assessment assessment = candidate.assessmentOf(value);
mMutation.process(value);

return new FailUpdated(
orig -> new Spaced(
new Value(mMatchingValue.next()),
new Text("mismatched with"),
new DescriptionDescription(orig),
NEW_LINE,
new Text("after"),
mMutationDescription),
assessment);
}


@Override
public Description description()
{
return new Spaced(new Text("matches"), new Value(mMatchingValue.next()), new Text("after"), mMutationDescription);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* Copyright 2023 dmfs GmbH
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.saynotobugs.confidence.test.quality;

import org.junit.jupiter.api.Test;
import org.saynotobugs.confidence.Assessment;
import org.saynotobugs.confidence.Description;
import org.saynotobugs.confidence.Quality;
import org.saynotobugs.confidence.description.LiteralDescription;
import org.saynotobugs.confidence.description.Text;
import org.saynotobugs.confidence.quality.composite.AllOf;
import org.saynotobugs.confidence.quality.trivial.Anything;

import java.util.ArrayList;
import java.util.List;

import static java.util.Collections.singletonList;
import static org.saynotobugs.confidence.Assertion.assertThat;

class PassesPostMutationTest
{
@Test
void test()
{
assertThat(new PassesPostMutation<>(() -> new ArrayList<>(singletonList(1)), new Text("List::clear"), List::clear),
new AllOf<>(
new Passes<Quality<List<Integer>>>(new Anything<>()),
new Fails<>(new Quality<List<Integer>>()
{
@Override
public Assessment assessmentOf(List<Integer> candidate)
{
return new Assessment()
{
@Override
public boolean isSuccess()
{
return candidate.size() == 1;
}

@Override
public Description description()
{
return new Text("Fail");
}
};
}

@Override
public Description description()
{
return LiteralDescription.EMPTY;
}
}, "[ <1> ] mismatched with \n ----\n Fail\n ---- \n after List::clear"),
new HasDescription("matches [ <1> ] after List::clear")
)
);
}

}

0 comments on commit 06a8283

Please sign in to comment.