From 517bb58a029e17f0524283d6c8d6cca2b9551bf2 Mon Sep 17 00:00:00 2001 From: shoebox Date: Sat, 20 Dec 2014 00:04:32 +0000 Subject: [PATCH 01/16] Refactoring --- .gitignore | 30 +++ .munit | 6 + project.xml | 21 ++ src/ShortCuts.hx | 4 +- src/mirror/Cpp.hx | 68 ++++++ src/mirror/CppFieldTool.hx | 73 ++++++ src/mirror/Jni.hx | 86 +++++++ src/mirror/JniFieldTool.hx | 152 ++++++++++++ src/mirror/Mirror.hx | 52 ++++ src/tools/ExprTool.hx | 21 ++ src/tools/FieldTool.hx | 27 +++ src/tools/FunctionTool.hx | 35 +++ src/tools/MetadataTools.hx | 44 ++++ src/tools/VariableTool.hx | 24 ++ test/JniTest.hx | 69 ++++++ .../dependencies/android/AndroidManifest.xml | 7 + test/extension/dependencies/android/build.xml | 13 + .../dependencies/android/project.properties | 15 ++ .../src/org/test/extension/TestExtension.java | 28 +++ test/extension/haxelib.json | 13 + test/extension/include.xml | 12 + .../ndll/Mac/testextension-debug.ndll | Bin 0 -> 68676 bytes test/extension/ndll/Mac/testextension.dll | Bin 0 -> 42608 bytes test/extension/ndll/Mac/testextension.ndll | Bin 0 -> 42636 bytes test/extension/ndll/Mac64/testextension.ndll | Bin 0 -> 42544 bytes .../libtestextension-debug.iphoneos-v7.a | Bin 0 -> 5304 bytes .../libtestextension-debug.iphoneos-v7.ndll | Bin 0 -> 5304 bytes .../iPhone/libtestextension-debug.iphoneos.a | Bin 0 -> 5304 bytes .../libtestextension-debug.iphoneos.ndll | Bin 0 -> 5304 bytes .../iPhone/libtestextension-debug.iphonesim.a | Bin 0 -> 5448 bytes .../libtestextension-debug.iphonesim.ndll | Bin 0 -> 5448 bytes .../iPhone/libtestextension.iphoneos-v7.a | Bin 0 -> 1912 bytes .../iPhone/libtestextension.iphoneos-v7.ndll | Bin 0 -> 1912 bytes .../ndll/iPhone/libtestextension.iphoneos.a | Bin 0 -> 1848 bytes .../iPhone/libtestextension.iphoneos.ndll | Bin 0 -> 1848 bytes .../ndll/iPhone/libtestextension.iphonesim.a | Bin 0 -> 2272 bytes .../iPhone/libtestextension.iphonesim.ndll | Bin 0 -> 2272 bytes test/extension/project/Build.xml | 33 +++ test/extension/project/build.sh | 107 +++++++++ test/extension/project/common/Extension.cpp | 6 + .../project/common/ExternalInterface.cpp | 32 +++ .../src/org/test/extension/TestExtension.hx | 19 ++ test/src/CppCallTest.hx | 26 ++ test/src/CppTest.hx | 66 ++++++ test/src/JniCallTest.hx | 35 +++ test/src/JniTest.hx | 69 ++++++ test/src/OpenflPrintClient.hx | 223 ++++++++++++++++++ test/src/TestMain.hx | 96 ++++++++ test/src/TestSuite.hx | 25 ++ test/src/testpackage/TestJni1.hx | 27 +++ test/src/testpackage/TestJni2.hx | 12 + 51 files changed, 1574 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 .munit create mode 100644 project.xml create mode 100644 src/mirror/Cpp.hx create mode 100644 src/mirror/CppFieldTool.hx create mode 100644 src/mirror/Jni.hx create mode 100644 src/mirror/JniFieldTool.hx create mode 100644 src/mirror/Mirror.hx create mode 100644 src/tools/ExprTool.hx create mode 100644 src/tools/FieldTool.hx create mode 100644 src/tools/FunctionTool.hx create mode 100644 src/tools/MetadataTools.hx create mode 100644 src/tools/VariableTool.hx create mode 100644 test/JniTest.hx create mode 100644 test/extension/dependencies/android/AndroidManifest.xml create mode 100644 test/extension/dependencies/android/build.xml create mode 100644 test/extension/dependencies/android/project.properties create mode 100644 test/extension/dependencies/android/src/org/test/extension/TestExtension.java create mode 100644 test/extension/haxelib.json create mode 100644 test/extension/include.xml create mode 100755 test/extension/ndll/Mac/testextension-debug.ndll create mode 100755 test/extension/ndll/Mac/testextension.dll create mode 100755 test/extension/ndll/Mac/testextension.ndll create mode 100755 test/extension/ndll/Mac64/testextension.ndll create mode 100644 test/extension/ndll/iPhone/libtestextension-debug.iphoneos-v7.a create mode 100644 test/extension/ndll/iPhone/libtestextension-debug.iphoneos-v7.ndll create mode 100644 test/extension/ndll/iPhone/libtestextension-debug.iphoneos.a create mode 100644 test/extension/ndll/iPhone/libtestextension-debug.iphoneos.ndll create mode 100644 test/extension/ndll/iPhone/libtestextension-debug.iphonesim.a create mode 100644 test/extension/ndll/iPhone/libtestextension-debug.iphonesim.ndll create mode 100644 test/extension/ndll/iPhone/libtestextension.iphoneos-v7.a create mode 100644 test/extension/ndll/iPhone/libtestextension.iphoneos-v7.ndll create mode 100644 test/extension/ndll/iPhone/libtestextension.iphoneos.a create mode 100644 test/extension/ndll/iPhone/libtestextension.iphoneos.ndll create mode 100644 test/extension/ndll/iPhone/libtestextension.iphonesim.a create mode 100644 test/extension/ndll/iPhone/libtestextension.iphonesim.ndll create mode 100644 test/extension/project/Build.xml create mode 100644 test/extension/project/build.sh create mode 100644 test/extension/project/common/Extension.cpp create mode 100644 test/extension/project/common/ExternalInterface.cpp create mode 100644 test/extension/src/org/test/extension/TestExtension.hx create mode 100644 test/src/CppCallTest.hx create mode 100644 test/src/CppTest.hx create mode 100644 test/src/JniCallTest.hx create mode 100644 test/src/JniTest.hx create mode 100644 test/src/OpenflPrintClient.hx create mode 100644 test/src/TestMain.hx create mode 100644 test/src/TestSuite.hx create mode 100644 test/src/testpackage/TestJni1.hx create mode 100644 test/src/testpackage/TestJni2.hx diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57141ee --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# mtask +bin +gen +report +.temp +lib + +# munit and mcover +/.mcover +TestSuite.hx + +# OS junk +Thumbs.db +.DS_Store + +/storefront-companion.sublime-workspace +/storefront-companion.sublime-project +*.hxproj +node_modules + +/.idea/ + +*.iml + +#iOS +*.a +*.ipa +*.so +*.DSYM +*.DSYM.zip diff --git a/.munit b/.munit new file mode 100644 index 0000000..d9540af --- /dev/null +++ b/.munit @@ -0,0 +1,6 @@ +version=munit +src=test/src +bin=bin +report=report +hxml=build.hxml +classPaths=src diff --git a/project.xml b/project.xml new file mode 100644 index 0000000..f55bce5 --- /dev/null +++ b/project.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/ShortCuts.hx b/src/ShortCuts.hx index b186d3f..38ec714 100644 --- a/src/ShortCuts.hx +++ b/src/ShortCuts.hx @@ -57,7 +57,7 @@ class ShortCuts{ * @return void */ static public function mirrors( ) : Array { - return MacroMirrors.build( ); + return mirror.Mirror.build();//MacroMirrors.build( ); } /** @@ -78,4 +78,4 @@ class ShortCuts{ // -------o misc -} \ No newline at end of file +} diff --git a/src/mirror/Cpp.hx b/src/mirror/Cpp.hx new file mode 100644 index 0000000..36896a1 --- /dev/null +++ b/src/mirror/Cpp.hx @@ -0,0 +1,68 @@ +package mirror; + +import haxe.macro.Context; +import haxe.macro.Expr; +import haxe.macro.Type.ClassType; + +using haxe.macro.Tools; +using mirror.CppFieldTool; +using tools.ExprTool; +using tools.FieldTool; +using tools.FunctionTool; +using tools.MetadataTools; +using tools.VariableTool; + +class Cpp +{ + function new(){} + + public static function build(field:Field, localClass:ClassType):Field + { + var library = field.getLibraryName(localClass); + var primitive = field.getPrimitiveName(localClass); + var func = field.getFunction(); + var argsCount = func.args.length; + + #if munit + var entryPrimitive = MetadataTools.create("cpp_primitive", field.pos, + [macro $v{primitive}]); + field.meta.push(entryPrimitive); + + var entryLibrary = MetadataTools.create("cpp_library", field.pos, + [macro $v{library}]); + field.meta.push(entryLibrary); + #end + + #if (verbose_mirrors) + Sys.println($v{library} + " :: " + $v{primitive} + '($argsCount)'); + #end + + var fieldName = getMirrorName(field.name); + var args = func.getArgsNames(); + var argsCount = args.length; + var returnExpr = func.createReturnExpr(fieldName, args); + var result = func.create(fieldName, field.pos); + if (Context.defined("cpp")) + { + func.expr = macro + { + if ($i{fieldName} == null) + { + $i{fieldName} = cpp.Lib.load($v{library}, $v{primitive}, $v{argsCount}); + #if verbose_mirrors + Sys.println("Lib not loaded, loading it"); + Sys.println($v{library} + "::" + $v{primitive} + '($argsCount)'); + #end + } + $returnExpr; + } + } + + return result; + } + + static inline function getMirrorName(name:String) + { + return 'mirror_cpp_$name'; + } +} diff --git a/src/mirror/CppFieldTool.hx b/src/mirror/CppFieldTool.hx new file mode 100644 index 0000000..301c600 --- /dev/null +++ b/src/mirror/CppFieldTool.hx @@ -0,0 +1,73 @@ +package mirror; + +import haxe.macro.Context; +import haxe.macro.Expr; +import haxe.macro.Type.ClassType; +import org.shoebox.macros.MacroMirrors.MetaDataTools; + +using tools.ExprTool; +using tools.FieldTool; +using tools.MetadataTools; + +class CppFieldTool +{ + public static inline var TagCpp = "CPP"; + public static inline var TagDefaultLibrary = "CPP_DEFAULT_LIBRARY"; + public static inline var TagPrimitivePrefix = "CPP_PRIMITIVE_PREFIX"; + + public static function isCpp(field:Field):Bool + { + return field.meta.has(TagCpp); + } + + public static function getPrimitiveName(field:Field, + localClass:ClassType):String + { + var entry:MetadataEntry = field.meta.get(TagCpp); + var result:String; + if (entry.params.length > 1) + { + result = entry.params[1].getString(); + } + else + { + var prefix = ""; + var func = field.getFunction(); + var context = Context.getLocalClass(); + var metas = localClass.meta.get(); + if ( metas.has(TagPrimitivePrefix)) + { + entry = metas.get(TagPrimitivePrefix); + if (entry.params.length == 0) + { + Context.error("Cpp primitive tag is defined without value", + field.pos); + } + + prefix = entry.params[0].getString() + '_'; + } + + result = prefix + field.name; + } + + return result; + } + + public static function getLibraryName(field:Field, + localClass:ClassType):String + { + var entry:MetadataEntry = field.meta.get(TagCpp); + var meta = localClass.meta.get(); + if (entry.params.length == 0 && !meta.has(TagDefaultLibrary)) + { + Context.error("Not default library defined globary or locally", + field.pos); + } + + var expr = entry.params.length > 0 ? entry.params[0] + : meta.get(TagDefaultLibrary).params[0]; + var result:String = expr.getString(); + + return result; + } +} diff --git a/src/mirror/Jni.hx b/src/mirror/Jni.hx new file mode 100644 index 0000000..6bddcfa --- /dev/null +++ b/src/mirror/Jni.hx @@ -0,0 +1,86 @@ +package mirror; + +import haxe.macro.Context; +import haxe.macro.Expr; +import haxe.macro.Type; + +using haxe.macro.Tools; +using mirror.JniFieldTool; +using tools.ExprTool; +using tools.FieldTool; +using tools.FunctionTool; +using tools.MetadataTools; +using tools.VariableTool; + +class Jni +{ + public function new(){} + + public static function build(field:Field, localClass:ClassType):Field + { + var jniPrimitive = field.getPrimitiveName(); + var jniSignature = field.getSignature(); + var jniPackage = field.getPackageName(); + + #if munit + var entrySignature = MetadataTools.create("jni_signature", field.pos, + [macro $v{jniSignature}]); + field.meta.push(entrySignature); + + var entryPrimitive = MetadataTools.create("jni_primitive", field.pos, + [macro $v{jniPrimitive}]); + field.meta.push(entryPrimitive); + + var entryPackage = MetadataTools.create("jni_package", field.pos, + [macro $v{jniPackage}]); + field.meta.push(entryPackage); + #end + + #if (verbose_mirrors) + Sys.println('$jniPackage // $jniPrimitive // $jniSignature'); + #end + + var func = field.getFunction(); + var fieldName = getMirrorName(field.name); + var args = func.getArgsNames(); + var argsCount = args.length; + var returnExpr = func.createReturnExpr(fieldName, args); + var result = func.create(fieldName, field.pos); + var isStaticMethod = field.isStaticField(); + if (Context.defined("android")) + { + func.expr = macro + { + if ($i{fieldName} == null) + { + #if verbose_mirrors + trace("Lib not loaded, loading it"); + trace($v{jniPackage} + " :: " + $v{jniPrimitive} + + ' :: signature '+$v{jniSignature}); + #end + + #if (openfl || nme) + if ($v{isStaticMethod}) + { + $i{fieldName} = openfl.utils.JNI.createStaticMethod( + $v{jniPackage}, $v{jniPrimitive}, $v{jniSignature}); + } + else + { + $i{fieldName} = openfl.utils.JNI.createMemberMethod( + $v{jniPackage}, $v{jniPrimitive}, $v{jniSignature}); + } + #end + } + + $returnExpr; + } + } + return result; + } + + static inline function getMirrorName(name:String) + { + return 'mirror_jni_$name'; + } +} diff --git a/src/mirror/JniFieldTool.hx b/src/mirror/JniFieldTool.hx new file mode 100644 index 0000000..33d8daa --- /dev/null +++ b/src/mirror/JniFieldTool.hx @@ -0,0 +1,152 @@ + package mirror; + +import haxe.macro.Context; +import haxe.macro.Expr; +import haxe.macro.Type; + +using haxe.macro.Tools; +using tools.ExprTool; +using tools.FieldTool; +using tools.MetadataTools; + + class JniFieldTool + { + public static inline var TagJni = 'JNI'; + public static inline var TagDefaultLibrary = 'JNI_DEFAULT_PACKAGE'; + + public static function isJni(field:Field):Bool + { + return field.meta.has(TagJni); + } + + public static function getPackageName(field:Field):String + { + var result:String; + var metas = Context.getLocalClass().get().meta.get(); + var entry:MetadataEntry = field.meta.get(TagJni); + if (metas.has(TagDefaultLibrary)) + { + if (metas.get(TagDefaultLibrary).params.length == 0) + { + #if (haxe_ver >= 3.1) + Context.fatalError("Default package is defined " + + "(JNI_DEFAULT_PACKAGE) without argument", field.pos); + #end + } + + result = entry.params.length > 0 ? entry.params[0].getString() + : metas.get(TagDefaultLibrary).params[0].getString(); + } + else + { + var params = entry.params; + result = (params.length > 1) ? params[0].getString() + : Context.getLocalClass().get().pack.join('.'); + } + + result = result.split('.').join('/') + "/" + Context.getLocalClass().get().name; + return result; + } + + public static function getPrimitiveName(field:Field):String + { + var entry:MetadataEntry = field.meta.get(TagJni); + var params = entry.params; + var length = params.length; + return (length > 0) ? entry.params[0].getString() : field.name; + } + + public static function getSignature(field:Field):String + { + var reference = FieldTool.getFunction(field); + var result = '('; + for (arg in reference.args) + { + result += translateArg(arg, field.pos); + } + + var returnType:Null = reference.ret.toType(); + result += ")" + translateType(returnType, field.pos); + + return result; + } + + public static function translateArg(arg:FunctionArg, pos:Position):String + { + var argType = arg.type.toType(); + return translateType(argType, pos); + } + + public static function translateType(argType:Null, pos:Position):String + { + return switch (argType) + { + case TAbstract(cf, a ): + translateAbstractType(cf.get(), pos); + + case TDynamic(t): + if (Context.defined("openfl")) + "Lorg/haxe/lime/HaxeObject;"; + else + "Lorg/haxe/nme/HaxeObject;"; + + default: + translateArgType(argType, pos); + } + } + + public static function translateAbstractType(type:AbstractType, pos:Position):String + { + var result:String = switch (type.name) + { + case "Bool" : "Z"; + case "Float" : "F"; + case "Int" : "I"; + case "Void" : "V"; + default: + } + + #if (haxe_ver >= 3.1) + if (result == null) + Context.fatalError("Unsupported abstract type ::: " + type.name, pos); + #end + + return result; + } + + public static function translateArgType(type:Null, pos:Position):String + { + return switch (type) + { + case TInst(t, params): + translateSubArgType(type, params, pos); + + default: + #if (haxe_ver >= 3.1) + Context.fatalError("Unsupported Type ::: " + type.getParameters()[0], pos); + #end + } + } + + public static function translateSubArgType(type:Null, params:Array, + pos:Position):String + { + var result:String; + switch (type.getParameters()[0].get().name) + { + case "String": + result = "Ljava/lang/String;"; + + case "Array": + result = "[" + translateType(params[0], pos); + + default: + var classType:ClassType = type.getParameters()[0].get(); + result = "L"+classType.pack.join("/") + + (classType.pack.length == 0 ? "" : "/" ) + + classType.name+";"; + } + + return result; + } + } diff --git a/src/mirror/Mirror.hx b/src/mirror/Mirror.hx new file mode 100644 index 0000000..10b21f6 --- /dev/null +++ b/src/mirror/Mirror.hx @@ -0,0 +1,52 @@ +package mirror; + +import haxe.macro.Context; +import haxe.macro.Expr; +import haxe.macro.Type.ClassType; + +using mirror.CppFieldTool; +using mirror.JniFieldTool; +using tools.ExprTool; +using tools.FieldTool; +using tools.MetadataTools; + +class Mirror +{ + static inline var CppMeta = "CPP"; + static inline var TagCppDefaultLib = "CPP_DEFAULT_LIBRARY"; + static inline var TagCppPrimitivePrefix = "CPP_PRIMITIVE_PREFIX"; + + function new(){} + + public static function build():Array + { + var fields = Context.getBuildFields(); + + var isCpp = #if munit true #else Context.defined("cpp") #end; + var isAndroid = #if munit true #else Context.defined("android") #end; + var isOpenFl = Context.defined("openfl") || Context.defined("nme"); + if (#if munit true #else isOpenFl #end) + { + var localClass = Context.getLocalClass().get(); + var result:Field; + for (field in fields.copy()) + { + if (isCpp && field.isCpp()) + { + result = Cpp.build(field, localClass); + } + else if (isAndroid && field.isJni()) + { + result = Jni.build(field, localClass); + } + + if (result != null) + { + fields.push(result); + } + } + } + + return fields; + } +} diff --git a/src/tools/ExprTool.hx b/src/tools/ExprTool.hx new file mode 100644 index 0000000..793066f --- /dev/null +++ b/src/tools/ExprTool.hx @@ -0,0 +1,21 @@ +package tools; + +import haxe.macro.Expr; + +class ExprTool +{ + public static function getString(expr:Expr):String + { + var result:String; + if (expr != null) + { + result = switch (expr.expr.getParameters()[0]) + { + case CString(value): value; + default: null; + } + } + + return result; + } +} diff --git a/src/tools/FieldTool.hx b/src/tools/FieldTool.hx new file mode 100644 index 0000000..599c5af --- /dev/null +++ b/src/tools/FieldTool.hx @@ -0,0 +1,27 @@ +package tools; + +import haxe.macro.Context; +import haxe.macro.Expr; + +class FieldTool +{ + public static function getFunction(field:Field):Function + { + var result:Function; + switch (field.kind) + { + case FFun(f): + result = f; + + default: + Context.error("Only function are supported", field.pos); + } + return result; + } + + static inline function isStaticField(field:Field):Bool + { + var result = Lambda.has(field.access, AStatic); + return result; + } +} diff --git a/src/tools/FunctionTool.hx b/src/tools/FunctionTool.hx new file mode 100644 index 0000000..33c0bab --- /dev/null +++ b/src/tools/FunctionTool.hx @@ -0,0 +1,35 @@ +package tools; + +import haxe.macro.Expr; + +class FunctionTool +{ + static inline function getArgsNames(func:Function):Array + { + var result:Array = [for (a in func.args) macro $i{a.name}]; + return result; + } + + static inline function isStaticField(field:Field):Bool + { + var result = Lambda.has(field.access, AStatic); + return result; + } + + static function createReturnExpr(func:Function, name:String, + args:Array):Expr + { + var expr:Expr = macro ""; + var params = func.ret.getParameters(); + if (params[0].name == "Void") + { + expr = macro $i{name}($a{args}); + } + else + { + expr = macro return $i{name}($a{args}); + } + + return expr; + } +} diff --git a/src/tools/MetadataTools.hx b/src/tools/MetadataTools.hx new file mode 100644 index 0000000..4987c47 --- /dev/null +++ b/src/tools/MetadataTools.hx @@ -0,0 +1,44 @@ +package tools; + +#if macro + +import haxe.macro.Expr; + +class MetadataTools +{ + public static function create(name:String, pos:Position + , params:Array):MetadataEntry + { + return {name : name, params : params, pos : pos}; + } + + public static function has(metas:Metadata, metaName:String):Bool + { + var result = false; + for(meta in metas) + { + if (meta.name == metaName) + { + result = true; + break; + } + } + return result; + } + + public static function get(metas:Metadata, metaName:String):MetadataEntry + { + var result:MetadataEntry = null; + for(meta in metas) + { + if (meta.name == metaName) + { + result = meta; + break; + } + } + return result; + } +} + +#end diff --git a/src/tools/VariableTool.hx b/src/tools/VariableTool.hx new file mode 100644 index 0000000..e84e186 --- /dev/null +++ b/src/tools/VariableTool.hx @@ -0,0 +1,24 @@ +package tools; + +import haxe.macro.Context; +import haxe.macro.Expr; + +class VariableTool +{ + public static function create(refFunction:Function, name:String, + position:Position):Field + { + var types = [for (arg in refFunction.args) arg.type]; + var fieldType : FieldType = FVar(TFunction(types, refFunction.ret)); + + return + { + name : name, + doc : null, + meta : [], + access : [APublic,AStatic], + kind : fieldType, + pos : position + }; + } +} diff --git a/test/JniTest.hx b/test/JniTest.hx new file mode 100644 index 0000000..b8c88fb --- /dev/null +++ b/test/JniTest.hx @@ -0,0 +1,69 @@ +package; + +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; + +import haxe.rtti.Meta; + +import testpackage.TestJni1; +import testpackage.TestJni2; + +class JniTest +{ + public function new() + { + TestJni1; + } + + @BeforeClass public function beforeClass():Void{} + @AfterClass public function afterClass():Void{} + @After public function tearDown():Void{} + @Before public function setup():Void{} + + @Test public function testAbstractSignature() + { + var metas = Meta.getStatics(TestJni1); + Assert.areEqual(metas.method1.jni_signature[0], + "(Ljava/lang/String;ZI)Ljava/lang/String;"); + + Assert.areEqual(metas.method2.jni_signature[0], "(ZIF)Z"); + Assert.areEqual(metas.method3.jni_signature[0], + "(Ljava/lang/String;IF)V"); + } + + @Test public function testSignatureNonAbstract() + { + var metas = Meta.getStatics(TestJni1); + Assert.areEqual(metas.method4.jni_signature[0], + "(Ltestpackage/TestClass;ZI)I"); + } + + @Test public function testAbstractArray() + { + var metas = Meta.getStatics(TestJni1); + Assert.areEqual(metas.methodArray1.jni_signature[0], + "([Ljava/lang/String;)I"); + Assert.areEqual(metas.methodArray2.jni_signature[0], + "([Ljava/lang/String;[I)[Ljava/lang/String;"); + } + + @Test public function testPackage() + { + var metas = Meta.getStatics(TestJni1); + Assert.areEqual(metas.method3.jni_package[0], "testpackage"); + } + + @Test public function testPackageMeta() + { + var metas = Meta.getStatics(TestJni1); + Assert.areEqual(metas.method4.jni_package[0], "package/toto/com"); + } + + @Test public function testDefaultPackage() + { + var metas = Meta.getStatics(TestJni2); + Assert.areEqual(metas.methodAlt.jni_package[0], + "org/shoebox/testpackagealt"); + } +} diff --git a/test/extension/dependencies/android/AndroidManifest.xml b/test/extension/dependencies/android/AndroidManifest.xml new file mode 100644 index 0000000..80f14da --- /dev/null +++ b/test/extension/dependencies/android/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/test/extension/dependencies/android/build.xml b/test/extension/dependencies/android/build.xml new file mode 100644 index 0000000..366e70e --- /dev/null +++ b/test/extension/dependencies/android/build.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/test/extension/dependencies/android/project.properties b/test/extension/dependencies/android/project.properties new file mode 100644 index 0000000..0fc47ff --- /dev/null +++ b/test/extension/dependencies/android/project.properties @@ -0,0 +1,15 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +android.library=true + +android.library.reference.1=../extension-api + +# Project target. +target=android-::ANDROID_TARGET_SDK_VERSION:: diff --git a/test/extension/dependencies/android/src/org/test/extension/TestExtension.java b/test/extension/dependencies/android/src/org/test/extension/TestExtension.java new file mode 100644 index 0000000..247c338 --- /dev/null +++ b/test/extension/dependencies/android/src/org/test/extension/TestExtension.java @@ -0,0 +1,28 @@ +package org.test.extension; + +import android.app.Activity; +import android.content.res.AssetManager; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.view.View; +import org.haxe.extension.Extension; + +public class TestExtension extends Extension +{ + public static float sampleMethod(int inputValue) + { + double result = inputValue * 12.12; + return (float)result; + } + + public static int[] testArray(int test) + { + int[] result = new int[3]; + result[0] = 10; + result[1] = test; + result[2] = 100; + return result; + } +} diff --git a/test/extension/haxelib.json b/test/extension/haxelib.json new file mode 100644 index 0000000..308dda4 --- /dev/null +++ b/test/extension/haxelib.json @@ -0,0 +1,13 @@ +{ + "name": "::extension::", + "url": "", + "license": "MIT", + "tags": [], + "description": "", + "version": "1.0.0", + "releasenote": "", + "contributors": [""], + "dependencies": { + + } +} \ No newline at end of file diff --git a/test/extension/include.xml b/test/extension/include.xml new file mode 100644 index 0000000..c37d0a8 --- /dev/null +++ b/test/extension/include.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/test/extension/ndll/Mac/testextension-debug.ndll b/test/extension/ndll/Mac/testextension-debug.ndll new file mode 100755 index 0000000000000000000000000000000000000000..0f09faa692c811a920822fe2821c5d72094fa74a GIT binary patch literal 68676 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 PEBOc(!?mzx2>Jg3K4c|( literal 0 HcmV?d00001 diff --git a/test/extension/ndll/Mac/testextension.dll b/test/extension/ndll/Mac/testextension.dll new file mode 100755 index 0000000000000000000000000000000000000000..c9808b7dfa8a288b06a0c0bd7b1f524815b29a12 GIT binary patch literal 42608 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 YNx-NpU08SVh!J@gjvSLWM(!W}AL+qQHvj+t literal 0 HcmV?d00001 diff --git a/test/extension/ndll/iPhone/libtestextension-debug.iphoneos-v7.a b/test/extension/ndll/iPhone/libtestextension-debug.iphoneos-v7.a new file mode 100644 index 0000000000000000000000000000000000000000..7d530bd3c1148af238279c299fbcdd93d78cb1c0 GIT binary patch literal 5304 zcmb7IeQZ~x?#H|5IiFjj7ZS;}-h0ErNXS1!;hym7PjSVqL^38!0=Z$_iq^R4{zDFeM7$h`S}1{1uryZ)Rd2zG6^ZAEEwZ5 zUogf}Wmz(crLd(VFv=w(TTJD$vZ!bBX=AfdO6Ep|a-6Yc^i;N4ho~v^FCcU(QxuqA zcht<7qCP)Nqt*OYg~E}Vd(0c@4)?^3_^8}~YzkRDJ(z_Y(-TG@hbbs}<3Be(nupdM zU=8d7_qXBUui-zs(QZMcJdWM} zTntXNA}NPUdMT9{%%)VN<`@-tje##Ch6A#5z7U^dG?5;;9BvkcN4<9+&r2AI5! ze6{qHM#@AkTP)$Jr>Xc9G3pVe%%>8?eVKSJT`cX1_slg0mR3x3H!h8&nTt#n9vNg0Yu* zHO5#A&p)BV%U1HLyL!xyQP8vFMsZe*P8^C5y5xB%DUk%v320V~jGj=_Y0jh9>~P$S zQS071Mmm)>XlWJWx6oTL4kHgUfmwN^a|so^IYt{_DA1U*8(jw8kr_<`zaSut|) zU20>R*EEJRz6>3v?o|Ekk6AHP9(g^{9OIA~A$NpVCRt4{yB`pylHPu%SE{_Ez{m*O{%`@VcV#fDtC%)l(<+d!us!1XFU2BFI}Q04rE+&+ByF*#X)$2j z+i+`R9@;&%VYD)I6{T-~6#5u#3ocTjJ&0#anLKaQ)s6!$&m|ke5qTFrC8!*6@88k% zWoT}H8qX7K`D)Q%5savfc>YjVI}YF&o+s3_w_#M18bJoy7dpD!&W_Hu&vYz++0i4M z9fMu#<~`(l*yq5V>RblJTAvT+))hdL`YYd@7x697?$UbU;I_2u<~8WsEIp$&SlR>H zv%MX)P=j3!CXd@3Vz7&Y-*LAX?5a5m;hhhFS$Dx@4PL2v0f8_*jj_c_OwQbUQ3Y{t z@n0=H?*URpJ!_BGAROW#o|^Vy$DLdsECa7hEf6%X>)=<4Mxhwol}qZ`Y#^f-N~x@# zNE*R@qxfVgmk%cOvXM^3Bf(@jk&L(C9d|fj?c;s! z9~#=R*}oU5;=9-%4TSv56KQ+_+#d~v0-?aF=nDVxxL!0y{V*%v?!cO1NM7Y5(!>v_Krw$^L3X zl_;0xcsduy7w2BRpvqutZCEshSHA=rRZTwx@GrX9NMzJZ%E2PsWYnb9j<+hGV=OdE{$^`#3k^i;l52gpm+i5 zjHasbnrKsJp68xAo*32^))?yAAX&FqYw&idS~PIrp48gw&&2TVdwYOeZRDH{~zbTxT!r!(f&tj>&4W3=Co^po-W2-Bgg6ANN`l+J1iWSov1azR!lyR8_*V zpKh|Vf-DDH_88h6#KO4K)V*q978Q<{2BTJF9)rX=%Wxej&GVLt0b~Bg*GxGi#5tDP zsdjOeXKIrWr-(rl#Qk9O&8&qVb1GED+1DT+f*&zX`UEl7}R6ftOmcnO%};4|$Um17v^2auT4DPoR8j4tPRhIU|_??Ad>Ck9Or z--{eDKi5)IIw0}i^$~28KR4y1DPJ_@3#L41O4MuRpMhk&lqsJuCB|3!K}h_JbYZ?q z`XM$207n@kCRWnXUMB_`&2deDRZlt&>u93D}DJju4^!BdF0*oGeKD6X*$J!7_GFzVk% z`*HA6Y!c5kzF<_FXHT*X{}?3iN4Cq5IP1(+5vA2$WorwWEVGQx{4EQG@RRB)D;J6; vimRT+4{AA<&grbQE&kNjSkmV3hcrZKU7hDxAY1q6AN~GcVU`WW6YKLoC->)& literal 0 HcmV?d00001 diff --git a/test/extension/ndll/iPhone/libtestextension-debug.iphoneos-v7.ndll b/test/extension/ndll/iPhone/libtestextension-debug.iphoneos-v7.ndll new file mode 100644 index 0000000000000000000000000000000000000000..685ff3d0cd6fd4f471ba1d81dd956377c8d81bc5 GIT binary patch literal 5304 zcmb7IeQZ!1;+q#O6GP6X*jLR7^!Tt3|>~t)%T$&!F>)SW%+&;~-R{?Uo6ZCdR zZC*@Hu>@ToDH)|yd?=feo|=7BV3hz~fe#00=UgE^3)<*|al~^*TF=r+vyb;_4;WK-YJfvAtt@Dw~k|uj>P&{o4jDwV00s@Bpx+@^KqE<=lX}8_S0gixtd$ zjH}VdT3G%G175a*m&0W<(?`L`j+w<7K00wILKu?gp(I5RJSTt|J~BpJE~hz;J~iNk z@=+V!+DAH-HK}RkF-t41|9~2McW!!o;#Q~kU$-W|6uWi8_vITQUv=tc zRhy_>5WnHSN4%GQlz(JtAICj2@y^XQpLSFntJz(yI_h?3H~#JE`Dg#RPWksw-VvfY z^?FqtRlcMozmfXBJ39pR<$*09jO}^zgX*6B1J$XYR{QQ;+XK0_f4~#v{59K6b=zXy z_9fU(&akacU9488-m6wFe0<5*^{}u%5_G*=d=YuBZH$XYANgIU68d#T9cR($1!~${ zx05y2`6f8G%kk&BVu9QFJQOZgF>S7u+Coj!qTq3F z!>o;QX!q5o(aMljq`du6$fMNFyF`Ju3T;%XJa5#+j)N}GWgCYh@-A#j5IJJrzoYBR zP~HAC+LP@0YTlp`^r($`{!kY?4&oSIAggI_Ln#+EiU_nXbac6$9i45T>6iz#qgOaP zhPu|xdC2#$&w)GDxdei>J|E7lD}XNLSHC%@+c!_UN9%)u+mf!E(;#oNs~R`RWlUAI~NRA-3601_@w3p1l;sC`WDNvIJNhp3gF)2 zzf3*v0YXK#wdOSthd6{*(?0CDoB2T+cx7sVpt`PuUn!b}VsLjZX=Jm3j8Q11vPL{< z1_#XIlciifm^8{}Iu+{N}`z=Rkq4$#K1@EsP|F(C`;efWE_ql&~ zc*kb{K7@*Qu|E3H+|I(OIGgLf<&NWqtp!t`F%3y-M4W+GCWS*XMF+oC_f?12>KIZ{h*P2T(_J zWsTQFn>_P8_muI(u(q(qP}T;@y2V<9uS?dV!Grgu*4}t#?$v)h<^7rQjb9yj>iS!5 z{LlzSwjDV9`&WLM|Lb$x`bUpAzqjuDrNtY6cWeUVCV>}$SAe&HoV*k02Zn%sz^%Y2 zP~M9$;X8xC`xRpGFc|=C$p27sLhv>te^c@D&O(17g@AXJ-r{+eQe};oHz9ayyu5?K zKMN$h52XEOG5~p%gGR{!SQx1PJQ;wMZ^{VFJAu5F?@wdHJt58q5?J%;$BA8X$sMWf zRj6{rw|?}w&OYczfGkg(lhtGi5WrGE5wHDwDIhRD?zJYg1AOvW@mA1(z{aC1tAwRL z)1+qwSqilDQS>>9#p6zs_o~ISsBpeC5Va!n7%0wJhIu4a=PeTjkM)~hQ*>B}^DMKI z?cyBI)FvTLlLw5G9{^%(W-aU(Q=ux(y$1Ra?8xJ!kCR7U&a>KM{JB@bhoG-je=$zp z4?SzaHO%v4@c1oznmk~f{30Od!87eVg$c~_15m8#GHx)m*GJHi{#?-sMPF3(1w{`jih3>WGobXBQuGN$F~5`#f#PSR3+t8C z56XGC9**l&@}DUAcad)Zuu$7kr;^({n6!<> zp9g=tZQB1)@KA?uvlO6-@aCk%o^c4G=2dxlqu@5=&D6X>)IeoTcGRogZ z|8d}AY!c5kUNExHv!}BU`zR>yNA}C0IO~j60;$zsVe1P$S!NlX{#zCb;V0EqRxT7x v6jvjSAJlpxoikWzTl}f5v82u74{7kyx;oFYK(-#wKl=T@!mKwGPvqx+Luu!q literal 0 HcmV?d00001 diff --git a/test/extension/ndll/iPhone/libtestextension-debug.iphoneos.a b/test/extension/ndll/iPhone/libtestextension-debug.iphoneos.a new file mode 100644 index 0000000000000000000000000000000000000000..c1aa94c4cb6d1cd107c9af61262ce187d183f889 GIT binary patch literal 5304 zcmb7IYiv}<6`s2fyxBFz#1N30lx^cyP?>$%EYJ{G6Z3Gf8;VJsM$qxy^_pF>FYT_0 ziA-uLr0@fprlnFVrDAbgDQY7WwUt^`iiFZiQ7e=>ZKb4Y6hXjEXaTiCs`@~2zi;kb z`|f&a$dS*S`OZ0W=FH>H%=%MX%yKHT)&F2L9E$`ODB2U<9O;h5;~Rs)jj?VRHpDi@ zBf)4S67T5=2BUElibniWhK9a8*tcV6aOlx}`*-vSP>==a1Mmth<63?}%M7HHvYb97 zOXc)fc0yLum1@-15u_)o=|Ux2EXazPFXhsM>1w7pDwN}bEpKKEjXFflqJ0^mv-yg^ z_`2gdV~Y9l#hQBNXntAS#(YF6OW9QAXg*oYRjT93p1X~Ksa3>rNtvot%h|#qt!ow|1Y6@+ zI5##)Ihsz6AClR^m|A}+`-Xe>?X=BeALiq8;GgLExMKAERs*4y7xLVtf&sA_C9z_gIYwFag{rp!wn0dF0KM8ct&#&*}#6 z>KIn@<}q^FLYkIlFjxmZnbOMX=$Q4s6cw>wm{GdQT^jp$VE{cH#R_10gu3%m6 zCWfBUMPpgZZyI!xAA3DH@<YTJg%~9?I;F=li5RQl2bxdIj!{e= zRtwWOr!QiUccQ`VrK+8?SQJC$Q8H7FF)rvB!8T`eRbLdNdbHGZELRa@3{CoUj4jLc zSy(p~>$@E*V?yBDn8yGXWeWP25rZ8cKn#Q>&F8TW0MjJSz!uR4&e^YlIgR`8#T;Tz zarTM5U=ojhGS`diqdzIs?w+O+>#r>>)h>Hx2Hz9n^sEryoBj9P+~1Z2&faMEyKcU= z=NC6cpz~&X;7iwULEkb{yF4}Z>IV<|-}-*(;k607y$|iZXyajw_S3WUf8XJMe%Iw^ zR-C`J&Gu)1t>WzLyYOMZc3dm-v$LO^3twj4_7B2Wi03ce-+p%1Xn+3F4BGj0U5Mke z%*lg!E}>1|+}zxq+P&7K-3%7vakLw7w7Ueq8(_x0^MgUksBk_pq>PErVwJ3A^`OSp z*+v2SiY0{WJSsh4!&v5Z^M-c+4#?|q{bAm)((9gq!SffoEpr()$hTP^_S~je=`sl0 z(SejB;DTJd6iaH!g#^n$ovC0{sYW%in^+Wh79tnKA5pV?lk)XBr2lk+f8Zqer2sHhLGen`}-8h%H}CkLW2XLoz!=p#3t z9*W4iBSu(ip^O5}V)6RG&L1>(kcM=eE<)}acyxR3fRz2xWK`ulWW8k>d3&*#vkscw zL%qAXJ$WD5jH-Gc82E+49Z#Z;`-S(C7fc{LJ{3zM!C*9xN_O0rgU9Z3J3ff!%&www1{|;v7 zJW_(-2si=W3myThQxPtFqmX#ILMs@MBtz<%%Y+$tM41tG|!#;-6@U()?<@%iFDad;Y`k P|J|yx?&ib%_(A^zenQ_e literal 0 HcmV?d00001 diff --git a/test/extension/ndll/iPhone/libtestextension-debug.iphoneos.ndll b/test/extension/ndll/iPhone/libtestextension-debug.iphoneos.ndll new file mode 100644 index 0000000000000000000000000000000000000000..ff9acdfb45f1fabf695058031c783c8a98cab489 GIT binary patch literal 5304 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 literal 0 HcmV?d00001 diff --git a/test/extension/ndll/iPhone/libtestextension-debug.iphonesim.ndll b/test/extension/ndll/iPhone/libtestextension-debug.iphonesim.ndll new file mode 100644 index 0000000000000000000000000000000000000000..5752b193250860486f020adaf2c30c14ebc4cdf8 GIT binary patch literal 5448 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 literal 0 HcmV?d00001 diff --git a/test/extension/ndll/iPhone/libtestextension.iphoneos-v7.a b/test/extension/ndll/iPhone/libtestextension.iphoneos-v7.a new file mode 100644 index 0000000000000000000000000000000000000000..4c917169881696d361580cf28e2f7cc82696caaa GIT binary patch literal 1912 zcmb7FO=uKZ5PnH?jWZ%S2#N@{xQB?6?fJ3e27e|pNsNpnnk+;;)O0$XOfS>jlbMc8 z6k(1cd)U>xIO@fV5Ktka7{tRK7WJ^8g5VDxJR}jakXb~w_p6?6GZPZj8tQ%Z^IpBG zS8rbL*stcb%)!vk$WKvOTB1li^0OR^D(x_~M`Lj8jkYVY6p>{m9+#wug2AJ7h^TGg zEM}#+V$!DsDwcLiN2G-{h+As?O^~DrFV}_tUW$$YB1;>#N#fGD@qQw;I zLN<9z&GuTrQB~91Y?R>9lTUO1ZGf~M+yGt!e%6RVs_H{5uRw2Ln}zQMaGlT1Kqf+& zMW-rP^}(*8!6ls~R(X9B@G%D77ek4GiD+ee7;W$^ucfwqgepwawt~cnlAVK{fmZEhuxIT$z83)znf3@7=n9Qa zSQ^fwKE~ge$i1BL`*Ir!ujl&}&@KpE(|!0Dd9N+tzo3VJ$+gx0ANt_+7~tI#ZWG7m z`?joQuza0LckFJr^7&(8wk7;}?uXs~&d-F?^Vh=1XXWsN52b`#nSUtoI}mz)J$Ilr z@p`Vw^SPCGp8ZzO+q0W){c}i2ZsjFgq+CzwPGVu7u)Aj#gy>tmJpOdi9WN#)lWyhD zkBNm;6YNcig?J;dv2U^L`OhWKV#bzq3$nS3Sse}VHcTd))1?QiKORI8QTyBwMN#rE zV1AcyzUDq4&c>8{Aa@8cbp?1>h?}f~%B&v*qwl7Sd0=tX6;rwieSQUQz&zG@ zAJ#Ev`UVj7Ol5$$A2(SCm04$kZA~k%8MiCp;~&6{4Ok7j=gXWw=diJ{*?V)&L*9-< z;`&efGW$2PjI~FAyM4JI7y<|PzqdwaTVNM-22YHEH-^+~*4Ah=YpYP|d-)BIJ!Ojg zRatuf@%QpRGxd?`KPfAIh)$)V%Ib^y70!4^;O$BE9qvpK^^(eG G0s0?QYLDOm literal 0 HcmV?d00001 diff --git a/test/extension/ndll/iPhone/libtestextension.iphoneos-v7.ndll b/test/extension/ndll/iPhone/libtestextension.iphoneos-v7.ndll new file mode 100644 index 0000000000000000000000000000000000000000..632c35bf7db7fe289c113c6745ac2c211fe5246b GIT binary patch literal 1912 zcmb7FO=uHa6uxbJzM6=1Av}=>j_9JI)R{EKD*mLBw)PQewH2x^PR7a9jAUkFGL=*j zvJ`RQ&t8nWaU&E|s3;b3;X-_GA*dkug9{gJg$j*`IDTg`W0TVI^n`Q2^KD3{lVjUqXE!BGMmD|*q1{Sj@aWmssqf1nEdw`zmw^9k#2{7mA(j`Qx3EpZ_Y(N0&&@z4LYYOU zDp&QvuA#v>oh4RzeG~982HqD#iGhh|z)>AT>$MCo5>b5&Uf&OnV=brn0k|4iAA|GI zY&A<32bmw^2G0jw;3R4&ENb)6Y^&f9N8u^I5#wh>qMV@>M$Mykw&08$js9wk;5=Kr zeYJv_iR)P-WS!8gB_+V&BuFiqPE5+h1<4t54wwU@!3wd?p^1Vm)oX)@3i8XmDU zoJW0(=a|U7obdZ{8w#)I`xVdz2wc;B_!xPwRp6)4L%_rz)&C#*;Pn{b-4kvT$L9Ms zuVt|OKb7v--EQUEr}$(`_|4SPjbElG!l~(N;r)|x_`%0g+^tMM6!`57y||v+*&2T{ z)#Uly%6rd#tLNRRmA5|c7Lr?e#TF^oQ@RtM=@54J#EcMqvzJf&JL{e(CPou(<;kb` zOtJ~~rua;>5!l!_TlV~?6Q?j^RjLKq+{LWz4e&OMCYn>F2a7)*M2e_=Zipf%`5>6z zC7iF>0mRvul8<~=Z0{Cg{59n5LX2Gj?h)c9>!330yTItXDPta3Ty@3RdEh3@W8HN{ zne|rq9|5C?a}Ky3e%3){)+PA)JxIcT7Wg;(tb@v|bB}o+^n9F+m$1)q;Bw4ko%dlK zbH;A~QO{Tgi2HGqbx@ggCfJs=0-JHW;yzvku4uq&&^=$~{5gjejm_Sha|ZGn91_=m z#FyFs7t2_?7r4=v`+*^FaQ}O2WVQu%K_~IV7R?=w>$ss59);D_jNG7?*SQGbjx9?=p0a8ilX-m1VgAQQYj$-X_ENupj-`7A&` E0Lh<_L;wH) literal 0 HcmV?d00001 diff --git a/test/extension/ndll/iPhone/libtestextension.iphoneos.a b/test/extension/ndll/iPhone/libtestextension.iphoneos.a new file mode 100644 index 0000000000000000000000000000000000000000..e17b391ce40d688dbf71fae8b30a21f1386445ca GIT binary patch literal 1848 zcmb7F&1(}u6raZWm8j$(*n{Yb9u&21(sWy)YAdN)iTKeX^`pG5o2^|)c0;n2C*tT9gh-VRm{srPq1rcirtsgCd3L;|sz0GW!go^s$&F{T8GrxJWZ)SE|m!3C9 z4~DnL_Qh3YNn(lEezh&GX`PDF5pP3Bd%Qzam6)n(iG-rWG&H^phlyJI&z(s29#Q&F zo*C#(3W&lDWDdGfq9*aU#8Ds-<;}~K%bO!skzBLj#)23-X3;h6g5}s$(6hOWdBSu@ zowV==F7;(~%WjN;)x!KdsI6>4V1I3z%$Q+uf7sfx`)hBP!-vDVn(jzlMAYVCICjA$X5k_K!Li6ll(US&)$AoFQ*g&FCH|Eo_?}UJU8CUU zE&H-$U5=v_eT{pmEgxYQ*{ov+i4i4x26_UoTFYR~+If5~0wKyeX|hli8X2<it6<#3?8Xmxz_Q`Mfoh43WP} zseAAH^||rspOwnTXjm*X@Al@WB99kB5oIA7IsK{B{dDeIrSjoG_{II)ft}rzKK^rQJP`&aB)tgln zuN+dm**&sPh@0gQIA3AR=Ec~Ja;fxmj<3q?N~OYQ_AGQ9Hpl+_un@&W?NdY)$9TRY zDJZ`EP$v-IZD@x?t~1BeLQH;#4Vk!yW*EN89{gKqF2aA~yJDgQ1n1;e=@)^>YqIK! z3BDkx*W^?+Fad7S1;tuJEfTp4^={tj`%R)-;sam{PRd>226^C~NSpI{$u=fpeQ_PS z6`T1EydZ7PX%pL+dknZ++I)WaOi4=7S7UQ5hzq)cXTrieL3$?R7&MY`bU5|j{2v}{ z8ZGjlVd)LW74d%+^-T4@g=K#x=TmX*&y!ARobi|m`tzw+ytev5SHDW=J(@asxF_WV8{R^MV*mgE literal 0 HcmV?d00001 diff --git a/test/extension/ndll/iPhone/libtestextension.iphoneos.ndll b/test/extension/ndll/iPhone/libtestextension.iphoneos.ndll new file mode 100644 index 0000000000000000000000000000000000000000..f676d92907709731b44f7fc0fa10a626c409e273 GIT binary patch literal 1848 zcmb7F&1(}u6raZWm8j$(*n{Yb9u&3irb)C=wUtz@MEq!x`cYoj?Zz%7yCK<16oiNu z4<7U`Y+ElL#Ip!O{{r!*f{0Z@>qm>Af`}M@Z!_B_p`t!`^Ly{j%x~W8o0;9xr5B9R z1L3XOo|vjEiWb*8)s9%Avr|#_#yZfEi0w_Pil(Z`cwAAmBpP3a!$j@)K;!2u)mI^%$Q+ef7r&7`%5I`@ZqqQQMI^{*hjs{reN#Y zJ{y?P4YS?B7JPa7WA4`)SSz3{&{pWP5E`ZC53;?4{6y>%`o02JN?j$#5w=-!r2`-u z=p7tb^w}DO^897MH)wcWG-U=BqJCF*Eu+u2e5Pg&p3ikiVXmJd2-fk$1`f`{aP%zM zOw!CT#p59lIEgxmi26JX$1b|WEIi~tI2IU*@|ID&lDp_+i|*LP_`h-l-!tm3YZTpr zWnYr4OL4TLuX!)^X5N(WD$Ff}H`5jMDlJiO<}KEVt6pW9>dmN% zR|zTJ%r4m{#EnV_oG&qE<3j9urCfe8%U9)AwOZvfdj>iVn`3`|Sco)H{}d6$FrM#7 z8j5c}v=4~yHndG5*O}uZLQH;#4Vk!$W*EN89{ihVF2H~7yJDgY1n1;e>6d`WYqI8w z3BDkx*W^?!Fad7S1;tuJZ4$W)^={qn`z@kd;(cHnPRbqNI(gt8OPlj~!8RsheQ^!C z8JqbIJTGm|X#?Asdla}++I)WaOi4=7S7&o9hzq)mXTrieL3%dp7?jC6I-JID{tpi} zjh6V&u=s}Kiuk{ZMyAH!!jeCebLm*}&y!9jIpZ-C^ykuAtiJj|SHDW=J(50gs3%R- IM>_WV8`1iN3;+NC literal 0 HcmV?d00001 diff --git a/test/extension/ndll/iPhone/libtestextension.iphonesim.a b/test/extension/ndll/iPhone/libtestextension.iphonesim.a new file mode 100644 index 0000000000000000000000000000000000000000..61ac27d88d98b4c9bbf84e2ada2bcfea226efd5b GIT binary patch literal 2272 zcma)7Uuaup6#uf_Zn1971`!p6-eJHoFyf1dA*+S>I#OHZhCqLbl&qME*Iz1qK!4}X%HNS6jE@vG zeMC!A7S+@%x;;?=HT8lKt)c}Ne*E{(XGg&u1_mVEIs``T$aBo^1K+^;5o~usIi4{n z{RnL?I^7_mTy`$km6`h($ngs33Wg)BRK#s23`DktVs-nhC->%9ftu$lqHwO=1J36G z(X698R$-!Ixz+U7u@1*+pp66^_brAY4(_R=P%W3M6;?A4WyW*k9iB(--|O4|tDxQk zqC&%|Ta}wq(_hEW&_{va`x}Am&qq|Q7Rf>}Omn3}=P_v~Th2toL}uMYHghkcL|F-D2Zx?XlOu-v;Y5#->t;bORs z7=rl!yeLG8)eNkE1-Jwo&lkhumk)c_-Xr z#~YtygR4rUbp-S5hR$s5hORf4px+Ihg!T_`%lE@K=C@7LjE08Yb_L>>cY+Tx5hZ-@ z@r4IU(Z`7pb@RRp5FAuYg_Z%;{4#lFKg#dkM-2E)-1N$?NuaS zYrca}F0RP5$xFG`+}yM3(t63Y@*;IgJ@}p>(uDtJB8nqc@P2>N3+^4qw!p0`BCr$; zoH#b1tY8XWpVxptJZra;>@YqQymRQ{aV66{%r-ujzrZ%^w}EFHZ>Zm3dwCyQ4Z43| z<8$ZF$p;K;K5$LaGm@%8Y`XhNhz;HcVX4mw@x|Au6R`0ah6_NBPs9HyYo-28$YZY9 z@p}Vtd}aY|+$k^|_bUAO90FWD_T^?r?8wYxk0}oH{2u`upCZp3pPj=RUswxq6N#Og@zdZ&zF*`#h$- z{yb0AC<)SSyILUAuIi4U(jo_T-%CLs={9ajnCShD`i1%7HU<9DI|o0`MP!v(Whf literal 0 HcmV?d00001 diff --git a/test/extension/ndll/iPhone/libtestextension.iphonesim.ndll b/test/extension/ndll/iPhone/libtestextension.iphonesim.ndll new file mode 100644 index 0000000000000000000000000000000000000000..c896ed0f93e1214d503bbe42bf926fa2d9ce9189 GIT binary patch literal 2272 zcma)7PiP!v6#urJv}+iRR#;6b~LmJp@wdP4MJJP(fu65hZ#M!LGkI^G$YkO`wl?-~0c* z_vZU|c3f{1%dZc1e)=1!LJUs!gj_ zrKVn~+s2IHlxrp7I(BUp-KzHMkkvwb1F5Y_Q=q?8Mpn$k?{9SEi2lY#CsY&a;T6 zMDvdBSjDNTdVy#lCRawnIl%32^dOVNZzu$N8S3!LM zM8&4lu&TGEroWCKppOH;3N`{cn2)GZE0Kjx$Xu!x|5wKuOvpX#AqU5u8}QceDeyiJ zy|YxQlcV3V4b~A&&CFrv`}QbuL?HapR|opL$394j7^6&PL$A0QSngey7;^C1a4}p* z0zv$Lo))6aY6jLn4_twb=SyJm%ZP)Im;*BSdy3~g1?(${T@IiQr^D>m)_=Lax)*J; zB_ri~|F(vxo z&x?F*PK_lAteZ3io*LD_n#f8D|KB-?gH_=niMyu56bk>o4 zqxA+txwsP37BA&SYx}^eOY3FV%8TTcdh|U*q>13oM3h9V;QjtrFSvIc+d_A)iqJ|p zbmr86vW6*meO?59{kYRfv%}<2_};Ngr$Cm%4Z`M`Ba&r7NbvF+|BA+~rQM5R6_#K)hZPQccO7%l=iegyvivR3L}fjr@g zp5M!e<1-6z$wKBHP6PR#`IISi4BrBop8)-xc}&Lha4$n)A^2RK1TsGknv(niXkPN0px59( ztO&vXCM9|97oQl$Pyn@N-lriLbVgm;Fj{+Yb<~o<)8d=v m69ns(>Dfz@)3_>07r8gRt1t1y>D`i1%8@g84uMHn0r(Hl2hnE$ literal 0 HcmV?d00001 diff --git a/test/extension/project/Build.xml b/test/extension/project/Build.xml new file mode 100644 index 0000000..0401c56 --- /dev/null +++ b/test/extension/project/Build.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/extension/project/build.sh b/test/extension/project/build.sh new file mode 100644 index 0000000..0fbf432 --- /dev/null +++ b/test/extension/project/build.sh @@ -0,0 +1,107 @@ +NDLL="../ndll/iPhone/" +HXCPP="haxelib run hxcpp Build.xml" +HXCPP_IPHONEOS=$HXCPP" -Diphoneos" +DEBUG="-Ddebug -Dfulldebug" +VERSION="-Dmiphoneos-version-min=7.0" +VERBOSE="-verbose" +GCC="-DHXCPP_GCC" +ARC="-DOBJC_ARC" +M64="-DHXCPP_M64" +LIB="downloadmanager" +DELAY="0.5" + +cleanup() +{ + rm -rf "obj" + rm -rf "all_objs" +} + +ios_armv6() +{ + echo "\n\n\\033[1;32mCompiling for armv6" + sleep $DELAY + rm -rf NDLL"lib"LIB"-debug.iphoneos.a" + rm -rf NDLL"lib"LIB".iphoneos.a" + $HXCPP_IPHONEOS $VERBOSE $DEBUG $ARC $GCC + sleep $DELAY + $HXCPP_IPHONEOS $VERBOSE $ARC $GCC + sleep $DELAY +} + +ios_armv7() +{ + echo "\n\n\\033[1;32mCompiling for armv7" + rm -rf NDLL"lib"LIB"-debug.iphoneos-v7.a" + rm -rf NDLL"lib"LIB".iphoneos-v7.a" + + $HXCPP_IPHONEOS -DHXCPP_ARMV7 $VERBOSE $DEBUG $VERSION $ARC $GCC + sleep $DELAY + $HXCPP_IPHONEOS -DHXCPP_ARMV7 $VERBOSE $VERSION $ARC $GCC + sleep $DELAY +} + +ios_simulator() +{ + echo "\n\n\033[1;32mCompiling for simulator" + rm -rf NDLL"lib"LIB"-debug.iphonesim.a" + rm -rf NDLL"lib"LIB".iphonesim.a" + $HXCPP -Diphonesim $VERBOSE $DEBUG $ARC $VERSION $GCC + sleep $DELAY + $HXCPP -Diphonesim -DHXCPP_ARMV7 $VERBOSE $VERSION $ARC $GCC + sleep $DELAY +} + +mac() +{ + echo "\n\n\033[1;32mCompiling for OSX" + rm -rf NDLL"lib"LIB"-debug.iphonesim.a" + rm -rf NDLL"lib"LIB".iphonesim.a" + $HXCPP $VERBOSE $DEBUG $VERSION + sleep $DELAY + $HXCPP -DM64 $VERBOSE $VERSION + sleep $DELAY +} + +mac64() +{ + echo "\n\n\033[1;32mCompiling for OSX 64bit" + rm -rf NDLL"lib"LIB"-debug.iphonesim.a" + rm -rf NDLL"lib"LIB".iphonesim.a" + $HXCPP $VERBOSE $DEBUG $VERSION + sleep $DELAY + $HXCPP -DM64 $VERBOSE $VERSION + sleep $DELAY +} + +case "$1" in + "v6") + cleanup + ios_armv6 + ;; + "v7") + cleanup + ios_armv7 + ;; + "simulator") + cleanup + ios_simulator + ;; + "mac") + cleanup + mac + ;; + "mac64") + cleanup + mac64 + ;; + *) + cleanup + ios_armv6 + ios_armv7 + ios_simulator + mac + mac64 + ;; +esac + +cleanup diff --git a/test/extension/project/common/Extension.cpp b/test/extension/project/common/Extension.cpp new file mode 100644 index 0000000..bf4edee --- /dev/null +++ b/test/extension/project/common/Extension.cpp @@ -0,0 +1,6 @@ +#include "Utils.h" + +namespace TestExtension +{ + +} diff --git a/test/extension/project/common/ExternalInterface.cpp b/test/extension/project/common/ExternalInterface.cpp new file mode 100644 index 0000000..d66a67f --- /dev/null +++ b/test/extension/project/common/ExternalInterface.cpp @@ -0,0 +1,32 @@ +#ifndef STATIC_LINK +#define IMPLEMENT_API +#endif + +#if defined(HX_WINDOWS) || defined(HX_MACOS) || defined(HX_LINUX) +#define NEKO_COMPATIBLE +#endif + +#include + +static value testextension_sampleMethod(value val) +{ + return alloc_float(val_int(val) * 12.12); +} +DEFINE_PRIM (testextension_sampleMethod, 1); + +static value prefix_test1(value testString, value testBool) +{ + return alloc_float(1.23); +} +DEFINE_PRIM (prefix_test1, 2); + +extern "C" void testextension_main() +{ + val_int(0); // Fix Neko init +} +DEFINE_ENTRY_POINT(testextension_main); + +extern "C" int testextension_register_prims() +{ + return 0; +} diff --git a/test/extension/src/org/test/extension/TestExtension.hx b/test/extension/src/org/test/extension/TestExtension.hx new file mode 100644 index 0000000..43cb0fe --- /dev/null +++ b/test/extension/src/org/test/extension/TestExtension.hx @@ -0,0 +1,19 @@ +package org.test.extension; + +@:build(ShortCuts.mirrors()) +@CPP_DEFAULT_LIBRARY("testextension") +@CPP_PRIMITIVE_PREFIX("testextension") +class TestExtension +{ + + #if android @JNI #else @CPP #end + public static function sampleMethod(value:Int):Float + { + return -1.0; + } + + @JNI public static function testArray(value:Int):Array + { + return []; + } +} diff --git a/test/src/CppCallTest.hx b/test/src/CppCallTest.hx new file mode 100644 index 0000000..a71e0a4 --- /dev/null +++ b/test/src/CppCallTest.hx @@ -0,0 +1,26 @@ +package; + +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; + +#if cpp +import org.test.extension.TestExtension; +#end + +class CppCallTest +{ + public function new() + { + trace("constructor"); + } + + #if (mac || ios) + @Test public function test1() + { + var result = TestExtension.sampleMethod(100); + Assert.areEqual(result, 1212); + } + + #end +} diff --git a/test/src/CppTest.hx b/test/src/CppTest.hx new file mode 100644 index 0000000..9cbce32 --- /dev/null +++ b/test/src/CppTest.hx @@ -0,0 +1,66 @@ +package; + +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; + +import haxe.rtti.Meta; + +class CppTest +{ + public function new() + { + Test1; + Test2; + } + + @BeforeClass public function beforeClass():Void{} + @AfterClass public function afterClass():Void{} + @After public function tearDown():Void{} + @Before public function setup():Void{} + + #if !android + @Test public function testLibrary() + { + Assert.areEqual(Meta.getStatics(Test1).test1.cpp_library[0], "testextension"); + Assert.areEqual(Meta.getStatics(Test1).test2.cpp_library[0], "toto"); + } + + @Test public function testPrimitive() + { + Assert.areEqual(Meta.getStatics(Test1).test1.cpp_primitive[0], "prefix_test1"); + Assert.areEqual(Meta.getStatics(Test1).test2.cpp_primitive[0], "prim"); + } + + @Test public function testDefault() + { + Assert.areEqual(Meta.getStatics(Test2).test1.cpp_library[0], "testextension"); + Assert.areEqual(Meta.getStatics(Test2).test1.cpp_primitive[0], "test1"); + } + + @Test public function testCall1() + { + #if cpp + var result = Test1.test1("toto", false); + Assert.areEqual(result, 1.23); + #end + } + #end +} + +@:build(ShortCuts.mirrors()) +@CPP_DEFAULT_LIBRARY("testextension") +@CPP_PRIMITIVE_PREFIX("prefix") +class Test1 +{ + @CPP public static function test1(toto:String, value:Bool):Float{return 0.0;}; + @CPP("toto", "prim") public static function test2(toto:String, + value:Bool):Bool{return false;}; +} + +@:build(ShortCuts.mirrors()) +@CPP_DEFAULT_LIBRARY("testextension") +class Test2 +{ + @CPP public static function test1(toto:String, value:Bool):Void{}; +} diff --git a/test/src/JniCallTest.hx b/test/src/JniCallTest.hx new file mode 100644 index 0000000..2f0b87b --- /dev/null +++ b/test/src/JniCallTest.hx @@ -0,0 +1,35 @@ +package; + +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; + +#if android +import org.test.extension.TestExtension; +#end + +class JniCallTest +{ + public function new() + { + trace("constructor"); + } + + #if android + @Test public function test1() + { + var result = TestExtension.sampleMethod(100); + Assert.areEqual(result, 1212); + } + + @Test public function testArray() + { + var result = TestExtension.testArray(42); + Assert.areEqual(result.length, 3); + Assert.areEqual(result[0], 10); + Assert.areEqual(result[1], 42); + Assert.areEqual(result[2], 100); + } + + #end +} diff --git a/test/src/JniTest.hx b/test/src/JniTest.hx new file mode 100644 index 0000000..86343a0 --- /dev/null +++ b/test/src/JniTest.hx @@ -0,0 +1,69 @@ +package; + +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; + +import haxe.rtti.Meta; + +import testpackage.TestJni1; +import testpackage.TestJni2; + +class JniTest +{ + public function new() + { + TestJni1; + } + + @BeforeClass public function beforeClass():Void{} + @AfterClass public function afterClass():Void{} + @After public function tearDown():Void{} + @Before public function setup():Void{} + + @Test public function testAbstractSignature() + { + var metas = Meta.getStatics(TestJni1); + Assert.areEqual(metas.method1.jni_signature[0], + "(Ljava/lang/String;ZI)Ljava/lang/String;"); + + Assert.areEqual(metas.method2.jni_signature[0], "(ZIF)Z"); + Assert.areEqual(metas.method3.jni_signature[0], + "(Ljava/lang/String;IF)V"); + } + + @Test public function testSignatureNonAbstract() + { + var metas = Meta.getStatics(TestJni1); + Assert.areEqual(metas.method4.jni_signature[0], + "(Ltestpackage/TestClass;ZI)I"); + } + + @Test public function testAbstractArray() + { + var metas = Meta.getStatics(TestJni1); + Assert.areEqual(metas.methodArray1.jni_signature[0], + "([Ljava/lang/String;)I"); + Assert.areEqual(metas.methodArray2.jni_signature[0], + "([Ljava/lang/String;[I)[Ljava/lang/String;"); + } + + @Test public function testPackage() + { + var metas = Meta.getStatics(TestJni1); + Assert.areEqual(metas.method3.jni_package[0], "testpackage/TestJni1"); + } + + @Test public function testPackageMeta() + { + var metas = Meta.getStatics(TestJni1); + Assert.areEqual(metas.method4.jni_package[0], "package/toto/com/TestJni1"); + } + + @Test public function testDefaultPackage() + { + var metas = Meta.getStatics(TestJni2); + Assert.areEqual(metas.methodAlt.jni_package[0], + "org/shoebox/testpackagealt/TestJni2"); + } +} diff --git a/test/src/OpenflPrintClient.hx b/test/src/OpenflPrintClient.hx new file mode 100644 index 0000000..cd8f136 --- /dev/null +++ b/test/src/OpenflPrintClient.hx @@ -0,0 +1,223 @@ +/**** +* Copyright 2013 Massive Interactive. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY MASSIVE INTERACTIVE ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MASSIVE INTERACTIVE OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of Massive Interactive. +****/ +package; + +import massive.munit.client.PrintClientBase; +import massive.munit.AssertionException; +import massive.munit.ITestResultClient; +import massive.munit.TestResult; +import massive.munit.util.MathUtil; +import massive.haxe.util.ReflectUtil; +import massive.munit.util.Timer; + + +/** + * Generates basic text formatted test result output. + * + *

+ * Example output: + *

+ *
+ * MUnit Results
+ * ------------------------------
+ * 
+ * Class: SampleTest ...
+ * Class: sub.ItemTest ..
+ * 
+ * PASSED
+ * Tests: 5  Passed: 5  Failed: 0 Errors: 0 Ignored: 0 Time: 0.202
+ * ==============================
+ * 
+ * + * @author Mike Stead + */ +class OpenflPrintClient extends PrintClientBase +{ + + /** + * Default id of this client. + */ + public static inline var DEFAULT_ID:String = "print"; + + #if openfl + var textField:flash.text.TextField; + #end + + var result:String; + + #if (js||flash) + var external:ExternalPrintClient; + #if flash8 + var textField:flash.TextField; + #elseif flash + var textField:flash.text.TextField; + #elseif js + var textArea:Dynamic; + #end + #end + + public function new(?includeIgnoredReport:Bool = true) + { + super(includeIgnoredReport); + id = DEFAULT_ID; + result = ""; + } + + override function init():Void + { + super.init(); + + #if nodejs + #elseif (js || flash) + external = new ExternalPrintClientJS(); + #if flash + initFlash(); + #elseif js + initJS(); + #end + #end + + #if openfl + initFlash(); + #end + + originalTrace = haxe.Log.trace; + #if !openfl + haxe.Log.trace = customTrace; + #end + } + + #if (flash || openfl) + function initFlash() + { + #if flash + if(!flash.external.ExternalInterface.available) + { + throw new massive.munit.MUnitException("ExternalInterface not available"); + } + #end + + #if flash8 + textField = flash.Lib.current.createTextField("__munitOutput", 20000, 0, 0, flash.Stage.width, flash.Stage.height); + textField.wordWrap = true; + textField.selectable = true; + #else + textField = new flash.text.TextField(); + textField.selectable = true; + textField.width = flash.Lib.current.stage.stageWidth; + textField.height = flash.Lib.current.stage.stageHeight; + flash.Lib.current.addChild(textField); + + #if flash + if(!flash.system.Capabilities.isDebugger) + { + printLine("WARNING: Flash Debug Player not installed. May cause unexpected behaviour in MUnit when handling thrown exceptions."); + } + #end + #end + + + + + } + #elseif js + function initJS() + { + #if haxe3 + var div = js.Browser.document.getElementById("haxe:trace"); + #else + var div = js.Lib.document.getElementById("haxe:trace"); + #end + if (div == null) + { + var positionInfo = ReflectUtil.here(); + var error:String = "MissingElementException: 'haxe:trace' element not found at " + positionInfo.className + "#" + positionInfo.methodName + "(" + positionInfo.lineNumber + ")"; + js.Lib.alert(error); + } + } + #end + + + ////// TEST CLASS LIFECYCLE ////// + override function printOverallResult(result:Bool) + { + super.printOverallResult(result); + + #if (nodejs) + #elseif (js || flash) + external.setResult(result); + external.setResultBackground(result); + #end + } + + + + function customTrace(value, ?info:haxe.PosInfos) + { + addTrace(value, info); + } + + ////// PRINT APIS ////// + + override public function reportFinalStatistics(testCount:Int, passCount:Int, failCount:Int, errorCount:Int, ignoreCount:Int, time:Float):Dynamic + { + trace(result); + return super.reportFinalStatistics(testCount, passCount, failCount, errorCount, ignoreCount, time); + } + + override public function print(value:Dynamic) + { + super.print(value); + #if flash8 + value = untyped flash.Boot.__string_rec(value, ""); + textField.text += value; + textField.scroll = textField.maxscroll; + #elseif (flash || openfl) + #if mobile + result += value; + #else + textField.appendText(value); + textField.scrollV = textField.maxScrollV; + #end + #end + + #if nodejs + untyped process.stdout.write(value); + #elseif (neko || cpp || php) + Sys.print(value); + #elseif (js || flash) + external.print(value); + #end + } + + override public function printLine(value:Dynamic, ?indent:Int = 0) + { + super.printLine(value, indent); + } + +} diff --git a/test/src/TestMain.hx b/test/src/TestMain.hx new file mode 100644 index 0000000..a81b4b3 --- /dev/null +++ b/test/src/TestMain.hx @@ -0,0 +1,96 @@ +/**************************************** **************************************** + * Copyright 2010 Massive Interactive. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY MASSIVE INTERACTIVE ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MASSIVE INTERACTIVE OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of Massive Interactive. + */ + +import massive.munit.client.PrintClient; +import massive.munit.client.RichPrintClient; +import massive.munit.client.HTTPClient; +import massive.munit.client.JUnitReportClient; +import massive.munit.client.SummaryReportClient; +import massive.munit.TestRunner; +#if js +import js.Lib; +#end + +/** + * Auto generated Test Application. + * Refer to munit command line tool for more information (haxelib run munit) + */ + +class TestMain +{ + static function main(){ new TestMain();} + + public function new() + { + var suites = new Array>(); + suites.push(TestSuite); + + var client; + var httpClient; + #if openfl + client = new OpenflPrintClient(); + httpClient = new HTTPClient(new SummaryReportClient()); + #else + #if MCOVER + client = new mcover.coverage.munit.client.MCoverPrintClient(); + httpClient = new HTTPClient(new mcover.coverage.munit.client.MCoverSummaryReportClient()); + #else + client = new RichPrintClient(); + httpClient = new HTTPClient(new SummaryReportClient()); + #end + #end + + var runner:TestRunner = new TestRunner(client); + runner.addResultClient(httpClient); + //runner.addResultClient(new HTTPClient(new JUnitReportClient())); + runner.completionHandler = completionHandler; + runner.run(suites); + } + + /* + updates the background color and closes the current browser + for flash and html targets (useful for continous integration servers) + */ + private function completionHandler(successful:Bool):Void + { + try + { + #if flash + flash.external.ExternalInterface.call("testResult", successful); + #elseif js + js.Lib.eval("testResult(" + successful + ");"); + #elseif (neko || cpp || php) + Sys.exit(0); + #end + } + // if run from outside browser can get error which we can ignore + catch (e:Dynamic) + { + } + } +} diff --git a/test/src/TestSuite.hx b/test/src/TestSuite.hx new file mode 100644 index 0000000..66c7fe6 --- /dev/null +++ b/test/src/TestSuite.hx @@ -0,0 +1,25 @@ +import massive.munit.TestSuite; + +import CppCallTest; +import CppTest; +import JniCallTest; +import JniTest; + +/** + * Auto generated Test Suite for MassiveUnit. + * Refer to munit command line tool for more information (haxelib run munit) + */ + +class TestSuite extends massive.munit.TestSuite +{ + + public function new() + { + super(); + + add(CppCallTest); + add(CppTest); + add(JniCallTest); + add(JniTest); + } +} diff --git a/test/src/testpackage/TestJni1.hx b/test/src/testpackage/TestJni1.hx new file mode 100644 index 0000000..45f1e65 --- /dev/null +++ b/test/src/testpackage/TestJni1.hx @@ -0,0 +1,27 @@ +package testpackage; + +@:build(ShortCuts.mirrors()) +class TestJni1 +{ + @JNI public static function method1(toto:String, value1:Bool, + value2:Int):String{return null;} + + @JNI("primitivename") public static function method2(toto:Bool, + value:Int, float:Float):Bool{return false;} + + @JNI("primitivename") public static function method3(toto:String, + value:Int, float:Float):Void{} + + @JNI("package.toto.com", "primitivename") public static function method4(toto:TestClass, + value1:Bool, value2:Int):Int{return 0;} + + @JNI public static function methodArray1(array1:Array):Int{return 0;} + + @JNI public static function methodArray2(array1:Array, + array2:Array):Array{return null;} +} + +class TestClass +{ + +} diff --git a/test/src/testpackage/TestJni2.hx b/test/src/testpackage/TestJni2.hx new file mode 100644 index 0000000..d3ca276 --- /dev/null +++ b/test/src/testpackage/TestJni2.hx @@ -0,0 +1,12 @@ +package testpackage; + +@:build(ShortCuts.mirrors()) +@JNI_DEFAULT_PACKAGE("org.shoebox.testpackage") +class TestJni2 +{ + @JNI + public static function method1(toto:String):Void{} + + @JNI("org.shoebox.testpackagealt") + public static function methodAlt(toto:String):Void{} +} From e9857808964be34deba63ad587bfe580443e1c68 Mon Sep 17 00:00:00 2001 From: shoebox Date: Sat, 20 Dec 2014 00:07:44 +0000 Subject: [PATCH 02/16] Cleanup renmants --- src/ShortCuts.hx | 68 +--- src/mirror/CppFieldTool.hx | 1 - src/org/shoebox/macros/MacroErrReport.hx | 176 --------- src/org/shoebox/macros/MacroInjector.hx | 214 ----------- src/org/shoebox/macros/MacroMirrors.hx | 466 ----------------------- 5 files changed, 8 insertions(+), 917 deletions(-) delete mode 100644 src/org/shoebox/macros/MacroErrReport.hx delete mode 100644 src/org/shoebox/macros/MacroInjector.hx delete mode 100644 src/org/shoebox/macros/MacroMirrors.hx diff --git a/src/ShortCuts.hx b/src/ShortCuts.hx index 38ec714..02172ec 100644 --- a/src/ShortCuts.hx +++ b/src/ShortCuts.hx @@ -18,64 +18,12 @@ import haxe.macro.Context; import haxe.macro.Expr; #end -/** - * ... - * @author shoe[box] - */ - -class ShortCuts{ - - // -------o constructor - - /** - * constructor - * - * @param - * @return void - */ - public function new() { - - } - - // -------o public - #if macro - - /** - * - * - * @public - * @return void - */ - static public function inject( ) : Array { - return MacroInjector.inject( ); - } - - /** - * - * - * @public - * @return void - */ - static public function mirrors( ) : Array { - return mirror.Mirror.build();//MacroMirrors.build( ); - } - - /** - * - * - * @public - * @return void - */ - static public function errorReport( ) : Array { - return MacroErrReport.report( ); - } - - #end - - // -------o protected - - - - // -------o misc - +class ShortCuts +{ + function new(){} + + static public function mirrors( ):Array + { + return mirror.Mirror.build(); + } } diff --git a/src/mirror/CppFieldTool.hx b/src/mirror/CppFieldTool.hx index 301c600..5658757 100644 --- a/src/mirror/CppFieldTool.hx +++ b/src/mirror/CppFieldTool.hx @@ -3,7 +3,6 @@ package mirror; import haxe.macro.Context; import haxe.macro.Expr; import haxe.macro.Type.ClassType; -import org.shoebox.macros.MacroMirrors.MetaDataTools; using tools.ExprTool; using tools.FieldTool; diff --git a/src/org/shoebox/macros/MacroErrReport.hx b/src/org/shoebox/macros/MacroErrReport.hx deleted file mode 100644 index 8697653..0000000 --- a/src/org/shoebox/macros/MacroErrReport.hx +++ /dev/null @@ -1,176 +0,0 @@ -package org.shoebox.macros; - -import haxe.macro.Context; -import haxe.macro.Expr; - -/** - * ... - * @author shoe[box] - */ - -class MacroErrReport{ - - // -------o constructor - - /** - * constructor - * - * @param - * @return void - */ - private function new() { - - } - - // -------o public - #if macro - - /** - * - * - * @public - * @return void - */ - static public function report( ) : Array { - var a = Context.getBuildFields( ); - var sModule = Context.makeExpr( Context.getLocalClass( ).get( ).module , Context.currentPos( ) ); - var eName : Expr; - // - for( f in a ){ - - switch( f.kind ){ - - case FFun( func ): - - // - //sFunc = Context.makeExpr( f.name , Context.currentPos( ) ); - var eRet : Expr = null; - if( func.ret != null ){ - - switch( func.ret ){ - - case TPath( t ): - switch( t.name ){ - - case "Void": - - case "Float": - eRet = macro return -1; - - case "Int": - eRet = macro return -1; - - case "Bool": - eRet = macro return false; - - default: - eRet = macro return null; - - } - - default: - eRet = null; - } - } - - // - var expr : Expr = func.expr; - expr = macro { - //trace("call ::: "+$sModule); - try{ - $expr; - }catch( e : flash.errors.ArgumentError ){ - #if HypSystem - fr.hyperfiction.HypSystem.reportError( - $sModule , - e.toString( ), - haxe.CallStack.toString( haxe.CallStack.exceptionStack( ) )+"\n"+haxe.CallStack.toString( haxe.CallStack.callStack( ) ) - ); - #else - trace("ArgumentError"); - throw( e ); - #end - }catch( e : flash.errors.TypeError ){ - - #if HypSystem - fr.hyperfiction.HypSystem.reportError( - $sModule , - e.toString( ), - haxe.CallStack.toString( haxe.CallStack.exceptionStack( ) )+"\n"+haxe.CallStack.toString( haxe.CallStack.callStack( ) ) - ); - #else - trace("TypeError"); - throw( e ); - #end - - }catch( e : flash.errors.Error ){ - - #if HypSystem - fr.hyperfiction.HypSystem.reportError( - $sModule , - e.toString( ), - haxe.CallStack.toString( haxe.CallStack.exceptionStack( ) )+"\n"+haxe.CallStack.toString( haxe.CallStack.callStack( ) ) - ); - #else - trace("Error"); - throw( e ); - #end - - }catch( unknown : Dynamic ) { - - #if HypSystem - fr.hyperfiction.HypSystem.reportError( - $sModule , - "Unknown exception : "+Std.string(unknown) , - haxe.CallStack.toString( haxe.CallStack.exceptionStack( ) )+"\n"+haxe.CallStack.toString( haxe.CallStack.callStack( ) ) - ); - #end - - trace("Unknow error ::: "+$sModule); - trace( unknown ); - trace( haxe.CallStack.toString( haxe.CallStack.callStack( ) ) ); - #if HypSystem - fr.hyperfiction.HypSystem.reportError( - $sModule , - "Unknown exception : "+Std.string(unknown) , - haxe.CallStack.toString( haxe.CallStack.exceptionStack( ) )+"\n"+haxe.CallStack.toString( haxe.CallStack.callStack( ) ) - ); - #end - } - - }; - - if( eRet != null ){ - expr = macro { - $expr; - $eRet; - } - } - - func.expr = expr; - /* - var e = macro { - try{ - $(expr); - }catch( e : flash.errors.Error ){ - trace("errror ::: "+e); - } - }; - */ - default: - - } - } - - return a; - } - #end - - - // -------o protected - - - - // -------o misc - -} \ No newline at end of file diff --git a/src/org/shoebox/macros/MacroInjector.hx b/src/org/shoebox/macros/MacroInjector.hx deleted file mode 100644 index e22c783..0000000 --- a/src/org/shoebox/macros/MacroInjector.hx +++ /dev/null @@ -1,214 +0,0 @@ -/* -Copyright (c) 2013, shoe[box] -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -package org.shoebox.macros; - -#if macro -import haxe.macro.Context; -import haxe.macro.Expr; -import haxe.macro.Type; -import haxe.macro.TypeTools; -import haxe.macro.*; - -using haxe.macro.Tools; -#end - -/** - * ... - * @author shoe[box] - */ - -class MacroInjector{ - - // -------o constructor - - /** - * constructor - * - * @param - * @return void - */ - public function new() { - - } - - // -------o public - - #if macro - - /** - * - * - * @public - * @return void - */ - static public function inject( ) : Array { - var aFields : Array = Context.getBuildFields( ); - - var aCopy = aFields.copy( ); - - var bWrite : Bool; - var eName : Expr; - var sGet : String; - var sName : String; - var sSet : String; - var aMetas : Array; - for( field in aFields ){ - - //Reset - bWrite = false; - eName = null; - sName = null; - - //Meta - aMetas = [ for( m in field.meta ) if( m.name == "inject") m ]; - - //No meta data - if( aMetas.length == 0 ) - continue; - - //Parsing des metas - for( meta in aMetas ){ - switch( meta.name ){ - - case "inject": - for( p in meta.params ){ - - switch( p.expr.getParameters( )[ 0 ]){ - - case CString( s ): - sName = s; - - case CIdent( b ): - bWrite = b == "true"; - - default: - - } - - } - - } - } - - - // - #if verbose - Sys.println(" [INJECT] - "+(bWrite?"RW":"R-")+" | Optional name : "+sName); - #end - - //New Methods name - sGet = "get_"+field.name; - sSet = bWrite ? "set_"+field.name : "never"; - - //Reponse - var ct : ComplexType = field.kind.getParameters( )[ 0 ]; - var oKind : Null = ComplexTypeTools.toType( ct ).getParameters( )[0]; - var sKind : String = Std.string( oKind )+""; - - //Getter - aCopy.push( _createField( true , sName, field.access, field.pos , sGet , ct.toString( )+"" , ct , false ) ); - - //Setter - if( bWrite ) - aCopy.push( _createField( false , sName , field.access , field.pos , sSet , ct.toString( )+"" , ct , false ) ); - - //the new getter/setter - var type : FieldType = FProp( sGet , sSet , ct ); - var getterSetter : Field = - { - name : field.name , - doc : null, - meta : [], - access : field.access, - kind : type, - pos : field.pos - }; - - //On supprime la source - aCopy.remove( field ); - aCopy.push( getterSetter ); - - } - - return aCopy; - } - - // -------o protected - - /** - * - * - * @private - * @return void - */ - static private function _createField( - bGetter : Bool, - sOptional_name : String, - aAccess : Array , - pos : Position , - sName : String , - sKind : String, - ct : ComplexType , - bGet : Bool = true , - bStatic : Bool = false - ) : Field{ - - var e = Context.makeExpr( sKind , pos ); - var func : Function = { args : [ ] , expr : null , params : [] , ret : ct }; - - if( bGetter ){ - //trace( "getter :: "+$i{ sKind }+" - "+sOptional_name ); - func.expr = macro { - #if inthebox - return org.shoebox.patterns.injector.Injector.getInstance( ).get( - cast( $i{ sKind } , Class ), - $v{ sOptional_name } - ); - #else - return null; - #end - }; - - }else{ - func.args.push( { name : "arg", type : ct , opt : false, value : null } ); - func.expr = macro { - //trace( $i{ "arg" } ); - #if inthebox - return org.shoebox.patterns.injector.Injector.getInstance( ).set( - $i{ "arg" }, - cast( $i{ sKind } , Class ), - $v{ sOptional_name } - ); - #else - return null; - #end - }; - } - var fRes : Field = { - name : sName , - doc : null, - meta : [], - access : aAccess, - kind : FFun( func ), - pos : pos - }; - if( bStatic ) - fRes.access.push( AStatic ); - - return fRes; - } - - #end - - // -------o misc - -} \ No newline at end of file diff --git a/src/org/shoebox/macros/MacroMirrors.hx b/src/org/shoebox/macros/MacroMirrors.hx deleted file mode 100644 index 45fb898..0000000 --- a/src/org/shoebox/macros/MacroMirrors.hx +++ /dev/null @@ -1,466 +0,0 @@ -/* -Copyright (c) 2013, shoe[box] -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -package org.shoebox.macros; - -#if macro -import haxe.macro.ComplexTypeTools; -import haxe.macro.Context; -import haxe.macro.Expr; -import haxe.macro.Type; -import haxe.macro.TypeTools; -import haxe.macro.*; - -using haxe.macro.Tools; -#end - -/** - * ... - * @author shoe[box] - */ -class MacroMirrors -{ - #if macro - - public static inline var CPP_META:String = "CPP"; - public static inline var IOS_META:String = "IOS"; - public static inline var JNI_META:String = "JNI"; - - public static inline var TAG_CPP_DEFAULT_LIB:String = "CPP_DEFAULT_LIBRARY"; - public static inline var TAG_CPP_PRIM_PREFIX:String = "CPP_PRIMITIVE_PREFIX"; - - static var VOID = TPath({name:"Void", pack:[], params:[] }); - static var DYNAMIC = TPath({name:"Dynamic", pack:[], params:[], sub:null}); - - public static function build():Array - { - var fields:Array = Context.getBuildFields( ); - - if (!Context.defined("openfl")) - return fields; - - var localClass:ClassType = Context.getLocalClass( ).get(); - var config = parseConfig(localClass); - - var result:Field; - for (field in fields.copy()) - { - result = parseField(field, localClass, config); - if (result != null) - { - fields.push(result); - result = null; - } - } - - return fields; - } - - static function parseConfig(localClass:ClassType):ContextConfig - { - var config:ContextConfig = {}; - var metas:Metadata = localClass.meta.get(); - if (MetaDataTools.has(metas, TAG_CPP_DEFAULT_LIB)) - config.cppDefaultLibrary = getString(MetaDataTools.get(metas, - TAG_CPP_DEFAULT_LIB).params[0]); - - if (MetaDataTools.has(metas, TAG_CPP_PRIM_PREFIX)) - config.cppPrimitivePrefix = getString(MetaDataTools.get(metas, - TAG_CPP_PRIM_PREFIX).params[0]); - - return config; - } - - static function getLibraryName(field:Field, meta:MetadataEntry, metaLength:Int, - config:ContextConfig):String - { - var result:String; - - if (metaLength == 0 && config.cppDefaultLibrary == null) - Context.error('The primitive name is not defined for field' + - '${field.name} and no CPP_DEFAULT_LIBRARY setup', field.pos); - - if (config.cppDefaultLibrary != null && metaLength == 0) - result = config.cppDefaultLibrary; - else - result = getString(meta.params[0]); - - return result; - } - - static function getPrimitiveName(field:Field, meta:MetadataEntry, metaLength:Int, - config:ContextConfig):String - { - if (metaLength == 2) - return getString(meta.params[1]); - - return (config.cppPrimitivePrefix != null ? - config.cppPrimitivePrefix + "_" : "") + field.name; - } - - static function parseField(field:Field, localClass:ClassType, - config:ContextConfig):Field - { - var result:Field; - var meta:MetadataEntry; - var metaLength:Int; - var libraryName:String; - var primiveName:String; - - if (MetaDataTools.has(field.meta, CPP_META) && Context.defined("cpp")) - { - meta = MetaDataTools.get(field.meta, CPP_META); - metaLength = meta.params.length; - - libraryName = getLibraryName(field, meta, metaLength, config); - primiveName = getPrimitiveName(field, meta, metaLength, config); - - result = cpp(field, libraryName, primiveName, "CPP"); - } - else if (MetaDataTools.has(field.meta, JNI_META) && Context.defined("android")) - { - meta = MetaDataTools.get(field.meta, JNI_META); - metaLength = meta.params.length; - - result = jni(field, - (metaLength > 0) ? getString(meta.params[0]) : localClass.module, - (metaLength > 1) ? getString(meta.params[1]) : field.name - ); - } - else if (MetaDataTools.has(field.meta, IOS_META) && Context.defined("ios")) - { - meta = MetaDataTools.get(field.meta, IOS_META); - metaLength = meta.params.length; - - libraryName = getLibraryName(field, meta, metaLength, config); - primiveName = getPrimitiveName(field, meta, metaLength, config); - result = cpp(field, libraryName, primiveName, "IOS"); - } - - return result; - } - - static function jni(field:Field, packageName:String, - ?variableName:String ):Field - { - packageName = packageName.split(".").join("/"); - - var result:Function = FieldTool.getFunction(field); - if (result.ret == null) - result.ret = VOID; - - var argumentNames:Array = getArgsNames(result); - var signature = JniTools.getSignature(field); - - if (!isStaticField(field)) - result.args[0].type = DYNAMIC; - - #if verbose_mirrors - Sys.println('[JNI] $packageName \t $variableName $signature'); - #end - - var mirrorName:String = getMirrorName(variableName, "jni"); - var resultVariable = createVariable(mirrorName, result, field.pos); - var returnType:String = result.ret.getParameters( )[0].name; - var returnExpr = null; - var isStaticMethod = isStaticField(field); - - if (returnType != "Void") - { - //Switching the return type to dynamic - result.ret = DYNAMIC; - - returnExpr = macro - { - #if verbose_mirrors - var args:Array = $a{argumentNames}; - trace( "call with args ::: " + args); - #end - return $i{mirrorName}($a{argumentNames}); - }; - } - else - returnExpr = macro $i{mirrorName}($a{argumentNames}); - - result.expr = macro - { - if ($i{mirrorName} == null) - { - #if verbose_mirrors - trace("Lib not loaded, loading it"); - trace($v{packageName} + " :: " + $v{variableName} - + ' :: signature '+$v{signature}); - #end - - if ($v{isStaticMethod}) - $i{mirrorName} = openfl.utils.JNI.createStaticMethod( - $v{packageName}, $v{variableName}, $v{signature}); - else - $i{mirrorName} = openfl.utils.JNI.createMemberMethod( - $v{packageName}, $v{variableName}, $v{signature}); - } - - $returnExpr; - } - - return resultVariable; - } - - static function getMirrorName(name:String, target:String = "cpp"):String - { - return 'mirror_' + target + '_' + name; - } - - static function cpp(field:Field, packageName:String, ?name:String, - ?type:String ) : Field - { - var func:Function = FieldTool.getFunction(field); - - var argsCount:Int = func.args.length; - var argumentNames:Array = getArgsNames(func); - - var mirrorName:String = getMirrorName(name, "cpp"); - var fieldVariable = createVariable(mirrorName, func, field.pos); - var returnExpr = macro ""; - - - #if verbose_mirrors - Sys.println('[$type] $packageName \t $name ($argsCount)'); - #end - - if (func.ret.getParameters( )[ 0 ].name == "Void") - returnExpr = macro $i{mirrorName}($a{argumentNames}); - else - returnExpr = macro return $i{mirrorName}($a{argumentNames}); - - func.expr = macro - { - if ($i{mirrorName} == null) - { - #if verbose_mirrors - trace("Lib not loaded, loading it"); - trace($v{packageName}+"::"+$v{name}+'($argsCount)'); - #end - - $i{mirrorName} = cpp.Lib.load($v{packageName}, $v{name}, - $v{argsCount}); - } - $returnExpr; - } - - return fieldVariable; - } - - static function createVariable(variableName:String, refFunction:Function, - positon:Position):Field - { - var types = [for (arg in refFunction.args) arg.type]; - var fieldType : FieldType = FVar(TFunction(types, refFunction.ret)); - - return - { - name : variableName, - doc : null, - meta : [], - access : [APublic,AStatic], - kind : fieldType, - pos : positon - }; - } - - static function getString(e:Expr):String - { - if (e == null) - return null; - - return switch ( e.expr.getParameters( )[ 0 ] ) - { - case CString(s): - s; - - default: - null; - } - } - - static inline function getArgsNames(func:Function):Array - { - var result:Array = [for (a in func.args) macro $i{ a.name }]; - return result; - } - - static inline function isStaticField(field:Field):Bool - { - var result = Lambda.has(field.access, AStatic); - return result; - } -} - -class JniTools -{ - public static function getSignature(field:Field):String - { - var func:Function = FieldTool.getFunction(field); - var signature = "("; - for(arg in func.args) - signature += translateArg(arg, field.pos); - - var returnType:Null = func.ret.toType(); - - signature += ")" + translateType(returnType, field.pos); - - return signature; - } - - public static function translateArg(arg:FunctionArg, pos:Position):String - { - var argType:Null = arg.type.toType(); - return translateType(argType, pos); - } - - public static function translateType(argType:Null, pos:Position):String - { - return switch (argType) - { - case TAbstract(cf, a ): - translateAbstractType(cf.get(), pos); - - case TDynamic(t): - if (Context.defined("openfl")) - "Lorg/haxe/lime/HaxeObject;"; - else - "Lorg/haxe/nme/HaxeObject;"; - - default: - translateArgType(argType, pos); - } - } - - public static function translateArgType(type:Null, pos:Position):String - { - return switch (type) - { - case TInst(t, params): - translateSubArgType(type, params, pos); - - default: - #if (haxe_ver >= 3.1) - Context.fatalError( - "Unsupported Type ::: " + type.getParameters()[0], pos); - #end - } - } - - public static function translateSubArgType(type:Null, params:Array, - pos:Position):String - { - var result:String; - switch (type.getParameters()[0].get().name) - { - case "String": - result = "Ljava/lang/String;"; - - case "Array": - result = "[" + translateType(params[0], pos); - - default: - var classType:ClassType = type.getParameters()[0].get(); - result = "L"+classType.pack.join("/") - + (classType.pack.length == 0 ? "" : "/" ) - + classType.name+";"; - } - - return result; - } - - public static function translateAbstractType(a:AbstractType, pos:Position):String - { - var result:String = null; - result = switch (a.name) - { - case "Float": - "F"; - - case "Bool": - "Z"; - - case "Int": - "I"; - - case "Void": - "V"; - - default: - #if (haxe_ver >= 3.1) - Context.fatalError("Unsupported abstract type ::: "+a.name, pos); - #end - } - - return result; - } -} - -class FieldTool -{ - public static function getFunction(field:Field):Function - { - var result:Function; - switch (field.kind) - { - case FFun(f): - result = f; - - default: - Context.error("Only function are supported", field.pos); - } - return result; - } -} - -class MetaDataTools -{ - - public static function has(metas:Metadata, metaName:String):Bool - { - var result = false; - for(meta in metas) - { - if (meta.name == metaName) - { - result = true; - break; - } - } - return result; - } - - public static function get(metas:Metadata, metaName:String):MetadataEntry - { - var result:MetadataEntry = null; - for(meta in metas) - { - if (meta.name == metaName) - { - result = meta; - break; - } - } - return result; - } - - #end -} - -typedef ContextConfig= -{ - @:optional var cppPrimitivePrefix:String; - @:optional var cppDefaultLibrary:String; -} From 423c577335060d50204cd7a624e9653df7614b21 Mon Sep 17 00:00:00 2001 From: shoebox Date: Sat, 20 Dec 2014 00:14:53 +0000 Subject: [PATCH 03/16] Updating license --- LICENSE | 22 ++++++++++++++++------ src/ShortCuts.hx | 13 ------------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/LICENSE b/LICENSE index f194bea..7f425c6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,9 +1,19 @@ -Copyright (c) 2013, shoe[box] -All rights reserved. +Copyright (c) 2014 shoe[box] -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/ShortCuts.hx b/src/ShortCuts.hx index 02172ec..af39d0d 100644 --- a/src/ShortCuts.hx +++ b/src/ShortCuts.hx @@ -1,16 +1,3 @@ -/* -Copyright (c) 2013, shoe[box] -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ -package ; - import org.shoebox.macros.*; #if macro From bff76d59ed492473750a147bc9cff66179b970df Mon Sep 17 00:00:00 2001 From: shoebox Date: Sat, 20 Dec 2014 00:41:17 +0000 Subject: [PATCH 04/16] Merging fixes --- src/mirror/JniFieldTool.hx | 31 +++++++++++++++++++++++++------ src/tools/FunctionTool.hx | 2 +- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/mirror/JniFieldTool.hx b/src/mirror/JniFieldTool.hx index 33d8daa..ea1348c 100644 --- a/src/mirror/JniFieldTool.hx +++ b/src/mirror/JniFieldTool.hx @@ -97,18 +97,37 @@ using tools.MetadataTools; public static function translateAbstractType(type:AbstractType, pos:Position):String { - var result:String = switch (type.name) + function error() { - case "Bool" : "Z"; - case "Float" : "F"; - case "Int" : "I"; - case "Void" : "V"; + Context.fatalError("Unsupported abstract type ::: " + type.name, pos); + return "ERROR"; + } + + var result:String; + switch (type.name) + { + case "Bool" : result = "Z"; + case "Float" : result = "F"; + case "Int" : result = "I"; + case "Void" : result = "V"; default: + #if (haxe_ver >= 3.1) + var complexType = type.type; + switch (complexType) + { + case TAbstract(t, _): + var concreteT = t.get(); + result = translateAbstractType(concreteT, pos); + + default: + error(); + } + #end } #if (haxe_ver >= 3.1) if (result == null) - Context.fatalError("Unsupported abstract type ::: " + type.name, pos); + error(); #end return result; diff --git a/src/tools/FunctionTool.hx b/src/tools/FunctionTool.hx index 33c0bab..8323a21 100644 --- a/src/tools/FunctionTool.hx +++ b/src/tools/FunctionTool.hx @@ -7,7 +7,7 @@ class FunctionTool static inline function getArgsNames(func:Function):Array { var result:Array = [for (a in func.args) macro $i{a.name}]; - return result; + return result.copy(); } static inline function isStaticField(field:Field):Bool From 537d841d7abca6b09c1f0a7bce0b0dda18a93553 Mon Sep 17 00:00:00 2001 From: shoebox Date: Sun, 21 Dec 2014 02:15:29 +0000 Subject: [PATCH 05/16] Jni non static calls --- src/mirror/Jni.hx | 29 +++++++- src/mirror/JniFieldTool.hx | 30 ++++++-- src/tools/VariableTool.hx | 18 ++--- test/JniTest.hx | 69 ------------------ .../org/test/extension/NonStaticMirror.java | 20 +++++ .../ndll/Mac/testextension-debug.ndll | Bin 68676 -> 68676 bytes test/extension/ndll/Mac/testextension.dll | Bin 42608 -> 0 bytes .../ndll/Mac64/testextension-debug.ndll | Bin 0 -> 68072 bytes .../libtestextension-debug.iphoneos-v7.a | Bin 5304 -> 0 bytes .../libtestextension-debug.iphoneos-v7.ndll | Bin 5304 -> 0 bytes .../iPhone/libtestextension-debug.iphoneos.a | Bin 5304 -> 0 bytes .../libtestextension-debug.iphoneos.ndll | Bin 5304 -> 0 bytes .../iPhone/libtestextension-debug.iphonesim.a | Bin 5448 -> 0 bytes .../libtestextension-debug.iphonesim.ndll | Bin 5448 -> 0 bytes .../iPhone/libtestextension.iphoneos-v7.a | Bin 1912 -> 0 bytes .../iPhone/libtestextension.iphoneos-v7.ndll | Bin 1912 -> 0 bytes .../ndll/iPhone/libtestextension.iphoneos.a | Bin 1848 -> 0 bytes .../iPhone/libtestextension.iphoneos.ndll | Bin 1848 -> 0 bytes .../ndll/iPhone/libtestextension.iphonesim.a | Bin 2272 -> 0 bytes .../iPhone/libtestextension.iphonesim.ndll | Bin 2272 -> 0 bytes test/extension/project/Build.xml | 5 +- test/extension/project/build.sh | 24 +++++- test/src/JniNonStaticTest.hx | 55 ++++++++++++++ test/src/TestSuite.hx | 2 + test/src/testpackage/NonStaticMirror.hx | 13 ++++ 25 files changed, 171 insertions(+), 94 deletions(-) delete mode 100644 test/JniTest.hx create mode 100644 test/extension/dependencies/android/src/org/test/extension/NonStaticMirror.java delete mode 100755 test/extension/ndll/Mac/testextension.dll create mode 100755 test/extension/ndll/Mac64/testextension-debug.ndll delete mode 100644 test/extension/ndll/iPhone/libtestextension-debug.iphoneos-v7.a delete mode 100644 test/extension/ndll/iPhone/libtestextension-debug.iphoneos-v7.ndll delete mode 100644 test/extension/ndll/iPhone/libtestextension-debug.iphoneos.a delete mode 100644 test/extension/ndll/iPhone/libtestextension-debug.iphoneos.ndll delete mode 100644 test/extension/ndll/iPhone/libtestextension-debug.iphonesim.a delete mode 100644 test/extension/ndll/iPhone/libtestextension-debug.iphonesim.ndll delete mode 100644 test/extension/ndll/iPhone/libtestextension.iphoneos-v7.a delete mode 100644 test/extension/ndll/iPhone/libtestextension.iphoneos-v7.ndll delete mode 100644 test/extension/ndll/iPhone/libtestextension.iphoneos.a delete mode 100644 test/extension/ndll/iPhone/libtestextension.iphoneos.ndll delete mode 100644 test/extension/ndll/iPhone/libtestextension.iphonesim.a delete mode 100644 test/extension/ndll/iPhone/libtestextension.iphonesim.ndll create mode 100644 test/src/JniNonStaticTest.hx create mode 100644 test/src/testpackage/NonStaticMirror.hx diff --git a/src/mirror/Jni.hx b/src/mirror/Jni.hx index 6bddcfa..4ca1bf9 100644 --- a/src/mirror/Jni.hx +++ b/src/mirror/Jni.hx @@ -14,6 +14,8 @@ using tools.VariableTool; class Jni { + static var DYNAMIC = TPath({name:"Dynamic", pack:[], params:[], sub:null}); + public function new(){} public static function build(field:Field, localClass:ClassType):Field @@ -36,10 +38,6 @@ class Jni field.meta.push(entryPackage); #end - #if (verbose_mirrors) - Sys.println('$jniPackage // $jniPrimitive // $jniSignature'); - #end - var func = field.getFunction(); var fieldName = getMirrorName(field.name); var args = func.getArgsNames(); @@ -47,6 +45,29 @@ class Jni var returnExpr = func.createReturnExpr(fieldName, args); var result = func.create(fieldName, field.pos); var isStaticMethod = field.isStaticField(); + + #if (verbose_mirrors) + Sys.println('[Mirror] Static : ' + isStaticMethod + + ' --------------------------------------------------------'); + Sys.println('\tPackage = $jniPackage'); + Sys.println('\tPrimitive = $jniPrimitive'); + Sys.println('\tSignature = $jniSignature\n'); + #end + + if (!isStaticMethod) + func.args[0].type = DYNAMIC; + + var returnTypeName = field.getFunction().ret.toString(); + switch (returnTypeName) + { + case "Void", "Int", "Bool", "String", "Float": + + case "Array", "Array", "Array": + + default: + field.getFunction().ret = DYNAMIC; + } + if (Context.defined("android")) { func.expr = macro diff --git a/src/mirror/JniFieldTool.hx b/src/mirror/JniFieldTool.hx index ea1348c..1e519b8 100644 --- a/src/mirror/JniFieldTool.hx +++ b/src/mirror/JniFieldTool.hx @@ -4,6 +4,8 @@ import haxe.macro.Context; import haxe.macro.Expr; import haxe.macro.Type; +using haxe.macro.ComplexTypeTools; +using haxe.macro.TypeTools; using haxe.macro.Tools; using tools.ExprTool; using tools.FieldTool; @@ -60,14 +62,16 @@ using tools.MetadataTools; { var reference = FieldTool.getFunction(field); var result = '('; - for (arg in reference.args) - { + var args = reference.args.copy(); + if (!field.isStaticField()) + args.shift(); + + for (arg in args) result += translateArg(arg, field.pos); - } var returnType:Null = reference.ret.toType(); result += ")" + translateType(returnType, field.pos); - + return result; } @@ -161,9 +165,21 @@ using tools.MetadataTools; default: var classType:ClassType = type.getParameters()[0].get(); - result = "L"+classType.pack.join("/") - + (classType.pack.length == 0 ? "" : "/" ) - + classType.name+";"; + var metas = Context.getLocalClass().get().meta.get(); + if (Context.getLocalClass().get().module == classType.module + && metas.has(TagDefaultLibrary)) + { + var entry:MetadataEntry = metas.get(TagDefaultLibrary); + var raw = entry.params[0].getString(); + var parts = raw.split('.'); + result = "L" + parts.join('/') + '/' + Context.getLocalClass().get().name + ';'; + } + else + { + result = "L" + classType.pack.join("/") + + (classType.pack.length == 0 ? "" : "/" ) + + classType.name+";"; + } } return result; diff --git a/src/tools/VariableTool.hx b/src/tools/VariableTool.hx index e84e186..9f76352 100644 --- a/src/tools/VariableTool.hx +++ b/src/tools/VariableTool.hx @@ -5,20 +5,20 @@ import haxe.macro.Expr; class VariableTool { - public static function create(refFunction:Function, name:String, + public static function create(reference:Function, name:String, position:Position):Field { - var types = [for (arg in refFunction.args) arg.type]; - var fieldType : FieldType = FVar(TFunction(types, refFunction.ret)); + var types = [for (arg in reference.args) arg.type]; + var fieldType : FieldType = FVar(TFunction(types, reference.ret)); return { - name : name, - doc : null, - meta : [], - access : [APublic,AStatic], - kind : fieldType, - pos : position + name : name, + doc : null, + meta : [], + access : [APublic,AStatic], + kind : fieldType, + pos : position }; } } diff --git a/test/JniTest.hx b/test/JniTest.hx deleted file mode 100644 index b8c88fb..0000000 --- a/test/JniTest.hx +++ /dev/null @@ -1,69 +0,0 @@ -package; - -import massive.munit.util.Timer; -import massive.munit.Assert; -import massive.munit.async.AsyncFactory; - -import haxe.rtti.Meta; - -import testpackage.TestJni1; -import testpackage.TestJni2; - -class JniTest -{ - public function new() - { - TestJni1; - } - - @BeforeClass public function beforeClass():Void{} - @AfterClass public function afterClass():Void{} - @After public function tearDown():Void{} - @Before public function setup():Void{} - - @Test public function testAbstractSignature() - { - var metas = Meta.getStatics(TestJni1); - Assert.areEqual(metas.method1.jni_signature[0], - "(Ljava/lang/String;ZI)Ljava/lang/String;"); - - Assert.areEqual(metas.method2.jni_signature[0], "(ZIF)Z"); - Assert.areEqual(metas.method3.jni_signature[0], - "(Ljava/lang/String;IF)V"); - } - - @Test public function testSignatureNonAbstract() - { - var metas = Meta.getStatics(TestJni1); - Assert.areEqual(metas.method4.jni_signature[0], - "(Ltestpackage/TestClass;ZI)I"); - } - - @Test public function testAbstractArray() - { - var metas = Meta.getStatics(TestJni1); - Assert.areEqual(metas.methodArray1.jni_signature[0], - "([Ljava/lang/String;)I"); - Assert.areEqual(metas.methodArray2.jni_signature[0], - "([Ljava/lang/String;[I)[Ljava/lang/String;"); - } - - @Test public function testPackage() - { - var metas = Meta.getStatics(TestJni1); - Assert.areEqual(metas.method3.jni_package[0], "testpackage"); - } - - @Test public function testPackageMeta() - { - var metas = Meta.getStatics(TestJni1); - Assert.areEqual(metas.method4.jni_package[0], "package/toto/com"); - } - - @Test public function testDefaultPackage() - { - var metas = Meta.getStatics(TestJni2); - Assert.areEqual(metas.methodAlt.jni_package[0], - "org/shoebox/testpackagealt"); - } -} diff --git a/test/extension/dependencies/android/src/org/test/extension/NonStaticMirror.java b/test/extension/dependencies/android/src/org/test/extension/NonStaticMirror.java new file mode 100644 index 0000000..e862e03 --- /dev/null +++ b/test/extension/dependencies/android/src/org/test/extension/NonStaticMirror.java @@ -0,0 +1,20 @@ +package org.test.extension; + +import android.util.Log; + +public class NonStaticMirror +{ + static NonStaticMirror instance = null; + + public static NonStaticMirror getJniInstance() + { + if (instance == null) instance = new NonStaticMirror(); + return instance; + } + + public boolean method1(boolean value1, String value2) + { + Log.d("debug", "method1 = " + value2); + return true; + } +} diff --git a/test/extension/ndll/Mac/testextension-debug.ndll b/test/extension/ndll/Mac/testextension-debug.ndll index 0f09faa692c811a920822fe2821c5d72094fa74a..c43d96f7d2a3f4db1693a56696cf4b2454d1c434 100755 GIT binary patch delta 18 acmX>ygXPE!mJK_WFqeu?+q`>8XF32>dIygXPE!mJK_WFvskevU&HC&U64+4GDSx diff --git a/test/extension/ndll/Mac/testextension.dll b/test/extension/ndll/Mac/testextension.dll deleted file mode 100755 index c9808b7dfa8a288b06a0c0bd7b1f524815b29a12..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42608 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 q<<Y3+B!?hrGX< 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 diff --git a/test/extension/ndll/iPhone/libtestextension-debug.iphoneos-v7.ndll b/test/extension/ndll/iPhone/libtestextension-debug.iphoneos-v7.ndll deleted file mode 100644 index 685ff3d0cd6fd4f471ba1d81dd956377c8d81bc5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5304 zcmb7IeQZ!1;+q#O6GP6X*jLR7^!Tt3|>~t)%T$&!F>)SW%+&;~-R{?Uo6ZCdR zZC*@Hu>@ToDH)|yd?=feo|=7BV3hz~fe#00=UgE^3)<*|al~^*TF=r+vyb;_4;WK-YJfvAtt@Dw~k|uj>P&{o4jDwV00s@Bpx+@^KqE<=lX}8_S0gixtd$ zjH}VdT3G%G175a*m&0W<(?`L`j+w<7K00wILKu?gp(I5RJSTt|J~BpJE~hz;J~iNk z@=+V!+DAH-HK}RkF-t41|9~2McW!!o;#Q~kU$-W|6uWi8_vITQUv=tc zRhy_>5WnHSN4%GQlz(JtAICj2@y^XQpLSFntJz(yI_h?3H~#JE`Dg#RPWksw-VvfY z^?FqtRlcMozmfXBJ39pR<$*09jO}^zgX*6B1J$XYR{QQ;+XK0_f4~#v{59K6b=zXy z_9fU(&akacU9488-m6wFe0<5*^{}u%5_G*=d=YuBZH$XYANgIU68d#T9cR($1!~${ zx05y2`6f8G%kk&BVu9QFJQOZgF>S7u+Coj!qTq3F z!>o;QX!q5o(aMljq`du6$fMNFyF`Ju3T;%XJa5#+j)N}GWgCYh@-A#j5IJJrzoYBR zP~HAC+LP@0YTlp`^r($`{!kY?4&oSIAggI_Ln#+EiU_nXbac6$9i45T>6iz#qgOaP zhPu|xdC2#$&w)GDxdei>J|E7lD}XNLSHC%@+c!_UN9%)u+mf!E(;#oNs~R`RWlUAI~NRA-3601_@w3p1l;sC`WDNvIJNhp3gF)2 zzf3*v0YXK#wdOSthd6{*(?0CDoB2T+cx7sVpt`PuUn!b}VsLjZX=Jm3j8Q11vPL{< z1_#XIlciifm^8{}Iu+{N}`z=Rkq4$#K1@EsP|F(C`;efWE_ql&~ zc*kb{K7@*Qu|E3H+|I(OIGgLf<&NWqtp!t`F%3y-M4W+GCWS*XMF+oC_f?12>KIZ{h*P2T(_J zWsTQFn>_P8_muI(u(q(qP}T;@y2V<9uS?dV!Grgu*4}t#?$v)h<^7rQjb9yj>iS!5 z{LlzSwjDV9`&WLM|Lb$x`bUpAzqjuDrNtY6cWeUVCV>}$SAe&HoV*k02Zn%sz^%Y2 zP~M9$;X8xC`xRpGFc|=C$p27sLhv>te^c@D&O(17g@AXJ-r{+eQe};oHz9ayyu5?K zKMN$h52XEOG5~p%gGR{!SQx1PJQ;wMZ^{VFJAu5F?@wdHJt58q5?J%;$BA8X$sMWf zRj6{rw|?}w&OYczfGkg(lhtGi5WrGE5wHDwDIhRD?zJYg1AOvW@mA1(z{aC1tAwRL z)1+qwSqilDQS>>9#p6zs_o~ISsBpeC5Va!n7%0wJhIu4a=PeTjkM)~hQ*>B}^DMKI z?cyBI)FvTLlLw5G9{^%(W-aU(Q=ux(y$1Ra?8xJ!kCR7U&a>KM{JB@bhoG-je=$zp z4?SzaHO%v4@c1oznmk~f{30Od!87eVg$c~_15m8#GHx)m*GJHi{#?-sMPF3(1w{`jih3>WGobXBQuGN$F~5`#f#PSR3+t8C z56XGC9**l&@}DUAcad)Zuu$7kr;^({n6!<> zp9g=tZQB1)@KA?uvlO6-@aCk%o^c4G=2dxlqu@5=&D6X>)IeoTcGRogZ z|8d}AY!c5kUNExHv!}BU`zR>yNA}C0IO~j60;$zsVe1P$S!NlX{#zCb;V0EqRxT7x v6jvjSAJlpxoikWzTl}f5v82u74{7kyx;oFYK(-#wKl=T@!mKwGPvqx+Luu!q diff --git a/test/extension/ndll/iPhone/libtestextension-debug.iphoneos.a b/test/extension/ndll/iPhone/libtestextension-debug.iphoneos.a deleted file mode 100644 index c1aa94c4cb6d1cd107c9af61262ce187d183f889..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5304 zcmb7IYiv}<6`s2fyxBFz#1N30lx^cyP?>$%EYJ{G6Z3Gf8;VJsM$qxy^_pF>FYT_0 ziA-uLr0@fprlnFVrDAbgDQY7WwUt^`iiFZiQ7e=>ZKb4Y6hXjEXaTiCs`@~2zi;kb z`|f&a$dS*S`OZ0W=FH>H%=%MX%yKHT)&F2L9E$`ODB2U<9O;h5;~Rs)jj?VRHpDi@ zBf)4S67T5=2BUElibniWhK9a8*tcV6aOlx}`*-vSP>==a1Mmth<63?}%M7HHvYb97 zOXc)fc0yLum1@-15u_)o=|Ux2EXazPFXhsM>1w7pDwN}bEpKKEjXFflqJ0^mv-yg^ z_`2gdV~Y9l#hQBNXntAS#(YF6OW9QAXg*oYRjT93p1X~Ksa3>rNtvot%h|#qt!ow|1Y6@+ zI5##)Ihsz6AClR^m|A}+`-Xe>?X=BeALiq8;GgLExMKAERs*4y7xLVtf&sA_C9z_gIYwFag{rp!wn0dF0KM8ct&#&*}#6 z>KIn@<}q^FLYkIlFjxmZnbOMX=$Q4s6cw>wm{GdQT^jp$VE{cH#R_10gu3%m6 zCWfBUMPpgZZyI!xAA3DH@<YTJg%~9?I;F=li5RQl2bxdIj!{e= zRtwWOr!QiUccQ`VrK+8?SQJC$Q8H7FF)rvB!8T`eRbLdNdbHGZELRa@3{CoUj4jLc zSy(p~>$@E*V?yBDn8yGXWeWP25rZ8cKn#Q>&F8TW0MjJSz!uR4&e^YlIgR`8#T;Tz zarTM5U=ojhGS`diqdzIs?w+O+>#r>>)h>Hx2Hz9n^sEryoBj9P+~1Z2&faMEyKcU= z=NC6cpz~&X;7iwULEkb{yF4}Z>IV<|-}-*(;k607y$|iZXyajw_S3WUf8XJMe%Iw^ zR-C`J&Gu)1t>WzLyYOMZc3dm-v$LO^3twj4_7B2Wi03ce-+p%1Xn+3F4BGj0U5Mke z%*lg!E}>1|+}zxq+P&7K-3%7vakLw7w7Ueq8(_x0^MgUksBk_pq>PErVwJ3A^`OSp z*+v2SiY0{WJSsh4!&v5Z^M-c+4#?|q{bAm)((9gq!SffoEpr()$hTP^_S~je=`sl0 z(SejB;DTJd6iaH!g#^n$ovC0{sYW%in^+Wh79tnKA5pV?lk)XBr2lk+f8Zqer2sHhLGen`}-8h%H}CkLW2XLoz!=p#3t z9*W4iBSu(ip^O5}V)6RG&L1>(kcM=eE<)}acyxR3fRz2xWK`ulWW8k>d3&*#vkscw zL%qAXJ$WD5jH-Gc82E+49Z#Z;`-S(C7fc{LJ{3zM!C*9xN_O0rgU9Z3J3ff!%&www1{|;v7 zJW_(-2si=W3myThQxPtFqmX#ILMs@MBtz<%%Y+$tM41tG|!#;-6@U()?<@%iFDad;Y`k P|J|yx?&ib%_(A^zenQ_e diff --git a/test/extension/ndll/iPhone/libtestextension-debug.iphoneos.ndll b/test/extension/ndll/iPhone/libtestextension-debug.iphoneos.ndll deleted file mode 100644 index ff9acdfb45f1fabf695058031c783c8a98cab489..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5304 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 diff --git a/test/extension/ndll/iPhone/libtestextension-debug.iphonesim.ndll b/test/extension/ndll/iPhone/libtestextension-debug.iphonesim.ndll deleted file mode 100644 index 5752b193250860486f020adaf2c30c14ebc4cdf8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5448 zcmb7I4QyLi6~50ujqAAiY1*w4o$Ap58R~53&uv+MlB`J^NLbV)w1t-27srX+I<~Q$ zE|hMhv}1|dqLx2ZFr;NfXo9X(0tA{ss?@TTfyM?%4ADxkty7AIR0?R-hzQ?z-*xir zxLY~$dFP&U?m73|bI-f?KHtB|%tT^ayld-&4I%#m)Hl^{3^g`{Lk)ia`i4d*nj6-K zL;m_uDBRTK_t%HoN^!%FZn|1g7-i@Jw^^u0gCfSZ?GD$PhnFJj&Bhf$#Q&8~oyMO<0 z8Cp)Dq3KOG8h(qPV7mmQmkQxqB18<7_C)53ATiCcoYl7YzV_XH3p`uT18MI9%~cBF zq0lA9NeEI7Mh8ZRWjr~gVwG~+uGXC$mJ(0euSLKwzz5;S@KI$o9Tr*eVGayrqKC*A z`nU%BOXz%q!56|}9~m<_9L+BB@icmdV0%tYK!_#;!CV3s`4}-HYC6SnyrO$v)jllq z(moRLWR#jxK3;-6@1qNGXt#^vNTedld9jag>A=5-H7$ZgKC-#Y9euokyxxruozg{f zc}&;bWO-2(^Hbvddvj(k9_dWRRi#N;SYzYx@eP=tgb&u(UgQJ6q8dxY@j{r14OGx) zp^sIlE!x!j=GRp9qrW^z8A*+dq>>B#w${GZJZHTh`DL9?BGgFHJirIi8BY#tNpT!? zh$8@96XLLg-Jg^rsX@Fg@thnQO-7j0f;e`=2jd=u587SD#2ABpsiid2*sEmH96_Zo zuCcxFk%m!B$MGh7tU^D)d?<8o|osPjx$F*f3k67V(B&X$wA~8 z@V<^_`3Tizhw*%dt#aiI3eg5M`aLhrOW{oTenHk?Nvs4K{TSZ(P(_W~Sy8p*0~OWK zI+}#DqO)eJ?_=c;l{-)~&RPhzl$UeI44_GQLwU8a+-QN;ofmEOEeMz7h4ix^E(;h> zwp3UiI%^i>9=CSeS;GOB-Xl6|tX?SEN-&sb4Z3W?2IC6|_-L|u73(lly~<(^z*R)? zi2PoUrb;>~;RT>W9L3Wx{!_6GPha~O4?5}$?r>tSLkJi5N`E*I^4CQYxRpE@4ut}tKy&y3f8BtYjSl*uR(%@-&DlfA2Sk3h!P23= zZw|7tRCFLUhFRxgY&?jYOeU2L@}?WaRnNNW2Gg0;foLR$J_qYbbkM2}-e~yfe z$>Bt5z)Z+PW=0)n=vYEpFACkOn{=V5=prpY-BsUUAFd~iF%qNE-jEb_xv<1SDFw_L z!iA3QH~PGjqHye8gxucsNLy={l%3L~SJk)II`HYaEtN{3EJeY7d1~T2keoU_`tIBu zx8S~77dOM#P$%4!k6yzDuD8UJ`|YWTFDUyb3hmG4?WgW!@0l6Jt2J{0k7JiT`!2!D zX73-ro8Da4a(???53e}?&#iY(hm`dNxstyDz@w?Jrfn@sCHnKQbSG{>Y;@UUjb&A{gFz+Dxe=20=58qfct@Je@BxjONw;i#B&!!s}X}=XoknmA6-$I{3W3I!wS@C#eu`q0Ro? zK!Q4vK&9e@;PFQN2Q{D1H)RCooIsw(0(1TU^x>KiR{#mTKhTd8tK?EEVy#tZe4@N< z*Qu%&=zD=YWH}~}MRlZGry4~(!R`S9{#6K&OTTGzd-;~ta;9x^3})##&fOG zRM&#*HuMm=eyHgWH05^?^O<&L1i`Cwh9dz9Fce-eC$o;UlggB{O$z|;xwYtf(` zYGhhTwY&m6zm)*09~+GC9OOSQBPXW#4TCkCK4;_MWcn!^|1|iMHvTE_M{N9A@Ch6L zb?|#_{AuuAHXeDH-elt^z^}9M$HA|*@#ElqHhvTMVGqL>Q~Yj0jZgR4_$%P?Dk^;+ z^2GUGP^_5R0G{!TYkoEO9Qb^``2n~a{6*vyF!d(kJsDGAi6b9i{Am#LXgKfw;W*I2ujCUp5SVVpUaZT62A?t%K*yftAXB&cX&`;<# z=N1PVs;3ZqkMivaTN_u0_q&Od{2Q7<#!e=2e)kuq_yiH&j8g+KAsg#vdO j-g!#hWgx!GOGasX{_*%;mm67d0cqc1eU65(j)4CGP@M=H diff --git a/test/extension/ndll/iPhone/libtestextension.iphoneos-v7.a b/test/extension/ndll/iPhone/libtestextension.iphoneos-v7.a deleted file mode 100644 index 4c917169881696d361580cf28e2f7cc82696caaa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1912 zcmb7FO=uKZ5PnH?jWZ%S2#N@{xQB?6?fJ3e27e|pNsNpnnk+;;)O0$XOfS>jlbMc8 z6k(1cd)U>xIO@fV5Ktka7{tRK7WJ^8g5VDxJR}jakXb~w_p6?6GZPZj8tQ%Z^IpBG zS8rbL*stcb%)!vk$WKvOTB1li^0OR^D(x_~M`Lj8jkYVY6p>{m9+#wug2AJ7h^TGg zEM}#+V$!DsDwcLiN2G-{h+As?O^~DrFV}_tUW$$YB1;>#N#fGD@qQw;I zLN<9z&GuTrQB~91Y?R>9lTUO1ZGf~M+yGt!e%6RVs_H{5uRw2Ln}zQMaGlT1Kqf+& zMW-rP^}(*8!6ls~R(X9B@G%D77ek4GiD+ee7;W$^ucfwqgepwawt~cnlAVK{fmZEhuxIT$z83)znf3@7=n9Qa zSQ^fwKE~ge$i1BL`*Ir!ujl&}&@KpE(|!0Dd9N+tzo3VJ$+gx0ANt_+7~tI#ZWG7m z`?joQuza0LckFJr^7&(8wk7;}?uXs~&d-F?^Vh=1XXWsN52b`#nSUtoI}mz)J$Ilr z@p`Vw^SPCGp8ZzO+q0W){c}i2ZsjFgq+CzwPGVu7u)Aj#gy>tmJpOdi9WN#)lWyhD zkBNm;6YNcig?J;dv2U^L`OhWKV#bzq3$nS3Sse}VHcTd))1?QiKORI8QTyBwMN#rE zV1AcyzUDq4&c>8{Aa@8cbp?1>h?}f~%B&v*qwl7Sd0=tX6;rwieSQUQz&zG@ zAJ#Ev`UVj7Ol5$$A2(SCm04$kZA~k%8MiCp;~&6{4Ok7j=gXWw=diJ{*?V)&L*9-< z;`&efGW$2PjI~FAyM4JI7y<|PzqdwaTVNM-22YHEH-^+~*4Ah=YpYP|d-)BIJ!Ojg zRatuf@%QpRGxd?`KPfAIh)$)V%Ib^y70!4^;O$BE9qvpK^^(eG G0s0?QYLDOm diff --git a/test/extension/ndll/iPhone/libtestextension.iphoneos-v7.ndll b/test/extension/ndll/iPhone/libtestextension.iphoneos-v7.ndll deleted file mode 100644 index 632c35bf7db7fe289c113c6745ac2c211fe5246b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1912 zcmb7FO=uHa6uxbJzM6=1Av}=>j_9JI)R{EKD*mLBw)PQewH2x^PR7a9jAUkFGL=*j zvJ`RQ&t8nWaU&E|s3;b3;X-_GA*dkug9{gJg$j*`IDTg`W0TVI^n`Q2^KD3{lVjUqXE!BGMmD|*q1{Sj@aWmssqf1nEdw`zmw^9k#2{7mA(j`Qx3EpZ_Y(N0&&@z4LYYOU zDp&QvuA#v>oh4RzeG~982HqD#iGhh|z)>AT>$MCo5>b5&Uf&OnV=brn0k|4iAA|GI zY&A<32bmw^2G0jw;3R4&ENb)6Y^&f9N8u^I5#wh>qMV@>M$Mykw&08$js9wk;5=Kr zeYJv_iR)P-WS!8gB_+V&BuFiqPE5+h1<4t54wwU@!3wd?p^1Vm)oX)@3i8XmDU zoJW0(=a|U7obdZ{8w#)I`xVdz2wc;B_!xPwRp6)4L%_rz)&C#*;Pn{b-4kvT$L9Ms zuVt|OKb7v--EQUEr}$(`_|4SPjbElG!l~(N;r)|x_`%0g+^tMM6!`57y||v+*&2T{ z)#Uly%6rd#tLNRRmA5|c7Lr?e#TF^oQ@RtM=@54J#EcMqvzJf&JL{e(CPou(<;kb` zOtJ~~rua;>5!l!_TlV~?6Q?j^RjLKq+{LWz4e&OMCYn>F2a7)*M2e_=Zipf%`5>6z zC7iF>0mRvul8<~=Z0{Cg{59n5LX2Gj?h)c9>!330yTItXDPta3Ty@3RdEh3@W8HN{ zne|rq9|5C?a}Ky3e%3){)+PA)JxIcT7Wg;(tb@v|bB}o+^n9F+m$1)q;Bw4ko%dlK zbH;A~QO{Tgi2HGqbx@ggCfJs=0-JHW;yzvku4uq&&^=$~{5gjejm_Sha|ZGn91_=m z#FyFs7t2_?7r4=v`+*^FaQ}O2WVQu%K_~IV7R?=w>$ss59);D_jNG7?*SQGbjx9?=p0a8ilX-m1VgAQQYj$-X_ENupj-`7A&` E0Lh<_L;wH) diff --git a/test/extension/ndll/iPhone/libtestextension.iphoneos.a b/test/extension/ndll/iPhone/libtestextension.iphoneos.a deleted file mode 100644 index e17b391ce40d688dbf71fae8b30a21f1386445ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1848 zcmb7F&1(}u6raZWm8j$(*n{Yb9u&21(sWy)YAdN)iTKeX^`pG5o2^|)c0;n2C*tT9gh-VRm{srPq1rcirtsgCd3L;|sz0GW!go^s$&F{T8GrxJWZ)SE|m!3C9 z4~DnL_Qh3YNn(lEezh&GX`PDF5pP3Bd%Qzam6)n(iG-rWG&H^phlyJI&z(s29#Q&F zo*C#(3W&lDWDdGfq9*aU#8Ds-<;}~K%bO!skzBLj#)23-X3;h6g5}s$(6hOWdBSu@ zowV==F7;(~%WjN;)x!KdsI6>4V1I3z%$Q+uf7sfx`)hBP!-vDVn(jzlMAYVCICjA$X5k_K!Li6ll(US&)$AoFQ*g&FCH|Eo_?}UJU8CUU zE&H-$U5=v_eT{pmEgxYQ*{ov+i4i4x26_UoTFYR~+If5~0wKyeX|hli8X2<it6<#3?8Xmxz_Q`Mfoh43WP} zseAAH^||rspOwnTXjm*X@Al@WB99kB5oIA7IsK{B{dDeIrSjoG_{II)ft}rzKK^rQJP`&aB)tgln zuN+dm**&sPh@0gQIA3AR=Ec~Ja;fxmj<3q?N~OYQ_AGQ9Hpl+_un@&W?NdY)$9TRY zDJZ`EP$v-IZD@x?t~1BeLQH;#4Vk!yW*EN89{gKqF2aA~yJDgQ1n1;e=@)^>YqIK! z3BDkx*W^?+Fad7S1;tuJEfTp4^={tj`%R)-;sam{PRd>226^C~NSpI{$u=fpeQ_PS z6`T1EydZ7PX%pL+dknZ++I)WaOi4=7S7UQ5hzq)cXTrieL3$?R7&MY`bU5|j{2v}{ z8ZGjlVd)LW74d%+^-T4@g=K#x=TmX*&y!ARobi|m`tzw+ytev5SHDW=J(@asxF_WV8{R^MV*mgE diff --git a/test/extension/ndll/iPhone/libtestextension.iphoneos.ndll b/test/extension/ndll/iPhone/libtestextension.iphoneos.ndll deleted file mode 100644 index f676d92907709731b44f7fc0fa10a626c409e273..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1848 zcmb7F&1(}u6raZWm8j$(*n{Yb9u&3irb)C=wUtz@MEq!x`cYoj?Zz%7yCK<16oiNu z4<7U`Y+ElL#Ip!O{{r!*f{0Z@>qm>Af`}M@Z!_B_p`t!`^Ly{j%x~W8o0;9xr5B9R z1L3XOo|vjEiWb*8)s9%Avr|#_#yZfEi0w_Pil(Z`cwAAmBpP3a!$j@)K;!2u)mI^%$Q+ef7r&7`%5I`@ZqqQQMI^{*hjs{reN#Y zJ{y?P4YS?B7JPa7WA4`)SSz3{&{pWP5E`ZC53;?4{6y>%`o02JN?j$#5w=-!r2`-u z=p7tb^w}DO^897MH)wcWG-U=BqJCF*Eu+u2e5Pg&p3ikiVXmJd2-fk$1`f`{aP%zM zOw!CT#p59lIEgxmi26JX$1b|WEIi~tI2IU*@|ID&lDp_+i|*LP_`h-l-!tm3YZTpr zWnYr4OL4TLuX!)^X5N(WD$Ff}H`5jMDlJiO<}KEVt6pW9>dmN% zR|zTJ%r4m{#EnV_oG&qE<3j9urCfe8%U9)AwOZvfdj>iVn`3`|Sco)H{}d6$FrM#7 z8j5c}v=4~yHndG5*O}uZLQH;#4Vk!$W*EN89{ihVF2H~7yJDgY1n1;e>6d`WYqI8w z3BDkx*W^?!Fad7S1;tuJZ4$W)^={qn`z@kd;(cHnPRbqNI(gt8OPlj~!8RsheQ^!C z8JqbIJTGm|X#?Asdla}++I)WaOi4=7S7&o9hzq)mXTrieL3%dp7?jC6I-JID{tpi} zjh6V&u=s}Kiuk{ZMyAH!!jeCebLm*}&y!9jIpZ-C^ykuAtiJj|SHDW=J(50gs3%R- IM>_WV8`1iN3;+NC diff --git a/test/extension/ndll/iPhone/libtestextension.iphonesim.a b/test/extension/ndll/iPhone/libtestextension.iphonesim.a deleted file mode 100644 index 61ac27d88d98b4c9bbf84e2ada2bcfea226efd5b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2272 zcma)7Uuaup6#uf_Zn1971`!p6-eJHoFyf1dA*+S>I#OHZhCqLbl&qME*Iz1qK!4}X%HNS6jE@vG zeMC!A7S+@%x;;?=HT8lKt)c}Ne*E{(XGg&u1_mVEIs``T$aBo^1K+^;5o~usIi4{n z{RnL?I^7_mTy`$km6`h($ngs33Wg)BRK#s23`DktVs-nhC->%9ftu$lqHwO=1J36G z(X698R$-!Ixz+U7u@1*+pp66^_brAY4(_R=P%W3M6;?A4WyW*k9iB(--|O4|tDxQk zqC&%|Ta}wq(_hEW&_{va`x}Am&qq|Q7Rf>}Omn3}=P_v~Th2toL}uMYHghkcL|F-D2Zx?XlOu-v;Y5#->t;bORs z7=rl!yeLG8)eNkE1-Jwo&lkhumk)c_-Xr z#~YtygR4rUbp-S5hR$s5hORf4px+Ihg!T_`%lE@K=C@7LjE08Yb_L>>cY+Tx5hZ-@ z@r4IU(Z`7pb@RRp5FAuYg_Z%;{4#lFKg#dkM-2E)-1N$?NuaS zYrca}F0RP5$xFG`+}yM3(t63Y@*;IgJ@}p>(uDtJB8nqc@P2>N3+^4qw!p0`BCr$; zoH#b1tY8XWpVxptJZra;>@YqQymRQ{aV66{%r-ujzrZ%^w}EFHZ>Zm3dwCyQ4Z43| z<8$ZF$p;K;K5$LaGm@%8Y`XhNhz;HcVX4mw@x|Au6R`0ah6_NBPs9HyYo-28$YZY9 z@p}Vtd}aY|+$k^|_bUAO90FWD_T^?r?8wYxk0}oH{2u`upCZp3pPj=RUswxq6N#Og@zdZ&zF*`#h$- z{yb0AC<)SSyILUAuIi4U(jo_T-%CLs={9ajnCShD`i1%7HU<9DI|o0`MP!v(Whf diff --git a/test/extension/ndll/iPhone/libtestextension.iphonesim.ndll b/test/extension/ndll/iPhone/libtestextension.iphonesim.ndll deleted file mode 100644 index c896ed0f93e1214d503bbe42bf926fa2d9ce9189..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2272 zcma)7PiP!v6#urJv}+iRR#;6b~LmJp@wdP4MJJP(fu65hZ#M!LGkI^G$YkO`wl?-~0c* z_vZU|c3f{1%dZc1e)=1!LJUs!gj_ zrKVn~+s2IHlxrp7I(BUp-KzHMkkvwb1F5Y_Q=q?8Mpn$k?{9SEi2lY#CsY&a;T6 zMDvdBSjDNTdVy#lCRawnIl%32^dOVNZzu$N8S3!LM zM8&4lu&TGEroWCKppOH;3N`{cn2)GZE0Kjx$Xu!x|5wKuOvpX#AqU5u8}QceDeyiJ zy|YxQlcV3V4b~A&&CFrv`}QbuL?HapR|opL$394j7^6&PL$A0QSngey7;^C1a4}p* z0zv$Lo))6aY6jLn4_twb=SyJm%ZP)Im;*BSdy3~g1?(${T@IiQr^D>m)_=Lax)*J; zB_ri~|F(vxo z&x?F*PK_lAteZ3io*LD_n#f8D|KB-?gH_=niMyu56bk>o4 zqxA+txwsP37BA&SYx}^eOY3FV%8TTcdh|U*q>13oM3h9V;QjtrFSvIc+d_A)iqJ|p zbmr86vW6*meO?59{kYRfv%}<2_};Ngr$Cm%4Z`M`Ba&r7NbvF+|BA+~rQM5R6_#K)hZPQccO7%l=iegyvivR3L}fjr@g zp5M!e<1-6z$wKBHP6PR#`IISi4BrBop8)-xc}&Lha4$n)A^2RK1TsGknv(niXkPN0px59( ztO&vXCM9|97oQl$Pyn@N-lriLbVgm;Fj{+Yb<~o<)8d=v m69ns(>Dfz@)3_>07r8gRt1t1y>D`i1%8@g84uMHn0r(Hl2hnE$ diff --git a/test/extension/project/Build.xml b/test/extension/project/Build.xml index 0401c56..7896247 100644 --- a/test/extension/project/Build.xml +++ b/test/extension/project/Build.xml @@ -18,9 +18,10 @@ - - + + + diff --git a/test/extension/project/build.sh b/test/extension/project/build.sh index 0fbf432..e58f069 100644 --- a/test/extension/project/build.sh +++ b/test/extension/project/build.sh @@ -58,7 +58,7 @@ mac() rm -rf NDLL"lib"LIB".iphonesim.a" $HXCPP $VERBOSE $DEBUG $VERSION sleep $DELAY - $HXCPP -DM64 $VERBOSE $VERSION + $HXCPP $VERBOSE $VERSION sleep $DELAY } @@ -67,9 +67,22 @@ mac64() echo "\n\n\033[1;32mCompiling for OSX 64bit" rm -rf NDLL"lib"LIB"-debug.iphonesim.a" rm -rf NDLL"lib"LIB".iphonesim.a" - $HXCPP $VERBOSE $DEBUG $VERSION + $HXCPP $M64 $VERBOSE $DEBUG $VERSION + sleep $DELAY + $HXCPP $M64 $VERBOSE $VERSION + sleep $DELAY +} + +android() +{ + echo "\n\n\033[1;32mCompiling for Android" + rm -rf NDLL"lib"LIB"-debug.iphonesim.a" + rm -rf NDLL"lib"LIB".iphonesim.a" + $HXCPP -Dandroid $VERBOSE $DEBUG $VERSION + $HXCPP -Dandroid -DHXCPP_ARMV7 $VERBOSE $DEBUG $VERSION sleep $DELAY - $HXCPP -DM64 $VERBOSE $VERSION + $HXCPP -Dandroid $VERBOSE $VERSION + $HXCPP -Dandroid -DHXCPP_ARMV7 $VERBOSE $VERSION sleep $DELAY } @@ -94,6 +107,10 @@ case "$1" in cleanup mac64 ;; + "android") + cleanup + android + ;; *) cleanup ios_armv6 @@ -101,6 +118,7 @@ case "$1" in ios_simulator mac mac64 + android ;; esac diff --git a/test/src/JniNonStaticTest.hx b/test/src/JniNonStaticTest.hx new file mode 100644 index 0000000..0d09c96 --- /dev/null +++ b/test/src/JniNonStaticTest.hx @@ -0,0 +1,55 @@ +import haxe.rtti.Meta; +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; +import testpackage.NonStaticMirror; + +class JniNonStaticTest +{ + var meta1:Dynamic; + + public function new() + { + NonStaticMirror; + } + + @BeforeClass public function beforeClass() + { + meta1 = Meta.getFields(NonStaticMirror); + } + @AfterClass public function afterClass(){} + @Before public function setup(){} + @After public function tearDown(){} + + #if android + @Test public function testJavaInstance() + { + var instance = NonStaticMirror.getJniInstance(); + Assert.isNotNull(instance); + } + #end + + @Test public function testPackage() + { + Assert.areEqual(meta1.method1.jni_package[0], + "org/test/extension/NonStaticMirror"); + } + + @Test public function testSignature() + { + Assert.areEqual(meta1.method1.jni_signature[0], + '(ZLjava/lang/String;)Z'); + } + + #if android + @Test public function testCall() + { + var instance = NonStaticMirror.getJniInstance(); + Assert.isNotNull(instance); + + var classInstance = new NonStaticMirror(); + var result = classInstance.method1(instance, false, "osef"); + Assert.isTrue(result); + } + #end +} diff --git a/test/src/TestSuite.hx b/test/src/TestSuite.hx index 66c7fe6..118100f 100644 --- a/test/src/TestSuite.hx +++ b/test/src/TestSuite.hx @@ -3,6 +3,7 @@ import massive.munit.TestSuite; import CppCallTest; import CppTest; import JniCallTest; +import JniNonStaticTest; import JniTest; /** @@ -20,6 +21,7 @@ class TestSuite extends massive.munit.TestSuite add(CppCallTest); add(CppTest); add(JniCallTest); + add(JniNonStaticTest); add(JniTest); } } diff --git a/test/src/testpackage/NonStaticMirror.hx b/test/src/testpackage/NonStaticMirror.hx new file mode 100644 index 0000000..142f4c1 --- /dev/null +++ b/test/src/testpackage/NonStaticMirror.hx @@ -0,0 +1,13 @@ +package testpackage; + +@:build(ShortCuts.mirrors()) +@JNI_DEFAULT_PACKAGE("org.test.extension") +class NonStaticMirror +{ + public function new(){} + + @JNI public static function getJniInstance():NonStaticMirror{return null;}; + + @JNI public function method1(instance:NonStaticMirror, value1:Bool, + value2:String):Bool{return false;} +} From 5325831d5644152d9413dbdfb056c8324afd5028 Mon Sep 17 00:00:00 2001 From: shoebox Date: Sun, 21 Dec 2014 02:19:46 +0000 Subject: [PATCH 06/16] Reactivating unit tests --- build.hxml | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 build.hxml diff --git a/build.hxml b/build.hxml new file mode 100644 index 0000000..f0524e9 --- /dev/null +++ b/build.hxml @@ -0,0 +1,45 @@ +## Flash 9+ +-main TestMain +-lib munit +-lib hamcrest +-cp src +-cp test/extension/src +-cp test/src +-swf-version 11 +-swf bin/as3_test.swf + +--next + +## JavaScript +-main TestMain +-lib munit +-lib hamcrest +-cp src +-cp test/extension/src +-cp test/src +-js bin/js_test.js + +--next + +## Neko +-main TestMain +-lib munit +-lib hamcrest +-cp src +-cp test/extension/src +-cp test/src +-neko bin/neko_test.n + +--next + +## CPP +-main TestMain +-lib munit +-lib hamcrest +-cp src +-cp test/extension/src +-cp test/src +#-D HXCPP_M64 +-cpp bin/cpp_test + +-cmd haxelib run openfl test cpp -debug From 51fd97d3d7fbfb70efe462ae4e186f26c28cd656 Mon Sep 17 00:00:00 2001 From: shoebox Date: Mon, 22 Dec 2014 10:22:12 +0000 Subject: [PATCH 07/16] Adjustements to the extension --- .../ndll/Mac/testextension-debug.ndll | Bin 68676 -> 68676 bytes .../ndll/Mac64/testextension-debug.ndll | Bin 68072 -> 68072 bytes test/extension/project/build.sh | 13 +++++++------ test/extension/project/common/Extension.cpp | 6 ------ 4 files changed, 7 insertions(+), 12 deletions(-) delete mode 100644 test/extension/project/common/Extension.cpp diff --git a/test/extension/ndll/Mac/testextension-debug.ndll b/test/extension/ndll/Mac/testextension-debug.ndll index c43d96f7d2a3f4db1693a56696cf4b2454d1c434..5986efcc3a330324dc20a604acf41285dbc256a7 100755 GIT binary patch delta 18 acmX>ygXPE!mJK_WFt2+zee>=mo#_BvDGCJu delta 18 acmX>ygXPE!mJK_WFqeu?+q`>8XF32>dIhVtYrXT#0mZY delta 18 acmaDcndQY~mJJUkGp`h%w)yd7)-nKEr3oJZ diff --git a/test/extension/project/build.sh b/test/extension/project/build.sh index e58f069..0434022 100644 --- a/test/extension/project/build.sh +++ b/test/extension/project/build.sh @@ -9,6 +9,7 @@ ARC="-DOBJC_ARC" M64="-DHXCPP_M64" LIB="downloadmanager" DELAY="0.5" +COLOR="\n\n\\033[1;32m" cleanup() { @@ -18,7 +19,7 @@ cleanup() ios_armv6() { - echo "\n\n\\033[1;32mCompiling for armv6" + echo "$COLOR Compiling for armv6" sleep $DELAY rm -rf NDLL"lib"LIB"-debug.iphoneos.a" rm -rf NDLL"lib"LIB".iphoneos.a" @@ -30,7 +31,7 @@ ios_armv6() ios_armv7() { - echo "\n\n\\033[1;32mCompiling for armv7" + echo "$COLOR Compiling for armv7" rm -rf NDLL"lib"LIB"-debug.iphoneos-v7.a" rm -rf NDLL"lib"LIB".iphoneos-v7.a" @@ -42,7 +43,7 @@ ios_armv7() ios_simulator() { - echo "\n\n\033[1;32mCompiling for simulator" + echo "$COLOR Compiling for iOS simulator" rm -rf NDLL"lib"LIB"-debug.iphonesim.a" rm -rf NDLL"lib"LIB".iphonesim.a" $HXCPP -Diphonesim $VERBOSE $DEBUG $ARC $VERSION $GCC @@ -53,7 +54,7 @@ ios_simulator() mac() { - echo "\n\n\033[1;32mCompiling for OSX" + echo "$COLOR Compiling for OSX" rm -rf NDLL"lib"LIB"-debug.iphonesim.a" rm -rf NDLL"lib"LIB".iphonesim.a" $HXCPP $VERBOSE $DEBUG $VERSION @@ -64,7 +65,7 @@ mac() mac64() { - echo "\n\n\033[1;32mCompiling for OSX 64bit" + echo "$COLOR Compiling for OSX 64bit" rm -rf NDLL"lib"LIB"-debug.iphonesim.a" rm -rf NDLL"lib"LIB".iphonesim.a" $HXCPP $M64 $VERBOSE $DEBUG $VERSION @@ -75,7 +76,7 @@ mac64() android() { - echo "\n\n\033[1;32mCompiling for Android" + echo "$COLOR Compiling for Android" rm -rf NDLL"lib"LIB"-debug.iphonesim.a" rm -rf NDLL"lib"LIB".iphonesim.a" $HXCPP -Dandroid $VERBOSE $DEBUG $VERSION diff --git a/test/extension/project/common/Extension.cpp b/test/extension/project/common/Extension.cpp deleted file mode 100644 index bf4edee..0000000 --- a/test/extension/project/common/Extension.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "Utils.h" - -namespace TestExtension -{ - -} From a833ffeebbb6c65641402fa79dcbd9b4e7bb2217 Mon Sep 17 00:00:00 2001 From: shoebox Date: Mon, 22 Dec 2014 10:39:38 +0000 Subject: [PATCH 08/16] Adjustements in the JNI side --- src/mirror/JniFieldTool.hx | 14 +++++++- test/src/JniTest.hx | 66 ++++++++++++++++++++++++++------------ 2 files changed, 58 insertions(+), 22 deletions(-) diff --git a/src/mirror/JniFieldTool.hx b/src/mirror/JniFieldTool.hx index 1e519b8..1fa813f 100644 --- a/src/mirror/JniFieldTool.hx +++ b/src/mirror/JniFieldTool.hx @@ -55,7 +55,19 @@ using tools.MetadataTools; var entry:MetadataEntry = field.meta.get(TagJni); var params = entry.params; var length = params.length; - return (length > 0) ? entry.params[0].getString() : field.name; + + var result = switch (length) + { + case 0 : field.name; + case 1 : entry.params[0].getString(); + case 2 : entry.params[1].getString(); + case _ : + #if (haxe_ver >= 3.1) + Context.fatalError("Invalid number of arguments for the JNI tag", field.pos); + #end + } + + return result; } public static function getSignature(field:Field):String diff --git a/test/src/JniTest.hx b/test/src/JniTest.hx index 86343a0..c2ef7d0 100644 --- a/test/src/JniTest.hx +++ b/test/src/JniTest.hx @@ -11,59 +11,83 @@ import testpackage.TestJni2; class JniTest { + var meta1:Dynamic; + var meta2:Dynamic; + public function new() { TestJni1; + TestJni2; + } + + @BeforeClass public function beforeClass():Void + { + meta1 = Meta.getStatics(TestJni1); + meta2 = Meta.getStatics(TestJni2); } - @BeforeClass public function beforeClass():Void{} @AfterClass public function afterClass():Void{} @After public function tearDown():Void{} @Before public function setup():Void{} - @Test public function testAbstractSignature() + @Test public function testAbstractSignature1() { - var metas = Meta.getStatics(TestJni1); - Assert.areEqual(metas.method1.jni_signature[0], + Assert.areEqual(meta1.method1.jni_signature[0], "(Ljava/lang/String;ZI)Ljava/lang/String;"); + } + + @Test public function testPrimitive1() + { + Assert.areEqual(meta1.method1.jni_primitive[0], "method1"); + } + + @Test public function testAbstractSignature2() + { + Assert.areEqual(meta1.method2.jni_signature[0], "(ZIF)Z"); + } + + @Test public function testPrimitive2() + { + Assert.areEqual(meta1.method2.jni_primitive[0], "primitivename"); + } - Assert.areEqual(metas.method2.jni_signature[0], "(ZIF)Z"); - Assert.areEqual(metas.method3.jni_signature[0], + @Test public function testAbstractSignature3() + { + Assert.areEqual(meta1.method3.jni_signature[0], "(Ljava/lang/String;IF)V"); } - @Test public function testSignatureNonAbstract() + @Test public function testPrimitive3() + { + Assert.areEqual(meta1.method2.jni_primitive[0], "primitivename"); + } + + @Test public function testAbstractSignature4() { - var metas = Meta.getStatics(TestJni1); - Assert.areEqual(metas.method4.jni_signature[0], + Assert.areEqual(meta1.method4.jni_signature[0], "(Ltestpackage/TestClass;ZI)I"); } - @Test public function testAbstractArray() + @Test public function testPrimitive4() { - var metas = Meta.getStatics(TestJni1); - Assert.areEqual(metas.methodArray1.jni_signature[0], - "([Ljava/lang/String;)I"); - Assert.areEqual(metas.methodArray2.jni_signature[0], - "([Ljava/lang/String;[I)[Ljava/lang/String;"); + Assert.areEqual(meta1.method4.jni_primitive[0], "primitivename"); } @Test public function testPackage() { - var metas = Meta.getStatics(TestJni1); - Assert.areEqual(metas.method3.jni_package[0], "testpackage/TestJni1"); + Assert.areEqual(meta1.method1.jni_package[0], "testpackage/TestJni1"); + Assert.areEqual(meta1.method2.jni_package[0], "testpackage/TestJni1"); + Assert.areEqual(meta1.method3.jni_package[0], "testpackage/TestJni1"); } @Test public function testPackageMeta() { - var metas = Meta.getStatics(TestJni1); - Assert.areEqual(metas.method4.jni_package[0], "package/toto/com/TestJni1"); + Assert.areEqual(meta1.method4.jni_package[0], "package/toto/com/TestJni1"); } @Test public function testDefaultPackage() { - var metas = Meta.getStatics(TestJni2); - Assert.areEqual(metas.methodAlt.jni_package[0], + Assert.areEqual(meta2.methodAlt.jni_package[0], "org/shoebox/testpackagealt/TestJni2"); } } From 2db3dc9e6013ff0eea8ef840e987bc8de29d5065 Mon Sep 17 00:00:00 2001 From: shoebox Date: Mon, 22 Dec 2014 11:36:37 +0000 Subject: [PATCH 09/16] Default mirror body --- src/mirror/Mirror.hx | 58 ++++++++++++++++++++++++++++++++----- test/src/DefaultBodyTest.hx | 53 +++++++++++++++++++++++++++++++++ test/src/TestSuite.hx | 2 ++ 3 files changed, 105 insertions(+), 8 deletions(-) create mode 100644 test/src/DefaultBodyTest.hx diff --git a/src/mirror/Mirror.hx b/src/mirror/Mirror.hx index 10b21f6..474e79c 100644 --- a/src/mirror/Mirror.hx +++ b/src/mirror/Mirror.hx @@ -4,6 +4,8 @@ import haxe.macro.Context; import haxe.macro.Expr; import haxe.macro.Type.ClassType; +using haxe.macro.ComplexTypeTools; +using haxe.macro.Tools; using mirror.CppFieldTool; using mirror.JniFieldTool; using tools.ExprTool; @@ -12,10 +14,16 @@ using tools.MetadataTools; class Mirror { + static inline var MirrorDisabledMeta = "DISABLED"; static inline var CppMeta = "CPP"; static inline var TagCppDefaultLib = "CPP_DEFAULT_LIBRARY"; static inline var TagCppPrimitivePrefix = "CPP_PRIMITIVE_PREFIX"; + static var VOID:ComplexType = TPath({name:"Void", pack:[], params:[], sub:null}); + static var FLOAT:ComplexType = TPath({name:"Float", pack:[], params:[], sub:null}); + static var INT:ComplexType = TPath({name:"Int", pack:[], params:[], sub:null}); + static var BOOL:ComplexType = TPath({name:"Bool", pack:[], params:[], sub:null}); + function new(){} public static function build():Array @@ -25,24 +33,58 @@ class Mirror var isCpp = #if munit true #else Context.defined("cpp") #end; var isAndroid = #if munit true #else Context.defined("android") #end; var isOpenFl = Context.defined("openfl") || Context.defined("nme"); - if (#if munit true #else isOpenFl #end) + + + var isEnabled = + #if openfl + true; + #elseif munit + true; + #end + + var fieldDisabled:Bool; + var func:Function; + if (isEnabled) { var localClass = Context.getLocalClass().get(); var result:Field; for (field in fields.copy()) - { - if (isCpp && field.isCpp()) - { - result = Cpp.build(field, localClass); - } - else if (isAndroid && field.isJni()) + { + func = field.getFunction(); + if (func.ret == null) + func.ret = VOID; + + fieldDisabled = field.meta.has(MirrorDisabledMeta); + + if (!fieldDisabled) { - result = Jni.build(field, localClass); + if (isCpp && field.isCpp()) + { + result = Cpp.build(field, localClass); + } + else if (isAndroid && field.isJni()) + { + result = Jni.build(field, localClass); + } } if (result != null) { fields.push(result); + result = null; + } + else if (func.expr == null) + { + func.expr = switch (func.ret.toString()) + { + case "Bool" : macro return false; + case "Float" : macro return -1.0; + case "Void" : macro { + //Nothing + }; + case "Int" : macro return 0; + default : macro return null; + } } } } diff --git a/test/src/DefaultBodyTest.hx b/test/src/DefaultBodyTest.hx new file mode 100644 index 0000000..af65c99 --- /dev/null +++ b/test/src/DefaultBodyTest.hx @@ -0,0 +1,53 @@ +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; + +class DefaultBodyTest +{ + public function new() + { + + } + + @BeforeClass public function beforeClass(){} + @AfterClass public function afterClass(){} + @Before public function setup(){} + @After public function tearDown(){} + + @Test public function testDisabled() + { + Assert.isFalse(TestDefault.test1()); + Assert.isNull(TestDefault.test2()); + Assert.areEqual(TestDefault.test3(), -1.0); + Assert.isNull(TestDefault.test4()); + } + + @Test public function testdDefaultResponse() + { + Assert.areEqual(TestDefault.testCustomResponseString(), "osef"); + Assert.isTrue(TestDefault.testCustomBool()); + } +} + +@:build(ShortCuts.mirrors()) +class TestDefault +{ + @DISABLED @JNI @CPP public static function testVoid2():Void; + @DISABLED @JNI @CPP public static function testVoid(); + @DISABLED @JNI @CPP public static function test1():Bool; + @DISABLED @JNI @CPP public static function test2():String; + @DISABLED @JNI @CPP public static function test3():Float; + @DISABLED @JNI @CPP public static function test4():Dynamic + { + return null; + }; + @DISABLED @JNI @CPP public static function testCustomResponseString():String + { + return "osef"; + }; + + @DISABLED @JNI @CPP public static function testCustomBool():Bool + { + return true; + }; +} diff --git a/test/src/TestSuite.hx b/test/src/TestSuite.hx index 118100f..ddf0336 100644 --- a/test/src/TestSuite.hx +++ b/test/src/TestSuite.hx @@ -2,6 +2,7 @@ import massive.munit.TestSuite; import CppCallTest; import CppTest; +import DefaultBodyTest; import JniCallTest; import JniNonStaticTest; import JniTest; @@ -20,6 +21,7 @@ class TestSuite extends massive.munit.TestSuite add(CppCallTest); add(CppTest); + add(DefaultBodyTest); add(JniCallTest); add(JniNonStaticTest); add(JniTest); From a80f9aea0d6fd91f046c638680635135faa22080 Mon Sep 17 00:00:00 2001 From: shoebox Date: Mon, 22 Dec 2014 11:38:51 +0000 Subject: [PATCH 10/16] No more needed --- src/mirror/Mirror.hx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/mirror/Mirror.hx b/src/mirror/Mirror.hx index 474e79c..7642acb 100644 --- a/src/mirror/Mirror.hx +++ b/src/mirror/Mirror.hx @@ -20,9 +20,6 @@ class Mirror static inline var TagCppPrimitivePrefix = "CPP_PRIMITIVE_PREFIX"; static var VOID:ComplexType = TPath({name:"Void", pack:[], params:[], sub:null}); - static var FLOAT:ComplexType = TPath({name:"Float", pack:[], params:[], sub:null}); - static var INT:ComplexType = TPath({name:"Int", pack:[], params:[], sub:null}); - static var BOOL:ComplexType = TPath({name:"Bool", pack:[], params:[], sub:null}); function new(){} From 8a477007631040bb44ef5cddd5c4e53967ba915d Mon Sep 17 00:00:00 2001 From: shoebox Date: Mon, 22 Dec 2014 11:40:49 +0000 Subject: [PATCH 11/16] Test unit adjustements --- test/src/DefaultBodyTest.hx | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/test/src/DefaultBodyTest.hx b/test/src/DefaultBodyTest.hx index af65c99..231c968 100644 --- a/test/src/DefaultBodyTest.hx +++ b/test/src/DefaultBodyTest.hx @@ -32,22 +32,18 @@ class DefaultBodyTest @:build(ShortCuts.mirrors()) class TestDefault { - @DISABLED @JNI @CPP public static function testVoid2():Void; - @DISABLED @JNI @CPP public static function testVoid(); @DISABLED @JNI @CPP public static function test1():Bool; @DISABLED @JNI @CPP public static function test2():String; @DISABLED @JNI @CPP public static function test3():Float; - @DISABLED @JNI @CPP public static function test4():Dynamic + @DISABLED @JNI @CPP public static function test4():Dynamic; + @DISABLED @JNI @CPP public static function testCustomBool():Bool { - return null; + return true; }; @DISABLED @JNI @CPP public static function testCustomResponseString():String { return "osef"; }; - - @DISABLED @JNI @CPP public static function testCustomBool():Bool - { - return true; - }; + @DISABLED @JNI @CPP public static function testVoid1(); + @DISABLED @JNI @CPP public static function testVoid2():Void; } From f6d58487b66f400c90e80beea4d7eb41ccb70238 Mon Sep 17 00:00:00 2001 From: shoebox Date: Sat, 27 Dec 2014 12:52:01 +0100 Subject: [PATCH 12/16] Adjustements --- src/mirror/Mirror.hx | 11 ++--------- test/src/CppTest.hx | 20 +++++++++++++++++--- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/mirror/Mirror.hx b/src/mirror/Mirror.hx index 7642acb..92c1931 100644 --- a/src/mirror/Mirror.hx +++ b/src/mirror/Mirror.hx @@ -30,15 +30,8 @@ class Mirror var isCpp = #if munit true #else Context.defined("cpp") #end; var isAndroid = #if munit true #else Context.defined("android") #end; var isOpenFl = Context.defined("openfl") || Context.defined("nme"); - - - var isEnabled = - #if openfl - true; - #elseif munit - true; - #end - + var isEnabled = #if (openfl || munit) true #else false #end; + var fieldDisabled:Bool; var func:Function; if (isEnabled) diff --git a/test/src/CppTest.hx b/test/src/CppTest.hx index 9cbce32..fb9a428 100644 --- a/test/src/CppTest.hx +++ b/test/src/CppTest.hx @@ -40,9 +40,23 @@ class CppTest @Test public function testCall1() { - #if cpp - var result = Test1.test1("toto", false); - Assert.areEqual(result, 1.23); + #if (cpp) + var error = false; + var result:Null = null; + try + { + result = Test1.test1("toto", false); + } + catch (e:Dynamic) + { + error = true; + } + + #if openfl + Assert.isFalse(error); + #end + + Assert.areEqual(result, 1.23); #end } #end From 882a50d16c4b915139a5dd853e6adcffe0b5b394 Mon Sep 17 00:00:00 2001 From: shoebox Date: Sat, 27 Dec 2014 14:45:10 +0100 Subject: [PATCH 13/16] Abstact class test units --- src/mirror/CppFieldTool.hx | 4 +-- src/mirror/JniFieldTool.hx | 3 +- src/mirror/Mirror.hx | 7 +++-- test/src/AbstractTest.hx | 56 ++++++++++++++++++++++++++++++++++++++ test/src/CppTest.hx | 4 +-- test/src/TestSuite.hx | 2 ++ 6 files changed, 68 insertions(+), 8 deletions(-) create mode 100644 test/src/AbstractTest.hx diff --git a/src/mirror/CppFieldTool.hx b/src/mirror/CppFieldTool.hx index 5658757..ca547aa 100644 --- a/src/mirror/CppFieldTool.hx +++ b/src/mirror/CppFieldTool.hx @@ -39,7 +39,7 @@ class CppFieldTool entry = metas.get(TagPrimitivePrefix); if (entry.params.length == 0) { - Context.error("Cpp primitive tag is defined without value", + Context.error("C++ primitive tag is defined without value", field.pos); } @@ -59,7 +59,7 @@ class CppFieldTool var meta = localClass.meta.get(); if (entry.params.length == 0 && !meta.has(TagDefaultLibrary)) { - Context.error("Not default library defined globary or locally", + Context.error("Not default C++ library defined globary or locally", field.pos); } diff --git a/src/mirror/JniFieldTool.hx b/src/mirror/JniFieldTool.hx index 1fa813f..89fd6cf 100644 --- a/src/mirror/JniFieldTool.hx +++ b/src/mirror/JniFieldTool.hx @@ -79,11 +79,12 @@ using tools.MetadataTools; args.shift(); for (arg in args) + { result += translateArg(arg, field.pos); + } var returnType:Null = reference.ret.toType(); result += ")" + translateType(returnType, field.pos); - return result; } diff --git a/src/mirror/Mirror.hx b/src/mirror/Mirror.hx index 92c1931..fa1e388 100644 --- a/src/mirror/Mirror.hx +++ b/src/mirror/Mirror.hx @@ -45,7 +45,6 @@ class Mirror func.ret = VOID; fieldDisabled = field.meta.has(MirrorDisabledMeta); - if (!fieldDisabled) { if (isCpp && field.isCpp()) @@ -63,13 +62,15 @@ class Mirror fields.push(result); result = null; } - else if (func.expr == null) + + if (func.expr == null) { func.expr = switch (func.ret.toString()) { case "Bool" : macro return false; case "Float" : macro return -1.0; - case "Void" : macro { + case "Void" : macro + { //Nothing }; case "Int" : macro return 0; diff --git a/test/src/AbstractTest.hx b/test/src/AbstractTest.hx new file mode 100644 index 0000000..2e5b293 --- /dev/null +++ b/test/src/AbstractTest.hx @@ -0,0 +1,56 @@ + +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; + +import haxe.rtti.Meta; + +class AbstractTest +{ + var meta1:Dynamic; + + public function new() + { + GATracker; + } + + @BeforeClass public function beforeClass():Void + { + meta1 = Meta.getStatics(GATracker); + } + + @AfterClass public function afterClass():Void{} + @After public function tearDown():Void{} + @Before public function setup():Void{} + + @Test public function testJni1() + { + Assert.areEqual(meta1.testAbstractJni1.jni_signature[0], "(IF)Z"); + Assert.areEqual(meta1.testAbstractJni1.jni_primitive[0], "testAbstractJni1"); + } + + @Test public function testJni2() + { + Assert.areEqual(meta1.testAbstractJni2.jni_signature[0], "(F)I"); + Assert.areEqual(meta1.testAbstractJni2.jni_primitive[0], "testAbstractJni2"); + } + + @Test public function testCpp1() + { + Assert.areEqual(meta1.testCpp1.cpp_library[0], "toto"); + Assert.areEqual(meta1.testCpp1.cpp_primitive[0], "osef"); + } +} + +@:build(ShortCuts.mirrors()) +abstract GATracker(Int) +{ + inline public function new(value:Int) + { + this = value; + } + + @JNI public function testAbstractJni1(value:Float):Bool; + @JNI public static function testAbstractJni2(value:Float):Int; + @CPP('toto', 'osef') public function testCpp1(value:String):Int; +} diff --git a/test/src/CppTest.hx b/test/src/CppTest.hx index fb9a428..816195e 100644 --- a/test/src/CppTest.hx +++ b/test/src/CppTest.hx @@ -54,9 +54,9 @@ class CppTest #if openfl Assert.isFalse(error); - #end - + Assert.isNotNull(result); Assert.areEqual(result, 1.23); + #end #end } #end diff --git a/test/src/TestSuite.hx b/test/src/TestSuite.hx index ddf0336..28e2550 100644 --- a/test/src/TestSuite.hx +++ b/test/src/TestSuite.hx @@ -1,5 +1,6 @@ import massive.munit.TestSuite; +import AbstractTest; import CppCallTest; import CppTest; import DefaultBodyTest; @@ -19,6 +20,7 @@ class TestSuite extends massive.munit.TestSuite { super(); + add(AbstractTest); add(CppCallTest); add(CppTest); add(DefaultBodyTest); From 3a725c27b6f0b0c4534a619fa7c00bdf3632bd9e Mon Sep 17 00:00:00 2001 From: shoebox Date: Sun, 4 Jan 2015 20:22:50 +0000 Subject: [PATCH 14/16] Adjustements --- src/mirror/Jni.hx | 5 +---- src/mirror/JniFieldTool.hx | 20 +++++++++++++++++--- src/mirror/Mirror.hx | 6 ++++++ test/src/AbstractTest.hx | 1 + test/src/JniTest.hx | 6 +++--- 5 files changed, 28 insertions(+), 10 deletions(-) diff --git a/src/mirror/Jni.hx b/src/mirror/Jni.hx index 4ca1bf9..94fa8df 100644 --- a/src/mirror/Jni.hx +++ b/src/mirror/Jni.hx @@ -61,11 +61,8 @@ class Jni switch (returnTypeName) { case "Void", "Int", "Bool", "String", "Float": - case "Array", "Array", "Array": - - default: - field.getFunction().ret = DYNAMIC; + default : field.getFunction().ret = DYNAMIC; } if (Context.defined("android")) diff --git a/src/mirror/JniFieldTool.hx b/src/mirror/JniFieldTool.hx index 89fd6cf..1c4cdcc 100644 --- a/src/mirror/JniFieldTool.hx +++ b/src/mirror/JniFieldTool.hx @@ -26,6 +26,7 @@ using tools.MetadataTools; var result:String; var metas = Context.getLocalClass().get().meta.get(); var entry:MetadataEntry = field.meta.get(TagJni); + var hasFileName:Bool; if (metas.has(TagDefaultLibrary)) { if (metas.get(TagDefaultLibrary).params.length == 0) @@ -42,11 +43,24 @@ using tools.MetadataTools; else { var params = entry.params; - result = (params.length > 1) ? params[0].getString() - : Context.getLocalClass().get().pack.join('.'); + if (params.length > 1) + { + result = params[0].getString(); + } + else + { + result = Context.getLocalModule(); + hasFileName = true; + } } - result = result.split('.').join('/') + "/" + Context.getLocalClass().get().name; + var splitted = result.split('.'); + + if (!hasFileName) + splitted.push(Context.getLocalClass().get().name); + + result = splitted.join("/"); + return result; } diff --git a/src/mirror/Mirror.hx b/src/mirror/Mirror.hx index fa1e388..f577a70 100644 --- a/src/mirror/Mirror.hx +++ b/src/mirror/Mirror.hx @@ -40,6 +40,12 @@ class Mirror var result:Field; for (field in fields.copy()) { + switch (field.kind) + { + case FFun(f): + default : continue; + } + func = field.getFunction(); if (func.ret == null) func.ret = VOID; diff --git a/test/src/AbstractTest.hx b/test/src/AbstractTest.hx index 2e5b293..83fa31f 100644 --- a/test/src/AbstractTest.hx +++ b/test/src/AbstractTest.hx @@ -52,5 +52,6 @@ abstract GATracker(Int) @JNI public function testAbstractJni1(value:Float):Bool; @JNI public static function testAbstractJni2(value:Float):Int; + @JNI public static function testAbstractJni3(value:Float):Dynamic; @CPP('toto', 'osef') public function testCpp1(value:String):Int; } diff --git a/test/src/JniTest.hx b/test/src/JniTest.hx index c2ef7d0..64ba853 100644 --- a/test/src/JniTest.hx +++ b/test/src/JniTest.hx @@ -75,9 +75,9 @@ class JniTest @Test public function testPackage() { - Assert.areEqual(meta1.method1.jni_package[0], "testpackage/TestJni1"); - Assert.areEqual(meta1.method2.jni_package[0], "testpackage/TestJni1"); - Assert.areEqual(meta1.method3.jni_package[0], "testpackage/TestJni1"); + Assert.areEqual("testpackage/TestJni1", meta1.method1.jni_package[0]); + Assert.areEqual("testpackage/TestJni1", meta1.method2.jni_package[0]); + Assert.areEqual("testpackage/TestJni1", meta1.method3.jni_package[0]); } @Test public function testPackageMeta() From 41378f8808ec2d896efa6e732aada9c7e42b8f30 Mon Sep 17 00:00:00 2001 From: shoebox Date: Tue, 6 Jan 2015 10:53:36 +0000 Subject: [PATCH 15/16] Reactivate the IOS meta --- src/mirror/Cpp.hx | 1 - src/mirror/CppFieldTool.hx | 15 ++++++++++++--- src/mirror/Mirror.hx | 3 ++- src/tools/FieldTool.hx | 2 +- src/tools/FunctionTool.hx | 6 +++--- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/mirror/Cpp.hx b/src/mirror/Cpp.hx index 36896a1..3e07fd1 100644 --- a/src/mirror/Cpp.hx +++ b/src/mirror/Cpp.hx @@ -22,7 +22,6 @@ class Cpp var primitive = field.getPrimitiveName(localClass); var func = field.getFunction(); var argsCount = func.args.length; - #if munit var entryPrimitive = MetadataTools.create("cpp_primitive", field.pos, [macro $v{primitive}]); diff --git a/src/mirror/CppFieldTool.hx b/src/mirror/CppFieldTool.hx index ca547aa..534cd2b 100644 --- a/src/mirror/CppFieldTool.hx +++ b/src/mirror/CppFieldTool.hx @@ -11,6 +11,7 @@ using tools.MetadataTools; class CppFieldTool { public static inline var TagCpp = "CPP"; + public static inline var TagiOS = "IOS"; public static inline var TagDefaultLibrary = "CPP_DEFAULT_LIBRARY"; public static inline var TagPrimitivePrefix = "CPP_PRIMITIVE_PREFIX"; @@ -19,10 +20,16 @@ class CppFieldTool return field.meta.has(TagCpp); } + public static function isIos(field:Field):Bool + { + return field.meta.has(TagiOS); + } + public static function getPrimitiveName(field:Field, localClass:ClassType):String { - var entry:MetadataEntry = field.meta.get(TagCpp); + var entry:MetadataEntry = isIos(field) ? field.meta.get(TagiOS) + : field.meta.get(TagCpp); var result:String; if (entry.params.length > 1) { @@ -55,9 +62,11 @@ class CppFieldTool public static function getLibraryName(field:Field, localClass:ClassType):String { - var entry:MetadataEntry = field.meta.get(TagCpp); + var entry:MetadataEntry = isIos(field) ? field.meta.get(TagiOS) + : field.meta.get(TagCpp); var meta = localClass.meta.get(); - if (entry.params.length == 0 && !meta.has(TagDefaultLibrary)) + if ((entry.params == null || entry.params.length == 0) + && !meta.has(TagDefaultLibrary)) { Context.error("Not default C++ library defined globary or locally", field.pos); diff --git a/src/mirror/Mirror.hx b/src/mirror/Mirror.hx index f577a70..539e56a 100644 --- a/src/mirror/Mirror.hx +++ b/src/mirror/Mirror.hx @@ -28,6 +28,7 @@ class Mirror var fields = Context.getBuildFields(); var isCpp = #if munit true #else Context.defined("cpp") #end; + var isIos = #if munit true #else Context.defined("ios") #end; var isAndroid = #if munit true #else Context.defined("android") #end; var isOpenFl = Context.defined("openfl") || Context.defined("nme"); var isEnabled = #if (openfl || munit) true #else false #end; @@ -53,7 +54,7 @@ class Mirror fieldDisabled = field.meta.has(MirrorDisabledMeta); if (!fieldDisabled) { - if (isCpp && field.isCpp()) + if ((isCpp && field.isCpp()) || (isIos && field.isIos())) { result = Cpp.build(field, localClass); } diff --git a/src/tools/FieldTool.hx b/src/tools/FieldTool.hx index 599c5af..29141ac 100644 --- a/src/tools/FieldTool.hx +++ b/src/tools/FieldTool.hx @@ -19,7 +19,7 @@ class FieldTool return result; } - static inline function isStaticField(field:Field):Bool + public static inline function isStaticField(field:Field):Bool { var result = Lambda.has(field.access, AStatic); return result; diff --git a/src/tools/FunctionTool.hx b/src/tools/FunctionTool.hx index 8323a21..ba3ff98 100644 --- a/src/tools/FunctionTool.hx +++ b/src/tools/FunctionTool.hx @@ -4,19 +4,19 @@ import haxe.macro.Expr; class FunctionTool { - static inline function getArgsNames(func:Function):Array + static public inline function getArgsNames(func:Function):Array { var result:Array = [for (a in func.args) macro $i{a.name}]; return result.copy(); } - static inline function isStaticField(field:Field):Bool + static public inline function isStaticField(field:Field):Bool { var result = Lambda.has(field.access, AStatic); return result; } - static function createReturnExpr(func:Function, name:String, + static public function createReturnExpr(func:Function, name:String, args:Array):Expr { var expr:Expr = macro ""; From 935dfdbe2c4665c61b23d2df4d85b440fd3fe64f Mon Sep 17 00:00:00 2001 From: shoebox Date: Tue, 6 Jan 2015 10:57:38 +0000 Subject: [PATCH 16/16] Add a quick unit test for the IOS tag --- test/src/IosTest.hx | 37 +++++++++++++++++++++++++++++++++++++ test/src/TestSuite.hx | 2 ++ 2 files changed, 39 insertions(+) create mode 100644 test/src/IosTest.hx diff --git a/test/src/IosTest.hx b/test/src/IosTest.hx new file mode 100644 index 0000000..c9e9a44 --- /dev/null +++ b/test/src/IosTest.hx @@ -0,0 +1,37 @@ +package; + +import massive.munit.util.Timer; +import massive.munit.Assert; +import massive.munit.async.AsyncFactory; + +import haxe.rtti.Meta; + +class IosTest +{ + public function new() + { + TestIos; + } + + @Test public function testLibrary() + { + Assert.areEqual(Meta.getStatics(TestIos).test1.cpp_library[0], "testextension"); + Assert.areEqual(Meta.getStatics(TestIos).test2.cpp_library[0], "toto"); + } + + @Test public function testPrimitive() + { + Assert.areEqual(Meta.getStatics(TestIos).test1.cpp_primitive[0], "prefix_test1"); + Assert.areEqual(Meta.getStatics(TestIos).test2.cpp_primitive[0], "prim"); + } +} + +@:build(ShortCuts.mirrors()) +@CPP_DEFAULT_LIBRARY("testextension") +@CPP_PRIMITIVE_PREFIX("prefix") +class TestIos +{ + @IOS public static function test1(toto:String, value:Bool):Float{return 0.0;}; + @IOS("toto", "prim") public static function test2(toto:String, + value:Bool):Bool{return false;}; +} diff --git a/test/src/TestSuite.hx b/test/src/TestSuite.hx index 28e2550..b86f428 100644 --- a/test/src/TestSuite.hx +++ b/test/src/TestSuite.hx @@ -4,6 +4,7 @@ import AbstractTest; import CppCallTest; import CppTest; import DefaultBodyTest; +import IosTest; import JniCallTest; import JniNonStaticTest; import JniTest; @@ -24,6 +25,7 @@ class TestSuite extends massive.munit.TestSuite add(CppCallTest); add(CppTest); add(DefaultBodyTest); + add(IosTest); add(JniCallTest); add(JniNonStaticTest); add(JniTest);