Skip to content

Commit

Permalink
Working on cpp coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
Thrameos committed Jan 17, 2020
1 parent 5453c5e commit f4f9321
Show file tree
Hide file tree
Showing 13 changed files with 175 additions and 109 deletions.
4 changes: 1 addition & 3 deletions native/python/include/pyjp_field.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*****************************************************************************/
#ifndef _PYFIELD_H_
#define _PYFIELD_H_
Expand All @@ -31,8 +31,6 @@ struct PyJPField
static PyObject* getName(PyJPField* self, PyObject* arg);
static PyObject* __get__(PyJPField* self, PyObject* obj, PyObject* type);
static int __set__(PyJPField* self, PyObject* obj, PyObject* val);
static PyObject* isStatic(PyJPField* self, PyObject* arg);
static PyObject* isFinal(PyJPField* self, PyObject* arg);

JPField* m_Field;
} ;
Expand Down
1 change: 0 additions & 1 deletion native/python/include/pyjp_proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ struct PyJPProxy

static PyTypeObject Type;
static void initType(PyObject* module);
static bool check(PyObject* o);

static PyObject* __new__(PyTypeObject* self, PyObject* args, PyObject* kwargs);
static int __init__(PyJPProxy* self, PyObject* args, PyObject* kwargs);
Expand Down
1 change: 0 additions & 1 deletion native/python/include/pyjp_value.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ struct PyJPValue

static PyTypeObject Type;
static void initType(PyObject* module);
static bool check(PyObject* o);

// Object A
static PyObject* __new__(PyTypeObject* self, PyObject* args, PyObject* kwargs);
Expand Down
15 changes: 3 additions & 12 deletions native/python/jp_pythonenv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,7 @@ JPPyObject JPPythonEnv::getMethodDoc(PyJPMethod* javaMethod)
{
JP_TRACE_IN("JPPythonEnv::getMethodDoc");
if (s_Resources->s_GetMethodDoc.isNull())
{
JP_TRACE("Resource not set.");
return JPPyObject();
}
JP_RAISE_RUNTIME_ERROR("GetMethodDoc resource not set.");

ASSERT_NOT_NULL(javaMethod);

Expand Down Expand Up @@ -221,10 +218,7 @@ JPPyObject JPPythonEnv::getMethodAnnotations(PyJPMethod* javaMethod)
{
JP_TRACE_IN("JPPythonEnv::getMethodAnnotations");
if (s_Resources->s_GetMethodDoc.isNull())
{
JP_TRACE("Resource not set.");
return JPPyObject();
}
JP_RAISE_RUNTIME_ERROR("GetMethodAnnotations resource not set.");

ASSERT_NOT_NULL(javaMethod);

Expand Down Expand Up @@ -265,10 +259,7 @@ JPPyObject JPPythonEnv::getMethodCode(PyJPMethod* javaMethod)
{
JP_TRACE_IN("JPPythonEnv::getMethodCode");
if (s_Resources->s_GetMethodCode.isNull())
{
JP_TRACE("Resource not set.");
return JPPyObject();
}
JP_RAISE_RUNTIME_ERROR("GetMethodCode resource not set.");

ASSERT_NOT_NULL(javaMethod);

Expand Down
26 changes: 0 additions & 26 deletions native/python/pyjp_field.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@

static PyMethodDef fieldMethods[] = {
{"getName", (PyCFunction) (&PyJPField::getName), METH_NOARGS, ""},
{"isFinal", (PyCFunction) (&PyJPField::isFinal), METH_NOARGS, ""},
{"isStatic", (PyCFunction) (&PyJPField::isStatic), METH_NOARGS, ""},
{NULL},
};

Expand Down Expand Up @@ -150,27 +148,3 @@ int PyJPField::__set__(PyJPField* self, PyObject* obj, PyObject* pyvalue)
return -1;
JP_TRACE_OUT;
}

PyObject* PyJPField::isStatic(PyJPField* self, PyObject* arg)
{
try
{
ASSERT_JVM_RUNNING("PyJPField::isStatic");
JPJavaFrame frame;
return PyBool_FromLong(self->m_Field->isStatic());
}
PY_STANDARD_CATCH;
return NULL;
}

PyObject* PyJPField::isFinal(PyJPField* self, PyObject* arg)
{
try
{
ASSERT_JVM_RUNNING("PyJPField::isFinal");
JPJavaFrame frame;
return PyBool_FromLong(self->m_Field->isFinal());
}
PY_STANDARD_CATCH;
return NULL;
}
9 changes: 0 additions & 9 deletions native/python/pyjp_method.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,12 @@ struct PyGetSetDef methodGetSet[] = {
{"__name__", (getter) (&PyJPMethod::getName), NULL, NULL, NULL},
{"__doc__", (getter) (&PyJPMethod::getDoc), (setter) (&PyJPMethod::setDoc), NULL, NULL},
{"__annotations__", (getter) (&PyJPMethod::getAnnotations), (setter) (&PyJPMethod::setAnnotations), NULL, NULL},
#if PY_MAJOR_VERSION >= 3
{"__closure__", (getter) (&PyJPMethod::getClosure), NULL, NULL, NULL},
{"__code__", (getter) (&PyJPMethod::getCode), NULL, NULL, NULL},
{"__defaults__", (getter) (&PyJPMethod::getNone), NULL, NULL, NULL},
{"__kwdefaults__", (getter) (&PyJPMethod::getNone), NULL, NULL, NULL},
{"__globals__", (getter) (&PyJPMethod::getGlobals), NULL, NULL, NULL},
{"__qualname__", (getter) (&PyJPMethod::getQualName), NULL, NULL, NULL},
#else
{"func_closure", (getter) (&PyJPMethod::getClosure), NULL, NULL, NULL},
{"func_code", (getter) (&PyJPMethod::getCode), NULL, NULL, NULL},
{"func_defaults", (getter) (&PyJPMethod::getNone), NULL, NULL, NULL},
{"func_doc", (getter) (&PyJPMethod::getDoc), (setter) (&PyJPMethod::setDoc), NULL, NULL},
{"func_globals", (getter) (&PyJPMethod::getGlobals), NULL, NULL, NULL},
{"func_name", (getter) (&PyJPMethod::getName), NULL, NULL, NULL},
#endif
{NULL},
};

Expand Down
4 changes: 0 additions & 4 deletions native/python/pyjp_proxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,3 @@ int PyJPProxy::clear(PyJPProxy *self)
JP_TRACE_OUT;
}

bool PyJPProxy::check(PyObject* o)
{
return Py_TYPE(o) == &PyJPProxy::Type;
}
47 changes: 0 additions & 47 deletions native/python/pyjp_value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

static PyMethodDef classMethods[] = {
{"toString", (PyCFunction) (&PyJPValue::toString), METH_NOARGS, ""},
{"toUnicode", (PyCFunction) (&PyJPValue::toUnicode), METH_NOARGS, ""},
{NULL},
};

Expand Down Expand Up @@ -76,11 +75,6 @@ void PyJPValue::initType(PyObject* module)
PyModule_AddObject(module, "PyJPValue", (PyObject*) (&PyJPValue::Type));
}

bool PyJPValue::check(PyObject* o)
{
return Py_TYPE(o) == &PyJPValue::Type;
}

// These are from the internal methods when we alreayd have the jvalue

JPPyObject PyJPValue::alloc(const JPValue& value)
Expand Down Expand Up @@ -276,44 +270,3 @@ PyObject* PyJPValue::toString(PyJPValue* self)
return 0;
JP_TRACE_OUT;
}

/** This is the way to convert an object into a python string. */
PyObject* PyJPValue::toUnicode(PyJPValue* self)
{
JP_TRACE_IN("PyJPValue::toUnicode");
try
{
ASSERT_JVM_RUNNING("PyJPValue::toUnicode");
JPJavaFrame frame;
JPClass* cls = self->m_Value.getClass();
if (cls == JPTypeManager::_java_lang_String)
{
// Java strings are immutable so we will cache them.
ensureCache(self);
PyObject* out;
out = PyDict_GetItemString(self->m_Cache, "unicode"); // Borrowed reference
if (out == NULL)
{
jstring str = (jstring) self->m_Value.getValue().l;
if (str == NULL)
JP_RAISE_VALUE_ERROR("null string");
PyDict_SetItemString(self->m_Cache, "unicode", out = JPPyString::fromStringUTF8(JPJni::toStringUTF8(str), true).keep());
}
Py_INCREF(out);
return out;

}
if (cls->isPrimitive())
JP_RAISE_VALUE_ERROR("toUnicode requires a java object");
if (cls == NULL)
JP_RAISE_VALUE_ERROR("toUnicode called with null class");

// In general toString is not immutable, so we won't cache it.
return JPPyString::fromStringUTF8(JPJni::toString(self->m_Value.getValue().l), true).keep();
}
PY_STANDARD_CATCH;
return 0;
JP_TRACE_OUT;
}


14 changes: 8 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,21 @@
maintainer_email='cooperate@originell.org',
url='https://github.com/jpype-project/jpype',
platforms=[
'Operating System :: MacOS :: MacOS X',
'Operating System :: Microsoft :: Windows :: Windows 7',
'Operating System :: Microsoft :: Windows :: Windows Vista',
'Operating System :: POSIX :: Linux',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX',
'Operating System :: Unix',
'Operating System :: MacOS',
],
classifiers=[
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
],
topics=[
'Topic :: Software Development',
'Topic :: Scientific/Engineering',
],
packages=[
'jpype'],
package_dir={
Expand Down
5 changes: 5 additions & 0 deletions test/jpypetest/test_coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import sys
import os
import importlib
import _jpype

# Tests just for coverage
# These will be moved to the corresponding test file as needed
Expand Down Expand Up @@ -195,6 +196,10 @@ def testJStringRepr(self):
js = jpype.JString("fred")
self.assertTrue(repr(js), "fred")

def testSetResourceFail(self):
with self.assertRaises(RuntimeError):
_jpype.setResource("NotAResource", None)

# FIXME this one is broken
# def testJPrimitiveSetAttr(self):
# ji = jpype.JInt(1)
Expand Down
1 change: 1 addition & 0 deletions test/jpypetest/test_jclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,4 @@ def testInterfaceCtor(self):
with self.assertRaises(jpype.JException):
intr()


104 changes: 104 additions & 0 deletions test/jpypetest/test_module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Tests for module functionality including failures that cannot
# be triggered in normal operations
import _jpype
import unittest
import pickle
import os
import subprocess
import sys

# We don't want JPype loaded during this operation
if __name__!="subprocess":
import jpype

# Utility to run a subprocess and get the result
def subrun(function, *args):
""" Utility function to launch a subprocess and get the result. """
os.environ['PYTHONPATH'] = os.getcwd()
pickle.dump([*args], open("input.pic",'wb'))
child = subprocess.Popen([sys.executable, "-"],stdin=subprocess.PIPE)
prog= []
prog.append('with open(r"%s","r") as fd:'%os.path.abspath(__file__))
prog.append(' contents=fd.read()')
prog.append('__name__="subprocess"')
prog.append('exec(contents)')
prog.append('args=pickle.load(open("input.pic","rb"))')
prog.append('ex=None')
prog.append('ret=None')
prog.append('try:')
prog.append(' ret=%s(*args)'%function.__name__)
prog.append('except Exception as ex1:')
prog.append(' ex=ex1')
prog.append('pickle.dump([ret,ex], open("output.pic","wb"))')
child.communicate(input=bytes("\n".join(prog), 'utf-8'))
[ret,ex]=pickle.load(open("output.pic","rb"))
child.wait()
os.remove("input.pic")
os.remove("output.pic")
if ex:
raise ex
return ret


##############################################################################
# Test methods

def runStartup(path):
_jpype.startup(path, tuple(), False, False)
return True

def runStartupBadArgs(path):
_jpype.startup(path)

def runNoMethodDoc(path):
_jpype.startup(path, tuple(), False, False)
cls = _jpype.PyJPClass("java.lang.String")
methods = cls.getClassMethods()
methods[0].__doc__ # RuntimeError

def runNoMethodAnnotation(path):
_jpype.startup(path, tuple(), False, False)
cls = _jpype.PyJPClass("java.lang.String")
methods = cls.getClassMethods()
methods[0].__annotations__ # RuntimeError

def runNoMethodCode(path):
_jpype.startup(path, tuple(), False, False)
cls = _jpype.PyJPClass("java.lang.String")
methods = cls.getClassMethods()
methods[0].__code__ # RuntimeError

def runValueEntry():
# fails as no JVM is running yet
_jpype.PyJPValue()

def runShutdown():
import jpype
jpype.startJVM(convertStrings=False)
jpype.shutdownJVM()


##############################################################################

class TestModule(unittest.TestCase):
def setUp(self):
self.path = jpype.getDefaultJVMPath()
def testStartup(self):
self.assertTrue(subrun(runStartup, self.path))
def testStartupBadArgs(self):
with self.assertRaises(TypeError):
subrun(runStartupBadArgs, self.path)
def testNoMethodDoc(self):
with self.assertRaises(RuntimeError):
subrun(runNoMethodDoc, self.path)
def testNoMethodAnnotation(self):
with self.assertRaises(RuntimeError):
subrun(runNoMethodAnnotation, self.path)
def testNoMethodCode(self):
with self.assertRaises(RuntimeError):
subrun(runNoMethodCode, self.path)
def testValueEntry(self):
with self.assertRaises(RuntimeError):
subrun(runValueEntry)
def testShutdown(self):
subrun(runShutdown)
Loading

0 comments on commit f4f9321

Please sign in to comment.