Skip to content

Commit

Permalink
test: move test fixture native bindings from the main src/ dir to a s…
Browse files Browse the repository at this point in the history
…eparate test/ native binding
  • Loading branch information
TooTallNate committed May 12, 2012
1 parent 329ed4f commit 3db3eeb
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 41 deletions.
34 changes: 0 additions & 34 deletions src/ffi.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,6 @@ Handle<Value> WrapPointer(char *ptr, size_t length) {
void FFI::InitializeStaticFunctions(Handle<Object> target) {
Local<Object> o = Object::New();

// atoi and abs here for testing purposes
o->Set(String::NewSymbol("atoi"), WrapPointer((char *)atoi));

// Windows has multiple `abs` signatures, so we need to manually disambiguate
int (*absPtr)(int)(abs);
o->Set(String::NewSymbol("abs"), WrapPointer((char *)absPtr));

// dl functions used by the DynamicLibrary JS class
o->Set(String::NewSymbol("dlopen"), WrapPointer((char *)dlopen));
o->Set(String::NewSymbol("dlclose"), WrapPointer((char *)dlclose));
Expand All @@ -52,7 +45,6 @@ void FFI::InitializeBindings(Handle<Object> target) {
NODE_SET_METHOD(target, "ffi_prep_cif", FFIPrepCif);
NODE_SET_METHOD(target, "ffi_call", FFICall);
NODE_SET_METHOD(target, "ffi_call_async", FFICallAsync);
NODE_SET_METHOD(target, "strtoul", Strtoul);

// `ffi_status` enum values
SET_ENUM_VALUE(FFI_OK);
Expand Down Expand Up @@ -117,32 +109,6 @@ void FFI::InitializeBindings(Handle<Object> target) {
target->Set(String::NewSymbol("FFI_TYPES"), ftmap);
}

/*
* Hard-coded `strtoul` binding, for the benchmarks.
*
* args[0] - the string number to convert to a real Number
* args[1] - a "buffer" instance to write into (the "endptr")
* args[2] - the base (0 means autodetect)
*/

Handle<Value> FFI::Strtoul(const Arguments &args) {
HandleScope scope;
char buf[128];
int base;
char **endptr;

args[0]->ToString()->WriteUtf8(buf);

Local<Value> endptr_arg = args[0];
endptr = (char **)Buffer::Data(endptr_arg.As<Object>());

base = args[2]->Int32Value();

unsigned long val = strtoul(buf, endptr, base);

return scope.Close(Integer::NewFromUnsigned(val));
}

/*
* Function that creates and returns an `ffi_cif` pointer from the given return
* value type and argument types.
Expand Down
4 changes: 0 additions & 4 deletions src/ffi.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#define __STDC_LIMIT_MACROS true
Expand Down
8 changes: 8 additions & 0 deletions test/binding.gyp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
'targets': [
{
'target_name': 'ffi_tests',
'sources': [ 'ffi_tests.cc' ]
}
]
}
106 changes: 106 additions & 0 deletions test/ffi_tests.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#include <stdlib.h>
#include "v8.h"
#include "node.h"
#include "node_buffer.h"

using namespace v8;
using namespace node;

namespace {

/*
* Test struct definition used in the test harness functions below.
*/

typedef struct box {
int width;
int height;
} _box;

/*
* Accepts a struct by value, and returns a struct by value.
*/

box double_box(box input) {
box rtn;
rtn.width = input.width * 2;
rtn.height = input.height * 2;
return rtn;
}

/*
* Accepts a struct by value, and returns an int.
*/

int area_box(box input) {
return input.width * input.height;
}

/*
* Accepts a box pointer and returns an int.
*/

int area_box_ptr(box *input) {
return input->width * input->height;
}

/*
* Hard-coded `strtoul` binding, for the benchmarks.
*
* args[0] - the string number to convert to a real Number
* args[1] - a "buffer" instance to write into (the "endptr")
* args[2] - the base (0 means autodetect)
*/

Handle<Value> Strtoul(const Arguments &args) {
HandleScope scope;
char buf[128];
int base;
char **endptr;

args[0]->ToString()->WriteUtf8(buf);

Local<Value> endptr_arg = args[0];
endptr = (char **)Buffer::Data(endptr_arg.As<Object>());

base = args[2]->Int32Value();

unsigned long val = strtoul(buf, endptr, base);

return scope.Close(Integer::NewFromUnsigned(val));
}


void wrap_pointer_cb(char *data, void *hint) {
//fprintf(stderr, "wrap_pointer_cb\n");
}

Handle<Object> WrapPointer(char *ptr) {
void *user_data = NULL;
size_t length = 0;
Buffer *buf = Buffer::New(ptr, length, wrap_pointer_cb, user_data);
return buf->handle_;
}

void Initialize(Handle<Object> target) {
HandleScope scope;

// atoi and abs here for testing purposes
target->Set(String::NewSymbol("atoi"), WrapPointer((char *)atoi));

// Windows has multiple `abs` signatures, so we need to manually disambiguate
int (*absPtr)(int)(abs);
target->Set(String::NewSymbol("abs"), WrapPointer((char *)absPtr));

// hard-coded `strtoul` binding, for the benchmarks
NODE_SET_METHOD(target, "strtoul", Strtoul);

// also need to test these custom functions
target->Set(String::NewSymbol("double_box"), WrapPointer((char *)double_box));
target->Set(String::NewSymbol("area_box"), WrapPointer((char *)area_box));
target->Set(String::NewSymbol("area_box_ptr"), WrapPointer((char *)area_box_ptr));
}

} // anonymous namespace

NODE_MODULE(ffi_tests, Initialize);
27 changes: 24 additions & 3 deletions test/foreign_function.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,50 @@

var expect = require('expect.js')
, ref = require('ref')
, Struct = require('ref-struct')
, ffi = require('../')
, bindings = require('./build/Release/ffi_tests')

describe('ForeignFunction', function () {

afterEach(gc)

// same struct as defined in ffi_tests.cc
var box = Struct({
width: ref.types.int
, height: ref.types.int
})

it('should call the static "abs" bindings', function () {
var _abs = ffi.Bindings.StaticFunctions.abs
var _abs = bindings.abs
var abs = ffi.ForeignFunction(_abs, 'int', [ 'int' ])
expect(abs).to.be.a('function')
expect(abs(-1234)).to.equal(1234)
})

it('should call the static "atoi" bindings', function () {
var _atoi = ffi.Bindings.StaticFunctions.atoi
var _atoi = bindings.atoi
var atoi = ffi.ForeignFunction(_atoi, 'int', [ 'string' ])
expect(atoi).to.be.a('function')
expect(atoi('1234')).to.equal(1234)
})

it('should call the static "double_box" bindings', function () {
var double_box = ffi.ForeignFunction(bindings.double_box, box, [ box ])
var b = new box
assert(b instanceof box)
b.width = 4
b.height = 5
var out = double_box(b)
assert(out instanceof box)
assert.equal(8, out.width)
assert.equal(10, out.height)
})

describe('async', function () {

it('should call the static "abs" bindings asynchronously', function (done) {
var _abs = ffi.Bindings.StaticFunctions.abs
var _abs = bindings.abs
var abs = ffi.ForeignFunction(_abs, 'int', [ 'int' ])
expect(abs).to.be.a('function')

Expand Down

0 comments on commit 3db3eeb

Please sign in to comment.