def test_primitive(self): obj = jclass("com.chaquo.python.TestOverload$Primitive")() self.assertEqual(obj.resolve(True), 'boolean true') self.assertEqual(obj.resolve(jboolean(True)), 'boolean true') self.assertEqual(obj.resolve(42), 'long 42') self.assertEqual(obj.resolve(jbyte(42)), 'byte 42') self.assertEqual(obj.resolve(jshort(42)), 'short 42') self.assertEqual(obj.resolve(jint(42)), 'int 42') self.assertEqual(obj.resolve(jlong(42)), 'long 42') self.assertEqual(obj.resolve(1.23), 'double 1.23') self.assertEqual(obj.resolve(jfloat(1.23)), 'float 1.23') self.assertEqual(obj.resolve(jdouble(1.23)), 'double 1.23') # When passing an int, applicable integral overloads should be preferred over floating # overloads no matter what the value is. self.assertEqual(obj.resolve_SF(42), 'short 42') with self.too_big: obj.resolve_SF(100000) self.assertEqual(obj.resolve_SF(float(100000)), 'float 100000.0') self.assertEqual(obj.resolve_IJ(42), 'long 42') self.assertEqual(obj.resolve_IJ(jbyte(42)), 'int 42') self.assertEqual(obj.resolve_IJ(jshort(42)), 'int 42') self.assertEqual(obj.resolve_IJ(jint(42)), 'int 42') self.assertEqual(obj.resolve_IJ(jlong(42)), 'long 42') self.assertEqual(obj.resolve_BIF(42), 'int 42') self.assertEqual(obj.resolve_BIF(jbyte(42)), 'byte 42') self.assertEqual(obj.resolve_BIF(jshort(42)), 'int 42') self.assertEqual(obj.resolve_BIF(jint(42)), 'int 42') self.assertEqual(obj.resolve_BIF(jlong(42)), 'float 42.0') self.assertEqual(obj.resolve_BIF(jfloat(42)), 'float 42.0') with self.inapplicable: obj.resolve_BIF(jdouble(42)) # This may seem inconsistent, but it's what Java does. float and double are both # applicable when passing an int, and float is more specific. self.assertEqual(obj.resolve_FD(42), 'float 42.0') self.assertEqual(obj.resolve_FD(42.0), 'double 42.0') self.assertEqual(obj.resolve_FD(jdouble(42)), 'double 42.0')
def test_varargs(self): obj = jclass("com.chaquo.python.TestOverload$Varargs")() self.assertEqual("", obj.resolve_empty_single_I()) self.assertEqual("int... []", obj.resolve_empty_single_I([])) self.assertEqual("int... null", obj.resolve_empty_single_I(None)) self.assertEqual("int 1", obj.resolve_empty_single_I(1)) self.assertEqual("int... [1]", obj.resolve_empty_single_I([1])) self.assertEqual("int... [1, 2]", obj.resolve_empty_single_I(1, 2)) self.assertEqual("int... [1, 2]", obj.resolve_empty_single_I([1, 2])) self.assertEqual("int... []", obj.resolve_ID()) # int is more specific than double. with self.ambiguous: obj.resolve_ID(None) # But int[] is not more specific than double[]. self.assertEqual("int... null", obj.resolve_ID(cast(jarray(jint), None))) self.assertEqual("double... null", obj.resolve_ID(cast(jarray(jdouble), None))) with self.inapplicable: obj.resolve_ID(None, None) self.assertEqual("int 42", obj.resolve_ID(42)) self.assertEqual("double 42.0", obj.resolve_ID(42.0)) self.assertEqual("double... [1.0, 2.0]", obj.resolve_ID(jarray(jdouble)([1, 2]))) self.assertEqual("double... [1.0, 2.0]", obj.resolve_ID(1.0, 2.0)) self.assertEqual("double... [1.0, 2.0]", obj.resolve_ID(1, 2.0)) self.assertEqual("double... [1.0, 2.0]", obj.resolve_ID(1.0, 2)) Long = jclass("java.lang.Long") with self.ambiguous: obj.resolve_I_Long() # Neither int nor Long are more specific. with self.ambiguous: obj.resolve_I_Long(None) # Neither int[] nor Long[] are more specific. self.assertEqual("Long... [null, null]", obj.resolve_I_Long(None, None)) with self.ambiguous: obj.resolve_I_Long(42) with self.inapplicable: obj.resolve_I_Long(42.0) self.assertEqual("int... [42]", obj.resolve_I_Long(jint(42))) self.assertEqual("Long... [42]", obj.resolve_I_Long(jlong(42))) self.assertEqual("Long... [42]", obj.resolve_I_Long(Long(42))) Number = jclass("java.lang.Number") # Long[] is more specific than Number[]. self.assertEqual("Long... []", obj.resolve_Number_Long()) self.assertEqual("Long... [42]", obj.resolve_Number_Long(42)) self.assertEqual("Long... null", obj.resolve_Number_Long(None)) self.assertEqual("Long... [null]", obj.resolve_Number_Long([None])) self.assertEqual("Long... [null, null]", obj.resolve_Number_Long(None, None)) self.assertEqual("Number... [42]", obj.resolve_Number_Long(cast(Number, Long(42)))) self.assertEqual("Number... null", obj.resolve_Number_Long(cast(jarray(Number), None))) self.assertEqual("Number... [null]", obj.resolve_Number_Long(cast(Number, None))) self.assertEqual("Number... [42]", obj.resolve_Number_Long(jarray(Number)([42]))) self.assertEqual("Number... [null]", obj.resolve_Number_Long(jarray(Number)([None])))
def test_boxing(self): obj = jclass("com.chaquo.python.TestOverload$Boxing")() Boolean = jclass("java.lang.Boolean") self.assertEqual(obj.resolve_Z_Boolean(True), 'boolean true') self.assertEqual(obj.resolve_Z_Boolean(jboolean(True)), 'boolean true') self.assertEqual(obj.resolve_Z_Boolean(Boolean(True)), 'Boolean true') self.assertEqual(obj.resolve_Z_Object(True), 'boolean true') self.assertEqual(obj.resolve_Z_Object(jboolean(True)), 'boolean true') self.assertEqual(obj.resolve_Z_Object(Boolean(True)), 'Object true') Long = jclass("java.lang.Long") Short = jclass("java.lang.Short") # When passing a primitive, applicable primitive overloads should be preferred over # boxed overloads no matter what the value is. self.assertEqual(obj.resolve_S_Long(42), 'short 42') with self.too_big: obj.resolve_S_Long(100000) self.assertEqual(obj.resolve_S_Long(jlong(100000)), 'Long 100000') self.assertEqual(obj.resolve_S_Long(jbyte(42)), 'short 42') self.assertEqual(obj.resolve_S_Long(jshort(42)), 'short 42') with self.inapplicable: # Automatic primitive conversion cannot be combined with autoboxing (JLS 5.3). obj.resolve_S_Long(jint(42)) self.assertEqual(obj.resolve_S_Long(jlong(42)), 'Long 42') self.assertEqual(obj.resolve_S_Long(Long(42)), 'Long 42') with self.inapplicable: # Auto-unboxing is not currently implemented. obj.resolve_S_Long(Short(42)) self.assertEqual(obj.resolve_Short_L(42), 'long 42') self.assertEqual(obj.resolve_Short_L(100000), 'long 100000') self.assertEqual(obj.resolve_Short_L(jbyte(42)), 'long 42') self.assertEqual(obj.resolve_Short_L(jshort(42)), 'long 42') self.assertEqual(obj.resolve_Short_L(jint(42)), 'long 42') self.assertEqual(obj.resolve_Short_L(jlong(42)), 'long 42') self.assertEqual(obj.resolve_Short_L(Short(42)), 'Short 42') with self.ambiguous: obj.resolve_Short_Long(42) with self.too_big: # It would be better to give an ambiguous overload error, but this message should # be clear enough to indicate that the short overload is being considered, and the # programmer can then use a wrapper to exclude it. obj.resolve_Short_Long(100000) with self.inapplicable: obj.resolve_Short_Long(jbyte(42)) self.assertEqual(obj.resolve_Short_Long(jshort(42)), 'Short 42') with self.inapplicable: obj.resolve_Short_Long(jint(42)) self.assertEqual(obj.resolve_Short_Long(jlong(42)), 'Long 42') self.assertEqual(obj.resolve_Short_Long(jlong(100000)), 'Long 100000') with self.ambiguous: obj.resolve_Integer_Float(42) self.assertEqual(obj.resolve_Integer_Float(42.0), 'Float 42.0') self.assertEqual(obj.resolve_Integer_Float(jfloat(42)), 'Float 42.0') with self.ambiguous: obj.resolve_Float_Double(42) with self.ambiguous: obj.resolve_Float_Double(42.0) with self.inapplicable: obj.resolve_Float_Double(jint(42)) self.assertEqual(obj.resolve_Float_Double(jfloat(42)), 'Float 42.0') self.assertEqual(obj.resolve_Float_Double(jdouble(42)), 'Double 42.0')