[tests] Generate some trampoline and registrar tests.

Generate trampoline and registrar tests that tests if a return type requires objc_msgSend or objc_msgSend_stret.

Now it's much easier to test new return types (a single line of code), which
avoids a _lot_ of copy-pasting, and makes sure all the different variations
are tested properly.

These new tests found several bugs, which are fixed in subsequent commits.
This commit is contained in:
Rolf Bjarne Kvinge 2016-10-07 12:48:01 +02:00
Родитель 084e691be2
Коммит d395e8df59
14 изменённых файлов: 669 добавлений и 750 удалений

1
tests/.gitignore поставляемый
Просмотреть файл

@ -25,4 +25,5 @@ mac-test-package
.nuget
logs
*.mSYM
*.generated.cs

Просмотреть файл

@ -40,7 +40,7 @@ namespace Bindings.Test {
* ObjC test class used for registrar
*/
[BaseType (typeof (NSObject))]
interface ObjCRegistrarTest {
partial interface ObjCRegistrarTest {
[Export ("Pi1")]
int Pi1 { get; set; }
@ -137,15 +137,6 @@ namespace Bindings.Test {
[Export ("Pc5")]
sbyte Pc5 { get; set; }
[Export ("PSiid1")]
Siid PSiid { get; set; }
[Export ("PSd1")]
Sd PSd { get; set; }
[Export ("PSf1")]
Sf PSf { get; set; }
[Export ("V")]
void V ();

Просмотреть файл

@ -7,32 +7,6 @@ using nint=System.Int32;
namespace Bindings.Test
{
public struct Sd { public double d1; }
public struct Sdd { public double d1; public double d2; }
public struct Sddd { public double d1; public double d2; public double d3; }
public struct Sdddd { public double d1; public double d2; public double d3; public double d4; }
public struct Si { public int i1; }
public struct Sii { public int i1; public int i2; }
public struct Siii { public int i1; public int i2; public int i3; }
public struct Siiii { public int i1; public int i2; public int i3; public int i4; }
public struct Siiiii { public int i1; public int i2; public int i3; public int i4; public int i5; }
public struct Sid { public int i1; public double d2; }
public struct Sdi { public double d1; public int i2; }
public struct Sidi { public int i1; public double d2; public int i3; }
public struct Siid { public int i1; public int i2; public double d3; }
public struct Sddi { public double d1; public double d2; public int i3; }
public struct Sl { public nint l1; }
public struct Sll { public nint l1; public nint l2; }
public struct Slll { public nint l1; public nint l2; public nint l3; }
public struct Scccc { public char c1; public char c2; public char c3; public char c4; }
public struct Sffff { public float f1; public float f2; public float f3; public float f4; }
public struct Sif { public int i1; public float f2; }
public struct Sf { public float f1; }
public struct Sff { public float f1; public float f2; }
public struct Siff { public int i1; public float f2; public float f3; }
public struct Siiff { public int i1; public int i2; public float f3; public float f4; }
public struct Sfi { public float f1; public int i2; }
public static class CFunctions {
[DllImport ("__Internal")]
public static extern int theUltimateAnswer ();

Просмотреть файл

@ -47,10 +47,12 @@
</ItemGroup>
<ItemGroup>
<ObjcBindingApiDefinition Include="ApiDefinition.cs" />
<ObjcBindingApiDefinition Include="ApiDefinition.generated.cs" />
<ObjcBindingApiDefinition Include="ApiProtocol.cs" />
</ItemGroup>
<ItemGroup>
<ObjcBindingCoreSource Include="StructsAndEnums.cs" />
<ObjcBindingCoreSource Include="StructsAndEnums.generated.cs" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.ObjCBinding.CSharp.targets" />
<ItemGroup>
@ -74,8 +76,26 @@
<None Include="..\..\tests\test-libraries\libtest.h">
<Link>libtest.h</Link>
</None>
<None Include="..\..\tests\test-libraries\libtest.structs.h">
<Link>libtest.structs.h</Link>
</None>
<None Include="..\..\tests\test-libraries\libtest.properties.h">
<Link>libtest.properties.h</Link>
</None>
<None Include="..\..\tests\test-libraries\testgenerator.cs">
<Link>testgenerator.cs</Link>
</None>
</ItemGroup>
<Target Name="BeforeBuild" Inputs="..\..\tests\test-libraries\libtest.m" Outputs="..\..\tests\test-libraries\.libs\ios\libtest.a">
<ItemGroup>
<GeneratedTestInput Include="..\..\tests\test-libraries\*.m" />
<GeneratedTestInput Include="..\..\tests\test-libraries\*.h" />
<GeneratedTestInput Include="..\..\tests\test-libraries\*.cs" />
<GeneratedTestInput Include="..\..\tests\test-libraries\Makefile" />
<GeneratedTestOutput Include="..\..\tests\test-libraries\.libs\ios\libtest.a" />
<GeneratedTestOutput Include="ApiDefinition.generated.cs" />
<GeneratedTestOutput Include="StructsAndEnums.generated.cs" />
</ItemGroup>
<Target Name="BeforeBuild" Inputs="@(GeneratedTestInput)" Outputs="@(GeneratedTestOutput)">
<Exec Command="make -j8 -C ..\..\tests\test-libraries" />
</Target>
</Project>

Просмотреть файл

@ -1638,151 +1638,14 @@ namespace MonoTouchFixtures.ObjCRuntime {
public void Test_D ()
{
using (var tc = new ObjCRegistrarTest ()) {
Verify (tc, Pd1: 0);
Assert.AreEqual (tc.Pd1, 0, "Pd1");
Assert.AreEqual (0, tc.D (), "1");
tc.Pd1 = 1.2;
Assert.AreEqual (1.2, tc.D (), "2");
Verify (tc, Pd1: 1.2);
Assert.AreEqual (tc.Pd1, 1.2, "Pd1");
}
}
[Test]
public void Test_Sd ()
{
using (var tc = new ObjCRegistrarTest ()) {
Assert.AreEqual (0, tc.Sd ().d1, "1");
Verify (tc, PSd1: new Sd () );
tc.PSd = new Sd () { d1 = 1.23 };
Assert.AreEqual (1.23, tc.Sd ().d1, "2");
Verify (tc, PSd1: new Sd () { d1 = 1.23 });
}
}
void Verify (ObjCRegistrarTest obj, string msg = null,
int? Pi1 = null,
int? Pi2 = null,
int? Pi3 = null,
int? Pi4 = null,
int? Pi5 = null,
int? Pi6 = null,
int? Pi7 = null,
int? Pi8 = null,
int? Pi9 = null,
float? Pf1 = null,
float? Pf2 = null,
float? Pf3 = null,
float? Pf4 = null,
float? Pf5 = null,
float? Pf6 = null,
float? Pf7 = null,
float? Pf8 = null,
float? Pf9 = null,
double? Pd1 = null,
double? Pd2 = null,
double? Pd3 = null,
double? Pd4 = null,
double? Pd5 = null,
double? Pd6 = null,
double? Pd7 = null,
double? Pd8 = null,
double? Pd9 = null,
char? Pc1 = null,
char? Pc2 = null,
char? Pc3 = null,
char? Pc4 = null,
char? Pc5 = null,
char? Pc6 = null,
char? Pc7 = null,
char? Pc8 = null,
char? Pc9 = null,
Siid? PSiid1 = null,
Sd? PSd1 = null,
Sf? PSf1 = null)
{
if (Pi1.HasValue)
Assert.AreEqual (obj.Pi1, Pi1.Value, "Pi1");
if (Pi2.HasValue)
Assert.AreEqual (obj.Pi2, Pi2.Value, "Pi2");
if (Pi3.HasValue)
Assert.AreEqual (obj.Pi3, Pi3.Value, "Pi3");
if (Pi4.HasValue)
Assert.AreEqual (obj.Pi4, Pi4.Value, "Pi4");
if (Pi5.HasValue)
Assert.AreEqual (obj.Pi5, Pi5.Value, "Pi5");
if (Pi6.HasValue)
Assert.AreEqual (obj.Pi6, Pi6.Value, "Pi6");
if (Pi7.HasValue)
Assert.AreEqual (obj.Pi7, Pi7.Value, "Pi7");
if (Pi8.HasValue)
Assert.AreEqual (obj.Pi8, Pi8.Value, "Pi8");
if (Pi9.HasValue)
Assert.AreEqual (obj.Pi9, Pi9.Value, "Pi9");
if (Pf1.HasValue)
Assert.AreEqual (obj.Pf1, Pf1.Value, "Pf1");
if (Pf2.HasValue)
Assert.AreEqual (obj.Pf2, Pf2.Value, "Pf2");
if (Pf3.HasValue)
Assert.AreEqual (obj.Pf3, Pf3.Value, "Pf3");
if (Pf4.HasValue)
Assert.AreEqual (obj.Pf4, Pf4.Value, "Pf4");
if (Pf5.HasValue)
Assert.AreEqual (obj.Pf5, Pf5.Value, "Pf5");
if (Pf6.HasValue)
Assert.AreEqual (obj.Pf6, Pf6.Value, "Pf6");
if (Pf7.HasValue)
Assert.AreEqual (obj.Pf7, Pf7.Value, "Pf7");
if (Pf8.HasValue)
Assert.AreEqual (obj.Pf8, Pf8.Value, "Pf8");
if (Pf9.HasValue)
Assert.AreEqual (obj.Pf9, Pf9.Value, "Pf9");
if (Pd1.HasValue)
Assert.AreEqual (obj.Pd1, Pd1.Value, "Pd1");
if (Pd2.HasValue)
Assert.AreEqual (obj.Pd2, Pd2.Value, "Pd2");
if (Pd3.HasValue)
Assert.AreEqual (obj.Pd3, Pd3.Value, "Pd3");
if (Pd4.HasValue)
Assert.AreEqual (obj.Pd4, Pd4.Value, "Pd4");
if (Pd5.HasValue)
Assert.AreEqual (obj.Pd5, Pd5.Value, "Pd5");
if (Pd6.HasValue)
Assert.AreEqual (obj.Pd6, Pd6.Value, "Pd6");
if (Pd7.HasValue)
Assert.AreEqual (obj.Pd7, Pd7.Value, "Pd7");
if (Pd8.HasValue)
Assert.AreEqual (obj.Pd8, Pd8.Value, "Pd8");
if (Pd9.HasValue)
Assert.AreEqual (obj.Pd9, Pd9.Value, "Pd9");
if (Pc1.HasValue)
Assert.AreEqual (obj.Pc1, Pc1.Value, "Pc1");
if (Pc2.HasValue)
Assert.AreEqual (obj.Pc2, Pc2.Value, "Pc2");
if (Pc3.HasValue)
Assert.AreEqual (obj.Pc3, Pc3.Value, "Pc3");
if (Pc4.HasValue)
Assert.AreEqual (obj.Pc4, Pc4.Value, "Pc4");
if (Pc5.HasValue)
Assert.AreEqual (obj.Pc5, Pc5.Value, "Pc5");
// if (Pc6.HasValue)
// Assert.AreEqual (obj.Pc6, Pc6.Value, "Pc6");
// if (Pc7.HasValue)
// Assert.AreEqual (obj.Pc7, Pc7.Value, "Pc7");
// if (Pc8.HasValue)
// Assert.AreEqual (obj.Pc8, Pc8.Value, "Pc8");
// if (Pc9.HasValue)
// Assert.AreEqual (obj.Pc9, Pc9.Value, "Pc9");
if (PSiid1.HasValue)
Assert.AreEqual (obj.PSiid, PSiid1.Value, "PSiid1");
if (PSd1.HasValue)
Assert.AreEqual (obj.PSd, PSd1.Value, "PSd1");
if (PSf1.HasValue)
Assert.AreEqual (obj.PSf, PSf1.Value, "PSf1");
}
public class TestClass : ObjCRegistrarTest
{
}

Просмотреть файл

@ -43,10 +43,19 @@ namespace MonoTouchFixtures.ObjCRuntime {
public class TrampolineTest {
public static readonly nfloat pi = 3.14159f;
public bool IsSim64 { get { return IntPtr.Size == 8 && Runtime.Arch == Arch.SIMULATOR; } }
public bool IsSim32 { get { return IntPtr.Size == 4 && Runtime.Arch == Arch.SIMULATOR; } }
public bool IsArm64 { get { return IntPtr.Size == 8 && Runtime.Arch == Arch.DEVICE; } }
public bool IsArm32 { get { return IntPtr.Size == 4 && Runtime.Arch == Arch.DEVICE; } }
public static bool IsSim64 { get { return IntPtr.Size == 8 && Runtime.Arch == Arch.SIMULATOR; } }
public static bool IsSim32 { get { return IntPtr.Size == 4 && Runtime.Arch == Arch.SIMULATOR; } }
public static bool IsArm64 { get { return IntPtr.Size == 8 && Runtime.Arch == Arch.DEVICE; } }
public static bool IsArm32 {
get {
#if __WATCHOS__
return false;
#else
return IntPtr.Size == 4 && Runtime.Arch == Arch.DEVICE;
#endif
}
}
public static bool IsArmv7k {
get {
#if __WATCHOS__
@ -76,229 +85,6 @@ namespace MonoTouchFixtures.ObjCRuntime {
}
#endif // !__WATCHOS__
[Test]
public void StretIIIITrampolineTest ()
{
StretTrampolines obj = new StretTrampolines ();
IntPtr class_ptr = Class.GetHandle ("StretTrampolines");
IIIIStruct rv = new IIIIStruct ();
double rvd;
float rvf;
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = IIIIStruct_objc_msgSend (obj.Handle, new Selector ("Test_IIIIStruct").Handle);
} else {
IIIIStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_IIIIStruct").Handle);
}
Assert.That ("[1;2;3;4]" == rv.ToString ());
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = IIIIStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticIIIIStruct").Handle);
} else {
IIIIStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticIIIIStruct").Handle);
}
Assert.That ("[10;20;30;40]" == rv.ToString ());
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = IIIIStruct_objc_msgSend (obj.Handle, new Selector ("Test_IIIIStructProperty").Handle);
} else {
IIIIStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_IIIIStructProperty").Handle);
}
Assert.That ("[100;200;300;400]" == rv.ToString ());
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = IIIIStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticIIIIStructProperty").Handle);
} else {
IIIIStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticIIIIStructProperty").Handle);
}
Assert.That ("[1000;2000;3000;4000]" == rv.ToString ());
rvd = rvf = 0;
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = IIIIStruct_objc_msgSend_out_float (class_ptr, new Selector ("Test_StaticIIIIStruct_out_Float:").Handle, out rvf);
} else {
IIIIStruct_objc_msgSend_stret_out_float (out rv, class_ptr, new Selector ("Test_StaticIIIIStruct_out_Float:").Handle, out rvf);
}
//Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd);
Assert.That ("[10;20;300;4000]" == rv.ToString ());
Assert.That (rvf == 3.15f);
rvd = rvf = 0;
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = IIIIStruct_objc_msgSend_out_double (obj.Handle, new Selector ("Test_IIIIStruct_out_Double:").Handle, out rvd);
} else {
IIIIStruct_objc_msgSend_stret_out_double (out rv, obj.Handle, new Selector ("Test_IIIIStruct_out_Double:").Handle, out rvd);
}
//Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd);
Assert.That ("[1;20;300;4000]" == rv.ToString ());
Assert.That (rvd == 3.14);
}
[Test]
public void StretFFFFTrampolineTest ()
{
StretTrampolines obj = new StretTrampolines ();
IntPtr class_ptr = Class.GetHandle ("StretTrampolines");
var rv = new FFFFStruct ();
double rvd;
float rvf;
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = FFFFStruct_objc_msgSend (obj.Handle, new Selector ("Test_FFFFStruct").Handle);
} else {
FFFFStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_FFFFStruct").Handle);
}
Assert.That ("[1;2;3;4]" == rv.ToString ());
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = FFFFStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticFFFFStruct").Handle);
} else {
FFFFStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticFFFFStruct").Handle);
}
Assert.That ("[10;20;30;40]" == rv.ToString ());
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = FFFFStruct_objc_msgSend (obj.Handle, new Selector ("Test_FFFFStructProperty").Handle);
} else {
FFFFStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_FFFFStructProperty").Handle);
}
Assert.That ("[100;200;300;400]" == rv.ToString ());
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = FFFFStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticFFFFStructProperty").Handle);
} else {
FFFFStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticFFFFStructProperty").Handle);
}
Assert.That ("[1000;2000;3000;4000]" == rv.ToString ());
rvd = rvf = 0;
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = FFFFStruct_objc_msgSend_out_float (class_ptr, new Selector ("Test_StaticFFFFStruct_out_Float:").Handle, out rvf);
} else {
FFFFStruct_objc_msgSend_stret_out_float (out rv, class_ptr, new Selector ("Test_StaticFFFFStruct_out_Float:").Handle, out rvf);
}
//Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd);
Assert.That ("[10;20;300;4000]" == rv.ToString ());
Assert.That (rvf == 3.15f);
rvd = rvf = 0;
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = FFFFStruct_objc_msgSend_out_double (obj.Handle, new Selector ("Test_FFFFStruct_out_Double:").Handle, out rvd);
} else {
FFFFStruct_objc_msgSend_stret_out_double (out rv, obj.Handle, new Selector ("Test_FFFFStruct_out_Double:").Handle, out rvd);
}
//Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd);
Assert.That ("[1;20;300;4000]" == rv.ToString ());
Assert.That (rvd == 3.14);
}
[Test]
public void StretFIFITrampolineTest ()
{
StretTrampolines obj = new StretTrampolines ();
IntPtr class_ptr = Class.GetHandle ("StretTrampolines");
var rv = new FIFIStruct ();
double rvd;
float rvf;
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = FIFIStruct_objc_msgSend (obj.Handle, new Selector ("Test_FIFIStruct").Handle);
} else {
FIFIStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_FIFIStruct").Handle);
}
Assert.That ("[1;2;3;4]" == rv.ToString ());
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = FIFIStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticFIFIStruct").Handle);
} else {
FIFIStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticFIFIStruct").Handle);
}
Assert.That ("[10;20;30;40]" == rv.ToString ());
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = FIFIStruct_objc_msgSend (obj.Handle, new Selector ("Test_FIFIStructProperty").Handle);
} else {
FIFIStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_FIFIStructProperty").Handle);
}
Assert.That ("[100;200;300;400]" == rv.ToString ());
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = FIFIStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticFIFIStructProperty").Handle);
} else {
FIFIStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticFIFIStructProperty").Handle);
}
Assert.That ("[1000;2000;3000;4000]" == rv.ToString ());
rvd = rvf = 0;
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = FIFIStruct_objc_msgSend_out_float (class_ptr, new Selector ("Test_StaticFIFIStruct_out_Float:").Handle, out rvf);
} else {
FIFIStruct_objc_msgSend_stret_out_float (out rv, class_ptr, new Selector ("Test_StaticFIFIStruct_out_Float:").Handle, out rvf);
}
//Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd);
Assert.That ("[10;20;300;4000]" == rv.ToString ());
Assert.That (rvf == 3.15f);
rvd = rvf = 0;
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = FIFIStruct_objc_msgSend_out_double (obj.Handle, new Selector ("Test_FIFIStruct_out_Double:").Handle, out rvd);
} else {
FIFIStruct_objc_msgSend_stret_out_double (out rv, obj.Handle, new Selector ("Test_FIFIStruct_out_Double:").Handle, out rvd);
}
//Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd);
Assert.That ("[1;20;300;4000]" == rv.ToString ());
Assert.That (rvd == 3.14);
}
[Test]
public void StretIFIFTrampolineTest ()
{
StretTrampolines obj = new StretTrampolines ();
IntPtr class_ptr = Class.GetHandle ("StretTrampolines");
var rv = new IFIFStruct ();
double rvd;
float rvf;
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = IFIFStruct_objc_msgSend (obj.Handle, new Selector ("Test_IFIFStruct").Handle);
} else {
IFIFStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_IFIFStruct").Handle);
}
Assert.That ("[1;2;3;4]" == rv.ToString ());
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = IFIFStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticIFIFStruct").Handle);
} else {
IFIFStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticIFIFStruct").Handle);
}
Assert.That ("[10;20;30;40]" == rv.ToString ());
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = IFIFStruct_objc_msgSend (obj.Handle, new Selector ("Test_IFIFStructProperty").Handle);
} else {
IFIFStruct_objc_msgSend_stret (out rv, obj.Handle, new Selector ("Test_IFIFStructProperty").Handle);
}
Assert.That ("[100;200;300;400]" == rv.ToString ());
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = IFIFStruct_objc_msgSend (class_ptr, new Selector ("Test_StaticIFIFStructProperty").Handle);
} else {
IFIFStruct_objc_msgSend_stret (out rv, class_ptr, new Selector ("Test_StaticIFIFStructProperty").Handle);
}
Assert.That ("[1000;2000;3000;4000]" == rv.ToString ());
rvd = rvf = 0;
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = IFIFStruct_objc_msgSend_out_float (class_ptr, new Selector ("Test_StaticIFIFStruct_out_Float:").Handle, out rvf);
} else {
IFIFStruct_objc_msgSend_stret_out_float (out rv, class_ptr, new Selector ("Test_StaticIFIFStruct_out_Float:").Handle, out rvf);
}
//Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd);
Assert.That ("[10;20;300;4000]" == rv.ToString ());
Assert.That (rvf == 3.15f);
rvd = rvf = 0;
if (IsSim64 || IsArm64 || IsArmv7k) {
rv = IFIFStruct_objc_msgSend_out_double (obj.Handle, new Selector ("Test_IFIFStruct_out_Double:").Handle, out rvd);
} else {
IFIFStruct_objc_msgSend_stret_out_double (out rv, obj.Handle, new Selector ("Test_IFIFStruct_out_Double:").Handle, out rvd);
}
//Console.WriteLine ("Got: {0} and {1} and {2}", rv.ToString (), rvf, rvd);
Assert.That ("[1;20;300;4000]" == rv.ToString ());
Assert.That (rvd == 3.14);
}
[Test]
public void DoubleReturnTest ()
{
@ -356,82 +142,6 @@ namespace MonoTouchFixtures.ObjCRuntime {
extern static void Matrix4_objc_msgSend_stret (out OpenTK.Matrix4 retval, IntPtr receiver, IntPtr selector);
#endif // !__WATCHOS__
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")]
extern static void IIIIStruct_objc_msgSend_stret (out IIIIStruct retval, IntPtr receiver, IntPtr selector);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
extern static IIIIStruct IIIIStruct_objc_msgSend (IntPtr receiver, IntPtr selector);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")]
extern static void IIIIStruct_objc_msgSend_stret_out_double (out IIIIStruct retval, IntPtr receiver, IntPtr selector, out double arg1);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
extern static IIIIStruct IIIIStruct_objc_msgSend_out_double (IntPtr receiver, IntPtr selector, out double arg1);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")]
extern static void IIIIStruct_objc_msgSend_stret_out_float (out IIIIStruct retval, IntPtr receiver, IntPtr selector, out float arg1);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
extern static IIIIStruct IIIIStruct_objc_msgSend_out_float (IntPtr receiver, IntPtr selector, out float arg1);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")]
extern static void FFFFStruct_objc_msgSend_stret (out FFFFStruct retval, IntPtr receiver, IntPtr selector);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
extern static FFFFStruct FFFFStruct_objc_msgSend (IntPtr receiver, IntPtr selector);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")]
extern static void FFFFStruct_objc_msgSend_stret_out_double (out FFFFStruct retval, IntPtr receiver, IntPtr selector, out double arg1);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
extern static FFFFStruct FFFFStruct_objc_msgSend_out_double (IntPtr receiver, IntPtr selector, out double arg1);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")]
extern static void FFFFStruct_objc_msgSend_stret_out_float (out FFFFStruct retval, IntPtr receiver, IntPtr selector, out float arg1);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
extern static FFFFStruct FFFFStruct_objc_msgSend_out_float (IntPtr receiver, IntPtr selector, out float arg1);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")]
extern static void IFIFStruct_objc_msgSend_stret (out IFIFStruct retval, IntPtr receiver, IntPtr selector);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
extern static IFIFStruct IFIFStruct_objc_msgSend (IntPtr receiver, IntPtr selector);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")]
extern static void IFIFStruct_objc_msgSend_stret_out_double (out IFIFStruct retval, IntPtr receiver, IntPtr selector, out double arg1);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
extern static IFIFStruct IFIFStruct_objc_msgSend_out_double (IntPtr receiver, IntPtr selector, out double arg1);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")]
extern static void IFIFStruct_objc_msgSend_stret_out_float (out IFIFStruct retval, IntPtr receiver, IntPtr selector, out float arg1);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
extern static IFIFStruct IFIFStruct_objc_msgSend_out_float (IntPtr receiver, IntPtr selector, out float arg1);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")]
extern static void FIFIStruct_objc_msgSend_stret (out FIFIStruct retval, IntPtr receiver, IntPtr selector);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
extern static FIFIStruct FIFIStruct_objc_msgSend (IntPtr receiver, IntPtr selector);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")]
extern static void FIFIStruct_objc_msgSend_stret_out_double (out FIFIStruct retval, IntPtr receiver, IntPtr selector, out double arg1);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
extern static FIFIStruct FIFIStruct_objc_msgSend_out_double (IntPtr receiver, IntPtr selector, out double arg1);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")]
extern static void FIFIStruct_objc_msgSend_stret_out_float (out FIFIStruct retval, IntPtr receiver, IntPtr selector, out float arg1);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend")]
extern static FIFIStruct FIFIStruct_objc_msgSend_out_float (IntPtr receiver, IntPtr selector, out float arg1);
[DllImport (LIBOBJC_DYLIB, EntryPoint="objc_msgSend_stret")]
extern static void double_objc_msgSend_stret_out_double (out double retval, IntPtr receiver, IntPtr selector, out double arg1);
@ -634,14 +344,14 @@ namespace MonoTouchFixtures.ObjCRuntime {
PointF point;
SizeF size;
if (IsArm32 && !IsArmv7k) {
if (IsArm32) {
Messaging.PointF_objc_msgSend_stret (out point, obj.Handle, new Selector ("testPointF").Handle);
} else {
point = Messaging.PointF_objc_msgSend (obj.Handle, new Selector ("testPointF").Handle);
}
Assert.That (point == new PointF (pi*2, pi*20), "#testPointF");
if (IsArm32 && !IsArmv7k) {
if (IsArm32) {
Messaging.SizeF_objc_msgSend_stret (out size, obj.Handle, new Selector ("testSizeF").Handle);
} else {
size = Messaging.SizeF_objc_msgSend (obj.Handle, new Selector ("testSizeF").Handle);
@ -805,88 +515,6 @@ namespace MonoTouchFixtures.ObjCRuntime {
}
}
[Preserve (AllMembers = true)]
public struct IIIIStruct
{
public int A, B, C, D;
public IIIIStruct (int a, int b, int c, int d)
{
A = a;
B = b;
C = c;
D = d;
}
public override string ToString ()
{
return string.Format ("[{0};{1};{2};{3}]", A, B, C, D);
}
}
[Preserve (AllMembers = true)]
public struct FFFFStruct
{
public float A, B, C, D;
public FFFFStruct (float a, float b, float c, float d)
{
A = a;
B = b;
C = c;
D = d;
}
public override string ToString ()
{
return string.Format ("[{0};{1};{2};{3}]", A, B, C, D);
}
}
[Preserve (AllMembers = true)]
public struct FIFIStruct
{
public float A;
public int B;
public float C;
public int D;
public FIFIStruct (float a, int b, float c, int d)
{
A = a;
B = b;
C = c;
D = d;
}
public override string ToString ()
{
return string.Format ("[{0};{1};{2};{3}]", A, B, C, D);
}
}
[Preserve (AllMembers = true)]
public struct IFIFStruct
{
public int A;
public float B;
public int C;
public float D;
public IFIFStruct (int a, float b, int c, float d)
{
A = a;
B = b;
C = c;
D = d;
}
public override string ToString ()
{
return string.Format ("[{0};{1};{2};{3}]", A, B, C, D);
}
}
[Preserve (AllMembers = true)]
[Register ("LongTrampolines")]
public class LongTrampolines : NSObject
@ -913,158 +541,6 @@ namespace MonoTouchFixtures.ObjCRuntime {
[Preserve (AllMembers = true)]
public class StretTrampolines : NSObject
{
/* IIII */
[Export ("Test_IIIIStruct")]
IIIIStruct Test_IIIIStruct ()
{
return new IIIIStruct (1, 2, 3, 4);
}
[Export ("Test_StaticIIIIStruct")]
static IIIIStruct Test_StaticIIIIStruct ()
{
return new IIIIStruct (10, 20, 30, 40);
}
IIIIStruct Test_IIIIStructProperty {
[Export ("Test_IIIIStructProperty")]
get { return new IIIIStruct (100, 200, 300, 400); }
}
static IIIIStruct Test_StaticIIIIStructProperty {
[Export ("Test_StaticIIIIStructProperty")]
get { return new IIIIStruct (1000, 2000, 3000, 4000); }
}
[Export ("Test_IIIIStruct_out_Double:")]
IIIIStruct Test_IIIIStruct_out_Double (out double foo)
{
foo = 3.14;
return new IIIIStruct (1, 20, 300, 4000);
}
[Export ("Test_StaticIIIIStruct_out_Float:")]
static IIIIStruct Test_StaticIIIIStruct_out_Float (out float foo)
{
foo = 3.15f;
return new IIIIStruct (10, 20, 300, 4000);
}
/* FFFF */
[Export ("Test_FFFFStruct")]
FFFFStruct Test_FFFFStruct ()
{
return new FFFFStruct (1, 2, 3, 4);
}
[Export ("Test_StaticFFFFStruct")]
static FFFFStruct Test_StaticFFFFStructStruct ()
{
return new FFFFStruct (10, 20, 30, 40);
}
FFFFStruct Test_FFFFStructtStructProperty {
[Export ("Test_FFFFStructProperty")]
get { return new FFFFStruct (100, 200, 300, 400); }
}
static FFFFStruct Test_StaticFFFFStructProperty {
[Export ("Test_StaticFFFFStructProperty")]
get { return new FFFFStruct (1000, 2000, 3000, 4000); }
}
[Export ("Test_FFFFStruct_out_Double:")]
FFFFStruct Test_FFFFStruct_out_Double (out double foo)
{
foo = 3.14;
return new FFFFStruct (1, 20, 300, 4000);
}
[Export ("Test_StaticFFFFStruct_out_Float:")]
static FFFFStruct Test_StaticFFFFStruct_out_Float (out float foo)
{
foo = 3.15f;
return new FFFFStruct (10, 20, 300, 4000);
}
/* FIFI */
[Export ("Test_FIFIStruct")]
FIFIStruct Test_FIFIStruct ()
{
return new FIFIStruct (1, 2, 3, 4);
}
[Export ("Test_StaticFIFIStruct")]
static FIFIStruct Test_StaticFIFIStructStruct ()
{
return new FIFIStruct (10, 20, 30, 40);
}
FIFIStruct Test_FIFIStructtStructProperty {
[Export ("Test_FIFIStructProperty")]
get { return new FIFIStruct (100, 200, 300, 400); }
}
static FIFIStruct Test_StaticFIFIStructProperty {
[Export ("Test_StaticFIFIStructProperty")]
get { return new FIFIStruct (1000, 2000, 3000, 4000); }
}
[Export ("Test_FIFIStruct_out_Double:")]
FIFIStruct Test_FIFIStruct_out_Double (out double foo)
{
foo = 3.14;
return new FIFIStruct (1, 20, 300, 4000);
}
[Export ("Test_StaticFIFIStruct_out_Float:")]
static FIFIStruct Test_StaticFIFIStruct_out_Float (out float foo)
{
foo = 3.15f;
return new FIFIStruct (10, 20, 300, 4000);
}
/* IFIF */
[Export ("Test_IFIFStruct")]
IFIFStruct Test_IFIFStruct ()
{
return new IFIFStruct (1, 2, 3, 4);
}
[Export ("Test_StaticIFIFStruct")]
static IFIFStruct Test_StaticIFIFStructStruct ()
{
return new IFIFStruct (10, 20, 30, 40);
}
IFIFStruct Test_IFIFStructtStructProperty {
[Export ("Test_IFIFStructProperty")]
get { return new IFIFStruct (100, 200, 300, 400); }
}
static IFIFStruct Test_StaticIFIFStructProperty {
[Export ("Test_StaticIFIFStructProperty")]
get { return new IFIFStruct (1000, 2000, 3000, 4000); }
}
[Export ("Test_IFIFStruct_out_Double:")]
IFIFStruct Test_IFIFStruct_out_Double (out double foo)
{
foo = 3.14;
return new IFIFStruct (1, 20, 300, 4000);
}
[Export ("Test_StaticIFIFStruct_out_Float:")]
static IFIFStruct Test_StaticIFIFStruct_out_Float (out float foo)
{
foo = 3.15f;
return new IFIFStruct (10, 20, 300, 4000);
}
#if !__WATCHOS__
[Export ("myTimeRange")]
CMTimeRange TimeRange {

Просмотреть файл

@ -478,7 +478,9 @@
<Compile Include="Foundation\DictionaryContainerTest.cs" />
<Compile Include="ObjCRuntime\Messaging.cs" />
<Compile Include="ObjCRuntime\TrampolineTest.cs" />
<Compile Include="ObjCRuntime\TrampolineTest.generated.cs" />
<Compile Include="ObjCRuntime\RegistrarTest.cs" />
<Compile Include="ObjCRuntime\RegistrarTest.generated.cs" />
<Compile Include="CoreGraphics\DataProviderTest.cs" />
<Compile Include="HealthKit\QuantityTypeIdentifierTest.cs" />
<Compile Include="HealthKit\CategoryTypeIdentifierTest.cs" />
@ -753,4 +755,15 @@
<ImageAsset Condition="'$(TargetFrameworkIdentifier)' != 'Xamarin.WatchOS'" Include="Assets.xcassets\AppIcons.appiconset\icon-app-76%402x.png" />
<ImageAsset Condition="'$(TargetFrameworkIdentifier)' != 'Xamarin.WatchOS'" Include="Assets.xcassets\AppIcons.appiconset\icon-app-83.5%402x.png" />
</ItemGroup>
<ItemGroup>
<GeneratedTestInput Include="..\..\tests\test-libraries\*.m" />
<GeneratedTestInput Include="..\..\tests\test-libraries\*.h" />
<GeneratedTestInput Include="..\..\tests\test-libraries\*.cs" />
<GeneratedTestInput Include="..\..\tests\test-libraries\Makefile" />
<GeneratedTestOutput Include="ObjCRuntime\TrampolineTest.generated.cs" />
<GeneratedTestOutput Include="ObjCRuntime\RegistrarTest.generated.cs" />
</ItemGroup>
<Target Name="BeforeBuild" Inputs="@(GeneratedTestInput)" Outputs="@(GeneratedTestOutput)">
<Exec Command="make -j8 -C ..\..\tests\test-libraries" />
</Target>
</Project>

3
tests/test-libraries/.gitignore поставляемый
Просмотреть файл

@ -3,4 +3,7 @@
.libs
libtest-ar.m
libtest-object.m
libtest.structs.h
libtest.properties.h
libtest.decompile.m

Просмотреть файл

@ -5,6 +5,30 @@ include $(TOP)/Make.config
# in system headers show up.
export CCACHE_CPP2=1
GENERATED_FILES = \
libtest.structs.h \
libtest.decompile.m \
libtest.properties.h \
../bindings-test/ApiDefinition.generated.cs \
../bindings-test/StructsAndEnums.generated.cs \
../monotouch-test/ObjCRuntime/RegistrarTest.generated.cs \
../monotouch-test/ObjCRuntime/TrampolineTest.generated.cs \
GENERATED_FILES_PATTERN = \
libtest.structs%h \
libtest.decompile%m \
libtest.properties%h \
../bindings-test/ApiDefinition.generated%cs \
../bindings-test/StructsAndEnums.generated%cs \
../monotouch-test/ObjCRuntime/RegistrarTest.generated%cs \
../monotouch-test/ObjCRuntime/TrampolineTest.generated%cs \
testgenerator.exe: testgenerator.cs Makefile
$(Q) mcs -out:$@ $<
$(GENERATED_FILES_PATTERN): testgenerator.exe
$(Q) mono --debug $<
libtest-object.m libtest-ar.m:
$(Q) ln -fhs libtest.m $@
@ -24,12 +48,13 @@ $(2)_TARGETS = \
$$(foreach arch,$(3),.libs/$(1)/libtest-ar.$$(arch).a) \
.libs/$(1)/XTest.framework \
all-local:: $$($(2)_TARGETS)
all-local:: $$($(2)_TARGETS) $(GENERATED_FILES)
clean-$(1):
rm -Rf .libs/$(1)
CLEAN_TARGETS += clean-$(1)
EXTRA_DEPENDENCIES = libtest.h $(GENERATED_FILES)
.libs/$(1)/libtest-object.%.o: export EXTRA_DEFINES=-DPREFIX=1
.libs/$(1)/libtest-ar.%.o: export EXTRA_DEFINES=-DPREFIX=2

Просмотреть файл

@ -0,0 +1 @@


Просмотреть файл

@ -13,31 +13,7 @@ void useZLib ();
* Various structs used in ObjCRegistrarTest
*/
struct Sd { double d1; } Sd;
struct Sdd { double d1; double d2; } Sdd;
struct Sddd { double d1; double d2; double d3; } Sddd;
struct Sdddd { double d1; double d2; double d3; double d4; } Sdddd;
struct Si { int i1; } Si;
struct Sii { int i1; int i2; } Sii;
struct Siii { int i1; int i2; int i3; } Siii;
struct Siiii { int i1; int i2; int i3; int i4; } Siiii;
struct Siiiii { int i1; int i2; int i3; int i4; int i5; } Siiiii;
struct Sid { int i1; double d2; } Sid;
struct Sdi { double d1; int i2; } Sdi;
struct Sidi { int i1; double d2; int i3; } Sidi;
struct Siid { int i1; int i2; double d3; } Siid;
struct Sddi { double d1; double d2; int i3; } Sddi;
struct Sl { long l1; } Sl;
struct Sll { long l1; long l2; } Sll;
struct Slll { long l1; long l2; long l3; } Slll;
struct Scccc { char c1; char c2; char c3; char c4; } Scccc;
struct Sffff { float f1; float f2; float f3; float f4; } Sffff;
struct Sif { int i1; float f2; } Sif;
struct Sf { float f1; } Sf;
struct Sff { float f1; float f2; } Sff;
struct Siff { int i1; float f2; float f3; } Siff;
struct Siiff { int i1; int i2; float f3; float f4; } Siiff;
struct Sfi { float f1; int i2; } Sfi;
#include "libtest.structs.h"
typedef unsigned int (^RegistrarTestBlock) (unsigned int magic);
@ -79,9 +55,7 @@ typedef unsigned int (^RegistrarTestBlock) (unsigned int magic);
@property char Pc4;
@property char Pc5;
@property struct Siid PSiid1;
@property struct Sd PSd1;
@property struct Sf PSf1;
#include "libtest.properties.h"
-(void) V;

Просмотреть файл

@ -80,12 +80,12 @@ static UltimateMachine *shared;
-(struct Sd) Sd
{
return _PSd1;
return _PSd;
}
-(struct Sf) Sf
{
return _PSf1;
return _PSf;
}
-(void) V:(int)i1 i:(int)i2 i:(int)i3 i:(int)i4 i:(int)i5 i:(int)i6 i:(int)i7
@ -115,12 +115,12 @@ static UltimateMachine *shared;
-(void) V:(int)i1 i:(int)i2 Siid:(struct Siid)s1 i:(int)i3 i:(int)i4 d:(double)d1 d:(double)d2 d:(double)d3 i:(int)i5 i:(int)i6 i:(int)i7
{
_Pi1 = i1; _Pi2 = i2; _PSiid1 = s1; _Pi3 = i3; _Pi4 = i4; _Pd1 = d1; _Pd2 = d2; _Pd3 = d2; _Pi5 = i5; _Pi6 = i6; _Pi7 = i7;
_Pi1 = i1; _Pi2 = i2; _PSiid = s1; _Pi3 = i3; _Pi4 = i4; _Pd1 = d1; _Pd2 = d2; _Pd3 = d2; _Pi5 = i5; _Pi6 = i6; _Pi7 = i7;
}
-(void) V:(int)i1 i:(int)i2 f:(float)f1 Siid:(struct Siid)s1 i:(int)i3 i:(int)i4 d:(double)d1 d:(double)d2 d:(double)d3 i:(int)i5 i:(int)i6 i:(int)i7
{
_Pi1 = i1; _Pi2 = i2; _Pf1 = f1; _PSiid1 = s1; _Pi3 = i3; _Pi4 = i4; _Pd1 = d1; _Pd2 = d2; _Pd3 = d3; _Pi5 = i5; _Pi6 = i6; _Pi7 = i7;
_Pi1 = i1; _Pi2 = i2; _Pf1 = f1; _PSiid = s1; _Pi3 = i3; _Pi4 = i4; _Pd1 = d1; _Pd2 = d2; _Pd3 = d3; _Pi5 = i5; _Pi6 = i6; _Pi7 = i7;
}
-(void) V:(char)c1 c:(char)c2 c:(char)c3 c:(char)c4 c:(char)c5 i:(int)i1 d:(double)d1
@ -253,3 +253,5 @@ static UltimateMachine *shared;
// Do nothing
}
@end
#include "libtest.decompile.m"

Просмотреть файл

@ -0,0 +1,538 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
static class C {
[Flags]
enum Architecture
{
None = 0,
Sim32 = 1,
Sim64 = 2,
Arm32 = 4,
Armv7k = 8,
// Arm64 is never stret
}
// X86: structs > 8 + structs with 3 members.
// X64: structs > 16
// ARM32: all structs, except those matching an integral platform type (i.e. a struct with a single int, but not a struct with a single float).
// ARM64: never
// armv7k: > 16, except homogeneous types with no more than 4 elements (i.e. structs with 3 or 4 doubles).
// the numbers below are bitmasks of Architecture values.
static string [] structs_and_stret = {
/* integral types */
"c:0", "cc:4", "ccc:5", "cccc:4",
"s:0", "ss:4", "sss:5", "ssss:4",
"i:0", "ii:4", "iii:5", "iiii:5", "iiiii:15",
"l:4", "ll:5", "lll:15", "llll:15", "lllll:15",
/* floating point types */
"f:4", "ff:4", "fff:5", "ffff:5", "fffff:15",
"d:4", "dd:5", "ddd:7", "dddd:7", "ddddd:15",
/* mixed types */
"if:4", "fi:4", // 8 bytes
"iff:5", // 12 bytes
"iiff:5", // 16 bytes
"id:5", "di:5", // 16 bytes
"iid:5", // 16 bytes
"idi:15", // 16 bytes on i386 and 24 bytes on x86_64 (due to alignment)
"ddi:15", // 24 bytes
"didi:15", // 24 bytes on 32-bit arch, 32 bytes on 64-bit arch
"idid:15", // 24 bytes on 32-bit arch, 32 bytes on 64-bit arch
"dldl:15",
"ldld:15",
"fifi:5",
"ifif:5",
};
static string [] structs = structs_and_stret.Select ((v) => v.IndexOf (':') >= 0 ? v.Substring (0, v.IndexOf (':')) : v).ToArray ();
static Architecture [] strets = structs_and_stret.Select ((v) => v.IndexOf (':') >= 0 ? (Architecture) int.Parse (v.Substring (v.IndexOf (':') + 1)) : Architecture.None).ToArray ();
static string GetNativeName (char t)
{
switch (t) {
case 'f': return "float";
case 'd': return "double";
case 'c': return "char";
case 's': return "short";
case 'i': return "int";
case 'l': return "long long";
default:
throw new NotImplementedException ();
}
}
static string GetManagedName (char t)
{
switch (t) {
case 'f': return "float";
case 'd': return "double";
case 'c': return "byte";
case 's': return "short";
case 'i': return "int";
case 'l': return "long";
default:
throw new NotImplementedException ();
}
}
static string GetValue (char t, int i, int multiplier = 1)
{
switch (t) {
case 'c':
case 's':
case 'i':
case 'l': return ((i + 1) * multiplier).ToString ();
case 'f': return (3.14f * (i + 1) * multiplier) + "f";
case 'd': return (1.23f * (i + 1) * multiplier).ToString ();
default:
throw new NotImplementedException ();
}
}
static void WriteLibTestStructH ()
{
var w = new StringBuilder ();
foreach (var s in structs) {
w.Append ($"struct S{s} {{ ");
for (int i = 0; i < s.Length; i++) {
w.Append (GetNativeName (s [i])).Append (" x").Append (i).Append ("; ");
}
w.AppendLine ($"}} S{s};");
}
File.WriteAllText ("libtest.structs.h", w.ToString ());
}
static void WriteLibTestDecompileM ()
{
var w = new StringBuilder ();
// This is code to be disassembled to see how it's compiled by clang
// to see if a particular structure is using objc_msgSend_stret or not.
//
// To disassemble:
// otool -vVt .libs/ios/libtest.armv7.o
//
// Then in the _decompile_me output, look for the _____* function call,
// matching the structure you want to check, and then backtrack until
// you see either an objc_msgSend or objc_msgSend_stret call, and you
// have your answer.
#if false
w.AppendLine ("extern \"C\" {");
foreach (var s in structs)
w.AppendLine ($"void _____________________________________{s} (struct S{s} x) __attribute__ ((optnone)) {{ }}");
w.AppendLine ("void decompile_me () __attribute__ ((optnone))");
w.AppendLine ("{");
w.AppendLine ("\tObjCRegistrarTest *obj = NULL;");
foreach (var s in structs) {
w.AppendLine ($"\t_____________________________________{s} ([obj PS{s}]);");
}
w.AppendLine ("}");
w.AppendLine ("}");
#endif
File.WriteAllText ("libtest.decompile.m", w.ToString ());
}
static void WriteLibTestPropertiesH ()
{
var w = new StringBuilder ();
foreach (var s in structs)
w.AppendLine ($"\t@property struct S{s} PS{s};");
File.WriteAllText ("libtest.properties.h", w.ToString ());
}
static void WriteApiDefinition ()
{
var w = new StringBuilder ();
w.AppendLine (@"using System;
#if !__WATCHOS__
using System.Drawing;
#endif
#if __UNIFIED__
using ObjCRuntime;
using Foundation;
using UIKit;
#else
using MonoTouch.ObjCRuntime;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
#endif
namespace Bindings.Test {
partial interface ObjCRegistrarTest {
");
foreach (var s in structs) {
w.AppendLine ($"\t\t[Export (\"PS{s}\")]");
w.AppendLine ($"\t\tS{s} PS{s} {{ get; set; }}");
w.AppendLine ();
}
w.AppendLine (@" }
}");
File.WriteAllText ("../bindings-test/ApiDefinition.generated.cs", w.ToString ());
}
static void WriteStructsAndEnums ()
{
var w = new StringBuilder ();
w.AppendLine (@"using System;
using System.Runtime.InteropServices;
#if !__UNIFIED__
using nint=System.Int32;
#endif
namespace Bindings.Test
{
");
foreach (var s in structs) {
w.AppendLine ($"\tpublic struct S{s} {{ ");
w.Append ("\t\t");
for (int i = 0; i < s.Length; i++) {
w.Append ("public ").Append (GetManagedName (s [i])).Append (" x").Append (i).Append ("; ");
}
w.AppendLine ();
w.Append ($"\t\tpublic override string ToString () {{ return $\"S{s} [");
for (int i = 0; i < s.Length; i++) {
w.Append ("{x").Append (i).Append ("};");
}
w.Length--;
w.AppendLine ("]\"; } ");
w.AppendLine ("\t}");
w.AppendLine ();
}
w.AppendLine (@"}");
File.WriteAllText ("../bindings-test/StructsAndEnums.generated.cs", w.ToString ());
}
static void WriteRegistrarTests ()
{
var w = new StringBuilder ();
w.AppendLine (@"
#if XAMCORE_2_0
using Foundation;
using ObjCRuntime;
using MonoTouchException=ObjCRuntime.RuntimeException;
using NativeException=Foundation.MonoTouchException;
#else
using MonoTouch;
using MonoTouch.Foundation;
using MonoTouch.ObjCRuntime;
using MonoTouchException=MonoTouch.RuntimeException;
using NativeException=MonoTouch.Foundation.MonoTouchException;
#endif
using NUnit.Framework;
using Bindings.Test;
using XamarinTests.ObjCRuntime;
namespace MonoTouchFixtures.ObjCRuntime {
[TestFixture]
[Preserve (AllMembers = true)]
public class RegistrarTestGenerated {");
foreach (var s in structs) {
w.AppendLine ("\t\t[Test]");
w.AppendLine ($"\t\tpublic void Test_{s} ()");
w.AppendLine ("\t\t{");
w.AppendLine ("\t\t\tusing (var tc = new ObjCRegistrarTest ()) {");
w.AppendLine ($"\t\t\t\tvar s = tc.PS{s};");
for (int i = 0; i < s.Length; i++)
w.AppendLine ($"\t\t\t\tAssert.AreEqual (0, s.x{i}, \"pre-#{i}\");");
w.Append ($"\t\t\t\tvar k = new S{s} () {{ ");
for (int i = 0; i < s.Length; i++)
w.Append ($"x{i} = ").Append (GetValue (s [i], i)).Append (", ");
w.Length -= 2;
w.AppendLine ("};");
w.AppendLine ($"\t\t\t\ttc.PS{s} = k;");
w.AppendLine ($"\t\t\t\ts = tc.PS{s};");
for (int i = 0; i < s.Length; i++)
w.AppendLine ($"\t\t\t\tAssert.AreEqual (k.x{i}, s.x{i}, \"post-#{i}\");");
w.AppendLine ("\t\t\t}");
w.AppendLine ("\t\t}");
w.AppendLine ();
}
w.AppendLine (@" }
}");
File.WriteAllText ("../monotouch-test/ObjCRuntime/RegistrarTest.generated.cs", w.ToString ());
}
static void WriteTrampolineTests ()
{
var w = new StringBuilder ();
w.AppendLine (@"
using System;
using System.Runtime.InteropServices;
#if XAMCORE_2_0
using Foundation;
using ObjCRuntime;
#else
using MonoTouch;
using MonoTouch.Foundation;
using MonoTouch.ObjCRuntime;
#endif
using NUnit.Framework;
using Bindings.Test;
using XamarinTests.ObjCRuntime;
namespace MonoTouchFixtures.ObjCRuntime {
[TestFixture]
[Preserve (AllMembers = true)]
public class TrampolineTestGenerated {");
w.AppendLine ("\t\tconst string LIBOBJC_DYLIB = \"/usr/lib/libobjc.dylib\";");
w.AppendLine ();
w.AppendLine ("\t\t[Register (\"GeneratedStretTrampolines\")]");
w.AppendLine ("\t\t[Preserve (AllMembers = true)]");
w.AppendLine ("\t\tpublic class GeneratedStretTrampolines : NSObject {");
foreach (var s in structs) {
w.AppendLine ();
w.AppendLine ($"\t\t\t// {s}");
w.AppendLine ();
w.AppendLine ($"\t\t\t[Export (\"Test_{s}Struct\")]");
w.AppendLine ($"\t\t\tS{s} Test_{s}Struct ()");
w.AppendLine ($"\t\t\t{{");
w.AppendLine ($"\t\t\t\treturn {GenerateNewExpression (s, 1)};");
w.AppendLine ($"\t\t\t}}");
w.AppendLine ();
w.AppendLine ($"\t\t\t[Export (\"Test_Static{s}Struct\")]");
w.AppendLine ($"\t\t\tstatic S{s} Test_Static{s}Struct ()");
w.AppendLine ($"\t\t\t{{");
w.AppendLine ($"\t\t\t\treturn {GenerateNewExpression (s, 2)};");
w.AppendLine ($"\t\t\t}}");
w.AppendLine ();
w.AppendLine ($"\t\t\tS{s} Test_{s}StructProperty {{");
w.AppendLine ($"\t\t\t\t[Export (\"Test_{s}StructProperty\")]");
w.AppendLine ($"\t\t\t\tget {{ return {GenerateNewExpression (s, 3)}; }}");
w.AppendLine ($"\t\t\t}}");
w.AppendLine ();
w.AppendLine ($"\t\t\tstatic S{s} Test_Static{s}StructProperty {{");
w.AppendLine ($"\t\t\t\t[Export (\"Test_Static{s}StructProperty\")]");
w.AppendLine ($"\t\t\t\tget {{ return {GenerateNewExpression (s, 4)}; }}");
w.AppendLine ($"\t\t\t}}");
w.AppendLine ();
w.AppendLine ($"\t\t\t[Export (\"Test_{s}Struct_out_double:\")]");
w.AppendLine ($"\t\t\tS{s} Test_{s}Struct (out double x0)");
w.AppendLine ($"\t\t\t{{");
w.AppendLine ($"\t\t\t\tx0 = 3.14;");
w.AppendLine ($"\t\t\t\treturn {GenerateNewExpression (s, 5)};");
w.AppendLine ($"\t\t\t}}");
w.AppendLine ();
w.AppendLine ($"\t\t\t[Export (\"Test_Static{s}Struct_out_float:\")]");
w.AppendLine ($"\t\t\tstatic S{s} Test_Static{s}Struct (out float x0)");
w.AppendLine ($"\t\t\t{{");
w.AppendLine ($"\t\t\t\tx0 = 3.15f;");
w.AppendLine ($"\t\t\t\treturn {GenerateNewExpression (s, 6)};");
w.AppendLine ($"\t\t\t}}");
}
w.AppendLine ("\t\t}");
foreach (var s in structs) {
if (s.Length == 1 || s.Contains ('c'))
continue; // our trampolines don't currently like structs with a single member, nor char members
bool never;
w.AppendLine ();
w.AppendLine ($"\t\t[Test]");
w.AppendLine ($"\t\tpublic void Test_{s} ()");
w.AppendLine ($"\t\t{{");
w.AppendLine ($"\t\t\tIntPtr class_ptr = Class.GetHandle (typeof (GeneratedStretTrampolines));");
w.AppendLine ($"\t\t\tS{s} rv = new S{s} ();");
w.AppendLine ($"\t\t\tdouble rvd;");
w.AppendLine ($"\t\t\tfloat rvf;");
w.AppendLine ($"\t\t\tusing (var obj = new GeneratedStretTrampolines ()) {{");
WriteStretConditions (w, s, out never);
if (never) {
w.AppendLine ($"\t\t\t\trv = S{s}_objc_msgSend (obj.Handle, new Selector (\"Test_{s}Struct\").Handle);");
} else {
w.AppendLine ($"\t\t\t\t\tS{s}_objc_msgSend_stret (out rv, obj.Handle, new Selector (\"Test_{s}Struct\").Handle);");
w.AppendLine ($"\t\t\t\t}} else {{");
w.AppendLine ($"\t\t\t\t\trv = S{s}_objc_msgSend (obj.Handle, new Selector (\"Test_{s}Struct\").Handle);");
w.AppendLine ($"\t\t\t\t}}");
}
w.AppendLine ($"\t\t\t\tAssert.AreEqual (({GenerateNewExpression (s, 1)}).ToString (), rv.ToString (), \"a\");");
w.AppendLine ();
WriteStretConditions (w, s, out never);
if (never) {
w.AppendLine ($"\t\t\t\trv = S{s}_objc_msgSend (class_ptr, new Selector (\"Test_Static{s}Struct\").Handle);");
} else {
w.AppendLine ($"\t\t\t\t\tS{s}_objc_msgSend_stret (out rv, class_ptr, new Selector (\"Test_Static{s}Struct\").Handle);");
w.AppendLine ($"\t\t\t\t}} else {{");
w.AppendLine ($"\t\t\t\t\trv = S{s}_objc_msgSend (class_ptr, new Selector (\"Test_Static{s}Struct\").Handle);");
w.AppendLine ($"\t\t\t\t}}");
}
w.AppendLine ($"\t\t\t\tAssert.AreEqual (({GenerateNewExpression (s, 2)}).ToString (), rv.ToString (), \"a\");");
w.AppendLine ();
WriteStretConditions (w, s, out never);
if (never) {
w.AppendLine ($"\t\t\t\trv = S{s}_objc_msgSend (obj.Handle, new Selector (\"Test_{s}StructProperty\").Handle);");
} else {
w.AppendLine ($"\t\t\t\t\tS{s}_objc_msgSend_stret (out rv, obj.Handle, new Selector (\"Test_{s}StructProperty\").Handle);");
w.AppendLine ($"\t\t\t\t}} else {{");
w.AppendLine ($"\t\t\t\t\trv = S{s}_objc_msgSend (obj.Handle, new Selector (\"Test_{s}StructProperty\").Handle);");
w.AppendLine ($"\t\t\t\t}}");
}
w.AppendLine ($"\t\t\t\tAssert.AreEqual (({GenerateNewExpression (s, 3)}).ToString (), rv.ToString (), \"a\");");
w.AppendLine ();
WriteStretConditions (w, s, out never);
if (never) {
w.AppendLine ($"\t\t\t\trv = S{s}_objc_msgSend (class_ptr, new Selector (\"Test_Static{s}StructProperty\").Handle);");
} else {
w.AppendLine ($"\t\t\t\t\tS{s}_objc_msgSend_stret (out rv, class_ptr, new Selector (\"Test_Static{s}StructProperty\").Handle);");
w.AppendLine ($"\t\t\t\t}} else {{");
w.AppendLine ($"\t\t\t\t\trv = S{s}_objc_msgSend (class_ptr, new Selector (\"Test_Static{s}StructProperty\").Handle);");
w.AppendLine ($"\t\t\t\t}}");
}
w.AppendLine ($"\t\t\t\tAssert.AreEqual (({GenerateNewExpression (s, 4)}).ToString (), rv.ToString (), \"a\");");
w.AppendLine ();
w.AppendLine ($"\t\t\t\trvd = 0;");
WriteStretConditions (w, s, out never);
if (never) {
w.AppendLine ($"\t\t\t\trv = S{s}_objc_msgSend_out_double (obj.Handle, new Selector (\"Test_{s}Struct_out_double:\").Handle, out rvd);");
} else {
w.AppendLine ($"\t\t\t\t\tS{s}_objc_msgSend_stret_out_double (out rv, obj.Handle, new Selector (\"Test_{s}Struct_out_double:\").Handle, out rvd);");
w.AppendLine ($"\t\t\t\t}} else {{");
w.AppendLine ($"\t\t\t\t\trv = S{s}_objc_msgSend_out_double (obj.Handle, new Selector (\"Test_{s}Struct_out_double:\").Handle, out rvd);");
w.AppendLine ($"\t\t\t\t}}");
}
w.AppendLine ($"\t\t\t\tAssert.AreEqual (({GenerateNewExpression (s, 5)}).ToString (), rv.ToString (), \"a\");");
w.AppendLine ($"\t\t\t\tAssert.AreEqual (3.14, rvd, \"double out\");");
w.AppendLine ();
w.AppendLine ($"\t\t\t\trvf = 0;");
WriteStretConditions (w, s, out never);
if (never) {
w.AppendLine ($"\t\t\t\trv = S{s}_objc_msgSend_out_float (class_ptr, new Selector (\"Test_Static{s}Struct_out_float:\").Handle, out rvf);");
} else {
w.AppendLine ($"\t\t\t\t\tS{s}_objc_msgSend_stret_out_float (out rv, class_ptr, new Selector (\"Test_Static{s}Struct_out_float:\").Handle, out rvf);");
w.AppendLine ($"\t\t\t\t}} else {{");
w.AppendLine ($"\t\t\t\t\trv = S{s}_objc_msgSend_out_float (class_ptr, new Selector (\"Test_Static{s}Struct_out_float:\").Handle, out rvf);");
w.AppendLine ($"\t\t\t\t}}");
}
w.AppendLine ($"\t\t\t\tAssert.AreEqual (({GenerateNewExpression (s, 6)}).ToString (), rv.ToString (), \"a\");");
w.AppendLine ($"\t\t\t\tAssert.AreEqual (3.15f, rvf, \"float out\");");
w.AppendLine ();
w.AppendLine ($"\t\t\t}}");
w.AppendLine ($"\t\t}}");
// objc_msgSend variants
w.AppendLine ();
w.AppendLine ($"\t\t[DllImport (LIBOBJC_DYLIB, EntryPoint=\"objc_msgSend\")]");
w.AppendLine ($"\t\textern static S{s} S{s}_objc_msgSend (IntPtr received, IntPtr selector);");
w.AppendLine ();
w.AppendLine ($"\t\t[DllImport (LIBOBJC_DYLIB, EntryPoint=\"objc_msgSend\")]");
w.AppendLine ($"\t\textern static S{s} S{s}_objc_msgSend_out_float (IntPtr received, IntPtr selector, out float x1);");
w.AppendLine ();
w.AppendLine ($"\t\t[DllImport (LIBOBJC_DYLIB, EntryPoint=\"objc_msgSend\")]");
w.AppendLine ($"\t\textern static S{s} S{s}_objc_msgSend_out_double (IntPtr received, IntPtr selector, out double x1);");
w.AppendLine ();
w.AppendLine ($"\t\t[DllImport (LIBOBJC_DYLIB, EntryPoint=\"objc_msgSend_stret\")]");
w.AppendLine ($"\t\textern static void S{s}_objc_msgSend_stret (out S{s} rv, IntPtr received, IntPtr selector);");
w.AppendLine ();
w.AppendLine ($"\t\t[DllImport (LIBOBJC_DYLIB, EntryPoint=\"objc_msgSend_stret\")]");
w.AppendLine ($"\t\textern static void S{s}_objc_msgSend_stret_out_float (out S{s} rv, IntPtr received, IntPtr selector, out float x1);");
w.AppendLine ();
w.AppendLine ($"\t\t[DllImport (LIBOBJC_DYLIB, EntryPoint=\"objc_msgSend_stret\")]");
w.AppendLine ($"\t\textern static void S{s}_objc_msgSend_stret_out_double (out S{s} rv, IntPtr received, IntPtr selector, out double x1);");
}
w.AppendLine (@" }
}");
File.WriteAllText ("../monotouch-test/ObjCRuntime/TrampolineTest.generated.cs", w.ToString ());
}
static void WriteStretConditions (StringBuilder w, string s, out bool never)
{
var stret = strets [Array.IndexOf (structs, s)];
if (stret == Architecture.None) {
never = true;
} else {
never = false;
w.Append ("\t\t\t\tif (");
if ((stret & Architecture.Arm32) == Architecture.Arm32)
w.Append ("TrampolineTest.IsArm32 || ");
if ((stret & Architecture.Armv7k) == Architecture.Armv7k)
w.Append ("TrampolineTest.IsArmv7k || ");
if ((stret & Architecture.Sim32) == Architecture.Sim32)
w.Append ("TrampolineTest.IsSim32 || ");
if ((stret & Architecture.Sim64) == Architecture.Sim64)
w.Append ("TrampolineTest.IsSim64 || ");
w.Length -= 4;
w.AppendLine (") {");
}
}
static string GenerateNewExpression (string s, int multiplier = 1)
{
var sb = new StringBuilder ();
sb.Append ($"new S{s} () {{ ");
for (int i = 0; i < s.Length; i++)
sb.Append ("x").Append (i).Append (" = ").Append (GetValue (s [i], i, multiplier)).Append (", ");
sb.Length -= 2;
sb.Append (" }");
return sb.ToString ();
}
static void Main ()
{
while (Path.GetFileName (Environment.CurrentDirectory) != "test-libraries")
Environment.CurrentDirectory = Path.GetDirectoryName (Environment.CurrentDirectory);
/* native code */
WriteLibTestStructH ();
WriteLibTestDecompileM ();
WriteLibTestPropertiesH ();
/* binding code */
WriteApiDefinition ();
WriteStructsAndEnums ();
/* tests */
WriteRegistrarTests ();
WriteTrampolineTests ();
Console.WriteLine ("Generated test files");
}
}

Просмотреть файл

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{CD430449-8E59-4ECD-ADD9-ACF79E9E660B}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>testgenerator</RootNamespace>
<AssemblyName>testgenerator</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ExternalConsole>true</ExternalConsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ExternalConsole>true</ExternalConsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="testgenerator.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>