Skip to content

Commit

Permalink
add basic test suite, number tests, list tests
Browse files Browse the repository at this point in the history
  • Loading branch information
hansihe committed May 10, 2016
1 parent 354b420 commit 26b479d
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 90 deletions.
3 changes: 3 additions & 0 deletions RELEASE_CHECKLIST.md
@@ -0,0 +1,3 @@
1. Bump rustler, rustler_codegen, rustler_mix (including lib/rustler.ex), installer template version numbers
2. Publish crates, rustler_mix, installer
3. Update documentation
8 changes: 4 additions & 4 deletions src/codegen_runtime.rs
Expand Up @@ -12,11 +12,11 @@ use ::{NifResult, NifEncoder};

// This is the last level of rust safe rust code before the BEAM.
// No panics should go above this point, as they will unwrap into the C code and ruin the day.
pub fn handle_nif_call(function: for<'a> fn(&'a NifEnv, &Vec<NifTerm>) -> NifResult<NifTerm<'a>>,
_arity: usize, r_env: NIF_ENV,
pub fn handle_nif_call(function: for<'a> fn(&'a NifEnv, &Vec<NifTerm>) -> NifResult<NifTerm<'a>>,
_arity: usize, r_env: NIF_ENV,
argc: c_int, argv: *const NIF_TERM) -> NIF_TERM {
let env = NifEnv { env: r_env };

let terms = unsafe { ::std::slice::from_raw_parts(argv, argc as usize) }.iter()
.map(|x| NifTerm::new(&env, *x)).collect::<Vec<NifTerm>>();

Expand All @@ -30,7 +30,7 @@ pub fn handle_nif_call(function: for<'a> fn(&'a NifEnv, &Vec<NifTerm>) -> NifRes
match result {
Ok(res) => res,
Err(_err) => {
exception::throw(env.as_c_arg(),
exception::throw(env.as_c_arg(),
get_atom_init("nif_panic").to_term(&env).as_c_arg())
},
}
Expand Down
4 changes: 2 additions & 2 deletions test/Cargo.toml
Expand Up @@ -4,8 +4,8 @@ version = "0.1.0"
authors = ["HansiHE <hansihe@hansihe.com>"]

[lib]
name = "test_primitives"
path = "test_primitives.rs"
name = "test"
path = "src/lib.rs"
crate-type = ["dylib"]

[dependencies.rustler]
Expand Down
21 changes: 21 additions & 0 deletions test/src/lib.rs
@@ -0,0 +1,21 @@
#![feature(plugin)]
#![plugin(rustler_codegen)]

#[macro_use]
extern crate rustler;

mod test_primitives;
use test_primitives::{add_u32, add_i32, tuple_add};

mod test_list;
use test_list::{sum_list};

rustler_export_nifs!(
"Elixir.TestNative",
[("add_u32", 2, add_u32),
("add_i32", 2, add_i32),
("tuple_add", 1, tuple_add),
("sum_list", 1, sum_list)],
None
);

16 changes: 16 additions & 0 deletions test/src/test_list.rs
@@ -0,0 +1,16 @@
use rustler;
use rustler::{NifEnv, NifTerm, NifError, NifEncoder, NifResult};
use rustler::list::NifListIterator;

pub fn sum_list<'a>(env: &'a NifEnv, args: &Vec<NifTerm>) -> NifResult<NifTerm<'a>> {
let iter: NifListIterator = try!(args[0].decode());

let res: Result<Vec<i64>, NifError> = iter
.map(|x| x.decode::<i64>())
.collect();

match res {
Ok(result) => Ok(result.iter().fold(0, |acc, &x| acc + x).encode(env)),
Err(err) => Err(err),
}
}
26 changes: 26 additions & 0 deletions test/src/test_primitives.rs
@@ -0,0 +1,26 @@
use rustler;
use rustler::{NifEnv, NifTerm, NifError, NifEncoder, NifResult};

pub fn add_u32<'a>(env: &'a NifEnv, args: &Vec<NifTerm>) -> NifResult<NifTerm<'a>> {
let lhs: u32 = try!(args[0].decode());
let rhs: u32 = try!(args[1].decode());

Ok((lhs + rhs).encode(env))
}
pub fn add_i32<'a>(env: &'a NifEnv, args: &Vec<NifTerm>) -> NifResult<NifTerm<'a>> {
let lhs: i32 = try!(args[0].decode());
let rhs: i32 = try!(args[1].decode());

Ok((lhs + rhs).encode(env))
}

#[NifTuple] struct AddTuple { lhs: i32, rhs: i32 }
pub fn tuple_add<'a>(env: &'a NifEnv, args: &Vec<NifTerm>) -> NifResult<NifTerm<'a>> {
let tuple: AddTuple = try!(args[0].decode());
Ok((tuple.lhs + tuple.rhs).encode(env))
}

pub fn echo_u8<'a>(env: &'a NifEnv, args: &Vec<NifTerm>) -> NifResult<NifTerm<'a>> {
let num: u8 = try!(args[0].decode());
Ok(num.encode(env))
}
15 changes: 15 additions & 0 deletions test/test/list_test.exs
@@ -0,0 +1,15 @@
defmodule ListTest do
use ExUnit.Case, async: true

test "list iteration" do
assert 8 == TestNative.sum_list([1, 2, 1, 4])
end

test "list iteration fails on improper lists" do
assert_raise ErlangError, fn -> TestNative.sum_list([1, 4, 2 | :invalid]) end
end

test "list iteration fails on invalid entries" do
assert_raise ArgumentError, fn -> TestNative.sum_list([1, 4, :invalid, 2]) end
end
end
21 changes: 10 additions & 11 deletions test/test/primitives_test.exs
@@ -1,16 +1,15 @@
defmodule PrimitivesTest do
use ExUnit.Case, async: true
use TestLoadNif, [
module: PrimitivesTestNative,
native: "test_primitives",
functions: [
add_u32: 2,
add_i32: 2,
tuple_add: 1,
],
]

test "u8 decoding and encoding" do
PrimitivesTestNative.test(1, 2)
test "number decoding and encoding" do
assert 3 == TestNative.add_u32(1, 2)
assert 3 == TestNative.add_i32(6, -3)
assert -3 == TestNative.add_i32(3, -6)
end

test "number decoding should fail on invalid terms" do
assert_raise ArgumentError, fn -> TestNative.add_u32(-1, 1) end
assert_raise ArgumentError, fn -> TestNative.add_u32("1", 1) end
assert_raise ArgumentError, fn -> TestNative.add_i32(2147483648, 1) end
end
end
48 changes: 13 additions & 35 deletions test/test/test_helper.exs
Expand Up @@ -2,44 +2,22 @@ defmodule NifNotLoadedError do
defexception message: "nif not loaded"
end

defmodule TestLoadNif do
require Rustler

defmacro __using__(opts) do
module_name = opts[:module]
{mod_name, _} = Code.eval_quoted(module_name)
defmodule TestNative do
@on_load :load_nif

native_name = opts[:native]
functions = opts[:functions]

defmodule mod_name do

@on_load :_load_nif

quote do
def _load_nif do
:ok = :erlang.load_nif("./target/debug/lib#{unquote(native_name)}", [])
end
end
|> Code.eval_quoted([], __ENV__)

for {name, arity} <- functions do
args = Enum.map(1..arity, &(Macro.var(String.to_atom("_#{&1}"), nil)))
quote do
def unquote(name)(unquote_splicing(args)), do: throw(NifNotLoadedError)
end
end
|> Code.eval_quoted([], __ENV__)

end
def load_nif do
Rustler.load_nif("test")
end

#quote do
# ExUnit.Callbacks.setup_all do
# TestLoadNif.setup(unquote(module_name), unquote(native_name))
# on_exit fn -> TestLoadNif.exit(unquote(module_name)) end
# :ok
# end
#end
nil
defp err do
throw NifNotLoadedError
end

def add_u32(_, _), do: err
def add_i32(_, _), do: err
def tuple_add(_), do: err
def sum_list(_), do: err

end
38 changes: 0 additions & 38 deletions test/test_primitives.rs

This file was deleted.

0 comments on commit 26b479d

Please sign in to comment.