forked from LeenkxTeam/LNXSDK
Update Files
This commit is contained in:
7
Kha/Backends/Kinc-hxcpp/khacpp/test/README.md
Normal file
7
Kha/Backends/Kinc-hxcpp/khacpp/test/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# hxcpp tests
|
||||
|
||||
The tests here are hxcpp specific. Notice that there are more target independent tests available in the [haxe repo](https://github.com/HaxeFoundation/haxe).
|
||||
|
||||
## Running the tests
|
||||
|
||||
haxe --run RunTests
|
209
Kha/Backends/Kinc-hxcpp/khacpp/test/RunTests.hx
Normal file
209
Kha/Backends/Kinc-hxcpp/khacpp/test/RunTests.hx
Normal file
@ -0,0 +1,209 @@
|
||||
class RunTests
|
||||
{
|
||||
static var baseDir:String;
|
||||
static var errors = new Array<String>();
|
||||
static var cppAst:Array<String> = [];
|
||||
static var sysArgs = new Array<String>();
|
||||
static var binDir = "";
|
||||
static var ext = "";
|
||||
static var m64 = true;
|
||||
static var m64Def = "HXCPP_M64";
|
||||
static var windows = false;
|
||||
static var sep = "/";
|
||||
|
||||
public static function cffi()
|
||||
{
|
||||
setDir("cffi/project");
|
||||
|
||||
command("haxelib", ["run", "hxcpp", "build.xml", "-debug", '-D$m64Def']);
|
||||
|
||||
setDir("cffi");
|
||||
command("haxe", ["compile.hxml", "-debug"] );
|
||||
command("haxe", ["compile-utf8.hxml", "-debug"] );
|
||||
command("haxe", ["compile-neko.hxml", "-debug"] );
|
||||
|
||||
copy('project/ndll/$binDir/prime$ext', 'bin/neko/prime.ndll');
|
||||
|
||||
setDir("cffi");
|
||||
command("bin" + sep + "cpp" + sep + "TestMain-debug",[]);
|
||||
command("bin" + sep + "cpp-utf8" + sep + "TestMain-debug",[]);
|
||||
|
||||
if (m64Def=="HXCPP_M64")
|
||||
{
|
||||
setDir("cffi/bin/neko");
|
||||
command("neko", ["TestMain.n"]);
|
||||
}
|
||||
}
|
||||
|
||||
public static function runHaxe()
|
||||
{
|
||||
setDir("haxe");
|
||||
command("haxe", ["compile.hxml", "-debug", "-D", m64Def].concat(cppAst) );
|
||||
command("bin" + sep + "TestMain-debug",[]);
|
||||
}
|
||||
|
||||
public static function runTelemetry()
|
||||
{
|
||||
setDir("telemetry");
|
||||
|
||||
// Telemetry should work in debug and non-debug modes
|
||||
// TODO: do we need m64Def?
|
||||
command("haxe", ["compile.hxml", "-debug"].concat(cppAst) );
|
||||
command("bin" + sep + "TestMain-debug",[]);
|
||||
|
||||
command("haxe", ["compile.hxml"].concat(cppAst) );
|
||||
command("bin" + sep + "TestMain",[]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static function debugger()
|
||||
{
|
||||
setDir("debugger");
|
||||
|
||||
command("haxe", ["compile.hxml"] );
|
||||
command("bin" + sep + "App-debug",[]);
|
||||
}
|
||||
|
||||
public static function opMatrix()
|
||||
{
|
||||
setDir("opMatrix");
|
||||
|
||||
command("haxe", ["--run","MkOps.hx"] );
|
||||
}
|
||||
|
||||
|
||||
public static function cppia()
|
||||
{
|
||||
setDir("cppia");
|
||||
|
||||
command("haxe", ["compile-host.hxml"] );
|
||||
command("haxe", ["compile-client.hxml"] );
|
||||
command("bin" + sep + "CppiaHost",[ "bin" + sep + "client.cppia" ]);
|
||||
command("bin" + sep + "CppiaHost",[ "bin" + sep + "client.cppia", "-jit" ]);
|
||||
}
|
||||
|
||||
public static function native()
|
||||
{
|
||||
setDir("native");
|
||||
|
||||
command("haxe", ["compile.hxml"] );
|
||||
command("bin" + sep + "Native",[]);
|
||||
}
|
||||
|
||||
public static function std32()
|
||||
{
|
||||
setDir("std");
|
||||
|
||||
command("haxe", ["compile32.hxml"] );
|
||||
command("cpp32"+sep+"Test",[]);
|
||||
}
|
||||
|
||||
public static function std64()
|
||||
{
|
||||
setDir("std");
|
||||
|
||||
command("haxe", ["compile64.hxml"] );
|
||||
command("cpp64"+sep+"Test",[]);
|
||||
}
|
||||
|
||||
|
||||
public static function setDir(name:String)
|
||||
{
|
||||
Sys.println("Enter " + baseDir + "/" + name);
|
||||
Sys.setCwd(baseDir + "/" + name);
|
||||
}
|
||||
|
||||
public static function command(prog:String, args:Array<String>)
|
||||
{
|
||||
Sys.println( prog + " " + args.join(" ") );
|
||||
var code = Sys.command(prog,args);
|
||||
if (code!=0)
|
||||
throw( "failed:" + prog + " " + args.join(" ") );
|
||||
}
|
||||
|
||||
public static function run(name:String, func:Void->Void)
|
||||
{
|
||||
var args = sysArgs;
|
||||
if (args.length>0 && args.indexOf(name)<0)
|
||||
{
|
||||
Sys.println("Skip test " + name);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
func();
|
||||
}
|
||||
catch(e:Dynamic)
|
||||
{
|
||||
trace('Error running $name : $e');
|
||||
errors.push('Error running $name : $e');
|
||||
}
|
||||
}
|
||||
|
||||
public static function copy(from:String, to:String)
|
||||
{
|
||||
if (windows)
|
||||
{
|
||||
from = from.split("/").join("\\");
|
||||
to = to.split("/").join("\\");
|
||||
}
|
||||
command( windows ? "copy" : "cp", [ from, to ] );
|
||||
}
|
||||
|
||||
public static function main()
|
||||
{
|
||||
var systemName = Sys.systemName().toLowerCase();
|
||||
switch(systemName.substr(0,3) )
|
||||
{
|
||||
case "mac":
|
||||
m64 = true;
|
||||
binDir = "Mac64";
|
||||
ext = ".dylib";
|
||||
case "lin":
|
||||
m64 = true;
|
||||
binDir = "Linux64";
|
||||
ext = ".dso";
|
||||
case "win":
|
||||
m64 = true;
|
||||
binDir = "Windows64";
|
||||
ext = ".dll";
|
||||
windows = true;
|
||||
sep = "\\";
|
||||
default:
|
||||
throw 'Unknown system "$systemName"';
|
||||
}
|
||||
|
||||
sysArgs = Sys.args();
|
||||
if (sysArgs.remove("-cppast"))
|
||||
cppAst = ["-D", "cppast"];
|
||||
|
||||
m64Def = m64 ? "HXCPP_M64" : "HXCPP_M32";
|
||||
|
||||
baseDir = Sys.getCwd();
|
||||
|
||||
run("cppia", cppia);
|
||||
run("cffi", cffi);
|
||||
//run("opMatrix", opMatrix);
|
||||
run("haxe", runHaxe);
|
||||
run("telemetry", runTelemetry);
|
||||
run("std32", std32);
|
||||
run("std64", std64);
|
||||
run("native", native);
|
||||
run("debugger", debugger);
|
||||
|
||||
Sys.println("");
|
||||
|
||||
if (errors.length==0)
|
||||
{
|
||||
Sys.println("All good!");
|
||||
Sys.exit(0);
|
||||
}
|
||||
Sys.println("There were errors:");
|
||||
for(error in errors)
|
||||
Sys.println(error);
|
||||
Sys.exit(-1);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,4 @@
|
||||
-cp src
|
||||
-main TestMain
|
||||
-neko bin/neko/TestMain.n
|
||||
-cp ../unit
|
@ -0,0 +1,5 @@
|
||||
-cp src
|
||||
-main TestMain
|
||||
-cpp bin/cpp-utf8
|
||||
-cp ../unit
|
||||
-D disable_unicode_strings
|
4
Kha/Backends/Kinc-hxcpp/khacpp/test/cffi/compile.hxml
Normal file
4
Kha/Backends/Kinc-hxcpp/khacpp/test/cffi/compile.hxml
Normal file
@ -0,0 +1,4 @@
|
||||
-cp src
|
||||
-main TestMain
|
||||
-cpp bin/cpp
|
||||
-cp ../unit
|
381
Kha/Backends/Kinc-hxcpp/khacpp/test/cffi/project/Project.cpp
Normal file
381
Kha/Backends/Kinc-hxcpp/khacpp/test/cffi/project/Project.cpp
Normal file
@ -0,0 +1,381 @@
|
||||
#ifndef STATIC_LINK
|
||||
#define IMPLEMENT_API
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(HX_WINDOWS) || defined(HX_MACOS) || defined(HX_LINUX)
|
||||
// Include neko glue....
|
||||
#define NEKO_COMPATIBLE
|
||||
#endif
|
||||
|
||||
#include <hx/CFFIPrime.h>
|
||||
#include <math.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
|
||||
int addInts(int a, int b)
|
||||
{
|
||||
return a+b;
|
||||
}
|
||||
DEFINE_PRIME2(addInts);
|
||||
|
||||
void printString(const char *inMessage)
|
||||
{
|
||||
printf("Message : %s.\n", inMessage);
|
||||
}
|
||||
DEFINE_PRIME1v(printString);
|
||||
|
||||
std::vector<AutoGCRoot *> roots;
|
||||
|
||||
void setRoot(int inRoot, value inValue)
|
||||
{
|
||||
if (roots.size()<=inRoot)
|
||||
roots.resize(inRoot+1);
|
||||
if (roots[inRoot]==0)
|
||||
roots[inRoot] = new AutoGCRoot(inValue);
|
||||
else
|
||||
roots[inRoot]->set(inValue);
|
||||
}
|
||||
DEFINE_PRIME2v(setRoot);
|
||||
|
||||
|
||||
value getRoot(int inRoot)
|
||||
{
|
||||
if (inRoot>=roots.size() || !roots[inRoot])
|
||||
return alloc_null();
|
||||
return roots[inRoot]->get();
|
||||
}
|
||||
DEFINE_PRIME1(getRoot);
|
||||
|
||||
|
||||
void clearRoots()
|
||||
{
|
||||
for(int i=0;i<roots.size();i++)
|
||||
{
|
||||
delete roots[i];
|
||||
roots[i] = 0;
|
||||
}
|
||||
}
|
||||
DEFINE_PRIME0v(clearRoots);
|
||||
|
||||
|
||||
double distance3D(int x, int y, int z)
|
||||
{
|
||||
return sqrt( (double)(x*x + y*y+ z*z) );
|
||||
}
|
||||
DEFINE_PRIME3(distance3D);
|
||||
|
||||
void fields(value object)
|
||||
{
|
||||
if ( val_is_null(object))
|
||||
printf("null fields\n");
|
||||
else
|
||||
printf("x : %f\n", val_field_numeric(object, val_id("x")) );
|
||||
}
|
||||
DEFINE_PRIME1v(fields);
|
||||
|
||||
|
||||
HxString stringVal(HxString inString)
|
||||
{
|
||||
printf("String : %s (%d)\n", inString.c_str(), inString.size());
|
||||
return HxString("Ok");
|
||||
}
|
||||
DEFINE_PRIME1(stringVal);
|
||||
|
||||
|
||||
HxString getNullString()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
DEFINE_PRIME0(getNullString);
|
||||
|
||||
|
||||
// Conflict with name - use anon-namespace
|
||||
namespace {
|
||||
value select(int which, value object0, value object1, value object2, value object3)
|
||||
{
|
||||
switch(which)
|
||||
{
|
||||
case 0: return object0;
|
||||
case 1: return object1;
|
||||
case 2: return object2;
|
||||
case 3: return object3;
|
||||
default: return alloc_null();
|
||||
}
|
||||
}
|
||||
DEFINE_PRIME5(select);
|
||||
}
|
||||
|
||||
float floats(bool add, float firstVal, float secondVal)
|
||||
{
|
||||
return add ? firstVal + secondVal : firstVal - secondVal;
|
||||
}
|
||||
DEFINE_PRIME3(floats);
|
||||
|
||||
|
||||
int multi5(int i0, int i1, int i2, int i3, int i4)
|
||||
{
|
||||
return i0 + i1 + i2 + i3 + i4;
|
||||
}
|
||||
DEFINE_PRIME5(multi5);
|
||||
|
||||
|
||||
|
||||
int multi6(int i0, int i1, int i2, int i3, int i4, int i5)
|
||||
{
|
||||
return i0 + i1 + i2 + i3 + i4 + i5;
|
||||
}
|
||||
DEFINE_PRIME6(multi6);
|
||||
|
||||
int multi7(int i0, int i1, int i2, int i3, int i4, int i5, int i6)
|
||||
{
|
||||
return i0 + i1 + i2 + i3 + i4 + i5 + i6;
|
||||
}
|
||||
DEFINE_PRIME7(multi7);
|
||||
|
||||
|
||||
int multi8(int i0, int i1, int i2, int i3, int i4, int i5, int i6, int i7)
|
||||
{
|
||||
return i0 + i1 + i2 + i3 + i4 + i5 + i6 + i7;
|
||||
}
|
||||
DEFINE_PRIME8(multi8);
|
||||
|
||||
|
||||
int multi9(int i0, int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8)
|
||||
{
|
||||
return i0 + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8;
|
||||
}
|
||||
DEFINE_PRIME9(multi9);
|
||||
|
||||
int multi10(int i0, int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9)
|
||||
{
|
||||
return i0 + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9;
|
||||
}
|
||||
DEFINE_PRIME10(multi10);
|
||||
|
||||
int multi11(int i0, int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10)
|
||||
{
|
||||
return i0 + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10;
|
||||
}
|
||||
DEFINE_PRIME11(multi11);
|
||||
|
||||
|
||||
int multi12(int i0, int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, int i11)
|
||||
{
|
||||
return i0 + i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10 + i11;
|
||||
}
|
||||
DEFINE_PRIME12(multi12);
|
||||
|
||||
|
||||
HxString addStrings(HxString s0, HxString s1)
|
||||
{
|
||||
if (hxs_encoding(s0)!=hx::StringUtf16 && hxs_encoding(s1)!=hx::StringUtf16)
|
||||
{
|
||||
std::string w0 = hxs_utf8(s0,0);
|
||||
std::string w1 = hxs_utf8(s1,0);
|
||||
std::string result = w0+w1;
|
||||
return alloc_hxs_utf8( result.c_str(), result.size() );
|
||||
}
|
||||
std::wstring w0 = hxs_wchar(s0,0);
|
||||
std::wstring w1 = hxs_wchar(s1,0);
|
||||
std::wstring result = w0+w1;
|
||||
return alloc_hxs_wchar( result.c_str(), result.size() );
|
||||
}
|
||||
DEFINE_PRIME2(addStrings);
|
||||
|
||||
|
||||
// Old-style CFFI
|
||||
value isBool(value inVal)
|
||||
{
|
||||
return alloc_bool( val_is_bool(inVal) );
|
||||
}
|
||||
DEFINE_PRIM(isBool,1);
|
||||
|
||||
value isNull(value inVal)
|
||||
{
|
||||
return alloc_bool( val_is_null(inVal) );
|
||||
}
|
||||
DEFINE_PRIM(isNull,1);
|
||||
|
||||
|
||||
value allocNull()
|
||||
{
|
||||
return alloc_null();
|
||||
}
|
||||
DEFINE_PRIM(allocNull,0);
|
||||
|
||||
|
||||
value appendString(value bufVal, value stringVal)
|
||||
{
|
||||
buffer buf = val_to_buffer(bufVal);
|
||||
val_buffer(buf,stringVal);
|
||||
return buffer_val(buf);
|
||||
}
|
||||
DEFINE_PRIM(appendString,2);
|
||||
|
||||
|
||||
value bufferToString(value bufVal)
|
||||
{
|
||||
buffer buf = val_to_buffer(bufVal);
|
||||
return buffer_to_string(buf);
|
||||
}
|
||||
DEFINE_PRIM(bufferToString, 1);
|
||||
|
||||
|
||||
value valToString(value a, value b)
|
||||
{
|
||||
buffer buf = alloc_buffer("String:");
|
||||
val_buffer(buf,a);
|
||||
val_buffer(buf,b);
|
||||
return buffer_to_string(buf);
|
||||
}
|
||||
DEFINE_PRIM(valToString, 2);
|
||||
|
||||
|
||||
|
||||
value valIsBuffer(value bufVal)
|
||||
{
|
||||
return alloc_bool( val_is_buffer(bufVal) );
|
||||
}
|
||||
DEFINE_PRIM(valIsBuffer, 1);
|
||||
|
||||
|
||||
value subBuffer(value inString, value inLen)
|
||||
{
|
||||
buffer buf = alloc_buffer("Cold as ");
|
||||
const char *string = val_string(inString);
|
||||
buffer_append_sub(buf,string, val_int(inLen) );
|
||||
return buffer_to_string(buf);
|
||||
}
|
||||
DEFINE_PRIM(subBuffer, 2);
|
||||
|
||||
|
||||
value charString(value inC0, value inC1, value inC2)
|
||||
{
|
||||
buffer buf = alloc_buffer("A ");
|
||||
buffer_append_char(buf,val_int(inC0));
|
||||
buffer_append_char(buf,val_int(inC1));
|
||||
buffer_append_char(buf,val_int(inC2));
|
||||
return buffer_to_string(buf);
|
||||
}
|
||||
DEFINE_PRIM(charString, 3);
|
||||
|
||||
|
||||
value byteDataSize(value byteData)
|
||||
{
|
||||
CffiBytes bytes = getByteData(byteData);
|
||||
if (bytes.data==0)
|
||||
return alloc_null();
|
||||
return alloc_int(bytes.length);
|
||||
}
|
||||
DEFINE_PRIM(byteDataSize, 1);
|
||||
|
||||
|
||||
value byteDataByte(value byteData, value inIndex)
|
||||
{
|
||||
CffiBytes bytes = getByteData(byteData);
|
||||
if (bytes.data==0)
|
||||
return alloc_null();
|
||||
|
||||
return alloc_int(bytes.data[ val_int(inIndex) ]);
|
||||
}
|
||||
DEFINE_PRIM(byteDataByte, 2);
|
||||
|
||||
|
||||
int myFreeCount = 0;
|
||||
|
||||
DEFINE_KIND(myKind);
|
||||
|
||||
void destroyMyKind(value inAbstract)
|
||||
{
|
||||
//printf("destroyMyKind\n");
|
||||
// In this case, the data belongs to the abstract
|
||||
myFreeCount++;
|
||||
}
|
||||
|
||||
void freeMyKind(value inAbstract)
|
||||
{
|
||||
//printf("freeMyKind\n");
|
||||
void *data = val_to_kind(inAbstract,myKind);
|
||||
// In this case, we own the data, so must delete it
|
||||
delete (int *)data;
|
||||
myFreeCount++;
|
||||
}
|
||||
|
||||
|
||||
value allocAbstract()
|
||||
{
|
||||
if (!myKind)
|
||||
myKind = alloc_kind();
|
||||
|
||||
void *data = new int(99);
|
||||
|
||||
value abs = alloc_abstract(myKind, data);
|
||||
val_gc(abs, freeMyKind);
|
||||
return abs;
|
||||
}
|
||||
DEFINE_PRIM(allocAbstract, 0);
|
||||
|
||||
|
||||
|
||||
value createAbstract()
|
||||
{
|
||||
if (!myKind)
|
||||
myKind = alloc_kind();
|
||||
|
||||
value abs = create_abstract(myKind, sizeof(int), destroyMyKind);
|
||||
int *data = (int *)val_get_handle(abs,myKind);
|
||||
*data = 99;
|
||||
return abs;
|
||||
}
|
||||
DEFINE_PRIM(createAbstract, 0);
|
||||
|
||||
|
||||
|
||||
value getAbstract(value inAbstract)
|
||||
{
|
||||
void *data = val_to_kind(inAbstract,myKind);
|
||||
if (!data)
|
||||
return alloc_int(-1);
|
||||
|
||||
return alloc_int(*(int *)data);
|
||||
}
|
||||
DEFINE_PRIM(getAbstract, 1);
|
||||
|
||||
|
||||
value getAbstractFreeCount()
|
||||
{
|
||||
return alloc_int(myFreeCount);
|
||||
}
|
||||
DEFINE_PRIM(getAbstractFreeCount, 0);
|
||||
|
||||
|
||||
value freeAbstract(value inAbstract)
|
||||
{
|
||||
free_abstract(inAbstract);
|
||||
return alloc_null();
|
||||
}
|
||||
DEFINE_PRIM(freeAbstract, 1);
|
||||
|
||||
|
||||
value createAnon()
|
||||
{
|
||||
value v = alloc_empty_object();
|
||||
alloc_field(v,val_id("TInt"),alloc_int(7));
|
||||
alloc_field(v,val_id("TFloat"),alloc_float(7.2));
|
||||
alloc_field(v,val_id("TBool"),alloc_bool(true));
|
||||
|
||||
buffer buf = alloc_buffer_len(4);
|
||||
int data = 0xdeadbeef;
|
||||
memcpy(buffer_data(buf),&data,sizeof(int));
|
||||
alloc_field(v,val_id("TClass(Array)"),buffer_val(buf));
|
||||
return v;
|
||||
}
|
||||
|
||||
DEFINE_PRIM(createAnon,0);
|
||||
|
||||
|
||||
|
||||
|
||||
|
15
Kha/Backends/Kinc-hxcpp/khacpp/test/cffi/project/build.xml
Normal file
15
Kha/Backends/Kinc-hxcpp/khacpp/test/cffi/project/build.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<xml>
|
||||
<include name="${HXCPP}/toolchain/haxe-target.xml"/>
|
||||
|
||||
<files id="prime">
|
||||
<depend files="hxcpp-depends"/>
|
||||
<file name="Project.cpp" />
|
||||
</files>
|
||||
|
||||
<target id="default" output="${LIBPREFIX}prime${HX_TARGET_SUFFIX}" tool="linker" toolid="${STD_MODULE_LINK}">
|
||||
|
||||
<outdir name="${NDLLDIR}/${BINDIR}" />
|
||||
<files id="prime"/>
|
||||
</target>
|
||||
|
||||
</xml>
|
20
Kha/Backends/Kinc-hxcpp/khacpp/test/cffi/src/Loader.hx
Normal file
20
Kha/Backends/Kinc-hxcpp/khacpp/test/cffi/src/Loader.hx
Normal file
@ -0,0 +1,20 @@
|
||||
#if macro
|
||||
import haxe.macro.Expr;
|
||||
#end
|
||||
|
||||
|
||||
class Loader
|
||||
{
|
||||
#if cpp
|
||||
public static function __init__()
|
||||
{
|
||||
cpp.Lib.pushDllSearchPath( "project/ndll/" + cpp.Lib.getBinDirectory() );
|
||||
}
|
||||
#end
|
||||
|
||||
public static inline macro function load(inName2:Expr, inSig:Expr)
|
||||
{
|
||||
return macro cpp.Prime.load("prime", $inName2, $inSig, false);
|
||||
}
|
||||
}
|
||||
|
18
Kha/Backends/Kinc-hxcpp/khacpp/test/cffi/src/TestBase.hx
Normal file
18
Kha/Backends/Kinc-hxcpp/khacpp/test/cffi/src/TestBase.hx
Normal file
@ -0,0 +1,18 @@
|
||||
import haxe.PosInfos;
|
||||
|
||||
class TestBase extends haxe.unit.TestCase
|
||||
{
|
||||
public function assertClose(inWant:Float, inGot:Float, ?c : PosInfos )
|
||||
{
|
||||
assertTrue( Math.abs(inWant-inGot) < 0.001, c );
|
||||
}
|
||||
|
||||
public function assertEq<T>(inWant:T, inGot:T, ?c : PosInfos )
|
||||
{
|
||||
var same = inWant==inGot;
|
||||
if (!same)
|
||||
trace('Expected $inWant, got $inGot');
|
||||
assertTrue(same, c);
|
||||
}
|
||||
}
|
||||
|
193
Kha/Backends/Kinc-hxcpp/khacpp/test/cffi/src/TestCffi.hx
Normal file
193
Kha/Backends/Kinc-hxcpp/khacpp/test/cffi/src/TestCffi.hx
Normal file
@ -0,0 +1,193 @@
|
||||
#if cpp
|
||||
import cpp.Lib;
|
||||
import cpp.vm.Gc;
|
||||
#elseif neko
|
||||
import neko.Lib;
|
||||
import neko.vm.Gc;
|
||||
#end
|
||||
|
||||
import Loader;
|
||||
|
||||
import haxe.io.BytesData;
|
||||
|
||||
class TestCffi extends TestBase
|
||||
{
|
||||
static var isBool:Dynamic->Bool = Lib.load("prime", "isBool", 1);
|
||||
static var isNull:Dynamic->Bool = Lib.load("prime", "isNull", 1);
|
||||
static var allocNull:Void->Dynamic = Lib.load("prime", "allocNull", 0);
|
||||
static var appendString:BytesData->String->BytesData = Lib.load("prime", "appendString", 2);
|
||||
static var bufferToString:BytesData->String = Lib.load("prime", "bufferToString", 1);
|
||||
static var valIsBuffer:Dynamic->Bool = Lib.load("prime", "valIsBuffer", 1);
|
||||
static var valToString:Dynamic->Dynamic->String = Lib.load("prime", "valToString", 2);
|
||||
static var subBuffer:String->Int->String = Lib.load("prime", "subBuffer", 2);
|
||||
static var charString:Int->Int->Int->String = Lib.load("prime", "charString", 3);
|
||||
static var byteDataSize:haxe.io.Bytes->Int = Lib.load("prime", "byteDataSize", 1);
|
||||
static var byteDataByte:haxe.io.Bytes->Int->Int = Lib.load("prime", "byteDataByte", 2);
|
||||
static var setRoot:Int->Dynamic->Void = Lib.load("prime", "setRoot", 2);
|
||||
static var getRoot:Int->Dynamic = Lib.load("prime", "getRoot", 1);
|
||||
static var clearRoots:Void->Void = Lib.load("prime", "clearRoots", 0);
|
||||
static var createAbstract:Void->Dynamic = Lib.load("prime", "createAbstract", 0);
|
||||
static var allocAbstract:Void->Dynamic = Lib.load("prime", "allocAbstract", 0);
|
||||
static var getAbstract:Dynamic->Int = Lib.load("prime", "getAbstract", 1);
|
||||
static var freeAbstract:Dynamic->Void = Lib.load("prime", "freeAbstract", 1);
|
||||
static var getAbstractFreeCount:Void->Int = Lib.load("prime", "getAbstractFreeCount", 0);
|
||||
static var createAnon:Void->Dynamic = Lib.load("prime", "createAnon", 0);
|
||||
|
||||
|
||||
static var cppObjectAsDynamic:cpp.Callable<Int->cpp.Object>;
|
||||
|
||||
|
||||
inline function getObjectAsString() : String
|
||||
{
|
||||
// Just test to see if this compiles
|
||||
if (cppObjectAsDynamic!=null)
|
||||
return cppObjectAsDynamic(1);
|
||||
return null;
|
||||
}
|
||||
|
||||
public function testCffi()
|
||||
{
|
||||
cpp.Prime.nekoInit("prime");
|
||||
|
||||
assertTrue( isBool!=null );
|
||||
assertTrue( isBool(true) );
|
||||
assertTrue( isBool(false) );
|
||||
assertFalse( isBool(21) );
|
||||
assertFalse( isBool("Hello") );
|
||||
assertFalse( isBool(null) );
|
||||
|
||||
assertTrue( isNull!=null );
|
||||
assertTrue( isNull(null) );
|
||||
assertFalse( isNull(false) );
|
||||
assertFalse( isNull(32) );
|
||||
assertFalse( isNull("") );
|
||||
|
||||
assertTrue( allocNull!=null );
|
||||
assertEquals(null, allocNull() );
|
||||
|
||||
assertTrue( appendString!=null );
|
||||
assertTrue( bufferToString!=null );
|
||||
assertTrue( getRoot!=null );
|
||||
assertTrue( setRoot!=null );
|
||||
|
||||
assertTrue( createAnon!=null );
|
||||
|
||||
|
||||
assertFalse( valIsBuffer(null) );
|
||||
assertFalse( valIsBuffer(1) );
|
||||
assertFalse( valIsBuffer({}) );
|
||||
assertFalse( valIsBuffer("String Buf") );
|
||||
|
||||
if (cppObjectAsDynamic!=null)
|
||||
assertTrue( getObjectAsString()==null);
|
||||
|
||||
var anon = createAnon();
|
||||
for(f in Reflect.fields(anon))
|
||||
{
|
||||
#if cpp
|
||||
var value:Dynamic = Reflect.field(anon, f);
|
||||
//trace(f + " " + Type.typeof(value) );
|
||||
assertTrue( Std.string(Type.typeof(value)) == f );
|
||||
#end
|
||||
}
|
||||
|
||||
for(i in 0...100)
|
||||
setRoot(i,[i]);
|
||||
|
||||
Gc.run(true);
|
||||
|
||||
|
||||
|
||||
var base = "Hello ";
|
||||
var bytes = haxe.io.Bytes.ofString(base).getData();
|
||||
|
||||
#if !neko
|
||||
assertTrue( valIsBuffer(bytes) );
|
||||
// Can't acess neko buffer from haxe code
|
||||
bytes = appendString(bytes,"World");
|
||||
var result = bufferToString(bytes);
|
||||
assertEq(result,"Hello World");
|
||||
#end
|
||||
|
||||
assertEq(valToString(null,1),"String:null1");
|
||||
assertEq(valToString("x",1.1),"String:x1.1");
|
||||
assertEq(valToString("Hello"," World"),"String:Hello World");
|
||||
assertEq(valToString([1],[]),"String:[1][]");
|
||||
|
||||
assertEq(subBuffer("hello",4),"Cold as hell");
|
||||
|
||||
#if !neko
|
||||
assertEq(charString(99,97,116),"A cat");
|
||||
#end
|
||||
|
||||
var bytes = haxe.io.Bytes.ofString("String Buffer");
|
||||
assertEq( byteDataSize(bytes), 13 );
|
||||
assertEq( byteDataByte(bytes,1), 't'.code );
|
||||
|
||||
assertEq( getAbstractFreeCount(), 0 );
|
||||
|
||||
var createdAbs = createAbstract();
|
||||
assertTrue( createdAbs!=null );
|
||||
assertEq( getAbstract(createdAbs), 99 );
|
||||
// Explicitly freeing abstract does not call finalizer
|
||||
freeAbstract( createdAbs );
|
||||
assertEq( getAbstractFreeCount(), 0 );
|
||||
assertEq( getAbstract(createdAbs), -1 );
|
||||
assertEq( getAbstractFreeCount(), 0 );
|
||||
createdAbs = null;
|
||||
Gc.run(true);
|
||||
assertEq( getAbstractFreeCount(), 0 );
|
||||
|
||||
var allocatedAbs = allocAbstract();
|
||||
assertTrue( allocatedAbs!=null );
|
||||
assertEq( getAbstract(allocatedAbs), 99 );
|
||||
assertEq( getAbstractFreeCount(), 0 );
|
||||
freeAbstract( allocatedAbs );
|
||||
assertEq( getAbstract(allocatedAbs), -1 );
|
||||
assertEq( getAbstractFreeCount(), 0 );
|
||||
allocatedAbs = null;
|
||||
|
||||
|
||||
createDeepAbstracts(2);
|
||||
clearStack(12);
|
||||
|
||||
Gc.run(true);
|
||||
|
||||
var freeCount = getAbstractFreeCount();
|
||||
if (freeCount!=2)
|
||||
{
|
||||
Sys.println('\nWarning: $freeCount != 2');
|
||||
}
|
||||
|
||||
for(i in 0...100)
|
||||
assertEq( getRoot(i)+"", [i]+"" );
|
||||
|
||||
clearRoots();
|
||||
|
||||
for(i in 0...100)
|
||||
assertEq( getRoot(i), null );
|
||||
|
||||
assertEq( getAbstractFreeCount(), 2 );
|
||||
}
|
||||
|
||||
function clearStack(count:Int, ?nothing:Dynamic):Dynamic
|
||||
{
|
||||
if (count==0)
|
||||
return 0;
|
||||
return clearStack(count-1);
|
||||
}
|
||||
|
||||
// Try to hide references from GC stack marking
|
||||
function createDeepAbstracts(inDepth:Int)
|
||||
{
|
||||
if (inDepth==0)
|
||||
{
|
||||
createAbstract();
|
||||
allocAbstract();
|
||||
}
|
||||
else
|
||||
createDeepAbstracts(inDepth-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
17
Kha/Backends/Kinc-hxcpp/khacpp/test/cffi/src/TestMain.hx
Normal file
17
Kha/Backends/Kinc-hxcpp/khacpp/test/cffi/src/TestMain.hx
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
class TestMain
|
||||
{
|
||||
public static function main()
|
||||
{
|
||||
var r = new haxe.unit.TestRunner();
|
||||
r.add(new TestCffi());
|
||||
r.add(new TestPrime());
|
||||
|
||||
var t0 = haxe.Timer.stamp();
|
||||
var success = r.run();
|
||||
trace(" Time : " + (haxe.Timer.stamp()-t0)*1000 );
|
||||
Sys.exit(success ? 0 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
78
Kha/Backends/Kinc-hxcpp/khacpp/test/cffi/src/TestPrime.hx
Normal file
78
Kha/Backends/Kinc-hxcpp/khacpp/test/cffi/src/TestPrime.hx
Normal file
@ -0,0 +1,78 @@
|
||||
|
||||
|
||||
class TestPrime extends TestBase
|
||||
{
|
||||
static var add = Loader.load("addInts", "iii" );
|
||||
#if cpp
|
||||
static var printString = Loader.load("printString", "cv" );
|
||||
#end
|
||||
static var distance3d = Loader.load("distance3D", "iiid" );
|
||||
static var select = Loader.load("select", "iooooo" );
|
||||
static var floats = Loader.load("floats", "bfff" );
|
||||
static var stringVal = Loader.load("stringVal", "ss" );
|
||||
static var multi5 = Loader.load("multi5", "iiiiii" );
|
||||
static var multi6 = Loader.load("multi6", "iiiiiii" );
|
||||
static var multi7 = Loader.load("multi7", "iiiiiiii" );
|
||||
static var multi8 = Loader.load("multi8", "iiiiiiiii" );
|
||||
static var multi9 = Loader.load("multi9", "iiiiiiiiii" );
|
||||
static var multi10 = Loader.load("multi10","iiiiiiiiiii" );
|
||||
static var multi11 = Loader.load("multi11","iiiiiiiiiiii" );
|
||||
static var multi12 = Loader.load("multi12","iiiiiiiiiiiii" );
|
||||
static var getNullString = Loader.load("getNullString","s" );
|
||||
static var addStrings = Loader.load("addStrings", 'sss');
|
||||
|
||||
// Non-static test
|
||||
var fields = Loader.load("fields", "ov" );
|
||||
|
||||
public function testPrime()
|
||||
{
|
||||
cpp.Prime.nekoInit("prime");
|
||||
|
||||
assertTrue(add!=null);
|
||||
assertEquals(7, add(2,5));
|
||||
|
||||
#if cpp
|
||||
printString("Hello World");
|
||||
#end
|
||||
|
||||
var len = distance3d(3,4,5);
|
||||
assertClose(50,len*len);
|
||||
|
||||
fields( { x:11, name:"Hello" } );
|
||||
fields( null );
|
||||
|
||||
assertEquals("Ok", stringVal("HxString"));
|
||||
|
||||
assertEquals(null, getNullString());
|
||||
|
||||
assertEquals( ""+[1], ""+select(0, [1], "Hello", {x:1}, add) );
|
||||
var shouldBeNull:String = "" + select(0, null, "Hello", {x:1}, add);
|
||||
trace( "null ?" + shouldBeNull + "/" + shouldBeNull.length );
|
||||
assertEquals( "null", shouldBeNull );
|
||||
//assertEquals( "null", ""+select(0, null, "Hello", {x:1}, add) );
|
||||
assertEquals( ""+"Hello", ""+select(1, [1], "Hello", {x:1}, add));
|
||||
assertEquals( ""+{x:1}, ""+select(2, [1], "Hello", {x:1}, add) );
|
||||
assertEquals( ""+add, ""+select(3, [1], "Hello", {x:1}, add) );
|
||||
|
||||
assertClose( 7.3, floats(true,4.2,3.1) );
|
||||
assertClose( 1.1, floats(false,4.2,3.1) );
|
||||
|
||||
assertEquals( 5, multi5(1,1,1,1,1) );
|
||||
assertEquals( 6, multi6(1,1,1,1,1,1) );
|
||||
assertEquals( 7, multi7(1,1,1,1,1,1,1) );
|
||||
assertEquals( 8, multi8(1,1,1,1,1,1,1,1) );
|
||||
assertEquals( 9, multi9(1,1,1,1,1,1,1,1,1) );
|
||||
assertEquals( 10, multi10(1,1,1,1,1,1,1,1,1,1) );
|
||||
assertEquals( 11, multi11(1,1,1,1,1,1,1,1,1,1,1) );
|
||||
assertEquals( 12, multi12(1,1,1,1,1,1,1,1,1,1,1,1) );
|
||||
|
||||
var s0 = "hello";
|
||||
var s1 = "こんにちは";
|
||||
assertTrue( addStrings(s0,s0) == s0+s0 );
|
||||
var s01 = addStrings(s0,s1);
|
||||
assertTrue( s01 == s0+s1 );
|
||||
var s11 = addStrings(s1,s1);
|
||||
assertTrue( s11 == s1+s1 );
|
||||
|
||||
}
|
||||
}
|
167
Kha/Backends/Kinc-hxcpp/khacpp/test/cppia/Client.hx
Normal file
167
Kha/Backends/Kinc-hxcpp/khacpp/test/cppia/Client.hx
Normal file
@ -0,0 +1,167 @@
|
||||
class ClientOne implements pack.HostInterface
|
||||
{
|
||||
public function new() { }
|
||||
public function getOne() : Int return 1;
|
||||
public function getOneString() : String return "1";
|
||||
}
|
||||
|
||||
class Client
|
||||
{
|
||||
public static var clientBool0 = true;
|
||||
public static var clientBool1 = false;
|
||||
public static var clientBool2 = true;
|
||||
public static var clientBool3 = false;
|
||||
|
||||
public static function main()
|
||||
{
|
||||
Common.status = "running";
|
||||
|
||||
// See if it compiles
|
||||
if (sys.thread.Thread.current()==null)
|
||||
{
|
||||
Common.status = "Cppia Thread.current not working.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (Common.hostImplementation.getOne()!=1)
|
||||
{
|
||||
Common.status = "Bad call to getOne";
|
||||
return;
|
||||
}
|
||||
if (Common.hostImplementation.getOneString()!="1")
|
||||
{
|
||||
Common.status = "Bad call to getOneString";
|
||||
return;
|
||||
}
|
||||
|
||||
var c = new ClientExtends();
|
||||
if (!c.ok())
|
||||
{
|
||||
Common.status = "Bad client extension";
|
||||
return;
|
||||
}
|
||||
if (c.whoStartedYou()!="HostBase")
|
||||
{
|
||||
Common.status = "Bad class fallthrough - got " + c.whoStartedYou();
|
||||
return;
|
||||
}
|
||||
if (c.whoOverridesYou()!="ClientExtends")
|
||||
{
|
||||
Common.status = "Bad class override - got " + c.whoOverridesYou();
|
||||
return;
|
||||
}
|
||||
if (!c.testPointers())
|
||||
{
|
||||
Common.status = "Could not move native pointers";
|
||||
return;
|
||||
}
|
||||
|
||||
var hostInterface:IHostInterface = c;
|
||||
if (hostInterface.whoStartedYou()!="HostBase")
|
||||
{
|
||||
Common.status = "Bad interface fallthrough";
|
||||
return;
|
||||
}
|
||||
if (hostInterface.whoOverridesYou()!="ClientExtends")
|
||||
{
|
||||
Common.status = "Bad interface override";
|
||||
return;
|
||||
}
|
||||
if (hostInterface.hostImplOnly(1,"two",3)!="1two3")
|
||||
{
|
||||
Common.status = "Bad hostImplOnly implementation";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!c.testOne())
|
||||
{
|
||||
Common.status = "Bad ClientExtends getOne";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
var clientInterface:IClientInterface = c;
|
||||
if (clientInterface.whoStartedYou()!="HostBase")
|
||||
{
|
||||
Common.status = "Bad client interface fallthrough";
|
||||
return;
|
||||
}
|
||||
if (clientInterface.uniqueClientFunc()!="uniqueClientFunc")
|
||||
{
|
||||
Common.status = "Bad new client interface call";
|
||||
return;
|
||||
}
|
||||
|
||||
if (clientInterface.whoOverridesYou()!="ClientExtends")
|
||||
{
|
||||
Common.status = "Bad client interface override";
|
||||
return;
|
||||
}
|
||||
|
||||
var clientHostInterface:IClientHostInterface = c;
|
||||
if (clientHostInterface.whoStartedYou()!="HostBase")
|
||||
{
|
||||
Common.status = "Bad client interface fallthrough";
|
||||
return;
|
||||
}
|
||||
if (clientHostInterface.whoOverridesYou()!="ClientExtends")
|
||||
{
|
||||
Common.status = "Bad client interface override";
|
||||
return;
|
||||
}
|
||||
if (clientHostInterface.whoAreYou()!="ClientExtends")
|
||||
{
|
||||
Common.status = "Bad client/host interface";
|
||||
return;
|
||||
}
|
||||
|
||||
var c:ClientIHostImpl = new ClientIHostImpl();
|
||||
if (c.hostImplOnly(0,null,0)!="client" || c.whoStartedYou()!="client" || c.whoOverridesYou()!="client")
|
||||
{
|
||||
Common.status = "Trouble implementing host interface";
|
||||
return;
|
||||
}
|
||||
|
||||
var c:ClientExtends = new ClientExtends2();
|
||||
if (c.getGeneration()!=2)
|
||||
{
|
||||
Common.status = "Error calling cppia super function";
|
||||
return;
|
||||
}
|
||||
|
||||
var c = new ClientExtends2();
|
||||
if (c.testOne())
|
||||
{
|
||||
Common.status = "ClientExtends2 getOne should fail";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!c.testOneExtended())
|
||||
{
|
||||
Common.status = "ClientExtends2 testOneExtended failed";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!c.testFour())
|
||||
{
|
||||
Common.status = "ClientExtends2 testFour error";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
var hostBools = HostBase.hostBool0 + "/" + HostBase.hostBool1+ "/" + HostBase.hostBool2+ "/" + HostBase.hostBool3;
|
||||
var clientBools = clientBool0 + "/" + clientBool1+ "/" + clientBool2+ "/" + clientBool3;
|
||||
if (hostBools!=clientBools)
|
||||
{
|
||||
Common.status = "Error in bool representation:" + hostBools + "!=" + clientBools;
|
||||
return;
|
||||
}
|
||||
|
||||
Common.clientImplementation = new ClientOne();
|
||||
Common.status = "ok";
|
||||
|
||||
Common.callback = () -> Common.callbackSet = 2;
|
||||
}
|
||||
}
|
62
Kha/Backends/Kinc-hxcpp/khacpp/test/cppia/ClientExtends.hx
Normal file
62
Kha/Backends/Kinc-hxcpp/khacpp/test/cppia/ClientExtends.hx
Normal file
@ -0,0 +1,62 @@
|
||||
class ClientExtends extends HostBase implements IClientInterface implements IClientHostInterface
|
||||
{
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public function ok():Bool
|
||||
{
|
||||
return getVal()==1.25;
|
||||
}
|
||||
|
||||
public function testOne()
|
||||
{
|
||||
return getOne()==1;
|
||||
}
|
||||
|
||||
public function testOneExtended()
|
||||
{
|
||||
return getOne()==111;
|
||||
}
|
||||
|
||||
|
||||
#if (hxcpp_api_level>=400)
|
||||
public function testPointers() : Bool
|
||||
{
|
||||
pointerDest = pointerSrc;
|
||||
return getDestVal()==4;
|
||||
}
|
||||
|
||||
override public function getGeneration()
|
||||
{
|
||||
return super.getGeneration() + 1;
|
||||
}
|
||||
#else
|
||||
override public function getGeneration()
|
||||
{
|
||||
return super.getGeneration() + 1;
|
||||
}
|
||||
#end
|
||||
|
||||
override public function whoStartedYou() : String return super.whoStartedYou();
|
||||
|
||||
// override IHostInteface
|
||||
override public function whoOverridesYou() return "ClientExtends";
|
||||
|
||||
// new IClientInterface
|
||||
public function uniqueClientFunc() return "uniqueClientFunc";
|
||||
|
||||
// IClientHostInterface
|
||||
public function whoAreYou() return "ClientExtends";
|
||||
|
||||
public function getOne() return 1;
|
||||
|
||||
public function getTwo() return 2;
|
||||
|
||||
public function getThree() return 3;
|
||||
|
||||
override public function update() return "ClientExtends update";
|
||||
}
|
||||
|
||||
|
25
Kha/Backends/Kinc-hxcpp/khacpp/test/cppia/ClientExtends2.hx
Executable file
25
Kha/Backends/Kinc-hxcpp/khacpp/test/cppia/ClientExtends2.hx
Executable file
@ -0,0 +1,25 @@
|
||||
class ClientExtends2 extends ClientExtends
|
||||
{
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
override public function getGeneration()
|
||||
{
|
||||
return super.getGeneration()+1;
|
||||
}
|
||||
|
||||
public function getFour() return 4;
|
||||
|
||||
public function testFour() : Bool
|
||||
{
|
||||
return getFour()==4;
|
||||
}
|
||||
|
||||
override public function getOne() return 111;
|
||||
|
||||
override public function update() return "ClientExtends2 update";
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
class ClientIHostImpl implements IHostInterface
|
||||
{
|
||||
public function new() { }
|
||||
|
||||
public function hostImplOnly(i:Int, s:String, f:Float) : String return "client";
|
||||
public function whoStartedYou() : String return "client";
|
||||
public function whoOverridesYou() : String return "client";
|
||||
}
|
10
Kha/Backends/Kinc-hxcpp/khacpp/test/cppia/Common.hx
Normal file
10
Kha/Backends/Kinc-hxcpp/khacpp/test/cppia/Common.hx
Normal file
@ -0,0 +1,10 @@
|
||||
class Common
|
||||
{
|
||||
public static var status:String = "tests not run";
|
||||
public static var hostImplementation:pack.HostInterface;
|
||||
public static var clientImplementation:pack.HostInterface;
|
||||
|
||||
public static var callbackSet:Int = 0;
|
||||
public static var callback: Void->Void;
|
||||
|
||||
}
|
90
Kha/Backends/Kinc-hxcpp/khacpp/test/cppia/CppiaHost.hx
Normal file
90
Kha/Backends/Kinc-hxcpp/khacpp/test/cppia/CppiaHost.hx
Normal file
@ -0,0 +1,90 @@
|
||||
import cpp.cppia.Host;
|
||||
|
||||
import HostBase;
|
||||
|
||||
class HostOne implements pack.HostInterface
|
||||
{
|
||||
public static var called = 0;
|
||||
|
||||
public function new()
|
||||
{
|
||||
}
|
||||
|
||||
public function getOne() : Int
|
||||
{
|
||||
called ++;
|
||||
return 1;
|
||||
}
|
||||
public function getOneString() : String
|
||||
{
|
||||
called++;
|
||||
return "1";
|
||||
}
|
||||
}
|
||||
|
||||
class CppiaHost
|
||||
{
|
||||
|
||||
public static function main()
|
||||
{
|
||||
Common.hostImplementation = new HostOne();
|
||||
|
||||
Common.callback = () -> Common.callbackSet = 1;
|
||||
|
||||
/*
|
||||
if (new HostExtends().getYou().extendOnly != 1)
|
||||
{
|
||||
Sys.println("extend-overide type failed");
|
||||
Sys.exit(-1);
|
||||
}
|
||||
*/
|
||||
|
||||
Host.main();
|
||||
Sys.println("TestStatus: " + Common.status );
|
||||
if (Common.status!="ok")
|
||||
{
|
||||
Sys.println("failed");
|
||||
Sys.exit(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (HostOne.called!=2)
|
||||
{
|
||||
Sys.println("No client implementation call - failed");
|
||||
Sys.exit(-1);
|
||||
}
|
||||
|
||||
if (Common.clientImplementation==null)
|
||||
{
|
||||
Sys.println("No client implementation - failed");
|
||||
Sys.exit(-1);
|
||||
}
|
||||
if (Common.clientImplementation.getOne()!=1)
|
||||
{
|
||||
Sys.println("Bad client Int implementation - failed");
|
||||
Sys.exit(-1);
|
||||
}
|
||||
if (Common.clientImplementation.getOneString()!="1")
|
||||
{
|
||||
Sys.println("Bad client String implementation - failed");
|
||||
Sys.exit(-1);
|
||||
}
|
||||
|
||||
var hostBase:HostBase = Type.createInstance(Type.resolveClass("ClientExtends2"),[]);
|
||||
|
||||
if (!hostBase.testUpdateOverride())
|
||||
{
|
||||
Sys.println("Bad update override");
|
||||
Sys.exit(-1);
|
||||
}
|
||||
|
||||
Common.callback();
|
||||
if (Common.callbackSet!=2)
|
||||
{
|
||||
Sys.println("Bad cppia closure");
|
||||
Sys.exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
59
Kha/Backends/Kinc-hxcpp/khacpp/test/cppia/HostBase.hx
Normal file
59
Kha/Backends/Kinc-hxcpp/khacpp/test/cppia/HostBase.hx
Normal file
@ -0,0 +1,59 @@
|
||||
#if (hxcpp_api_level>=400)
|
||||
import cpp.Native;
|
||||
#end
|
||||
|
||||
class HostBase implements IHostInterface
|
||||
{
|
||||
static var hostInit = 10;
|
||||
public static var hostBool0 = true;
|
||||
public static var hostBool1 = false;
|
||||
public static var hostBool2 = true;
|
||||
public static var hostBool3 = false;
|
||||
|
||||
var floatVal:Float;
|
||||
var pointerSrc:cpp.Star<Int>;
|
||||
var pointerDest:cpp.Star<Int>;
|
||||
|
||||
public function new()
|
||||
{
|
||||
floatVal = 1.25;
|
||||
#if (hxcpp_api_level>=400)
|
||||
pointerSrc = Native.malloc( Native.sizeof(Int) );
|
||||
Native.set(pointerSrc,4);
|
||||
pointerDest = null;
|
||||
#end
|
||||
}
|
||||
|
||||
public function getDestVal() : Int
|
||||
{
|
||||
#if (hxcpp_api_level>=400)
|
||||
if (pointerDest==null)
|
||||
return -1;
|
||||
return Native.get(pointerDest);
|
||||
#else
|
||||
return 4;
|
||||
#end
|
||||
}
|
||||
|
||||
public function getYou() : HostBase
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public function testUpdateOverride() : Bool
|
||||
{
|
||||
return update()=="ClientExtends2 update";
|
||||
}
|
||||
|
||||
|
||||
public function getVal() return floatVal;
|
||||
|
||||
public function getGeneration() return 0;
|
||||
|
||||
public function update() return "HostBase update";
|
||||
|
||||
// IHostInteface
|
||||
public function hostImplOnly(i:Int, s:String, f:Float) : String return i+s+f;
|
||||
public function whoStartedYou() return "HostBase";
|
||||
public function whoOverridesYou() return "No one";
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
// Same as IHostInterface, but not implemented in host
|
||||
interface IClientHostInterface extends IHostInterface
|
||||
{
|
||||
public function whoAreYou() : String;
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
interface IClientInterface
|
||||
{
|
||||
// Same as IHostInterface, but not implemented in host
|
||||
public function whoStartedYou() : String;
|
||||
public function whoOverridesYou() : String;
|
||||
public function uniqueClientFunc() : String;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
interface IHostInterface
|
||||
{
|
||||
public function hostImplOnly(i:Int, s:String, f:Float) : String;
|
||||
public function whoStartedYou() : String;
|
||||
public function whoOverridesYou() : String;
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
-main Client
|
||||
-D dll_import=host_classes.info
|
||||
-cppia bin/client.cppia
|
||||
-cp ../unit
|
@ -0,0 +1,6 @@
|
||||
-main CppiaHost
|
||||
-D scriptable
|
||||
-D dll_export=host_classes.info
|
||||
-dce no
|
||||
-cpp bin
|
||||
-cp ../unit
|
@ -0,0 +1,7 @@
|
||||
package pack;
|
||||
|
||||
interface HostInterface
|
||||
{
|
||||
public function getOne() : Int;
|
||||
public function getOneString() : String;
|
||||
}
|
45
Kha/Backends/Kinc-hxcpp/khacpp/test/debugger/App.hx
Normal file
45
Kha/Backends/Kinc-hxcpp/khacpp/test/debugger/App.hx
Normal file
@ -0,0 +1,45 @@
|
||||
|
||||
class App
|
||||
{
|
||||
public static var hasRunBreakMe = false;
|
||||
public static var hasRunBreakMe2 = false;
|
||||
|
||||
function breakMe()
|
||||
{
|
||||
hasRunBreakMe = true;
|
||||
}
|
||||
|
||||
function breakMe2() hasRunBreakMe2 = true;
|
||||
|
||||
|
||||
public function new()
|
||||
{
|
||||
breakMe();
|
||||
breakMe2();
|
||||
Lines.lineStep();
|
||||
}
|
||||
|
||||
public static function main()
|
||||
{
|
||||
TestDebugger.setup();
|
||||
|
||||
new App();
|
||||
|
||||
if (!TestDebugger.finished)
|
||||
{
|
||||
Sys.println("Not all breakpoints triggered");
|
||||
Sys.exit(-1);
|
||||
}
|
||||
else if (!TestDebugger.ok)
|
||||
{
|
||||
Sys.println("Some debugger checks failed");
|
||||
Sys.exit(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Sys.println("All good!");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
20
Kha/Backends/Kinc-hxcpp/khacpp/test/debugger/Lines.hx
Normal file
20
Kha/Backends/Kinc-hxcpp/khacpp/test/debugger/Lines.hx
Normal file
@ -0,0 +1,20 @@
|
||||
class Lines // line 1
|
||||
{ // line 2
|
||||
public static var line = -1; // line 3
|
||||
// line 4
|
||||
public static function lineStep() // line 5
|
||||
{ // line 6
|
||||
line = 7; // line 7;
|
||||
callFunction(); // 8
|
||||
line = 9; // line 9;
|
||||
callFunction(); // 10
|
||||
// 11
|
||||
line = 12; // 12
|
||||
} // line 13
|
||||
// 14
|
||||
public static function callFunction() // 15
|
||||
{ // 16
|
||||
// 17
|
||||
line = 18;
|
||||
}
|
||||
}
|
156
Kha/Backends/Kinc-hxcpp/khacpp/test/debugger/TestDebugger.hx
Normal file
156
Kha/Backends/Kinc-hxcpp/khacpp/test/debugger/TestDebugger.hx
Normal file
@ -0,0 +1,156 @@
|
||||
import cpp.vm.Debugger;
|
||||
#if haxe4
|
||||
import sys.thread.Thread;
|
||||
#else
|
||||
import cpp.vm.Thread;
|
||||
#end
|
||||
|
||||
typedef DebuggerContext = { className : String,
|
||||
functionName : String,
|
||||
fileName : String,
|
||||
lineNumber : Int };
|
||||
|
||||
typedef DebuggerTest = { setup:Void->Void,
|
||||
test:DebuggerContext->Bool,
|
||||
name:String,
|
||||
resume:Int->Void };
|
||||
|
||||
class TestDebugger
|
||||
{
|
||||
public static var ok = true;
|
||||
public static var finished = false;
|
||||
static var jobs:Array<DebuggerTest>;
|
||||
static var currentTest:DebuggerContext->Bool;
|
||||
static var currentName:String;
|
||||
static var currentResume:Void->Void;
|
||||
|
||||
|
||||
public static function setup()
|
||||
{
|
||||
Debugger.enableCurrentThreadDebugging(false);
|
||||
var mainThread = Thread.current();
|
||||
Thread.create( function() {
|
||||
startDebugger();
|
||||
mainThread.sendMessage("setup");
|
||||
});
|
||||
|
||||
var message = Thread.readMessage(true);
|
||||
Sys.println("Debugger : " + message);
|
||||
Debugger.enableCurrentThreadDebugging(true);
|
||||
|
||||
}
|
||||
|
||||
static function handleThreadEvent(threadNumber : Int, event : Int,
|
||||
stackFrame : Int,
|
||||
className : String,
|
||||
functionName : String,
|
||||
fileName : String, lineNumber : Int)
|
||||
{
|
||||
if (event==Debugger.THREAD_STOPPED)
|
||||
{
|
||||
var ctx = { className:className, functionName:functionName, fileName:fileName, lineNumber:lineNumber };
|
||||
|
||||
if (!currentTest(ctx))
|
||||
{
|
||||
ok = false;
|
||||
Sys.println('Test failed : $currentName - got $ctx');
|
||||
Sys.exit(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextTest(threadNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static function cont(id:Int)
|
||||
{
|
||||
Debugger.continueThreads(-1,1);
|
||||
}
|
||||
|
||||
static function step(id:Int)
|
||||
{
|
||||
Debugger.stepThread(id,Debugger.STEP_INTO,1);
|
||||
}
|
||||
|
||||
|
||||
static function stepOver(id:Int)
|
||||
{
|
||||
Debugger.stepThread(id,Debugger.STEP_OVER,1);
|
||||
}
|
||||
|
||||
|
||||
static function stepOut(id:Int)
|
||||
{
|
||||
Debugger.stepThread(id,Debugger.STEP_OUT,1);
|
||||
}
|
||||
|
||||
static function nextTest(threadId:Int)
|
||||
{
|
||||
var test = jobs.shift();
|
||||
if (test==null)
|
||||
{
|
||||
finished = true;
|
||||
currentName = null;
|
||||
currentTest = null;
|
||||
currentResume = null;
|
||||
Debugger.setEventNotificationHandler(null);
|
||||
cont(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentName = test.name;
|
||||
currentTest = test.test;
|
||||
test.setup();
|
||||
Sys.println(' $currentName...');
|
||||
test.resume(threadId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static function startDebugger()
|
||||
{
|
||||
Debugger.setEventNotificationHandler(handleThreadEvent);
|
||||
jobs = [
|
||||
{ setup:function() Debugger.addClassFunctionBreakpoint("App","breakMe"),
|
||||
test:function(ctx) return !App.hasRunBreakMe,
|
||||
name:"Set function breakpoint App.breakMe",
|
||||
resume:cont },
|
||||
{ setup:function() Debugger.addClassFunctionBreakpoint("App","breakMe2"),
|
||||
test:function(ctx) return App.hasRunBreakMe && !App.hasRunBreakMe2,
|
||||
name:"Set function breakpoint App.breakMe2",
|
||||
resume:cont},
|
||||
{ setup:function() Debugger.addFileLineBreakpoint("Lines.hx",7),
|
||||
test:function(ctx) return Lines.line==-1,
|
||||
name:"Set line breakpoint Lines.hx:7",
|
||||
resume:cont},
|
||||
{ setup:function() { },
|
||||
test:function(ctx) return Lines.line==7,
|
||||
name:"Step from Lines.hx:7",
|
||||
resume:step},
|
||||
{ setup:function() { },
|
||||
test:function(ctx) return Lines.line==18,
|
||||
name:"Step over callFunction",
|
||||
resume:stepOver},
|
||||
{ setup:function() { },
|
||||
test:function(ctx) return Lines.line==9,
|
||||
name:"Step over line 9",
|
||||
resume:step},
|
||||
{ setup:function() { },
|
||||
test:function(ctx) return Lines.line==9,
|
||||
name:"step into callFunction",
|
||||
resume:step},
|
||||
{ setup:function() { },
|
||||
test:function(ctx) return Lines.line==18,
|
||||
name:"step out of callFunction",
|
||||
resume:stepOut },
|
||||
{ setup:function() { },
|
||||
test:function(ctx) return Lines.line==12,
|
||||
name:"step out of Lines",
|
||||
resume:stepOut },
|
||||
|
||||
|
||||
];
|
||||
nextTest(-1);
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
-main App
|
||||
-cpp bin
|
||||
-D hxcpp_debugger
|
||||
-D HXCPP_DEBUGGER
|
||||
-debug
|
||||
-cp ../unit
|
@ -0,0 +1,10 @@
|
||||
package api;
|
||||
|
||||
@:nativeGen
|
||||
@:structAccess
|
||||
class HaxeApi
|
||||
{
|
||||
@:keep
|
||||
public static function createBase( ) : HaxeObject return new impl.HaxeImpl();
|
||||
}
|
||||
|
@ -0,0 +1,12 @@
|
||||
package api;
|
||||
|
||||
@:nativeGen
|
||||
interface HaxeObject
|
||||
{
|
||||
public function getName( ):cpp.StdString;
|
||||
public function setName( inName:cpp.StdStringRef ) : Void;
|
||||
public function createChild() : HaxeObject;
|
||||
public function printInt(x:Int):Void;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,4 @@
|
||||
-cpp gen-externs
|
||||
-D static_link
|
||||
api.HaxeApi
|
||||
-cp ../unit
|
@ -0,0 +1,44 @@
|
||||
package impl;
|
||||
|
||||
import api.HaxeObject;
|
||||
|
||||
@:keep
|
||||
class HaxeImpl implements HaxeObject
|
||||
{
|
||||
var parentName:String;
|
||||
var name:String;
|
||||
var haxeObject:HaxeObject;
|
||||
|
||||
public function new(?inParent:HaxeImpl)
|
||||
{
|
||||
haxeObject = null;
|
||||
parentName = inParent==null ? "" : inParent.name;
|
||||
if (haxeObject==null)
|
||||
haxeObject = this;
|
||||
}
|
||||
|
||||
public function getName( ):cpp.StdString
|
||||
{
|
||||
return cpp.StdString.ofString(name);
|
||||
}
|
||||
|
||||
@:unreflective
|
||||
public function setName( inName:cpp.StdStringRef ) : Void
|
||||
{
|
||||
name = inName.toString();
|
||||
}
|
||||
|
||||
public function createChild() : HaxeObject
|
||||
{
|
||||
var child = new HaxeImpl(this);
|
||||
return child;
|
||||
}
|
||||
|
||||
public function printInt(x:Int):Void
|
||||
{
|
||||
Sys.println( Std.string(x) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
15
Kha/Backends/Kinc-hxcpp/khacpp/test/extern-use/Build.xml
Normal file
15
Kha/Backends/Kinc-hxcpp/khacpp/test/extern-use/Build.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<xml>
|
||||
<files id="myfiles">
|
||||
<compilerflag value="-I${HXCPP}/include"/>
|
||||
<compilerflag value="-I../extern-lib/gen-externs/include"/>
|
||||
<file name="Main.cpp" />
|
||||
</files>
|
||||
|
||||
<target id="default" tool="linker" toolid="exe" output="ExternUse">
|
||||
<files id="myfiles"/>
|
||||
|
||||
<libpath name="../extern-lib/gen-externs" />
|
||||
<lib base="liboutput" />
|
||||
</target>
|
||||
|
||||
</xml>
|
73
Kha/Backends/Kinc-hxcpp/khacpp/test/extern-use/Main.cpp
Normal file
73
Kha/Backends/Kinc-hxcpp/khacpp/test/extern-use/Main.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <hx/Native.h>
|
||||
#include <api/HaxeObject.h>
|
||||
#include <api/HaxeApi.h>
|
||||
|
||||
|
||||
struct MyStruct
|
||||
{
|
||||
hx::Ref<api::HaxeObject *> haxeRef;
|
||||
};
|
||||
|
||||
extern void __hxcpp_collect(bool inMajor);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
MyStruct *myStruct = new MyStruct();
|
||||
|
||||
|
||||
const char *err = hx::Init();
|
||||
if (err)
|
||||
{
|
||||
printf("Could not initialize library: %s\n", err);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
hx::NativeAttach autoAttach;
|
||||
|
||||
api::HaxeObject *obj = api::HaxeApi::createBase();
|
||||
obj->setName("child");
|
||||
|
||||
myStruct->haxeRef = obj;
|
||||
obj->setName("Name");
|
||||
|
||||
api::HaxeObject *child = obj->createChild();
|
||||
}
|
||||
|
||||
{
|
||||
hx::NativeAttach autoAttach;
|
||||
__hxcpp_collect(true);
|
||||
}
|
||||
|
||||
{
|
||||
hx::NativeAttach autoAttach;
|
||||
if (myStruct->haxeRef->getName()!="Name")
|
||||
{
|
||||
printf("Could not get value back (%s)\n", myStruct->haxeRef->getName().c_str() );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
hx::NativeAttach autoAttach0;
|
||||
hx::NativeAttach autoAttach1;
|
||||
hx::NativeAttach autoAttach2;
|
||||
hx::NativeAttach autoAttach3;
|
||||
if (hx::GcGetThreadAttachedCount()!=4)
|
||||
{
|
||||
printf("Bad attach count\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (hx::GcGetThreadAttachedCount()!=0)
|
||||
{
|
||||
printf("Bad clear attach count\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("all good\n");
|
||||
return 0;
|
||||
}
|
||||
|
66
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/TestIntHash.hx
Normal file
66
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/TestIntHash.hx
Normal file
@ -0,0 +1,66 @@
|
||||
class TestIntHash extends haxe.unit.TestCase
|
||||
{
|
||||
function spamAlot()
|
||||
{
|
||||
var values = new Array< Null<Int> >();
|
||||
values[0] = null;
|
||||
var h = new Map<Int,Int>();
|
||||
|
||||
for(i in 0...2000)
|
||||
{
|
||||
for(j in 0...2000)
|
||||
{
|
||||
var idx = Std.int(Math.random()*2999);
|
||||
if (h.get(idx)!=values[idx])
|
||||
throw "Bad value";
|
||||
if ( (i % 4)== 1 || Math.random()>0.5 )
|
||||
{
|
||||
if (h.remove(idx) != (values[idx]!=null))
|
||||
throw "Error in remove!";
|
||||
values[idx] = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
h.set(idx,j);
|
||||
values[idx] = j;
|
||||
}
|
||||
}
|
||||
var keys = h.keys();
|
||||
var keyed = new Array<Bool>();
|
||||
for(i in 0...values.length)
|
||||
keyed[i] = false;
|
||||
for( key in h.keys())
|
||||
keyed[ key ] = true;
|
||||
for(i in 0...values.length)
|
||||
if (keyed[i]!=(values[i]!=null))
|
||||
throw "Bad value";
|
||||
|
||||
var valued = new Array<Int>();
|
||||
for( val in h.iterator())
|
||||
valued[val]++;
|
||||
|
||||
for(val in values)
|
||||
if (val!=null)
|
||||
{
|
||||
if (valued[val]<1)
|
||||
throw "Not valued!";
|
||||
valued[val]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function test()
|
||||
{
|
||||
var err = "";
|
||||
try
|
||||
{
|
||||
spamAlot();
|
||||
}
|
||||
catch(e:String)
|
||||
{
|
||||
err = e;
|
||||
}
|
||||
assertTrue(err=="");
|
||||
}
|
||||
|
||||
}
|
49
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/TestKeywords.hx
Normal file
49
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/TestKeywords.hx
Normal file
@ -0,0 +1,49 @@
|
||||
private enum GnarlyEnum
|
||||
{
|
||||
e0;
|
||||
GnarlyEnum;
|
||||
narlyEnum;
|
||||
Dynamic;
|
||||
getFixed(i:Int);
|
||||
getInt;
|
||||
init(i:Int);
|
||||
String;
|
||||
index(i:Int);
|
||||
const;
|
||||
super(i:Int);
|
||||
tag(i:Int);
|
||||
getTag(i:Int);
|
||||
getObject(i:Int);
|
||||
}
|
||||
|
||||
class TestKeywords extends haxe.unit.TestCase
|
||||
{
|
||||
public function new() super();
|
||||
|
||||
//public function getGnarly() { return GnarlyEnum.super(1); }
|
||||
public function getGnarly() { return Dynamic; }
|
||||
|
||||
public function testEnum()
|
||||
{
|
||||
var count =
|
||||
switch( getGnarly() )
|
||||
{
|
||||
case e0: 1;
|
||||
//case GnarlyEnum: 1;
|
||||
case narlyEnum: 1;
|
||||
case Dynamic: 3;
|
||||
case getFixed(i): 1;
|
||||
case getInt: 1;
|
||||
case init(i): 1;
|
||||
case String: 1;
|
||||
case index(i): 1;
|
||||
case const: 1;
|
||||
//case GnarlyEnum.super(i): 2;
|
||||
case tag(i): 1;
|
||||
case getTag(i): 1;
|
||||
case getObject(i): 1;
|
||||
default: 0;
|
||||
}
|
||||
assertTrue(count==3);
|
||||
}
|
||||
}
|
76
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/TestMain.hx
Normal file
76
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/TestMain.hx
Normal file
@ -0,0 +1,76 @@
|
||||
package;
|
||||
import gc.TestGC;
|
||||
|
||||
class TestMain #if nme extends nme.display.Sprite #end {
|
||||
|
||||
static function runTests():Int
|
||||
{
|
||||
var passes = 1;
|
||||
#if !nme
|
||||
var args = Sys.args();
|
||||
if (args.length>0)
|
||||
passes = Std.parseInt(args[0]);
|
||||
#end
|
||||
|
||||
var r = new haxe.unit.TestRunner();
|
||||
r.add(new TestTypes());
|
||||
r.add(new TestKeywords());
|
||||
r.add(new TestSort());
|
||||
r.add(new TestGC());
|
||||
#if !nme
|
||||
r.add(new gc.TestGCThreaded());
|
||||
#end
|
||||
r.add(new TestIntHash());
|
||||
r.add(new TestStringHash());
|
||||
r.add(new TestObjectHash());
|
||||
r.add(new TestWeakHash());
|
||||
#if !nme
|
||||
r.add(new file.TestFile());
|
||||
#end
|
||||
|
||||
#if cpp
|
||||
r.add(new native.TestFinalizer());
|
||||
#end
|
||||
|
||||
for(i in 0...passes)
|
||||
{
|
||||
var t0 = haxe.Timer.stamp();
|
||||
var success = r.run();
|
||||
trace(" Time : " + (haxe.Timer.stamp()-t0)*1000 );
|
||||
if (!success)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if nme
|
||||
var frameCount = 0;
|
||||
var tf:nme.text.TextField;
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
tf = new nme.text.TextField();
|
||||
tf.text="RUN...";
|
||||
addChild(tf);
|
||||
addEventListener( nme.events.Event.ENTER_FRAME, onFrame );
|
||||
}
|
||||
|
||||
function onFrame(_)
|
||||
{
|
||||
var err = runTests();
|
||||
tf.text = "" + (++frameCount);
|
||||
stage.opaqueBackground = err==0 ? 0xff00ff00: 0xffff0000;
|
||||
|
||||
}
|
||||
|
||||
static function endTest(error:Int) trace(error==0 ? "All tests OK" : "Tests Failed!");
|
||||
#else
|
||||
public static function main()
|
||||
{
|
||||
Sys.exit(runTests());
|
||||
}
|
||||
public static function endTest(error:Int) Sys.exit(error);
|
||||
#end
|
||||
}
|
||||
|
||||
|
91
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/TestObjectHash.hx
Normal file
91
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/TestObjectHash.hx
Normal file
@ -0,0 +1,91 @@
|
||||
class ObjectData
|
||||
{
|
||||
public var id:Int;
|
||||
public function new(inId:Int) id = inId;
|
||||
}
|
||||
|
||||
|
||||
class TestObjectHash extends haxe.unit.TestCase
|
||||
{
|
||||
function spamAlot()
|
||||
{
|
||||
var values = new Array< Null<Int> >();
|
||||
values[0] = null;
|
||||
var h = new Map<ObjectData,Int>();
|
||||
var idxToKey = new Array<ObjectData>();
|
||||
for(idx in 0...3000)
|
||||
idxToKey[idx] = new ObjectData(idx);
|
||||
|
||||
for(i in 0...2000)
|
||||
{
|
||||
for(j in 0...2000)
|
||||
{
|
||||
var idxInt = Std.int(Math.random()*2999);
|
||||
var idx = idxToKey[idxInt];
|
||||
if (h.get(idx)!=values[idxInt])
|
||||
{
|
||||
throw "Bad value";
|
||||
}
|
||||
if ( (i % 4)== 1 || Math.random()>0.5 )
|
||||
{
|
||||
if (h.remove(idx) != (values[idxInt]!=null))
|
||||
{
|
||||
trace("Bad remove");
|
||||
throw "Error in remove!";
|
||||
}
|
||||
values[idxInt] = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
h.set(idx,j);
|
||||
values[idxInt] = j;
|
||||
}
|
||||
}
|
||||
var keys = h.keys();
|
||||
var keyed = new Array<Bool>();
|
||||
for(i in 0...values.length)
|
||||
keyed[i] = false;
|
||||
for( key in h.keys())
|
||||
{
|
||||
var idxInt = key.id;
|
||||
keyed[ idxInt ] = true;
|
||||
}
|
||||
for(i in 0...values.length)
|
||||
if (keyed[i]!=(values[i]!=null))
|
||||
throw "Bad value";
|
||||
|
||||
var valued = new Array<Int>();
|
||||
#if neko
|
||||
valued[3000]=0;
|
||||
for(i in 0...3000)
|
||||
valued[i] = 0;
|
||||
#end
|
||||
for( val in h.iterator())
|
||||
valued[val]++;
|
||||
|
||||
for(val in values)
|
||||
if (val!=null)
|
||||
{
|
||||
if (valued[val]<1)
|
||||
throw "Not valued!";
|
||||
valued[val]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function test()
|
||||
{
|
||||
var err = "";
|
||||
try
|
||||
{
|
||||
spamAlot();
|
||||
}
|
||||
catch(e:Dynamic)
|
||||
{
|
||||
trace(e);
|
||||
err = e;
|
||||
}
|
||||
assertTrue(err=="");
|
||||
}
|
||||
|
||||
}
|
60
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/TestSort.hx
Normal file
60
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/TestSort.hx
Normal file
@ -0,0 +1,60 @@
|
||||
class SortData
|
||||
{
|
||||
public var value:Int;
|
||||
public var id:Int;
|
||||
static var ids = 0;
|
||||
|
||||
public function new()
|
||||
{
|
||||
value = Std.int(Math.random()*500);
|
||||
id = ids++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TestSort extends haxe.unit.TestCase
|
||||
{
|
||||
public function testObjects()
|
||||
{
|
||||
var tests = new Array<SortData>();
|
||||
for(i in 0...100000)
|
||||
tests.push( new SortData() );
|
||||
|
||||
var sorted = tests.copy();
|
||||
sorted.sort( function(a,b) return a.value - b.value );
|
||||
|
||||
for(i in 1...sorted.length)
|
||||
{
|
||||
if (sorted[i].value < sorted[i-1].value)
|
||||
throw "Index out of order";
|
||||
if (sorted[i].value == sorted[i-1].value &&
|
||||
sorted[i].id <= sorted[i-1].id )
|
||||
throw "Not stable sort";
|
||||
}
|
||||
|
||||
var sorted = tests.copy();
|
||||
var compares = 0;
|
||||
sorted.sort( function(a,b) {
|
||||
// Churn some GC
|
||||
var array = new Array<Int>();
|
||||
compares++;
|
||||
array.push(a.value);
|
||||
array.push(b.value);
|
||||
return array[0] < array[1] ? 1 : array[0] > array[1] ? -1 : 0;
|
||||
});
|
||||
|
||||
//Sys.println("\nCompares per log elements:" + (compares/(tests.length*Math.log(tests.length))));
|
||||
|
||||
for(i in 1...sorted.length)
|
||||
{
|
||||
if (sorted[i].value > sorted[i-1].value)
|
||||
throw "Index out of order";
|
||||
if (sorted[i].value == sorted[i-1].value &&
|
||||
sorted[i].id <= sorted[i-1].id )
|
||||
throw "Not stable sort";
|
||||
}
|
||||
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
88
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/TestStringHash.hx
Normal file
88
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/TestStringHash.hx
Normal file
@ -0,0 +1,88 @@
|
||||
class TestStringHash extends haxe.unit.TestCase
|
||||
{
|
||||
function spamAlot()
|
||||
{
|
||||
var values = new Array< Null<Int> >();
|
||||
values[0] = null;
|
||||
var h = new Map<String,Int>();
|
||||
var idxToKey = new Array<String>();
|
||||
for(idx in 0...3000)
|
||||
idxToKey[idx] = Std.string(idx);
|
||||
|
||||
for(i in 0...2000)
|
||||
{
|
||||
for(j in 0...2000)
|
||||
{
|
||||
var idxInt = Std.int(Math.random()*2999);
|
||||
var idx = idxToKey[idxInt];
|
||||
if (h.get(idx)!=values[idxInt])
|
||||
{
|
||||
throw "Bad value";
|
||||
}
|
||||
if ( (i % 4)== 1 || Math.random()>0.5 )
|
||||
{
|
||||
if (h.remove(idx) != (values[idxInt]!=null))
|
||||
{
|
||||
trace("Bad remove");
|
||||
throw "Error in remove!";
|
||||
}
|
||||
values[idxInt] = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
h.set(idx,j);
|
||||
values[idxInt] = j;
|
||||
}
|
||||
}
|
||||
var arr = [0,1,2];
|
||||
var keys = h.keys();
|
||||
// Empty allocations can mess with the GC nursery
|
||||
cpp.NativeArray.setSize(arr,0);
|
||||
cpp.NativeArray.setSize(arr,3);
|
||||
var keyed = new Array<Bool>();
|
||||
for(i in 0...values.length)
|
||||
keyed[i] = false;
|
||||
for( key in h.keys())
|
||||
{
|
||||
var idxInt = Std.parseInt(key);
|
||||
keyed[ idxInt ] = true;
|
||||
}
|
||||
for(i in 0...values.length)
|
||||
if (keyed[i]!=(values[i]!=null))
|
||||
throw "Bad value";
|
||||
|
||||
var valued = new Array<Int>();
|
||||
#if neko
|
||||
valued[3000]=0;
|
||||
for(i in 0...3000)
|
||||
valued[i] = 0;
|
||||
#end
|
||||
for( val in h.iterator())
|
||||
valued[val]++;
|
||||
|
||||
for(val in values)
|
||||
if (val!=null)
|
||||
{
|
||||
if (valued[val]<1)
|
||||
throw "Not valued!";
|
||||
valued[val]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function test()
|
||||
{
|
||||
var err = "";
|
||||
try
|
||||
{
|
||||
spamAlot();
|
||||
}
|
||||
catch(e:Dynamic)
|
||||
{
|
||||
trace(e);
|
||||
err = e;
|
||||
}
|
||||
assertTrue(err=="");
|
||||
}
|
||||
|
||||
}
|
49
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/TestTypes.hx
Normal file
49
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/TestTypes.hx
Normal file
@ -0,0 +1,49 @@
|
||||
class TestTypes extends haxe.unit.TestCase
|
||||
{
|
||||
var i0:Int = 1;
|
||||
var i1:cpp.Int32 = 1;
|
||||
var i2:cpp.UInt32 = 1;
|
||||
var i3:cpp.Int64 = 1;
|
||||
var i4:cpp.UInt64 = 1;
|
||||
var i5:cpp.Int8 = 1;
|
||||
var i6:cpp.UInt8 = 1;
|
||||
var i7:cpp.Int16 = 1;
|
||||
var i8:cpp.UInt16 = 1;
|
||||
|
||||
public function new() super();
|
||||
|
||||
function stringToCcs(string:String) : cpp.ConstCharStar
|
||||
{
|
||||
return string;
|
||||
}
|
||||
|
||||
function ccsToString(ccs:cpp.ConstCharStar) : String
|
||||
{
|
||||
return ccs;
|
||||
}
|
||||
|
||||
function ccsToStringCast(ccs:cpp.ConstCharStar) : String
|
||||
{
|
||||
return cast ccs;
|
||||
}
|
||||
|
||||
public function testConstCharStar()
|
||||
{
|
||||
var ccs = stringToCcs("hello");
|
||||
assertTrue( ccsToString(ccs)=="hello" );
|
||||
assertTrue( ccsToStringCast(ccs)=="hello" );
|
||||
}
|
||||
|
||||
public function testDynamic()
|
||||
{
|
||||
var d:Dynamic = this;
|
||||
assertTrue(d.i0==1);
|
||||
assertTrue(d.i1==1);
|
||||
assertTrue(d.i2==1);
|
||||
assertTrue(d.i3==1);
|
||||
assertTrue(d.i4==1);
|
||||
assertTrue(d.i5==1);
|
||||
assertTrue(d.i6==1);
|
||||
assertTrue(d.i7==1);
|
||||
}
|
||||
}
|
93
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/TestWeakHash.hx
Normal file
93
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/TestWeakHash.hx
Normal file
@ -0,0 +1,93 @@
|
||||
import haxe.ds.WeakMap;
|
||||
|
||||
class WeakObjectData
|
||||
{
|
||||
public var id:Int;
|
||||
public function new(inId:Int) id = inId;
|
||||
public function toString() return "Data " + id;
|
||||
}
|
||||
|
||||
|
||||
class TestWeakHash extends haxe.unit.TestCase
|
||||
{
|
||||
var retained:Array<WeakObjectData>;
|
||||
|
||||
function createMap(inCount:Int)
|
||||
{
|
||||
retained = [];
|
||||
var map = new WeakMap<WeakObjectData,Int>();
|
||||
for(i in 0...inCount)
|
||||
{
|
||||
var obj = new WeakObjectData(i);
|
||||
if ( (i&1)==0 )
|
||||
retained.push(obj);
|
||||
map.set(obj,i);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
function createMapDeep(inDepth:Int, inCount:Int)
|
||||
{
|
||||
if (inDepth<1)
|
||||
return createMap(inCount);
|
||||
|
||||
return createMapDeep(inDepth-1, inCount);
|
||||
}
|
||||
|
||||
function checkMap(map:WeakMap<WeakObjectData,Int>, expect:Int)
|
||||
{
|
||||
var valid = 0;
|
||||
var oddFound = 0;
|
||||
for(k in map.keys())
|
||||
{
|
||||
if( (k.id&1)!= 0)
|
||||
{
|
||||
oddFound ++;
|
||||
//throw "Odd retained " + k.id;
|
||||
}
|
||||
else
|
||||
valid++;
|
||||
}
|
||||
// There may be one or two values lurking on the stack, which is conservatively marked
|
||||
if (oddFound>2)
|
||||
trace("Too many odd values retained " + oddFound);
|
||||
if (!(valid>=expect && valid<expect+2))
|
||||
trace("WeakHash invalid range "+ expect + "..." + valid + "..." + (expect+2) );
|
||||
assertTrue(valid>=expect && valid<expect+2);
|
||||
}
|
||||
function deepCheckMap(inDepth:Int, map:WeakMap<WeakObjectData,Int>, expect:Int)
|
||||
{
|
||||
if (inDepth<1)
|
||||
checkMap(map,expect);
|
||||
else
|
||||
deepCheckMap(inDepth-1, map, expect);
|
||||
}
|
||||
|
||||
function deepClearRetained(inRecurse:Int)
|
||||
{
|
||||
if (inRecurse>0)
|
||||
deepClearRetained(inRecurse-1);
|
||||
else
|
||||
retained = [];
|
||||
}
|
||||
|
||||
public function test()
|
||||
{
|
||||
var err = "";
|
||||
try
|
||||
{
|
||||
var map = createMapDeep(20,1000);
|
||||
cpp.vm.Gc.run(true);
|
||||
deepCheckMap(10,map,500);
|
||||
deepClearRetained(10);
|
||||
cpp.vm.Gc.run(true);
|
||||
checkMap(map,0);
|
||||
}
|
||||
catch(e:String)
|
||||
{
|
||||
trace(e);
|
||||
err = e;
|
||||
}
|
||||
assertTrue(err=="");
|
||||
}
|
||||
|
||||
}
|
5
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/compile.hxml
Normal file
5
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/compile.hxml
Normal file
@ -0,0 +1,5 @@
|
||||
-cpp bin
|
||||
-main TestMain
|
||||
-resource TestMain.hx
|
||||
-D HXCPP_GC_GENERATIONAL
|
||||
-cp ../unit
|
34
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/compile_nme.nmml
Normal file
34
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/compile_nme.nmml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<project>
|
||||
|
||||
<meta
|
||||
title="GCTests"
|
||||
package="org.haxe.hxcpp.gctest"
|
||||
version="1.0.0"
|
||||
company="haxefoundation"
|
||||
/>
|
||||
|
||||
<app
|
||||
file="TestMain"
|
||||
main="TestMain"
|
||||
/>
|
||||
|
||||
<window
|
||||
width="640"
|
||||
height="480"
|
||||
orientation="landscape"
|
||||
fps="60"
|
||||
background="0xeeeeee"
|
||||
require_shaders="true"
|
||||
resizable="true"
|
||||
hardware="true"
|
||||
/>
|
||||
|
||||
<haxelib name="nme" />
|
||||
<haxedef name="HXCPP_GC_GENERATIONAL" />
|
||||
<haxedef name="HXCPP_DEBUG_LINK" />
|
||||
<haxeflag name="-resource TestMain.hx" />
|
||||
<cp path="../unit" />
|
||||
|
||||
</project>
|
||||
|
10
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/file/TestFile.hx
Normal file
10
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/file/TestFile.hx
Normal file
@ -0,0 +1,10 @@
|
||||
package file;
|
||||
|
||||
class TestFile extends haxe.unit.TestCase
|
||||
{
|
||||
public function testGetContentEmptyFile()
|
||||
{
|
||||
assertEquals('', sys.io.File.getContent('./file/empty.txt'));
|
||||
}
|
||||
|
||||
}
|
102
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/gc/TestBigStack.hx
Executable file
102
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/gc/TestBigStack.hx
Executable file
@ -0,0 +1,102 @@
|
||||
package gc;
|
||||
|
||||
class TestBigStack
|
||||
{
|
||||
var refs:Array<TestBigStack>;
|
||||
var self:TestBigStack;
|
||||
|
||||
public function new()
|
||||
{
|
||||
refs = [];
|
||||
self = this;
|
||||
}
|
||||
|
||||
function check()
|
||||
{
|
||||
if (self!=this)
|
||||
throw("Bad self reference");
|
||||
}
|
||||
|
||||
|
||||
function checkRec()
|
||||
{
|
||||
if (self!=this)
|
||||
throw("Bad self reference");
|
||||
for(r in refs)
|
||||
r.checkRec();
|
||||
}
|
||||
|
||||
function runRec(depth:Int)
|
||||
{
|
||||
var d = depth-1;
|
||||
if (d==0)
|
||||
return this;
|
||||
var b0 = new TestBigStack().runRec(d);
|
||||
var b1 = new TestBigStack().runRec(d);
|
||||
var b2 = new TestBigStack().runRec(d);
|
||||
var b3 = new TestBigStack().runRec(d);
|
||||
var b4 = new TestBigStack().runRec(d);
|
||||
var b5 = new TestBigStack().runRec(d);
|
||||
var b6 = new TestBigStack().runRec(d);
|
||||
var b7 = new TestBigStack().runRec(d);
|
||||
var b8 = new TestBigStack().runRec(d);
|
||||
var b9 = new TestBigStack().runRec(d);
|
||||
var b10 = new TestBigStack().runRec(d);
|
||||
var b11 = new TestBigStack().runRec(d);
|
||||
var b12 = new TestBigStack().runRec(d);
|
||||
var b13 = new TestBigStack().runRec(d);
|
||||
var b14 = new TestBigStack().runRec(d);
|
||||
var b15 = new TestBigStack().runRec(d);
|
||||
var b16 = new TestBigStack().runRec(d);
|
||||
var b17 = new TestBigStack().runRec(d);
|
||||
var b18 = new TestBigStack().runRec(d);
|
||||
var b19 = new TestBigStack().runRec(d);
|
||||
refs.push(b0);
|
||||
b0.check();
|
||||
b1.check();
|
||||
b2.check();
|
||||
b3.check();
|
||||
b4.check();
|
||||
b5.check();
|
||||
b6.check();
|
||||
b7.check();
|
||||
b8.check();
|
||||
b9.check();
|
||||
b10.check();
|
||||
b11.check();
|
||||
b12.check();
|
||||
b13.check();
|
||||
b14.check();
|
||||
b15.check();
|
||||
b16.check();
|
||||
b17.check();
|
||||
b18.check();
|
||||
b19.check();
|
||||
return this;
|
||||
}
|
||||
|
||||
function run(passes:Int, depth:Int)
|
||||
{
|
||||
for(p in 0...passes)
|
||||
{
|
||||
//if ( (p%1000)==0 )
|
||||
// Sys.println('Pass $p...');
|
||||
refs = [];
|
||||
runRec(depth);
|
||||
checkRec();
|
||||
}
|
||||
}
|
||||
|
||||
public static function test() : Bool
|
||||
{
|
||||
try {
|
||||
var b = new TestBigStack();
|
||||
b.run(5000,5);
|
||||
return true;
|
||||
}
|
||||
catch(e:Dynamic)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
129
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/gc/TestGC.hx
Normal file
129
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/gc/TestGC.hx
Normal file
@ -0,0 +1,129 @@
|
||||
package gc;
|
||||
import haxe.io.Bytes;
|
||||
import cpp.vm.Gc;
|
||||
|
||||
class CustomObject {
|
||||
public function new():Void {}
|
||||
}
|
||||
|
||||
class TestGC extends haxe.unit.TestCase {
|
||||
function createDummy(val:Dynamic):Dynamic {
|
||||
return { dummy: val };
|
||||
}
|
||||
|
||||
function gc():Dynamic {
|
||||
Gc.run(true);
|
||||
return Gc.getNextZombie();
|
||||
}
|
||||
|
||||
/**
|
||||
For avoiding the simple call being optimized in some way.
|
||||
*/
|
||||
function create(f:Void->Void):Void {
|
||||
f();
|
||||
clearStack(10);
|
||||
}
|
||||
|
||||
function clearStack(count:Int, ?nothing:Dynamic):Dynamic
|
||||
{
|
||||
if (count==0)
|
||||
return 0;
|
||||
return clearStack(count-1);
|
||||
}
|
||||
|
||||
|
||||
function createAbc():Void {
|
||||
var object = { test: "abc" };
|
||||
Gc.doNotKill(object);
|
||||
}
|
||||
public function testObject():Void {
|
||||
create(createAbc);
|
||||
var zombie = gc();
|
||||
assertTrue(zombie != null);
|
||||
assertEquals("abc", zombie.test);
|
||||
assertTrue(gc() == null);
|
||||
}
|
||||
|
||||
// Null<int> for numbers < 256 are special cases
|
||||
// Infact, there are no guarantees that Null<Int> will be actual objects in the future
|
||||
/*
|
||||
function create1234():Void {
|
||||
var object:Null<Int> = 1234;
|
||||
Gc.doNotKill(object);
|
||||
};
|
||||
public function testBoxedInt():Void {
|
||||
create(create1234);
|
||||
var zombie:Dynamic = gc();
|
||||
assertTrue(zombie != null);
|
||||
assertEquals(1234, zombie);
|
||||
assertTrue(gc() == null);
|
||||
}
|
||||
*/
|
||||
|
||||
function createFunction():Void {
|
||||
var object = function() return "abc";
|
||||
Gc.doNotKill(object);
|
||||
};
|
||||
public function testFunc():Void {
|
||||
create(createFunction);
|
||||
var zombie = gc();
|
||||
assertTrue(zombie != null);
|
||||
assertEquals("abc", zombie());
|
||||
assertTrue(gc() == null);
|
||||
}
|
||||
|
||||
function createCustom():Void {
|
||||
var object = new CustomObject();
|
||||
Gc.doNotKill(object);
|
||||
};
|
||||
public function testCustomObject():Void {
|
||||
create(createCustom);
|
||||
var zombie = gc();
|
||||
assertTrue(zombie != null);
|
||||
assertTrue(Std.isOfType(zombie, CustomObject));
|
||||
assertTrue(gc() == null);
|
||||
}
|
||||
|
||||
function createBytes():Void {
|
||||
var object = Bytes.alloc(1);
|
||||
Gc.doNotKill(object);
|
||||
};
|
||||
public function testBytes():Void {
|
||||
create(createBytes);
|
||||
var zombie = gc();
|
||||
assertTrue(zombie != null);
|
||||
assertTrue(Std.isOfType(zombie, Bytes));
|
||||
assertTrue(gc() == null);
|
||||
}
|
||||
|
||||
public function testBigStack():Void {
|
||||
assertTrue( TestBigStack.test() );
|
||||
}
|
||||
|
||||
#if !cppia
|
||||
public function testConstStrings():Void {
|
||||
// Const strings void Gc overhead
|
||||
var strings = new Array<String>();
|
||||
strings.push( haxe.Resource.getString("TestMain.hx") );
|
||||
strings.push( "some string" );
|
||||
var chars = "abc123";
|
||||
// Optimization for single chars...
|
||||
for(c in 0...chars.length)
|
||||
strings.push( chars.substr(c,1) );
|
||||
for(string in strings)
|
||||
assertTrue( untyped __global__.__hxcpp_is_const_string(string) );
|
||||
Gc.run(true);
|
||||
for(string in strings)
|
||||
assertTrue( untyped __global__.__hxcpp_is_const_string(string) );
|
||||
|
||||
var strings = new Array<String>();
|
||||
strings.push( haxe.Resource.getString("TestMain.hx").substr(10) );
|
||||
strings.push( "some string" + chars );
|
||||
for(c in 0...chars.length-1)
|
||||
strings.push( chars.substr(c,2) );
|
||||
|
||||
for(string in strings)
|
||||
assertFalse( untyped __global__.__hxcpp_is_const_string(string) );
|
||||
}
|
||||
#end
|
||||
}
|
134
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/gc/TestGCThreaded.hx
Normal file
134
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/gc/TestGCThreaded.hx
Normal file
@ -0,0 +1,134 @@
|
||||
package gc;
|
||||
import haxe.io.Bytes;
|
||||
import haxe.crypto.Md5;
|
||||
import cpp.vm.Gc;
|
||||
import sys.io.File;
|
||||
#if haxe4
|
||||
import sys.thread.Thread;
|
||||
#else
|
||||
import cpp.vm.Thread;
|
||||
#end
|
||||
|
||||
class Wrapper
|
||||
{
|
||||
public var a:Int;
|
||||
public function new(inA:Int) a = inA;
|
||||
}
|
||||
|
||||
|
||||
@:cppInclude("./ZoneTest.cpp")
|
||||
@:depend("./ZoneTest.cpp")
|
||||
class TestGCThreaded extends haxe.unit.TestCase
|
||||
{
|
||||
@:keep
|
||||
static var keepRunning = false;
|
||||
@:keep
|
||||
static var nativeRunning = false;
|
||||
var bigText:String;
|
||||
|
||||
|
||||
override public function setup()
|
||||
{
|
||||
var lines = [ for(i in 0...100000) "abc123\n" ];
|
||||
#if nme
|
||||
bigText = lines.join("");
|
||||
#else
|
||||
File.saveContent( "gc/big.txt", lines.join("") );
|
||||
#end
|
||||
}
|
||||
|
||||
public function testThreadOnce():Void
|
||||
{
|
||||
startNative();
|
||||
doThreadedWork(4,100);
|
||||
stopNative();
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
|
||||
public function testThreadMany():Void
|
||||
{
|
||||
startNative();
|
||||
for(i in 0...10)
|
||||
#if nme
|
||||
doThreadedWork(4,100);
|
||||
#else
|
||||
doThreadedWork(100,100);
|
||||
#end
|
||||
stopNative();
|
||||
assertTrue(true);
|
||||
}
|
||||
|
||||
@:native("nativeLoop")
|
||||
extern static function nativeLoop() : Void;
|
||||
|
||||
function startNative()
|
||||
{
|
||||
Thread.create( () -> {
|
||||
nativeRunning = true;
|
||||
keepRunning = true;
|
||||
nativeLoop();
|
||||
});
|
||||
}
|
||||
function stopNative()
|
||||
{
|
||||
keepRunning = false;
|
||||
while(nativeRunning)
|
||||
Sys.sleep(0.1);
|
||||
}
|
||||
|
||||
function doThreadedWork(numThreads, numWork):Void
|
||||
{
|
||||
var threads:Array<Thread> = makeThreads(numThreads);
|
||||
|
||||
for (i in 0...numWork)
|
||||
threads[i % threads.length].sendMessage('doWork');
|
||||
|
||||
for (i in 0...numThreads)
|
||||
{
|
||||
threads[i].sendMessage('exit');
|
||||
Thread.readMessage(true);
|
||||
}
|
||||
}
|
||||
|
||||
function makeThreads(numThreads:Int):Array<Thread>
|
||||
{
|
||||
#if nme
|
||||
var text:String = bigText;
|
||||
#else
|
||||
var text:String = File.getContent("gc/big.txt");
|
||||
#end
|
||||
var main:Thread = Thread.current();
|
||||
var threads:Array<Thread> = [];
|
||||
for (i in 0...numThreads)
|
||||
{
|
||||
threads.push( Thread.create(function() {
|
||||
while(true) {
|
||||
var message:Dynamic = Thread.readMessage(true);
|
||||
if(message == 'exit')
|
||||
break;
|
||||
else
|
||||
Md5.encode(text);
|
||||
var arrays = new Array<Array<Wrapper>>();
|
||||
for(i in 0...100)
|
||||
{
|
||||
var wrappers = new Array<Wrapper>();
|
||||
arrays.push(wrappers);
|
||||
for(j in 0...1000)
|
||||
wrappers.push( new Wrapper(1) );
|
||||
}
|
||||
var sum = 0;
|
||||
for(a in arrays)
|
||||
for(w in a)
|
||||
sum += w.a;
|
||||
|
||||
assertTrue(sum==100000);
|
||||
}
|
||||
main.sendMessage('done');
|
||||
}) );
|
||||
}
|
||||
return threads;
|
||||
}
|
||||
|
||||
}
|
||||
|
15
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/gc/ZoneTest.cpp
Normal file
15
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/gc/ZoneTest.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
|
||||
void nativeLoop()
|
||||
{
|
||||
while( gc::TestGCThreaded_obj::keepRunning)
|
||||
{
|
||||
|
||||
for(int i=0; i<100; i++)
|
||||
::gc::Wrapper_obj::__alloc( HX_CTX_GET ,1);
|
||||
|
||||
::Sys_obj::sleep(0.01);
|
||||
}
|
||||
gc::TestGCThreaded_obj::nativeRunning = false;
|
||||
}
|
||||
|
||||
|
149
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/native/TestFinalizer.hx
Normal file
149
Kha/Backends/Kinc-hxcpp/khacpp/test/haxe/native/TestFinalizer.hx
Normal file
@ -0,0 +1,149 @@
|
||||
package native;
|
||||
|
||||
@:native("ExternStruct")
|
||||
extern class ExternStruct
|
||||
{
|
||||
@:native("~ExternStruct")
|
||||
public function destroy():Void;
|
||||
|
||||
@:native("new ExternStruct")
|
||||
public static function create():cpp.Pointer<ExternStruct>;
|
||||
}
|
||||
|
||||
|
||||
#if !cppia
|
||||
@:headerCode('
|
||||
struct ExternStruct {
|
||||
ExternStruct() { }
|
||||
~ExternStruct() { }
|
||||
};
|
||||
')
|
||||
class ExternWrapper
|
||||
{
|
||||
var pointer:cpp.Pointer<ExternStruct>;
|
||||
public static var instances:Int = 0;
|
||||
|
||||
public function new()
|
||||
{
|
||||
pointer = ExternStruct.create();
|
||||
instances++;
|
||||
cpp.vm.Gc.setFinalizer(this, cpp.Function.fromStaticFunction(destroy));
|
||||
}
|
||||
|
||||
@:void static public function destroy(ExternWrapper : ExternWrapper) : Void {
|
||||
instances--;
|
||||
ExternWrapper.pointer.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class CustomFinalizable
|
||||
{
|
||||
public static var count = 0;
|
||||
|
||||
public function new()
|
||||
{
|
||||
cpp.vm.Gc.setFinalizer(this, cpp.Function.fromStaticFunction(__finalizeCallback));
|
||||
}
|
||||
|
||||
function __finalize() : Void count++;
|
||||
|
||||
@:void public static function __finalizeCallback(o : CustomFinalizable) : Void
|
||||
{
|
||||
if(o != null)
|
||||
o.__finalize();
|
||||
else
|
||||
Sys.println("Null callback object?");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#end
|
||||
|
||||
|
||||
class MyFinalizable extends cpp.Finalizable
|
||||
{
|
||||
public static var count = 0;
|
||||
|
||||
public function new()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
override public function finalize()
|
||||
{
|
||||
count ++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class TestFinalizer extends haxe.unit.TestCase
|
||||
{
|
||||
|
||||
override public function setup()
|
||||
{
|
||||
MyFinalizable.count = 0;
|
||||
CustomFinalizable.count = 0;
|
||||
}
|
||||
|
||||
#if !cppia
|
||||
function createExternWrapper(i:Int)
|
||||
{
|
||||
if (i<=0)
|
||||
new ExternWrapper();
|
||||
else
|
||||
createExternWrapper(i-1);
|
||||
}
|
||||
|
||||
|
||||
public function testCount()
|
||||
{
|
||||
for(i in 0...10)
|
||||
{
|
||||
createExternWrapper(2);
|
||||
cpp.vm.Gc.run(true);
|
||||
}
|
||||
Sys.println("\nExtern instances remaining:" + ExternWrapper.instances);
|
||||
assertTrue( ExternWrapper.instances < 10 );
|
||||
}
|
||||
|
||||
function createCustomFinalizable(i:Int)
|
||||
{
|
||||
if (i<=0)
|
||||
new CustomFinalizable();
|
||||
else
|
||||
createCustomFinalizable(i-1);
|
||||
}
|
||||
|
||||
|
||||
public function testCustomFinalizable()
|
||||
{
|
||||
for(i in 0...100)
|
||||
createCustomFinalizable(2);
|
||||
cpp.vm.Gc.run(true);
|
||||
Sys.println("custom cleared:" + CustomFinalizable.count);
|
||||
assertTrue(CustomFinalizable.count>0);
|
||||
}
|
||||
|
||||
#end
|
||||
|
||||
function createMyFinalizable(i:Int)
|
||||
{
|
||||
if (i<=0)
|
||||
new MyFinalizable();
|
||||
else
|
||||
createMyFinalizable(i-1);
|
||||
}
|
||||
|
||||
public function testFinalizable()
|
||||
{
|
||||
for(i in 0...100)
|
||||
createMyFinalizable(2);
|
||||
cpp.vm.Gc.run(true);
|
||||
Sys.println("MyFinalizable cleared:" + MyFinalizable.count);
|
||||
assertTrue(MyFinalizable.count>0);
|
||||
}
|
||||
}
|
||||
|
||||
|
21
Kha/Backends/Kinc-hxcpp/khacpp/test/native/Native.hx
Normal file
21
Kha/Backends/Kinc-hxcpp/khacpp/test/native/Native.hx
Normal file
@ -0,0 +1,21 @@
|
||||
package;
|
||||
|
||||
class Native
|
||||
{
|
||||
static function main()
|
||||
{
|
||||
var r = new haxe.unit.TestRunner();
|
||||
r.add(new tests.TestStdio());
|
||||
r.add(new tests.TestRgb());
|
||||
r.add(new tests.TestRectangle());
|
||||
r.add(new tests.TestGlobalNamespace());
|
||||
r.add(new tests.TestNativeGen());
|
||||
r.add(new tests.TestNonVirtual());
|
||||
r.add(new tests.TestPtr());
|
||||
r.add(new tests.TestNativeEnum());
|
||||
var t0 = haxe.Timer.stamp();
|
||||
var success = r.run();
|
||||
trace(" Time : " + (haxe.Timer.stamp()-t0)*1000 );
|
||||
Sys.exit(success ? 0 : 1);
|
||||
}
|
||||
}
|
22
Kha/Backends/Kinc-hxcpp/khacpp/test/native/NativeGen.hx
Normal file
22
Kha/Backends/Kinc-hxcpp/khacpp/test/native/NativeGen.hx
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
@:nativeGen
|
||||
@:structAccess
|
||||
class NativeGen
|
||||
{
|
||||
public var x:Float;
|
||||
public static var y:Int;
|
||||
public function getValue():Float return x;
|
||||
|
||||
public static function someNativeFunction()
|
||||
{
|
||||
trace("Hi!");
|
||||
}
|
||||
}
|
||||
|
||||
@:native("cpp::Struct<NativeGen>")
|
||||
@:include("NativeGen.h")
|
||||
extern class NativeGenStruct extends NativeGen
|
||||
{
|
||||
}
|
||||
|
||||
|
4
Kha/Backends/Kinc-hxcpp/khacpp/test/native/compile.hxml
Normal file
4
Kha/Backends/Kinc-hxcpp/khacpp/test/native/compile.hxml
Normal file
@ -0,0 +1,4 @@
|
||||
-cpp bin
|
||||
-main Native
|
||||
-D HXCPP_DEBUGGER
|
||||
-cp ../unit
|
44
Kha/Backends/Kinc-hxcpp/khacpp/test/native/externs/RGB.hx
Normal file
44
Kha/Backends/Kinc-hxcpp/khacpp/test/native/externs/RGB.hx
Normal file
@ -0,0 +1,44 @@
|
||||
package externs;
|
||||
|
||||
import cpp.UInt8;
|
||||
import cpp.Pointer;
|
||||
|
||||
@:include("./../lib/LibInclude.h")
|
||||
@:sourceFile("./../lib/RGB.cpp")
|
||||
@:native("RGB")
|
||||
extern class RGB
|
||||
{
|
||||
public var r:UInt8;
|
||||
public var g:UInt8;
|
||||
public var b:UInt8;
|
||||
|
||||
public function getLuma():Int;
|
||||
public function toInt():Int;
|
||||
|
||||
@:native("new RGB")
|
||||
public static function create(r:Int, g:Int, b:Int):Pointer<RGB>;
|
||||
|
||||
@:native("~RGB")
|
||||
public function deleteMe():Void;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// By extending RGB we keep the same API as far as haxe is concerned, but store the data (not pointer)
|
||||
// The native Reference class knows how to take the reference to the structure
|
||||
@:native("cpp.Reference<RGB>")
|
||||
extern class RGBRef extends RGB
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
// By extending RGBRef, we can keep the same api,
|
||||
// rather than a pointer
|
||||
@:native("cpp.Struct<RGB>")
|
||||
extern class RGBStruct extends RGBRef
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
38
Kha/Backends/Kinc-hxcpp/khacpp/test/native/externs/Rectangle.hx
Executable file
38
Kha/Backends/Kinc-hxcpp/khacpp/test/native/externs/Rectangle.hx
Executable file
@ -0,0 +1,38 @@
|
||||
package externs;
|
||||
|
||||
import externs.RectangleApi;
|
||||
|
||||
@:include("./RectangleDef.h")
|
||||
@:structAccess
|
||||
@:native("Rectangle")
|
||||
extern class Rectangle
|
||||
{
|
||||
@:native("Rectangle::instanceCount")
|
||||
static var instanceCount:Int;
|
||||
|
||||
public var x:Int;
|
||||
public var y:Int;
|
||||
public var width:Int;
|
||||
public var height:Int;
|
||||
|
||||
public function area() : Int;
|
||||
|
||||
@:native("new Rectangle")
|
||||
@:overload( function():cpp.Star<Rectangle>{} )
|
||||
@:overload( function(x:Int):cpp.Star<Rectangle>{} )
|
||||
@:overload( function(x:Int, y:Int):cpp.Star<Rectangle>{} )
|
||||
@:overload( function(x:Int, y:Int, width:Int):cpp.Star<Rectangle>{} )
|
||||
static function create(x:Int, y:Int, width:Int, height:Int):cpp.Star<Rectangle>;
|
||||
|
||||
@:native("Rectangle")
|
||||
@:overload( function():Rectangle {} )
|
||||
@:overload( function(x:Int):Rectangle {} )
|
||||
@:overload( function(x:Int, y:Int):Rectangle {} )
|
||||
@:overload( function(x:Int, y:Int, width:Int):Rectangle {} )
|
||||
static function make(x:Int, y:Int, width:Int, height:Int):Rectangle;
|
||||
|
||||
@:native("~Rectangle")
|
||||
public function delete():Void;
|
||||
}
|
||||
|
||||
typedef RectanglePtr = cpp.Star<Rectangle>;
|
9
Kha/Backends/Kinc-hxcpp/khacpp/test/native/externs/RectangleApi.hx
Executable file
9
Kha/Backends/Kinc-hxcpp/khacpp/test/native/externs/RectangleApi.hx
Executable file
@ -0,0 +1,9 @@
|
||||
package externs;
|
||||
|
||||
// This class acts as a container for the Rectangle implementation, which will get included
|
||||
// in the cpp file, and therfore get compiled and linked with the correct flags
|
||||
@:cppInclude("./RectangleImpl.cpp")
|
||||
@:keep
|
||||
class RectangleApi
|
||||
{
|
||||
}
|
26
Kha/Backends/Kinc-hxcpp/khacpp/test/native/externs/RectangleDef.h
Executable file
26
Kha/Backends/Kinc-hxcpp/khacpp/test/native/externs/RectangleDef.h
Executable file
@ -0,0 +1,26 @@
|
||||
#ifndef RECTANGLE_DEF_INCLUDED
|
||||
#define RECTANGLE_DEF_INCLUDED
|
||||
|
||||
struct Rectangle
|
||||
{
|
||||
static int instanceCount;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
inline Rectangle(int inX=0, int inY=0, int inW=0, int inH=0) :
|
||||
x(inX), y(inY), width(inW), height(inH)
|
||||
{
|
||||
instanceCount++;
|
||||
}
|
||||
inline ~Rectangle()
|
||||
{
|
||||
instanceCount--;
|
||||
}
|
||||
|
||||
int area();
|
||||
};
|
||||
|
||||
#endif
|
8
Kha/Backends/Kinc-hxcpp/khacpp/test/native/externs/RectangleImpl.cpp
Executable file
8
Kha/Backends/Kinc-hxcpp/khacpp/test/native/externs/RectangleImpl.cpp
Executable file
@ -0,0 +1,8 @@
|
||||
#include "RectangleDef.h"
|
||||
|
||||
int Rectangle::instanceCount = 0;
|
||||
|
||||
int Rectangle::area()
|
||||
{
|
||||
return width*height;
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
package externs;
|
||||
|
||||
@:native("short *") @:unreflective
|
||||
extern class ShortPtr { }
|
28
Kha/Backends/Kinc-hxcpp/khacpp/test/native/lib/LibInclude.h
Normal file
28
Kha/Backends/Kinc-hxcpp/khacpp/test/native/lib/LibInclude.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef LIB_INCLUDE_INCLUDED
|
||||
#define LIB_INCLUDE_INCLUDED
|
||||
|
||||
struct RGB
|
||||
{
|
||||
unsigned char r;
|
||||
unsigned char g;
|
||||
unsigned char b;
|
||||
|
||||
|
||||
RGB(int inR=0, int inG=0, int inB=0) :
|
||||
r(inR), g(inG), b(inB)
|
||||
{
|
||||
}
|
||||
|
||||
int getLuma();
|
||||
int toInt();
|
||||
};
|
||||
|
||||
struct Gradient
|
||||
{
|
||||
RGB colour0;
|
||||
RGB colour1;
|
||||
int steps;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
5
Kha/Backends/Kinc-hxcpp/khacpp/test/native/lib/RGB.cpp
Normal file
5
Kha/Backends/Kinc-hxcpp/khacpp/test/native/lib/RGB.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
#include "LibInclude.h"
|
||||
|
||||
int RGB::getLuma() { return (r+g+b)/3; }
|
||||
|
||||
int RGB::toInt() { return (r<<16) | (g<<8) | b; }
|
12
Kha/Backends/Kinc-hxcpp/khacpp/test/native/tests/TestGlobalNamespace.hx
Executable file
12
Kha/Backends/Kinc-hxcpp/khacpp/test/native/tests/TestGlobalNamespace.hx
Executable file
@ -0,0 +1,12 @@
|
||||
package tests;
|
||||
|
||||
class TestGlobalNamespace extends haxe.unit.TestCase
|
||||
{
|
||||
var shortPtr:externs.ShortPtr;
|
||||
|
||||
public function testGen()
|
||||
{
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,65 @@
|
||||
package tests;
|
||||
|
||||
// Uses native enum, which does not play nice with Dynamic - must use @:unreflective
|
||||
@:unreflective
|
||||
@:enum extern abstract SystemMetric(SystemMetricImpl) {
|
||||
@:native("wxSYS_MOUSE_BUTTONS") var MOUSE_BUTTONS;
|
||||
@:native("wxSYS_OS") var OS;
|
||||
}
|
||||
@:unreflective
|
||||
@:native("wxSystemMetric")
|
||||
extern class SystemMetricImpl { }
|
||||
|
||||
|
||||
|
||||
// Wraps enum in struct, which does play nice...
|
||||
@:enum extern abstract SystemMetricStruct(SystemMetricStructImpl) {
|
||||
@:native("wxSYS_MOUSE_BUTTONS") var MOUSE_BUTTONS;
|
||||
@:native("wxSYS_OS") var OS;
|
||||
}
|
||||
@:native("cpp::Struct<wxSystemMetric, cpp::EnumHandler>")
|
||||
extern class SystemMetricStructImpl { }
|
||||
|
||||
@:headerCode('
|
||||
enum wxSystemMetric
|
||||
{
|
||||
wxSYS_OS = 3,
|
||||
wxSYS_MOUSE_BUTTONS = 27,
|
||||
};
|
||||
')
|
||||
class TestNativeEnum extends haxe.unit.TestCase
|
||||
{
|
||||
var x:SystemMetric = SystemMetric.MOUSE_BUTTONS;
|
||||
var xStruct:SystemMetricStruct = SystemMetricStruct.MOUSE_BUTTONS;
|
||||
|
||||
function isX(val:SystemMetric)
|
||||
{
|
||||
return (val==x);
|
||||
}
|
||||
|
||||
function isXStruct(val:SystemMetricStruct)
|
||||
{
|
||||
return (val==xStruct);
|
||||
}
|
||||
|
||||
|
||||
public function test()
|
||||
{
|
||||
assertTrue( isX(SystemMetric.MOUSE_BUTTONS)==true );
|
||||
assertTrue( isX(SystemMetric.OS)==false );
|
||||
assertTrue( isXStruct(SystemMetricStruct.MOUSE_BUTTONS)==true );
|
||||
assertTrue( isXStruct(SystemMetricStruct.OS)==false );
|
||||
var d:Dynamic = this;
|
||||
assertTrue( d.x==null );
|
||||
assertTrue( d.xStruct!=null );
|
||||
assertTrue( d.isX==null );
|
||||
assertTrue( d.isXStruct!=null );
|
||||
var func = d.isXStruct;
|
||||
assertTrue(func!=null);
|
||||
assertTrue(func(SystemMetricStruct.MOUSE_BUTTONS)==true );
|
||||
assertTrue(func(SystemMetricStruct.OS)==false );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,23 @@
|
||||
package tests;
|
||||
|
||||
import NativeGen;
|
||||
|
||||
class TestNativeGen extends haxe.unit.TestCase
|
||||
{
|
||||
@:unreflective var unreflectiveValue:NativeGen;
|
||||
|
||||
@:unreflective public function unreflectiveFunction(inGen:NativeGen)
|
||||
{
|
||||
unreflectiveValue = inGen;
|
||||
return unreflectiveValue.x==22;
|
||||
}
|
||||
|
||||
public function testCreate()
|
||||
{
|
||||
var nGen:NativeGenStruct = null;
|
||||
nGen.x = 22;
|
||||
assertTrue(nGen.getValue()==22);
|
||||
|
||||
assertTrue(unreflectiveFunction(nGen) );
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package tests;
|
||||
|
||||
class Base
|
||||
{
|
||||
public function new() {}
|
||||
|
||||
@:nonVirtual public function getNvName() return "Base";
|
||||
public function getName() return "Base";
|
||||
}
|
||||
|
||||
|
||||
class Derived extends Base
|
||||
{
|
||||
@:nonVirtual override public function getNvName() return "Derived";
|
||||
override public function getName() return "Derived";
|
||||
}
|
||||
|
||||
|
||||
class TestNonVirtual extends haxe.unit.TestCase
|
||||
{
|
||||
public function testOverride()
|
||||
{
|
||||
var derived = new Derived();
|
||||
|
||||
assertTrue( derived.getName() == "Derived" );
|
||||
assertTrue( derived.getNvName() == "Derived" );
|
||||
var closure:Dynamic = derived.getNvName;
|
||||
assertTrue( closure() == "Derived" );
|
||||
|
||||
var base:Base = derived;
|
||||
|
||||
assertTrue( base.getName() == "Derived" );
|
||||
assertTrue( base.getNvName() == "Base" );
|
||||
var closure:Dynamic = base.getNvName;
|
||||
assertTrue( closure() == "Base" );
|
||||
}
|
||||
}
|
378
Kha/Backends/Kinc-hxcpp/khacpp/test/native/tests/TestPtr.hx
Normal file
378
Kha/Backends/Kinc-hxcpp/khacpp/test/native/tests/TestPtr.hx
Normal file
@ -0,0 +1,378 @@
|
||||
package tests;
|
||||
|
||||
import NativeGen;
|
||||
import cpp.NativeGc;
|
||||
import cpp.Stdlib;
|
||||
import cpp.Pointer;
|
||||
import cpp.RawPointer;
|
||||
import cpp.UInt8;
|
||||
using cpp.NativeArray;
|
||||
using cpp.NativeString;
|
||||
|
||||
@:unreflective
|
||||
@:native("CVec")
|
||||
extern class Vec {
|
||||
public var x:Float;
|
||||
public var y:Float;
|
||||
public var z:Float;
|
||||
}
|
||||
|
||||
|
||||
@:unreflective
|
||||
@:structAccess
|
||||
@:native("CVec")
|
||||
extern class VecStructAccess {
|
||||
public var x:Float;
|
||||
public var y:Float;
|
||||
public var z:Float;
|
||||
|
||||
@:native("new CVec")
|
||||
public static function create(val:Float) : Pointer<VecStructAccess>;
|
||||
|
||||
public function set99(ioVec:VecStructAccess):Void;
|
||||
}
|
||||
|
||||
|
||||
@:unreflective
|
||||
@:native("cpp::Struct<CVec>")
|
||||
extern class VecStruct {
|
||||
public var x:Float;
|
||||
public var y:Float;
|
||||
public var z:Float;
|
||||
}
|
||||
|
||||
@:native("::SomeStruct")
|
||||
extern class Native_SomeStruct {
|
||||
var data:RawPointer<cpp.UInt8>;
|
||||
var dataLength:Int;
|
||||
|
||||
inline function getDataBytes():haxe.io.Bytes {
|
||||
var bdata:haxe.io.BytesData = [];
|
||||
cpp.NativeArray.setData(bdata, cast data, dataLength); // Null Function Pointer
|
||||
return haxe.io.Bytes.ofData(bdata);
|
||||
}
|
||||
|
||||
inline function getUnmanagedDataBytes():haxe.io.Bytes {
|
||||
var bdata:haxe.io.BytesData = [];
|
||||
cpp.NativeArray.setUnmanagedData(bdata, cast data, dataLength); // Null Function Pointer
|
||||
return haxe.io.Bytes.ofData(bdata);
|
||||
}
|
||||
|
||||
}
|
||||
@:native("::cpp::Reference<SomeStruct>")
|
||||
extern class SomeStructRef extends Native_SomeStruct {}
|
||||
@:native("::cpp::Struct<SomeStruct>")
|
||||
extern class SomeStruct extends SomeStructRef {}
|
||||
|
||||
class IntHolder
|
||||
{
|
||||
public var ival:Int;
|
||||
|
||||
public function new(inVal:Int = 1) ival = inVal;
|
||||
}
|
||||
|
||||
@:headerCode('
|
||||
struct CVec{
|
||||
CVec(double inX=0) : x(inX), y(inX), z(inX) { }
|
||||
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
|
||||
void set99(CVec &ioVex) { ioVex.x=99; }
|
||||
};
|
||||
|
||||
struct SomeStruct {
|
||||
SomeStruct() : data((unsigned char *)"Hi!"), dataLength(3) { }
|
||||
|
||||
unsigned char *data;
|
||||
int dataLength;
|
||||
};
|
||||
')
|
||||
@:cppFileCode('
|
||||
int callPointer(CVec *) { return 5; }
|
||||
')
|
||||
class TestPtr extends haxe.unit.TestCase{
|
||||
|
||||
/*
|
||||
Alternate version
|
||||
@:generic
|
||||
public static inline function malloc<T>(size:Int) : cpp.Pointer<T>{
|
||||
var p : cpp.RawPointer<cpp.Void> = untyped __cpp__("malloc({0})",size);
|
||||
return cast cpp.Pointer.fromRaw( cast p );
|
||||
}
|
||||
*/
|
||||
|
||||
public function testMalloc() {
|
||||
var a : Pointer<Vec> = Stdlib.malloc( Stdlib.sizeof(Vec) );
|
||||
assertTrue( a!=null );
|
||||
assertTrue( a.raw!=null );
|
||||
a.ptr.x = 66;
|
||||
assertTrue( a.ptr.x == 66 );
|
||||
Stdlib.free(a);
|
||||
}
|
||||
|
||||
public function testExtened() {
|
||||
var test = NativeGc.allocateExtended( TestPtr, Stdlib.sizeof(Int) * 5 );
|
||||
var a : Pointer<Int> = cast Pointer.endOf(test);
|
||||
for(i in 0...5)
|
||||
a.setAt(i,i);
|
||||
for(i in 0...5)
|
||||
assertTrue( a.postIncRef() == i );
|
||||
}
|
||||
|
||||
function test9194() {
|
||||
// will fail during C++ compile
|
||||
var buffer: cpp.RawPointer<cpp.Void> = null;
|
||||
var floatBuffer: cpp.RawPointer<cpp.Float32> = cast buffer;
|
||||
// generates incorrect: float* floatBuffer = buffer
|
||||
// the lack of native casting means the compiler throws an error here
|
||||
|
||||
var buffer: cpp.Star<cpp.Void> = null;
|
||||
var floatBuffer: cpp.Star<cpp.Float32> = cast buffer;
|
||||
// generates correct: float* floatBuffer = ( (float*) buffer )
|
||||
|
||||
assertTrue(floatBuffer==null);
|
||||
}
|
||||
|
||||
|
||||
public function testNull() {
|
||||
var nullP : Pointer<Vec> = null;
|
||||
var nullRawP = nullP.raw;
|
||||
assertTrue( nullP==null );
|
||||
assertTrue( null==nullP );
|
||||
assertFalse( nullP!=null );
|
||||
assertTrue( nullRawP==null );
|
||||
assertFalse( nullRawP!=null );
|
||||
nullRawP = null;
|
||||
assertTrue( nullRawP==null );
|
||||
}
|
||||
|
||||
private function anonOf(d:Dynamic) : Dynamic return {ptr:d};
|
||||
|
||||
public function testStructAccess() {
|
||||
var e = VecStructAccess.create(1);
|
||||
var tmp = e.ptr;
|
||||
var tmp1 = e.ref;
|
||||
tmp.set99(tmp1);
|
||||
assertTrue(e.ptr.x==99);
|
||||
}
|
||||
|
||||
@:native("callPointer") @:extern
|
||||
private static function callPointer(ptr:cpp.Pointer<Vec>):Int;
|
||||
|
||||
public function testPointerCast() {
|
||||
var map = new Map<Int, cpp.Pointer<Vec> >();
|
||||
map.set(1,null);
|
||||
var result = callPointer( map.get(2) );
|
||||
assertTrue(result==5);
|
||||
}
|
||||
|
||||
public function testDynamic() {
|
||||
var a = [1];
|
||||
var intPtr = a.address(0);
|
||||
var d:Dynamic = intPtr;
|
||||
assertFalse(d==[2].address(0));
|
||||
assertTrue(d==a.address(0));
|
||||
var anon = anonOf(d);
|
||||
assertFalse([2].address(0)==d);
|
||||
assertTrue(a.address(0)==d);
|
||||
assertFalse(intPtr==[2].address(0));
|
||||
assertTrue(intPtr==a.address(0));
|
||||
assertFalse(anon.ptr==[2].address(0));
|
||||
assertTrue(anon.ptr==a.address(0));
|
||||
assertFalse([2].address(0)==anon.ptr);
|
||||
assertTrue(a.address(0)==anon.ptr);
|
||||
}
|
||||
|
||||
function getAnonI(a:Dynamic) : Dynamic
|
||||
{
|
||||
return a.i;
|
||||
}
|
||||
|
||||
|
||||
public function testAnon() {
|
||||
var a = [1];
|
||||
var intPtr = a.address(0);
|
||||
var anon = { i:intPtr };
|
||||
assertTrue( getAnonI(anon)==intPtr );
|
||||
|
||||
var vecPtr = VecStructAccess.create(1);
|
||||
var anon = { i:vecPtr };
|
||||
assertTrue( getAnonI(anon)==vecPtr );
|
||||
|
||||
var vec:VecStruct = null;
|
||||
vec.x = 123;
|
||||
var anon = { i:vec };
|
||||
assertTrue( getAnonI(anon)==vec );
|
||||
}
|
||||
|
||||
static function callMe(x:Int) return 10+x;
|
||||
|
||||
static function notProcAddress(module:String, func:String) return null;
|
||||
|
||||
public function testArrayAccess() {
|
||||
var array = [ 0.0, 1.1, 2.2, 3.3 ];
|
||||
var ptr = cpp.Pointer.arrayElem(array, 0);
|
||||
assertTrue( ptr[1]==1.1 );
|
||||
ptr[1] = 2;
|
||||
assertTrue( ptr[1]==2 );
|
||||
ptr[1]++;
|
||||
assertTrue( ptr[1]==3 );
|
||||
ptr[1]-=2.5;
|
||||
assertTrue( ptr[1]==0.5 );
|
||||
|
||||
var raw = ptr.raw;
|
||||
assertTrue( raw[2]==2.2 );
|
||||
raw[2] = 2;
|
||||
assertTrue( raw[2]==2 );
|
||||
raw[2]++;
|
||||
assertTrue( raw[2]==3 );
|
||||
raw[2]-=2.5;
|
||||
assertTrue( raw[2]==0.5 );
|
||||
|
||||
}
|
||||
|
||||
public function testFromRaw()
|
||||
{
|
||||
var i = new IntHolder(3);
|
||||
var ptr = cpp.Pointer.fromRaw(cpp.Pointer.addressOf(i).rawCast());
|
||||
assertTrue( ptr.ref.ival==i.ival );
|
||||
ptr.ref.ival==23;
|
||||
assertTrue( ptr.ref.ival==i.ival );
|
||||
}
|
||||
|
||||
private static var output:cpp.Pointer<Array<Int>>;
|
||||
|
||||
private static var arrayValue:Array<Int>;
|
||||
private static function makeValue():{ a:cpp.Pointer<Array<Int>> }
|
||||
{
|
||||
arrayValue = [9];
|
||||
return { a: cpp.Pointer.addressOf(arrayValue) };
|
||||
}
|
||||
|
||||
@:analyzer(no_fusion)
|
||||
public function testDynamicOutput()
|
||||
{
|
||||
// Declared as structure (just `var val = ...` works too)
|
||||
var val:{ a:cpp.Pointer<Array<Int>> } = makeValue();
|
||||
|
||||
var a:cpp.Pointer<Array<Int>> = val.a;
|
||||
output = a;
|
||||
output = (val.a:Dynamic);
|
||||
output = val.a;
|
||||
output = (val.a:cpp.Pointer<Array<Int>>);
|
||||
val.a = output;
|
||||
|
||||
// Declared as Dynamic
|
||||
var val2:Dynamic = makeValue();
|
||||
a = val2.a;
|
||||
output = a;
|
||||
output = (val2.a:Dynamic);
|
||||
output = val2.a;
|
||||
output = (val2.a:cpp.Pointer<Array<Int>>);
|
||||
val2.a = output;
|
||||
assertTrue( val2.a==output );
|
||||
assertTrue( output==val.a );
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testAutoCast() {
|
||||
var z = [ 1, 2, 3 ];
|
||||
assertTrue( cpp.NativeArray.address(z, 0).ptr == cpp.NativeArray.address(z, 0).ptr );
|
||||
assertTrue( cpp.NativeArray.address(z, 1).ptr != cpp.NativeArray.address(z, 0).ptr );
|
||||
assertTrue( cpp.NativeArray.address(z, 1).gt(cpp.NativeArray.address(z, 0)) );
|
||||
assertTrue( cpp.NativeArray.address(z, 1).geq(cpp.NativeArray.address(z, 0)) );
|
||||
assertTrue( cpp.NativeArray.address(z, 1).geq(cpp.NativeArray.address(z, 1)) );
|
||||
assertTrue( cpp.NativeArray.address(z, 0).leq(cpp.NativeArray.address(z, 0)) );
|
||||
assertTrue( cpp.NativeArray.address(z, 1).leq(cpp.NativeArray.address(z, 2)) );
|
||||
assertTrue( cpp.NativeArray.address(z, 1).leq(cpp.NativeArray.address(z, 2)) );
|
||||
assertTrue( cpp.NativeArray.address(z, 0) == cpp.Pointer.ofArray(z) );
|
||||
assertTrue( cpp.NativeArray.address(z, 1) == cpp.Pointer.arrayElem(z,1) );
|
||||
assertTrue( cpp.NativeArray.address(z, 1) != cpp.Pointer.fromHandle(null) );
|
||||
assertTrue( cpp.Function.fromStaticFunction(callMe)(1)==11 );
|
||||
try
|
||||
{
|
||||
assertTrue( cpp.Function.fromStaticFunction(notProcAddress)!=cpp.Function.getProcAddress("nomodule","nofunc!") );
|
||||
}
|
||||
catch(e:Dynamic)
|
||||
{
|
||||
// Could not load module - expected
|
||||
}
|
||||
}
|
||||
|
||||
static function functionCaller(fn:cpp.Function<Void->Int,cpp.abi.Abi>) {
|
||||
var a = fn.call();
|
||||
}
|
||||
|
||||
public function testFunctionStructAccess() {
|
||||
assertTrue( functionCaller != null );
|
||||
}
|
||||
|
||||
public function testSetData() {
|
||||
var ss:SomeStruct = null;
|
||||
ss.dataLength = 4;
|
||||
ss.data = cast "bye!".c_str();
|
||||
var b = ss.getDataBytes();
|
||||
assertTrue( b.getString(0, b.length) == "bye!" );
|
||||
|
||||
var ss:SomeStruct = null;
|
||||
var b = ss.getUnmanagedDataBytes();
|
||||
assertTrue( b.getString(0, b.length) == "Hi!" );
|
||||
}
|
||||
|
||||
public function testZero() {
|
||||
var a = [1,2,3];
|
||||
a.zero();
|
||||
assertTrue(a.length==3);
|
||||
assertTrue(a[0]==0);
|
||||
assertTrue(a[1]==0);
|
||||
assertTrue(a[2]==0);
|
||||
}
|
||||
|
||||
public function testMemcmp() {
|
||||
var a = [1,2,3];
|
||||
var b = [2,2,3];
|
||||
assertTrue( a.memcmp(b) == -1 );
|
||||
assertTrue( b.memcmp(a) == 1 );
|
||||
assertTrue( a.memcmp(a) == 0 );
|
||||
}
|
||||
|
||||
public function testCapacity() {
|
||||
var a = [1,2,3];
|
||||
assertTrue( a.capacity() < 1000 );
|
||||
a.reserve(1000);
|
||||
assertTrue( a.capacity() == 1000 );
|
||||
a[1000] = 1;
|
||||
assertTrue( a.capacity() > 1000 );
|
||||
}
|
||||
|
||||
|
||||
public function testElementSize() {
|
||||
var a = [1];
|
||||
assertTrue( a.getElementSize() == cpp.Stdlib.sizeof(Int) );
|
||||
var a = ["hello!"];
|
||||
assertTrue( a.getElementSize() == cpp.Stdlib.sizeof(String) );
|
||||
var a = [7.1];
|
||||
assertTrue( a.getElementSize() == cpp.Stdlib.sizeof(Float) );
|
||||
}
|
||||
|
||||
|
||||
public function testBlit() {
|
||||
var a = [1,2,3,4];
|
||||
var b = [0,0,0,0];
|
||||
b.blit(0,a,0,a.length);
|
||||
for(i in 0...4)
|
||||
assertTrue(b[i] == a[i]);
|
||||
for(i in 0...4)
|
||||
b.blit(i,a,0,1);
|
||||
for(i in 0...4)
|
||||
assertTrue(b[i] == a[0]);
|
||||
for(i in 0...4)
|
||||
b.blit(i,a,2,1);
|
||||
for(i in 0...4)
|
||||
assertTrue(b[i] == a[2]);
|
||||
}
|
||||
}
|
||||
|
107
Kha/Backends/Kinc-hxcpp/khacpp/test/native/tests/TestRectangle.hx
Executable file
107
Kha/Backends/Kinc-hxcpp/khacpp/test/native/tests/TestRectangle.hx
Executable file
@ -0,0 +1,107 @@
|
||||
package tests;
|
||||
import externs.Rectangle;
|
||||
|
||||
class TestRectangle extends haxe.unit.TestCase
|
||||
{
|
||||
static var statRect:Rectangle;
|
||||
static var statRectPtr:RectanglePtr;
|
||||
|
||||
static var statRectProp(get,set):Rectangle;
|
||||
static var statRectPtrProp(get,set):RectanglePtr;
|
||||
|
||||
var memRect:Rectangle;
|
||||
var memRectPtr:RectanglePtr;
|
||||
|
||||
var memRectProp(get,set):Rectangle;
|
||||
var memRectPtrProp(get,set):RectanglePtr;
|
||||
|
||||
static function get_statRectProp() return statRect;
|
||||
static function set_statRectProp(val:Rectangle) return statRect=val;
|
||||
static function get_statRectPtrProp() return statRectPtr;
|
||||
static function set_statRectPtrProp(val:RectanglePtr) return statRectPtr=val;
|
||||
|
||||
|
||||
function get_memRectProp() return memRect;
|
||||
function set_memRectProp(val:Rectangle) return memRect=val;
|
||||
function get_memRectPtrProp() return memRectPtr;
|
||||
function set_memRectPtrProp(val:RectanglePtr) return memRectPtr=val;
|
||||
|
||||
|
||||
public function testRect()
|
||||
{
|
||||
// Struct - copy semantic
|
||||
var rectangle = Rectangle.make(3,4);
|
||||
assertTrue( rectangle.area()==0 );
|
||||
|
||||
var rect2 = rectangle;
|
||||
rect2.width = 2;
|
||||
rect2.height = 4;
|
||||
assertTrue( rect2.area()==8 );
|
||||
assertTrue( rectangle.area()==0 );
|
||||
|
||||
|
||||
// Take address ...
|
||||
var rectPtr:RectanglePtr = rectangle;
|
||||
|
||||
// Pointer-like sysntax
|
||||
rectPtr.width = 3;
|
||||
rectPtr.height = 5;
|
||||
var dynamicPtr:Dynamic = rectPtr;
|
||||
|
||||
assertTrue( rectPtr.area()==15 );
|
||||
// Same object
|
||||
assertTrue( rectangle.area()==15 );
|
||||
|
||||
var dynamicCopy:Dynamic = rectangle; // 3,4 3x5
|
||||
|
||||
rectangle.width = 10;
|
||||
rectangle.height = 10;
|
||||
assertTrue( rectangle.area()==100 );
|
||||
|
||||
// points to original object
|
||||
var fromDynamic:RectanglePtr = rectPtr;
|
||||
assertTrue( fromDynamic.area()==100 );
|
||||
|
||||
// Restore from Dynamic ...
|
||||
rectangle = dynamicCopy;
|
||||
assertTrue( rectangle.area()==15 );
|
||||
}
|
||||
|
||||
public function testReflect()
|
||||
{
|
||||
statRect = Rectangle.make(1,2,3,4);
|
||||
memRect = Rectangle.make(4,5,6,7);
|
||||
// This is not correct in the GC moving case ...
|
||||
//statRectPtr = memRect;
|
||||
statRectPtr = Rectangle.create(1,1,2,2);
|
||||
memRectPtr = statRect;
|
||||
|
||||
assertTrue( statRectProp.area()==12 );
|
||||
assertTrue( memRectProp.area()==42 );
|
||||
assertTrue( statRectPtrProp.area()==4 );
|
||||
assertTrue( memRectPtrProp.area()==12 );
|
||||
|
||||
var d:Dynamic = this;
|
||||
var r:Rectangle = d.memRect;
|
||||
assertTrue( r.area()==42 );
|
||||
var prop:Rectangle = Reflect.getProperty(d,"memRectProp");
|
||||
assertTrue( prop.area()==42 );
|
||||
var propPtr:RectanglePtr = Reflect.getProperty(d,"memRectPtrProp");
|
||||
assertTrue( propPtr.area()==12 );
|
||||
|
||||
var d:Dynamic = TestRectangle;
|
||||
var r:Rectangle = d.statRect;
|
||||
assertTrue( r.area()==12 );
|
||||
var prop:Rectangle = Reflect.getProperty(d,"statRectProp");
|
||||
assertTrue( prop.area()==12 );
|
||||
var propPtr:RectanglePtr = Reflect.getProperty(d,"statRectPtrProp");
|
||||
assertTrue( propPtr.area()==4 );
|
||||
|
||||
|
||||
// No longer valid
|
||||
statRectPtr.delete();
|
||||
statRectPtr = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
53
Kha/Backends/Kinc-hxcpp/khacpp/test/native/tests/TestRgb.hx
Normal file
53
Kha/Backends/Kinc-hxcpp/khacpp/test/native/tests/TestRgb.hx
Normal file
@ -0,0 +1,53 @@
|
||||
package tests;
|
||||
import externs.RGB;
|
||||
|
||||
class TestRgb extends haxe.unit.TestCase
|
||||
{
|
||||
public function testCreate()
|
||||
{
|
||||
// Pointer-like sysntax
|
||||
var rgbPtr = RGB.create(255,0,128);
|
||||
assertTrue( rgbPtr.ptr.toInt() == 0xff0080 );
|
||||
rgbPtr.ptr.deleteMe();
|
||||
|
||||
|
||||
// Structure-like syntax
|
||||
var rgbStruct:RGBStruct = null;
|
||||
rgbStruct.r = 1;
|
||||
rgbStruct = null;
|
||||
rgbStruct.r = 1;
|
||||
rgbStruct.g = 2;
|
||||
rgbStruct.b = 3;
|
||||
assertTrue( rgbStruct.toInt() == 0x010203 );
|
||||
// Store in dynamic
|
||||
var d:Dynamic = rgbStruct;
|
||||
|
||||
// Reference (pointer) like syntax
|
||||
var rgbRef:RGBRef = rgbStruct;
|
||||
rgbRef.g = 255;
|
||||
assertTrue( rgbStruct.toInt() == 0x01ff03 );
|
||||
|
||||
// Get from dynamic
|
||||
rgbStruct = d;
|
||||
assertTrue( rgbStruct.toInt() == 0x010203 );
|
||||
|
||||
var rgbStruct2:RGBStruct = cast rgbRef;
|
||||
assertTrue( rgbStruct2.toInt() == 0x010203 );
|
||||
|
||||
// Reference refers to rgbStruct, not rgbStruct2
|
||||
rgbRef.b = 0;
|
||||
assertTrue( rgbStruct2.toInt() == 0x010203 );
|
||||
assertTrue( rgbStruct.toInt() == 0x010200 );
|
||||
|
||||
|
||||
// TODO - non-dynamic versions
|
||||
var d2:Dynamic = rgbStruct2;
|
||||
// == dynamic
|
||||
assertTrue( d2==d );
|
||||
// != dynamic
|
||||
var d0:Dynamic = rgbStruct;
|
||||
assertTrue( d0!=d );
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
package tests;
|
||||
import cpp.Stdio;
|
||||
using cpp.NativeArray;
|
||||
|
||||
class TestStdio extends haxe.unit.TestCase
|
||||
{
|
||||
public function test()
|
||||
{
|
||||
var file = Stdio.fopen("test.txt", "wb");
|
||||
var ints = [1];
|
||||
var size:cpp.SizeT = cpp.Stdlib.sizeof(Int);
|
||||
Stdio.fwrite( ints.address(0).raw, size, 1, file );
|
||||
Stdio.fclose(file);
|
||||
|
||||
var bytes = sys.io.File.getBytes("test.txt");
|
||||
var input = new haxe.io.BytesInput(bytes);
|
||||
var val = input.readInt32();
|
||||
|
||||
assertTrue(val==ints[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
100
Kha/Backends/Kinc-hxcpp/khacpp/test/opMatrix/MkOps.hx
Normal file
100
Kha/Backends/Kinc-hxcpp/khacpp/test/opMatrix/MkOps.hx
Normal file
@ -0,0 +1,100 @@
|
||||
class MkOps
|
||||
{
|
||||
public static function main()
|
||||
{
|
||||
var file = [];
|
||||
file.push("enum E { EVal0; EVal1; }");
|
||||
file.push("class Ops {");
|
||||
file.push(" public static var data: { ?f:Float };");
|
||||
file.push(" public static function check(b:Bool) { }");
|
||||
file.push(" public static function main() {");
|
||||
file.push(" var d:Dynamic = null;");
|
||||
file.push(" var ai = [1]; var fi=[1.2];");
|
||||
file.push(" var int:Int=0;");
|
||||
file.push(" var anon={a:Int, b:[2], c:EVal0};");
|
||||
file.push(" var anon2:Dynamic={a:1};");
|
||||
file.push(" var dynArray:Array<Dynamic> = [1];");
|
||||
file.push(" var uint8:cpp.UInt8 = 1;");
|
||||
file.push(" var int8:cpp.Int8 = 1;");
|
||||
file.push(" var uint16:cpp.UInt16 = 1;");
|
||||
file.push(" var int16:cpp.Int16 = 1;");
|
||||
file.push(" var uint64:cpp.UInt64 = 1;");
|
||||
file.push(" var int64:cpp.Int64 = 1;");
|
||||
file.push(" var string = 'S0';");
|
||||
file.push(" var arrarr = [ [12] ];");
|
||||
file.push(" var arrdyn = [ [d] ];");
|
||||
file.push(" var arrdynarray = [ [dynArray] ];");
|
||||
file.push(" var eval = EVal0;");
|
||||
|
||||
var exprs = [ "d", "null", "int", "ai", "ai[0]", "fi", "fi[0]", "anon.a", "anon.b", "anon.c", "anon", "anon2.xyz", "dynArray", "dynArray[0]", "3.8", '"Hello"', "uint8", "int8", "uint16", "int16", "uint64", "int64", "string", "arrarr", "arrarr[0]", "arrarr[0][0]", "arrdyn", "arrdynarray", "EVal1", "eval", "data.f" ];
|
||||
|
||||
var total = 0;
|
||||
for(e1 in exprs)
|
||||
{
|
||||
for(e2 in exprs)
|
||||
{
|
||||
file.push('check( $e1 != $e2 );');
|
||||
file.push('check( $e1 == $e2 );');
|
||||
file.push('check( $e1 > $e2 );');
|
||||
file.push('$e1 = $e2;');
|
||||
total += 4;
|
||||
if (!skipPlus(e1) && !skipPlus(e2))
|
||||
{
|
||||
file.push('$e1 += $e2;');
|
||||
file.push('$e1 -= $e2;');
|
||||
file.push('$e1 /= $e2;');
|
||||
file.push('$e1 / $e2;');
|
||||
file.push('$e1 *= $e2;');
|
||||
total +=5;
|
||||
}
|
||||
}
|
||||
}
|
||||
file.push("}}");
|
||||
|
||||
// Pass0 catches common stuff
|
||||
// Pass1 checks for "null on static targets"
|
||||
// Pass2 should work
|
||||
var errors = 0;
|
||||
for(pass in 0...3)
|
||||
{
|
||||
sys.io.File.saveContent("Ops.hx", file.join("\n") );
|
||||
|
||||
var proc = new sys.io.Process("haxe", ["-cpp", "cpp", "-D", "no-compilation", "-main", "Ops"] );
|
||||
try
|
||||
{
|
||||
var stderr = proc.stderr;
|
||||
var errMatch = ~/^Ops.hx:(\d+):(.*)/;
|
||||
while(true)
|
||||
{
|
||||
var line = stderr.readLine();
|
||||
if (errMatch.match(line))
|
||||
{
|
||||
var errLine = Std.parseInt(errMatch.matched(1));
|
||||
file[errLine-1] = "// " + errMatch.matched(2) + " " + file[errLine-1];
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(e:Dynamic) { }
|
||||
var code = proc.exitCode();
|
||||
Sys.println(' pass error $code, total errors = $errors/$total');
|
||||
if (pass==2 && code!=0)
|
||||
{
|
||||
Sys.println("Still errors after 3 passes - aborting");
|
||||
Sys.exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
var code = Sys.command("haxe", ["-cpp", "cpp", "-main", "Ops"] );
|
||||
Sys.println("Combos : " + total);
|
||||
Sys.println("Exit code : " + code);
|
||||
Sys.exit(code);
|
||||
}
|
||||
|
||||
// + and arrays do not mix...
|
||||
static function skipPlus(e:String)
|
||||
{
|
||||
return e=="ai" || e=="arrarr" || e=="arrdyn" || e=="arrarr[0]" || e=="fi" ||
|
||||
e=="arrdynarray" || e=="dynArray" || e=="eval" || e=="anon.b" || e== "EVal1";
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
import cpp.*;
|
||||
|
||||
// Windows only.
|
||||
// Compile with "-D no_console" for best effect
|
||||
|
||||
@:cppFileCode("#include <windows.h>")
|
||||
class MessageBox
|
||||
{
|
||||
public static function main()
|
||||
{
|
||||
var messageBox:cpp.Function< Pointer< Void > ->
|
||||
ConstCharStar ->
|
||||
ConstCharStar ->
|
||||
Int -> Int, cpp.abi.Winapi > =
|
||||
Function.getProcAddress("User32.dll", "MessageBoxA");
|
||||
|
||||
messageBox(null, "Hello, World!", "Hxcpp MessageBox", 0);
|
||||
|
||||
// This will actually print out if you have started from a console (not double-click)
|
||||
trace("Sneaky trace");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,4 @@
|
||||
-main MessageBox
|
||||
-cpp cpp
|
||||
-D no_console
|
||||
-cmd start cpp/MessageBox.exe
|
1005
Kha/Backends/Kinc-hxcpp/khacpp/test/std/Test.hx
Normal file
1005
Kha/Backends/Kinc-hxcpp/khacpp/test/std/Test.hx
Normal file
File diff suppressed because it is too large
Load Diff
41
Kha/Backends/Kinc-hxcpp/khacpp/test/std/Test.nmml
Normal file
41
Kha/Backends/Kinc-hxcpp/khacpp/test/std/Test.nmml
Normal file
@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<project>
|
||||
|
||||
<app
|
||||
file="TestLib"
|
||||
title="TestLib"
|
||||
package="org.haxe.hxcpp.TestLib"
|
||||
version="1.0"
|
||||
company="nme"
|
||||
main="Test"
|
||||
/>
|
||||
|
||||
<window
|
||||
width="640"
|
||||
height="480"
|
||||
orientation="landscape"
|
||||
fps="60"
|
||||
background="0xffffff"
|
||||
resizeable="true"
|
||||
hardware="true"
|
||||
/>
|
||||
|
||||
|
||||
<classpath name="." />
|
||||
<haxelib name="nme" />
|
||||
|
||||
<assets>
|
||||
<asset name="Test.hx" />
|
||||
</assets>
|
||||
|
||||
|
||||
<ndll name="std" />
|
||||
<ndll name="regexp" />
|
||||
<ndll name="zlib" />
|
||||
<ndll name="nme" haxelib="nme" nekoapi="1"/>
|
||||
|
||||
<certificates>
|
||||
<certificate file="signature.cer" name="mysign" password="ajkhsakjhf" />
|
||||
</certificates>
|
||||
|
||||
</project>
|
5
Kha/Backends/Kinc-hxcpp/khacpp/test/std/compile32.hxml
Normal file
5
Kha/Backends/Kinc-hxcpp/khacpp/test/std/compile32.hxml
Normal file
@ -0,0 +1,5 @@
|
||||
-main Test
|
||||
-cpp cpp32
|
||||
-D HXCPP_M32
|
||||
-D HXCPP_DEBUGGER
|
||||
-cp ../unit
|
4
Kha/Backends/Kinc-hxcpp/khacpp/test/std/compile64.hxml
Normal file
4
Kha/Backends/Kinc-hxcpp/khacpp/test/std/compile64.hxml
Normal file
@ -0,0 +1,4 @@
|
||||
-main Test
|
||||
-cpp cpp64
|
||||
-D HXCPP_M64
|
||||
-cp ../unit
|
8
Kha/Backends/Kinc-hxcpp/khacpp/test/std/testAndroid.hxml
Normal file
8
Kha/Backends/Kinc-hxcpp/khacpp/test/std/testAndroid.hxml
Normal file
@ -0,0 +1,8 @@
|
||||
-main Test
|
||||
-cpp arm32
|
||||
-D android
|
||||
-D exe_link
|
||||
-cp ../unit
|
||||
-cmd adb push arm32/Test /storage/ext_sd
|
||||
-cmd adb push Test.hx /storage/ext_sd
|
||||
-cmd adb shell "cd /storage/ext_sd && ./Test"
|
19
Kha/Backends/Kinc-hxcpp/khacpp/test/telemetry/TestBasic.hx
Normal file
19
Kha/Backends/Kinc-hxcpp/khacpp/test/telemetry/TestBasic.hx
Normal file
@ -0,0 +1,19 @@
|
||||
class TestBasic extends haxe.unit.TestCase
|
||||
{
|
||||
public function new() super();
|
||||
|
||||
function testStartTelemetry(string:String)
|
||||
{
|
||||
var thread_id:Int = startTelemetry(true, true);
|
||||
assertTrue(thread_id>=0);
|
||||
}
|
||||
|
||||
function startTelemetry(with_profiler:Bool=true,
|
||||
with_allocations:Bool=true):Int
|
||||
{
|
||||
// Compile will fail without -D HXCPP_TELEMETRY
|
||||
return untyped __global__.__hxcpp_hxt_start_telemetry(with_profiler,
|
||||
with_allocations);
|
||||
}
|
||||
|
||||
}
|
13
Kha/Backends/Kinc-hxcpp/khacpp/test/telemetry/TestMain.hx
Normal file
13
Kha/Backends/Kinc-hxcpp/khacpp/test/telemetry/TestMain.hx
Normal file
@ -0,0 +1,13 @@
|
||||
package;
|
||||
|
||||
class TestMain {
|
||||
|
||||
static function main(){
|
||||
var r = new haxe.unit.TestRunner();
|
||||
r.add(new TestBasic());
|
||||
var t0 = haxe.Timer.stamp();
|
||||
var success = r.run();
|
||||
trace(" Time : " + (haxe.Timer.stamp()-t0)*1000 );
|
||||
Sys.exit(success ? 0 : 1);
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
-cpp bin
|
||||
-main TestMain
|
||||
-resource TestMain.hx
|
||||
-D HXCPP_TELEMETRY
|
||||
-D HXCPP_STACK_TRACE
|
||||
-cp ../unit
|
2
Kha/Backends/Kinc-hxcpp/khacpp/test/telemetry/test.bat
Normal file
2
Kha/Backends/Kinc-hxcpp/khacpp/test/telemetry/test.bat
Normal file
@ -0,0 +1,2 @@
|
||||
haxe compile.hxml
|
||||
"bin/TestMain.exe"
|
40
Kha/Backends/Kinc-hxcpp/khacpp/test/threads/Test.hx
Normal file
40
Kha/Backends/Kinc-hxcpp/khacpp/test/threads/Test.hx
Normal file
@ -0,0 +1,40 @@
|
||||
import sys.thread.Thread;
|
||||
import sys.io.File;
|
||||
|
||||
@:cppInclude("./ThreadCode.cpp")
|
||||
class Test
|
||||
{
|
||||
static var mainThread:Thread;
|
||||
|
||||
@:native("runThread")
|
||||
extern static function createNativeThread():Void;
|
||||
|
||||
public static function callFromThread()
|
||||
{
|
||||
trace("Same:" + (mainThread==Thread.current()) );
|
||||
mainThread.sendMessage("Done");
|
||||
}
|
||||
|
||||
public static function main()
|
||||
{
|
||||
var me = Thread.current();
|
||||
mainThread = me;
|
||||
Thread.create( function() {
|
||||
File.copy("a.txt","b.txt");
|
||||
me.sendMessage("Done");
|
||||
trace("Same thread:" + (me==Thread.current()) );
|
||||
} );
|
||||
var result = Thread.readMessage(true);
|
||||
trace(result);
|
||||
|
||||
for(x in 0...20)
|
||||
{
|
||||
trace("call...");
|
||||
createNativeThread();
|
||||
trace("zzz...");
|
||||
Sys.sleep(1);
|
||||
var result = Thread.readMessage(true);
|
||||
trace(result);
|
||||
}
|
||||
}
|
||||
}
|
16
Kha/Backends/Kinc-hxcpp/khacpp/test/threads/ThreadCode.cpp
Normal file
16
Kha/Backends/Kinc-hxcpp/khacpp/test/threads/ThreadCode.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include <hx/Native.h>
|
||||
#include <hx/Thread.h>
|
||||
|
||||
THREAD_FUNC_TYPE threadFunc(void *data)
|
||||
{
|
||||
printf("In thread\n");
|
||||
hx::NativeAttach attach;
|
||||
Test_obj::callFromThread();
|
||||
THREAD_FUNC_RET
|
||||
}
|
||||
|
||||
void runThread()
|
||||
{
|
||||
HxCreateDetachedThread(threadFunc,nullptr);
|
||||
}
|
||||
|
1
Kha/Backends/Kinc-hxcpp/khacpp/test/threads/a.txt
Normal file
1
Kha/Backends/Kinc-hxcpp/khacpp/test/threads/a.txt
Normal file
@ -0,0 +1 @@
|
||||
hello
|
4
Kha/Backends/Kinc-hxcpp/khacpp/test/threads/compile.hxml
Normal file
4
Kha/Backends/Kinc-hxcpp/khacpp/test/threads/compile.hxml
Normal file
@ -0,0 +1,4 @@
|
||||
-main Test
|
||||
-cpp cpp
|
||||
-debug
|
||||
-cp ../unit
|
116
Kha/Backends/Kinc-hxcpp/khacpp/test/unit/haxe/unit/TestCase.hx
Normal file
116
Kha/Backends/Kinc-hxcpp/khacpp/test/unit/haxe/unit/TestCase.hx
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (C)2005-2017 Haxe Foundation
|
||||
*
|
||||
* 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:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package haxe.unit;
|
||||
import haxe.PosInfos;
|
||||
|
||||
/**
|
||||
This unit test class should be extended to create test cases. Each test
|
||||
method created in this extended class should start with the name "test".
|
||||
|
||||
These test methods should call the assertion methods:
|
||||
|
||||
* `assertTrue(a)`: Succeeds if `a` is `true`.
|
||||
* `assertFalse(a)`: Succeeds if `a` is `false`.
|
||||
* `assertEquals(expected, actual)`: Succeeds if `expected` and `actual`
|
||||
are equal.
|
||||
|
||||
```haxe
|
||||
class MyTestCase extends haxe.unit.TestCase {
|
||||
function testBasic() {
|
||||
assertEquals("A", "A");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The TestCase can be tested using `TestRunner`.
|
||||
|
||||
To run code before or after the test, override the functions `setup`
|
||||
and `tearDown`.
|
||||
|
||||
@see <https://haxe.org/manual/std-unit-testing.html>
|
||||
**/
|
||||
@:keepSub
|
||||
@:publicFields
|
||||
class TestCase {
|
||||
/**
|
||||
The current test status of the TestRunner.
|
||||
**/
|
||||
public var currentTest : TestStatus;
|
||||
|
||||
public function new( ) {
|
||||
}
|
||||
|
||||
/**
|
||||
Override this method to execute code before the test runs.
|
||||
**/
|
||||
public function setup() : Void {
|
||||
}
|
||||
|
||||
/**
|
||||
Override this method to execute code after the test ran.
|
||||
**/
|
||||
public function tearDown() : Void {
|
||||
}
|
||||
|
||||
function print( v : Dynamic ) {
|
||||
haxe.unit.TestRunner.print(v);
|
||||
}
|
||||
|
||||
/**
|
||||
Succeeds if `b` is `true`.
|
||||
**/
|
||||
function assertTrue( b:Bool, ?c : PosInfos ) : Void {
|
||||
currentTest.done = true;
|
||||
if (b != true){
|
||||
currentTest.success = false;
|
||||
currentTest.error = "expected true but was false";
|
||||
currentTest.posInfos = c;
|
||||
throw currentTest;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Succeeds if `b` is `false`.
|
||||
**/
|
||||
function assertFalse( b:Bool, ?c : PosInfos ) : Void {
|
||||
currentTest.done = true;
|
||||
if (b == true){
|
||||
currentTest.success = false;
|
||||
currentTest.error = "expected false but was true";
|
||||
currentTest.posInfos = c;
|
||||
throw currentTest;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Succeeds if `expected` and `actual` are equal.
|
||||
**/
|
||||
function assertEquals<T>( expected: T , actual: T, ?c : PosInfos ) : Void {
|
||||
currentTest.done = true;
|
||||
if (actual != expected){
|
||||
currentTest.success = false;
|
||||
currentTest.error = "expected '" + expected + "' but was '" + actual + "'";
|
||||
currentTest.posInfos = c;
|
||||
throw currentTest;
|
||||
}
|
||||
}
|
||||
}
|
100
Kha/Backends/Kinc-hxcpp/khacpp/test/unit/haxe/unit/TestResult.hx
Normal file
100
Kha/Backends/Kinc-hxcpp/khacpp/test/unit/haxe/unit/TestResult.hx
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (C)2005-2017 Haxe Foundation
|
||||
*
|
||||
* 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:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package haxe.unit;
|
||||
|
||||
/**
|
||||
TestResult contains the result of the executed unit tests.
|
||||
**/
|
||||
class TestResult {
|
||||
var m_tests : List<TestStatus>;
|
||||
|
||||
/**
|
||||
`true` if the unit test succesfully executed the test cases.
|
||||
**/
|
||||
public var success(default, null) : Bool;
|
||||
|
||||
public function new() {
|
||||
m_tests = new List();
|
||||
success = true;
|
||||
}
|
||||
|
||||
public function add( t:TestStatus ) : Void {
|
||||
m_tests.add(t);
|
||||
if( !t.success )
|
||||
success = false;
|
||||
}
|
||||
|
||||
/**
|
||||
String representation from the result of the unit test.
|
||||
**/
|
||||
public function toString() : String {
|
||||
var buf = new StringBuf();
|
||||
var failures = 0;
|
||||
for ( test in m_tests ){
|
||||
if (test.success == false){
|
||||
buf.add("* ");
|
||||
buf.add(test.classname);
|
||||
buf.add("::");
|
||||
buf.add(test.method);
|
||||
buf.add("()");
|
||||
buf.add("\n");
|
||||
|
||||
buf.add("ERR: ");
|
||||
if( test.posInfos != null ){
|
||||
buf.add(test.posInfos.fileName);
|
||||
buf.add(":");
|
||||
buf.add(test.posInfos.lineNumber);
|
||||
buf.add("(");
|
||||
buf.add(test.posInfos.className);
|
||||
buf.add(".");
|
||||
buf.add(test.posInfos.methodName);
|
||||
buf.add(") - ");
|
||||
}
|
||||
buf.add(test.error);
|
||||
buf.add("\n");
|
||||
|
||||
if (test.backtrace != null) {
|
||||
buf.add(test.backtrace);
|
||||
buf.add("\n");
|
||||
}
|
||||
|
||||
buf.add("\n");
|
||||
failures++;
|
||||
}
|
||||
}
|
||||
buf.add("\n");
|
||||
if (failures == 0)
|
||||
buf.add("OK ");
|
||||
else
|
||||
buf.add("FAILED ");
|
||||
|
||||
buf.add(m_tests.length);
|
||||
buf.add(" tests, ");
|
||||
buf.add(failures);
|
||||
buf.add(" failed, ");
|
||||
buf.add( (m_tests.length - failures) );
|
||||
buf.add(" success");
|
||||
buf.add("\n");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
186
Kha/Backends/Kinc-hxcpp/khacpp/test/unit/haxe/unit/TestRunner.hx
Normal file
186
Kha/Backends/Kinc-hxcpp/khacpp/test/unit/haxe/unit/TestRunner.hx
Normal file
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (C)2005-2017 Haxe Foundation
|
||||
*
|
||||
* 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:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package haxe.unit;
|
||||
import Reflect;
|
||||
|
||||
/**
|
||||
This class runs unit test cases and prints the result.
|
||||
|
||||
```haxe
|
||||
var r = new haxe.unit.TestRunner();
|
||||
r.add(new MyTestCase());
|
||||
// add other TestCases here
|
||||
|
||||
// finally, run the tests
|
||||
r.run();
|
||||
```
|
||||
|
||||
@see <https://haxe.org/manual/std-unit-testing.html>
|
||||
**/
|
||||
class TestRunner {
|
||||
/**
|
||||
The unit test results. Available after the `run()` is called.
|
||||
**/
|
||||
public var result(default, null) : TestResult;
|
||||
|
||||
var cases : List<TestCase>;
|
||||
|
||||
#if flash
|
||||
static var tf : flash.text.TextField = null;
|
||||
#end
|
||||
|
||||
/**
|
||||
Prints the given object/value.
|
||||
|
||||
* Flash outputs the result in a new `TextField` on stage.
|
||||
* JavaScript outputs the result using `console.log`.
|
||||
* Other targets use native `print` to output the result.
|
||||
|
||||
This function is `dynamic` so it can be overriden in custom setups.
|
||||
**/
|
||||
public static dynamic function print( v : Dynamic ) untyped {
|
||||
#if flash
|
||||
if( tf == null ) {
|
||||
tf = new flash.text.TextField();
|
||||
tf.selectable = false;
|
||||
tf.width = flash.Lib.current.stage.stageWidth;
|
||||
tf.autoSize = flash.text.TextFieldAutoSize.LEFT;
|
||||
flash.Lib.current.addChild(tf);
|
||||
}
|
||||
tf.appendText(v);
|
||||
#elseif neko
|
||||
__dollar__print(v);
|
||||
#elseif php
|
||||
php.Lib.print(v);
|
||||
#elseif cpp
|
||||
cpp.Lib.print(v);
|
||||
#elseif js
|
||||
var msg = js.Boot.__string_rec(v,"");
|
||||
var d;
|
||||
if( __js__("typeof")(document) != "undefined"
|
||||
&& (d = document.getElementById("haxe:trace")) != null ) {
|
||||
msg = StringTools.htmlEscape(msg).split("\n").join("<br/>");
|
||||
d.innerHTML += msg+"<br/>";
|
||||
}
|
||||
else if ( __js__("typeof process") != "undefined"
|
||||
&& __js__("process").stdout != null
|
||||
&& __js__("process").stdout.write != null)
|
||||
__js__("process").stdout.write(msg); // node
|
||||
else if ( __js__("typeof console") != "undefined"
|
||||
&& __js__("console").log != null )
|
||||
__js__("console").log(msg); // document-less js (which may include a line break)
|
||||
|
||||
#elseif cs
|
||||
cs.system.Console.Write(v);
|
||||
#elseif java
|
||||
var str:String = v;
|
||||
untyped __java__("java.lang.System.out.print(str)");
|
||||
#elseif python
|
||||
python.Lib.print(v);
|
||||
#elseif (hl || lua)
|
||||
Sys.print(Std.string(v));
|
||||
#end
|
||||
}
|
||||
|
||||
private static function customTrace( v, ?p : haxe.PosInfos ) {
|
||||
print(p.fileName+":"+p.lineNumber+": "+Std.string(v)+"\n");
|
||||
}
|
||||
|
||||
public function new() {
|
||||
result = new TestResult();
|
||||
cases = new List();
|
||||
}
|
||||
|
||||
/**
|
||||
Add TestCase instances to the unit test.
|
||||
**/
|
||||
public function add( c:TestCase ) : Void{
|
||||
cases.add(c);
|
||||
}
|
||||
|
||||
/**
|
||||
Runs the unit tests and prints the results.
|
||||
|
||||
@return `true` if the unit test succesfully executed the test cases.
|
||||
**/
|
||||
public function run() : Bool {
|
||||
result = new TestResult();
|
||||
for ( c in cases ){
|
||||
runCase(c);
|
||||
}
|
||||
print(result.toString());
|
||||
return result.success;
|
||||
}
|
||||
|
||||
function runCase( t:TestCase ) : Void {
|
||||
var old = haxe.Log.trace;
|
||||
haxe.Log.trace = customTrace;
|
||||
|
||||
var cl = Type.getClass(t);
|
||||
var fields = Type.getInstanceFields(cl);
|
||||
|
||||
print( "Class: "+Type.getClassName(cl)+" ");
|
||||
for ( f in fields ){
|
||||
var fname = f;
|
||||
var field = Reflect.field(t, f);
|
||||
if ( StringTools.startsWith(fname,"test") && Reflect.isFunction(field) ){
|
||||
t.currentTest = new TestStatus();
|
||||
t.currentTest.classname = Type.getClassName(cl);
|
||||
t.currentTest.method = fname;
|
||||
t.setup();
|
||||
|
||||
try {
|
||||
Reflect.callMethod(t, field, new Array());
|
||||
|
||||
if( t.currentTest.done ){
|
||||
t.currentTest.success = true;
|
||||
print(".");
|
||||
}else{
|
||||
t.currentTest.success = false;
|
||||
t.currentTest.error = "(warning) no assert";
|
||||
print("W");
|
||||
}
|
||||
}catch ( e : TestStatus ){
|
||||
print("F");
|
||||
t.currentTest.backtrace = haxe.CallStack.toString(haxe.CallStack.exceptionStack());
|
||||
}catch ( e : Dynamic ){
|
||||
print("E");
|
||||
#if js
|
||||
if( e.message != null ){
|
||||
t.currentTest.error = "exception thrown : "+e+" ["+e.message+"]";
|
||||
}else{
|
||||
t.currentTest.error = "exception thrown : "+e;
|
||||
}
|
||||
#else
|
||||
t.currentTest.error = "exception thrown : "+e;
|
||||
#end
|
||||
t.currentTest.backtrace = haxe.CallStack.toString(haxe.CallStack.exceptionStack());
|
||||
}
|
||||
result.add(t.currentTest);
|
||||
t.tearDown();
|
||||
}
|
||||
}
|
||||
|
||||
print("\n");
|
||||
haxe.Log.trace = old;
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C)2005-2017 Haxe Foundation
|
||||
*
|
||||
* 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:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package haxe.unit;
|
||||
import haxe.CallStack;
|
||||
|
||||
import haxe.PosInfos;
|
||||
|
||||
/**
|
||||
The status information of a unit test case method.
|
||||
|
||||
@see <https://haxe.org/manual/std-unit-testing.html>
|
||||
**/
|
||||
class TestStatus {
|
||||
/**
|
||||
`true` when the unit test is executed.
|
||||
**/
|
||||
public var done : Bool;
|
||||
|
||||
/**
|
||||
`true` when succesfully unit tested.
|
||||
**/
|
||||
public var success : Bool;
|
||||
|
||||
/**
|
||||
The error message of the unit test method.
|
||||
**/
|
||||
public var error : String;
|
||||
|
||||
/**
|
||||
The method name of the unit test.
|
||||
**/
|
||||
public var method : String;
|
||||
|
||||
/**
|
||||
The class name of the unit test.
|
||||
**/
|
||||
public var classname : String;
|
||||
|
||||
/**
|
||||
The position information of the unit test.
|
||||
**/
|
||||
public var posInfos : PosInfos;
|
||||
|
||||
/**
|
||||
The representation of the stack exception.
|
||||
**/
|
||||
public var backtrace : String;
|
||||
|
||||
public function new() {
|
||||
done = false;
|
||||
success = false;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user