added spec + updated tests

This commit is contained in:
Leon van Kammen 2023-03-17 16:06:24 +01:00
parent 8dceb33b3e
commit 045efa0349
11 changed files with 192 additions and 114 deletions

9
dist/xrfragment.js vendored
View File

@ -76,9 +76,6 @@ Std.parseInt = function(x) {
}
return null;
};
var haxe_ds_StringMap = function() {
this.h = Object.create(null);
};
var haxe_iterators_ArrayIterator = function(array) {
this.current = 0;
this.array = array;
@ -102,7 +99,7 @@ var xrfragment_Query = function(str) {
}
};
xrfragment_Query.prototype = {
qualify: function(nodename) {
selected: function(nodename) {
if(this.q.copy_all) {
this.accept = true;
}
@ -290,7 +287,7 @@ xrfragment_Url.parse = function(qs) {
var fragment = qs.split("#");
var splitArray = fragment[1].split("&");
var regexPlus = new EReg("\\+","g");
var resultMap = new haxe_ds_StringMap();
var resultMap = { };
var _g = 0;
var _g1 = splitArray.length;
while(_g < _g1) {
@ -314,7 +311,7 @@ xrfragment_Url.parse = function(qs) {
v.args.push(x);
}
}
resultMap.h[key] = v;
resultMap[key] = v;
}
}
return resultMap;

2
dist/xrfragment.lua vendored
View File

@ -1148,7 +1148,7 @@ __xrfragment_Query.prototype = _hx_e();
__xrfragment_Query.prototype.toObject = function(self)
do return self.q end
end
__xrfragment_Query.prototype.qualify = function(self,nodename)
__xrfragment_Query.prototype.selected = function(self,nodename)
if (self.q.copy_all) then
self.accept = true;
end;

4
dist/xrfragment.py vendored
View File

@ -1183,7 +1183,7 @@ class xrfragment_Query:
_hx_class_name = "xrfragment.Query"
__slots__ = ("str", "q", "include", "exclude", "accept", "preset")
_hx_fields = ["str", "q", "include", "exclude", "accept", "preset"]
_hx_methods = ["toObject", "qualify", "parse", "test"]
_hx_methods = ["toObject", "selected", "parse", "test"]
def __init__(self,_hx_str):
self.preset = ""
@ -1198,7 +1198,7 @@ class xrfragment_Query:
def toObject(self):
return self.q
def qualify(self,nodename):
def selected(self,nodename):
if Reflect.field(self.q,"copy_all"):
self.accept = True
if (nodename in self.include):

10
make
View File

@ -22,10 +22,12 @@ install(){
haxelib install hscript
}
runtest(){
set -x
which python3 && python3 test/generated/test.py | awk '{ print "py: "$0 } END{ print "\n"}'
which node && node test/generated/test.js | awk '{ print "js: "$0 } END{ print "\n"}'
tests(){
{
which python3 && python3 test/generated/test.py src/spec/*.json | awk '{ print "py: "$0 } END{ print "\n"}'
which node && node test/generated/test.js src/spec/*.json | awk '{ print "js: "$0 } END{ print "\n"}'
} | tee /tmp/log.txt
grep error /tmp/log.txt && exit 1
}
test -z $1 && { try rm dist/* ; haxe build.hxml; exit $?; }

View File

@ -1,14 +1,52 @@
import xrfragment.Query;
import xrfragment.Url;
class Spec {
macro public static function load(path : String) {
var value = sys.io.File.getContent(path),
json = haxe.Json.parse(value);
return macro $v{json};
}
}
class Test {
static public function main():Void {
trace("starting tests");
testUrl();
//testQuery();
test( Spec.load("src/spec/query.or.json") );
test( Spec.load("src/spec/url.json") );
}
static public function test(spec:Array<Dynamic>):Void {
var Query = xrfragment.Query;
var errors:Int = 0;
for( i in 0...spec.length ){
var q:Query = null;
var res:haxe.DynamicAccess<Dynamic> = null;
var valid:Bool = false;
var item:Dynamic = spec[i];
if( item.fn == "query" ) q = new Query(item.data);
if( item.fn == "url" ) res = Url.parse(item.data);
if( item.expect.fn == "selected" ) valid = item.expect.out == q.selected( item.expect.input );
if( item.expect.fn == "equal.string" ) valid = item.expect.out == res.get(item.expect.input).string;
if( item.expect.fn == "equal.xy" ) valid = item.expect.out == (Std.string(res.get(item.expect.input).x) + Std.string(res.get(item.expect.input).y) );
if( item.expect.fn == "equal.multi" ) valid = equalMulti(res, item);
var ok:String = valid ? "[ ] " : "[ ] ";
trace( ok + item.fn + ": '" + item.data + "'" + (item.label ? " <= " + (item.label?item.label:item.expect.fn) : ""));
if( !valid ) errors += 1;
}
if( errors > 1 ) trace("\n-----\n[ ] "+errors+" errors :/");
}
static public function equalMulti(res:haxe.DynamicAccess<Dynamic>, item:Dynamic):Bool {
var target:Dynamic = res.get(item.expect.input);
var str:String = "";
for( i in 0...target.args.length ){
str = str + "|" + target.args[i].string;
}
str = str.substr(1);
return str == item.expect.out;
}
static public function testUrl():Void {
var Url = xrfragment.Url;
var uri:String = "http://foo.com?foo=1#bar=flop&a=1,2&b=c|d|1,2,3";
@ -32,97 +70,97 @@ class Test {
var q:Dynamic = new Query("price:!=4 moo or bar");
var obj:Dynamic = q.toObject();
q.test( "price", 4);
var ok = !q.qualify("slkklskdf");
var ok = !q.selected("slkklskdf");
if( !ok ) throw 'node should not be allowed';
q = new Query("price:!=3 moo or bar");
var obj:Dynamic = q.toObject();
q.test( "price", 4);
var ok = q.qualify("slkklskdf");
var ok = q.selected("slkklskdf");
if( !ok ) throw 'non-mentioned node should be allowed';
q = new Query("moo or bar");
var obj:Dynamic = q.toObject();
var ok = !q.qualify("slkklskdf");
var ok = !q.selected("slkklskdf");
if( !ok ) throw 'node should not be allowed';
obj = q.toObject();
var ok = q.qualify("moo");
var ok = q.selected("moo");
if( !ok ) throw 'moo should be allowed';
var ok = q.qualify("bar");
var ok = q.selected("bar");
if( !ok ) throw 'bar should be allowed';
q = new Query("price:>3 moo or bar");
var obj:Dynamic = q.toObject();
q.test( "price", 4);
var ok = q.qualify("foo");
var ok = q.selected("foo");
if( !ok ) throw 'node should be allowed';
var ok = q.qualify("bar");
var ok = q.selected("bar");
if( !ok ) throw 'node should be allowed';
var ok = q.qualify("moo");
var ok = q.selected("moo");
if( !ok ) throw 'node should be allowed';
q = new Query("price:>3 price:<10 -bar");
var obj:Dynamic = q.toObject();
q.test( "price", 4);
var ok = q.qualify("foo");
var ok = q.selected("foo");
if( !ok ) throw 'node should be allowed';
var ok = !q.qualify("bar");
var ok = !q.selected("bar");
if( !ok ) throw 'bar should not be allowed';
q.test("price", 20);
var ok = !q.qualify("foo");
var ok = !q.selected("foo");
if( !ok ) throw 'price 20 should not be allowed';
q = new Query("-bar");
var obj:Dynamic = q.toObject();
var ok = q.qualify("foo");
var ok = q.selected("foo");
if( !ok ) throw 'node should be allowed';
var ok = !q.qualify("bar");
var ok = !q.selected("bar");
if( !ok ) throw 'bar should not be allowed';
q = new Query("title:*");
var obj:Dynamic = q.toObject();
var ok = !q.qualify("foo");
var ok = !q.selected("foo");
if( !ok ) throw 'node should not be allowed';
q.test("foo","bar");
var ok = !q.qualify("foo");
var ok = !q.selected("foo");
if( !ok ) throw 'node should not be allowed';
q.test("title","bar");
var ok = q.qualify("foo");
var ok = q.selected("foo");
if( !ok ) throw 'node should be allowed';
q = new Query("-bar +bar");
var obj:Dynamic = q.toObject();
var ok = q.qualify("foo");
var ok = q.selected("foo");
if( !ok ) throw 'node should be allowed';
var ok = q.qualify("bar");
var ok = q.selected("bar");
if( !ok ) throw 'bar should be allowed';
q = new Query("?discount");
var obj:Dynamic = q.toObject();
q.test("?discount","-foo");
var ok = !q.qualify("foo");
var ok = !q.selected("foo");
if( !ok ) throw 'foo should not be allowed';
q = new Query("?");
q.test("?","-foo");
var ok = !q.qualify("foo");
var ok = !q.selected("foo");
if( !ok ) throw 'foo should not be allowed';
q = new Query("?");
var ok = q.qualify("foo");
var ok = q.selected("foo");
if( !ok ) throw 'foo should not be allowed';
q = new Query("?discount");
q.test("?discount","-foo");
var ok = !q.qualify("foo");
var ok = !q.selected("foo");
if( !ok ) throw 'foo should not be allowed';
q = new Query("?discount +foo");
var obj:Dynamic = q.toObject();
q.test("?discount","-foo");
var ok = !q.qualify("foo");
var ok = !q.selected("foo");
if( !ok ) throw 'foo should not be allowed';
var ok = !q.qualify("foo");
var ok = !q.selected("foo");
if( !ok ) throw 'foo should not be allowed';
trace("all tests passed");

4
src/spec/query.or.json Normal file
View File

@ -0,0 +1,4 @@
[
{"fn":"query","data":"foo or bar", "expect":{ "fn":"selected","input":"foo","out":true}},
{"fn":"query","data":"foo or bar", "expect":{ "fn":"selected","input":"xxx","out":false}, "label":"nonselected entity"}
]

5
src/spec/url.json Normal file
View File

@ -0,0 +1,5 @@
[
{"fn":"url","data":"http://foo.com?foo=1#bar=flop&a=1,2&b=c|d|1,2,3", "expect":{ "fn":"equal.string","input":"bar","out":"flop"}},
{"fn":"url","data":"http://foo.com?foo=1#bar=flop&a=1.2,2.2&b=c|d|1,2,3", "expect":{ "fn":"equal.xy", "input":"a","out":"1.22.2"},"label":"a equal.xy"},
{"fn":"url","data":"http://foo.com?foo=1#b=c|d|1,2,3", "expect":{ "fn":"equal.multi", "input":"b","out":"c|d|1,2,3"},"label":"b equal.multi"}
]

View File

@ -54,7 +54,7 @@ class Query {
}
@:keep
public function qualify( nodename:String ): Bool {
public function selected( nodename:String ): Bool {
if( this.q.copy_all ) this.accept = true;
if( this.include.contains(nodename) ) this.accept = true;
if( this.exclude.contains(nodename) ) this.accept = false;

View File

@ -18,11 +18,11 @@ class Value {
class Url {
@:keep
public static function parse(qs:String):Map<String, Value> {
public static function parse(qs:String):haxe.DynamicAccess<Dynamic> {
var fragment:Array<String> = qs.split("#");
var splitArray:Array<String> = fragment[1].split('&');
var regexPlus = ~/\+/g; // Regex for replacing addition symbol with a space
var resultMap = new Map<String,Value>();
var resultMap:haxe.DynamicAccess<Dynamic> = {};
for (i in 0...splitArray.length) {
var splitByEqual = splitArray[i].split('=');
var key:String = splitByEqual[0];

View File

@ -87,28 +87,59 @@ Std.parseInt = function(x) {
var Test = function() { };
Test.__name__ = true;
Test.main = function() {
console.log("src/Test.hx:7:","starting tests");
Test.testUrl();
Test.test([{ fn : "query", expect : { fn : "selected", input : "foo", out : true}, data : "foo or bar"},{ fn : "query", expect : { fn : "selected", input : "xxx", out : false}, label : "nonselected entity", data : "foo or bar"}]);
Test.test([{ fn : "url", expect : { fn : "equal.string", input : "bar", out : "flop"}, data : "http://foo.com?foo=1#bar=flop&a=1,2&b=c|d|1,2,3"},{ fn : "url", expect : { fn : "equal.xy", input : "a", out : "1.22.2"}, label : "a equal.xy", data : "http://foo.com?foo=1#bar=flop&a=1.2,2.2&b=c|d|1,2,3"},{ fn : "url", expect : { fn : "equal.multi", input : "b", out : "c|d|1,2,3"}, label : "b equal.multi", data : "http://foo.com?foo=1#b=c|d|1,2,3"}]);
};
Test.testUrl = function() {
var Url = xrfragment_Url;
var uri = "http://foo.com?foo=1#bar=flop&a=1,2&b=c|d|1,2,3";
console.log("src/Test.hx:15:",uri);
var tmp = Url.parse(uri);
console.log("src/Test.hx:16:",tmp == null ? "null" : haxe_ds_StringMap.stringify(tmp.h));
};
var haxe_ds_StringMap = function() {
this.h = Object.create(null);
};
haxe_ds_StringMap.__name__ = true;
haxe_ds_StringMap.stringify = function(h) {
var s = "{";
var first = true;
for (var key in h) {
if (first) first = false; else s += ',';
s += key + ' => ' + Std.string(h[key]);
Test.test = function(spec) {
var Query = xrfragment_Query;
var errors = 0;
var _g = 0;
var _g1 = spec.length;
while(_g < _g1) {
var i = _g++;
var q = null;
var res = null;
var valid = false;
var item = spec[i];
if(item.fn == "query") {
q = new xrfragment_Query(item.data);
}
if(item.fn == "url") {
res = xrfragment_Url.parse(item.data);
}
if(item.expect.fn == "selected") {
valid = item.expect.out == q.selected(item.expect.input);
}
if(item.expect.fn == "equal.string") {
valid = item.expect.out == res[item.expect.input].string;
}
if(item.expect.fn == "equal.xy") {
valid = item.expect.out == Std.string(res[item.expect.input].x) + Std.string(res[item.expect.input].y);
}
if(item.expect.fn == "equal.multi") {
valid = Test.equalMulti(res,item);
}
var ok = valid ? "[ ✔ ] " : "[ ❌] ";
console.log("src/Test.hx:34:",ok + Std.string(item.fn) + ": '" + Std.string(item.data) + "'" + (item.label ? " <= " + (item.label ? item.label : item.expect.fn) : ""));
if(!valid) {
++errors;
}
}
return s + "}";
if(errors > 1) {
console.log("src/Test.hx:37:","\n-----\n[ ❌] " + errors + " errors :/");
}
};
Test.equalMulti = function(res,item) {
var target = res[item.expect.input];
var str = "";
var _g = 0;
var _g1 = target.args.length;
while(_g < _g1) {
var i = _g++;
str = str + "|" + target.args[i].string;
}
str = HxOverrides.substr(str,1,null);
return str == item.expect.out;
};
var haxe_iterators_ArrayIterator = function(array) {
this.current = 0;
@ -201,7 +232,7 @@ var xrfragment_Query = function(str) {
};
xrfragment_Query.__name__ = true;
xrfragment_Query.prototype = {
qualify: function(nodename) {
selected: function(nodename) {
if(this.q.copy_all) {
this.accept = true;
}
@ -391,7 +422,7 @@ xrfragment_Url.parse = function(qs) {
var fragment = qs.split("#");
var splitArray = fragment[1].split("&");
var regexPlus = new EReg("\\+","g");
var resultMap = new haxe_ds_StringMap();
var resultMap = { };
var _g = 0;
var _g1 = splitArray.length;
while(_g < _g1) {
@ -415,7 +446,7 @@ xrfragment_Url.parse = function(qs) {
v.args.push(x);
}
}
resultMap.h[key] = v;
resultMap[key] = v;
}
}
return resultMap;

View File

@ -7,7 +7,6 @@ import sys as python_lib_Sys
import functools as python_lib_Functools
import re as python_lib_Re
import traceback as python_lib_Traceback
from io import StringIO as python_lib_io_StringIO
import urllib.parse as python_lib_urllib_Parse
@ -329,25 +328,57 @@ class Dynamic: pass
class Test:
_hx_class_name = "Test"
__slots__ = ()
_hx_statics = ["main", "testUrl"]
_hx_statics = ["main", "test", "equalMulti"]
@staticmethod
def main():
print("starting tests")
Test.testUrl()
Test.test([_hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "selected", 'input': "foo", 'out': True}), 'data': "foo or bar"}), _hx_AnonObject({'fn': "query", 'expect': _hx_AnonObject({'fn': "selected", 'input': "xxx", 'out': False}), 'label': "nonselected entity", 'data': "foo or bar"})])
Test.test([_hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.string", 'input': "bar", 'out': "flop"}), 'data': "http://foo.com?foo=1#bar=flop&a=1,2&b=c|d|1,2,3"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.xy", 'input': "a", 'out': "1.22.2"}), 'label': "a equal.xy", 'data': "http://foo.com?foo=1#bar=flop&a=1.2,2.2&b=c|d|1,2,3"}), _hx_AnonObject({'fn': "url", 'expect': _hx_AnonObject({'fn': "equal.multi", 'input': "b", 'out': "c|d|1,2,3"}), 'label': "b equal.multi", 'data': "http://foo.com?foo=1#b=c|d|1,2,3"})])
@staticmethod
def testUrl():
Url = xrfragment_Url
uri = "http://foo.com?foo=1#bar=flop&a=1,2&b=c|d|1,2,3"
print(str(uri))
tmp = Url.parse(uri)
print(str(("null" if ((tmp is None)) else tmp.toString())))
def test(spec):
Query = xrfragment_Query
errors = 0
_g = 0
_g1 = len(spec)
while (_g < _g1):
i = _g
_g = (_g + 1)
q = None
res = None
valid = False
item = (spec[i] if i >= 0 and i < len(spec) else None)
if (Reflect.field(item,"fn") == "query"):
q = xrfragment_Query(Reflect.field(item,"data"))
if (Reflect.field(item,"fn") == "url"):
res = xrfragment_Url.parse(Reflect.field(item,"data"))
if (Reflect.field(Reflect.field(item,"expect"),"fn") == "selected"):
valid = (Reflect.field(Reflect.field(item,"expect"),"out") == q.selected(Reflect.field(Reflect.field(item,"expect"),"input")))
if (Reflect.field(Reflect.field(item,"expect"),"fn") == "equal.string"):
valid = HxOverrides.eq(Reflect.field(Reflect.field(item,"expect"),"out"),Reflect.field(Reflect.field(res,Reflect.field(Reflect.field(item,"expect"),"input")),"string"))
if (Reflect.field(Reflect.field(item,"expect"),"fn") == "equal.xy"):
valid = (Reflect.field(Reflect.field(item,"expect"),"out") == ((Std.string(Reflect.field(Reflect.field(res,Reflect.field(Reflect.field(item,"expect"),"input")),"x")) + Std.string(Reflect.field(Reflect.field(res,Reflect.field(Reflect.field(item,"expect"),"input")),"y")))))
if (Reflect.field(Reflect.field(item,"expect"),"fn") == "equal.multi"):
valid = Test.equalMulti(res,item)
ok = ("[ ✔ ] " if valid else "[ ❌] ")
print(str((((((("null" if ok is None else ok) + Std.string(Reflect.field(item,"fn"))) + ": '") + Std.string(Reflect.field(item,"data"))) + "'") + HxOverrides.stringOrNull((((" <= " + HxOverrides.stringOrNull(((Reflect.field(item,"label") if (Reflect.field(item,"label")) else Reflect.field(Reflect.field(item,"expect"),"fn"))))) if (Reflect.field(item,"label")) else ""))))))
if (not valid):
errors = (errors + 1)
if (errors > 1):
print(str((("\n-----\n[ ❌] " + Std.string(errors)) + " errors :/")))
class haxe_IMap:
_hx_class_name = "haxe.IMap"
__slots__ = ()
@staticmethod
def equalMulti(res,item):
target = Reflect.field(res,Reflect.field(Reflect.field(item,"expect"),"input"))
_hx_str = ""
_g = 0
_g1 = Reflect.field(Reflect.field(target,"args"),"length")
while (_g < _g1):
i = _g
_g = (_g + 1)
_hx_str = ((("null" if _hx_str is None else _hx_str) + "|") + HxOverrides.stringOrNull(HxOverrides.arrayGet(Reflect.field(target,"args"), i).string))
_hx_str = HxString.substr(_hx_str,1,None)
return (_hx_str == Reflect.field(Reflect.field(item,"expect"),"out"))
class haxe_Exception(Exception):
@ -431,36 +462,6 @@ class haxe_ValueException(haxe_Exception):
class haxe_ds_StringMap:
_hx_class_name = "haxe.ds.StringMap"
__slots__ = ("h",)
_hx_fields = ["h"]
_hx_methods = ["keys", "toString"]
_hx_interfaces = [haxe_IMap]
def __init__(self):
self.h = dict()
def keys(self):
return python_HaxeIterator(iter(self.h.keys()))
def toString(self):
s_b = python_lib_io_StringIO()
s_b.write("{")
it = self.keys()
i = it
while i.hasNext():
i1 = i.next()
s_b.write(Std.string(i1))
s_b.write(" => ")
s_b.write(Std.string(Std.string(self.h.get(i1,None))))
if it.hasNext():
s_b.write(", ")
s_b.write("}")
return s_b.getvalue()
class haxe_iterators_ArrayIterator:
_hx_class_name = "haxe.iterators.ArrayIterator"
__slots__ = ("array", "current")
@ -1292,7 +1293,7 @@ class xrfragment_Query:
_hx_class_name = "xrfragment.Query"
__slots__ = ("str", "q", "include", "exclude", "accept", "preset")
_hx_fields = ["str", "q", "include", "exclude", "accept", "preset"]
_hx_methods = ["toObject", "qualify", "parse", "test"]
_hx_methods = ["toObject", "selected", "parse", "test"]
def __init__(self,_hx_str):
self.preset = ""
@ -1307,7 +1308,7 @@ class xrfragment_Query:
def toObject(self):
return self.q
def qualify(self,nodename):
def selected(self,nodename):
if Reflect.field(self.q,"copy_all"):
self.accept = True
if (nodename in self.include):
@ -1514,7 +1515,7 @@ class xrfragment_Url:
_this = (fragment[1] if 1 < len(fragment) else None)
splitArray = _this.split("&")
regexPlus = EReg("\\+","g")
resultMap = haxe_ds_StringMap()
resultMap = _hx_AnonObject({})
_g = 0
_g1 = len(splitArray)
while (_g < _g1):
@ -1540,7 +1541,7 @@ class xrfragment_Url:
xrfragment_Url.guessType(x,(args[i1] if i1 >= 0 and i1 < len(args) else None))
_this2 = v.args
_this2.append(x)
resultMap.h[key] = v
setattr(resultMap,(("_hx_" + key) if ((key in python_Boot.keywords)) else (("_hx_" + key) if (((((len(key) > 2) and ((ord(key[0]) == 95))) and ((ord(key[1]) == 95))) and ((ord(key[(len(key) - 1)]) != 95)))) else key)),v)
return resultMap
@staticmethod