aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorJukka Jylanki <jjylanki@imvu.com>2013-03-29 13:42:58 +0200
committerJukka Jylänki <jujjyl@gmail.com>2013-04-12 14:26:55 +0300
commit92dee924425cb3ee1b7a266ab7a280f94baf33be (patch)
tree01689b726cb10d9f9a02ac8db1db2836bb0d4a97 /tests
parentda222ce8d8529d92d4256369bd910e4d5929a008 (diff)
Migrate embind tests from IMVU repository to emscripten repository.
Diffstat (limited to 'tests')
-rwxr-xr-xtests/embind/embind.test.js1495
-rw-r--r--tests/embind/embind_test.cpp1651
-rw-r--r--tests/embind/embind_test.js398
-rwxr-xr-xtests/embind/imvu_test_adapter.js614
-rwxr-xr-xtests/embind/underscore-1.4.2.js1200
-rwxr-xr-xtests/runner.py54
6 files changed, 4900 insertions, 512 deletions
diff --git a/tests/embind/embind.test.js b/tests/embind/embind.test.js
new file mode 100755
index 00000000..94d935f2
--- /dev/null
+++ b/tests/embind/embind.test.js
@@ -0,0 +1,1495 @@
+module({
+ Emscripten: '../../../../build/embind_test.js',
+}, function(imports) {
+ var cm = imports.Emscripten;
+
+ var CheckForLeaks = fixture("check for leaks", function() {
+ this.setUp(function() {
+ if (typeof INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER === "undefined") { // TODO: Enable this to work in Emscripten runner as well!
+ cm._mallocDebug(2);
+ assert.equal(0, cm.count_emval_handles());
+ cm._mallocAssertAllMemoryFree();
+ }
+ });
+ this.tearDown(function() {
+ if (typeof INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER === "undefined") { // TODO: Enable this to work in Emscripten runner as well!
+ cm._mallocAssertAllMemoryFree();
+ assert.equal(0, cm.count_emval_handles());
+ }
+ });
+ });
+
+ var BaseFixture = CheckForLeaks;
+
+ BaseFixture.extend("temp jig", function() {
+ test("temp test", function() {
+ });
+ });
+
+ if (typeof INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER === "undefined") { // TODO: Enable this to work in Emscripten runner as well!
+
+ BaseFixture.extend("leak testing", function() {
+ test("no memory allocated at start of test", function() {
+ cm._mallocAssertAllMemoryFree();
+ });
+ test("assert when memory is allocated", function() {
+ var ptr = cm._malloc(42);
+ assert.throws(cm._MemoryAllocationError, function() {
+ cm._mallocAssertAllMemoryFree();
+ });
+ cm._free(ptr);
+ });
+ test("allocated memory counts down again for free", function() {
+ var ptr = cm._malloc(42);
+ cm._free(ptr);
+ cm._mallocAssertAllMemoryFree();
+ });
+ test("free without malloc throws MemoryAllocationError", function() {
+ var ptr = cm._malloc(42);
+ cm._free(ptr);
+ assert.throws(cm._MemoryAllocationError, function() {
+ cm._free(ptr);
+ });
+ });
+ });
+
+ }
+
+ BaseFixture.extend("access to base class members", function() {
+ test("method name in derived class silently overrides inherited name", function() {
+ var derived = new cm.Derived();
+ assert.equal("Derived", derived.getClassName());
+ derived.delete();
+ });
+ test("can reference base method from derived class", function(){
+ var derived = new cm.Derived();
+ assert.equal("Base", derived.getClassNameFromBase());
+ derived.delete();
+ });
+ test("can reference base method from doubly derived class", function() {
+ var derivedTwice = new cm.DerivedTwice();
+ assert.equal("Base", derivedTwice.getClassNameFromBase());
+ derivedTwice.delete();
+ });
+ test("can reference base method through unbound classes", function() {
+ var derivedThrice = new cm.DerivedThrice();
+ assert.equal("Base", derivedThrice.getClassNameFromBase());
+ derivedThrice.delete();
+ });
+ test("property name in derived class hides identically named property in base class for set", function() {
+ var derived = new cm.Derived();
+ derived.setMember(7);
+
+ derived.member = 17;
+
+ assert.equal(17, derived.getMember());
+ derived.delete();
+ });
+ test("can reference base property from derived class for get", function(){
+ var derived = new cm.Derived();
+ derived.setBaseMember(5);
+
+ assert.equal(5, derived.baseMember);
+
+ derived.delete();
+ });
+ test("can reference property of any base class for get when multiply derived", function(){
+ var derived = new cm.MultiplyDerived();
+ derived.setBaseMember(11);
+
+ assert.equal(11, derived.baseMember);
+
+ derived.delete();
+ });
+ test("can reference base property from derived class for set", function(){
+ var derived = new cm.Derived();
+
+ derived.baseMember = 32;
+
+ assert.equal(32, derived.getBaseMember());
+ derived.delete();
+ });
+ test("can reference property of any base for set when multiply derived", function(){
+ var derived = new cm.MultiplyDerived();
+ derived.setBaseMember(97);
+
+ derived.baseMember = 32;
+
+ assert.equal(32, derived.getBaseMember());
+ derived.delete();
+ });
+ test("can reach around derived property to access base property with same name for get", function() {
+ var derived = new cm.Derived();
+ derived.setMember(12);
+ derived.delete();
+ });
+
+ test("if deriving from second base adjusts pointer", function() {
+ var derived = new cm.HasTwoBases;
+ assert.equal("Base2", derived.getField());
+ derived.delete();
+ });
+
+ test("properties adjust pointer", function() {
+ var derived = new cm.HasTwoBases;
+ derived.field = "Foo";
+ assert.equal("Foo", derived.getField());
+ assert.equal("Foo", derived.field);
+ derived.delete();
+ });
+
+ test("calling method on unrelated class throws error", function() {
+ var a = new cm.HasTwoBases;
+ var e = assert.throws(cm.BindingError, function() {
+ cm.Derived.prototype.setMember.call(a, "foo");
+ });
+ assert.equal('Derived.setMember incompatible with "this" of type HasTwoBases', e.message);
+ a.delete();
+ });
+
+ test("calling method with invalid this throws error", function() {
+ var e = assert.throws(cm.BindingError, function() {
+ cm.Derived.prototype.setMember.call(undefined, "foo");
+ });
+ if (typeof INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER === "undefined") { // TODO: Enable this to work in Emscripten runner as well!
+ // got Error: expected: Derived.setMember with invalid "this": undefined, actual: Derived.setMember incompatible with "this" of type Object
+ assert.equal('Derived.setMember with invalid "this": undefined', e.message);
+ }
+
+ var e = assert.throws(cm.BindingError, function() {
+ cm.Derived.prototype.setMember.call("this", "foo");
+ });
+ if (typeof INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER === "undefined") { // TODO: Enable this to work in Emscripten runner as well!
+ // TODO got 'Derived.setMember incompatible with "this" of type Object'
+ assert.equal('Derived.setMember with invalid "this": this', e.message);
+ }
+
+ var e = assert.throws(cm.BindingError, function() {
+ cm.Derived.prototype.setMember.call({}, "foo");
+ });
+ if (typeof INVOKED_FROM_EMSCRIPTEN_TEST_RUNNER === "undefined") { // TODO: Enable this to work in Emscripten runner as well!
+ assert.equal('Derived.setMember incompatible with "this" of type Object', e.message);
+ }
+ });
+
+ test("setting and getting property on unrelated class throws error", function() {
+ var a = new cm.HasTwoBases;
+ var e = assert.throws(cm.BindingError, function() {
+ Object.getOwnPropertyDescriptor(cm.HeldBySmartPtr.prototype, 'i').set.call(a, 10);
+ });
+ assert.equal('HeldBySmartPtr.i setter incompatible with "this" of type HasTwoBases', e.message);
+
+ var e = assert.throws(cm.BindingError, function() {
+ Object.getOwnPropertyDescriptor(cm.HeldBySmartPtr.prototype, 'i').get.call(a);
+ });
+ assert.equal('HeldBySmartPtr.i getter incompatible with "this" of type HasTwoBases', e.message);
+
+ a.delete();
+ });
+ });
+
+ BaseFixture.extend("automatic upcasting of parameters passed to C++", function() {
+ // raw
+ test("raw pointer argument is upcast to parameter type", function() {
+ var derived = new cm.Derived();
+ var name = cm.embind_test_get_class_name_via_base_ptr(derived);
+ assert.equal("Base", name);
+ derived.delete();
+ });
+
+ test("automatic raw pointer upcasting works with multiple inheritance", function() {
+ var derived = new cm.MultiplyDerived();
+ var name = cm.embind_test_get_class_name_via_base_ptr(derived);
+ assert.equal("Base", name);
+ derived.delete();
+ });
+
+ test("automatic raw pointer upcasting does not change local pointer", function() {
+ var derived = new cm.MultiplyDerived();
+ cm.embind_test_get_class_name_via_base_ptr(derived);
+ assert.equal("MultiplyDerived", derived.getClassName());
+ derived.delete();
+ });
+
+ test("passing incompatible raw pointer to method throws exception", function() {
+ var base = new cm.Base();
+ assert.throws(cm.BindingError, function() {
+ cm.embind_test_get_class_name_via_second_base_ptr(base);
+ });
+ base.delete();
+ });
+
+ // raw polymorphic
+ test("polymorphic raw pointer argument is upcast to parameter type", function() {
+ var derived = new cm.PolyDerived();
+ var name = cm.embind_test_get_class_name_via_polymorphic_base_ptr(derived);
+ assert.equal("PolyBase", name);
+ derived.delete();
+ });
+
+ test("automatic polymorphic raw pointer upcasting works with multiple inheritance", function() {
+ var derived = new cm.PolyMultiplyDerived();
+ var name = cm.embind_test_get_class_name_via_polymorphic_base_ptr(derived);
+ assert.equal("PolyBase", name);
+ derived.delete();
+ });
+
+ test("passing incompatible raw polymorphic pointer to method throws exception", function() {
+ var base = new cm.PolyBase();
+ assert.throws(cm.BindingError, function() {
+ cm.embind_test_get_class_name_via_polymorphic_second_base_ptr(base);
+ });
+ base.delete();
+
+ });
+
+ // smart
+ test("can pass smart pointer to raw pointer parameter", function() {
+ var smartBase = cm.embind_test_return_smart_base_ptr();
+ assert.equal("Base", cm.embind_test_get_class_name_via_base_ptr(smartBase));
+ smartBase.delete();
+ });
+
+ test("can pass and upcast smart pointer to raw pointer parameter", function() {
+ var smartDerived = cm.embind_test_return_smart_derived_ptr();
+ assert.equal("Base", cm.embind_test_get_class_name_via_base_ptr(smartDerived));
+ smartDerived.delete();
+ });
+
+ test("smart pointer argument is upcast to parameter type", function() {
+ var derived = cm.embind_test_return_smart_derived_ptr();
+ assert.instanceof(derived, cm.Derived);
+ assert.instanceof(derived, cm.Base);
+ var name = cm.embind_test_get_class_name_via_smart_base_ptr(derived);
+ assert.equal("Base", name);
+ derived.delete();
+ });
+
+ test("return smart derived ptr as base", function() {
+ var derived = cm.embind_test_return_smart_derived_ptr_as_base();
+ assert.equal("PolyDerived", cm.embind_test_get_virtual_class_name_via_smart_polymorphic_base_ptr(derived));
+ assert.equal("PolyDerived", derived.getClassName());
+ derived.delete();
+ });
+
+ test("return smart derived ptr as val", function() {
+ var derived = cm.embind_test_return_smart_derived_ptr_as_val();
+ assert.equal("PolyDerived", cm.embind_test_get_virtual_class_name_via_smart_polymorphic_base_ptr(derived));
+ derived.delete();
+ });
+
+ test("automatic smart pointer upcasting works with multiple inheritance", function() {
+ var derived = cm.embind_test_return_smart_multiply_derived_ptr();
+ var name = cm.embind_test_get_class_name_via_smart_base_ptr(derived);
+ assert.equal("Base", name);
+ derived.delete();
+ });
+
+ test("automatically upcasted smart pointer parameter shares ownership with original argument", function() {
+ var derived = cm.embind_test_return_smart_multiply_derived_ptr();
+ assert.equal(1, cm.MultiplyDerived.getInstanceCount());
+ cm.embind_save_smart_base_pointer(derived);
+ assert.equal(1, cm.MultiplyDerived.getInstanceCount());
+ derived.delete();
+ assert.equal(1, cm.MultiplyDerived.getInstanceCount());
+ cm.embind_save_smart_base_pointer(null);
+ assert.equal(0, cm.MultiplyDerived.getInstanceCount());
+ });
+
+ // smart polymorphic
+ test("smart polymorphic pointer argument is upcast to parameter type", function() {
+ var derived = cm.embind_test_return_smart_polymorphic_derived_ptr();
+ var name = cm.embind_test_get_class_name_via_smart_polymorphic_base_ptr(derived);
+ assert.equal("PolyBase", name);
+ derived.delete();
+ });
+
+ test("automatic smart polymorphic pointer upcasting works with multiple inheritance", function() {
+ var derived = cm.embind_test_return_smart_polymorphic_multiply_derived_ptr();
+ var name = cm.embind_test_get_class_name_via_smart_polymorphic_base_ptr(derived);
+ assert.equal("PolyBase", name);
+ derived.delete();
+ });
+ });
+
+ BaseFixture.extend("automatic downcasting of return values received from C++", function() {
+ // raw
+ test("non-polymorphic raw pointers are not downcast and do not break automatic casting mechanism", function() {
+ var base = cm.embind_test_return_raw_derived_ptr_as_base();
+ assert.equal("Base", base.getClassName());
+ assert.instanceof(base, cm.Base);
+ base.delete();
+ });
+
+ // raw polymorphic
+ test("polymorphic raw pointer return value is downcast to allocated type (if that is bound)", function() {
+ var derived = cm.embind_test_return_raw_polymorphic_derived_ptr_as_base();
+ assert.instanceof(derived, cm.PolyBase);
+ assert.instanceof(derived, cm.PolyDerived);
+ assert.equal("PolyDerived", derived.getClassName());
+ var siblingDerived = cm.embind_test_return_raw_polymorphic_sibling_derived_ptr_as_base();
+ assert.equal("PolySiblingDerived", siblingDerived.getClassName());
+ siblingDerived.delete();
+ derived.delete();
+ });
+
+ test("polymorphic raw pointer return value is downcast to the most derived bound type", function() {
+ var derivedThrice = cm.embind_test_return_raw_polymorphic_derived_four_times_not_bound_as_base();
+ // if the actual returned type is not bound, then don't assume anything
+ assert.equal("PolyBase", derivedThrice.getClassName());
+ // if we ever fix this, then reverse the assertion
+ //assert.equal("PolyDerivedThrice", derivedThrice.getClassName());
+ derivedThrice.delete();
+ });
+
+ test("polymorphic smart pointer return value is downcast to the most derived type which has an associated smart pointer", function() {
+ var derived = cm.embind_test_return_poly_derived_twice_without_smart_pointer_as_poly_base();
+ // if the actual returned type is not bound, then don't assume anything
+ assert.equal("PolyBase", derived.getClassName());
+ // if we ever fix this, then remove the assertion
+ //assert.equal("PolyDerived", derived.getClassName());
+ derived.delete();
+ });
+
+ test("automatic downcasting works with multiple inheritance", function() {
+ var base = cm.embind_test_return_raw_polymorphic_multiply_derived_ptr_as_base();
+ var secondBase = cm.embind_test_return_raw_polymorphic_multiply_derived_ptr_as_second_base();
+ assert.equal("PolyMultiplyDerived", base.getClassName());
+ // embind does not support multiple inheritance
+ //assert.equal("PolyMultiplyDerived", secondBase.getClassName());
+ secondBase.delete();
+ base.delete();
+ });
+
+ // smart
+ test("non-polymorphic smart pointers do not break automatic casting mechanism", function() {
+ });
+
+ // smart polymorphic
+ test("automatically downcasting a smart pointer does not change the underlying pointer", function() {
+ cm.PolyDerived.setPtrDerived();
+ assert.equal("PolyBase", cm.PolyDerived.getPtrClassName());
+ var derived = cm.PolyDerived.getPtr();
+ assert.equal("PolyDerived", derived.getClassName());
+ assert.equal("PolyBase", cm.PolyDerived.getPtrClassName());
+ derived.delete();
+ cm.PolyDerived.releasePtr();
+ });
+
+ test("polymorphic smart pointer return value is actual allocated type (when bound)", function() {
+ var derived = cm.embind_test_return_smart_polymorphic_derived_ptr_as_base();
+ assert.equal("PolyDerived", derived.getClassName());
+
+ var siblingDerived = cm.embind_test_return_smart_polymorphic_sibling_derived_ptr_as_base();
+ assert.equal("PolySiblingDerived", siblingDerived.getClassName());
+
+ siblingDerived.delete();
+ derived.delete();
+ });
+ });
+
+ BaseFixture.extend("embind", function() {
+ test("value creation", function() {
+ assert.equal(15, cm.emval_test_new_integer());
+ assert.equal("Hello everyone", cm.emval_test_new_string());
+ assert.equal("Hello everyone", cm.emval_test_get_string_from_val({key: "Hello everyone"}));
+
+ var object = cm.emval_test_new_object();
+ assert.equal('bar', object.foo);
+ assert.equal(1, object.baz);
+ });
+
+ test("pass const reference to primitive", function() {
+ assert.equal(3, cm.const_ref_adder(1, 2));
+ });
+
+ test("passthrough", function() {
+ var a = {foo: 'bar'};
+ var b = cm.emval_test_passthrough(a);
+ a.bar = 'baz';
+ assert.equal('baz', b.bar);
+
+ assert.equal(0, cm.count_emval_handles());
+ });
+
+ test("void return converts to undefined", function() {
+ assert.equal(undefined, cm.emval_test_return_void());
+ });
+
+ test("booleans can be marshalled", function() {
+ assert.equal(false, cm.emval_test_not(true));
+ assert.equal(true, cm.emval_test_not(false));
+ });
+
+ test("convert double to unsigned", function() {
+ var rv = cm.emval_test_as_unsigned(1.5);
+ assert.equal('number', typeof rv);
+ assert.equal(1, rv);
+ assert.equal(0, cm.count_emval_handles());
+ });
+
+ test("get length of array", function() {
+ assert.equal(10, cm.emval_test_get_length([0, 1, 2, 3, 4, 5, 'a', 'b', 'c', 'd']));
+ assert.equal(0, cm.count_emval_handles());
+ });
+
+ test("add a bunch of things", function() {
+ assert.equal(66.0, cm.emval_test_add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
+ assert.equal(0, cm.count_emval_handles());
+ });
+
+ test("sum array", function() {
+ assert.equal(66, cm.emval_test_sum([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]));
+ assert.equal(0, cm.count_emval_handles());
+ });
+
+ test("strings", function() {
+ assert.equal("foobar", "foo" + "bar");
+ assert.equal("foobar", cm.emval_test_take_and_return_std_string("foobar"));
+
+ assert.equal("foobar", cm.emval_test_take_and_return_std_string_const_ref("foobar"));
+ });
+
+ test("nuls pass through strings", function() {
+ assert.equal("foo\0bar", cm.emval_test_take_and_return_std_string("foo\0bar"));
+ });
+
+ test("no memory leak when passing strings in by const reference", function() {
+ cm.emval_test_take_and_return_std_string_const_ref("foobar");
+ });
+
+ test("can create new object", function() {
+ assert.deepEqual({}, cm.embind_test_new_Object());
+ });
+
+ test("can invoke constructors with arguments", function() {
+ function constructor(i, s, argument) {
+ this.i = i;
+ this.s = s;
+ this.argument = argument;
+ }
+ constructor.prototype.method = function() {
+ return this.argument;
+ };
+ var x = {};
+ var instance = cm.embind_test_new_factory(constructor, x);
+ assert.equal(10, instance.i);
+ assert.equal("hello", instance.s);
+ assert.equal(x, instance.argument);
+ });
+
+ test("can return module property objects", function() {
+ assert.equal(cm.HEAP8, cm.get_module_property("HEAP8"));
+ });
+
+ test("can return big class instances", function() {
+ var c = cm.embind_test_return_big_class_instance();
+ assert.equal(11, c.member);
+ c.delete();
+ });
+
+ test("can return small class instances", function() {
+ var c = cm.embind_test_return_small_class_instance();
+ assert.equal(7, c.member);
+ c.delete();
+ });
+
+ test("can pass small class instances", function() {
+ var c = new cm.SmallClass();
+ var m = cm.embind_test_accept_small_class_instance(c);
+ assert.equal(7, m);
+ c.delete();
+ });
+
+ test("can pass big class instances", function() {
+ var c = new cm.BigClass();
+ var m = cm.embind_test_accept_big_class_instance(c);
+ assert.equal(11, m);
+ c.delete();
+ });
+
+ test("can get member classes then call its member functions", function() {
+ var p = new cm.ParentClass();
+ var c = p.getBigClass();
+ var m = c.getMember();
+ assert.equal(11, m);
+ c.delete();
+ p.delete();
+ });
+
+ test('C++ -> JS primitive type range checks', function() {
+ // all types should have zero.
+ assert.equal("0", cm.char_to_string(0));
+ assert.equal("0", cm.signed_char_to_string(0));
+ assert.equal("0", cm.unsigned_char_to_string(0));
+ assert.equal("0", cm.short_to_string(0));
+ assert.equal("0", cm.unsigned_short_to_string(0));
+ assert.equal("0", cm.int_to_string(0));
+ assert.equal("0", cm.unsigned_int_to_string(0));
+ assert.equal("0", cm.long_to_string(0));
+ assert.equal("0", cm.unsigned_long_to_string(0));
+
+ // all types should have positive values.
+ assert.equal("5", cm.char_to_string(5));
+ assert.equal("5", cm.signed_char_to_string(5));
+ assert.equal("5", cm.unsigned_char_to_string(5));
+ assert.equal("5", cm.short_to_string(5));
+ assert.equal("5", cm.unsigned_short_to_string(5));
+ assert.equal("5", cm.int_to_string(5));
+ assert.equal("5", cm.unsigned_int_to_string(5));
+ assert.equal("5", cm.long_to_string(5));
+ assert.equal("5", cm.unsigned_long_to_string(5));
+
+ // signed types should have negative values.
+ assert.equal("-5", cm.char_to_string(-5)); // Assuming char as signed.
+ assert.equal("-5", cm.signed_char_to_string(-5));
+ assert.equal("-5", cm.short_to_string(-5));
+ assert.equal("-5", cm.int_to_string(-5));
+ assert.equal("-5", cm.long_to_string(-5));
+
+ // assumptions: char == signed char == 8 bits
+ // unsigned char == 8 bits
+ // short == 16 bits
+ // int == long == 32 bits
+
+ // all types should have their max positive values.
+ assert.equal("127", cm.char_to_string(127));
+ assert.equal("127", cm.signed_char_to_string(127));
+ assert.equal("255", cm.unsigned_char_to_string(255));
+ assert.equal("32767", cm.short_to_string(32767));
+ assert.equal("65535", cm.unsigned_short_to_string(65535));
+ assert.equal("2147483647", cm.int_to_string(2147483647));
+ assert.equal("4294967295", cm.unsigned_int_to_string(4294967295));
+ assert.equal("2147483647", cm.long_to_string(2147483647));
+ assert.equal("4294967295", cm.unsigned_long_to_string(4294967295));
+
+ // signed types should have their min negative values.
+ assert.equal("-128", cm.char_to_string(-128));
+ assert.equal("-128", cm.signed_char_to_string(-128));
+ assert.equal("-32768", cm.short_to_string(-32768));
+ assert.equal("-2147483648", cm.int_to_string(-2147483648));
+ assert.equal("-2147483648", cm.long_to_string(-2147483648));
+
+ // passing out of range values should fail.
+ assert.throws(TypeError, function() { cm.char_to_string(-129); });
+ assert.throws(TypeError, function() { cm.char_to_string(128); });
+ assert.throws(TypeError, function() { cm.signed_char_to_string(-129); });
+ assert.throws(TypeError, function() { cm.signed_char_to_string(128); });
+ assert.throws(TypeError, function() { cm.unsigned_char_to_string(-1); });
+ assert.throws(TypeError, function() { cm.unsigned_char_to_string(256); });
+ assert.throws(TypeError, function() { cm.short_to_string(-32769); });
+ assert.throws(TypeError, function() { cm.short_to_string(32768); });
+ assert.throws(TypeError, function() { cm.unsigned_short_to_string(-1); });
+ assert.throws(TypeError, function() { cm.unsigned_short_to_string(65536); });
+ assert.throws(TypeError, function() { cm.int_to_string(-2147483649); });
+ assert.throws(TypeError, function() { cm.int_to_string(2147483648); });
+ assert.throws(TypeError, function() { cm.unsigned_int_to_string(-1); });
+ assert.throws(TypeError, function() { cm.unsigned_int_to_string(4294967296); });
+ assert.throws(TypeError, function() { cm.long_to_string(-2147483649); });
+ assert.throws(TypeError, function() { cm.long_to_string(2147483648); });
+ assert.throws(TypeError, function() { cm.unsigned_long_to_string(-1); });
+ assert.throws(TypeError, function() { cm.unsigned_long_to_string(4294967296); });
+
+ });
+
+/*
+ test("can get templated member classes then call its member functions", function() {
+ var p = new cm.ContainsTemplatedMemberClass();
+ var c = p.getTestTemplate();
+ var m = c.getMember(1);
+ assert.equal(87, m);
+ c.delete();
+ p.delete();
+ });
+*/
+ });
+
+ BaseFixture.extend("vector", function() {
+ test("std::vector returns as an native object", function() {
+ var vec = cm.emval_test_return_vector();
+
+ assert.equal(3, vec.size());
+ assert.equal(10, vec.get(0));
+ assert.equal(20, vec.get(1));
+ assert.equal(30, vec.get(2));
+ vec.delete();
+ });
+
+ test("out of bounds std::vector access returns undefined", function() {
+ var vec = cm.emval_test_return_vector();
+
+ assert.throws(TypeError, function() { vec.get(-1); });
+ assert.equal(undefined, vec.get(4));
+
+ vec.delete();
+ });
+
+ test("std::vector<std::shared_ptr<>> can be passed back", function() {
+ var vec = cm.emval_test_return_shared_ptr_vector();
+
+ assert.equal(2, vec.size());
+ var str0 = vec.get(0);
+ var str1 = vec.get(1);
+
+ assert.equal('string #1', str0.get());
+ assert.equal('string #2', str1.get());
+ str0.delete();
+ str1.delete();
+
+ vec.delete();
+ });
+
+ test("objects can be pushed back", function() {
+ var vectorHolder = new cm.VectorHolder();
+ var vec = vectorHolder.get();
+ assert.equal(2, vec.size());
+
+ var str = new cm.StringHolder('abc');
+ vec.push_back(str);
+ str.delete();
+ assert.equal(3, vec.size());
+ var str = vec.get(2);
+ assert.equal('abc', str.get());
+
+ str.delete();
+ vec.delete();
+ vectorHolder.delete();
+ });
+
+ test("can get elements with array operator", function(){
+ var vec = cm.emval_test_return_vector();
+ assert.equal(10, vec.get(0));
+ vec.delete();
+ });
+
+ test("can set elements with array operator", function() {
+ var vec = cm.emval_test_return_vector();
+ assert.equal(10, vec.get(0));
+ vec.set(2, 60);
+ assert.equal(60, vec.get(2));
+ vec.delete();
+ });
+
+ test("can set and get objects", function() {
+ var vec = cm.emval_test_return_shared_ptr_vector();
+ var str = vec.get(0);
+ assert.equal('string #1', str.get());
+ str.delete();
+ vec.delete();
+ });
+ });
+
+ BaseFixture.extend("map", function() {
+ test("std::map returns as native object", function() {
+ var map = cm.embind_test_get_string_int_map();
+
+ assert.equal(2, map.size());
+ assert.equal(1, map.get("one"));
+ assert.equal(2, map.get("two"));
+
+ map.delete();
+ });
+
+ test("std::map can set keys and values", function() {
+ var map = cm.embind_test_get_string_int_map();
+
+ assert.equal(2, map.size());
+
+ map.set("three", 3);
+
+ assert.equal(3, map.size());
+ assert.equal(3, map.get("three"));
+
+ map.set("three", 4);
+
+ assert.equal(3, map.size());
+ assert.equal(4, map.get("three"));
+
+ map.delete();
+ });
+ });
+
+ BaseFixture.extend("functors", function() {
+ test("can get and call function ptrs", function() {
+ var ptr = cm.emval_test_get_function_ptr();
+ assert.equal("foobar", ptr.opcall("foobar"));
+ ptr.delete();
+ });
+
+ test("can pass functor to C++", function() {
+ var ptr = cm.emval_test_get_function_ptr();
+ assert.equal("asdf", cm.emval_test_take_and_call_functor(ptr));
+ ptr.delete();
+ });
+
+ test("can clone handles", function() {
+ var a = cm.emval_test_get_function_ptr();
+ assert.equal(1, a.$$.count.value);
+ var b = a.clone();
+ assert.equal(2, a.$$.count.value);
+ assert.equal(2, b.$$.count.value);
+ a.delete();
+
+ assert.throws(cm.BindingError, function() {
+ a.delete();
+ });
+ b.delete();
+ });
+ });
+
+ BaseFixture.extend("classes", function() {
+ test("class instance", function() {
+ var a = {foo: 'bar'};
+ assert.equal(0, cm.count_emval_handles());
+ var c = new cm.ValHolder(a);
+ assert.equal(1, cm.count_emval_handles());
+ assert.equal('bar', c.getVal().foo);
+ assert.equal(1, cm.count_emval_handles());
+
+ c.setVal('1234');
+ assert.equal('1234', c.getVal());
+
+ c.delete();
+ assert.equal(0, cm.count_emval_handles());
+ });
+
+ test("class instance $$ property is non-enumerable", function() {
+ var c = new cm.ValHolder(undefined);
+ assert.deepEqual([], Object.keys(c));
+ var d = c.clone();
+ c.delete();
+
+ assert.deepEqual([], Object.keys(d));
+ d.delete();
+ });
+
+ test("class methods", function() {
+ assert.equal(10, cm.ValHolder.some_class_method(10));
+
+ var b = cm.ValHolder.makeValHolder("foo");
+ assert.equal("foo", b.getVal());
+ b.delete();
+ });
+
+ test("can't call methods on deleted class instances", function() {
+ var c = new cm.ValHolder(undefined);
+ c.delete();
+ assert.throws(cm.BindingError, function() {
+ c.getVal();
+ });
+ assert.throws(cm.BindingError, function() {
+ c.delete();
+ });
+ });
+
+ test("calling constructor without new raises BindingError", function() {
+ var e = assert.throws(cm.BindingError, function() {
+ cm.ValHolder(undefined);
+ });
+ assert.equal("Use 'new' to construct ValHolder", e.message);
+ });
+
+ test("can return class instances by value", function() {
+ var c = cm.emval_test_return_ValHolder();
+ assert.deepEqual({}, c.getVal());
+ c.delete();
+ });
+
+ test("can pass class instances to functions by reference", function() {
+ var a = {a:1};
+ var c = new cm.ValHolder(a);
+ cm.emval_test_set_ValHolder_to_empty_object(c);
+ assert.deepEqual({}, c.getVal());
+ c.delete();
+ });
+
+ test("can pass smart pointer by reference", function() {
+ var base = cm.embind_test_return_smart_base_ptr();
+ var name = cm.embind_test_get_class_name_via_reference_to_smart_base_ptr(base);
+ assert.equal("Base", name);
+ base.delete();
+ });
+
+ test("can pass smart pointer by value", function() {
+ var base = cm.embind_test_return_smart_base_ptr();
+ var name = cm.embind_test_get_class_name_via_smart_base_ptr(base);
+ assert.equal("Base", name);
+ base.delete();
+ });
+
+ // todo: fix this
+ // This test does not work because we make no provision for argument values
+ // having been changed after returning from a C++ routine invocation. In
+ // this specific case, the original pointee of the smart pointer was
+ // freed and replaced by a new one, but the ptr in our local handle
+ // was never updated after returning from the call.
+ test("can modify smart pointers passed by reference", function() {
+// var base = cm.embind_test_return_smart_base_ptr();
+// cm.embind_modify_smart_pointer_passed_by_reference(base);
+// assert.equal("Changed", base.getClassName());
+// base.delete();
+ });
+
+ test("can not modify smart pointers passed by value", function() {
+ var base = cm.embind_test_return_smart_base_ptr();
+ cm.embind_attempt_to_modify_smart_pointer_when_passed_by_value(base);
+ assert.equal("Base", base.getClassName());
+ base.delete();
+ });
+
+ test("const return value", function() {
+ var c = new cm.ValHolder("foo");
+ assert.equal("foo", c.getConstVal());
+ c.delete();
+ });
+
+ test("return object by const ref", function() {
+ var c = new cm.ValHolder("foo");
+ assert.equal("foo", c.getValConstRef());
+ c.delete();
+ });
+
+ test("instanceof", function() {
+ var c = new cm.ValHolder("foo");
+ assert.instanceof(c, cm.ValHolder);
+ c.delete();
+ });
+
+ test("can access struct fields", function() {
+ var c = new cm.CustomStruct();
+ assert.equal(10, c.field);
+ assert.equal(10, c.getField());
+ c.delete();
+ });
+
+ test("can set struct fields", function() {
+ var c = new cm.CustomStruct();
+ c.field = 15;
+ assert.equal(15, c.field);
+ c.delete();
+ });
+
+ test("assignment returns value", function() {
+ var c = new cm.CustomStruct();
+ assert.equal(15, c.field = 15);
+ c.delete();
+ });
+
+ test("assigning string to integer raises TypeError", function() {