@teradataprebuilt/fastcall-linux-node-v59
Version:
fastcall - Very fast, asynchronous, dyncall based foreign function interface library for Node.js
652 lines (530 loc) • 27 kB
JavaScript
;
var fastcall = require('../../lib');
var Library = fastcall.Library;
var helpers = require('./helpers');
var assert = require('assert');
var _ = require('lodash');
var ref = fastcall.ref;
var Promise = require('bluebird');
var async = Promise.coroutine;
describe('Library', function () {
var libPath = null;
before(async(regeneratorRuntime.mark(function _callee() {
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return helpers.findTestlib();
case 2:
libPath = _context.sent;
case 3:
case 'end':
return _context.stop();
}
}
}, _callee, this);
})));
describe('initialize', function () {
describe('without options', function () {
it('should init in sync mode as default', function () {
var lib = new Library(libPath);
try {
assert(_.isObject(lib));
lib.initialize();
assert.equal(lib.options.defaultCallMode, Library.callMode.sync);
} finally {
lib.release();
}
});
});
describe('with options', function () {
it('should init in sync mode explicitly', function () {
var lib = new Library(libPath, { defaultCallMode: Library.callMode.sync });
try {
assert(_.isObject(lib));
lib.initialize();
assert.equal(lib.options.defaultCallMode, Library.callMode.sync);
} finally {
lib.release();
}
});
it('should init in async mode explicitly', function () {
var lib = new Library(libPath, { defaultCallMode: Library.callMode.async });
try {
assert(_.isObject(lib));
lib.initialize();
assert.equal(lib.options.defaultCallMode, Library.callMode.async);
} finally {
lib.release();
}
});
it('should throw when mode is unknown', function () {
assert.throws(function () {
var lib = new Library(libPath, { defaultCallMode: 42 });
});
});
});
});
describe('sync call mode (smoke test)', function () {
var lib = null;
beforeEach(function () {
lib = new Library(libPath);
});
afterEach(function () {
lib.release();
lib = null;
});
describe('node-ffi style declaration', function () {
it('should invoke "mul" with "declare"', function () {
lib.function({ mul: ['int', [ref.types.int, 'int']] });
testMulSync('int mul(int arg0, int arg1)');
});
it('should invoke "mul" with "declareSync"', function () {
lib.syncFunction({ mul: ['int', [ref.types.int, 'int']] });
testMulSync('int mul(int arg0, int arg1)');
});
it("should send Node.js Buffer's memory content to native code", function () {
lib.function({ readLongPtr: ['long', [ref.refType('long'), 'uint']] });
testReadLongPtrSync('long readLongPtr(long* arg0, uint arg1)');
});
it("should allow to write Node.js's string content in native code", function () {
lib.function({ writeString: ['void', ['char*']] });
testWriteStringSync('void writeString(char* arg0)');
});
it('should read natvie memory', function () {
lib.function({ getString: ['char*', []] });
testGetStringSync('char* getString()');
});
it('should handle out arguments', function () {
lib.function({ getNumbers: ['void', ['double**', ref.refType('size_t')]] });
testGetNumbersSync('void getNumbers(double** arg0, size_t* arg1)');
});
it('should support callbacks', function () {
lib.callback({ TMakeIntFunc: ['int', [ref.types.float, 'double']] }).function({ makeInt: ['int', ['float', 'double', 'TMakeIntFunc']] });
testMakeIntSync('int TMakeIntFunc(float arg0, double arg1)', 'int makeInt(float arg0, double arg1, TMakeIntFunc arg2)');
});
});
describe('string declaration', function () {
it('should invoke "mul" with "declare"', function () {
// Argument name is optional:
lib.function('int mul(int value, int)');
testMulSync('int mul(int value, int arg1)');
});
it('should invoke "mul" with "declareSync"', function () {
// Argument name is optional:
lib.function('int mul(int, int by)');
testMulSync('int mul(int arg0, int by)');
});
it("should send Node.js Buffer's memory content to native code", function () {
lib.function('long readLongPtr(long* ptr, uint offset)');
testReadLongPtrSync('long readLongPtr(long* ptr, uint offset)');
});
it("should allow to write Node.js's string content in native code", function () {
lib.function('void writeString(char* )');
testWriteStringSync('void writeString(char* arg0)');
});
it('should read natvie memory', function () {
lib.function('char *getString()');
testGetStringSync('char* getString()');
});
it('should handle out arguments', function () {
lib.function(' void getNumbers ( double * * nums , size_t*count) ');
testGetNumbersSync('void getNumbers(double** nums, size_t* count)');
});
it('should support callbacks', function () {
lib.callback('int TMakeIntFunc(float fv, double)').function('int makeInt(float , double dv, TMakeIntFunc func)');
testMakeIntSync('int TMakeIntFunc(float fv, double arg1)', 'int makeInt(float arg0, double dv, TMakeIntFunc func)');
});
});
function testMulSync(declaration) {
assert(lib.functions);
assert(lib.functions.mul);
assert(lib.interface);
assert(_.isFunction(lib.interface.mul));
var mul = lib.interface.mul;
// Verify metadata:
assert(mul.function);
assert.equal(mul.function.toString(), declaration);
assert.equal(mul.function.name, 'mul');
assert.equal(mul.function.resultType.name, 'int');
assert.equal(mul.function.args.length, 2);
assert(_.isString(mul.function.args[0].name));
assert.equal(mul.function.args[0].type.name, 'int');
assert(_.isString(mul.function.args[1].name));
assert.equal(mul.function.args[1].type.name, 'int');
// Call!
assert.equal(mul(2, 2), 4);
assert.equal(mul(10, 2), 20);
assert.equal(mul(10, "3"), 30);
assert.equal(mul(10.1, 2.1), 20);
assert.equal(mul(mul(4, 4), 2), 32);
// Zero is the default:
assert.equal(mul(10), 0);
assert.equal(mul(), 0);
assert.equal(mul("a", "b"), 0);
}
function testReadLongPtrSync(declaration) {
var readLongPtr = lib.interface.readLongPtr;
assert(_.isFunction(readLongPtr));
assert(readLongPtr.function);
assert.equal(readLongPtr.function.toString(), declaration);
var long = ref.types.long;
var data = new Buffer(long.size * 2);
long.set(data, 0, 1);
long.set(data, long.size, 42);
assert.equal(readLongPtr(data, 0), 1);
assert.equal(readLongPtr(data, 1), 42);
}
function testWriteStringSync(declaration) {
var writeString = lib.interface.writeString;
assert(_.isFunction(writeString));
assert(writeString.function);
assert.equal(writeString.function.toString(), declaration);
var string = ref.allocCString(' ');
writeString(string);
assert.equal(ref.readCString(string), 'hello');
}
function testGetStringSync(declaration) {
var getString = lib.interface.getString;
assert(_.isFunction(getString));
assert(getString.function);
assert.equal(getString.function.toString(), declaration);
var string = getString();
assert(_.isBuffer(string));
assert(_.isObject(string.type));
assert.equal(string.type.name, 'char');
assert.equal(string.type.indirection, 1);
assert.equal(string.length, 0);
assert.equal(ref.readCString(string), 'world');
}
// void getNumbers(double** nums, size_t* size)
function testGetNumbersSync(declaration) {
var getNumbers = lib.interface.getNumbers;
assert(_.isFunction(getNumbers));
assert.equal(getNumbers.function.toString(), declaration);
var double = ref.types.double;
var doublePtrType = ref.refType(double);
var doublePtrPtr = ref.alloc(doublePtrType);
var sizeTPtr = ref.alloc('size_t');
getNumbers(doublePtrPtr, sizeTPtr);
var size = ref.deref(sizeTPtr);
assert.equal(size, 3);
var doublePtr = ref.deref(doublePtrPtr);
assert(_.isBuffer(doublePtr));
var first = ref.deref(doublePtr);
assert(_.isNumber(first));
assert.equal(first, 1.1);
doublePtr = ref.reinterpret(doublePtr, size * double.size);
assert.equal(double.get(doublePtr, 1 * double.size), 2.2);
assert.equal(double.get(doublePtr, 2 * double.size), 3.3);
}
function testMakeIntSync(callbackDecl, funcDecl) {
var TMakeIntFunc = lib.interface.TMakeIntFunc;
assert(_.isFunction(TMakeIntFunc));
assert(TMakeIntFunc.callback);
assert.equal(TMakeIntFunc.callback.toString(), callbackDecl);
var makeInt = lib.interface.makeInt;
assert(_.isFunction(makeInt));
assert.equal(makeInt.function.toString(), funcDecl);
var result = makeInt(1.1, 2.2, function (fv, dv) {
return fv + dv;
});
assert.equal(result, Math.floor((1.1 + 2.2) * 2));
}
});
describe('async call mode (smoke test)', function () {
var lib = null;
beforeEach(function () {
lib = new Library(libPath, { defaultCallMode: Library.callMode.async });
});
afterEach(function () {
lib.release();
lib = null;
});
describe('node-ffi style declaration', function () {
it('should invoke "mul" with "declare"', function () {
lib.function({ mul: ['int', [ref.types.int, 'int']] });
return testMulAsync('int mul(int arg0, int arg1)');
});
it('should invoke "mul" with "declareAsync"', function () {
lib.asyncFunction({ mul: ['int', [ref.types.int, 'int']] });
return testMulAsync('int mul(int arg0, int arg1)');
});
it("should send Node.js Buffer's memory content to native code", function () {
lib.function({ readLongPtr: ['long', [ref.refType('long'), 'uint']] });
return testReadLongPtrAsync('long readLongPtr(long* arg0, uint arg1)');
});
it("should allow to write Node.js's string content in native code", function () {
lib.function({ writeString: ['void', ['char*']] });
return testWriteStringAsync('void writeString(char* arg0)');
});
it('should read natvie memory', function () {
lib.function({ getString: ['char*', []] });
return testGetStringAsync('char* getString()');
});
it('should handle out arguments', function () {
lib.function({ getNumbers: ['void', ['double**', ref.refType('size_t')]] });
return testGetNumbersAsync('void getNumbers(double** arg0, size_t* arg1)');
});
it('should support callbacks', function () {
lib.callback({ TMakeIntFunc: ['int', [ref.types.float, 'double']] }).function({ makeInt: ['int', ['float', 'double', 'TMakeIntFunc']] });
return testMakeIntAsync('int TMakeIntFunc(float arg0, double arg1)', 'int makeInt(float arg0, double arg1, TMakeIntFunc arg2)');
});
});
describe('string declaration', function () {
it('should invoke "mul" with "declare"', function () {
// Argument name is optional:
lib.function('int mul(int value, int)');
return testMulAsync('int mul(int value, int arg1)');
});
it('should invoke "mul" with "declareAsync"', function () {
// Argument name is optional:
lib.function('int mul(int, int by)');
return testMulAsync('int mul(int arg0, int by)');
});
it("should send Node.js Buffer's memory content to native code", function () {
lib.function('long readLongPtr(long* ptr, uint offset)');
return testReadLongPtrAsync('long readLongPtr(long* ptr, uint offset)');
});
it("should allow to write Node.js's string content in native code", function () {
lib.function('void writeString(char* )');
return testWriteStringAsync('void writeString(char* arg0)');
});
it('should read natvie memory', function () {
lib.function('char *getString()');
return testGetStringAsync('char* getString()');
});
it('should handle out arguments', function () {
lib.function(' void getNumbers ( double * * nums , size_t*count) ');
return testGetNumbersAsync('void getNumbers(double** nums, size_t* count)');
});
it('should support callbacks', function () {
lib.callback('int TMakeIntFunc(float fv, double)').function('int makeInt(float , double dv, TMakeIntFunc func)');
return testMakeIntAsync('int TMakeIntFunc(float fv, double arg1)', 'int makeInt(float arg0, double dv, TMakeIntFunc func)');
});
});
var testMulAsync = async(regeneratorRuntime.mark(function _callee2(declaration) {
var mul;
return regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
assert(lib.functions);
assert(lib.functions.mul);
assert(lib.interface);
assert(_.isFunction(lib.interface.mul));
mul = lib.interface.mul;
// Verify metadata:
assert(mul.function);
assert.equal(mul.function.toString(), declaration);
assert.equal(mul.function.name, 'mul');
assert.equal(mul.function.resultType.name, 'int');
assert.equal(mul.function.args.length, 2);
assert(_.isString(mul.function.args[0].name));
assert.equal(mul.function.args[0].type.name, 'int');
assert(_.isString(mul.function.args[1].name));
assert.equal(mul.function.args[1].type.name, 'int');
// Call!
_context2.t0 = assert;
_context2.next = 17;
return mul(2, 2);
case 17:
_context2.t1 = _context2.sent;
_context2.t0.equal.call(_context2.t0, _context2.t1, 4);
_context2.t2 = assert;
_context2.next = 22;
return mul(10, 2);
case 22:
_context2.t3 = _context2.sent;
_context2.t2.equal.call(_context2.t2, _context2.t3, 20);
_context2.t4 = assert;
_context2.next = 27;
return mul(10, "3");
case 27:
_context2.t5 = _context2.sent;
_context2.t4.equal.call(_context2.t4, _context2.t5, 30);
_context2.t6 = assert;
_context2.next = 32;
return mul(10.1, 2.1);
case 32:
_context2.t7 = _context2.sent;
_context2.t6.equal.call(_context2.t6, _context2.t7, 20);
_context2.t8 = assert;
_context2.next = 37;
return mul(4, 4);
case 37:
_context2.t9 = _context2.sent;
_context2.next = 40;
return mul(_context2.t9, 2);
case 40:
_context2.t10 = _context2.sent;
_context2.t8.equal.call(_context2.t8, _context2.t10, 32);
_context2.t11 = assert;
_context2.next = 45;
return mul(10);
case 45:
_context2.t12 = _context2.sent;
_context2.t11.equal.call(_context2.t11, _context2.t12, 0);
_context2.t13 = assert;
_context2.next = 50;
return mul();
case 50:
_context2.t14 = _context2.sent;
_context2.t13.equal.call(_context2.t13, _context2.t14, 0);
_context2.t15 = assert;
_context2.next = 55;
return mul("a", "b");
case 55:
_context2.t16 = _context2.sent;
_context2.t15.equal.call(_context2.t15, _context2.t16, 0);
case 57:
case 'end':
return _context2.stop();
}
}
}, _callee2, this);
}));
var testReadLongPtrAsync = async(regeneratorRuntime.mark(function _callee3(declaration) {
var readLongPtr, long, data;
return regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
readLongPtr = lib.interface.readLongPtr;
assert(_.isFunction(readLongPtr));
assert.equal(readLongPtr.function.toString(), declaration);
long = ref.types.long;
data = new Buffer(long.size * 2);
long.set(data, 0, 1);
long.set(data, long.size, 42);
_context3.t0 = assert;
_context3.next = 10;
return readLongPtr(data, 0);
case 10:
_context3.t1 = _context3.sent;
_context3.t0.equal.call(_context3.t0, _context3.t1, 1);
_context3.t2 = assert;
_context3.next = 15;
return readLongPtr(data, 1);
case 15:
_context3.t3 = _context3.sent;
_context3.t2.equal.call(_context3.t2, _context3.t3, 42);
case 17:
case 'end':
return _context3.stop();
}
}
}, _callee3, this);
}));
var testWriteStringAsync = async(regeneratorRuntime.mark(function _callee4(declaration) {
var writeString, string;
return regeneratorRuntime.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
writeString = lib.interface.writeString;
assert(_.isFunction(writeString));
assert.equal(writeString.function.toString(), declaration);
string = ref.allocCString(' ');
_context4.next = 6;
return writeString(string);
case 6:
assert.equal(ref.readCString(string), 'hello');
case 7:
case 'end':
return _context4.stop();
}
}
}, _callee4, this);
}));
var testGetStringAsync = async(regeneratorRuntime.mark(function _callee5(declaration) {
var getString, string;
return regeneratorRuntime.wrap(function _callee5$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
getString = lib.interface.getString;
assert(_.isFunction(getString));
assert.equal(getString.function.toString(), declaration);
_context5.next = 5;
return getString();
case 5:
string = _context5.sent;
assert(_.isBuffer(string));
assert(_.isObject(string.type));
assert.equal(string.type.name, 'char');
assert.equal(string.type.indirection, 1);
assert.equal(ref.readCString(string), 'world');
case 11:
case 'end':
return _context5.stop();
}
}
}, _callee5, this);
}));
// void getNumbers(double** nums, size_t* size)
var testGetNumbersAsync = async(regeneratorRuntime.mark(function _callee6(declaration) {
var getNumbers, double, doublePtrType, doublePtrPtr, sizeTPtr, size, doublePtr, first;
return regeneratorRuntime.wrap(function _callee6$(_context6) {
while (1) {
switch (_context6.prev = _context6.next) {
case 0:
getNumbers = lib.interface.getNumbers;
assert(_.isFunction(getNumbers));
assert.equal(getNumbers.function.toString(), declaration);
double = ref.types.double;
doublePtrType = ref.refType(double);
doublePtrPtr = ref.alloc(doublePtrType);
sizeTPtr = ref.alloc('size_t');
_context6.next = 9;
return getNumbers(doublePtrPtr, sizeTPtr);
case 9:
size = ref.deref(sizeTPtr);
assert.equal(size, 3);
doublePtr = ref.deref(doublePtrPtr);
assert(_.isBuffer(doublePtr));
first = ref.deref(doublePtr);
assert(_.isNumber(first));
assert.equal(first, 1.1);
doublePtr = ref.reinterpret(doublePtr, size * double.size);
assert.equal(double.get(doublePtr, 1 * double.size), 2.2);
assert.equal(double.get(doublePtr, 2 * double.size), 3.3);
case 19:
case 'end':
return _context6.stop();
}
}
}, _callee6, this);
}));
var testMakeIntAsync = async(regeneratorRuntime.mark(function _callee7(callbackDecl, funcDecl) {
var TMakeIntFunc, makeInt, predeclaredCallback, result;
return regeneratorRuntime.wrap(function _callee7$(_context7) {
while (1) {
switch (_context7.prev = _context7.next) {
case 0:
TMakeIntFunc = lib.interface.TMakeIntFunc;
assert(_.isFunction(TMakeIntFunc));
assert(TMakeIntFunc.callback);
assert.equal(TMakeIntFunc.callback.toString(), callbackDecl);
makeInt = lib.interface.makeInt;
assert(_.isFunction(makeInt));
assert.equal(makeInt.function.toString(), funcDecl);
predeclaredCallback = TMakeIntFunc(function (fv, dv) {
return fv + dv;
});
_context7.next = 10;
return makeInt(1.1, 2.2, predeclaredCallback);
case 10:
result = _context7.sent;
assert.equal(result, Math.floor((1.1 + 2.2) * 2));
case 12:
case 'end':
return _context7.stop();
}
}
}, _callee7, this);
}));
});
});
//# sourceMappingURL=libraryTests.js.map