You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2026/01/01 10:12:45 UTC

(jena) branch main updated (b6e6962dae -> 3b2658418c)

This is an automated email from the ASF dual-hosted git repository.

andy pushed a change to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git


    from b6e6962dae remove mixed decl silence (now obsolete), add silence for if-function
     new 16ec4d84d7 Rename NodeValue constants for certain xsd:double cases
     new f5a3dfb9cc Restore using prefixes for text output
     new ca1ec6cfed GH-3674: Fix ROUND()
     new d61e8f8612 Notes for skipped tests
     new 73d6528caf Details for ASK eval test failure
     new 3b2658418c Use -XX:+EnableDynamicAgentLoading for surefire to avoid variable setting

The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../org/apache/jena/sparql/expr/NodeValue.java     |  28 +-
 .../sparql/expr/nodevalue/NodeValueDouble.java     |   2 +-
 .../jena/sparql/expr/nodevalue/NodeValueFloat.java |   2 +-
 .../jena/sparql/expr/nodevalue/NodeValueOps.java   |   2 +-
 .../jena/sparql/expr/nodevalue/XSDFuncOp.java      |  40 ++-
 .../org/apache/jena/sparql/function/CastXSD.java   |   9 +-
 .../apache/jena/sparql/util/QueryExecUtils.java    | 167 ++++++-----
 .../org/apache/jena/sparql/util/XSDNumUtils.java   |  20 +-
 .../apache/jena/arq/junit/sparql/SparqlTests.java  |   6 +-
 .../jena/arq/junit/sparql/tests/QueryEvalTest.java | 101 ++++---
 .../org/apache/jena/sparql/expr/LibTestExpr.java   |   4 +-
 .../jena/sparql/expr/TestExpressionsMath.java      |  16 +-
 .../apache/jena/sparql/expr/TestFunctions2.java    | 323 ++++++++++-----------
 .../jena/sparql/expr/TestLeviathanFunctions.java   |   2 +-
 .../org/apache/jena/sparql/expr/TestXSDFuncOp.java |  98 +++++++
 jena-core/pom.xml                                  |   4 +
 jena-extras/jena-querybuilder/pom.xml              |   3 +-
 jena-fuseki2/jena-fuseki-core/pom.xml              |   3 +-
 18 files changed, 502 insertions(+), 328 deletions(-)


(jena) 05/06: Details for ASK eval test failure

Posted by an...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git

commit 73d6528cafed444989481c6ad7906859772d954f
Author: Andy Seaborne <an...@apache.org>
AuthorDate: Tue Dec 30 21:06:35 2025 +0000

    Details for ASK eval test failure
---
 .../jena/arq/junit/sparql/tests/QueryEvalTest.java | 101 ++++++++++++---------
 1 file changed, 60 insertions(+), 41 deletions(-)

diff --git a/jena-arq/src/test/java/org/apache/jena/arq/junit/sparql/tests/QueryEvalTest.java b/jena-arq/src/test/java/org/apache/jena/arq/junit/sparql/tests/QueryEvalTest.java
index 88a3617969..610b72463c 100644
--- a/jena-arq/src/test/java/org/apache/jena/arq/junit/sparql/tests/QueryEvalTest.java
+++ b/jena-arq/src/test/java/org/apache/jena/arq/junit/sparql/tests/QueryEvalTest.java
@@ -257,6 +257,50 @@ public class QueryEvalTest extends AbstractManifestTest {
         return;
     }
 
+    private void runTestAsk(Query query, QueryExecution qe) {
+        boolean bActual = qe.execAsk();
+        if ( results != null ) {
+            if ( results.isBoolean() ) {
+                boolean bExpected = results.getBooleanResult();
+                if ( bExpected != bActual ) {
+                    printFailedAskTest(query, qe, bExpected, bActual);
+                }
+                assertEquals(bExpected, bActual, ()->"ASK test results do not match");
+            } else {
+                Model resultsAsModel = results.getModel();
+                StmtIterator sIter = results.getModel().listStatements(null, RDF.type, ResultSetGraphVocab.ResultSet);
+                if ( !sIter.hasNext() )
+                    throw new TestSetupException("Can't find the ASK result");
+                Statement s = sIter.nextStatement();
+                if ( sIter.hasNext() )
+                    throw new TestSetupException("Too many result sets in ASK result");
+                Resource r = s.getSubject();
+                Property p = resultsAsModel.createProperty(ResultSetGraphVocab.getURI() + "boolean");
+
+                boolean x = r.getRequiredProperty(p).getBoolean();
+                if ( x != bActual )
+                    assertEquals(x, bActual, ()->"ASK test results do not match");
+            }
+        }
+        return;
+    }
+
+    private void runTestConstruct(Query query, QueryExecution qe) {
+        // Do the query!
+        if ( query.isConstructQuad() ) {
+            Dataset resultActual = qe.execConstructDataset();
+            compareDatasetResults(resultActual, query);
+        } else {
+            Model resultsActual = qe.execConstruct();
+            compareGraphResults(resultsActual, query);
+        }
+    }
+
+    private void runTestDescribe(Query query, QueryExecution qe) {
+        Model resultsActual = qe.execDescribe();
+        compareGraphResults(resultsActual, query);
+    }
+
     private ResultSetRewindable convertToStrings(ResultSetRewindable resultsActual) {
         List<Binding> bindings = new ArrayList<>();
         while (resultsActual.hasNext()) {
@@ -312,17 +356,6 @@ public class QueryEvalTest extends AbstractManifestTest {
         }
     }
 
-    private void runTestConstruct(Query query, QueryExecution qe) {
-        // Do the query!
-        if ( query.isConstructQuad() ) {
-            Dataset resultActual = qe.execConstructDataset();
-            compareDatasetResults(resultActual, query);
-        } else {
-            Model resultsActual = qe.execConstruct();
-            compareGraphResults(resultsActual, query);
-        }
-    }
-
     private void compareGraphResults(Model resultsActual, Query query) {
         if ( results != null ) {
             try {
@@ -364,36 +397,6 @@ public class QueryEvalTest extends AbstractManifestTest {
         }
     }
 
-    private void runTestDescribe(Query query, QueryExecution qe) {
-        Model resultsActual = qe.execDescribe();
-        compareGraphResults(resultsActual, query);
-    }
-
-    private void runTestAsk(Query query, QueryExecution qe) {
-        boolean result = qe.execAsk();
-        if ( results != null ) {
-            if ( results.isBoolean() ) {
-                boolean b = results.getBooleanResult();
-                assertEquals(b, result, ()->"ASK test results do not match");
-            } else {
-                Model resultsAsModel = results.getModel();
-                StmtIterator sIter = results.getModel().listStatements(null, RDF.type, ResultSetGraphVocab.ResultSet);
-                if ( !sIter.hasNext() )
-                    throw new TestSetupException("Can't find the ASK result");
-                Statement s = sIter.nextStatement();
-                if ( sIter.hasNext() )
-                    throw new TestSetupException("Too many result sets in ASK result");
-                Resource r = s.getSubject();
-                Property p = resultsAsModel.createProperty(ResultSetGraphVocab.getURI() + "boolean");
-
-                boolean x = r.getRequiredProperty(p).getBoolean();
-                if ( x != result )
-                    assertEquals(x, result, ()->"ASK test results do not match");
-            }
-        }
-        return;
-    }
-
     private void printFailedResultSetTest(Query query, QueryExecution qe, ResultSetRewindable qrExpected, ResultSetRewindable qrActual) {
         PrintStream out = System.out;
         out.println();
@@ -419,6 +422,22 @@ public class QueryEvalTest extends AbstractManifestTest {
         out.flush();
     }
 
+    private void printFailedAskTest(Query query, QueryExecution qe, boolean qrExpected, boolean qrActual) {
+        PrintStream out = System.out;
+        out.println();
+        out.println("=======================================");
+        out.println("Failure: " + description());
+        out.println("Query: \n" + query);
+        if ( qe != null && qe.getDataset() != null ) {
+            out.println("Data:");
+            RDFDataMgr.write(out, qe.getDataset(), Lang.TRIG);
+        }
+        out.println("Got: " + qrActual + " --------------------------------");
+        out.println("Expected: " + qrExpected + " -----------------------------");
+        out.println();
+        out.flush();
+    }
+
     private void printFailedModelTest(Query query, Model expected, Model results) {
         PrintWriter out = FileUtils.asPrintWriterUTF8(System.out);
         out.println("=======================================");


(jena) 02/06: Restore using prefixes for text output

Posted by an...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git

commit f5a3dfb9cc839e525bcd9b80acf770381638588d
Author: Andy Seaborne <an...@apache.org>
AuthorDate: Tue Dec 30 19:02:06 2025 +0000

    Restore using prefixes for text output
---
 .../apache/jena/sparql/util/QueryExecUtils.java    | 167 ++++++++++-----------
 1 file changed, 83 insertions(+), 84 deletions(-)

diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/QueryExecUtils.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/QueryExecUtils.java
index d90d152e86..a51ab6e000 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/util/QueryExecUtils.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/QueryExecUtils.java
@@ -16,56 +16,56 @@
  * limitations under the License.
  */
 
-package org.apache.jena.sparql.util ;
+package org.apache.jena.sparql.util;
 
 import java.io.OutputStream;
 import java.io.PrintStream;
 import java.util.ArrayList;
-import java.util.List ;
+import java.util.List;
 
 import org.apache.jena.atlas.json.JSON;
 import org.apache.jena.atlas.json.JsonArray;
 import org.apache.jena.graph.Graph;
-import org.apache.jena.query.* ;
-import org.apache.jena.rdf.model.Model ;
-import org.apache.jena.rdf.model.RDFNode ;
-import org.apache.jena.riot.Lang ;
+import org.apache.jena.query.*;
+import org.apache.jena.rdf.model.Model;
+import org.apache.jena.rdf.model.RDFNode;
+import org.apache.jena.riot.Lang;
 import org.apache.jena.riot.RDFFormat;
 import org.apache.jena.riot.RDFWriter;
 import org.apache.jena.riot.resultset.ResultSetLang;
-import org.apache.jena.shared.PrefixMapping ;
-import org.apache.jena.shared.impl.PrefixMappingImpl ;
-import org.apache.jena.sparql.ARQConstants ;
-import org.apache.jena.sparql.ARQException ;
-import org.apache.jena.sparql.algebra.Algebra ;
-import org.apache.jena.sparql.algebra.Op ;
-import org.apache.jena.sparql.algebra.OpVars ;
-import org.apache.jena.sparql.algebra.op.OpProject ;
-import org.apache.jena.sparql.core.DatasetGraph ;
-import org.apache.jena.sparql.core.Prologue ;
-import org.apache.jena.sparql.core.Var ;
-import org.apache.jena.sparql.engine.QueryIterator ;
+import org.apache.jena.shared.PrefixMapping;
+import org.apache.jena.shared.impl.PrefixMappingImpl;
+import org.apache.jena.sparql.ARQConstants;
+import org.apache.jena.sparql.ARQException;
+import org.apache.jena.sparql.algebra.Algebra;
+import org.apache.jena.sparql.algebra.Op;
+import org.apache.jena.sparql.algebra.OpVars;
+import org.apache.jena.sparql.algebra.op.OpProject;
+import org.apache.jena.sparql.core.DatasetGraph;
+import org.apache.jena.sparql.core.Prologue;
+import org.apache.jena.sparql.core.Var;
+import org.apache.jena.sparql.engine.QueryIterator;
 import org.apache.jena.sparql.engine.ResultSetStream;
 import org.apache.jena.sparql.exec.QueryExec;
 import org.apache.jena.sparql.exec.QueryExecutionAdapter;
 import org.apache.jena.sparql.resultset.RDFOutput;
-import org.apache.jena.sparql.resultset.ResultsFormat ;
+import org.apache.jena.sparql.resultset.ResultsFormat;
 import org.apache.jena.sparql.resultset.ResultsWriter;
 import org.apache.jena.sparql.resultset.SPARQLResult;
 
 /** Some utilities for query processing. */
 public class QueryExecUtils {
-    protected static PrefixMapping globalPrefixMap = new PrefixMappingImpl() ;
+    protected static PrefixMapping globalPrefixMap = new PrefixMappingImpl();
     static {
-        globalPrefixMap.setNsPrefix("rdf",  ARQConstants.rdfPrefix) ;
-        globalPrefixMap.setNsPrefix("rdfs", ARQConstants.rdfsPrefix) ;
-        globalPrefixMap.setNsPrefix("xsd",  ARQConstants.xsdPrefix) ;
-        globalPrefixMap.setNsPrefix("owl" , ARQConstants.owlPrefix) ;
-        globalPrefixMap.setNsPrefix("ex" ,  "http://example.org/") ;
-        globalPrefixMap.setNsPrefix("ns" ,  "http://example.org/ns#") ;
-        globalPrefixMap.setNsPrefix("" ,    "http://example/") ;
+        globalPrefixMap.setNsPrefix("rdf",  ARQConstants.rdfPrefix);
+        globalPrefixMap.setNsPrefix("rdfs", ARQConstants.rdfsPrefix);
+        globalPrefixMap.setNsPrefix("xsd",  ARQConstants.xsdPrefix);
+        globalPrefixMap.setNsPrefix("owl" , ARQConstants.owlPrefix);
+        globalPrefixMap.setNsPrefix("ex" ,  "http://example.org/");
+        globalPrefixMap.setNsPrefix("ns" ,  "http://example.org/ns#");
+        globalPrefixMap.setNsPrefix("" ,    "http://example/");
     }
-    protected static Prologue      dftPrologue     = new Prologue(globalPrefixMap) ;
+    protected static Prologue      dftPrologue     = new Prologue(globalPrefixMap);
 
     public static void exec(Query query, DatasetGraph dsg) {
         QueryExec qExec = QueryExec.dataset(dsg).query(query).build();
@@ -78,11 +78,11 @@ public class QueryExecUtils {
     }
 
     public static void exec(QueryExec queryExec) {
-        exec(queryExec.getQuery(), queryExec) ;
+        exec(queryExec.getQuery(), queryExec);
     }
 
     public static void exec(Prologue prologue, QueryExec queryExec) {
-        exec(prologue, queryExec, ResultsFormat.TEXT) ;
+        exec(prologue, queryExec, ResultsFormat.TEXT);
     }
 
     public static void exec(Prologue prologue, QueryExec queryExec, ResultsFormat outputFormat) {
@@ -95,11 +95,11 @@ public class QueryExecUtils {
     }
 
     public static void executeQuery(QueryExecution queryExecution) {
-        executeQuery(null, queryExecution) ;
+        executeQuery(null, queryExecution);
     }
 
     public static void executeQuery(Prologue prologue, QueryExecution queryExecution) {
-        executeQuery(prologue, queryExecution, ResultsFormat.TEXT) ;
+        executeQuery(prologue, queryExecution, ResultsFormat.TEXT);
     }
 
     public static void executeQuery(Prologue prologue, QueryExecution queryExecution, ResultsFormat outputFormat) {
@@ -107,30 +107,30 @@ public class QueryExecUtils {
     }
 
     public static void executeQuery(Prologue prologue, QueryExecution queryExecution, ResultsFormat outputFormat, OutputStream output) {
-        Query query = queryExecution.getQuery() ;
+        Query query = queryExecution.getQuery();
         if ( prologue == null && query != null )
-            prologue = query.getPrologue() ;
+            prologue = query.getPrologue();
         if ( prologue == null )
-            prologue = dftPrologue ;
+            prologue = dftPrologue;
         if ( query.isSelectType() )
-            doSelectQuery(prologue, queryExecution, outputFormat, output) ;
+            doSelectQuery(prologue, queryExecution, outputFormat, output);
         else if ( query.isDescribeType() )
-            doDescribeQuery(prologue, queryExecution, outputFormat, output) ;
+            doDescribeQuery(prologue, queryExecution, outputFormat, output);
         else if ( query.isConstructQuad() )
             // Before isConstructType.
-            doConstructQuadsQuery(prologue, queryExecution, outputFormat, output) ;
+            doConstructQuadsQuery(prologue, queryExecution, outputFormat, output);
         else if ( query.isConstructType() )
-            doConstructQuery(prologue, queryExecution, outputFormat, output) ;
+            doConstructQuery(prologue, queryExecution, outputFormat, output);
         else if ( query.isAskType() )
-            doAskQuery(prologue, queryExecution, outputFormat, output) ;
+            doAskQuery(prologue, queryExecution, outputFormat, output);
         else if ( query.isJsonType() )
-            doJsonQuery(prologue, queryExecution, outputFormat, output) ;
+            doJsonQuery(prologue, queryExecution, outputFormat, output);
         else
             throw new QueryException("Unrecognized query form");
     }
 
     public static void execute(Op op, DatasetGraph dsg) {
-        execute(op, dsg, ResultsFormat.TEXT) ;
+        execute(op, dsg, ResultsFormat.TEXT);
     }
 
     public static void execute(Op op, DatasetGraph dsg, ResultsFormat outputFormat) {
@@ -138,21 +138,20 @@ public class QueryExecUtils {
     }
 
     public static void execute(Op op, DatasetGraph dsg, ResultsFormat outputFormat, OutputStream output) {
-        QueryIterator qIter = Algebra.exec(op, dsg) ;
+        QueryIterator qIter = Algebra.exec(op, dsg);
 
-        List<Var> vars = null ;
+        List<Var> vars = null;
         if ( op instanceof OpProject )
-            vars = ((OpProject)op).getVars() ;
+            vars = ((OpProject)op).getVars();
         else
             // The variables defined in patterns (not Filters, nor NOT EXISTS,
             // nor ORDER BY)
-            vars = new ArrayList<>(OpVars.visibleVars(op)) ;
+            vars = new ArrayList<>(OpVars.visibleVars(op));
 
-        ResultSet results = ResultSetStream.create(vars, qIter) ;
-        outputResultSet(results, null, outputFormat, output) ;
+        ResultSet results = ResultSetStream.create(vars, qIter);
+        outputResultSet(results, null, outputFormat, output);
     }
 
-
     public static void output(SPARQLResult result, ResultsFormat outputFormat, OutputStream output) {
         if ( result.isResultSet() ) {
             ResultSet rs = result.getResultSet();
@@ -180,10 +179,10 @@ public class QueryExecUtils {
 
     public static void outputResultSet(ResultSet resultSet, Prologue prologue, ResultsFormat outputFormat, OutputStream output) {
         if ( prologue == null )
-            prologue = new Prologue(globalPrefixMap) ;
+            prologue = new Prologue(globalPrefixMap);
 
         if ( outputFormat == ResultsFormat.TEXT ) {
-            ResultSetFormatter.out(output, resultSet);
+            ResultSetFormatter.out(output, resultSet,prologue.getPrefixMapping());
             return;
         }
 
@@ -212,16 +211,16 @@ public class QueryExecUtils {
         if ( prologue != null )
             context.set(ARQConstants.symPrologue, prologue);
         ResultsWriter.create().context(context).lang(rsLang).build().write(output, resultSet);
-        return ;
+        return;
     }
 
     private static void doSelectQuery(Prologue prologue, QueryExecution qe, ResultsFormat outputFormat, OutputStream output) {
         if ( prologue == null )
-            prologue = qe.getQuery().getPrologue() ;
+            prologue = qe.getQuery().getPrologue();
         if ( outputFormat == null )
             outputFormat = ResultsFormat.TEXT;
-        ResultSet results = qe.execSelect() ;
-        outputResultSet(results, prologue, outputFormat, output) ;
+        ResultSet results = qe.execSelect();
+        outputResultSet(results, prologue, outputFormat, output);
     }
 
     private static void doJsonQuery(Prologue prologue, QueryExecution queryExecution, ResultsFormat outputFormat, OutputStream output) {
@@ -230,8 +229,8 @@ public class QueryExecUtils {
     }
 
     private static void doDescribeQuery(Prologue prologue, QueryExecution qe, ResultsFormat outputFormat, OutputStream output) {
-        Model r = qe.execDescribe() ;
-        writeModel(r, outputFormat, output) ;
+        Model r = qe.execDescribe();
+        writeModel(r, outputFormat, output);
     }
 
     private static void doConstructQuery(Prologue prologue, QueryExecution qe, ResultsFormat outputFormat, OutputStream output) {
@@ -239,17 +238,17 @@ public class QueryExecUtils {
             doConstructQuadsQuery(prologue, qe, outputFormat, output);
             return;
         }
-        Model r = qe.execConstruct() ;
-        writeModel(r, outputFormat, output) ;
+        Model r = qe.execConstruct();
+        writeModel(r, outputFormat, output);
     }
 
     private static void doConstructQuadsQuery(Prologue prologue, QueryExecution qe, ResultsFormat outputFormat, OutputStream output) {
         Dataset ds = qe.execConstructDataset();
-        writeDataset(ds, outputFormat, output) ;
+        writeDataset(ds, outputFormat, output);
     }
 
     private static void doAskQuery(Prologue prologue, QueryExecution qe, ResultsFormat outputFormat, OutputStream output) {
-        boolean resultBoolean = qe.execAsk() ;
+        boolean resultBoolean = qe.execAsk();
 
         if ( outputFormat == ResultsFormat.TEXT ) {
             ResultSetFormatter.out(output, resultBoolean);
@@ -291,7 +290,7 @@ public class QueryExecUtils {
      * that one RDFNode
      */
     public static RDFNode getExactlyOne(String qs, Model model) {
-        return getExactlyOne(qs, DatasetFactory.wrap(model)) ;
+        return getExactlyOne(qs, DatasetFactory.wrap(model));
     }
 
     /**
@@ -299,12 +298,12 @@ public class QueryExecUtils {
      * that one RDFNode
      */
     public static RDFNode getExactlyOne(String qs, Dataset ds) {
-        Query q = QueryFactory.create(qs) ;
+        Query q = QueryFactory.create(qs);
         if ( q.getResultVars().size() != 1 )
-            throw new ARQException("getExactlyOne: Must have exactly one result columns") ;
-        String varname = q.getResultVars().get(0) ;
+            throw new ARQException("getExactlyOne: Must have exactly one result columns");
+        String varname = q.getResultVars().get(0);
         try ( QueryExecution qExec = QueryExecutionFactory.create(q, ds) ) {
-            return getExactlyOne(qExec, varname) ;
+            return getExactlyOne(qExec, varname);
         }
     }
 
@@ -314,16 +313,16 @@ public class QueryExecUtils {
      * Use with {@code try ( QueryExecution qExec = ....)}.
      */
     public static RDFNode getExactlyOne(QueryExecution qExec, String varname) {
-        ResultSet rs = qExec.execSelect() ;
+        ResultSet rs = qExec.execSelect();
 
         if ( !rs.hasNext() )
-            throw new ARQException("Not found: var ?" + varname) ;
+            throw new ARQException("Not found: var ?" + varname);
 
-        QuerySolution qs = rs.nextSolution() ;
-        RDFNode r = qs.get(varname) ;
+        QuerySolution qs = rs.nextSolution();
+        RDFNode r = qs.get(varname);
         if ( rs.hasNext() )
-            throw new ARQException("More than one: var ?" + varname) ;
-        return r ;
+            throw new ARQException("More than one: var ?" + varname);
+        return r;
     }
 
     /**
@@ -332,35 +331,35 @@ public class QueryExecUtils {
      * Use with {@code try ( QueryExecution qExec = ....)}.
      */
     public static RDFNode getAtMostOne(QueryExecution qExec, String varname) {
-        ResultSet rs = qExec.execSelect() ;
+        ResultSet rs = qExec.execSelect();
 
         if ( !rs.hasNext() )
-            return null ;
+            return null;
 
-        QuerySolution qs = rs.nextSolution() ;
-        RDFNode r = qs.get(varname) ;
+        QuerySolution qs = rs.nextSolution();
+        RDFNode r = qs.get(varname);
         if ( rs.hasNext() ) {
-            QuerySolution qs2 = rs.next() ;
-            RDFNode r2 = qs2.get(varname) ;
+            QuerySolution qs2 = rs.next();
+            RDFNode r2 = qs2.get(varname);
             if ( rs.hasNext() )
-                throw new ARQException("More than one: var ?" + varname + " -> " + r + ", " + r2 + ", ...") ;
+                throw new ARQException("More than one: var ?" + varname + " -> " + r + ", " + r2 + ", ...");
             else
-                throw new ARQException("Found two matches: var ?" + varname + " -> " + r + ", " + r2) ;
+                throw new ARQException("Found two matches: var ?" + varname + " -> " + r + ", " + r2);
         }
-        return r ;
+        return r;
     }
 
     /**
      * Execute, returning all matches, which may be zero.
      */
     public static List<RDFNode> getAll(QueryExecution qExec, String varname) {
-        ResultSet rs = qExec.execSelect() ;
+        ResultSet rs = qExec.execSelect();
         List<RDFNode> matches = new ArrayList<>();
         rs.forEachRemaining(qs->{
-            RDFNode r = qs.get(varname) ;
+            RDFNode r = qs.get(varname);
             if ( r != null )
                 matches.add(r);
         });
-        return matches ;
+        return matches;
     }
 }


(jena) 06/06: Use -XX:+EnableDynamicAgentLoading for surefire to avoid variable setting

Posted by an...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git

commit 3b2658418c90a23da86e9fb244ca4a9e4bdbf1c8
Author: Andy Seaborne <an...@apache.org>
AuthorDate: Tue Dec 30 21:35:47 2025 +0000

    Use -XX:+EnableDynamicAgentLoading for surefire to avoid variable setting
---
 jena-core/pom.xml                     | 4 ++++
 jena-extras/jena-querybuilder/pom.xml | 3 ++-
 jena-fuseki2/jena-fuseki-core/pom.xml | 3 ++-
 3 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/jena-core/pom.xml b/jena-core/pom.xml
index 6c2bd867ea..d11d60b14f 100644
--- a/jena-core/pom.xml
+++ b/jena-core/pom.xml
@@ -151,7 +151,11 @@
           </dependency>
         </dependencies>
         <configuration>
+          <!-- One possibility
           <argLine>-javaagent:${org.mockito:mockito-core:jar} -Xshare:off</argLine>
+          -->
+          <!-- Without needing ${org.mockito:mockito-core:jar} -->
+          <argLine>-XX:+EnableDynamicAgentLoading -Xshare:off</argLine>
           <includes>
             <include>org/apache/jena/test/JenaCoreTestAll.java</include>
           </includes>
diff --git a/jena-extras/jena-querybuilder/pom.xml b/jena-extras/jena-querybuilder/pom.xml
index 60c5b8246d..dda1cc395d 100644
--- a/jena-extras/jena-querybuilder/pom.xml
+++ b/jena-extras/jena-querybuilder/pom.xml
@@ -93,7 +93,8 @@
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
-          <argLine>@{argLine} -javaagent:${org.mockito:mockito-core:jar} -Xshare:off</argLine>
+          <!--<argLine>@{argLine} -javaagent:${org.mockito:mockito-core:jar} -Xshare:off</argLine>-->
+          <argLine>@{argLine} -XX:+EnableDynamicAgentLoading -Xshare:off</argLine>
         </configuration>
       </plugin>
       <plugin>
diff --git a/jena-fuseki2/jena-fuseki-core/pom.xml b/jena-fuseki2/jena-fuseki-core/pom.xml
index 5296f67b6c..1df7dc45c6 100644
--- a/jena-fuseki2/jena-fuseki-core/pom.xml
+++ b/jena-fuseki2/jena-fuseki-core/pom.xml
@@ -166,7 +166,8 @@
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
         <configuration>
-          <argLine>@{argLine} -javaagent:${org.mockito:mockito-core:jar} -Xshare:off</argLine>
+          <!--<argLine>@{argLine} -javaagent:${org.mockito:mockito-core:jar} -Xshare:off</argLine>-->
+          <argLine>@{argLine} -XX:+EnableDynamicAgentLoading -Xshare:off</argLine>
           <includes>
             <include>**/TS_*.java</include>
           </includes>


(jena) 03/06: GH-3674: Fix ROUND()

Posted by an...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git

commit ca1ec6cfedf3563df598b79565f0dbcd4f6de754
Author: Andy Seaborne <an...@apache.org>
AuthorDate: Tue Dec 30 19:04:31 2025 +0000

    GH-3674: Fix ROUND()
---
 .../org/apache/jena/sparql/util/XSDNumUtils.java   |  20 +-
 .../apache/jena/sparql/expr/TestFunctions2.java    | 323 ++++++++++-----------
 .../org/apache/jena/sparql/expr/TestXSDFuncOp.java |  98 +++++++
 3 files changed, 267 insertions(+), 174 deletions(-)

diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/XSDNumUtils.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/XSDNumUtils.java
index aa884ce0ca..91d6a3fdb5 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/util/XSDNumUtils.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/XSDNumUtils.java
@@ -20,6 +20,9 @@ package org.apache.jena.sparql.util;
 
 import java.math.BigDecimal;
 
+import org.apache.jena.sparql.expr.ExprEvalException;
+import org.apache.jena.sparql.expr.NodeValue;
+
 public class XSDNumUtils {
 
     /**
@@ -35,7 +38,7 @@ public class XSDNumUtils {
             case "+INF", "+inf" -> Double.POSITIVE_INFINITY;
             case "-INF", "-inf" -> Double.NEGATIVE_INFINITY;
             case "NaN"          -> Double.NaN ;
-            // Acceptable as Java doubles (value is "NaN" but not as xsd:double
+            // Acceptable as Java doubles (value is "NaN" but not as xsd:double)
             case "-NaN"-> throw new NumberFormatException("-NaN is not valid as an xsd:double");
             case "+NaN"-> throw new NumberFormatException("+NaN is not valid as an xsd:double");
             // Includes +0 and -0.
@@ -64,6 +67,20 @@ public class XSDNumUtils {
         };
     }
 
+    /**
+     * isNaN() - for xsd:double and xsd:float.
+     * The argument must be numeric; if not, this function throws {@link ExprEvalException}.
+     */
+    public static boolean isNaN(NodeValue nv) {
+        if ( ! nv.isNumber() )
+            throw new ExprEvalException("Not a numeric datatype");
+        if ( nv.isDouble() )
+            return Double.isNaN(nv.getDouble());
+        if ( nv.isFloat() )
+            return Float.isNaN(nv.getFloat());
+        return false;
+    }
+
     /** Parse an XSD decimal. */
     public static BigDecimal xsdParseDecimal(String lexicalForm) {
         return new BigDecimal(lexicalForm);
@@ -120,7 +137,6 @@ public class XSDNumUtils {
         return canonicalDecimalStrWithDot(bd);
     }
 
-
     /**
      * Strict XSD 1.0 format for {@code xsd:decimal}.
      * <p>
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestFunctions2.java b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestFunctions2.java
index 6b72e2ff78..44b5ef44e1 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestFunctions2.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestFunctions2.java
@@ -19,13 +19,14 @@
 package org.apache.jena.sparql.expr;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 
+import org.apache.jena.datatypes.RDFDatatype;
 import org.apache.jena.graph.Node;
 import org.apache.jena.shared.PrefixMapping;
 import org.apache.jena.sparql.ARQConstants;
@@ -91,61 +92,68 @@ public class TestFunctions2
     // Any same value would do - we test for the exact lexical form
     // of the implementation.
 
-    @Test public void round_01()    { test("round(123)",    "123"); }
-    @Test public void round_02()    { test("round(123.5)",  "'124.0'^^xsd:decimal"); }
-    @Test public void round_03()    { test("round(-0.5e0)", "0.0e0"); }
-    @Test public void round_04()    { test("round(-1.5)",   "'-1.0'^^xsd:decimal"); }
-    @Test public void round_05()    { test("round(-0)",     "-0"); }
-
-    @Test public void abs_01()    { test("abs(1)",      "1"); }
-    @Test public void abs_02()    { test("abs(1.0)",    "1.0"); }
-    @Test public void abs_03()    { test("abs(1.0e0)",  "1.0e0"); }
-    @Test public void abs_04()    { test("abs(-1)",     "1"); }
-    @Test public void abs_05()    { test("abs(+0)",     "0"); }
-    @Test public void abs_06()    { test("abs(-0)",     "0"); }
+    // ROUND
+    @Test public void round_01()  { test("round(123)",    "123"); }
+    @Test public void round_02()  { test("round(123.5)",  "'124.0'^^xsd:decimal"); }
+    @Test public void round_03()  { test("round(-0.5e0)", "-0.0e0"); }
+    @Test public void round_04()  { test("round(-1.5)",   "'-1.0'^^xsd:decimal"); }
+    @Test public void round_05()  { test("round(-0)",     "-0"); }
+
+    @Test public void round_10()  { test("round('NaN'^^xsd:double)",    "'NaN'^^xsd:double"); }
+    @Test public void round_11()  { test("round('NaN'^^xsd:float)",     "'NaN'^^xsd:float"); }
+    @Test public void round_12()  { test("round('-0'^^xsd:double)",     "'-0.0e0'^^xsd:double"); }
+    @Test public void round_13()  { test("round('-0'^^xsd:float)",      "'-0.0'^^xsd:float"); }
+    @Test public void round_14()  { test("round('-0'^^xsd:double)",     "'-0.0e0'^^xsd:double"); }
+
+    @Test public void abs_01()    { test("abs(1)",        "1"); }
+    @Test public void abs_02()    { test("abs(1.0)",      "1.0"); }
+    @Test public void abs_03()    { test("abs(1.0e0)",    "1.0e0"); }
+    @Test public void abs_04()    { test("abs(-1)",       "1"); }
+    @Test public void abs_05()    { test("abs(+0)",       "0"); }
+    @Test public void abs_06()    { test("abs(-0)",       "0"); }
 
     // CEIL
-    @Test public void ceil_01()    { test("ceil(1)",        "1"); }
-    @Test public void ceil_02()    { test("ceil(1.0)",      "'1.0'^^xsd:decimal"); }
-    @Test public void ceil_03()    { test("ceil(1e0)",      "1.0e0"); }
-    @Test public void ceil_04()    { test("ceil(1.5e0)",    "2.0e0"); }
-    @Test public void ceil_05()    { test("ceil(-0.9)",     "'0.0'^^xsd:decimal"); }
-    @Test public void ceil_06()    { test("ceil(-9)",       "-9"); }
-    @Test public void ceil_07()    { test("ceil(-9.5)",     "'-9.0'^^xsd:decimal"); }
-    @Test public void ceil_08()    { test("ceil(0)",        "0"); }
+    @Test public void ceil_01()   { test("ceil(1)",       "1"); }
+    @Test public void ceil_02()   { test("ceil(1.0)",     "'1.0'^^xsd:decimal"); }
+    @Test public void ceil_03()   { test("ceil(1e0)",     "1.0e0"); }
+    @Test public void ceil_04()   { test("ceil(1.5e0)",   "2.0e0"); }
+    @Test public void ceil_05()   { test("ceil(-0.9)",    "'0.0'^^xsd:decimal"); }
+    @Test public void ceil_06()   { test("ceil(-9)",      "-9"); }
+    @Test public void ceil_07()   { test("ceil(-9.5)",    "'-9.0'^^xsd:decimal"); }
+    @Test public void ceil_08()   { test("ceil(0)",       "0"); }
 
     // FLOOR
-    @Test public void floor_01()    { test("floor(1)",      "1"); }
-    @Test public void floor_02()    { test("floor(1.0)",    "'1.0'^^xsd:decimal"); }
-    @Test public void floor_03()    { test("floor(1e0)",    "1.0e0"); }
-    @Test public void floor_04()    { test("floor(1.5e0)",  "1.0e0"); }
-    @Test public void floor_05()    { test("floor(-0.9)",   "'-1.0'^^xsd:decimal"); }
-    @Test public void floor_06()    { test("floor(-9)",     "-9"); }
-    @Test public void floor_07()    { test("floor(-9.5)",   "'-10.0'^^xsd:decimal"); }
-    @Test public void floor_08()    { test("floor(0)",      "0"); }
+    @Test public void floor_01()  { test("floor(1)",      "1"); }
+    @Test public void floor_02()  { test("floor(1.0)",    "'1.0'^^xsd:decimal"); }
+    @Test public void floor_03()  { test("floor(1e0)",    "1.0e0"); }
+    @Test public void floor_04()  { test("floor(1.5e0)",  "1.0e0"); }
+    @Test public void floor_05()  { test("floor(-0.9)",   "'-1.0'^^xsd:decimal"); }
+    @Test public void floor_06()  { test("floor(-9)",     "-9"); }
+    @Test public void floor_07()  { test("floor(-9.5)",   "'-10.0'^^xsd:decimal"); }
+    @Test public void floor_08()  { test("floor(0)",      "0"); }
 
-    // simple, PLWL, xsd:string.
 
     // CONCAT
-    @Test public void concat_01()   { test("concat('a')",       "'a'"); }
-    @Test public void concat_02()   { test("concat('a', 'b')",  "'ab'"); }
-    @Test public void concat_03()   { test("concat('a'@en, 'b')",  "'ab'"); }
-    @Test public void concat_04()   { test("concat('a'@en, 'b'@en)",  "'ab'@en"); }
-    //@Test public void concat_05()   { test("concat('a'^^xsd:string, 'b')",  "'ab'^^xsd:string"); }
-    @Test public void concat_05()   { test("concat('a'^^xsd:string, 'b')",  "'ab'"); }
-    @Test public void concat_06()   { test("concat('a'^^xsd:string, 'b'^^xsd:string)",  "'ab'^^xsd:string"); }
-    @Test public void concat_07()   { test("concat('a'^^xsd:string, 'b'^^xsd:string)",  "'ab'^^xsd:string"); }
+    @Test public void concat_00()    { test("concat()",       "''"); }
+    @Test public void concat_01()    { test("concat('a')",       "'a'"); }
+    @Test public void concat_02()    { test("concat('a', 'b')",  "'ab'"); }
+    @Test public void concat_03()    { test("concat('a'@en, 'b')",  "'ab'"); }
+    @Test public void concat_04()    { test("concat('a'@en, 'b'@en)",  "'ab'@en"); }
+    //@Test public void concat_05()    { test("concat('a'^^xsd:string, 'b')",  "'ab'^^xsd:string"); }
+    @Test public void concat_05()    { test("concat('a'^^xsd:string, 'b')",  "'ab'"); }
+    @Test public void concat_06()    { test("concat('a'^^xsd:string, 'b'^^xsd:string)",  "'ab'^^xsd:string"); }
+    @Test public void concat_07()    { test("concat('a'^^xsd:string, 'b'^^xsd:string)",  "'ab'^^xsd:string"); }
     //@Test public void concat_08()   { test("concat('a', 'b'^^xsd:string)",  "'ab'^^xsd:string"); }
-    @Test public void concat_08()   { test("concat('a', 'b'^^xsd:string)",  "'ab'"); }
-    @Test public void concat_09()   { test("concat('a'@en, 'b'^^xsd:string)",  "'ab'"); }
-    @Test public void concat_10()   { test("concat('a'^^xsd:string, 'b'@en)",  "'ab'"); }
-    @Test public void concat_11()   { test("concat()",  "''"); }
+    @Test public void concat_08()    { test("concat('a', 'b'^^xsd:string)",  "'ab'"); }
+    @Test public void concat_09()    { test("concat('a'@en, 'b'^^xsd:string)",  "'ab'"); }
+    @Test public void concat_10()    { test("concat('a'^^xsd:string, 'b'@en)",  "'ab'"); }
+    @Test public void concat_11()    { test("concat()",  "''"); }
 
     @Test
     public void concat_90()          { assertThrows(ExprEvalException.class, ()-> test("concat(1)",      "1") ); }
 
     @Test
-    public void concat_91()         { test("concat('a'@en, 'b'@fr)",  "'ab'"); }
+    public void concat_91()          { test("concat('a'@en, 'b'@fr)",  "'ab'"); }
 
     // SUBSTR
     @Test public void substr_01()    { test("substr('abc',1)",      "'abc'"); }
@@ -156,15 +164,15 @@ public class TestFunctions2
     @Test public void substr_06()    { test("substr('12345',-1,3)", "'1'"); }
 
     // These are the examples in F&O
-    @Test public void substr_10()   { test("substr('motor car', 6)",      "' car'"); }
-    @Test public void substr_11()   { test("substr('metadata', 4, 3)",    "'ada'"); }
-    @Test public void substr_12()   { test("substr('12345', 1.5, 2.6)",   "'234'"); }
-    @Test public void substr_13()   { test("substr('12345', 0, 3)",       "'12'"); }
-    @Test public void substr_14()   { test("substr('12345', 5, -3)",      "''"); }
-    @Test public void substr_15()   { test("substr('12345', -3, 5)",      "'1'"); }
-    @Test public void substr_16()   { test("substr('12345', 0/0E0, 3)",   "''"); }
-    @Test public void substr_17()   { test("substr('12345', 1, 0/0E0)",   "''"); }
-    @Test public void substr_18()   { test("substr('', 1, 3)",            "''"); }
+    @Test public void substr_10()    { test("substr('motor car', 6)",      "' car'"); }
+    @Test public void substr_11()    { test("substr('metadata', 4, 3)",    "'ada'"); }
+    @Test public void substr_12()    { test("substr('12345', 1.5, 2.6)",   "'234'"); }
+    @Test public void substr_13()    { test("substr('12345', 0, 3)",       "'12'"); }
+    @Test public void substr_14()    { test("substr('12345', 5, -3)",      "''"); }
+    @Test public void substr_15()    { test("substr('12345', -3, 5)",      "'1'"); }
+    @Test public void substr_16()    { test("substr('12345', 0/0E0, 3)",   "''"); }
+    @Test public void substr_17()    { test("substr('12345', 1, 0/0E0)",   "''"); }
+    @Test public void substr_18()    { test("substr('', 1, 3)",            "''"); }
 
     @Test
     public void substr_20()         { assertThrows(ExprEvalException.class, ()-> test("substr(1, 1, 3)",            "''") ); }
@@ -226,35 +234,30 @@ public class TestFunctions2
     */
 
     // CONTAINS
-    @Test public void contains_01()    { test("contains('abc', 'a')", "true"); }
-    @Test public void contains_02()    { test("contains('abc', 'b')", "true"); }
-    @Test public void contains_03()    { test("contains('ABC', 'a')", "false"); }
-    @Test public void contains_04()    { test("contains('abc', '')",  "true"); }
-    @Test public void contains_05()    { test("contains('', '')",     "true"); }
-    @Test public void contains_06()    { test("contains('', 'a')",    "false"); }
-    @Test public void contains_07()    { test("contains('12345', '34')",        "true"); }
-    @Test public void contains_08()    { test("contains('12345', '123456')",    "false"); }
+    @Test public void contains_01()     { test("contains('abc', 'a')", "true"); }
+    @Test public void contains_02()     { test("contains('abc', 'b')", "true"); }
+    @Test public void contains_03()     { test("contains('ABC', 'a')", "false"); }
+    @Test public void contains_04()     { test("contains('abc', '')",  "true"); }
+    @Test public void contains_05()     { test("contains('', '')",     "true"); }
+    @Test public void contains_06()     { test("contains('', 'a')",    "false"); }
+    @Test public void contains_07()     { test("contains('12345', '34')",        "true"); }
+    @Test public void contains_08()     { test("contains('12345', '123456')",    "false"); }
 
-    @Test public void contains_10()    { test("contains('abc', 'a'^^xsd:string)",          "true"); }
-    @Test
-    public void contains_11()    { assertThrows(ExprEvalException.class, ()-> test("contains('abc', 'a'@en)",          "true") ); }
+    @Test public void contains_10()     { test("contains('abc', 'a'^^xsd:string)",          "true"); }
+    @Test public void contains_11()     { assertThrows(ExprEvalException.class, ()-> test("contains('abc', 'a'@en)",          "true") ); }
 
-    @Test public void contains_12()    { test("contains('abc'@en, 'a')",          "true"); }
-    @Test public void contains_13()    { test("contains('abc'@en, 'a'^^xsd:string)",          "true"); }
-    @Test public void contains_14()    { test("contains('abc'@en, 'a'@en)",       "true"); }
-    @Test
-    public void contains_15()          { assertThrows(ExprEvalException.class, ()-> test("contains('abc'@en, 'a'@fr)",       "true") ); }
+    @Test public void contains_12()     { test("contains('abc'@en, 'a')",          "true"); }
+    @Test public void contains_13()     { test("contains('abc'@en, 'a'^^xsd:string)",          "true"); }
+    @Test public void contains_14()     { test("contains('abc'@en, 'a'@en)",       "true"); }
+    @Test public void contains_15()     { assertThrows(ExprEvalException.class, ()-> test("contains('abc'@en, 'a'@fr)",       "true") ); }
 
-    @Test public void contains_16()    { test("contains('abc'^^xsd:string, 'a')", "true"); }
+    @Test public void contains_16()     { test("contains('abc'^^xsd:string, 'a')", "true"); }
 
-    @Test
-    public void contains_17()          { assertThrows(ExprEvalException.class, ()-> test("contains('abc'^^xsd:string, 'a'@en)", "true") ); }
-    @Test public void contains_18()    { test("contains('abc'^^xsd:string, 'a'^^xsd:string)", "true"); }
+    @Test public void contains_17()     { assertThrows(ExprEvalException.class, ()-> test("contains('abc'^^xsd:string, 'a'@en)", "true") ); }
+    @Test public void contains_18()     { test("contains('abc'^^xsd:string, 'a'^^xsd:string)", "true"); }
 
-    @Test
-    public void contains_20()    { assertThrows(ExprEvalException.class, ()-> test("contains(1816, 'a'^^xsd:string)", "true") ); }
-    @Test
-    public void contains_21()    { assertThrows(ExprEvalException.class, ()-> test("contains('abc', 1066)", "true") ); }
+    @Test public void contains_20()     { assertThrows(ExprEvalException.class, ()-> test("contains(1816, 'a'^^xsd:string)", "true") ); }
+    @Test public void contains_21()     { assertThrows(ExprEvalException.class, ()-> test("contains('abc', 1066)", "true") ); }
 
     @Test public void strstarts_01()    { test("strstarts('abc', 'a')", "true"); }
     @Test public void strstarts_02()    { test("strstarts('abc', 'b')", "false"); }
@@ -264,8 +267,7 @@ public class TestFunctions2
     @Test public void strstarts_06()    { test("strstarts('', 'a')",    "false"); }
 
     @Test public void strstarts_10()    { test("strstarts('abc', 'a'^^xsd:string)",          "true"); }
-    @Test
-    public void strstarts_11()    { assertThrows(ExprEvalException.class, ()-> test("strstarts('abc', 'a'@en)",          "true") ); }
+    @Test public void strstarts_11()    { assertThrows(ExprEvalException.class, ()-> test("strstarts('abc', 'a'@en)",          "true") ); }
 
     @Test public void strstarts_12()    { test("strstarts('abc'@en, 'a')",          "true"); }
     @Test public void strstarts_13()    { test("strstarts('abc'@en, 'a'^^xsd:string)",          "true"); }
@@ -279,10 +281,8 @@ public class TestFunctions2
     public void strstarts_17()          { assertThrows(ExprEvalException.class, ()-> test("strstarts('abc'^^xsd:string, 'a'@en)", "true") ); }
     @Test public void strstarts_18()    { test("strstarts('abc'^^xsd:string, 'a'^^xsd:string)", "true"); }
 
-    @Test
-    public void strstarts_20()    { assertThrows(ExprEvalException.class, ()-> test("strstarts(1816, 'a'^^xsd:string)", "true") ); }
-    @Test
-    public void strstarts_21()    { assertThrows(ExprEvalException.class, ()-> test("strstarts('abc', 1066)", "true") ); }
+    @Test public void strstarts_20()    { assertThrows(ExprEvalException.class, ()-> test("strstarts(1816, 'a'^^xsd:string)", "true") ); }
+    @Test public void strstarts_21()    { assertThrows(ExprEvalException.class, ()-> test("strstarts('abc', 1066)", "true") ); }
 
     // STRENDS
     @Test public void strends_01()      { test("strends('abc', 'c')", "true"); }
@@ -293,8 +293,7 @@ public class TestFunctions2
     @Test public void strends_06()      { test("strends('', 'a')",    "false"); }
 
     @Test public void strends_10()      { test("strends('abc', 'c'^^xsd:string)",          "true"); }
-    @Test
-    public void strends11()             { assertThrows(ExprEvalException.class, ()-> test("strends('abc', 'c'@en)",          "true") ); }
+    @Test public void strends11()       { assertThrows(ExprEvalException.class, ()-> test("strends('abc', 'c'@en)",          "true") ); }
 
     @Test public void strends_12()      { test("strends('abc'@en, 'c')",          "true"); }
     @Test public void strends_13()      { test("strends('abc'@en, 'c'^^xsd:string)",          "true"); }
@@ -307,10 +306,8 @@ public class TestFunctions2
     public void strends_17()            { assertThrows(ExprEvalException.class, ()-> test("strends('abc'^^xsd:string, 'a'@en)", "true") ); }
     @Test public void strends_18()      { test("strends('abc'^^xsd:string, 'abc'^^xsd:string)", "true"); }
 
-    @Test
-    public void strends_20()            { assertThrows(ExprEvalException.class, ()-> test("strends(1816, '6'^^xsd:string)", "true") ); }
-    @Test
-    public void strends_21()            { assertThrows(ExprEvalException.class, ()-> test("strends('abc', 1066)", "true") ); }
+    @Test public void strends_20()      { assertThrows(ExprEvalException.class, ()-> test("strends(1816, '6'^^xsd:string)", "true") ); }
+    @Test public void strends_21()      { assertThrows(ExprEvalException.class, ()-> test("strends('abc', 1066)", "true") ); }
 
     // YEAR
     @Test public void year_01()         { test("year('2010-12-24T16:24:01.123'^^xsd:dateTime)", "2010"); }
@@ -436,49 +433,45 @@ public class TestFunctions2
     @Test public void hours_20()        { test("hours('2010-12-24T16:24:01.123-08:00'^^xsd:dateTime)", "16"); }
     @Test public void hours_21()        { test("hours('16:24:24-08:00'^^xsd:time)", "16"); }
 
-    @Test public void hours_dur_01()     { test("hours('P1Y2M3DT4H5M6S'^^xsd:duration)", "4"); }
+    @Test public void hours_dur_01()    { test("hours('P1Y2M3DT4H5M6S'^^xsd:duration)", "4"); }
 
     // MINUTES
-    @Test public void minutes_01()        { test("minutes('2010-12-24T16:24:01.123'^^xsd:dateTime)", "24"); }
-    @Test
-    public void minutes_02()              { assertThrows(ExprEvalException.class, ()-> test("minutes('2010-12-24'^^xsd:date)", "") ); }
-    @Test public void minutes_03()        { test("minutes('16:24:01'^^xsd:time)", "24"); }
+    @Test public void minutes_01()      { test("minutes('2010-12-24T16:24:01.123'^^xsd:dateTime)", "24"); }
+    @Test public void minutes_02()      { assertThrows(ExprEvalException.class, ()-> test("minutes('2010-12-24'^^xsd:date)", "") ); }
+    @Test public void minutes_03()      { test("minutes('16:24:01'^^xsd:time)", "24"); }
 
-    @Test public void minutes_10()        { test("minutes('2010-12-24T16:24:01.123Z'^^xsd:dateTime)", "24"); }
-    @Test public void minutes_11()        { test("minutes('16:24:01.1Z'^^xsd:time)", "24"); }
+    @Test public void minutes_10()      { test("minutes('2010-12-24T16:24:01.123Z'^^xsd:dateTime)", "24"); }
+    @Test public void minutes_11()      { test("minutes('16:24:01.1Z'^^xsd:time)", "24"); }
 
-    @Test public void minutes_20()        { test("minutes('2010-12-24T16:24:01.123-08:00'^^xsd:dateTime)", "24"); }
-    @Test public void minutes_21()        { test("minutes('16:24:01.01-08:00'^^xsd:time)", "24"); }
+    @Test public void minutes_20()      { test("minutes('2010-12-24T16:24:01.123-08:00'^^xsd:dateTime)", "24"); }
+    @Test public void minutes_21()      { test("minutes('16:24:01.01-08:00'^^xsd:time)", "24"); }
 
-    @Test public void minutes_dur_01()    { test("minutes('P1Y2M3DT4H5M6S'^^xsd:duration)", "5"); }
+    @Test public void minutes_dur_01()  { test("minutes('P1Y2M3DT4H5M6S'^^xsd:duration)", "5"); }
 
     // SECONDS
-    @Test public void seconds_01()        { test("seconds('2010-12-24T16:24:01.123'^^xsd:dateTime)", "01.123"); }
+    @Test public void seconds_01()      { test("seconds('2010-12-24T16:24:01.123'^^xsd:dateTime)", "01.123"); }
     @Test
-    public void seconds_02()              { assertThrows(ExprEvalException.class, ()-> test("seconds('2010-12-24'^^xsd:date)", "") ); }
-    @Test public void seconds_03()        { test("seconds('16:24:01'^^xsd:time)", "'01'^^xsd:decimal"); }
+    public void seconds_02()            { assertThrows(ExprEvalException.class, ()-> test("seconds('2010-12-24'^^xsd:date)", "") ); }
+    @Test public void seconds_03()      { test("seconds('16:24:01'^^xsd:time)", "'01'^^xsd:decimal"); }
 
-    @Test public void seconds_10()        { test("seconds('2010-12-24T16:24:31.123Z'^^xsd:dateTime)", "31.123"); }
-    @Test public void seconds_11()        { test("seconds('16:24:01.1Z'^^xsd:time)", "'01.1'^^xsd:decimal"); }
+    @Test public void seconds_10()      { test("seconds('2010-12-24T16:24:31.123Z'^^xsd:dateTime)", "31.123"); }
+    @Test public void seconds_11()      { test("seconds('16:24:01.1Z'^^xsd:time)", "'01.1'^^xsd:decimal"); }
 
-    @Test public void seconds_20()        { test("seconds('2010-12-24T16:24:35.123-08:00'^^xsd:dateTime)", "35.123"); }
-    @Test public void seconds_21()        { test("seconds('16:24:01.01-08:00'^^xsd:time)", "'01.01'^^xsd:decimal"); }
+    @Test public void seconds_20()      { test("seconds('2010-12-24T16:24:35.123-08:00'^^xsd:dateTime)", "35.123"); }
+    @Test public void seconds_21()      { test("seconds('16:24:01.01-08:00'^^xsd:time)", "'01.01'^^xsd:decimal"); }
 
-    @Test public void seconds_dur_01()    { test("seconds('P1Y2M3DT4H5M6S'^^xsd:duration)", "'6.0'^^xsd:decimal"); }
+    @Test public void seconds_dur_01()  { test("seconds('P1Y2M3DT4H5M6S'^^xsd:duration)", "'6.0'^^xsd:decimal"); }
 
     // TIMEZONE
-    @Test public void timezone_01()       { test("timezone('2010-12-24T16:24:35.123Z'^^xsd:dateTime)", "'PT0S'^^xsd:dayTimeDuration"); }
-    @Test public void timezone_02()       { test("timezone('2010-12-24T16:24:35.123-08:00'^^xsd:dateTime)", "'-PT8H'^^xsd:dayTimeDuration"); }
-    @Test public void timezone_03()       { test("timezone('2010-12-24T16:24:35.123+01:00'^^xsd:dateTime)", "'PT1H'^^xsd:dayTimeDuration"); }
-    @Test public void timezone_04()       { test("timezone('2010-12-24T16:24:35.123-00:00'^^xsd:dateTime)", "'-PT0S'^^xsd:dayTimeDuration"); }
-    @Test public void timezone_05()       { test("timezone('2010-12-24T16:24:35.123+00:00'^^xsd:dateTime)", "'PT0S'^^xsd:dayTimeDuration"); }
+    @Test public void timezone_01()     { test("timezone('2010-12-24T16:24:35.123Z'^^xsd:dateTime)", "'PT0S'^^xsd:dayTimeDuration"); }
+    @Test public void timezone_02()     { test("timezone('2010-12-24T16:24:35.123-08:00'^^xsd:dateTime)", "'-PT8H'^^xsd:dayTimeDuration"); }
+    @Test public void timezone_03()     { test("timezone('2010-12-24T16:24:35.123+01:00'^^xsd:dateTime)", "'PT1H'^^xsd:dayTimeDuration"); }
+    @Test public void timezone_04()     { test("timezone('2010-12-24T16:24:35.123-00:00'^^xsd:dateTime)", "'-PT0S'^^xsd:dayTimeDuration"); }
+    @Test public void timezone_05()     { test("timezone('2010-12-24T16:24:35.123+00:00'^^xsd:dateTime)", "'PT0S'^^xsd:dayTimeDuration"); }
 
-    @Test
-    public void timezone_09()             { assertThrows(ExprEvalException.class, ()-> test("timezone('2010-12-24T16:24:35'^^xsd:dateTime)", "'PT0S'^^xsd:dayTimeDuration") ); }
-    @Test
-    public void timezone_10()             { assertThrows(ExprEvalException.class, ()-> test("timezone(2010)", "'PT0S'^^xsd:dayTimeDuration") ); }
-    @Test
-    public void timezone_11()             { assertThrows(ExprEvalException.class, ()-> test("timezone('2010-junk'^^xsd:gYear)", "'PT0S'^^xsd:dayTimeDuration") ); }
+    @Test public void timezone_09()     { assertThrows(ExprEvalException.class, ()-> test("timezone('2010-12-24T16:24:35'^^xsd:dateTime)", "'PT0S'^^xsd:dayTimeDuration") ); }
+    @Test public void timezone_10()     { assertThrows(ExprEvalException.class, ()-> test("timezone(2010)", "'PT0S'^^xsd:dayTimeDuration") ); }
+    @Test public void timezone_11()     { assertThrows(ExprEvalException.class, ()-> test("timezone('2010-junk'^^xsd:gYear)", "'PT0S'^^xsd:dayTimeDuration") ); }
 
     // General "adjust-to-timezone"
     @Test public void adjust_1() {
@@ -503,40 +496,32 @@ public class TestFunctions2
 
 
     // TZ
-    @Test public void tz_01()             { test("tz('2010-12-24T16:24:35.123Z'^^xsd:dateTime)", "'Z'"); }
-    @Test public void tz_02()             { test("tz('2010-12-24T16:24:35.123-08:00'^^xsd:dateTime)", "'-08:00'"); }
-    @Test public void tz_03()             { test("tz('2010-12-24T16:24:35.123+01:00'^^xsd:dateTime)", "'+01:00'"); }
-    @Test public void tz_04()             { test("tz('2010-12-24T16:24:35.123-00:00'^^xsd:dateTime)", "'-00:00'"); }
-    @Test public void tz_05()             { test("tz('2010-12-24T16:24:35.123+00:00'^^xsd:dateTime)", "'+00:00'"); }
-    @Test public void tz_06()             { test("tz('2010-12-24T16:24:35.123'^^xsd:dateTime)", "''"); }
+    @Test public void tz_01()           { test("tz('2010-12-24T16:24:35.123Z'^^xsd:dateTime)", "'Z'"); }
+    @Test public void tz_02()           { test("tz('2010-12-24T16:24:35.123-08:00'^^xsd:dateTime)", "'-08:00'"); }
+    @Test public void tz_03()           { test("tz('2010-12-24T16:24:35.123+01:00'^^xsd:dateTime)", "'+01:00'"); }
+    @Test public void tz_04()           { test("tz('2010-12-24T16:24:35.123-00:00'^^xsd:dateTime)", "'-00:00'"); }
+    @Test public void tz_05()           { test("tz('2010-12-24T16:24:35.123+00:00'^^xsd:dateTime)", "'+00:00'"); }
+    @Test public void tz_06()           { test("tz('2010-12-24T16:24:35.123'^^xsd:dateTime)", "''"); }
 
-    @Test
-					 public void tz_10()                   { assertThrows(ExprEvalException.class, ()-> test("tz(2010)", "''") ); }
-    @Test
-					 public void tz_11()                   { assertThrows(ExprEvalException.class, ()-> test("tz('2010-junk'^^xsd:gYear)", "''") ); }
+    @Test public void tz_10()           { assertThrows(ExprEvalException.class, ()-> test("tz(2010)", "''") ); }
+    @Test public void tz_11()           { assertThrows(ExprEvalException.class, ()-> test("tz('2010-junk'^^xsd:gYear)", "''") ); }
 
     // NOW
     //@Test public void now_01()        { test("now() > '2010-12-24T16:24:35.123-08:00'^^xsd:dateTime", "true"); }
 
-
     // MD5
-    @Test public void md5_01()      { test("md5('abcd')","'e2fc714c4727ee9395f324cd2e7f331f'"); }
-    @Test public void md5_02()            { test("md5('abcd'^^xsd:string)","'e2fc714c4727ee9395f324cd2e7f331f'"); }
-    @Test
-					 public void md5_03()            { assertThrows(ExprEvalException.class, ()-> test("md5('abcd'@en)","'e2fc714c4727ee9395f324cd2e7f331f'") ); }
-    @Test
-					 public void md5_04()            { assertThrows(ExprEvalException.class, ()-> test("md5(1234)","'e2fc714c4727ee9395f324cd2e7f331f'") ); }
+    @Test public void md5_01()          { test("md5('abcd')","'e2fc714c4727ee9395f324cd2e7f331f'"); }
+    @Test public void md5_02()          { test("md5('abcd'^^xsd:string)","'e2fc714c4727ee9395f324cd2e7f331f'"); }
+    @Test public void md5_03()          { assertThrows(ExprEvalException.class, ()-> test("md5('abcd'@en)","'e2fc714c4727ee9395f324cd2e7f331f'") ); }
+    @Test public void md5_04()          { assertThrows(ExprEvalException.class, ()-> test("md5(1234)","'e2fc714c4727ee9395f324cd2e7f331f'") ); }
 
     // SHA1
+    @Test public void sha1_01()         { test("sha1('abcd')","'81fe8bfe87576c3ecb22426f8e57847382917acf'"); }
+    @Test public void sha1_02()         { test("sha1('abcd'^^xsd:string)","'81fe8bfe87576c3ecb22426f8e57847382917acf'"); }
+    @Test public void sha1_03()         { assertThrows(ExprEvalException.class, ()-> test("sha1('abcd'@en)","'81fe8bfe87576c3ecb22426f8e57847382917acf'") ); }
+    @Test public void sha1_04()         { assertThrows(ExprEvalException.class, ()-> test("sha1(123)","'81fe8bfe87576c3ecb22426f8e57847382917acf'") ); }
 
-    @Test public void sha1_01()      { test("sha1('abcd')","'81fe8bfe87576c3ecb22426f8e57847382917acf'"); }
-    @Test public void sha1_02()      { test("sha1('abcd'^^xsd:string)","'81fe8bfe87576c3ecb22426f8e57847382917acf'"); }
-    @Test
-					 public void sha1_03()            { assertThrows(ExprEvalException.class, ()-> test("sha1('abcd'@en)","'81fe8bfe87576c3ecb22426f8e57847382917acf'") ); }
-    @Test
-					 public void sha1_04()            { assertThrows(ExprEvalException.class, ()-> test("sha1(123)","'81fe8bfe87576c3ecb22426f8e57847382917acf'") ); }
-
-    // SHA224
+//    // SHA224
 //    @Test public void sha224_01()      { test("sha224('abcd')","'e2fc714c4727ee9395f324cd2e7f331f'"); }
 //
 //    @Test
@@ -550,49 +535,43 @@ public class TestFunctions2
 
     // SHA256
 
-    @Test public void sha256_01()      { test("sha256('abcd')","'88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589'"); }
-
-    @Test public void sha256_02()      { test("sha256('abcd'^^xsd:string)","'88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589'"); }
-
-    @Test
-					 public void sha256_03()            { assertThrows(ExprEvalException.class, ()-> test("sha256('abcd'@en)","'88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589'") ); }
-
-    @Test
-					 public void sha256_04()            { assertThrows(ExprEvalException.class, ()-> test("sha256(<uri>)","'88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589'") ); }
+    @Test public void sha256_01()       { test("sha256('abcd')","'88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589'"); }
+    @Test public void sha256_02()       { test("sha256('abcd'^^xsd:string)","'88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589'"); }
+    @Test public void sha256_03()       { assertThrows(ExprEvalException.class, ()-> test("sha256('abcd'@en)","'88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589'") ); }
+    @Test public void sha256_04()       { assertThrows(ExprEvalException.class, ()-> test("sha256(<uri>)","'88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589'") ); }
 
     // SHA384
-    @Test public void sha384_01()      { test("sha384('abcd')","'1165b3406ff0b52a3d24721f785462ca2276c9f454a116c2b2ba20171a7905ea5a026682eb659c4d5f115c363aa3c79b'"); }
-
-
-    @Test public void sha384_02()      { test("sha384('abcd'^^xsd:string)","'1165b3406ff0b52a3d24721f785462ca2276c9f454a116c2b2ba20171a7905ea5a026682eb659c4d5f115c363aa3c79b'"); }
-
-    @Test
-					 public void sha384_03()            { assertThrows(ExprEvalException.class, ()-> test("sha384('abcd'@en)","'1165b3406ff0b52a3d24721f785462ca2276c9f454a116c2b2ba20171a7905ea5a026682eb659c4d5f115c363aa3c79b'") ); }
-
-    @Test
-					 public void sha384_04()            { assertThrows(ExprEvalException.class, ()-> test("sha384(123.45)","'1165b3406ff0b52a3d24721f785462ca2276c9f454a116c2b2ba20171a7905ea5a026682eb659c4d5f115c363aa3c79b'") ); }
+    @Test public void sha384_01()       { test("sha384('abcd')","'1165b3406ff0b52a3d24721f785462ca2276c9f454a116c2b2ba20171a7905ea5a026682eb659c4d5f115c363aa3c79b'"); }
+    @Test public void sha384_02()       { test("sha384('abcd'^^xsd:string)","'1165b3406ff0b52a3d24721f785462ca2276c9f454a116c2b2ba20171a7905ea5a026682eb659c4d5f115c363aa3c79b'"); }
+    @Test public void sha384_03()       { assertThrows(ExprEvalException.class, ()-> test("sha384('abcd'@en)","'1165b3406ff0b52a3d24721f785462ca2276c9f454a116c2b2ba20171a7905ea5a026682eb659c4d5f115c363aa3c79b'") ); }
+    @Test public void sha384_04()       { assertThrows(ExprEvalException.class, ()-> test("sha384(123.45)","'1165b3406ff0b52a3d24721f785462ca2276c9f454a116c2b2ba20171a7905ea5a026682eb659c4d5f115c363aa3c79b'") ); }
 
     // SHA512
-    @Test public void sha512_01()      { test("sha512('abcd')","'d8022f2060ad6efd297ab73dcc5355c9b214054b0d1776a136a669d26a7d3b14f73aa0d0ebff19ee333368f0164b6419a96da49e3e481753e7e96b716bdccb6f'"); }
-
-    @Test public void sha512_02()      { test("sha512('abcd'^^xsd:string)","'d8022f2060ad6efd297ab73dcc5355c9b214054b0d1776a136a669d26a7d3b14f73aa0d0ebff19ee333368f0164b6419a96da49e3e481753e7e96b716bdccb6f'"); }
-
-    @Test
-					 public void sha512_03()            { assertThrows(ExprEvalException.class, ()-> test("md5('abcd'@en)","'d8022f2060ad6efd297ab73dcc5355c9b214054b0d1776a136a669d26a7d3b14f73aa0d0ebff19ee333368f0164b6419a96da49e3e481753e7e96b716bdccb6f'") ); }
-
-    @Test
-					 public void sha512_04()            { assertThrows(ExprEvalException.class, ()-> test("md5(0.0e0)","'d8022f2060ad6efd297ab73dcc5355c9b214054b0d1776a136a669d26a7d3b14f73aa0d0ebff19ee333368f0164b6419a96da49e3e481753e7e96b716bdccb6f'") ); }
+    @Test public void sha512_01()       { test("sha512('abcd')","'d8022f2060ad6efd297ab73dcc5355c9b214054b0d1776a136a669d26a7d3b14f73aa0d0ebff19ee333368f0164b6419a96da49e3e481753e7e96b716bdccb6f'"); }
+    @Test public void sha512_02()       { test("sha512('abcd'^^xsd:string)","'d8022f2060ad6efd297ab73dcc5355c9b214054b0d1776a136a669d26a7d3b14f73aa0d0ebff19ee333368f0164b6419a96da49e3e481753e7e96b716bdccb6f'"); }
+    @Test public void sha512_03()       { assertThrows(ExprEvalException.class, ()-> test("md5('abcd'@en)","'d8022f2060ad6efd297ab73dcc5355c9b214054b0d1776a136a669d26a7d3b14f73aa0d0ebff19ee333368f0164b6419a96da49e3e481753e7e96b716bdccb6f'") ); }
+    @Test public void sha512_04()       { assertThrows(ExprEvalException.class, ()-> test("md5(0.0e0)","'d8022f2060ad6efd297ab73dcc5355c9b214054b0d1776a136a669d26a7d3b14f73aa0d0ebff19ee333368f0164b6419a96da49e3e481753e7e96b716bdccb6f'") ); }
 
     // --------
 
     private static PrefixMapping pmap = ARQConstants.getGlobalPrefixMap();
 
-    private static void test(String string, String result) {
-        Expr expr = ExprUtils.parse(string, pmap);
+    private static void test(String expressionStr, String result) {
+        Expr expr = ExprUtils.parse(expressionStr, pmap);
         NodeValue nv = expr.eval(null, new FunctionEnvBase());
         Node r = NodeFactoryExtra.parseNode(result);
         NodeValue nvr = NodeValue.makeNode(r);
 
+        // Check datatypes.
+        RDFDatatype dtActual = nv.asNode().getLiteralDatatype();
+        RDFDatatype dtExpected = nvr.asNode().getLiteralDatatype();
+        assertEquals(dtExpected, dtActual, "Differing datatpes");
+
+        // Same term works for NaNs
+        if ( nv.asNode().sameTermAs(nvr.asNode()) )
+            return;
+
+        // Not NaNs!
         assertTrue(NodeValue.sameValueAs(nvr, nv), "Not same value: Expected: " + nvr + " : Actual = " + nv);
         // test result must be lexical form exact.
         assertEquals(r, nv.asNode());
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestXSDFuncOp.java b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestXSDFuncOp.java
index 971ac7b58b..894fc3a444 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestXSDFuncOp.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestXSDFuncOp.java
@@ -805,6 +805,104 @@ public class TestXSDFuncOp {
         assertEquals(2d, r.getDouble(), accuracyExact_D, "Wrong result");
     }
 
+    @Test public void testRoundDouble1() {
+        NodeValue nv = NodeValue.makeDouble(1.23d);
+        NodeValue r = XSDFuncOp.round(nv);
+        assertTrue(r.isDouble(), "Not a double: "+r);
+        assertTrue(r instanceof NodeValueDouble, "Not a NodeValueDouble: "+r);
+        assertEquals(1d, r.getDouble(), 0d, "Wrong result");
+    }
+
+    @Test public void testRoundDouble2() {
+        NodeValue nv = NodeValue.makeDouble(0d);
+        NodeValue r = XSDFuncOp.round(nv);
+        assertTrue(r.isDouble(), "Not a double: "+r);
+        assertTrue(r instanceof NodeValueDouble, "Not a NodeValueDouble: "+r);
+        assertEquals(0.0d, r.getDouble(), 0d, "Wrong result");
+    }
+
+    @Test public void testRoundDouble3() {
+        NodeValue nv = NodeValue.makeDouble(-0d);
+        NodeValue r = XSDFuncOp.round(nv);
+        assertTrue(r.isDouble(), "Not a double: "+r);
+        assertTrue(r instanceof NodeValueDouble, "Not a NodeValueDouble: "+r);
+        assertEquals(-0.0d, r.getDouble(), 0d, "Wrong result");
+    }
+
+    @Test public void testRoundDouble4() {
+        NodeValue nv = NodeValue.makeDouble(Double.NaN);
+        NodeValue r = XSDFuncOp.round(nv);
+        assertTrue(XSDNumUtils.isNaN(r));
+    }
+
+    @Test public void testRoundDouble5() {
+        NodeValue nv = NodeValue.makeDouble(Double.POSITIVE_INFINITY);
+        NodeValue r = XSDFuncOp.round(nv);
+        assertEquals(r.getDouble(), Double.POSITIVE_INFINITY);
+    }
+
+    @Test public void testRoundDouble6() {
+        NodeValue nv = NodeValue.makeDouble(Double.NEGATIVE_INFINITY);
+        NodeValue r = XSDFuncOp.round(nv);
+        assertEquals(r.getDouble(), Double.NEGATIVE_INFINITY);
+    }
+
+    @Test public void testRoundFloat1() {
+        NodeValue nv = NodeValue.makeFloat(1.23f);
+        NodeValue r = XSDFuncOp.round(nv);
+        assertTrue(r.isFloat(), "Not a float: "+r);
+        assertTrue(r instanceof NodeValueFloat, "Not a NodeValueFloat: "+r);
+        assertEquals(1f, r.getFloat(), 0f, "Wrong result");
+    }
+
+    @Test public void testRoundFloat2() {
+        NodeValue nv = NodeValue.makeFloat(0f);
+        NodeValue r = XSDFuncOp.round(nv);
+        assertTrue(r.isFloat(), "Not a float: "+r);
+        assertTrue(r instanceof NodeValueFloat, "Not a NodeValueFloat: "+r);
+        assertEquals(0.0f, r.getFloat(), 0f, "Wrong result");
+    }
+
+    @Test public void testRoundFloat3() {
+        NodeValue nv = NodeValue.makeFloat(-0f);
+        NodeValue r = XSDFuncOp.round(nv);
+        assertTrue(r.isFloat(), "Not a float: "+r);
+        assertTrue(r instanceof NodeValueFloat, "Not a NodeValueFloat: "+r);
+        assertEquals(-0.0f, r.getFloat(), 0f, "Wrong result");
+    }
+
+    @Test public void testRoundFloat4() {
+        NodeValue nv = NodeValue.makeFloat(Float.NaN);
+        NodeValue r = XSDFuncOp.round(nv);
+        assertTrue(XSDNumUtils.isNaN(r));
+    }
+
+    @Test public void testRoundFloat5() {
+        NodeValue nv = NodeValue.makeFloat(Float.POSITIVE_INFINITY);
+        NodeValue r = XSDFuncOp.round(nv);
+        assertEquals(r.getFloat(), Float.POSITIVE_INFINITY);
+    }
+
+    @Test public void testRoundFloat6() {
+        NodeValue nv = NodeValue.makeFloat(Float.NEGATIVE_INFINITY);
+        NodeValue r = XSDFuncOp.round(nv);
+        assertEquals(r.getFloat(), Double.NEGATIVE_INFINITY);
+    }
+
+    @Test public void testRound1() {
+        NodeValue nv = NodeValue.makeDecimal(1.23);
+        NodeValue r = XSDFuncOp.round(nv);
+        assertTrue(r instanceof NodeValueDecimal, "Not a NodeValueDecimal: "+r);
+        assertEquals(new BigDecimal("1"), r.getDecimal(), "Wrong result");
+    }
+
+    @Test public void testRound2() {
+        NodeValue nv = NodeValue.makeDecimal(-1.23);
+        NodeValue r = XSDFuncOp.round(nv);
+        assertTrue(r instanceof NodeValueDecimal, "Not a NodeValueDecimal: "+r);
+        assertEquals(new BigDecimal("-1"), r.getDecimal(), "Wrong result");
+    }
+
     @Test public void testCeiling1() {
         NodeValue nv = NodeValue.makeDecimal(2.6);
         NodeValue r = XSDFuncOp.ceiling(nv);


(jena) 04/06: Notes for skipped tests

Posted by an...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git

commit d61e8f86125c987248cf46ac9613b89beed8dc06
Author: Andy Seaborne <an...@apache.org>
AuthorDate: Tue Dec 30 19:04:52 2025 +0000

    Notes for skipped tests
---
 .../src/test/java/org/apache/jena/arq/junit/sparql/SparqlTests.java | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/jena-arq/src/test/java/org/apache/jena/arq/junit/sparql/SparqlTests.java b/jena-arq/src/test/java/org/apache/jena/arq/junit/sparql/SparqlTests.java
index d0fe1d0072..3f552c1a72 100644
--- a/jena-arq/src/test/java/org/apache/jena/arq/junit/sparql/SparqlTests.java
+++ b/jena-arq/src/test/java/org/apache/jena/arq/junit/sparql/SparqlTests.java
@@ -110,16 +110,18 @@ public class SparqlTests {
         // ---- Query Evaluation Tests
         if ( equalsType(testType, TestManifest.QueryEvaluationTest) ) {
 
+            // tests not supported.
+
             // ??
             if ( entryContainsSubstring(entry, "aggregates/manifest#agg-groupconcat-04") ) {
                 return null;
             }
 
-            // ??
+            // Two BNODE in the SELECT
             if ( entryContainsSubstring(entry, "functions/manifest#bnode01") ) {
                 return null;
             }
-            // ??
+            // Jena bug?
             if ( entryContainsSubstring(entry, "property-path/manifest#values_and_path") ) {
                 return null;
             }


(jena) 01/06: Rename NodeValue constants for certain xsd:double cases

Posted by an...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git

commit 16ec4d84d77196c2fd5ae75825df43beeeb6e913
Author: Andy Seaborne <an...@apache.org>
AuthorDate: Tue Dec 30 19:00:01 2025 +0000

    Rename NodeValue constants for certain xsd:double cases
---
 .../org/apache/jena/sparql/expr/NodeValue.java     | 28 +++++++++++----
 .../sparql/expr/nodevalue/NodeValueDouble.java     |  2 +-
 .../jena/sparql/expr/nodevalue/NodeValueFloat.java |  2 +-
 .../jena/sparql/expr/nodevalue/NodeValueOps.java   |  2 +-
 .../jena/sparql/expr/nodevalue/XSDFuncOp.java      | 40 ++++++++++++++++++++--
 .../org/apache/jena/sparql/function/CastXSD.java   |  9 +++--
 .../org/apache/jena/sparql/expr/LibTestExpr.java   |  4 +--
 .../jena/sparql/expr/TestExpressionsMath.java      | 16 ++++-----
 .../jena/sparql/expr/TestLeviathanFunctions.java   |  2 +-
 9 files changed, 80 insertions(+), 25 deletions(-)

diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/expr/NodeValue.java b/jena-arq/src/main/java/org/apache/jena/sparql/expr/NodeValue.java
index 26fc926e66..e127b4aaf0 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/expr/NodeValue.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/expr/NodeValue.java
@@ -106,19 +106,35 @@ public abstract class NodeValue extends ExprNode
     public static final NodeValue TRUE   = NodeValue.makeNode("true", XSDboolean);
     public static final NodeValue FALSE  = NodeValue.makeNode("false", XSDboolean);
 
+    public static final NodeValue nvEmptyString  = NodeValue.makeString("");
+
     public static final NodeValue nvZERO = NodeValue.makeNode(NodeConst.nodeZero);
-    public static final NodeValue nvNegZERO = NodeValue.makeNode("-0.0e0", XSDdouble);
     public static final NodeValue nvONE  = NodeValue.makeNode(NodeConst.nodeOne);
     public static final NodeValue nvTEN  = NodeValue.makeNode(NodeConst.nodeTen);
 
     public static final NodeValue nvDecimalZERO = NodeValue.makeNode("0.0", XSDdecimal);
     public static final NodeValue nvDecimalONE  = NodeValue.makeNode("1.0", XSDdecimal);
 
-    public static final NodeValue nvNaN     = NodeValue.makeNode("NaN", XSDdouble);
-    public static final NodeValue nvINF     = NodeValue.makeNode("INF", XSDdouble);
-    public static final NodeValue nvNegINF  = NodeValue.makeNode("-INF",XSDdouble);
+    public static final NodeValue nvDoubleNegZERO = NodeValue.makeNode("-0.0e0", XSDdouble);
+    public static final NodeValue nvDoubleNaN     = NodeValue.makeNode("NaN", XSDdouble);
+    public static final NodeValue nvDoubleINF     = NodeValue.makeNode("INF", XSDdouble);
+    public static final NodeValue nvDoubleNegINF  = NodeValue.makeNode("-INF",XSDdouble);
 
-    public static final NodeValue nvEmptyString  = NodeValue.makeString("");
+    /** @deprecated Use {@link #nvDoubleNegZERO} */
+    @Deprecated
+    public static final NodeValue nvNegZERO = nvDoubleNegZERO;
+
+    /** @deprecated Use {@link #nvDoubleNaN} */
+    @Deprecated
+    public static final NodeValue nvNaN     = nvDoubleNaN;
+
+    /** @deprecated Use {@link #nvDoubleINF} */
+    @Deprecated
+    public static final NodeValue nvINF     = nvDoubleINF;
+
+    /** @deprecated Use {@link #nvDoubleNegINF} */
+    @Deprecated
+    public static final NodeValue nvNegINF  = nvDoubleNegINF;
 
     public static final String xsdNamespace = XSD+"#";
 
@@ -605,7 +621,7 @@ public abstract class NodeValue extends ExprNode
         // Java equals, not "same value" or "same term"
         if ( other == null ) return false;
         if ( this == other ) return true;
-        // This is the equality condition Jena uses - lang tags are different by case.
+        // This is the equality condition Jena uses
         if ( ! ( other instanceof NodeValue nv) )
             return false;
         return asNode().equals(nv.asNode());
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueDouble.java b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueDouble.java
index 0351f913d7..5e404a7141 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueDouble.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueDouble.java
@@ -31,7 +31,7 @@ import org.apache.jena.sparql.util.XSDNumUtils;
 
 public class NodeValueDouble extends NodeValue {
 
-    double value = Double.NaN;
+    private final double value;
 
     public NodeValueDouble(double d)         { super(); value = d; }
     public NodeValueDouble(double d, Node n) { super(n); value = d; }
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueFloat.java b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueFloat.java
index 20cfc14dea..0b32c89a86 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueFloat.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueFloat.java
@@ -26,7 +26,7 @@ import org.apache.jena.sparql.util.XSDNumUtils;
 
 public class NodeValueFloat extends NodeValue
 {
-    float value = Float.NaN;
+    private final float value;
 
     public NodeValueFloat(float f)         { super(); value = f; }
     public NodeValueFloat(float f, Node n) { super(n); value = f; }
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueOps.java b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueOps.java
index b11cbc79ad..5b397efb6f 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueOps.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueOps.java
@@ -40,7 +40,7 @@ import org.apache.jena.sparql.util.NodeUtils;
  * Operations relating to {@link NodeValue NodeValues}.
  * <ul>
  * <li>The code parts of arithmetic operations on {@link NodeValue}s.
- * <li>Library code such as Argument testing
+ * <li>Library code such as expression string argument testing
  * </ul>
  * <p>
  * This class is not considered to be part of the ARQ API.
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/XSDFuncOp.java b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/XSDFuncOp.java
index 6bfc904fe1..6fd848817d 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/XSDFuncOp.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/XSDFuncOp.java
@@ -397,14 +397,50 @@ public class XSDFuncOp
                     dec = v.getDecimal().setScale(0, RoundingMode.HALF_UP);
                 return NodeValue.makeDecimal(dec);
             case OP_FLOAT:
-                return NodeValue.makeFloat(Math.round(v.getFloat()));
+                return NodeValue.makeFloat(roundFloat(v.getFloat()));
             case OP_DOUBLE:
-                return NodeValue.makeDouble(Math.round(v.getDouble()));
+                return NodeValue.makeDouble(roundDouble(v.getDouble()));
             default:
                 throw new ARQInternalErrorException("Unrecognized numeric operation : " + v);
         }
     }
 
+    private static double roundDouble(double d) {
+        if ( Double.isNaN(d) )
+            return Double.NaN;
+        if ( d == Double.POSITIVE_INFINITY )
+            return d;
+        if ( d == Double.NEGATIVE_INFINITY )
+            return d;
+        if ( d == -0.0e0 )
+            return d;
+        // Math.round returns a java long
+        long resultLong = Math.round(d);
+        if ( resultLong == 0 && d < 0 )
+            // Return -0 for round negative to 0.
+            return -0.0e0d;
+        // Cast to double by the return.
+        return resultLong;
+    }
+
+    private static float roundFloat(float f) {
+        if ( Float.isNaN(f) )
+            return Float.NaN;
+        if ( f == Float.POSITIVE_INFINITY )
+            return f;
+        if ( f == Float.NEGATIVE_INFINITY )
+            return f;
+        if ( f == -0.0e0f )
+            return f;
+        // Math.round returns a java long
+        long resultLong = Math.round(f);
+        if ( resultLong == 0 && f < 0 )
+            // Return -0 for round negative to 0.
+            return -0.0e0f;
+        // Math.round returns a java long, which is cast to float by the return.
+        return resultLong;
+    }
+
     // The following function 'roundXpath3' implements the definition for "fn:round" in F&O v3.
     // This is different to the "fn:round" in F&O v2.
     // SPARQL 1.1 references F&O v2.
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD.java b/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD.java
index ae43940b2c..07362c4142 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD.java
@@ -18,8 +18,8 @@
 
 package org.apache.jena.sparql.function;
 
-import static org.apache.jena.sparql.expr.NodeValue.nvNaN;
-import static org.apache.jena.sparql.expr.NodeValue.nvNegZERO;
+import static org.apache.jena.sparql.expr.NodeValue.nvDoubleNaN;
+import static org.apache.jena.sparql.expr.NodeValue.nvDoubleNegZERO;
 import static org.apache.jena.sparql.expr.NodeValue.nvZERO;
 import static org.apache.jena.sparql.expr.nodevalue.XSDFuncOp.*;
 import java.math.BigDecimal;
@@ -273,7 +273,10 @@ public class CastXSD {
         if ( nv.isBoolean() )
             return nv;
         if ( nv.isNumber() ) {
-            if ( NodeValue.sameValueAs(nv, nvZERO) || NodeValue.sameValueAs(nv, nvNaN) || NodeValue.sameValueAs(nv, nvNegZERO) )
+            if ( NodeValue.sameValueAs(nv, nvZERO) )
+                return NodeValue.FALSE;
+            // sameValueAs Covers xsd:float
+            if ( NodeValue.sameValueAs(nv, nvDoubleNaN) || NodeValue.sameValueAs(nv, nvDoubleNegZERO) )
                 return NodeValue.FALSE;
             return NodeValue.TRUE;
         }
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/expr/LibTestExpr.java b/jena-arq/src/test/java/org/apache/jena/sparql/expr/LibTestExpr.java
index b56dec1871..44e455442b 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/expr/LibTestExpr.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/expr/LibTestExpr.java
@@ -94,8 +94,8 @@ public class LibTestExpr {
         assertTrue(sameValueSameDatatype(expected, actual), ()->"Expected = " + expected + " : Actual = " + actual);
     }
 
-    public static void testIsNaN(String exprStr) {
-        testSameObject(exprStr, NodeValue.nvNaN);
+    public static void testDoubleIsNaN(String exprStr) {
+        testSameObject(exprStr, NodeValue.nvDoubleNaN);
     }
 
     public static void testSameObject(String exprStr, NodeValue expected) {
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestExpressionsMath.java b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestExpressionsMath.java
index 13e8aa18e7..d8392350f9 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestExpressionsMath.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestExpressionsMath.java
@@ -20,7 +20,7 @@ package org.apache.jena.sparql.expr;
 
 import static org.apache.jena.sparql.expr.LibTestExpr.test;
 import static org.apache.jena.sparql.expr.LibTestExpr.testDouble;
-import static org.apache.jena.sparql.expr.LibTestExpr.testIsNaN;
+import static org.apache.jena.sparql.expr.LibTestExpr.testDoubleIsNaN;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
 import org.junit.jupiter.api.Test;
@@ -41,7 +41,7 @@ public class TestExpressionsMath
     @Test public void exp_04()          { test("math:exp(1e0/0)", "'INF'^^xsd:double"); }
     @Test public void exp_05()          { test("math:exp('INF'^^xsd:double)", "'INF'^^xsd:double"); }
     @Test public void exp_06()          { test("math:exp('-INF'^^xsd:double)", "'0.0e0'^^xsd:double"); }
-    @Test public void exp_07()          { testIsNaN("math:exp('NaN'^^xsd:double)"); }
+    @Test public void exp_07()          { testDoubleIsNaN("math:exp('NaN'^^xsd:double)"); }
 
     @Test public void exp10_01()        { test("math:exp10(2)", "100"); }
     @Test public void exp10_02()        { testDouble("math:exp10(-1)", 0.1, 0.00001); }
@@ -55,7 +55,7 @@ public class TestExpressionsMath
     @Test public void log_04()          { test("math:log(0)", "'-INF'^^xsd:double"); }
     @Test public void log_05()          { test("math:exp('INF'^^xsd:double)", "'INF'^^xsd:double"); }
     @Test public void log_06()          { test("math:exp('-INF'^^xsd:double)", "'0.0e0'^^xsd:double"); }
-    @Test public void log_07()          { testIsNaN("math:exp('NaN'^^xsd:double)"); }
+    @Test public void log_07()          { testDoubleIsNaN("math:exp('NaN'^^xsd:double)"); }
 
     @Test public void pow_01()          { test("math:pow(2,2)", "4"); }
     @Test public void pow_02()          { testDouble("math:pow(2,-2)", 0.25, 0.00001); }
@@ -67,18 +67,18 @@ public class TestExpressionsMath
 
     @Test public void pow_13()          { test("math:pow('INF'^^xsd:double,0)", "'1.0e0'^^xsd:double"); }
     @Test public void pow_14()          { test("math:pow('-INF'^^xsd:double, 0)", "'1.0e0'^^xsd:double"); }
-    @Test public void pow_15()          { testIsNaN("math:pow('NaN'^^xsd:double, 1)"); }
-    @Test public void pow_16()          { testIsNaN("math:pow(1, 'NaN'^^xsd:double)"); }
+    @Test public void pow_15()          { testDoubleIsNaN("math:pow('NaN'^^xsd:double, 1)"); }
+    @Test public void pow_16()          { testDoubleIsNaN("math:pow(1, 'NaN'^^xsd:double)"); }
 
     @Test public void sqrt_01()         { test("math:sqrt(1)", "'1.0e0'^^xsd:double"); }
     @Test public void sqrt_02()         { testDouble("math:sqrt(2)", Math.sqrt(2), 0.000001); }
-    @Test public void sqrt_03()         { testIsNaN("math:sqrt(-2)"); }
+    @Test public void sqrt_03()         { testDoubleIsNaN("math:sqrt(-2)"); }
 
     @Test public void sqrt_04()         { assertThrows(ARQException.class, ()->test("math:sqrt('TWO')", "'dummy'")); }
 
     @Test public void sqrt_10()         { test("math:sqrt('INF'^^xsd:double)", "'INF'^^xsd:double"); }
-    @Test public void sqrt_11()         { testIsNaN("math:sqrt('-INF'^^xsd:double)"); }
-    @Test public void sqrt_12()         { testIsNaN("math:sqrt('NaN'^^xsd:double)"); }
+    @Test public void sqrt_11()         { testDoubleIsNaN("math:sqrt('-INF'^^xsd:double)"); }
+    @Test public void sqrt_12()         { testDoubleIsNaN("math:sqrt('NaN'^^xsd:double)"); }
 
     //  4.8.7 math:sqrt
     //  4.8.8 math:sin
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestLeviathanFunctions.java b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestLeviathanFunctions.java
index 55e06dc527..bf10c8c831 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestLeviathanFunctions.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestLeviathanFunctions.java
@@ -135,7 +135,7 @@ public class TestLeviathanFunctions {
     public void log_03() {
         NodeValue actual = LibTestExpr.eval("lfn:log(-1)");
         // Test the object, not the value.
-        assertTrue(NodeValue.nvNaN.equals(actual));
+        assertTrue(NodeValue.nvDoubleNaN.equals(actual));
     }
 
     @Test