Add SynthResult to the API (#8370)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Wed, 23 Mar 2022 21:56:33 +0000 (16:56 -0500)
committerGitHub <noreply@github.com>
Wed, 23 Mar 2022 21:56:33 +0000 (21:56 +0000)
Does not modify the code to return a SynthResult yet, just adds the class.

Co-authored-by: Aina Niemetz <aina.niemetz@gmail.com>
20 files changed:
docs/api/cpp/cpp.rst
docs/api/cpp/synthresult.rst [new file with mode: 0644]
docs/api/java/java.rst
docs/api/python/base/python.rst
docs/api/python/base/synthresult.rst [new file with mode: 0644]
src/api/cpp/cvc5.cpp
src/api/cpp/cvc5.h
src/api/java/CMakeLists.txt
src/api/java/io/github/cvc5/api/Solver.java
src/api/java/io/github/cvc5/api/SynthResult.java [new file with mode: 0644]
src/api/java/jni/solver.cpp
src/api/java/jni/synth_result.cpp [new file with mode: 0644]
src/api/python/cvc5.pxd
src/api/python/cvc5.pxi
test/unit/api/cpp/CMakeLists.txt
test/unit/api/cpp/synth_result_black.cpp [new file with mode: 0644]
test/unit/api/java/CMakeLists.txt
test/unit/api/java/SynthResultTest.java [new file with mode: 0644]
test/unit/api/python/CMakeLists.txt
test/unit/api/python/test_synth_result.py [new file with mode: 0644]

index 49548222af0f4e1842db1f5b254f552998564d7c..67f2c805304e79ff537d8b9ae3d0791638d0a597 100644 (file)
@@ -26,6 +26,7 @@ For most applications, the :cpp:class:`Solver <cvc5::api::Solver>` class is the
     solver
     sort
     statistics
+    synthresult
     term
 
 
@@ -33,7 +34,7 @@ Class hierarchy
 ^^^^^^^^^^^^^^^
 
 ``namespace cvc5::api {``
-  
+
   * class :cpp:class:`CVC5ApiException <cvc5::api::CVC5ApiException>`
   * class :cpp:class:`CVC5ApiRecoverableException <cvc5::api::CVC5ApiRecoverableException>`
   * class :ref:`api/cpp/datatype:datatype`
@@ -60,8 +61,9 @@ Class hierarchy
   * class :ref:`api/cpp/sort:sort`
   * class :cpp:class:`Stat <cvc5::api::Stat>`
   * class :cpp:class:`Statistics <cvc5::api::Statistics>`
+  * class :ref:`api/cpp/synthresult:synthresult`
   * class :ref:`api/cpp/term:term`
 
     * class :cpp:class:`const_iterator <cvc5::api::Term::const_iterator>`
 
-``}``
\ No newline at end of file
+``}``
diff --git a/docs/api/cpp/synthresult.rst b/docs/api/cpp/synthresult.rst
new file mode 100644 (file)
index 0000000..1765f48
--- /dev/null
@@ -0,0 +1,7 @@
+SynthResult
+===========
+
+.. doxygenclass:: cvc5::api::SynthResult
+    :project: cvc5
+    :members:
+    :undoc-members:
index 71a70023b3ec75aaa8edb985d1f3e7b9e3e78cab..dad64be0548f53069e43895be39f04a93a5b1a06 100644 (file)
@@ -72,6 +72,7 @@ Building cvc5 Java API
   * class `Sort <io/github/cvc5/api/Sort.html>`_
   * class `Stat <io/github/cvc5/api/Stat.html>`_
   * class `Statistics <io/github/cvc5/api/Statistics.html>`_
+  * class `SynthResult <io/github/cvc5/api/SynthResult.html>`_
   * class `Term <io/github/cvc5/api/Term.html>`_
   * class `Triplet<A,B,C> <io/github/cvc5/api/Triplet.html>`_
   * class `Utils <io/github/cvc5/api/Utils.html>`_
index 5036fa08149adb39e99b951734c69794af8d8668..cf2122b12ee0793f20455ffe3b73366f433075e2 100644 (file)
@@ -28,5 +28,6 @@ See the :doc:`pythonic API <../pythonic/pythonic>` for a higher-level programmin
     roundingmode
     solver
     sort
-    term 
+    synthresult
+    term
     unknownexplanation
diff --git a/docs/api/python/base/synthresult.rst b/docs/api/python/base/synthresult.rst
new file mode 100644 (file)
index 0000000..e89ef80
--- /dev/null
@@ -0,0 +1,6 @@
+SynthResult
+===========
+
+.. autoclass:: cvc5.SynthResult
+    :members:
+    :undoc-members:
index 95d3815d6369ae823518c95cfef9354e0b26fae4..0eba91ee291c2a52b2fc88694c4ac148ca7d923c 100644 (file)
@@ -83,6 +83,7 @@
 #include "util/statistics_stats.h"
 #include "util/statistics_value.h"
 #include "util/string.h"
+#include "util/synth_result.h"
 #include "util/uninterpreted_sort_value.h"
 #include "util/utility.h"
 
@@ -988,6 +989,45 @@ std::ostream& operator<<(std::ostream& out, enum Result::UnknownExplanation e)
   return out;
 }
 
+/* -------------------------------------------------------------------------- */
+/* SynthResult */
+/* -------------------------------------------------------------------------- */
+
+SynthResult::SynthResult(const cvc5::SynthResult& r)
+    : d_result(new cvc5::SynthResult(r))
+{
+}
+
+SynthResult::SynthResult() : d_result(new cvc5::SynthResult()) {}
+
+bool SynthResult::isNull() const
+{
+  return d_result->getStatus() == cvc5::SynthResult::NONE;
+}
+
+bool SynthResult::hasSolution(void) const
+{
+  return d_result->getStatus() == cvc5::SynthResult::SOLUTION;
+}
+
+bool SynthResult::hasNoSolution() const
+{
+  return d_result->getStatus() == cvc5::SynthResult::NO_SOLUTION;
+}
+
+bool SynthResult::isUnknown() const
+{
+  return d_result->getStatus() == cvc5::SynthResult::UNKNOWN;
+}
+
+std::string SynthResult::toString(void) const { return d_result->toString(); }
+
+std::ostream& operator<<(std::ostream& out, const SynthResult& sr)
+{
+  out << sr.toString();
+  return out;
+}
+
 /* -------------------------------------------------------------------------- */
 /* Sort                                                                       */
 /* -------------------------------------------------------------------------- */
index 9adae13373ae6ad4e0862773cbb54c0773ce67b7..6d7f0417c288c7a3c726663e14e2e3c88f7a3b51 100644 (file)
@@ -50,6 +50,7 @@ class Options;
 class Random;
 class Rational;
 class Result;
+class SynthResult;
 class StatisticsRegistry;
 
 namespace main {
@@ -61,6 +62,7 @@ namespace api {
 class Solver;
 class Statistics;
 struct APIStatistics;
+class Term;
 
 /* -------------------------------------------------------------------------- */
 /* Exception                                                                  */
@@ -257,7 +259,7 @@ class CVC5_EXPORT Result
   Result(const cvc5::Result& r);
 
   /**
-   * The interal result wrapped by this result.
+   * The internal result wrapped by this result.
    *
    * @note This is a ``std::shared_ptr`` rather than a ``std::unique_ptr``
    *       since ``cvc5::Result`` is not ref counted.
@@ -282,6 +284,80 @@ std::ostream& operator<<(std::ostream& out, const Result& r) CVC5_EXPORT;
 std::ostream& operator<<(std::ostream& out,
                          enum Result::UnknownExplanation e) CVC5_EXPORT;
 
+/* -------------------------------------------------------------------------- */
+/* Result                                                                     */
+/* -------------------------------------------------------------------------- */
+
+/**
+ * Encapsulation of a solver synth result.
+ *
+ * This is the return value of the API methods:
+ *   - Solver::checkSynth()
+ *   - Solver::checkSynthNext()
+ *
+ * which we call synthesis queries.  This class indicates whether the
+ * synthesis query has a solution, has no solution, or is unknown.
+ */
+class CVC5_EXPORT SynthResult
+{
+  friend class Solver;
+
+ public:
+  /** Constructor. */
+  SynthResult();
+
+  /**
+   * @return true if SynthResult is null, i.e., not a SynthResult returned
+   * from a synthesis query.
+   */
+  bool isNull() const;
+
+  /**
+   * @return true if the synthesis query has a solution.
+   */
+  bool hasSolution() const;
+
+  /**
+   * @return true if the synthesis query has no solution. In this case, it
+   * was determined that there was no solution.
+   */
+  bool hasNoSolution() const;
+
+  /**
+   * @return true if the result of the synthesis query could not be determined.
+   */
+  bool isUnknown() const;
+
+  /**
+   * @return a string representation of this synthesis result.
+   */
+  std::string toString() const;
+
+ private:
+  /**
+   * Constructor.
+   * @param r the internal synth result that is to be wrapped by this synth
+   *          result
+   * @return the SynthResult
+   */
+  SynthResult(const cvc5::SynthResult& r);
+  /**
+   * The internal result wrapped by this result.
+   *
+   * @note This is a `std::shared_ptr` rather than a `std::unique_ptr`
+   *       since `cvc5::SynthResult` is not ref counted.
+   */
+  std::shared_ptr<cvc5::SynthResult> d_result;
+};
+
+/**
+ * Serialize a SynthResult to given stream.
+ * @param out the output stream
+ * @param r the result to be serialized to the given output stream
+ * @return the output stream
+ */
+std::ostream& operator<<(std::ostream& out, const SynthResult& r) CVC5_EXPORT;
+
 /* -------------------------------------------------------------------------- */
 /* Sort                                                                       */
 /* -------------------------------------------------------------------------- */
@@ -987,6 +1063,7 @@ class CVC5_EXPORT Term
   friend class DatatypeSelector;
   friend class Solver;
   friend class Grammar;
+  friend class SynthResult;
   friend struct std::hash<Term>;
 
  public:
index 95c1ae4a4cdd98aa14979339bda1b435bca5214d..342a3739499e9f711318c876a7827ff2f4bf7fe4 100644 (file)
@@ -67,6 +67,7 @@ set(JAVA_FILES
   ${CMAKE_CURRENT_LIST_DIR}/io/github/cvc5/api/Sort.java
   ${CMAKE_CURRENT_LIST_DIR}/io/github/cvc5/api/Stat.java
   ${CMAKE_CURRENT_LIST_DIR}/io/github/cvc5/api/Statistics.java
+  ${CMAKE_CURRENT_LIST_DIR}/io/github/cvc5/api/SynthResult.java
   ${CMAKE_CURRENT_LIST_DIR}/io/github/cvc5/api/Term.java
   ${CMAKE_CURRENT_LIST_DIR}/io/github/cvc5/api/Triplet.java
   ${CMAKE_CURRENT_LIST_DIR}/io/github/cvc5/api/Utils.java
@@ -121,6 +122,7 @@ add_library(cvc5jni
   jni/sort.cpp
   jni/stat.cpp
   jni/statistics.cpp
+  jni/synth_result.cpp
   jni/term.cpp)
 
 add_dependencies(cvc5jni generate-jni-headers)
index d0cc01232cfcf4413458df8babecc65388feb341..f1f2b91f6653a5db5e0456fb62762d9132c6dc4a 100644 (file)
@@ -2699,6 +2699,17 @@ public class Solver implements IPointer, AutoCloseable
 
   private native long getNullResult(long pointer);
 
+  /**
+   * @return null synth result
+   */
+  public SynthResult getNullSynthResult()
+  {
+    long resultPointer = getNullSynthResult(pointer);
+    return new SynthResult(this, resultPointer);
+  }
+
+  private native long getNullSynthResult(long pointer);
+
   /**
    * @return null op
    */
diff --git a/src/api/java/io/github/cvc5/api/SynthResult.java b/src/api/java/io/github/cvc5/api/SynthResult.java
new file mode 100644 (file)
index 0000000..7d9b5b6
--- /dev/null
@@ -0,0 +1,84 @@
+/******************************************************************************
+ * Top contributors (to current version):
+ *   Andrew Reynolds
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved.  See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * The cvc5 java API.
+ */
+
+package io.github.cvc5.api;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class SynthResult extends AbstractPointer
+{
+  // region construction and destruction
+  SynthResult(Solver solver, long pointer)
+  {
+    super(solver, pointer);
+  }
+
+  protected native void deletePointer(long pointer);
+
+  public long getPointer()
+  {
+    return pointer;
+  }
+
+  // endregion
+
+  /**
+   * Return true if SynthResult is empty, i.e., a nullary SynthResult, and not
+   * an actual result returned from a synthesis query.
+   */
+  public boolean isNull()
+  {
+    return isNull(pointer);
+  }
+
+  private native boolean isNull(long pointer);
+
+  /**
+   * Return true if the synthesis query has a solution.
+   */
+  public boolean hasSolution()
+  {
+    return hasSolution(pointer);
+  }
+
+  private native boolean hasSolution(long pointer);
+
+  /**
+   * Return true if the synthesis query has no solution. In this case, it was
+   * determined there was no solution.
+   */
+  public boolean hasNoSolution()
+  {
+    return hasNoSolution(pointer);
+  }
+
+  private native boolean hasNoSolution(long pointer);
+
+  /**
+   * Return true if the result of the synthesis query could not be determined.
+   */
+  public boolean isUnknown()
+  {
+    return isUnknown(pointer);
+  }
+
+  private native boolean isUnknown(long pointer);
+
+  /**
+   * @return a string representation of this result.
+   */
+  protected native String toString(long pointer);
+}
index fae1b44eb99be0b3c29a71e7d00525e371996cf7..f440c164632bdb4c3879d4bda41ab6e8d2fb39c9 100644 (file)
@@ -2705,6 +2705,20 @@ Java_io_github_cvc5_api_Solver_getNullResult(JNIEnv* env, jobject, jlong)
   CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, 0);
 }
 
+/*
+ * Class:     io_github_cvc5_api_Solver
+ * Method:    getNullSynthResult
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL
+Java_io_github_cvc5_api_Solver_getNullSynthResult(JNIEnv* env, jobject, jlong)
+{
+  CVC5_JAVA_API_TRY_CATCH_BEGIN;
+  SynthResult* ret = new SynthResult();
+  return reinterpret_cast<jlong>(ret);
+  CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, 0);
+}
+
 /*
  * Class:     io_github_cvc5_api_Solver
  * Method:    getNullOp
diff --git a/src/api/java/jni/synth_result.cpp b/src/api/java/jni/synth_result.cpp
new file mode 100644 (file)
index 0000000..6d0ab38
--- /dev/null
@@ -0,0 +1,101 @@
+/******************************************************************************
+ * Top contributors (to current version):
+ *   Andrew Reynolds
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved.  See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * The cvc5 Java API.
+ */
+
+#include "api/cpp/cvc5.h"
+#include "api_utilities.h"
+#include "io_github_cvc5_api_SynthResult.h"
+
+using namespace cvc5::api;
+
+/*
+ * Class:     io_github_cvc5_api_SynthResult
+ * Method:    deletePointer
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_io_github_cvc5_api_SynthResult_deletePointer(
+    JNIEnv*, jobject, jlong pointer)
+{
+  delete ((SynthResult*)pointer);
+}
+
+/*
+ * Class:     io_github_cvc5_api_SynthResult
+ * Method:    isNull
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_io_github_cvc5_api_SynthResult_isNull(JNIEnv* env, jobject, jlong pointer)
+{
+  CVC5_JAVA_API_TRY_CATCH_BEGIN;
+  SynthResult* current = (SynthResult*)pointer;
+  return (jboolean)current->isNull();
+  CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, (jboolean) false);
+}
+
+/*
+ * Class:     io_github_cvc5_api_SynthResult
+ * Method:    hasSolution
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_io_github_cvc5_api_SynthResult_hasSolution(
+    JNIEnv* env, jobject, jlong pointer)
+{
+  CVC5_JAVA_API_TRY_CATCH_BEGIN;
+  SynthResult* current = (SynthResult*)pointer;
+  return (jboolean)current->hasSolution();
+  CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, (jboolean) false);
+}
+
+/*
+ * Class:     io_github_cvc5_api_SynthResult
+ * Method:    hasNoSolution
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_io_github_cvc5_api_SynthResult_hasNoSolution(
+    JNIEnv* env, jobject, jlong pointer)
+{
+  CVC5_JAVA_API_TRY_CATCH_BEGIN;
+  SynthResult* current = (SynthResult*)pointer;
+  return (jboolean)current->hasNoSolution();
+  CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, (jboolean) false);
+}
+
+/*
+ * Class:     io_github_cvc5_api_SynthResult
+ * Method:    isUnknown
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_io_github_cvc5_api_SynthResult_isUnknown(
+    JNIEnv* env, jobject, jlong pointer)
+{
+  CVC5_JAVA_API_TRY_CATCH_BEGIN;
+  SynthResult* current = (SynthResult*)pointer;
+  return (jboolean)current->isUnknown();
+  CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, (jboolean) false);
+}
+
+/*
+ * Class:     io_github_cvc5_api_SynthResult
+ * Method:    toString
+ * Signature: (J)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_io_github_cvc5_api_SynthResult_toString(
+    JNIEnv* env, jobject, jlong pointer)
+{
+  CVC5_JAVA_API_TRY_CATCH_BEGIN;
+  SynthResult* current = (SynthResult*)pointer;
+  return env->NewStringUTF(current->toString().c_str());
+  CVC5_JAVA_API_TRY_CATCH_END_RETURN(env, nullptr);
+}
index 5f7b61cb5be235702b9ed035b1ff0c793b172880..c057e20f11ea5c1aada7f699d52a8ebdaf11f251 100644 (file)
@@ -193,6 +193,13 @@ cdef extern from "api/cpp/cvc5.h" namespace "cvc5::api":
         UnknownExplanation getUnknownExplanation() except +
         string toString() except +
 
+    cdef cppclass SynthResult:
+        SynthResult() except+
+        bint isNull() except +
+        bint hasSolution() except +
+        bint hasNoSolution() except +
+        bint isUnknown() except +
+        string toString() except +
 
     cdef cppclass RoundingMode:
         pass
index 9ef53b86baf33493e92cedbcd2f063888d8a30e1..3305352d35cc81e3cabe05ecb28979cce717e657 100644 (file)
@@ -21,6 +21,7 @@ from cvc5 cimport DatatypeConstructorDecl as c_DatatypeConstructorDecl
 from cvc5 cimport DatatypeDecl as c_DatatypeDecl
 from cvc5 cimport DatatypeSelector as c_DatatypeSelector
 from cvc5 cimport Result as c_Result
+from cvc5 cimport SynthResult as c_SynthResult
 from cvc5 cimport RoundingMode as c_RoundingMode
 from cvc5 cimport UnknownExplanation as c_UnknownExplanation
 from cvc5 cimport Op as c_Op
@@ -615,6 +616,50 @@ cdef class Result:
     def __repr__(self):
         return self.cr.toString().decode()
 
+cdef class SynthResult:
+    """
+      Encapsulation of a solver synth result. This is the return value of the
+      API methods:
+        - :py:meth:`Solver.checkSynth()`
+        - :py:meth:`Solver.checkSynthNext()`
+      which we call synthesis queries. This class indicates whether the
+      synthesis query has a solution, has no solution, or is unknown.
+    """
+    cdef c_SynthResult cr
+    def __cinit__(self):
+        # gets populated by solver
+        self.cr = c_SynthResult()
+
+    def isNull(self):
+        """
+            :return: True if SynthResult is null, i.e. not a SynthResult returned from a synthesis query.
+        """
+        return self.cr.isNull()
+
+    def hasSolution(self):
+        """
+            :return: True if the synthesis query has a solution.
+        """
+        return self.cr.hasSolution()
+
+    def hasNoSolution(self):
+        """
+            :return: True if the synthesis query has no solution.
+            In this case, then it was determined there was no solution.
+        """
+        return self.cr.hasNoSolution()
+
+    def isUnknown(self):
+        """
+            :return: True if the result of the synthesis query could not be determined.
+        """
+        return self.cr.isUnknown()
+
+    def __str__(self):
+        return self.cr.toString().decode()
+
+    def __repr__(self):
+        return self.cr.toString().decode()
 
 cdef class RoundingMode:
     """
index d356236be417927f84b4027cf1bc13393b002226..cf6816981da07c4e21a5fac0cc39b521b372b0b9 100644 (file)
@@ -25,4 +25,5 @@ cvc5_add_unit_test_black(theory_arith_nl_black api/cpp)
 cvc5_add_unit_test_black(theory_uf_ho_black api/cpp)
 cvc5_add_unit_test_white(op_white api/cpp)
 cvc5_add_unit_test_white(solver_white api/cpp)
+cvc5_add_unit_test_black(synth_result_black api/cpp)
 cvc5_add_unit_test_white(term_white api/cpp)
diff --git a/test/unit/api/cpp/synth_result_black.cpp b/test/unit/api/cpp/synth_result_black.cpp
new file mode 100644 (file)
index 0000000..d2aebdb
--- /dev/null
@@ -0,0 +1,38 @@
+/******************************************************************************
+ * Top contributors (to current version):
+ *   Andrew Reynolds
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved.  See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * Black box testing of the SynthResult class
+ */
+
+#include "test_api.h"
+
+namespace cvc5 {
+
+using namespace api;
+
+namespace test {
+
+class TestApiBlackSynthResult : public TestApi
+{
+};
+
+TEST_F(TestApiBlackSynthResult, isNull)
+{
+  cvc5::api::SynthResult res_null;
+  ASSERT_TRUE(res_null.isNull());
+  ASSERT_FALSE(res_null.hasSolution());
+  ASSERT_FALSE(res_null.hasNoSolution());
+  ASSERT_FALSE(res_null.isUnknown());
+}
+
+}  // namespace test
+}  // namespace cvc5
index 5f573a1175caf7ddd49cf9eb3651c4d9bd4d370c..697dff60554e7c5419c9173f825cb66922406240 100644 (file)
@@ -28,6 +28,7 @@ set(java_test_src_files
   ${CMAKE_CURRENT_SOURCE_DIR}/ResultTest.java
   ${CMAKE_CURRENT_SOURCE_DIR}/SolverTest.java
   ${CMAKE_CURRENT_SOURCE_DIR}/SortTest.java
+  ${CMAKE_CURRENT_SOURCE_DIR}/SynthResultTest.java
   ${CMAKE_CURRENT_SOURCE_DIR}/TermTest.java
 )
 
diff --git a/test/unit/api/java/SynthResultTest.java b/test/unit/api/java/SynthResultTest.java
new file mode 100644 (file)
index 0000000..058decd
--- /dev/null
@@ -0,0 +1,47 @@
+/******************************************************************************
+ * Top contributors (to current version):
+ *   Andrew Reynolds
+ *
+ * This file is part of the cvc5 project.
+ *
+ * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+ * in the top-level source directory and their institutional affiliations.
+ * All rights reserved.  See the file COPYING in the top-level source
+ * directory for licensing information.
+ * ****************************************************************************
+ *
+ * Black box testing of the SynthResult class
+ */
+
+package tests;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import io.github.cvc5.api.*;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class SynthResultTest
+{
+  private Solver d_solver;
+
+  @BeforeEach void setUp()
+  {
+    d_solver = new Solver();
+  }
+
+  @AfterEach void tearDown()
+  {
+    d_solver.close();
+  }
+
+  @Test void isNull()
+  {
+    SynthResult res_null = d_solver.getNullSynthResult();
+    assertTrue(res_null.isNull());
+    assertFalse(res_null.hasSolution());
+    assertFalse(res_null.hasNoSolution());
+    assertFalse(res_null.isUnknown());
+  }
+}
index a322bbcc225e469794927c18c3380fd815bac664..fe68f1eea53550085fc466a51ed6d674040ffb79 100644 (file)
@@ -38,3 +38,4 @@ cvc5_add_python_api_unit_test(test_grammar test_grammar.py)
 cvc5_add_python_api_unit_test(test_to_python_obj test_to_python_obj.py)
 cvc5_add_python_api_unit_test(test_op test_op.py)
 cvc5_add_python_api_unit_test(test_result test_result.py)
+cvc5_add_python_api_unit_test(test_synth_result test_synth_result.py)
diff --git a/test/unit/api/python/test_synth_result.py b/test/unit/api/python/test_synth_result.py
new file mode 100644 (file)
index 0000000..a07b635
--- /dev/null
@@ -0,0 +1,33 @@
+###############################################################################
+# Top contributors (to current version):
+#   Andrew Reynolds
+#
+# This file is part of the cvc5 project.
+#
+# Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
+# in the top-level source directory and their institutional affiliations.
+# All rights reserved.  See the file COPYING in the top-level source
+# directory for licensing information.
+# #############################################################################
+#
+# Unit tests for synth result API.
+#
+# Obtained by translating test/unit/api/synth_result_black.cpp
+##
+
+import pytest
+import cvc5
+from cvc5 import SynthResult
+
+
+@pytest.fixture
+def solver():
+    return cvc5.Solver()
+
+
+def test_is_null(solver):
+    res_null = SynthResult(solver)
+    assert res_null.isNull()
+    assert not res_null.hasSolution()
+    assert not res_null.hasNoSolution()
+    assert not res_null.isUnknown()