Skip to content

Commit

Permalink
More generative testing enhancements
Browse files Browse the repository at this point in the history
  • Loading branch information
mikera committed Dec 22, 2024
1 parent eacc88c commit 5370a17
Show file tree
Hide file tree
Showing 25 changed files with 187 additions and 31 deletions.
5 changes: 2 additions & 3 deletions convex-core/src/main/java/convex/core/cpos/Belief.java
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,8 @@ public Index<AccountKey, SignedData<Order>> getOrders() {

@Override
public boolean equals(ACell a) {
if (!(a instanceof Belief)) return false;
Belief as=(Belief)a;
return equals(as);
if (a instanceof Belief) return equals((Belief)a);
return super.equals(a);
}

/**
Expand Down
1 change: 1 addition & 0 deletions convex-core/src/main/java/convex/core/cvm/ops/Invoke.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ protected Invoke(AVector<AOp<ACell>> ops) {
}

public static <T extends ACell> Invoke<T> create(ASequence<AOp<ACell>> ops) {
if (ops.count()==0) return null;
AVector<AOp<ACell>> vops = ops.toVector();
return new Invoke<T>(vops);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public void validateStructure() throws InvalidDataException {
public boolean equals(ACell a) {
if (a==null) return false;
if (a.getTag()!=tag) return false;
return encoding.equals(a.getEncoding());
return getEncoding().equals(a.getEncoding());
}

@Override
Expand Down
7 changes: 7 additions & 0 deletions convex-core/src/main/java/convex/core/data/AVector.java
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ public AType getType() {
*/
@Override
public abstract T get(long i);

/**
* Remove an element at the specified position in a vector. WARNING: likely to be O(n)
* @param i
* @return Shortened Vector, or null if position was invalid
*/
public abstract AVector<T> dissocAt(long i);

/**
* Appends a ListVector chunk to this vector. This vector must contain a whole
Expand Down
7 changes: 7 additions & 0 deletions convex-core/src/main/java/convex/core/data/MapEntry.java
Original file line number Diff line number Diff line change
Expand Up @@ -290,4 +290,11 @@ protected void visitAllChildren(Consumer<AVector<ACell>> visitor) {
// nothing to visit
}

@Override
public AVector<ACell> dissocAt(long i) {
if (i==0) return Vectors.create(get(1));
if (i==1) return Vectors.create(get(0));
return null;
}

}
11 changes: 11 additions & 0 deletions convex-core/src/main/java/convex/core/data/VectorArray.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package convex.core.data;

import java.util.Arrays;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.function.BiFunction;
Expand Down Expand Up @@ -295,6 +296,16 @@ public Ref<ACell> getRef(int i) {
return getCanonical().getRef(i);
}

@Override
public AVector<T> dissocAt(long i) {
int n=(int)count;
if ((i<0)||(i>=n)) return null;
ACell[] cells=Arrays.copyOf(data, n-1);
System.arraycopy(data, (int)(i+1), cells, (int)i, (int)(n-i-1));

return wrap(cells);
}




Expand Down
25 changes: 25 additions & 0 deletions convex-core/src/main/java/convex/core/data/VectorLeaf.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package convex.core.data;

import java.util.Arrays;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.function.BiFunction;
Expand Down Expand Up @@ -437,6 +438,10 @@ public void add(T e) {

}

/**
* Get the length of the prefix vector, will be 0 if no prefix
* @return
*/
public long prefixLength() {
return count - items.length;
}
Expand Down Expand Up @@ -737,4 +742,24 @@ protected void visitAllChildren(Consumer<AVector<T>> visitor) {
visitor.accept(child);
}
}

@Override
public AVector<T> dissocAt(long i) {
if ((i<0)||(i>=count)) return null;
long pl=prefixLength();
if (i >= pl) {
int cn=items.length;
if (cn==1) {
// Just return prefix, or empty vector if no prefix
return (pl==0)?Vectors.empty():prefix.getValue();
}

int ci=(int)(i-pl);
Ref<T>[] newItems=Arrays.copyOf(items, cn-1);
System.arraycopy(items, ci+1, newItems, ci, cn-ci-1);

return new VectorLeaf<T>(newItems,prefix,count-1);
}
return slice(0,i).concat(slice(i+1,count));
}
}
6 changes: 6 additions & 0 deletions convex-core/src/main/java/convex/core/data/VectorTree.java
Original file line number Diff line number Diff line change
Expand Up @@ -745,5 +745,11 @@ protected void visitAllChildren(Consumer<AVector<T>> visitor) {
visitor.accept(child);
}
}

@Override
public AVector<T> dissocAt(long i) {
if ((i<0)||(i>=count)) return null;
return slice(0,i).concat(slice(i+1,count));
}

}
6 changes: 6 additions & 0 deletions convex-core/src/main/java/convex/core/data/Vectors.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package convex.core.data;

import java.util.Collection;
import java.util.Comparator;

import org.bouncycastle.util.Arrays;

Expand All @@ -23,6 +24,11 @@ public class Vectors {

public static final int MAX_ENCODING_LENGTH = Math.max(VectorLeaf.MAX_ENCODING_LENGTH,VectorTree.MAX_ENCODING_LENGTH);

@SuppressWarnings("rawtypes")
public static final Comparator<AVector> lengthComparator = (a,b)->{
return Utils.checkedInt(a.count()-b.count());
};

/**
* Creates a canonical AVector with the given elements
*
Expand Down
17 changes: 12 additions & 5 deletions convex-core/src/test/java/convex/comms/GenTestFormat.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,19 @@ public void primitiveRoundTrip(@From(PrimitiveGen.class) ACell prim) throws BadF
public void dataRoundTrip(@From(ValueGen.class) ACell value) throws BadFormatException, IOException {
Ref<ACell> pref = Ref.get(Cells.persist(value)); // ensure persisted
Blob b = Cells.encode(value);
ACell o = Format.read(b);
try {
ACell o = Format.read(b);

assertEquals(value, o);
assertEquals(b, Cells.encode(o));
assertEquals(pref.getValue(), o);

FuzzTestFormat.doMutationTest(b);
} catch (BadFormatException e) {
System.err.println("Bad format in GenTestFromat: "+b);
throw e;
}

assertEquals(value, o);
assertEquals(b, Cells.encode(o));
assertEquals(pref.getValue(), o);

FuzzTestFormat.doMutationTest(b);
}
}
21 changes: 20 additions & 1 deletion convex-core/src/test/java/convex/core/cvm/GenTestOps.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package convex.core.cvm;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.runner.RunWith;
Expand All @@ -9,13 +10,16 @@
import com.pholser.junit.quickcheck.Property;
import com.pholser.junit.quickcheck.runner.JUnitQuickcheck;

import convex.core.data.ACell;
import convex.core.init.InitTest;
import convex.core.lang.OpsTest;
import convex.test.generators.FormGen;
import convex.test.generators.OpsGen;

@RunWith(JUnitQuickcheck.class)
public class GenTestOps {

@SuppressWarnings("rawtypes")
@SuppressWarnings({ "rawtypes", "unchecked" })
@Property
public void testOpExecution(@From(OpsGen.class) AOp op) {
// A context should be able to execute any valid Op without throwing
Expand All @@ -26,8 +30,23 @@ public void testOpExecution(@From(OpsGen.class) AOp op) {
assertEquals(0,c.getDepth());

assertTrue(c.getJuiceUsed()>initialJuice);

OpsTest.doOpTest(op);

}

@SuppressWarnings({ "unchecked", "rawtypes" })
public void testCompile(@From(FormGen.class) ACell form) {
Context c=Context.create(InitTest.STATE);
c=c.compile(form);
if (c.isExceptional()) {
// can easily happen, invalid syntax etc
} else {
AOp op=Ops.ensureOp(c.getResult());
assertNotNull(op);
OpsTest.doOpTest(op);
}
}


}
27 changes: 27 additions & 0 deletions convex-core/src/test/java/convex/core/data/GenTestVectors.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,31 @@ public void testConcatPrefixes(@From(VectorGen.class) AVector a, @From(VectorGen
assertEquals(a.get(cp - 1), b.get(cp - 1));
}
}

@SuppressWarnings({ "rawtypes", "unchecked" })
@Property
public void testElementProperties(@From(VectorGen.class) AVector a,long index) {
long n=a.count();
if (n==0) return; // skip for empty vector


long i=Math.abs(Math.floorMod(index, n));

// Get the element
ACell e=a.get(i);
ObjectsTest.doAnyValueTests(e);

// dissoc the specified element
AVector d=a.dissocAt(i);
assertEquals(n-1,d.count());
if (i<n-1) {
assertEquals(d.get(i),a.get(i+1));
assertEquals(d.get(n-2),a.get(n-1));
}
VectorsTest.doVectorTests(d);

// check element ref
assertEquals(a.getElementRef(i),Ref.get(e));
}

}
11 changes: 9 additions & 2 deletions convex-core/src/test/java/convex/core/lang/OpsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,13 @@ public void testLambda() {

doOpTest(lam);
}

@Test
public void testBadInvokeOp() {
Context c = context();
c=step(c,"(eval #[db00])"); // Dense record that looks like an Invoke op with no values
assertEquals(DenseRecord.create(0xdb, Vectors.empty()),c.getResult());
}

@Test
public void testLambdaString() {
Expand All @@ -387,9 +394,9 @@ public void testLocalRegression() throws BadFormatException {
assertThrows(BadFormatException.class,()->Format.read(enc));
}

public <T extends ACell> void doOpTest(AOp<T> op) {
public static <T extends ACell> void doOpTest(AOp<T> op) {
// Executing any Op should not throw
context().execute(op);
TestState.CONTEXT.fork().execute(op);

try {
op.validate();
Expand Down
18 changes: 18 additions & 0 deletions convex-core/src/test/java/convex/test/generators/AGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package convex.test.generators;

import com.pholser.junit.quickcheck.generator.GenerationStatus;
import com.pholser.junit.quickcheck.generator.Generator;
import com.pholser.junit.quickcheck.random.SourceOfRandomness;

/**
* Generator for arbitrary Addresses
*/
public abstract class AGenerator<T> extends Generator<T> {

protected AGenerator(Class<T> type) {
super(type);
}

@Override
public abstract T generate(SourceOfRandomness r, GenerationStatus status);
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package convex.test.generators;

import com.pholser.junit.quickcheck.generator.GenerationStatus;
import com.pholser.junit.quickcheck.generator.Generator;
import com.pholser.junit.quickcheck.random.SourceOfRandomness;

import convex.core.cvm.Address;

/**
* Generator for arbitrary Addresses
*/
public class AddressGen extends Generator<Address> {
public class AddressGen extends AGenerator<Address> {

public AddressGen() {
super(Address.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package convex.test.generators;

import com.pholser.junit.quickcheck.generator.GenerationStatus;
import com.pholser.junit.quickcheck.generator.Generator;
import com.pholser.junit.quickcheck.random.SourceOfRandomness;

import convex.core.data.ABlob;
Expand All @@ -18,7 +17,7 @@
*
*/
@SuppressWarnings("rawtypes")
public class AnyMapGen extends Generator<AMap> {
public class AnyMapGen extends AGenerator<AMap> {
public AnyMapGen() {
super(AMap.class);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package convex.test.generators;

import com.pholser.junit.quickcheck.generator.GenerationStatus;
import com.pholser.junit.quickcheck.generator.Generator;
import com.pholser.junit.quickcheck.random.SourceOfRandomness;

import convex.core.Constants;
Expand All @@ -18,7 +17,7 @@
*
*/
@SuppressWarnings("rawtypes")
public class AnyRecordGen extends Generator<ARecord> {
public class AnyRecordGen extends AGenerator<ARecord> {
public AnyRecordGen() {
super(ARecord.class);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package convex.test.generators;

import com.pholser.junit.quickcheck.generator.GenerationStatus;
import com.pholser.junit.quickcheck.generator.Generator;
import com.pholser.junit.quickcheck.random.SourceOfRandomness;

import convex.core.data.ABlob;
Expand All @@ -15,7 +14,7 @@
* Generator for binary Blobs
*
*/
public class BlobGen extends Generator<ABlob> {
public class BlobGen extends AGenerator<ABlob> {
public BlobGen() {
super(ABlob.class);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package convex.test.generators;

import com.pholser.junit.quickcheck.generator.GenerationStatus;
import com.pholser.junit.quickcheck.generator.Generator;
import com.pholser.junit.quickcheck.random.SourceOfRandomness;

import convex.core.data.prim.CVMBool;
Expand All @@ -11,7 +10,7 @@
/**
* Generator for booleans
*/
public class BooleanGen extends Generator<CVMBool> {
public class BooleanGen extends AGenerator<CVMBool> {
public BooleanGen() {
super(CVMBool.class);
}
Expand Down
Loading

0 comments on commit 5370a17

Please sign in to comment.