diff --git a/test/README.txt b/test/README.txt new file mode 100644 index 00000000..c7d16dfe --- /dev/null +++ b/test/README.txt @@ -0,0 +1,8 @@ +To run the tests, add something like this to your apps.properties file: + +test +test.appdir = apps/test/code +test.repository.0 = apps/test/code +test.repository.1 = modules/jala/util/Test/code + +And you need to have a MySQL JDBC driver in lib/ext, as well as create the database schema provided in db.sql. diff --git a/test/code/Global/global.js b/test/code/Global/global.js new file mode 100755 index 00000000..b162d4d9 --- /dev/null +++ b/test/code/Global/global.js @@ -0,0 +1,33 @@ +function onStart() { + root.date = new Date(); + root.string = "root"; +} + +function hello_macro(param) { + return "hello"; +} + +function echo_macro(param, arg) { + return arg || param.what; +} + +function isDate_filter(arg) { + return arg instanceof Date; +} + +function isRootDate_filter(arg) { + return (arg instanceof Date) && + arg.getTime() == root.date.getTime(); +} + +function isResponseDate_filter(arg) { + return (arg instanceof Date) && arg == res.data.date; +} + +function makeLongString() { + var b = new java.lang.StringBuffer(); + for (var i = 1; i <= 10000; i++) { + b.append(i.toString()).append(" "); + } + return b.toString(); +} diff --git a/test/code/Global/subskins.skin b/test/code/Global/subskins.skin new file mode 100755 index 00000000..379245b9 --- /dev/null +++ b/test/code/Global/subskins.skin @@ -0,0 +1 @@ +mainskin<% #subskin1 %>subskin1<% #subskin2 %>subskin2<% #end %> diff --git a/test/code/Organisation/type.properties b/test/code/Organisation/type.properties new file mode 100644 index 00000000..c290c151 --- /dev/null +++ b/test/code/Organisation/type.properties @@ -0,0 +1,17 @@ + +_db = dbcTest +_table = tb_organisation + +_id = org_id +_parent = root.organisations + +persons = collection(Person) +persons.local = org_id +persons.foreign = person_org_id +persons.accessname = person_name +persons.order = person_name + +name = org_name +country = org_country + +someMountpoint = mountpoint(SomeMountpoint) diff --git a/test/code/Person/type.properties b/test/code/Person/type.properties new file mode 100644 index 00000000..ccc29ad1 --- /dev/null +++ b/test/code/Person/type.properties @@ -0,0 +1,14 @@ + +_db = dbcTest +_table = tb_person + +_id = person_id +_parent = organisation.persons, root.persons + +name = person_name +height = person_height +dateOfBirth = person_dateofbirth + +organisation = object(Organisation) +organisation.local = person_org_id +organisation.foreign = org_id diff --git a/test/code/Root/root.js b/test/code/Root/root.js new file mode 100755 index 00000000..4fe3c512 --- /dev/null +++ b/test/code/Root/root.js @@ -0,0 +1,35 @@ +function main_action() { + res.redirect(root.href("jala.test")); +} + +function hello_action() { + res.contentType = "text/plain"; + res.write("Hello"); +} + +function throwerror_action() { + throw Error(); +} + +function notfound_action() { + res.write("Not found"); +} + +function redirect_action() { + res.redirect(this.href("hello")); +} + +function error_action() { + res.write("Error"); +} + +function long_action() { + res.write(makeLongString()); +} + +function macro_macro(param) { + // change suffix + if (param.suffix) param.suffix = "."; + return this.string; +} + diff --git a/test/code/Root/type.properties b/test/code/Root/type.properties new file mode 100755 index 00000000..05a31029 --- /dev/null +++ b/test/code/Root/type.properties @@ -0,0 +1,16 @@ +date = date +string = string + + +organisations = collection(Organisation) +organisations.accessname = org_name + +organisationsByCountry = collection(Organisation) +organisationsByCountry.group = org_country +organisationsByCountry.group.prototype = Country +organisationsByCountry.group.order = org_country desc +organisationsByCountry.order = org_name desc + +persons = collection(Person) + +someMountpoint = mountpoint(SomeMountpoint) diff --git a/test/code/app.properties b/test/code/app.properties new file mode 100755 index 00000000..adf335b9 --- /dev/null +++ b/test/code/app.properties @@ -0,0 +1 @@ +baseUri = http://localhost:8080/test/ diff --git a/test/code/db.properties b/test/code/db.properties new file mode 100644 index 00000000..1f8a35c7 --- /dev/null +++ b/test/code/db.properties @@ -0,0 +1,5 @@ + +dbcTest.url = jdbc:mysql://localhost/helmaTest +dbcTest.driver = org.gjt.mm.mysql.Driver +dbcTest.user = helma +dbcTest.password = secret diff --git a/test/db.sql b/test/db.sql new file mode 100644 index 00000000..f2492706 --- /dev/null +++ b/test/db.sql @@ -0,0 +1,21 @@ + +CREATE DATABASE helmaTest; +USE helmaTest; + +GRANT ALL ON helmaTest.* TO helma@localhost IDENTIFIED BY 'secret'; + +CREATE TABLE tb_person ( + person_id MEDIUMINT(10) NOT NULL, + person_name TINYTEXT, + person_height TINYINT unsigned, + person_dateofbirth DATETIME, + person_org_id MEDIUMINT(10) unsigned, + PRIMARY KEY (person_id) +); + +CREATE TABLE tb_organisation ( + org_id MEDIUMINT(10) unsigned NOT NULL, + org_name TINYTEXT, + org_country TINYTEXT, + PRIMARY KEY (org_id) +); diff --git a/test/tests/HopObjectBasicMapping.js b/test/tests/HopObjectBasicMapping.js new file mode 100644 index 00000000..d5c3c320 --- /dev/null +++ b/test/tests/HopObjectBasicMapping.js @@ -0,0 +1,133 @@ +tests = [ + "testSimpleMapping", + "testSimpleCollection", + "testObjectReference", + "testCollectionForReference" +]; + +function setup() { +} + +function testSimpleMapping() { + + var data = { + name: "Oliver Stone", + dateOfBirth: new Date(1946, 8, 15, 6, 0, 0), + height: 182 + }; + var person = new Person(); + person.name = data.name; + person.dateOfBirth = data.dateOfBirth; + person.height = data.height; + root.persons.add(person); + var personId = person._id; + + res.commit(); // Commit Transaction + app.clearCache(); // Clear cache so that object is refetched + + var person = Person.getById(personId); + assertNotNull(person); + assertEqual(person._prototype, "Person"); + assertEqual(person._id, personId); + assertEqual(person.name, data.name); + assertEqual(person.height, data.height); + assertEqual(person.dateOfBirth.valueOf(), data.dateOfBirth.valueOf()); + res.commit(); + + person.remove(); +} + +function testSimpleCollection() { + + var data = { + name: "Helma" + }; + var orgCount = root.organisations.count(); + var org = new Organisation(); + org.name = data.name; + root.organisations.add(org); + var orgId = org._id; + + assertEqual(orgCount + 1, root.organisations.count()); + assertNotEqual(root.organisations.indexOf(org), -1); + + // fetch Object via position + assertEqual(root.organisations.get(root.organisations.indexOf(org)), org); + + // fetch Object via accessname + assertEqual(root.organisations.get(data.name), org); + + // fetch Object via id + assertEqual(root.organisations.getById(orgId), org); + + // test list + assertEqual(root.organisations.count(), root.organisations.list().length); + + org.remove(); + + assertEqual(orgCount, root.organisations.count()); + assertEqual(root.organisations.indexOf(org), -1); + assertNull(root.organisations.get(data.name)); + assertNull(root.organisations.getById(orgId)); + +} + + +function testObjectReference() { + + var org = new Organisation(); + org.name = "Helma"; + root.organisations.add(org); + var orgId = org._id; + + var person = new Person(); + person.name = "Hannes"; + person.organisation = org; + root.persons.add(person); + var personId = person._id; + + res.commit(); // Commit Transaction + app.clearCache(); // Clear cache so that object is refetched + + var org = Organisation.getById(orgId); + var person = Person.getById(personId); + assertEqual(person.organisation, org); + + org.remove(); + res.commit(); // Commit Transaction + + assertNull(person.organisation); + + person.remove(); +} + + +function testCollectionForReference() { + + var org = new Organisation(); + org.name = "Helma"; + root.organisations.add(org); + var orgId = org._id; + var personCount = org.persons.count(); + + var person = new Person(); + person.name = "Hannes"; + person.organisation = org; + root.persons.add(person); + org.persons.add(person); + + assertEqual(personCount + 1, org.persons.count()); + assertNotEqual(org.persons.indexOf(person), -1); + + org.persons.removeChild(person); + person.remove(); + + assertEqual(personCount, org.persons.count()); + assertEqual(org.persons.indexOf(person), -1); + + org.remove(); +} + + +function cleanup() { +} diff --git a/test/tests/HopObjectCollection.js b/test/tests/HopObjectCollection.js new file mode 100644 index 00000000..6f409b0b --- /dev/null +++ b/test/tests/HopObjectCollection.js @@ -0,0 +1,103 @@ +tests = [ + "testSize", + "testAddRemoveSmall", + "testAddRemoveLarge", + "testListSmall", + "testListLarge" +]; + +var helma, ikea; +var small = 3, large = 1234; + +function setup() { + ikea = makeOrg('Ikea', large); + helma = makeOrg('Helma', small); +} + +function testSize() { + assertEqual(ikea.persons.size(), large); + assertEqual(helma.persons.size(), small); +} + +function testAddRemoveSmall(org) { + testAddRemove(helma, small); +} + +function testAddRemoveLarge(org) { + testAddRemove(ikea, large); +} + +function testAddRemove(org, size) { + var person = new Person(); + person.name = "TestPerson"; + person.organisation = org; + person.persist(); + res.commit(); + assertEqual(org.persons.size(), size + 1); + org.persons.prefetchChildren(); + assertEqual(org.persons.indexOf(person), size); + assertEqual(org.persons.contains(person), size); + assertEqual(person.href(), org.persons.href() + "TestPerson/"); + person.remove(); + res.commit(); + assertEqual(org.persons.size(), size); + assertEqual(org.persons.indexOf(person), -1); + assertEqual(org.persons.contains(person), -1); +} + +function testListSmall() { + testList(helma, small); +} + +function testListLarge() { + testList(ikea, large); +} + +function testList(org, size) { + function iterate(list, start, length) { + assertEqual(list.length, length); + for (var i = 0; i < length; i++) { + assertEqual(list[i].name, "Person " + org.name + " " + (start + i).format("0000")); + } + } + iterate(org.persons.list(), 0, size); + org.persons.invalidate(); + iterate(org.persons.list(), 0, size); + org.persons.invalidate(); + iterate(org.persons.list(1, size - 2), 1, size - 2); +} + +function cleanup() { + var persons = root.persons.list(); + for each (var person in persons) { + person.remove(); + } + ikea.remove(); + helma.remove(); +} + +function makeOrg(name, size) { + var org = new Organisation(); + org.name = name; + root.organisations.add(org); + + for (var i = 0; i < size; i++) { + var person = new Person(); + person.name = "Person " + name + " " + i.format("0000"); + person.organisation = org; + root.persons.add(person); + } + res.commit(); + return org; +} + +// debugging helpers +function dumpDataChange(message) { + res.debug(message + ": "); + dumpDataChangeFor("Person"); + dumpDataChangeFor("Organisation"); +} + +function dumpDataChangeFor(name) { + res.debug(name + ": " + app.__app__.getDbMapping(name).getLastDataChange()); +} diff --git a/test/tests/HopObjectGroupBy.js b/test/tests/HopObjectGroupBy.js new file mode 100644 index 00000000..ae7f2718 --- /dev/null +++ b/test/tests/HopObjectGroupBy.js @@ -0,0 +1,140 @@ +tests = [ + "testGroupByAddRemoveCommit", + "testGroupByAddRemoveNoCommit", + "testGroupOrder", + "testGroupTransient" +]; + +// todo: run with different sizes +var size = 1234; + +function setup() { + for (var i = 0; i < size; i++) { + var org = new Organisation(); + org.name = "Organisation " + i; + org.country = "C" + i; + root.organisations.add(org); + } + res.commit(); +} + +function testGroupByAddRemoveCommit() { + var countryCount = root.organisationsByCountry.count(); + var org = new Organisation(); + org.country = "AT" + Math.random(); + org.name = "Helma" + Math.random(); + root.organisations.add(org); + res.commit(); // Commit Transaction + + var country = root.organisationsByCountry.get(org.country); + assertEqual(countryCount + 1, root.organisationsByCountry.count()); + assertNotNull(country); + assertEqual(country._prototype, "Country"); + assertEqual(country._id, org.country); + + org.remove(); + res.commit(); // Commit Transaction + + assertNull(root.organisationsByCountry.get(org.country)); + assertEqual(countryCount, root.organisationsByCountry.count()); +} + +function testGroupByAddRemoveNoCommit() { + + var countryCount = root.organisationsByCountry.count(); + var org = new Organisation(); + org.country = "AT" + Math.random(); + org.name = "Helma" + Math.random(); + root.organisations.add(org); + root.organisationsByCountry.add(org); + + // FIXME HELMABUG: count does not get incremented immediately + assertEqual(countryCount + 1, root.organisationsByCountry.count()); + + var country = root.organisationsByCountry.get(org.country); + assertNotNull(country); + assertEqual(country._prototype, "Country"); + assertEqual(country._id, org.country); + assertEqual(country.count(), 1); + assertEqual(country.get(0), org); + + root.organisationsByCountry.removeChild(org); + org.remove(); + + // FIXME HELMABUG: country is still accessible at this point + // similar to http://helma.org/bugs/show_bug.cgi?id=551 + assertNull(root.organisationsByCountry.get(org.country)); + + assertEqual(countryCount, root.organisationsByCountry.count()); +} + +function testGroupOrder() { + + var org1 = new Organisation(); + org1.country = "AT" + Math.random(); + org1.name = "Helma" + Math.random(); + root.organisations.add(org1); + + var org2 = new Organisation(); + org2.country = "CH" + Math.random(); + org2.name = "Helma" + Math.random(); + root.organisations.add(org2); + + var org3 = new Organisation(); + org3.country = "DE" + Math.random(); + org3.name = "Helma" + Math.random(); + root.organisations.add(org3); + + var org4 = new Organisation(); + org4.country = org3.country; + org4.name = "Helma" + Math.random(); + root.organisations.add(org4); + + res.commit(); + + // make sure that countries and organisations are sorted in decreasing order (as specified in type.properties) + var countries = root.organisationsByCountry.list(); + for (var i=0; i0) assertTrue(root.organisationsByCountry.get(i-1)._id >= root.organisationsByCountry.get(i)._id) + for (var j=0; j0) assertTrue(root.organisationsByCountry.get(i).get(j-1)._id >= root.organisationsByCountry.get(i).get(j)._id) + } + } + + org1.remove(); + org2.remove(); + org3.remove(); + org4.remove(); +} + +function testGroupTransient() { + + var temp = new Root(); + var countryCount = temp.organisationsByCountry.count(); + var org = new Organisation(); + org.country = "AT" + Math.random(); + org.name = "Helma" + Math.random(); + temp.organisationsByCountry.add(org); + + var country = temp.organisationsByCountry.get(org.country); + assertEqual(countryCount + 1, temp.organisationsByCountry.count()); + assertNotNull(country); + assertEqual(country._prototype, "Country"); + assertEqual(country.groupname, org.country); + + // These don't work as org uses the parent from type.properties + // which is root.organisations. Not sure if this is a bug or not. + // assertEqual(country, org._parent); + // org.remove(); + country.removeChild(org); + + assertNull(root.organisationsByCountry.get(org.country)); + assertEqual(countryCount, temp.organisationsByCountry.count()); +} + +function cleanup() { + var orgs = root.organisations.list(); + for each (var org in orgs) { + org.remove(); + } +} \ No newline at end of file diff --git a/test/tests/HopObjectHref.js b/test/tests/HopObjectHref.js new file mode 100644 index 00000000..9515b3b5 --- /dev/null +++ b/test/tests/HopObjectHref.js @@ -0,0 +1,56 @@ +tests = [ + "testSimpleParent", + "testFallbackParent", + "testMountpoints" +]; + + +var org; +var person1; +var person2; + +function setup() { + org = new Organisation(); + org.name = "Helma"; + root.organisations.add(org); + + person1 = new Person(); + person1.name = "Hannes"; + person1.organisation = org; + root.persons.add(person1); + + person2 = new Person(); + person2.name = "Michi"; + root.persons.add(person2); +} + +function testSimpleParent() { + assertEqual(org.href(), root.organisations.href() + org.name + "/"); + assertEqual(root.organisations, org._parent); + assertEqual(root, org._parent._parent); +} + +function testFallbackParent() { + assertEqual(person1.href(), person1.organisation.persons.href() + person1.name + "/"); + assertEqual(person1.organisation.persons, person1._parent); + + assertEqual(person2.href(), root.persons.href() + person2._id + "/"); + assertEqual(root.persons, person2._parent); +} + +function testMountpoints() { + assertEqual(root.someMountpoint._prototype, "SomeMountpoint"); + assertEqual(root.someMountpoint._parent, root); + assertEqual(root.someMountpoint.href(), root.href() + "someMountpoint/"); + + assertEqual(org.someMountpoint._prototype, "SomeMountpoint"); + assertEqual(org.someMountpoint._parent, org); + // FIXME: Helma-Bug ? mountpoints are converted to lower case ? + assertEqual(org.someMountpoint.href(), org.href() + "someMountpoint/"); +} + +function cleanup() { + org.remove(); + person1.remove(); + person2.remove(); +} diff --git a/test/tests/Skin.js b/test/tests/Skin.js new file mode 100644 index 00000000..e8f5c3c3 --- /dev/null +++ b/test/tests/Skin.js @@ -0,0 +1,319 @@ +var tests = [ + "testCommentMacro", + "testDeepResolve", + "testDeepUnhandled", + "testDeep", + "testDeepFail", + "testDeepFailSilent", + "testJavaProp", + "testJavaMissing", + "testJavaMissingSilent", + "testJavaMissingVerbose", + "testUndefinedHandler", + "testJSProp", + "testJSMacro", + "testJSFunction", + "testJSMissing", + "testJSMissingSilent", + "testJSMissingVerbose", + "testDateFilter", + "testNestedRootMacro", + "testNestedParamMacro", + "testNestedResponseMacro", + "testNestedPrefixSuffix", + "testResponseProp", + "testResponseMacro", + "testResponseFunction", + "testResponseMissing", + "testResponseMissingSilent", + "testResponseMissingVerbose", + "testRootProp", + "testRootMacro", + "testRootMissing", + "testRootMissingSilent", + "testRootMissingVerbose", + "testSessionProp", + "testSessionMacro", + "testSessionFunction", + "testSessionMissing", + "testSessionMissingDefault", + "testSessionMissingSilent", + "testSessionMissingVerbose", + "testSessionDeepMissing", + "testSubskins" +]; + +var setup = function() { + res.handlers.color = new java.awt.Color["(int,int,int)"](0, 255, 0); + res.handlers.file = new java.io.File["(java.lang.String,java.lang.String)"](null, "file"); + res.handlers.jsobject = { + banana: "yellow", + kiwi_macro: function() { return this.kiwiColor }, + apple: function() {}, + kiwiColor: "green" + }; + res.data.date = new Date(); + res.data.banana = "yellow"; + res.data.kiwi_macro = function() { return "green" }; + res.data.apple = function() {}; + session.data.banana = "yellow"; + session.data.kiwi_macro = function() { return "green" }; + session.data.apple = function() {}; +}; + +var testCommentMacro = function() { + var skin = createSkin("<% // this.foo bar=<% this.foobar %> FIXME %>ok"); + var result = renderSkinAsString(skin); + assertEqual(result, "ok"); +} + +var testDeepResolve = function() { + res.handlers.deep = { + getMacroHandler: function(name) { + if (name != "foo") return null; + return { + bar_macro: function() { + return "ok"; + } + } + } + } + var result = renderSkinAsString(createSkin("<% deep.foo.bar %>")); + assertEqual(result, "ok"); +}; + +var testDeepUnhandled = function() { + res.handlers.deep = { + getMacroHandler: function(name) { + if (name != "foo") return null; + return { + onUnhandledMacro: function(name) { + if (name == "bar") return "ok"; + } + } + } + } + var result = renderSkinAsString(createSkin("<% deep.foo.bar %>")); + assertEqual(result, "ok"); +}; + +var testDeep = function() { + res.handlers.deep = { + foo: { + bar: "ok" + } + } + var result = renderSkinAsString(createSkin("<% deep.foo.bar %>")); + assertEqual(result, "ok"); +}; + +var testDeepFail = function() { + var result = renderSkinAsString(createSkin("<% root.foo.bar %>")); + assertStringContains(result, "Unhandled"); + var result = renderSkinAsString(createSkin("<% root.foo.bar failmode=silent %>")); + assertEqual(result, ""); +}; + +var testDeepFailSilent = function() { + res.handlers.deep = { + foo: {} + }; + var result = renderSkinAsString(createSkin("<% deep.foo.bar %>")); + assertEqual(result, ""); + var result = renderSkinAsString(createSkin("<% deep.foo.bar failmode=verbose %>")); + assertStringContains(result, "Unhandled"); +}; + + +var testJavaProp = function() { + var result = renderSkinAsString(createSkin("<% color.green %>")); + assertEqual(result, "255"); + result = renderSkinAsString(createSkin("<% color.red %>")); + assertEqual(result, "0"); +}; + +var testJavaMissing = function() { + var result = renderSkinAsString(createSkin("<% colo.foo %>")); + assertStringContains(result, "Unhandled"); +}; + +var testJavaMissingSilent = function() { + var result = renderSkinAsString(createSkin("<% color.foo failmode=silent default=ok %>")); + assertEqual(result, "ok"); +}; + +var testJavaMissingVerbose = function() { + var result = renderSkinAsString(createSkin("<% color.foo failmode=verbose %>")); + assertStringContains(result, "Unhandled"); +} + +var testUndefinedHandler = function() { + var result = renderSkinAsString(createSkin("<% file.parentFile %>")); + assertEqual(result, ""); +}; + +var testJSProp = function() { + var result = renderSkinAsString(createSkin("<% jsobject.banana %>")); + assertEqual(result, "yellow"); +}; + +var testJSMacro = function() { + var result = renderSkinAsString(createSkin("<% jsobject.kiwi %>")); + assertEqual(result, "green"); +}; + +var testJSFunction = function() { + var result = renderSkinAsString(createSkin("<% jsobject.apple failmode=silent %>")); + assertEqual(result, ""); +}; + +var testJSMissing = function() { + var result = renderSkinAsString(createSkin("<% jsobject.papaya %>")); + assertEqual(result, ""); +}; + +var testJSMissingSilent = function() { + var result = renderSkinAsString(createSkin("<% jsobject.papaya failmode=silent %>")); + assertEqual(result, ""); +}; + +var testJSMissingVerbose = function() { + var result = renderSkinAsString(createSkin("<% jsobject.papaya failmode=verbose %>")); + assertStringContains(result, "Unhandled"); +}; + +var testDateFilter = function() { + var result = renderSkinAsString(createSkin("<% root.date | isDate %>")); + assertEqual(result, "true"); +}; + +var testNestedRootMacro = function() { + var skin = "<% echo <% root.date %> | isRootDate %>"; + var result = renderSkinAsString(createSkin(skin)); + assertEqual(result, "true"); +} + +var testNestedParamMacro = function() { + var skin = "<% echo <% param.date %> | isDate %>"; + var result = renderSkinAsString(createSkin(skin), { date: new Date() }); + assertEqual(result, "true"); +} + + +var testNestedResponseMacro = function() { + var skin = "<% echo what=<% response.date %> | isResponseDate %>"; + var result = renderSkinAsString(createSkin(skin)); + assertEqual(result, "true"); +}; + +var testNestedPrefixSuffix = function() { + var skin = "<% root.macro prefix=<% root.string %> suffix=<% root.macro %> %>"; + var result = renderSkinAsString(createSkin(skin)); + // root.macro changes suffix to "." + assertEqual(result, "rootroot."); +} + +var testResponseProp = function() { + var result = renderSkinAsString(createSkin("<% response.banana %>")); + assertEqual(result, "yellow"); +}; + +var testResponseMacro = function() { + var result = renderSkinAsString(createSkin("<% response.kiwi %>")); + assertEqual(result, "green"); +}; + +var testResponseFunction = function() { + var result = renderSkinAsString(createSkin("<% response.apple failmode=silent %>")); + assertEqual(result, ""); +}; + +var testResponseMissing = function() { + var result = renderSkinAsString(createSkin("<% response.papaya %>")); + assertEqual(result, ""); +}; + +var testResponseMissingSilent = function() { + var result = renderSkinAsString(createSkin("<% response.papaya failmode=silent %>")); + assertEqual(result, ""); +}; + +var testResponseMissingVerbose = function() { + var result = renderSkinAsString(createSkin("<% response.papaya failmode=verbose %>")); + assertStringContains(result, "Unhandled"); +}; + +var testRootProp = function() { + var result = renderSkinAsString(createSkin("<% root.string %>")); + assertEqual(result, "root"); +}; + +var testRootMacro = function() { + var result = renderSkinAsString(createSkin("<% root.macro %>")); + assertEqual(result, "root"); +}; + +var testRootMissing = function() { + var result = renderSkinAsString(createSkin("<% root.undefinedmacro %>")); + assertStringContains(result, "Unhandled"); +}; + +var testRootMissingSilent = function() { + var result = renderSkinAsString(createSkin("<% root.undefinedmacro failmode=silent %>")); + assertEqual(result, ""); +}; + +var testRootMissingVerbose = function() { + var result = renderSkinAsString(createSkin("<% root.undefinedmacro failmode=verbose %>")); + assertStringContains(result, "Unhandled"); +}; + +var testSessionProp = function() { + var result = renderSkinAsString(createSkin("<% session.banana %>")); + assertEqual(result, "yellow"); +}; + +var testSessionMacro = function() { + var result = renderSkinAsString(createSkin("<% session.kiwi %>")); + assertEqual(result, "green"); +}; + +var testSessionFunction = function() { + var result = renderSkinAsString(createSkin("<% session.apple failmode=silent %>")); + assertEqual(result, ""); +}; + +var testSessionMissingDefault = function() { + var result = renderSkinAsString(createSkin("<% session.papaya default=nope %>")); + assertEqual(result, "nope"); +}; + +var testSessionMissing = function() { + var result = renderSkinAsString(createSkin("<% session.papaya %>")); + assertEqual(result, ""); +}; + +var testSessionMissingSilent = function() { + var result = renderSkinAsString(createSkin("<% session.papaya failmode=silent %>")); + assertEqual(result, ""); +}; + +var testSessionMissingVerbose = function() { + var result = renderSkinAsString(createSkin("<% session.papaya failmode=verbose %>")); + assertStringContains(result, "Unhandled"); +}; + +var testSessionDeepMissing = function() { + var result = renderSkinAsString(createSkin("<% session.user.name %>")); + assertStringContains(result, "Unhandled"); + // assertEqual(result, ""); +}; + +var testSubskins = function() { + var result = renderSkinAsString("subskins"); + assertEqual(result, "mainskin"); + result = renderSkinAsString("subskins#subskin1"); + assertEqual(result, "subskin1"); + result = renderSkinAsString("subskins#subskin2"); + assertEqual(result, "subskin2"); +}; diff --git a/test/tests/helma.Http.js b/test/tests/helma.Http.js new file mode 100644 index 00000000..3cd51cf8 --- /dev/null +++ b/test/tests/helma.Http.js @@ -0,0 +1,68 @@ +var tests = [ + "testSimple", + "testError", + "testNotFound", + "testRedirect", + "testRedirectNoFollow", + "testMaxResponseSize", + "testLongResponse" +]; + +app.addRepository("modules/helma/Http.js"); + +var http = new helma.Http(); + +var testSimple = function() { + var result = http.getUrl(root.href("hello")); + assertEqual(result.content, "Hello"); + assertEqual(result.code, 200); +}; + +var testError = function() { + var result = http.getUrl(root.href("throwerror")); + assertEqual(result.content, "Error"); + assertEqual(result.code, 500); +}; + +var testNotFound = function() { + var result = http.getUrl(root.href("nonExistingAction")); + assertEqual(result.content, "Not found"); + assertEqual(result.code, 404); +}; + +var testRedirect = function() { + var result = http.getUrl(root.href("redirect")); + assertEqual(result.content, "Hello"); + assertEqual(result.code, 200); +}; + +var testRedirectNoFollow = function() { + http.setFollowRedirects(false); + var result = null; + try { + result = http.getUrl(root.href("redirect")); + } finally { + http.setFollowRedirects(true); + } + assertEqual(result.content, ""); + // response codes 302 and 303 are both ok + assertTrue(result.code == 302 || result.code == 303); +}; + +var testMaxResponseSize = function() { + http.setMaxResponseSize(3); + var error = null; + try { + http.getUrl(root.href("hello")); + } catch (err) { + error = err; + } finally { + http.setMaxResponseSize(null); + } + assertNotNull(error); +}; + +var testLongResponse = function() { + var result = http.getUrl(root.href("long")); + assertEqual(result.content, makeLongString()); +}; diff --git a/test/tests/helma.Search.js b/test/tests/helma.Search.js new file mode 100644 index 00000000..f70a68d7 --- /dev/null +++ b/test/tests/helma.Search.js @@ -0,0 +1,347 @@ +var tests = [ + "testConstructor", + "testGetDirectory", + "testGetRAMDirectory", + "testCreateIndex", + "testGetReaderWriter", + "testIndexLock", + "testDocument", + "testAddDocuments", + "testSearch" +]; + +app.addRepository("modules/helma/Search.js"); + +var indexName = "testindex"; +var basePath = java.lang.System.getProperty("java.io.tmpdir"); +var index; + +/** + * Test preliminaries + */ +var setup = function() { + // check if there is a (leftover) directory with the same name + // in the system's temporary directory - if so throw an exception and stop + var dir = new helma.File(basePath, indexName); + if (dir.exists()) { + throw "There is already a directory '" + dir.getAbsolutePath() + + "', please remove it before trying to run test again"; + } + return; +}; + +/** + * Test the helma.Search constructor to make sure Lucene is loaded + */ +var testConstructor = function() { + // should not throw an exception + var s = new helma.Search(); + return; +}; + +/** + * Test getDirectory method + */ +var testGetDirectory = function() { + var search = new helma.Search(); + assertThrows(function() { + search.getDirectory(); + }); + var dirs = [ + new helma.File(basePath, indexName), + new File(basePath, indexName), + new java.io.File(basePath, indexName), + basePath + "/" + indexName + ]; + var dir, fsDir, dirPath; + for (var i in dirs) { + dir = dirs[i]; + if (dir.constructor != String) { + dirPath = dir.getAbsolutePath(); + } else { + dirPath = dir; + } + fsDir = search.getDirectory(dir); + assertNotNull(fsDir); + assertEqual(fsDir.getFile().getAbsolutePath(), dirPath); + } + return; +}; + +/** + * Test getRAMDirectory method + */ +var testGetRAMDirectory = function() { + var search = new helma.Search(); + assertThrows(function() { + search.getDirectory(); + }); + var dirs = [ + new helma.File(basePath, indexName), + new File(basePath, indexName), + new java.io.File(basePath, indexName), + basePath + "/" + indexName + ]; + var dir, ramDir; + for (var i in dirs) { + dir = dirs[i]; + ramDir = search.getRAMDirectory(dir); + assertNotNull(ramDir); + } + return; +}; + +/** + * Test index creation - this method creates a RAMDirectory based + * index for testing and stores it in the global variable "index" + */ +var testCreateIndex = function() { + var search = new helma.Search(); + // test creating a file based index + var fsDir = search.getDirectory(new helma.File(basePath, indexName)); + index = search.createIndex(fsDir); + assertNotNull(index); + // explicitly test index.create(true) + assertTrue(index.create(true)); + + // test creating a ram based index + var ramDir = search.getRAMDirectory(); + index = search.createIndex(ramDir); + assertNotNull(index); + // explicitly test index.create(true) + assertTrue(index.create(true)); + assertEqual(index.constructor, helma.Search.Index); + assertEqual(index.size(), 0); + return; +}; + +/** + * Test getting index reader, writer and modifier + */ +var testGetReaderWriter = function() { + // test getReader + var reader = index.getReader(); + assertNotNull(reader); + reader.close(); + // test getWriter + var writer = index.getWriter(); + assertNotNull(writer); + writer.close(); + return; +}; + +/** + * Test index locking + */ +var testIndexLock = function() { + // test if the index is correctly locked when opening a writer + var writer = index.getWriter(); + assertTrue(index.isLocked()); + // test if getWriter() throws an exception when trying to open a second writer + assertThrows(function() { + index.getWriter(); + }); + writer.close(); + assertFalse(index.isLocked()); + return; +}; + +/** + * Test document constructor and methods + */ +var testDocument = function() { + var doc = new helma.Search.Document(); + var f; + + // test type conversion + f = new helma.Search.Document.Field("id", 1); + assertEqual(f.value.constructor, String); + assertEqual(f.value, "1"); + var now = new Date(); + f = new helma.Search.Document.Field("createtime", now); + assertEqual(f.dateValue.constructor, Date); + assertEqual(f.dateValue.getTime(), now.getTime() - (now.getTime() % 60000)); + + // test adding field with default store and index options + doc.addField(new helma.Search.Document.Field("id", 1)); + f = doc.getField("id"); + assertNotNull(f); + assertTrue(f.isStored()); + assertTrue(f.isIndexed()); + assertTrue(f.isTokenized()); + + // test adding date field with changed field options + f = new helma.Search.Document.Field("createtime", new Date(), { + store: "no", + index: "tokenized" + }); + doc.addField(f); + f = doc.getField("createtime"); + assertNotNull(f); + assertFalse(f.isStored()); + assertTrue(f.isIndexed()); + assertTrue(f.isTokenized()); + + // test deprecated way of calling addField() + doc.addField("title", "Just a test", { + "store": false, + "index": true, + "tokenize": false + }); + f = doc.getField("title"); + assertNotNull(f); + assertFalse(f.isStored()); + assertTrue(f.isIndexed()); + assertFalse(f.isTokenized()); + + // test getFields() + var fields = doc.getFields(); + assertEqual(fields.length, 3); + assertEqual(fields[0].name, "id"); + assertEqual(fields[1].name, "createtime"); + assertEqual(fields[2].name, "title"); + return; +}; + +/** + * Test adding documents + */ +var testAddDocuments = function() { + // test addDocument() + var doc = new helma.Search.Document(); + doc.addField(new helma.Search.Document.Field("id", 1)); + index.addDocument(doc); + assertEqual(index.size(), 1); + + // test removeDocument() + index.removeDocument("id", 1); + assertEqual(index.size(), 0); + + // test addDocuments() and removeDocuments() with an array + doc = new helma.Search.Document(); + doc.addField(new helma.Search.Document.Field("id", 2)); + index.addDocuments([doc]); + assertEqual(index.size(), 1); + index.removeDocuments("id", [2]); + assertEqual(index.size(), 0); + + // test addDocuments() and removeDocuments() with a Hashtable as argument + var ht = new java.util.Hashtable(); + ht.put("doc", doc); + index.addDocuments(ht); + ht = new java.util.Hashtable(); + ht.put("id", 1); + ht.put("id", 2); + index.removeDocuments("id", ht); + assertEqual(index.size(), 0); + + // test addDocuments() and removeDocuments() with a Vector as argument + var v = new java.util.Vector(); + v.add(doc); + index.addDocuments(v); + v = new java.util.Vector(); + v.add(1); + v.add(2); + index.removeDocuments("id", v); + assertEqual(index.size(), 0); + + // test updateDocument + index.addDocument(doc); + doc = new helma.Search.Document(); + doc.addField("id", 2); + index.updateDocument(doc, "id"); + assertEqual(index.size(), 1); + + // test count() + doc = new helma.Search.Document(); + doc.addField("id", 3); + index.addDocument(doc); + assertEqual(index.count("id", 3), 1); + + return; +}; + +/** + * Test searching the index + */ +var testSearch = function() { + // clear the index + index.create(); + assertEqual(index.size(), 0); + + // populate the index with test content + var names = [ + "foo", + "bar", + "baz" + ]; + + var now = new Date(); + var doc; + names.forEach(function(name, idx) { + doc = new helma.Search.Document(); + doc.addField("id", idx + 1); + doc.addField("parent", idx % 2); + doc.addField("name", name); + doc.addField("timestamp", new Date(now.getTime() - (idx * 1e6))); + index.addDocument(doc); + }); + assertEqual(index.size(), 3); + + var searcher = index.getSearcher(); + assertNotNull(searcher); + assertNull(searcher.sortFields); + assertNotNull(searcher.getSearcher()); + assertTrue(searcher.getSearcher() instanceof Packages.org.apache.lucene.search.IndexSearcher); + + // test basic search + var q = new helma.Search.TermQuery("id", 1); + assertEqual(searcher.search(q), 1); + assertNotNull(searcher.hits); + assertEqual(searcher.hits.constructor, helma.Search.HitCollection); + assertEqual(searcher.hits.size(), 1); + var hit = searcher.hits.get(0); + assertNotNull(hit); + assertEqual(hit.constructor, helma.Search.Document); + assertEqual(hit.getField("name").constructor, helma.Search.Document.Field); + assertEqual(hit.getField("name").value, "foo"); + // test date value conversion + assertEqual(hit.getField("timestamp").value.constructor, String); + assertEqual(hit.getField("timestamp").dateValue.constructor, Date); + + // test query filter + var qf = new helma.Search.QueryFilter(new helma.Search.TermQuery("parent", 0)); + q = new helma.Search.WildcardQuery("name", "ba*"); + assertEqual(searcher.search(q, qf), 1); + assertEqual(searcher.hits.get(0).getField("name").value, names[2]); + + // test sorting of hits + searcher.sortBy("id", true); + assertEqual(searcher.search(q), 2); + assertEqual(searcher.hits.get(0).getField("name").value, names[2]); + assertEqual(searcher.hits.get(1).getField("name").value, names[1]); + + // test boolean query + q = new helma.Search.BooleanQuery(); + q.addTerm("parent", "0"); + assertEqual(q.toString(), "[(parent:0)]"); + q = new helma.Search.BooleanQuery(); + q.addTerm("parent", "0", "and"); + assertEqual(q.toString(), "[+(parent:0)]"); + q = new helma.Search.BooleanQuery(); + q.addTerm("parent", "0", "not"); + assertEqual(q.toString(), "[-(parent:0)]"); + + searcher.close(); + return; +}; + +/** + * Cleanup + */ +var cleanup = function() { + // remove the directory containing the test index + var dir = new helma.File(basePath, indexName); + dir.removeDirectory(); + return; +} \ No newline at end of file