tests.java.org.python.expose.generate.MethodExposerTest Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jython-standalone Show documentation
Show all versions of jython-standalone Show documentation
Jython is an implementation of the high-level, dynamic, object-oriented
language Python written in 100% Pure Java, and seamlessly integrated with
the Java platform. It thus allows you to run Python on any Java platform.
package org.python.expose.generate;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.python.core.BytecodeLoader;
import org.python.core.Py;
import org.python.core.PyBuiltinCallable;
import org.python.core.PyException;
import org.python.core.PyObject;
import org.python.core.ThreadState;
import org.python.expose.MethodType;
public class MethodExposerTest extends InterpTestCase implements Opcodes, PyTypes {
public static InstanceMethodExposer createExposer(String methodName,
Type returnType,
Type... args) {
return new InstanceMethodExposer(Type.getType(SimpleExposed.class),
Opcodes.ACC_PUBLIC,
methodName,
Type.getMethodDescriptor(returnType, args),
"simpleexposed");
}
public static PyBuiltinCallable createBound(String methodName, Type returnType, Type... args)
throws Exception {
return createBound(createExposer(methodName, returnType, args));
}
public static PyBuiltinCallable createBound(MethodExposer me) throws Exception {
Class> descriptor = me.load(new BytecodeLoader.Loader());
PyBuiltinCallable func = instantiate(descriptor, me.getNames()[0]);
if (me instanceof ClassMethodExposer) {
return func.bind(new SimpleExposed().getType());
}
return func.bind(new SimpleExposed());
}
public static PyBuiltinCallable instantiate(Class> descriptor, String name) throws Exception {
return (PyBuiltinCallable)descriptor.getConstructor(String.class).newInstance(name);
}
public void testSimpleMethod() throws Exception {
InstanceMethodExposer mp = createExposer("simple_method", VOID);
assertEquals("simple_method", mp.getNames()[0]);
assertEquals("org/python/expose/generate/SimpleExposed$simple_method_exposer",
mp.getInternalName());
assertEquals("org.python.expose.generate.SimpleExposed$simple_method_exposer",
mp.getClassName());
Class descriptor = mp.load(new BytecodeLoader.Loader());
PyBuiltinCallable instance = instantiate(descriptor, "simple_method");
assertSame("simple_method", instance.__getattr__("__name__").toString());
SimpleExposed simpleExposed = new SimpleExposed();
PyBuiltinCallable bound = instance.bind(simpleExposed);
assertEquals(instance.getClass(), bound.getClass());
assertEquals(Py.None, bound.__call__());
assertEquals(1, simpleExposed.timesCalled);
}
public void testPrefixing() throws Exception {
assertEquals("prefixed", createExposer("simpleexposed_prefixed", VOID).getNames()[0]);
}
public void testStringReturn() throws Exception {
assertEquals(Py.newString(SimpleExposed.TO_STRING_RETURN),
createBound("toString", STRING).__call__());
}
public void testBooleanReturn() throws Exception {
assertEquals(Py.False, createBound("__nonzero__", BOOLEAN).__call__());
}
public void testArgumentPassing() throws Exception {
PyBuiltinCallable bound = createBound("takesArgument", Type.DOUBLE_TYPE, PYOBJ);
assertEquals(1.0, Py.py2double(bound.__call__(Py.One)));
try {
bound.__call__();
fail("Need to pass an argument to takesArgument");
} catch (Exception e) {}
}
public void testBinary() throws Exception {
InstanceMethodExposer exposer = createExposer("__add__", PYOBJ, PYOBJ);
exposer.type = MethodType.BINARY;
PyBuiltinCallable bound = createBound(exposer);
assertEquals(Py.NotImplemented, bound.__call__(Py.None));
assertEquals(Py.One, bound.__call__(Py.False));
}
public void testCmp() throws Exception {
InstanceMethodExposer exp = createExposer("__cmp__", INT, PYOBJ);
exp.type = MethodType.CMP;
PyBuiltinCallable bound = createBound(exp);
try {
bound.__call__(Py.None);
fail("Returning -2 from __cmp__ should yield a type error");
} catch (PyException e) {
if (!e.match(Py.TypeError)) {
fail("Returning -2 from __cmp__ should yield a type error");
}
}
assertEquals(Py.One, bound.__call__(Py.False));
}
public void testNoneDefault() throws Exception {
InstanceMethodExposer exp = createExposer("defaultToNone", PYOBJ, PYOBJ);
exp.defaults = new String[] {"Py.None"};
PyBuiltinCallable bound = createBound(exp);
assertEquals(Py.One, bound.__call__(Py.One));
assertEquals(Py.None, bound.__call__());
}
public void testNullDefault() throws Exception {
InstanceMethodExposer exp = createExposer("defaultToNull", PYOBJ, PYOBJ);
exp.defaults = new String[] {"null"};
PyBuiltinCallable bound = createBound(exp);
assertEquals(Py.One, bound.__call__(Py.One));
assertEquals(null, bound.__call__());
}
public void testIntDefault() throws Exception {
InstanceMethodExposer exp = createExposer("defaultToOne", PYOBJ, INT);
exp.defaults = new String[] {"1"};
PyBuiltinCallable bound = createBound(exp);
assertEquals(Py.Zero, bound.__call__(Py.Zero));
assertEquals(Py.One, bound.__call__());
exp.defaults = new String[] {"X"};
try {
createBound(exp);
fail("Shouldn't be able to create the exposer with a non-int default value");
} catch (NumberFormatException nfe) {}
}
public void testPrimitiveDefaults() throws Exception {
InstanceMethodExposer exp = createExposer("manyPrimitives",
STRING,
CHAR,
SHORT,
Type.DOUBLE_TYPE,
BYTE);
exp.defaults = new String[] {"a", "1", "2", "3"};
PyBuiltinCallable bound = createBound(exp);
assertEquals("a12.03", bound.__call__().toString());
assertEquals("b12.03", bound.__call__(Py.newString('b')).toString());
exp.defaults = new String[] {"ab", "1", "2", "3"};
try {
createBound(exp);
fail("Char should only be one character");
} catch (InvalidExposingException iee) {}
}
public void testFullArguments() throws Exception {
InstanceMethodExposer exp = new InstanceMethodExposer(Type.getType(SimpleExposed.class),
Opcodes.ACC_PUBLIC,
"fullArgs",
Type.getMethodDescriptor(Type.LONG_TYPE,
new Type[] {APYOBJ,
ASTRING}),
"simpleexposed");
PyBuiltinCallable bound = createBound(exp);
assertEquals(Py.Zero, bound.__call__());
assertEquals(Py.One, bound.__call__(Py.One));
try {
new InstanceMethodExposer(Type.getType(SimpleExposed.class),
Opcodes.ACC_PUBLIC,
"fullArgs",
Type.getMethodDescriptor(PYOBJ, new Type[] {APYOBJ, ASTRING}),
"simpleexposed",
new String[0],
new String[] {"X"},
MethodType.DEFAULT,
"");
fail("Shouldn't be able to create the exposer with a default value");
} catch (InvalidExposingException ite) {}
}
public void testExposingStatic() {
try {
new InstanceMethodExposer(Type.getType(SimpleExposed.class),
Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
"fullArgs",
Type.getMethodDescriptor(PYOBJ, new Type[] {APYOBJ, ASTRING}),
"simpleexposed");
fail("Shouldn't be able to create an exposer on a static method");
} catch (InvalidExposingException ite) {}
}
public void testPrimitiveReturns() throws Exception {
assertEquals(12, Py.py2int(createBound("shortReturn", SHORT).__call__()));
assertEquals(0, Py.py2int(createBound("byteReturn", BYTE).__call__()));
assertEquals("a", createBound("charReturn", CHAR).__call__().toString());
}
public void testNullReturns() throws Exception {
assertEquals(Py.None, createBound("stringReturnNull", STRING).__call__());
}
public void testClassMethod() throws Exception {
ClassMethodExposer exp = new ClassMethodExposer(Type.getType(SimpleExposed.class),
Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
"classmethod",
Type.getMethodDescriptor(CHAR,
new Type[] {PYTYPE}),
"simpleexposed",
new String[0],
new String[0],
"");
PyBuiltinCallable bound = createBound(exp);
assertEquals("a", bound.__call__().toString());
}
public void testClassMethodDefaults() throws Exception {
ClassMethodExposer exp = new ClassMethodExposer(Type.getType(SimpleExposed.class),
Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
"defaultsclassmethod",
Type.getMethodDescriptor(INT,
new Type[] {PYTYPE,
STRING,
PYOBJ}),
"simpleexposed",
new String[0],
new String[] {"null", "Py.None"},
"");
PyBuiltinCallable bound = createBound(exp);
assertEquals(0, bound.__call__().asInt());
assertEquals(1, bound.__call__(Py.newString("hello")).asInt());
assertEquals(2, bound.__call__(Py.newString("nothello"), Py.None).asInt());
assertEquals(3, bound.__call__(Py.newString("nothello"), Py.One).asInt());
}
public void testThreadState() throws Exception {
PyBuiltinCallable bound = createBound("needsThreadState", STRING, THREAD_STATE, STRING);
ThreadState ts = Py.getThreadState();
PyObject expected = Py.newString("foo got state " + ts.hashCode());
assertEquals(expected, bound.__call__(Py.getThreadState(), Py.newString("foo")));
assertEquals(expected, bound.__call__(Py.newString("foo")));
ts = new ThreadState(ts.systemState);
assertEquals(Py.newString("foo got state " + ts.hashCode()),
bound.__call__(ts, Py.newString("foo")));
}
public void testThreadStateFullArguments() throws Exception {
InstanceMethodExposer exp = new InstanceMethodExposer(Type.getType(SimpleExposed.class),
Opcodes.ACC_PUBLIC,
"needsThreadStateWide",
Type.getMethodDescriptor(Type.INT_TYPE,
new Type[] {THREAD_STATE,
APYOBJ,
ASTRING}),
"simpleexposed");
PyBuiltinCallable bound = createBound(exp);
assertEquals(Py.Zero, bound.__call__(Py.getThreadState()));
assertEquals(Py.Zero, bound.__call__());
assertEquals(Py.One, bound.__call__(Py.getThreadState(), Py.One));
assertEquals(Py.One, bound.__call__(Py.One));
}
public void testThreadStateClassMethod() throws Exception {
ClassMethodExposer exp = new ClassMethodExposer(Type.getType(SimpleExposed.class),
Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
"needsThreadStateClass",
Type.getMethodDescriptor(STRING,
new Type[] {THREAD_STATE,
PYTYPE,
STRING,
STRING}),
"simpleexposed",
new String[0],
new String[] {"null"},
"");
PyBuiltinCallable bound = createBound(exp);
ThreadState ts = Py.getThreadState();
PyObject arg0 = Py.newString("bar");
PyObject arg1 = Py.newString(" and extra");
PyObject expected = Py.newString("bar got state " + ts.hashCode() + " got type and extra");
assertEquals(expected, bound.__call__(Py.getThreadState(), arg0, arg1));
assertEquals(expected, bound.__call__(arg0, arg1));
}
public void test__new__() throws Exception {
try {
createExposer("__new__", VOID);
fail("Shouldn't be able to make a MethodExposer with the name __new__");
} catch (InvalidExposingException ite) {}
}
}