Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions core/src/main/java/fj/data/Seq.java
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,15 @@ public boolean isEmpty() {
return ftree.isEmpty();
}

/**
* Checks if this sequence is not empty.
*
* @return True if this sequence is not empty, otherwise false.
*/
public boolean isNotEmpty() {
return !ftree.isEmpty();
}

/**
* Returns the number of elements in this sequence.
*
Expand Down
30 changes: 0 additions & 30 deletions props-core/src/test/java/fj/data/StreamProperties.java

This file was deleted.

209 changes: 209 additions & 0 deletions props-core/src/test/java/fj/data/properties/ArrayProperties.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
package fj.data.properties;

import fj.*;
import fj.data.Array;
import fj.data.Either;
import fj.test.Arbitrary;
import fj.test.Gen;
import fj.test.Property;
import fj.test.reflect.CheckParams;
import fj.test.runner.PropertyTestRunner;
import org.junit.runner.RunWith;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import static fj.Equal.arrayEqual;
import static fj.Equal.intEqual;
import static fj.Function.compose;
import static fj.Function.identity;
import static fj.data.Array.array;
import static fj.data.Array.empty;
import static fj.test.Arbitrary.*;
import static fj.test.Property.implies;
import static fj.test.Property.prop;
import static fj.test.Property.property;

@RunWith(PropertyTestRunner.class)
@CheckParams(maxSize = 10000)
public class ArrayProperties {

private static final Equal<Array<Integer>> eq = arrayEqual(intEqual);

private static final Arbitrary<P2<Array<Integer>, Integer>> arbArrayWithIndex = arbitrary(arbArray(arbInteger).gen
.filter(Array::isNotEmpty)
.bind(array -> Gen.choose(0, array.length() - 1).map(i -> P.p(array, i))));

public Property isEmpty() {
return property(arbArray(arbInteger), array -> prop(array.isEmpty() != array.isNotEmpty()));
}

public Property isNotEmpty() {
return property(arbArray(arbInteger), array -> prop(array.length() > 0 == array.isNotEmpty()));
}

public Property toOption() {
return property(arbArray(arbInteger), array ->
prop(array.toOption().isNone() || intEqual.eq(array.toOption().some(), array.get(0))));
}

public Property toEither() {
return property(arbArray(arbInteger), arbP1(arbInteger), (array, n) -> {
final Either<Integer, Integer> e = array.toEither(n);
return prop(e.isLeft() && intEqual.eq(e.left().value(), n._1()) ||
intEqual.eq(e.right().value(), array.get(0)));
});
}

public Property mapId() {
return property(arbArray(arbInteger), array -> prop(eq.eq(array.map(identity()), array)));
}

public Property mapCompose() {
final F<Integer, Integer> f = x -> x + 3;
final F<Integer, Integer> g = x -> x * 4;
return property(arbArray(arbInteger), array ->
prop(eq.eq(array.map(compose(f, g)), array.map(g).map(f))));
}

public Property foreachDoEffect() {
return property(arbArray(arbInteger), array -> {
int[] acc = {0};
array.foreachDoEffect(x -> acc[0] += x);

int acc2 = 0;
for (int x : array) { acc2 += x; }

return prop(intEqual.eq(acc[0], acc2));
});
}

public Property filter() {
final F<Integer, Boolean> predicate = (x -> x % 2 == 0);
return property(arbArray(arbInteger), array -> prop(array.filter(predicate).forall(predicate)));
}

public Property filterLength() {
final F<Integer, Boolean> predicate = (x -> x % 2 == 0);
return property(arbArray(arbInteger), array -> prop(array.filter(predicate).length() <= array.length()));
}

public Property bindLeftIdentity() {
final F<Integer, Array<Integer>> f = (i -> array(-i));
return property(arbArray(arbInteger), arbInteger, (array, i) ->
prop(eq.eq(array(i).bind(f), f.f(i))));
}

public Property bindRightIdentity() {
return property(arbArray(arbInteger), array -> prop(eq.eq(array.bind(Array::array), array)));
}

public Property bindAssociativity() {
final F<Integer, Array<Integer>> f = x -> array(x + 3);
final F<Integer, Array<Integer>> g = x -> array(x * 4);
return property(arbArray(arbInteger), array ->
prop(eq.eq(array.bind(f).bind(g), array.bind(i -> f.f(i).bind(g)))));
}

public Property foldRight() {
return property(arbArray(arbInteger), array ->
prop(eq.eq(array.foldRight((i, s) -> array(i).append(s), empty()), array)));
}

public Property foldLeft() {
return property(arbArray(arbInteger), array ->
prop(eq.eq(array.foldLeft((s, i) -> array(i).append(s), empty()),
array.reverse().foldRight((i, s) -> array(i).append(s), empty()))));
}

public Property scans() {
return property(arbArray(arbInteger), arbInteger, (array, z) -> {
final F<Integer, F<Integer, Integer>> add = x -> y -> x + y;
final Array<Integer> left = array.scanLeft(add, z);
final Array<Integer> right = array.reverse().scanRight(add, z).reverse();
return prop(eq.eq(left, right));
});
}

public Property scans1() {
return property(arbArray(arbInteger), array ->
implies(array.isNotEmpty(), () -> {
final F<Integer, F<Integer, Integer>> add = x -> y -> x + y;
final Array<Integer> left = array.scanLeft1(add);
final Array<Integer> right = array.reverse().scanRight1(add).reverse();
return prop(eq.eq(left, right));
}));
}

@CheckParams(maxSize = 100)
public Property sequence() {
return property(arbArray(arbInteger), arbArray(arbInteger), (array1, array2) ->
prop(eq.eq(array1.sequence(array2), array1.bind(__ -> array2))));
}

public Property reverseIdentity() {
return property(arbArray(arbInteger), array ->
prop(eq.eq(array.reverse().reverse(), array)));
}

public Property reverse() {
return property(arbArray(arbInteger), arbArray(arbInteger), (array1, array2) ->
prop(eq.eq(array1.append(array2).reverse(), array2.reverse().append(array1.reverse()))));
}

@CheckParams(minSize = 1)
public Property reverseIndex() {
return property(arbArrayWithIndex, p -> {
final Array<Integer> array = p._1();
final Integer i = p._2();
return prop(intEqual.eq(array.reverse().get(i), array.get(array.length() - i - 1)));
});
}

public Property appendLeftIdentity() {
return property(arbArray(arbInteger), array -> prop(eq.eq(Array.<Integer> empty().append(array), array)));
}

public Property appendRightIdentity() {
return property(arbArray(arbInteger), array -> prop(eq.eq(array.append(empty()), array)));
}

public Property appendAssociativity() {
return property(arbArray(arbInteger), arbArray(arbInteger), arbArray(arbInteger), (array1, array2, array3) ->
prop(eq.eq(array1.append(array2).append(array3), array1.append(array2.append(array3)))));
}

public Property appendLength() {
return property(arbArray(arbInteger), arbArray(arbInteger), (array1, array2) ->
prop(array1.append(array2).length() == array1.length() + array2.length()));
}

public Property arrayLength() {
return property(arbArray(arbInteger), array -> prop(array.length() == array.array().length));
}

@CheckParams(minSize = 1)
public Property index() {
return property(arbArrayWithIndex, p -> {
final Array<Integer> array = p._1();
final Integer i = p._2();
return prop(intEqual.eq(array.get(i), array.array(Integer[].class)[i]));
});
}

public Property forallExists() {
return property(arbArray(arbInteger), array ->
prop(array.forall(x -> x % 2 == 0) == !array.exists(x -> x % 2 != 0)));
}

public Property find() {
return property(arbArray(arbInteger), array -> prop(array.find(x -> x % 2 == 0).forall(x -> x % 2 == 0)));
}

@CheckParams(maxSize = 500)
public Property join() {
return property(arbArray(arbArray(arbInteger)), (Array<Array<Integer>> array) ->
prop(eq.eq(array.foldRight(Array::append, empty()), Array.join(array))));
}
}
Loading