library.js
4.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
var assert = require('assert')
, ref = require('ref')
, Struct = require('ref-struct')
, ffi = require('../')
, Library = ffi.Library
describe('Library', function () {
var charPtr = ref.refType(ref.types.char)
afterEach(gc)
it('should be a function', function () {
assert(typeof Library === 'function');
})
it('should work with the `new` operator', function () {
var l = new Library()
assert(typeof l === 'object');
})
it('should accept `null` as a first argument', function () {
if (process.platform == 'win32') {
// On Windows, null refers to just the main executable (e.g. node.exe).
// Windows never searches for symbols across multiple DLL's.
// Note: Exporting symbols from an executable is unusual on Windows.
// Normally you only see exports from DLL's. It happens that node.exe
// does export symbols, so null as a first argument can be tested.
// This is an implementation detail of node, and could potentially
// change in the future (e.g. if node gets broken up into DLL's
// rather than being one large static linked executable).
var winFuncs = new Library(null, {
'uv_fs_open': [ 'void', [ charPtr ] ]
})
assert(typeof winFuncs.uv_fs_open === 'function');
} else {
// On POSIX, null refers to the global symbol table, and lets you use
// symbols in the main executable and loaded shared libaries.
var posixFuncs = new Library(null, {
'printf': [ 'void', [ charPtr ] ]
})
assert(typeof posixFuncs.printf === 'function');
}
})
it('should accept a lib name as the first argument', function () {
var lib = process.platform == 'win32' ? 'msvcrt' : 'libm'
var libm = new Library(lib, {
'ceil': [ 'double', [ 'double' ] ]
})
assert(typeof libm.ceil === 'function');
assert(libm.ceil(1.1) === 2);
})
it('should accept a lib name with file extension', function() {
var lib = process.platform == 'win32'
? 'msvcrt.dll'
: 'libm' + ffi.LIB_EXT
var libm = new Library(lib, {
'ceil': [ 'double', ['double'] ]
})
assert(typeof libm.ceil === 'function');
assert(libm.ceil(100.9) === 101);
})
it('should throw when an invalid function name is used', function () {
try {
new Library(null, {
'doesnotexist__': [ 'void', [] ]
});
assert(false); // unreachable
} catch (e) {
assert(e);
}
})
it('should work with "strcpy" and a 128 length string', function () {
var lib = process.platform == 'win32' ? 'msvcrt.dll' : null;
var ZEROS_128 = Array(128 + 1).join('0');
var buf = new Buffer(256);
var strcpy = new Library(lib, {
'strcpy': [ charPtr, [ charPtr, 'string' ] ]
}).strcpy;
strcpy(buf, ZEROS_128);
assert(buf.readCString() === ZEROS_128);
})
it('should work with "strcpy" and a 2k length string', function () {
var lib = process.platform == 'win32' ? 'msvcrt' : null;
var ZEROS_2K = Array(2e3 + 1).join('0');
var buf = new Buffer(4096);
var strcpy = new Library(lib, {
'strcpy': [ charPtr, [ charPtr, 'string' ] ]
}).strcpy;
strcpy(buf, ZEROS_2K);
assert(buf.readCString() === ZEROS_2K);
})
if (process.platform == 'win32') {
it('should work with "GetTimeOfDay" and a "FILETIME" Struct pointer',
function () {
var FILETIME = new Struct({
'dwLowDateTime': ref.types.uint32
, 'dwHighDateTime': ref.types.uint32
})
var l = new Library('kernel32', {
'GetSystemTimeAsFileTime': [ 'void', [ 'pointer' ]]
})
var ft = new FILETIME()
l.GetSystemTimeAsFileTime(ft.ref())
// TODO: Add an assert clause here...
})
} else {
it('should work with "gettimeofday" and a "timeval" Struct pointer',
function () {
var timeval = new Struct({
'tv_sec': ref.types.long
, 'tv_usec': ref.types.long
})
var timevalPtr = ref.refType(timeval)
var timezonePtr = ref.refType(ref.types.void)
var l = new Library(null, {
'gettimeofday': [ref.types.int, [timevalPtr, timezonePtr]]
})
var tv = new timeval()
l.gettimeofday(tv.ref(), null)
assert.equal(Math.floor(Date.now() / 1000), tv.tv_sec)
})
}
describe('async', function () {
it('should call a function asynchronously', function (done) {
var lib = process.platform == 'win32' ? 'msvcrt' : 'libm'
var libm = new Library(lib, {
'ceil': [ 'double', [ 'double' ], { async: true } ]
})
libm.ceil(1.1, function (err, res) {
assert(err === null);
assert(res === 2);
done();
})
})
})
})