Skip to content

Commit

Permalink
Misc tests and metadata edits
Browse files Browse the repository at this point in the history
  • Loading branch information
mikera committed Oct 2, 2024
1 parent 2a46a02 commit 1318d23
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 13 deletions.
12 changes: 6 additions & 6 deletions convex-core/src/main/cvx/convex/core/metadata.cvx
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@
:return Any}]}}

callable?
{:doc {:description "Returns true if the target is callable. If symbol is provided, also checks that this symbol references a callable function in the specified account. See `call`."
{:doc {:description "Returns true if the target can be called. If symbol is provided, checks that this symbol references a callable function in the specified account. See `call`."
:errors {:CAST "If the symbol argument is not a Symbol."}
:examples [{:code "(callable? actor-address 'function-name)"}]
:signature [{:params [target]}
Expand All @@ -374,21 +374,21 @@
:return Character}]}}

coll?
{:doc {:description "Returns `true` if and only if the argument is a collection: List, Map, Set, or Vector. Returns false otherwise."
{:doc {:description "Tests if the argument is a data struture."
:examples [{:code "(coll? [1 2 3])"}]
:signature [{:params [x]
:return Boolean}]}}

cond
{:doc {:description ["Performs conditional tests on successive pairs of `test` -> `result`, returning the `result` for the first `test` that succeeds."
"Performs short-circuit evaluation: result expressions that are not used and any test expressions after the first success will not be executed."
"In the case that no test succeeds, a single aditional argument may be added as a fallback value. If no fallback value is available, nil will be returned."]
{:doc {:description ["Performs conditional tests on successive (test, result) pairs, computing the result for the first test that succeeds."
"Result expressions that are not used and any test expressions after the first success will not be executed."
"If no test succeeds, a final expression may be added as a fallback. If no fallback value is available, nil will be returned."]
:examples [{:code "(cond test-1 result-1 else-value)"}
{:code "(cond test-1 result-1 test-2 result-2 test-3 result--3)"}]
:signature [{:params []}
{:params [test]}
{:params [test result]}
{:params [test result fallback-value]}
{:params [test result fallback]}
{:params [test-1 result-1 test-2 result-2 & more]}]}
:special true}

Expand Down
5 changes: 4 additions & 1 deletion convex-core/src/main/java/convex/core/lang/Core.java
Original file line number Diff line number Diff line change
Expand Up @@ -670,9 +670,12 @@ public Context invoke(Context context, ACell[] args) {

@Override
public Context invoke(Context context, ACell[] args) {
// When used as a predicate
if (args.length==1) {
Address addr = RT.callableAddress(args[0]);
return context.withResult(Juice.LOOKUP,CVMBool.create(addr!=null));
if (addr==null) return context.withResult(Juice.LOOKUP,CVMBool.FALSE);
AccountStatus as = context.getState().getAccount(addr);
return context.withResult(Juice.LOOKUP,CVMBool.create(as!=null));
}

if (args.length != 2) return context.withArityError(rangeArityMessage(1,2, args.length));
Expand Down
10 changes: 9 additions & 1 deletion convex-core/src/test/java/convex/core/data/prim/DoubleTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
Expand All @@ -12,6 +13,7 @@
import convex.core.data.Format;
import convex.core.data.ObjectsTest;
import convex.core.exceptions.BadFormatException;
import convex.core.exceptions.InvalidDataException;

public class DoubleTest {

Expand All @@ -20,14 +22,19 @@ public class DoubleTest {

assertSame(CVMDouble.NaN,CVMDouble.create(Double.NaN));

// Canonical NaN encoding has just high bit set
// Canonical NaN encoding has just zeros as payload
assertEquals(Blob.fromHex("1d7ff8000000000000"),nan.getEncoding());

// create coerces to correct NaN
assertSame(CVMDouble.NaN,CVMDouble.create(Double.longBitsToDouble(0x7ff8000000ffffffL)));

Blob BAD_NAN=Blob.fromHex("1d7ff8000000ffffff");
assertThrows(BadFormatException.class,()->Format.read(BAD_NAN));

// We can artificially create a bad NaN, but it is invalid
CVMDouble badNaN=CVMDouble.unsafeCreate(Double.longBitsToDouble(0x7ff8000000ffffffL));
assertNotEquals(nan,badNaN);
assertThrows(InvalidDataException.class,()->badNaN.validate());
}

@Test public void testCompares() {
Expand All @@ -44,6 +51,7 @@ public class DoubleTest {
}

@Test public void testEquality() {
// Regular object equality
ObjectsTest.doEqualityTests(CVMDouble.ONE, CVMDouble.create(1.0));
ObjectsTest.doEqualityTests(CVMDouble.create(12345.0),CVMDouble.create(12345.0));

Expand Down
34 changes: 29 additions & 5 deletions convex-core/src/test/java/convex/core/lang/CoreTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@
*/
public class CoreTest extends ACVMTest {


protected CoreTest() throws IOException {
super(BaseTest.STATE);
}
Expand Down Expand Up @@ -654,6 +653,7 @@ public void testEquals() {
assertFalse(evalB("(= 1 2)"));
assertFalse(evalB("(= 1 nil)"));
assertFalse(evalB("(= 1 1.0)"));
assertFalse(evalB("(= false nil)"));
assertFalse(evalB("(= \\a \\b)"));
assertFalse(evalB("(= :foo :baz)"));
assertFalse(evalB("(= :foo 'foo)"));
Expand Down Expand Up @@ -3904,13 +3904,23 @@ public void testMapPred() {
assertFalse(evalB("(map? '(3 4 5))"));
assertTrue(evalB("(map? {1 2 3 4})"));
assertFalse(evalB("(map? #{1 2})"));

// This is technically a map since it is a record
assertTrue(evalB("(map? (account #0))")); // this is a record

// This is technically a map since it is Index
assertTrue(evalB("(map? (index))")); // this is a record

}

@Test
public void testCollPred() {
// Like Clojure coll?, returns true for any data structure
assertFalse(evalB("(coll? nil)"));
assertFalse(evalB("(coll? 1)"));
assertFalse(evalB("(coll? :foo)"));


assertTrue(evalB("(coll? {})"));
assertTrue(evalB("(coll? [])"));
assertTrue(evalB("(coll? ())"));
Expand All @@ -3921,6 +3931,7 @@ public void testCollPred() {
assertTrue(evalB("(coll? {1 2 3 4})"));
assertTrue(evalB("(coll? #{1 2})"));
assertTrue(evalB("(coll? (index))"));
assertTrue(evalB("(coll? (account #0))")); // this is a record
assertTrue(evalB("(coll? (index 0x 0x))"));
}

Expand All @@ -3942,13 +3953,15 @@ public void testEmptyPred() {
assertFalse(evalB("(empty? #{[]})"));

assertFalse(evalB("(empty? 0)"));
assertFalse(evalB("(empty? false)"));
assertFalse(evalB("(empty? :foo)"));
assertFalse(evalB("(empty? 'bar)"));
}

@Test
public void testSymbolPred() {
assertTrue(evalB("(symbol? 'foo)"));
assertTrue(evalB("(symbol? (quote .))"));
assertTrue(evalB("(symbol? (symbol :bar))"));

assertFalse(evalB("(symbol? (str 1))"));
Expand All @@ -3963,6 +3976,7 @@ public void testKeywordPred() {
assertTrue(evalB("(keyword? (keyword 'bar))"));

assertFalse(evalB("(keyword? nil)"));
assertFalse(evalB("(keyword? 'zzz)"));
assertFalse(evalB("(keyword? 1)"));
assertFalse(evalB("(keyword? [:foo])"));
}
Expand All @@ -3975,6 +3989,7 @@ public void testAddressPred() {

assertFalse(evalB("(address? nil)"));
assertFalse(evalB("(address? 1)"));
assertFalse(evalB("(address? [#1 #2])"));
assertFalse(evalB("(address? \"0a1b2c3d\")"));
assertFalse(evalB("(address? (blob *origin*))"));
}
Expand Down Expand Up @@ -4002,7 +4017,7 @@ public void testLongPred() {
assertFalse(evalB("(long? nil)"));
assertFalse(evalB("(long? 0xFF)"));
assertFalse(evalB("(long? [1 2])"));
assertFalse(evalB("(long? 7.0)"));
assertFalse(evalB("(long? 7.0)")); // not a long, even though numerically equivalent to one

// big integer boundaries
assertTrue(evalB("(long? 9223372036854775807)"));
Expand All @@ -4018,8 +4033,10 @@ public void testStrPred() {
assertTrue(evalB("(str? (str :foo))"));
assertTrue(evalB("(str? (str nil))"));
assertTrue(evalB("(str? \"\")"));
assertTrue(evalB("(str? \"Hello World\")"));

// These are not strings
assertFalse(evalB("(str? \\Q)")); // character is not itself a string
assertFalse(evalB("(str? 1)"));
assertFalse(evalB("(str? :foo)"));
assertFalse(evalB("(str? nil)"));
Expand Down Expand Up @@ -4724,7 +4741,7 @@ public void testExpand() {
assertEquals(Strings.create("foo"), eval("(expand (name :foo) (fn [x e] x))"));
assertEquals(CVMLong.create(3), eval("(expand '[1 2 3] (fn [x e] (nth x 2)))"));

assertNull(Syntax.unwrap(eval("(expand nil)")));
assertNull(eval("(expand nil)"));

assertCastError(step("(expand 1 :foo)"));
assertCastError(step("(expand { 888 227 723 560} [75 561 258 833])"));
Expand All @@ -4747,7 +4764,7 @@ public void testExpand_1() {

@Test
public void testExpandEdgeCases() {
// BAd functions
// Bad functions
assertCastError(step("(expand 123 #0 :foo)"));
assertCastError(step("(expand 123 #0)"));

Expand Down Expand Up @@ -4778,6 +4795,7 @@ public void testExpandOnce() {
public void testMacro() {
Context c=step("(defmacro foo [] :foo)");
assertEquals(Keywords.FOO,eval(c,"(foo)"));
assertEquals(Keywords.FOO,eval(c,"(expand '(foo))"));
}

@Test
Expand All @@ -4790,6 +4808,9 @@ public void testQuote() {

// interior macros shouldn't get expanded
assertEquals(Vectors.of(1,Lists.of(Symbols.IF,4,7),3),eval("(quote [1 (if 4 7) 3])"));

assertArityError(step ("(quote foo bar)"));
assertArityError(step ("(quote)"));
}

@Test
Expand Down Expand Up @@ -4878,7 +4899,10 @@ public void testCallableQ() {
assertFalse(evalB(ctx, "(callable? nil)"));
assertFalse(evalB(ctx, "(callable? :foo)"));
assertFalse(evalB(ctx, "(callable? [])"));


// Missing accounts definitely not callable
assertFalse(evalB(ctx, "(callable? #6666666)"));
assertFalse(evalB(ctx, "(callable? #6666666 'something)"));

assertCastError(step(ctx, "(callable? caddr :public)")); // not a Symbol
assertCastError(step(ctx, "(callable? caddr :random-name)"));
Expand Down

0 comments on commit 1318d23

Please sign in to comment.